命令注入
得到 flag: ISG{522b28987a79534f8a38b25ebcc474fb}
SQL 注入,关键字大小写绕过,空格用注释符绕过
http://202.120.7.206:60019/news-111111/**/union/**/sElect/**/1,flag/**/from/**/f
lag.html
表名:
得到 flag: ISG{7a78683a929dbc6bd8e5e96f0c185b16}
在 chrome 浏览器中打开 view-source:http://202.120.7.207:60007/
ZmxhZzpJU0d7SDNJSU9fMXNHX2pzX1RyNHB9做 base64解码得到
flag:ISG{H3IIO_1sG_js_Tr4p}
给了一个 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 即可
给了一个 64 位 ELF,从名称和 main 函数的内容可知,存在一个栈溢出,但是程序有
canary 保护。
然而,程序设置了 SIGABRT 的 handler,即检测到栈溢出后会调用这个 handler。而在
handler 中读取用户是否继续时,又存在一次溢出:
这处溢出,可以修改 v1 的内容。而 v1 最后可以作为 execve 要执行的命令路径。所
以只需要通过这个溢出,将 v1 的内容修改为/bin/sh,即可执行命令
提供了一个.py 脚本。阅读代码,发现 flag 内容会生成随机的 padding,最后一个
bytes 由用户提供,返回 RSA 加密的密文。用户可以提供 3 次,但每次的 padding 都
是重新随机生成的。
反复阅读代码,发现最后有个坑:每轮清空尾部的 padding 重新生成时,那条语句单
独放在了最后,没有放到 try-catch 块中,他默认 try-catch 里不会发生异常。而 int()转
换用户输入时,是可以发生异常的
所以,一旦在读入用户输入时发生异常,那么在清空 flag 尾部的 padding 时,按照
bits/8 算就会少清空一个 byte。而这次异常的输入又不会记入 3 次之内。如此这般,
就可以将 flag 的内容逐渐加长,需要 padding 的逐渐减少。最终可以使得 flag 长度正
好不需要随机 padding。
又因为 n 的总长度是限制,flag 最大不超过 256 bytes,所以只需要连续输入 256 次字
母内容,这样就可以确保接下来不会有随机 padding 的影响了:
接下来,用户只需要提供 3 个不同的末尾 bytes 即可。根据 RSA 的计算方式,最后相
当于求解同余意义下的三元线性方程组。为了便于计算,3 个末尾 bytes 分别取 0, 1, 2:
对应的方程组是
x^3 = r1 mod n
(256x+1)^3 = r2 mod n
(256x+2)^3 = r3 mod n
x 是带有 padding 的 flag;r1, r2, r3 是末尾为 0, 1, 2 所得到的密文。直接求解方程
组,得到 x mod n。其后面是 padding,只需要保留前面的 bytes 即为 flag
分析程序发现: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;