PWN

PWN study 0x01

PWN 渐入佳境

Posted by Elli0t on 2020-03-31

exp 的编写( python2 )

推荐使用 Sublime 编写 exp ,其中的 snippets 可以快速编写 exp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from pwn import *
import sys

context.terminal=["tmux","sp","-h"] #设置调试终端
context.log_level='debug' #设置详细程度("debug" 最为详细)

DEBUG = 1
LOCAL = True
BIN = 'bin'
HOST = 'host'
PORT = port

def exploit(p):


p.interactive()
return

if __name__ == '__main__':
elf = ELF(BIN)
if len(sys.argv) > 1:
LOCAL = False
p = remote(HOST,PORT) #远程
exploit(p)
else:
LOCAL = True
p = process(BIN) #本地
log.info('PID: ' + str(proc.pidof(p)[0]))
# pause
if DEBUG:
gdb.attach(p)
exploit(p)
  • 常用函数
    • context 用来指定各指令集和操作系统
      • context(os=’linux’,arch=’i386’,log_level=’debug’)
        • os 设置操作系统,可以设置的操作系统有 linux,windows,android,freebsd,cgc
        • arch 设置指令集,可以设置的有:’aarch64’, ‘alpha’, ‘amd64’, ‘arm’, ‘avr’, ‘cris’, ‘i386’, ‘ia64’, ‘m68k’, ‘mips’, ‘mips64’, ‘msp430’, ‘powerpc’, ‘powerpc64’, ‘s390’, ‘sparc’, ‘sparc64’, ‘thumb’, ‘vax’
        • log_level 设置日志详细程度,可以设置的有:’CRITICAL’, ‘DEBUG’, ‘ERROR’, ‘INFO’, ‘NOTSET’, ‘WARN’, ‘WARNING’
        • context.binary 可以根据二进制文件来自动设置参数
    • p = process(‘./challenge’) 本地运行二进制文件
    • p = remote(ip,port) 连接远程服务器
    • 发送数据的函数:send sendline sendlineafter sendafter
      • p.sendlineafter(‘name:’,’eli0t’)
    • 接收数据的函数:recv recvuntil recvall
      • p.recvuntil(‘\n’,drop = True)
    • 进入交互模式:
      • p.interactive()
    • 地址的处理:主要是对整数进行打包,就是转换成二进制的形式,比如转换成地址。p32、p64是打包,u32、u64是解包。
      • u32(p.recv(4)) #把这个4字节的地址接受过来转换为一个32位的数
      • u64(p.recv(6).ljust(8,’\x00’)) #填充一个\x00再转为64位的数
      • p32(0x08041000). p64(0x7f8e214a526a) #发给程序
    • ELF
      • ELF(‘bin’).symobols[‘system’] # 获取 system 函数偏移
      • next(ELF(‘bin’).search(‘/bin/sh’)) # 查找 /bin/sh 字符串,要加上next
      • ELF(‘bin’).plt[‘write’] # 从 plt 表获取 write 地址
      • ELF(‘bin’).got[‘write’] # 从 got 表获取 wirte 地址
    • asm 提供了 asm 模块,可以将汇编语言转化为机器语言
      • asm(‘mov eax,1;’)
    • disasm 反汇编
      • print disasm(‘\x90\x90’)
    • shellcode 的生成
      • shellcraft.i386.linux.sh() #生成 Linux32 位的 shellcode
      • shellcraft.amd64.linux.sh() #生成 Linux64 位的 shellcode
      • demo : shellcode = asm(shellcraft.amd64.linux.sh(),arch=’amd64’)
    • gdb pwntools 提供了 gdb 模块可以配合 gdb 调试 exp
      • gdb.attach()//附加到一个进展上进行调试
      • gdb.debug()//在调试器下启用新进程进行调试
    • Dynelf
      • pwntools的一个模块,可以解决扩展时没有libc尴尬问题(当然也可以手动设置,通过libc-database查找具体libc)
    • ROP
      • 可以生成ROP链

sublime 的使用( snippets )

没什么好介绍的

1
2
3
4
5
6
7
8
9
10
11
<snippet>
<content><![CDATA[
print('hello world')
]]></content>
<!-- Optional: Tab trigger to activate the snippet -->
<tabTrigger>fuck</tabTrigger>
<!-- Optional: Scope the tab trigger will be active in -->
<scope>source.python</scope>
<!-- Optional: Description to show in the menu -->
<description>pwn exp</description>
</snippet>

ida 的使用

使用前确定程序位数(file 命令查看一下是64位还是32位),来使用不同的 ida 程序

  • F5 :进入函数

  • tab :回到汇编窗口

  • space :进入全局窗口

  • n :修改变量名和函数名称

  • X :查看交叉引用

  • Shift+F12 :查看字符串

查看程序用到的所有字符串

gdb 的使用( pwndbg )

