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; // [rsp+14h] [rbp-4Ch]
char *endptr; // [rsp+18h] [rbp-48h] BYREF
char *v6; // [rsp+20h] [rbp-40h] BYREF
char *v7; // [rsp+28h] [rbp-38h] BYREF
char *v8; // [rsp+30h] [rbp-30h] BYREF
__int64 v9; // [rsp+38h] [rbp-28h]
__int64 v10; // [rsp+40h] [rbp-20h]
__int64 v11; // [rsp+48h] [rbp-18h]
__int64 v12; // [rsp+50h] [rbp-10h]
unsigned __int64 v13; // [rsp+58h] [rbp-8h]

v13 = __readfsqword(0x28u);
if ( argc != 5 )
{
puts("argc nonono");
exit(1);
}
v4 = strtol(argv[4], &endptr, 16) - 25923; // agrv 转化为long int[0-9,a-f]
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; // [rsp+1Ch] [rbp-14h]
__int64 v3; // [rsp+20h] [rbp-10h]
_QWORD *ptr; // [rsp+28h] [rbp-8h]

if ( a1 <= 1 || a1 > 200 )
return 0LL;
ptr = malloc(8LL * a1);
*ptr = 1LL; // 前两位为1
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]
# print(v9)
return v9

for i in range(1,199):
v4=i;
v9=feb(v4)
# print(v4,v4+3*v9)
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)
# flag{newbee_here}