打开查壳,找到主函数
int __cdecl main(int argc, const char **argv, const char **envp)
{
unsigned 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; // 将字符串类型转换为相应的long类型
v9 = f(v4);
v10 = strtol(argv[1], &v6, 16);
v11 = strtol(argv[2], &v7, 16);
v12 = strtol(argv[3], &v8, 16);
if ( v9 - v10 != 0x233F0E151CLL )
{
puts("argv1 nonono!");
exit(1);
}
if ( v9 - v11 != 0x1B45F81A32LL )
{
puts("argv2 nonono!");
exit(1);
}
if ( v9 - v12 != 0x244C071725LL )
{
puts("argv3 nonono!");
exit(1);
}
if ( (int)v4 + v12 + v11 + v10 != 0x13A31412F8CLL )
{
puts("argv sum nonono!");
exit(1);
}
puts("well done!decode your argv!");
return 0;
}
查找函数可知strtol()函数的作用是将字符串类型转换为相应的long类型。接着往下看,有很多方程组,可以想到用z3约束器来接方程组,其中V10,v11,v12可以用v9来表示。最后argv sum的方程式可以转换为v4+3*v9=...
先进入f()函数,查看v9与v4的关系,
f()函数如下:
__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;
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;
}
可以发现v4应该在1~200之间,想到爆破方法求出v4.v9.
爆破出来v4,v9 分别为58,591286729879;
然后写代码接出v10,v11,v12的解
from z3 import *
v10= Real('v10')
v11 = Real('v11')
v12 = Real('v12')
s = Solver()
s.add(591286729879 - v10 == 3563142128)
s.add( 591286729879- v11 == 27692482650)
s.add( 591286729879 - v12 == 367672337)
s.add(58+ v12 + v11 + v10 == 19163201824812)
if s.check() == sat:
result = s.model()
print(result)
else:
print("no")
v1=hex(591286729879- 0x233F0E151C)
v2=hex(591286729879-0x1B45F81A32)
v3=hex(591286729879-0x244C071725)
print(v1)
print(v2)
print(v3)
解出来的十六进制数转换为字符串,得到flag
flag{newbee_here}
学到的点:
- 尝试使用爆破方法解题
- strtol()函数含义是具体用法(此处参考一位大佬的文章)