pwn入门——2.工具基本使用

0x00 IDA pro

1. 两个版本

ida pro安装完成之后,会生成两个快捷方式,一个是ida pro(32-bit)一个是ida pro(64-bit),分别对应32位和64位程序

2. 分析程序

将文件拖动到ida中即可分析程序

常用快捷键

空格是看汇编
重命名 n

切换标签 tab

反编译F5

看汇编 空格

看字符串 shift + F12 ,
看各个段的位置 ctrl + s

查看反编译函数:tab/F5

查看字符串窗口:shift + F12

跳转到指定地址:G

追踪函数(交叉引用):X

解析成字符:R

反汇编窗口切换文本跟图形:space

重命名函数:N

退回到上个操作:esc

0x01 GDB

加载分析程序

gdb ./ret2text

退出gdb

q

运行程序

r / run

中断运行

ctrl + c

继续运行

c

下断点

b 函数名
b *函数地址

​b function/b *addr​​​

单步步入:

单步执行

ni #单步步过
si #单步步入
finish # 步出

计算器

p/d

查看当前函数汇编

disass

中断调试

gdb.attach(p)

退出当前函数

fini

查看当前文件权限

vmmap

查看栈结构

satck 大小

查看堆结构

heap

查看指定内存地址

x/40gx 地址

0x02 Pwntools

pwntools介绍

Pwntools是一个CTF框架和漏洞利用开发库,用Python开发,旨在让使用者简单快速的编写exploit。

几乎涵盖了做pwn题目脚本所需要用到的各种工具。

导入pwntools

from pwn import *

建立连接

建立连接对于解pwn题尤为重要,比赛时,一般会给你一个pwn题目文件(一般是linux elf文件),还会给你一个nc地址。

  • elf文件用于本地调试,发现漏洞
  • nc地址用于攻击,获取flag

因此,我们需要与nc服务器和elf文件建立连接。

与程序文件建立连接

我们可以利用pwnlib.elf模块来连接程序文件。

r = process('./bin')			#本地创建进程,本地调试
elf = ELF('./process') 			#process为题目给出的程序文件
与服务器建立连接

我们通过pwnlib.tubes模块来连接服务器

r = remote('ip',port) #在对应位置填入题目给出的ip和端口

设置目标架构和操作系统

我们可以通过设置目标架构和操作系统,来告诉pwntools我们程序的运行环境,pwntools会自动帮我们调整对应的编译格式和字节序。

context.arch = 'i386' 				#32位程序设置为i386;64位程序设置为amd64,如果已经导入elf文件,可以写成context.arch = elf.arch
context.binary = './process' 			#可以用这种方法自动设置成适当的值
context.os = 'linux'				#设置系统信息
context.log_level = 'debug' 			#可在屏幕上打印debug信息
context.terminal = ['tmux', 'splitw', '-h'] 	#告诉pwntools你的终端信息,方便后期动态调试
context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
context.terminal = ['ssh', '-x', 'sh', '-c']
context.endian = 'big' 				#设置字节序为大端序,小端序设置为little

交互

在了解了上述的一些准备工作之后,我们可以尝试开始和程序进行交互了。

接收数据
r.recv() 		#接收数据
r.recvline() 		#接收一行数据
r.recvall() 		#接收数据,直到达到EOF
发送数据
r.send() 				#发送数据
r.sendline() 				#发送一行数据
r.sendlineafter('str',payload) 		#当接收到指定数据时,发送数据
shell交互
r.interactive()

获取函数地址

当我们成功连接到程序文件时,我们可以利用pwntools快速获取函数地址。

例如获取puts函数地址:

puts_got_addr = elf.got['puts'] #获取puts函数got表地址
puts_plt_addr = elf.plt['puts'] #获取puts函数plt表地址
puts_sym_addr = elf.symbols['puts'] #获取puts函数符号表地址

shellcraft

我们做题时,会经常用到shellcode,但是每次都从网上找对应的shellcode会大大降低我们的做题效率。shellcraft模块可以帮我们自动生成shellcode。

shellcraft.sh()

打包解包&汇编

在我们发送和接收数据时,会经常使用打包解包操作。

p32() #将数据打包成32位二进制格式,字节序由context.endian设置
p64() #将数据打包成64位二进制格式,字节序由context.endian设置
u32() #将32位二进制格式数据解包
u64() #将64位二进制格式数据解包

