拿到程序发现 是用了 ollvm 混淆的
利用 deflat.py
脚本对程序去混淆。
__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
signed __int64 v4; // [rsp+1E0h] [rbp-110h]
int i; // [rsp+1E8h] [rbp-108h]
int idx; // [rsp+1ECh] [rbp-104h]
int v7; // [rsp+1ECh] [rbp-104h]
char s1[48]; // [rsp+1F0h] [rbp-100h]
char s[60]; // [rsp+220h] [rbp-D0h]
unsigned int v10; // [rsp+25Ch] [rbp-94h]
char *input_num; // [rsp+260h] [rbp-90h]
int v12; // [rsp+26Ch] [rbp-84h]
bool v13; // [rsp+272h] [rbp-7Eh]
unsigned __int8 v14; // [rsp+273h] [rbp-7Dh]
int v15; // [rsp+274h] [rbp-7Ch]
char *v16; // [rsp+278h] [rbp-78h]
int v17; // [rsp+284h] [rbp-6Ch]
int v18; // [rsp+288h] [rbp-68h]
bool v19; // [rsp+28Fh] [rbp-61h]
char *v20; // [rsp+290h] [rbp-60h]
int v21; // [rsp+298h] [rbp-58h]
bool v22; // [rsp+29Fh] [rbp-51h]
__int64 v23; // [rsp+2A0h] [rbp-50h]
bool v24; // [rsp+2AFh] [rbp-41h]
__int64 v25; // [rsp+2B0h] [rbp-40h]
__int64 v26; // [rsp+2B8h] [rbp-38h]
__int64 v27; // [rsp+2C0h] [rbp-30h]
__int64 v28; // [rsp+2C8h] [rbp-28h]
int v29; // [rsp+2D0h] [rbp-20h]
int v30; // [rsp+2D4h] [rbp-1Ch]
char *v31; // [rsp+2D8h] [rbp-18h]
int v32; // [rsp+2E0h] [rbp-10h]
int v33; // [rsp+2E4h] [rbp-Ch]
bool v34; // [rsp+2EBh] [rbp-5h]
v10 = 0;
memset(s, 0, 0x30uLL);
memset(s1, 0, 0x30uLL);
printf("Input:", 0LL);
input_num = s;
if ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 )
goto LABEL_43;
while ( 1 )
{
__isoc99_scanf("%s", input_num);
idx = 0;
if ( num1 < 10 || ((num2 - 1) * num2 & 1) == 0 )
break;
LABEL_43:
__isoc99_scanf("%s", input_num);
}
while ( 1 )
{
do
v12 = idx;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
v13 = v12 < 0x40;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 )
;
if ( !v13 )
break;
v14 = s[idx];
do
v15 = v14;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
if ( v15 == 10 )
{
v16 = &s[idx];
*v16 = 0;
break;
}
v17 = idx + 1;
do
idx = v17;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
}
for ( i = 0; ; ++i )
{
do
v18 = i;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
do
v19 = v18 < 6;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
if ( !v19 )
break;
do
v20 = s;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
v4 = *&v20[8 * i];
v7 = 0;
while ( 1 )
{
v21 = v7;
do
v22 = v21 < 64;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
if ( !v22 )
break;
v23 = v4;
v24 = v4 < 0;
if ( v4 >= 0 )
{
v27 = v4;
do
v28 = 2 * v27;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
v4 = v28;
}
else
{
v25 = 2 * v4;
do
v26 = v25;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
v4 = v26 ^ 0xB0004B7679FA26B3LL;
}
v29 = v7;
do
v7 = v29 + 1;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
}
v30 = 8 * i;
v31 = &s1[8 * i]; // 8字节
if ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 )
LABEL_55:
*v31 = v4;
*v31 = v4;
if ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 )
goto LABEL_55;
v32 = i + 1;
}
do
v33 = memcmp(s1, &cmp_data, 0x30uLL); // 0BC8FF26D43536296h
// 520100780530EE16h
// 4DC0B5EA935F08ECh
// 342B90AFD853F450h
// 8B250EBCAA2C3681h
// 55759F81A2C68AE4h
// 0B0004B7679FA26B3h
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 );
v34 = v33 != 0;
while ( num1 >= 10 && ((num2 - 1) * num2 & 1) != 0 )
;
if ( v34 )
puts("Wrong!");
else
puts("Correct!");
return v10;
}
混淆不是去的很完整。 但是 可以 比较明白的 看出程序的 逻辑。
这个时候 我们 可以先把 这个 加密的 具体逻辑写下来。
v12 = 0
if(v12<0x40):
v4 = v28
if(v4 >= 0):
v28 = v28 * 2
else:
v28 = v28 * 2
v28 = v28 ^ 0xB0004B7679FA26B3
v12 += 1
发现是 每次 都 乘2 一共乘了 0x40次 得到的 计算结果 喝一个 数组 比较 0x30 大小。
0xbc8ff26d43536296,
0x520100780530ee16,
0x4dc0b5ea935f08ec,
0x342b90afd853f450,
0x8b250ebcaa2c3681,
0x55759f81a2c68ae4
程序的主要逻辑是和 0xB0004B7679FA26B3
进行一个 异或。在这里,发现一个 知识。
一个奇数 异或 一个偶数 为 一个奇数, 一个奇数 异或 一个奇数 为 偶数 (程序的逻辑可以根据这个规则来写出 逆向脚本。注意每次异或 数据的长度可能发生变化)
因为加密里面 v4
是一个有符号数。所以我们在计算的时候,注意 ^ 0xB0004B7679FA26B3
会变成一个 奇数切变号,所以在每次 进行操作后要 | 0x8000000000000000
得到的值才是有效的。
# v12 = 0
# if(v12<0x40):
# v4 = v28
# if(v4 >= 0):
# v28 = v28 * 2
# else:
# v28 = v28 * 2
# v28 = v28 ^ 0xB0004B7679FA26B3
# v12 += 1
print (3^1)
print (4^1)
print (5^1)
print("------------------")
print (3^2)
print (4^2)
print (5^2)
cmp_data = [0xbc8ff26d43536296,
0x520100780530ee16,
0x4dc0b5ea935f08ec,
0x342b90afd853f450,
0x8b250ebcaa2c3681,
0x55759f81a2c68ae4]
key = 0xB0004B7679FA26B3
data = ""
for value in cmp_data:
for i in range(0, 64):
tail = value & 1
if tail == 1:
value = value ^ key
value = value // 2
if tail == 1:
value = value | 0x8000000000000000
#print(hex(value))
# end for
print(hex(value))
j = 0
while (j < 8):
data += chr(value & 0xFF)
value = value >> 8
j += 1
# end while
#end for
print(data)
# flag{6ff29390-6c20-4c56-ba70-a95758e3d1f8}