ctfshow 数学不及格
无壳,64位
知识点
strtol() 16进制转字符串 斐波拉契数列 z3约束器(可以不用)
关键代码
#主函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
| int __cdecl main(int argc, const char **argv, const char **envp) { int v4; char *endptr; char *v6; char *v7; char *v8; __int64 v9; __int64 v10; __int64 v11; __int64 v12; unsigned __int64 v13;
v13 = __readfsqword(0x28u); if ( argc != 5 ) { puts("argc nonono"); exit(1); } v4 = strtol(argv[4], &endptr, 16) - 25923; v9 = f(v4); v10 = strtol(argv[1], &v6, 16); v11 = strtol(argv[2], &v7, 16); v12 = strtol(argv[3], &v8, 16); if ( v9 - v10 != 151381742876LL ) { puts("argv1 nonono!"); exit(1); } if ( v9 - v11 != 117138004530LL ) { puts("argv2 nonono!"); exit(1); } if ( v9 - v12 != 155894355749LL ) { puts("argv3 nonono!"); exit(1); } if ( v4 + v12 + v11 + v10 != 1349446086540LL ) { puts("argv sum nonono!"); exit(1); } puts("well done!decode your argv!"); return 0; }
|
f()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| __int64 __fastcall f(int a1) { int i; __int64 v3; _QWORD *ptr;
if ( a1 <= 1 || a1 > 200 ) return 0LL; ptr = malloc(8LL * a1); *ptr = 1LL; ptr[1] = 1LL; v3 = 0LL; for ( i = 2; i < a1; ++i ) { ptr[i] = ptr[i - 1] + ptr[i - 2]; v3 = ptr[i]; } free(ptr); return v3; }
|
思路
四个判断等式联立求解,划掉v10-v12,得v4+3*v9;又因为v9为v4下标范围内的斐波拉契数列值,因此通过0<v4<200,有爆破可能性,直接遍历爆破v4与v9。(v4=58,v9=591286729879)
后面依次求解v10-v12,并把它们转化为字符串。
exp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| def feb(n): li=[] v9=0 li.append(1) li.append(1) for i in range(2,n): li.append(li[i-1] + li[i-2]) v9=li[i] return v9
for i in range(1,199): v4=i; v9=feb(v4) if(v4+3*v9==151381742876+117138004530+155894355749+1349446086540): print(v4,v9) break
v10 = hex(151381742876-v9) v11 = hex(117138004530-v9) v12 = hex(155894355749-v9)
s='666c61677b6e65776265655f686572657d' flag='' for i in range(0,len(s),2): flag+=chr(int(s[i:i+2],16)) print(flag)
|