有时我们也会用到汇编操作,例如我们要发送shellcode:

shellcode = asm(shellcraft.sh())
r.sendline(shellcode)

0x03 one_gadget

Github:GitHub - david942j/one_gadget: The best tool for finding one gadget RCE in libc.so.6

1. 支持架构:

  • i386
  • amd64 (x86-64)
  • aarch64 (ARMv8)

2. 用法

$ one_gadget
# Usage: one_gadget <FILE|-b BuildID> [options]
#     -b, --build-id BuildID           BuildID[sha1] of libc.
#     -f, --[no-]force-file            Force search gadgets in file instead of build id first.
#     -l, --level OUTPUT_LEVEL         The output level.
#                                      OneGadget automatically selects gadgets with higher successful probability.
#                                      Increase this level to ask OneGadget show more gadgets it found.
#                                      Default: 0
#     -n, --near FUNCTIONS/FILE        Order gadgets by their distance to the given functions or to the GOT functions of the given file.
#     -r, --[no-]raw                   Output gadgets offset only, split with one space.
#     -s, --script exploit-script      Run exploit script with all possible gadgets.
#                                      The script will be run as 'exploit-script $offset'.
#         --info BuildID               Show version information given BuildID.
#         --base BASE_ADDRESS          The base address of libc.
#                                      Default: 0
#         --version                    Current gem version.

#eg:
$ one_gadget libc.so
root@ubuntu:~/pwn$ one_gadget libc-2.23.so
0x45216 execve("/bin/sh", rsp+0x30, environ)
constraints:
  rax == NULL

0x4526a execve("/bin/sh", rsp+0x30, environ)
constraints:
  [rsp+0x30] == NULL

0xf0274 execve("/bin/sh", rsp+0x50, environ)
constraints:
  [rsp+0x50] == NULL

0xf1117 execve("/bin/sh", rsp+0x70, environ)
constraints:
  [rsp+0x70] == NULL

0x04 checksec

1. 用法

检查保护机制

$ checksec ./pwn

0x05 ROPgadget

Github:GitHub - JonathanSalwan/ROPgadget: This tool lets you search your gadgets on your binaries to facilitate your ROP exploitation. ROPgadget supports ELF, PE and Mach-O format on x86, x64, ARM, ARM64, PowerPC, SPARC, MIPS, RISC-V 64, and RISC-V Compressed architectures.

1. 用法

usage: ROPgadget.py [-h] [-v] [-c] [--binary <binary>] [--opcode <opcodes>]
                    [--string <string>] [--memstr <string>] [--depth <nbyte>]
                    [--only <key>] [--filter <key>] [--range <start-end>]
                    [--badbytes <byte>] [--rawArch <arch>] [--rawMode <mode>]
                    [--rawEndian <endian>] [--re <re>] [--offset <hexaddr>]
                    [--ropchain] [--thumb] [--console] [--norop] [--nojop]
                    [--callPreceded] [--nosys] [--multibr] [--all] [--noinstr]
                    [--dump] [--silent] [--align ALIGN] [--mipsrop <rtype>]

description:
  ROPgadget lets you search your gadgets on a binary. It supports several
  file formats and architectures and uses the Capstone disassembler for
  the search engine.

formats supported:
  - ELF
  - PE
  - Mach-O
  - Raw

architectures supported:
  - x86
  - x86-64
  - ARM
  - ARM64
  - MIPS
  - PowerPC
  - Sparc

