1. 程式人生 > >ctf-pwn的一些小技巧

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表示需要修改成的值;