pwndbg 是 gdb 一个插件, pwngdb 是 gdb 的功能拓展

  • 有很多详细的 gdb 教程
  • 常用指令
    • 下一条指令 ni,si # si 遇到 call 函数进入执行
    • 下断点 b main #在 main 函数停下来,b *0x5859c0。”*”号是必须加在地址前的,0x5859c0为函数指针的地址
    • 继续运行 c
    • 运行 r
    • 反汇编 disasm
    • 显示数据、内存
      • p # print 一些符号的地址
      • x/20gx 0x…(8直接显示) x/20wx 0x… (4字节显示)
      • x/s 0x… x/i 0x…
      • 查看寄存器 info r
      • 查看栈内容 stack 20
      • 内存映射 vmmap
      • tele
      • 查找数据 search
      • 查看 PLT 表 GOT 表 plt , got
      • 修改值 set *0x… = 0x… , set rbp = 0x
      • 运行时带参数
      • 栈溢出时构造字符串和确定偏移 cyclic 200 , cyclic -l baaa
      • 堆相关的指令
        • arena,paseheap,heapinfo,unlink,orange,binx,magic,tcache,…




命令 缩写 效果
gdb <*pid> 添加新程序
gdb attach 负载运行的程序
set args <*argv> 设置程序运行参数
show args 查看设置好的运行参数
quit q 退出gdb
symbol sy 导入符号表
info <*b> i 查看程序的状态/*查看断点
frame f 查看栈帧
backtrace bt 查看堆栈情况
list l 显示源代码
(debug模式)
display disp 跟踪查看某个变量
start s 启动程序并中断在入口
debug模式停在main(),否则停在start()
run r 直接运行程序直到断点
continue c 暂停后继续执行程序
next n 单步步过
step s 单步步入,函数跟踪
finish fin 跳出,执行到函数返回处
break /* b 下断点
watch 下内存断点并监视内存情况
print p 打印符号信息(debug模式)
x <n/f/u> 显示内存信息,具体用法附在下面
context 打印pwnbdg页面信息
dps 优雅地显示内存信息
disassemble 打印函数信息
vmmap 显示程序内存结构
search <*argv> 搜索内存中的值
输入 search -h 可查询用法
checksec 查看程序保护基质
x指令的具体用法:n、f、u为控制打印形式的参数
‘n‘ 代表打印格式,可为o(八进制),x(十六进制),d(十进制),u(无符号十进制),t(二进制),f(浮点类型),a(地址类型),i(解析成命令并反编译),c(字符)和s(字符串)
‘f‘ 用来设定输出长度,b(byte),h(halfword),w(word),giant(8bytes)。
‘u‘ 指定单位内存单元的字节数(默认为dword) 可用b(byte),h(halfword),w(word),giant(8bytes)替代
x指令也可以显示地址上的指令信息,用法:x/i

docker pwn 使用

这个是 python3 版本的

pwndocker网址

  • Docker Pull Command
    docker pull skysider/pwndocker

  • Usage

提前声明 ctf_name 的值(绑定的文件夹名称)
cap-add=SYS_PTRACE 开启 ptrace 权限

1
2
3
4
5
6
7
8
9
10
11
docker run -d \
--rm \
-h ${ctf_name} \
--name ${ctf_name} \
-v $(pwd)/${ctf_name}:/ctf/work \
-p 23946:23946 \
--cap-add=SYS_PTRACE \
skysider/pwndocker

启动:
docker exec -it ${ctf_name} /bin/bash

这个是 python2 版本的

https://hub.docker.com/r/beswing/swpwn/tags

  • Docker Pull Command
    docker pull beswing/swpwn:latest
  • Usage
    提前声明 ctf_name 的值(绑定的文件夹名称)

–rm :容器退出时就能够自动清理容器内部的文件系统
启动

1
2
3
4
5
6
docker run -it \
--rm \
--name ${ctf_name} \
-v $(pwd)/${ctf_name}:/pwn \
--cap-add=SYS_PTRACE \
beswing/swpwn

eli0t-pwn Docker

我自己搞了一个,稍微改了一下 swing 的
增加了一些工具🔧

https://hub.docker.com/r/ybm911/pwn

1
2
3
4
5
6
7
8
9
10
11
12
docker run -it \
--rm \
-w /pwn --name ${ctf_name} \
-v $(pwd)/${ctf_name}:/pwn \
--cap-add=SYS_PTRACE \
ybm911/pwn /bin/bash

docker run -it \
-w /pwn --name ${ctf_name} \
-v $(pwd)/${ctf_name}:/pwn \
--cap-add=SYS_PTRACE \
ybm911/pwn /bin/bash
参考链接

http://www.0daybank.org/?p=4309(跟我入坑PWN第一章)
http://www.freebuf.com
https://prowes5.github.io/2018/08/06/pwntools%E7%9A%84%E4%B8%80%E4%BA%9B%E7%AE%80%E5%8D%95%E5%85%A5%E9%97%A8%E6%80%BB%E7%BB%93/
http://brieflyx.me/2015/python-module/pwntools-intro/
Exploit利器——Pwntools
http://brieflyx.me/2015/python-module/pwntools-advanced/
Pwntools 高级应用