Galaxy Lab

focus on information security

ISG-2018 管理运维赛writeup

calc  

命令注入  
得到 flag: ISG{522b28987a79534f8a38b25ebcc474fb}  

news  

SQL 注入,关键字大小写绕过,空格用注释符绕过  
表名:  
得到 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;