ISG-2018 观安杯安全运维管理赛Writeup

2018-09-03 9,699

calc

命令注入  

得到 flag: ISG{522b28987a79534f8a38b25ebcc474fb}  


news

SQL 注入,关键字大小写绕过,空格用注释符绕过  

http://202.120.7.206:60019/news-111111/**/union/**/sElect/**/1,flag/**/from/**/f  

lag.html  

表名:  

得到 flag: ISG{7a78683a929dbc6bd8e5e96f0c185b16}  


secret

在 chrome 浏览器中打开 view-source:http://202.120.7.207:60007/  

ZmxhZzpJU0d7SDNJSU9fMXNHX2pzX1RyNHB9做 base64解码得到  

flag:ISG{H3IIO_1sG_js_Tr4p}  


junkcode

给了一个 32 位的 ELF,运行后需要提供输入 flag,并返回是否正确。在 IDA 中打开,  

发现 main 函数的代码比较混乱,应该是运行时解密的。  

所以用 gdb 调试,通过 disass main 查看运行时 main 函数的指令:从名称也可以猜  

到,0x080485d4 处调用的 check 应该就是输入的检查函数。而静态看到的 check 函  

数也是被加密过的。又从函数符号表中看到一个 xor,于是猜想是 xor 加密。  

对比 IDA 中和调试器中 check 函数的指令,尝试发现确实是用 34 做 key 进行的 xor  

加密。于是在 IDA 中把 check 函数的真实指令还原:  

然后就可以 F5 看反编译代码了,逻辑也比较清晰,就是需要把两段 buf 做 xor:  

要还原的话,直接把这两段内容做 xor 即可  


stackoverflow

给了一个 64 位 ELF,从名称和 main 函数的内容可知,存在一个栈溢出,但是程序有  

canary 保护。  

而,程序设置了 SIGABRT 的 handler,即检测到栈溢出后会调用这个 handler。而在  

handler 中读取用户是否继续时,又存在一次溢出:  

这处溢出,可以修改 v1 的内容。而 v1 最后可以作为 execve 要执行的命令路径。所  

以只需要通过这个溢出,将 v1 的内容修改为/bin/sh,即可执行命令  


babyrsa

提供了一个.py 脚本。阅读代码,发现 flag 内容会生成随机的 padding,最后一个  

bytes 由用户提供,返回 RSA 加密的密文。用户可以提供 次,但每次的 padding 都  

是重新随机生成的。  

反复阅读代码,发现最后有个坑:每轮清空尾部的 padding 重新生成时,那条语句单  

独放在了最后,没有放到 try-catch 块中,他默认 try-catch 里不会发生异常。而 int()转  

换用户输入时,是可以发生异常的  

所以,一旦在读入用户输入时发生异常,那么在清空 flag 尾部的 padding 时,按照  

bits/8 算就会少清空一个 byte。而这次异常的输入又不会记入 次之内。如此这般,  

就可以将 flag 的内容逐渐加长,需要 padding 的逐渐减少。最终可以使得 flag 长度正  

好不需要随机 padding。  

又因为 的总长度是限制,flag 最大不超过 256 bytes,所以只需要连续输入 256 次字  

母内容,这样就可以确保接下来不会有随机 padding 的影响了:  

接下来,用户只需要提供 个不同的末尾 bytes 即可。根据 RSA 的计算方式,最后相  

当于求解同余意义下的三元线性方程组。为了便于计算,个末尾 bytes 分别取 0, 1,  2:

对应的方程组是  

x^3 = r1 mod n  

(256x+1)^3 = r2 mod n  

(256x+2)^3 = r3 mod n  

是带有 padding 的 flagr1, r2, r3 是末尾为 0, 1, 2 所得到的密文。直接求解方程  

组,得到 x mod n。其后面是 padding,只需要保留前面的 bytes 即为 flag  


babynote

分析程序发现:1、在deletenote时未将ptr中对应地址置NULL;2、editnote时,直接将新的内容保存到原来的内存中,且未check大小;

 

所以,应该存在double free、UAF、heap-overflow三类漏洞;

这里,我们利用heap-overflow来实现利用;

总体思路是:利用heap-overflow来达到任意地址写,然后将free_hook中写入system()的地址;那么deletenote时,note_content=’/bin/sh’即可拿到shell;free_hook和system的地址需要libc的基地址+偏移来算,基地址的泄漏见后文;

1、add两个noteA,noteB,内存分布上,noteB所在的chunkB在chunkA之后;

2、然后,编辑noteA,在noteA中伪造一个空闲块fakechunkA:

fakechunkA.size=chunkA.size-0x10;利用editnote的溢出,来修改chunkB的pre_size和pre_inuse;在delete noteB时会unlink fakechunkA;

如何绕过unlink中(p->fd->bk==p&&p->bk->fd==p)的检查?

由于(&ptr+index_A)中保存了noteA的地址,也就是fakechunkA的块首地址;让fakechunkA的fd=(&ptr+index_A)-0x18,bk=(&ptr+index_A)-0x10即可绕过;

之后,(&ptr+index_A)中保存的就是(&ptr+index_A)-0x18;

3、这时,编辑noteA,content=’a’*0x18+p64(address);这样(&ptr+index_A)中保存了address;edit noteA我们达到了任意地址写;当然,这里让address=free_hook;

4、再次编辑noteA,content=p64(system);free_hook里写入了system的地址;

5、最后deletenote时,note_content=’/bin/sh’;

6、为了泄漏libc的基地址:

先add noteX,noteY;delete noteX后,chunkX会链入unsorted bin;chunkX.fd中保存了unsortedbin的地址;main_arena地址=unsortedbin地址-0x58;

此外这道题中,main_arena在libc中的偏移是0x0x3c4b20;这样可算出libc的基地址;

7、我们注意到&ptr=0x6020c0;而在editnote时用scanf来读入数据,遇到空格0x20会截断,所以在noteA前面要多次addnote,让(&ptr+index_A)不包含0x20;


本文作者:GalaxyLab

本文为安全脉搏专栏作者发布,转载请注明:https://www.secpulse.com/archives/75113.html

Tags:
评论  (0)
快来写下你的想法吧!

GalaxyLab

文章数:5 积分: 6

安全问答社区

安全问答社区

脉搏官方公众号

脉搏公众号