optional arguments:
  -h, --help            show this help message and exit
  -v, --version         Display the ROPgadget's version
  -c, --checkUpdate     Checks if a new version is available
  --binary <binary>     Specify a binary filename to analyze
  --opcode <opcodes>    Search opcode in executable segment
  --string <string>     Search string in readable segment
  --memstr <string>     Search each byte in all readable segment
  --depth <nbyte>       Depth for search engine (default 10)
  --only <key>          Only show specific instructions
  --filter <key>        Suppress specific mnemonics
  --range <start-end>   Search between two addresses (0x...-0x...)
  --badbytes <byte>     Rejects specific bytes in the gadget's address
  --rawArch <arch>      Specify an arch for a raw file
                        x86|arm|arm64|sparc|mips|ppc
  --rawMode <mode>      Specify a mode for a raw file 32|64|arm|thumb
  --rawEndian <endian>  Specify an endianness for a raw file little|big
  --re <re>             Regular expression
  --offset <hexaddr>    Specify an offset for gadget addresses
  --ropchain            Enable the ROP chain generation
  --thumb               Use the thumb mode for the search engine (ARM only)
  --console             Use an interactive console for search engine
  --norop               Disable ROP search engine
  --nojop               Disable JOP search engine
  --callPreceded        Only show gadgets which are call-preceded
  --nosys               Disable SYS search engine
  --multibr             Enable multiple branch gadgets
  --all                 Disables the removal of duplicate gadgets
  --noinstr             Disable the gadget instructions console printing
  --dump                Outputs the gadget bytes
  --silent              Disables printing of gadgets during analysis
  --align ALIGN         Align gadgets addresses (in bytes)
  --mipsrop <rtype>     MIPS useful gadgets finder
                        stackfinder|system|tails|lia0|registers

examples:
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --ropchain
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --depth 3
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --string "main"
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --string "m..n"
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --opcode c9c3
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --only "mov|ret"
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --only "mov|pop|xor|ret"
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --filter "xchg|add|sub|cmov.*"
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --norop --nosys
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --range 0x08041000-0x08042000
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --string main --range 0x080c9aaa-0x080c9aba
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --memstr "/bin/sh"
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --console
  ROPgadget.py --binary ./test-suite-binaries/elf-Linux-x86 --badbytes "00|01-1f|7f|42"
  ROPgadget.py --binary ./test-suite-binaries/Linux_lib64.so --offset 0xdeadbeef00000000
  ROPgadget.py --binary ./test-suite-binaries/elf-ARMv7-ls --depth 5
  ROPgadget.py --binary ./test-suite-binaries/elf-ARM64-bash --depth 5
  ROPgadget.py --binary ./test-suite-binaries/raw-x86.raw --rawArch=x86 --rawMode=32

0x06 LibcSearcher

Github:GitHub - lieanu/LibcSearcher: glibc offset search for ctf.

1. 简介

这是针对CTF比赛所做的小工具,在泄露了Libc中的某一个函数地址后,常常为不知道对方所使用的操作系统及libc的版本而苦恼,常规方法就是挨个把常见的Libc.so从系统里拿出来,与泄露的地址对比一下最后12位。

2. 安装

git clone https://github.com/lieanu/LibcSearcher.git
cd LibcSearcher
python setup.py develop

3. 用法

from LibcSearcher import *

#第二个参数,为已泄露的实际地址,或最后12位(比如:d90),int类型
libc = LibcSearcher("fgets", 0X7ff39014bd90)

libc.dump("system")        #system 偏移
libc.dump("str_bin_sh")    #/bin/sh 偏移
libc.dump("__libc_start_main_ret")  

注:如遇到无法找到对应libc库的情况,可以使用在线的查找工具

http://game2.ericdshen.com:31337/

0x07 GCC编译

命令参数

1.关掉DEP/NX(堆栈不可执行)

gcc -z execstack -o level level.c

2.关掉Stack Protector/Canary(栈保护)

gcc -fno-stack-protector -o level level.c

3.关掉/开启程序ASLR/PIE(程序随机化保护)

gcc -no-pie level level.c
gcc -pie level level.c

4.关闭/开启整个linux系统的ASLR保护

sudo -s echo 0 > /proc/sys/kernel/randomize_va_space exit
sudo -s echo 2 > /proc/sys/kernel/randomize_va_space

5.64位linux下面的GCC编译出一个32位可执行程序

#加参数 -m32
gcc -m32 -z execstack -fno-stack-protector -o level level.c

6.关闭所有保护

gcc -z execstack -fno-stack-protector -no-pie -o level level.c

0x08 常用命令

1. file命令

查看文件类型

$ file ./pwn

2. ldd命令

查看库

$ ldd ./pwn

3. objdump命令

反汇编

$ objdump -d -M intel ./pwn
def dbg():
	gdb.attach(r)
	pause()

​在需要调试的地方插入dbg(),如果我们之前在context.terminal中设置好终端类型,会自动帮我们开启新的终端窗口并打开gdb调试。​

查看文件在硬盘中的结构

objdump -s elf
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值