# 环境
# python
# str 和 bytes 转换
B = S.encode('utf-8') #可忽略参数 | |
S = B.decode('utf-8') | |
B = bytes(S,'utf-8') #不可忽略参数 |
# 字符串替换
dynstr = dynstr.replace("read","system") |
# checksec
- RELRO got 表写权限 Partial RELRO 代表具有写权限
- stack canary 栈溢出保护
- NX:No-eXecute 不可执行保护
- PIE(ASLR)内存地址随机化 代码地址前几位随机 后几位固定
# PWNtools
# 常用命令
context(log_level='debug') #python 调试 | |
gdb.attach(p, 'b *0x080323') #gdb 动态调试 |
# elf
当拥有 libc 文件时,利用 ret2libc 寻找 /bin/sh 字符串
libc=ELF(./libc.so.6) | |
binsh = libcbase + next(libc.search(b'/bin/sh')) |
获取.dynstr 段的数据
dynstr = elf.get_section_by_name('.dynstr').data() |
# LibcSearcher
from LibcSearcher import LibcSearcher | |
#获取__libc_start_main 的真实地址储存至 lsm_a | |
libc = LibcSearcher('__libc_start_main',lsm_a) #参数 1 为字符串,函数名,参数 2 为地址 | |
libcbase = lsm_a - libc.dump('__libc_start_main') | |
sys_a = libcbase + libc.dump('system') | |
bs_a = libcbase + libc.dump('str_bin_sh') |
# ROP
详细的资料
rop=ROP('./pwn',base=0x400000,badchars=b'\n') #一般只需第一个参数 | |
rop.chain(base: int=None) #返回 bytes 数据 | |
rop.call(resolvable, arguments: list=()) #加入某函数调用 | |
rop.raw(value) #直接填充一个值 | |
rop.dump(base: int=None) #用好看的方式打印构造后 | |
rop.migrate(next_base) | |
rop.resolve(resolvable) | |
rop.ret2csu(self, edi=Padding(‘edi’), rsi=Padding(‘rsi’), rdx=Padding(‘rdx’), rbx=Padding(‘rbx’), rbp=Padding(‘rbp’), r12=Padding(‘r12’), r13=Padding(‘r13’), r14=Padding(‘r14’), r15=Padding(‘r15’), call=None) |
rop = ROP("./main_no_relro_64") | |
rop.call('read', 0, bss_base, 100) | |
rop.raw(csu(0, 1 ,elf.got['read'],0,0x600988+8,8)) | |
rop.raw(0x0000000000400771) | |
print(len(rop.chain())) | |
rop.raw('a'*(stack_size-len(rop.chain()))) | |
io.send(rop.chain()) |
# GDB
-
l
-
b *0x999
b func
断点
-
p func
print 打印变量内容
-
x /80wg 0x9323454
读取内存内容 单位数 字节 单位字节数
-
vmmap
# objdump
objdump -d -j .plt pwn #查看.plt 表 |