我们这题被锤了,理由是与摘星实验室wp重合度高
重合度有多高我不知道,但是我们所有人都压根没听说过这个实验室
所以在这里放一个更加细致的wp,不想让几十个小时的努力付之东流。
文件打开了,函数很多,有3800个
先查字符串,对照着程序的运行结果
找到main函数
在这里,IDA 7.0无法很好的解释该程序,导致F5得到结果看起来正确但实际并不完整。
而IDA 7.6则会显著的标出错误部分,方便汇编代码上的审查
这是IDA7.6最初分析出来的main函数
看一下汇编代码,发现其中有很多字节码的混淆
这些才是导致IDA误判函数内容的原因
手动修复一下
得到main函数
void __usercall sub_4A2980(__int64 a1@<rbx>, __int64 a2@<rbp>, __int64 a3@<rdi>, __int64 a4@<rsi>, __int64 a5@<r12>, __int64 a6@<r13>, __int64 a7@<r14>, __int64 a8@<r15>)
{
char *v8; // r15
char *v9; // rdi
int *v10; // r12
char *v11; // r14
char *v12; // rbx
char *v13; // r13
int v14; // eax
signed __int64 v15; // rax
int v16; // edx
int v17; // eax
signed __int64 v18; // rax
int v19; // edx
int v20; // ecx
int v21; // eax
__int64 v22; // rax
char v23; // dl
char v24; // [rsp+30h] [rbp-3F8h]
__int64 v25; // [rsp+70h] [rbp-3B8h]
char v26; // [rsp+80h] [rbp-3A8h]
__int64 v27; // [rsp+C8h] [rbp-360h]
__int64 v28; // [rsp+110h] [rbp-318h]
__int64 v29; // [rsp+158h] [rbp-2D0h]
char v30; // [rsp+1A0h] [rbp-288h]
int v31; // [rsp+1C4h] [rbp-264h]
__int64 v32; // [rsp+1E8h] [rbp-240h]
int v33; // [rsp+20Ch] [rbp-21Ch]
char v34; // [rsp+2C0h] [rbp-168h]
char v35[8]; // [rsp+3E0h] [rbp-48h]
sub_40CC40();
memset(&v24, 0, 0x50ui64);
sub_49F840(&unk_4A68E0, "Input Your Key:");
sub_4A04A0(&unk_4A6580, &v24);
if ( strlen(&v24) == 64 )
{
if ( __OFADD__(1, 2004318072) )
{
if ( !__OFADD__(1, 2004318072) )
JUMPOUT(*(_QWORD *)&byte_4A2A4F);
}
v8 = &v24;
v9 = &v34;
v10 = (int *)&unk_4A4020;
v11 = &v34;
sub_49F840(&unk_4A68E0, "Are You Sure You Want To Keep Waiting...\n");
v12 = &v26;
v13 = &v26;
do
{
v14 = sub_401DB0(v8, 8i64);
v12[8] = 0;
*((_DWORD *)v12 + 1) = v14;
v15 = 4i64;
while ( 1 )
{
v16 = v15;
if ( v12[v15 + 3] )
break;
if ( !--v15 )
{
v16 = 0;
break;
}
}
*(_DWORD *)v12 = v16;
v17 = *v10;
v11[8] = 0;
*((_DWORD *)v11 + 1) = v17;
v18 = 4i64;
while ( 1 )
{
v19 = v18;
if ( v11[v18 + 3] )
break;
if ( !--v18 )
{
v19 = 0;
break;
}
}
v8 += 8;
*(_DWORD *)v11 = v19;
v12 += 36;
v11 += 36;
++v10;
}
while ( v8 != (char *)&v25 );
sub_403460(&v30, 13i64);
sub_403460(&v31, 14i64);
sub_403460(&v32, 15i64);
sub_403460(&v33, 16i64);
sub_4029E0(&v26, &v30);
sub_4029E0(&v27, &v30);
sub_402030(&v28, &v30);
sub_402030(&v29, &v30);
v20 = 0;
while ( 1 )
{
v21 = *(_DWORD *)v13;
if ( *(_DWORD *)v13 != *(_DWORD *)v9 )
break;
if ( v21 - 1 >= 0 )
{
if ( v35[36 * v20 - 861 + v21] != v35[36 * v20 - 285 + v21] )
break;
v22 = v21 - 2;
while ( (signed int)v22 >= 0 )
{
v23 = v13[v22-- + 4];
if ( v23 != v9[v22 + 5] )
goto LABEL_2;
}
}
++v20;
v13 += 36;
v9 += 36;
if ( v20 == 8 )
{
sub_401550("QWB{%s}\n");
return;
}
}
}
LABEL_2:
sub_401550("sorry\n");
}
第一关做了一个小判断,在修复函数前是很难看出来什么意思的
但也可以用x64dbg进行动态调试,勉强能够猜出是判断字符串的长度是不是等于0x40
之后遇到一个很费时的一个函数401EF0
进去之后基本看不懂,但是输入是写死的,只需要把每一个返回值找到就行了
记录下这些返回值,就是产生的key
key = [0xfffd,0x1fffd,0x3fffd,0x7fffd]
在下面的函数中被用到
随后来到函数sub_403460
看到这里(v16>>11) & 3
基本上就能猜出来是XTEA加密了
同时delta是0xE6EF3D20 sum是0x70C88617
其中的运算符全部用函数来代替了
接着再看sub_402030
里面又出现了401EF0函数,用来产生一个值
再往下看又遇见了xor函数
即把密文与401EF0产生的值进行异或操作
这四个函数都是相同的操作
依次找出所有的异或值
0xfd,0x1fd,0x3fd,0x7fd
然后就是进行字符串的比对了
由此写出脚本
def TEAdecode(c, key):
tmp_0 = c[0]
tmp_1 = c[1]
sum = 0xa6a53780
delta = 0x3d3529bc
for i in range(32):
tmp_1 -= ((tmp_0<<4) + key[2]) ^ (tmp_0 + sum) ^ ((tmp_0>>5) + key[3])
tmp_1 &= 0xffffffff
tmp_0 -= ((tmp_1<<4) + key[0]) ^ (tmp_1 + sum) ^ ((tmp_1>>5) + key[1])
tmp_0 &= 0xffffffff
sum -= delta
return (tmp_0, tmp_1)
def XTEAdecode(circle, c, key):
tmp_0 = c[0]
tmp_1 = c[1]
delta = 0x70C88617
sum = 0xE6EF3D20
for i in range(circle):
tmp_1 -= (((tmp_0 << 4) ^ (tmp_0 >> 5)) + tmp_0) ^ (sum + key[(sum>>11) & 3])
tmp_1 &= 0xffffffff
sum += delta;
tmp_0 -= (((tmp_1 << 4) ^ (tmp_1 >> 5)) + tmp_1) ^ (sum + key[sum & 3])
tmp_0 &= 0xffffffff
return (tmp_0, tmp_1)
c = [0x1F306772, 0xB75B0C29, 0x4A7CDBE3, 0x2877BDDF, 0x1354C485, 0x357C3C3A, 0x738AF06C, 0x89B7F537]
key = [0xfffd,0x1fffd,0x3fffd,0x7fffd]
for i in range(0, 4, 2):
c[i] ^= 0xfd
c[i+1] ^= 0x1fd
for i in range(4, 8, 2):
c[i] ^= 0x3fd
c[i+1] ^= 0x7fd
flag = ''
for i in range(0, 4, 2):
ans = XTEAdecode(32, c[i:], key)
flag += hex(ans[0])[2:] + hex(ans[1])[2:]
for i in range(4, 8, 2):
ans = TEAdecode(c[i:], key)
flag += hex(ans[0])[2:] + hex(ans[1])[2:]
print("QWB{"+flag.upper()+"}")
不知道是不是因为xtea和tea解密脚本相似度高的原因
但是如果是因为这个而ban掉参赛队伍,未免不太负责.毕竟解密脚本全网统一,我也是从网上找的代码....