ctf-pwn的一些小技巧

当我们在写exp的时候有些需要去复制粘贴某些函数在plt表,got表的地址,或者找ROP的地址,有些时候复制粘贴不方便且不方便阅读,这样时候我们就可以用pwntools中提供的一些函数;

以32位程序的exp为例:

ROPgadget:

0x0804872f : pop ebp ; ret
0x0804872c : pop ebx ; pop esi ; pop edi ; pop ebp ; ret
0x0804843d : pop ebx ; ret
0x0804872e : pop edi ; pop ebp ; ret
0x0804872d : pop esi ; pop edi ; pop ebp ; ret
0x08048426 : ret
0x0804857e : ret 0xeac1

在exp中的0x0804843d,可以这样代替:

p32(rop.search(8).address)

其中rop:

proc = ‘文件路径’
elf = ELF(proc)
rop = ROP(elf)

找到gets函数在plt表中的位置,并将一段字符串写入bss段中:

p32(elf.plt['gets']) + 'aaaa' + p32(elf.bss()+0x100)
p.sendline("要写入的字符串")

获得gets函数在got表中的地址:

p32(elf.got['puts'])

在exp中附加gdb调试exp:

context.log_level = 'debug'

#context.terminal = ['deepin-terminal', '-x', 'sh' ,'-c']
#deepin系统要加这句
if args.G:
    gdb.attach(p)

当带G参数运行exp时(python exp.py G),就会把gdb附加进去了;

执行int 0x80可执行对应的系统调用:

比如对于系统调用

execve("/bin/sh",NULL,NULL)
  • 系统调用号即eax应该为0xb(32位程序)或0x3b(64位程序)
  • 第一个参数即ebx应该指向/bin/sh的地址,其实执行sh的地址也可以
  • 第二个参数即ecx应该为0
  • 第三个参数edx应该为0

linux x64的传参方式:
它不同于x86的栈传参,它是优先6个寄存器传参,依次是RDI,RSI,RDX,RCX,R8,R9,然后多余的参数才传进栈内,所以在进行ROP,找gadget的时候注意先从rdi开始传参数,然后再是RSI,RDX,RCX,R8,R9,最后才是栈上面的;

知道libc.so找函数的偏移的方法:

libc = ELF('./libc.so')

system_offset = libc.symbols['system']

binsh_offset = next(libc.search('/bin.sh'))

recvuntil('?') : 直到看到' ?'后才进行操作;

格式化字符串常用函数 fmtstr_payload:

格式:

fmtstr_payload(num,{x_addr:str_addr})

num相当于%n$x中的n,表示第几个数,x_addr表示要修改的值的地址,str_addr表示需要修改成的值;

猜你喜欢

转载自blog.csdn.net/qq_40827990/article/details/83899433