一道很有意思的题,写wp记录一下。
题目自带ida文件,打开。
主函数逻辑
int __cdecl main(int argc, const char **argv, const char **envp)
{
int result; // eax
int v4; // ebx
size_t v5; // eax
int v6; // ebx
char Str[20]; // [esp+1Ch] [ebp-48h] BYREF
_DWORD v8[3]; // [esp+30h] [ebp-34h] BYREF
size_t v9; // [esp+3Ch] [ebp-28h]
int v10; // [esp+40h] [ebp-24h]
int v11; // [esp+44h] [ebp-20h]
_DWORD v12[3]; // [esp+48h] [ebp-1Ch]
int v13; // [esp+54h] [ebp-10h]
size_t len; // [esp+58h] [ebp-Ch]
FILE *v15; // [esp+5Ch] [ebp-8h]
__main();
v12[0] = func0; // exchange
v12[1] = func1; // |x+y|-|x|-|y|+2
v12[2] = func2; // |x|+|y|+2-|x+y|
v8[0] = 0;
v8[1] = 1;
v8[2] = 2;
v9 = 3;
v10 = 3;
v11 = 4;
v15 = fopen("data", "rb");
if ( !v15 )
return -1;
fseek(v15, 0, 2);
len = ftell(v15);
fseek(v15, 0, 0);
v13 = ftell(v15);
if ( v13 )
{
puts("something wrong");
result = 0;
}
else
{
for ( i = 0; i < len; ++i )
{
v4 = i;
Str[v4] = fgetc(v15);
}
v5 = strlen(Str);
if ( v5 <= len )
{
len = v9;
i = 0;
v13 = v11;
while ( i <= 2 )
{
v6 = i + 1;
v8[v6] = (v12[i])(v8, v10, v11);
v10 = ++i;
v11 = i + 1;
}
if ( v9 )
{
result = -1;
}
else
{
get_key(len, v13);
system("PAUSE");
result = 0;
}
}
else
{
result = -1;
}
}
return result;
}
get key函数打印flag。一开始简单看了下逻辑,发现参数就是3,4,遂写了个脚本跑了一遍,结果是flag: 20c2030ccc203002;直接wa。。。。。
说明里面有玄机,再次认真看看函数。
这里,在前面的赋值中v9=3,如果没有差错getkey函数不会被执行。
可能猫腻出在上面的加密里,看一看循环的逻辑。
三个函数都不复杂。v10,v11为下标。观察函数,发现在第三次循环时,赋值的对象是v8[3],超出了v8的范围,观察数据,发现v8[3]正好为v9。所以第三次循环的结果为v9时可以得到正确的执行路线。
再看前面的函数。函数打开了一个data文件,从里面读入字符填充str(长度20)这里v14相当于文件大小,v5为字符串长度,构造字节数量大于20的文件就可以满足执行
看完了逻辑来捋一遍思路。我们需要构造一个data,满足长度大于20,同时使第三次循环时函数返回值为0就可以解出flag。
按照正常逻辑,第三次循环的函数返回值是|x|+|y|+2-|x+y|,这个式子恒大于0。。
让我们奇思妙想。观察数据栈
(这是我命名后的样子)
既然第三个函数恒大于0;我们能不能通过第二个函数|x+y|-|x|-|y|+2来得到0呢,巧妙的是,我们可以通过第一个函数交换两个函数指针所指向的函数(在栈上可以看出,函数2,3分别对应v8[7],v8[8])从而实现构造0。而v8数组又可以通过data来控制。
现在我们可以开始构造data文件了。使用010editor
注意小端序存储。
前20个数据存入str,然后是v8数组(四个字节)。现在开始构造函数输入的数据。|x|+|y|+2-|x+y|这个式子当x,y大于零时,恒等于2。所以在|x+y|-|x|-|y|+2中,构造x=-1,y=2即可得到0
因此数组的前三个我们可以不管。第四个也就是v8[3],我们令它为0xffffffff(-1)
再往下是第一次函数交换时v8的下标,改为7和8。
保存后运行题目文件,得到flag。
flag{8cda1bdb68a72a392a3968a71bdb8cda}