64位ELF文件
ida64中打开发现有两处控制流平坦化。
装好angr,使用基于angr的脚本deflat.py去除控制流平坦化,在deflat.py所在目录下打开cmd命令行输入
python deflat.py hardCpp 0x4007E0
#“python版本 + 脚本名 + 文件名 + 起始地址”
第二处控制流平坦化同理去除。
运行几分钟即可得到去除控制流平坦化之后的程序。
如果原版deflat.py出错,可以试试优化之后的deflat.py
ida64打开生成的hardCpp_recovered文件,出来的程序有很多混淆,但勉强可以看。
int __cdecl main(int argc, const char **argv, const char **envp)
{
char v3; // al
char v4; // al
char v5; // al
char v6; // al
char v8; // al
char v9; // al
char v10; // al
char v11; // al
char v12[8]; // [rsp+A0h] [rbp-90h] BYREF
char v13[8]; // [rsp+A8h] [rbp-88h] BYREF
char v14[8]; // [rsp+B0h] [rbp-80h] BYREF
char v15[8]; // [rsp+B8h] [rbp-78h] BYREF
char v16[8]; // [rsp+C0h] [rbp-70h] BYREF
char v17[7]; // [rsp+C8h] [rbp-68h] BYREF
char v18; // [rsp+CFh] [rbp-61h]
int v19; // [rsp+D0h] [rbp-60h]
int v20; // [rsp+D4h] [rbp-5Ch]
int v21; // [rsp+D8h] [rbp-58h]
int v22; // [rsp+DCh] [rbp-54h]
char s; // [rsp+E0h] [rbp-50h] BYREF
char v24[23]; // [rsp+E1h] [rbp-4Fh] BYREF
char v25[8]; // [rsp+F8h] [rbp-38h] BYREF
char v26[8]; // [rsp+100h] [rbp-30h] BYREF
char v27[8]; // [rsp+108h] [rbp-28h] BYREF
char v28[4]; // [rsp+110h] [rbp-20h] BYREF
int v29; // [rsp+114h] [rbp-1Ch]
const char **v30; // [rsp+118h] [rbp-18h]
int v31; // [rsp+120h] [rbp-10h]
int v32; // [rsp+124h] [rbp-Ch]
int v33; // [rsp+128h] [rbp-8h]
bool v34; // [rsp+12Eh] [rbp-2h]
v32 = 0;
v31 = argc;
v30 = argv;
v29 = time(0LL);
puts("func(?)=\"01abfc750a0c942167651c40d088531d\"?");// 01abfc750a0c942167651c40d088531d是'#'的md5散列,告诉我们第一个字符是#
s = getchar();
fgets(v24, 21, stdin);
v22 = time(0LL);
v21 = v22 - v29; // 0
v33 = v22 - v29; // 0
if ( y >= 10 && (((x - 1) * x) & 1) != 0 )
goto LABEL_13;
while ( 1 )
{
v20 = strlen(&s);
v34 = v20 != 21;
if ( y < 10 || (((x - 1) * x) & 1) == 0 )
break;
LABEL_13:
v20 = strlen(&s);
}
while ( 1 )
{
v19 = 1;
if ( y < 10 || (((x - 1) * x) & 1) == 0 )
break;
v19 = 1;
}
while ( v19 < 21 )
{
if ( y >= 10 && (((x - 1) * x) & 1) != 0 )
{
v18 = v21 ^ *(&s + v19); // v18 = s[v19];
v17[0] = main::$_0::operator()(v27, v18); // v17[0]=v18 = s[v19];后1个字符
v16[0] = main::$_1::operator()(v25, *(&s + v21 + v19 - 1));// v16[0]=v18 = s[v19-1];前1个字符
v8 = main::$_1::operator() const(char)::{lambda(int)#1}::operator()(v16, 7LL);// s[v19-1]%7
v18 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v17, v8);// 两个字符相加
v15[0] = main::$_2::operator()(v28, v18); // 相加结果存入v15
v14[0] = main::$_2::operator()(v28, *(&s + v21 + v19 - 1));// 前一个字符存入v14
v9 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v14, 18LL);// 前一个字符跟18异或
v13[0] = main::$_3::operator()(v26, v9); // 异或结果存入v13
v10 = main::$_3::operator() const(char)::{lambda(char)#1}::operator()(v13, 3LL);// 再乘3
v12[0] = main::$_0::operator()(v27, v10);
v11 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v12, 2LL);// 加上2
v18 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v15, v11);// 异或
}
do
{
v18 = v21 ^ *(&s + v19);
v17[0] = main::$_0::operator()(v27, v18);
v16[0] = main::$_1::operator()(v25, *(&s + v21 + v19 - 1));
v3 = main::$_1::operator() const(char)::{lambda(int)#1}::operator()(v16, 7LL);
v18 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v17, v3);
v15[0] = main::$_2::operator()(v28, v18);
v14[0] = main::$_2::operator()(v28, *(&s + v21 + v19 - 1));
v4 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v14, 18LL);
v13[0] = main::$_3::operator()(v26, v4);
v5 = main::$_3::operator() const(char)::{lambda(char)#1}::operator()(v13, 3LL);
v12[0] = main::$_0::operator()(v27, v5);
v6 = main::$_0::operator() const(char)::{lambda(char)#1}::operator()(v12, 2LL);
v18 = main::$_2::operator() const(char)::{lambda(char)#1}::operator()(v15, v6);
}
while ( enc[v19 - 1] != v18 );
while ( y >= 10 && (((x - 1) * x) & 1) != 0 )
;
++v19;
}
if ( y >= 10 && (((x - 1) * x) & 1) != 0 )
goto LABEL_16;
while ( 1 )
{
puts("You win");
if ( y < 10 || (((x - 1) * x) & 1) == 0 )
break;
LABEL_16:
puts("You win");
}
return 0;
}
while里面各个函数分析一下。前两个就算了。
main:😒 _1::operator() const(char)::{lambda(int)#1}::operator函数
v15 = *(&v5 - 16) + *v5是关键,等价于把两个字符串相加后返回。
__int64 __fastcall main::$_0::operator() const(char)::{lambda(char)#1}::operator()(__int64 a1, char a2)
{
int v2; // eax
int v3; // eax
char *v5; // [rsp+0h] [rbp-40h]
int v6; // [rsp+8h] [rbp-38h]
int v7; // [rsp+Ch] [rbp-34h]
int v8; // [rsp+10h] [rbp-30h]
int v9; // [rsp+14h] [rbp-2Ch]
char *v10; // [rsp+18h] [rbp-28h]
char v11; // [rsp+23h] [rbp-1Dh]
int v12; // [rsp+24h] [rbp-1Ch]
bool v13; // [rsp+2Ah] [rbp-16h]
bool v14; // [rsp+2Bh] [rbp-15h]
unsigned int v15; // [rsp+2Ch] [rbp-14h]
v13 = (((x_5 - 1) * x_5) & 1) == 0;
v14 = y_6 < 10;
v12 = 0x3D016016;
v11 = a2;
v10 = a1;
do
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
v9 = v12;
v8 = v12 + 2037067308;
if ( v12 != -2037067308 )
break;
v5 = v10;
*(&v5 - 16) = v11;
v12 = -1418698808;
}
v7 = v9 + 1418698808;
if ( v9 != -1418698808 )
break;
v3 = -2037067308;
v5 = v10;
*(&v5 - 16) = v11;
v15 = *(&v5 - 16) + *v5;//关键
if ( y_6 < 10 || (((x_5 - 1) * x_5) & 1) == 0 )
v3 = 1456142001;
v12 = v3;
}
v6 = v9 - 1023500310;
if ( v9 != 1023500310 )
break;
v2 = -2037067308;
if ( v14 || v13 )
v2 = -1418698808;
v12 = v2;
}
HIDWORD(v5) = v9 - 1456142001;
}
while ( v9 != 1456142001 );
return v15;
}
main:😒_2::operator()函数,
只是单纯的把上一个函数的结果再返回。
char __fastcall main::$_2::operator()(__int64 a1, char a2)
{
int v2; // eax
int v3; // eax
__int64 v5; // [rsp+0h] [rbp-50h]
int v6; // [rsp+Ch] [rbp-44h]
int v7; // [rsp+10h] [rbp-40h]
int v8; // [rsp+14h] [rbp-3Ch]
int v9; // [rsp+18h] [rbp-38h]
int v10; // [rsp+1Ch] [rbp-34h]
__int64 v11; // [rsp+20h] [rbp-30h]
char v12; // [rsp+2Fh] [rbp-21h]
int v13; // [rsp+30h] [rbp-20h]
bool v14; // [rsp+35h] [rbp-1Bh]
bool v15; // [rsp+36h] [rbp-1Ah]
char v16; // [rsp+37h] [rbp-19h]
v14 = (((x_11 - 1) * x_11) & 1) == 0;
v15 = y_12 < 10;
v13 = -1990873412;
v12 = a2;
v11 = a1;
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
v10 = v13;
v9 = v13 + 1990873412;
if ( v13 != -1990873412 )
break;
v2 = -1373097315;
if ( v15 || v14 )
v2 = 1457028246;
v13 = v2;
}
v8 = v10 + 1373097315;
if ( v10 != -1373097315 )
break;
v5 = v11;
*(&v5 - 16) = v12;
LOBYTE(v5) = *(&v5 - 16);
v13 = 1457028246;
}
v7 = v10 + 961146335;
if ( v10 == -961146335 )
break;
v6 = v10 - 1457028246;
if ( v10 == 1457028246 )
{
v3 = -1373097315;
v5 = v11;
*(&v5 - 16) = v12;
LOBYTE(v5) = *(&v5 - 16);
v16 = v5;
if ( y_12 < 10 || (((x_11 - 1) * x_11) & 1) == 0 )
v3 = -961146335;
v13 = v3;
}
}
return v16;
}
main:😒_2::operator() const(char)::{lambda(char)#1}::operator()函数
把第奇数个字符跟18异或。
__int64 __fastcall main::$_2::operator() const(char)::{lambda(char)#1}::operator()(_BYTE *a1, char a2)
{
return (a2 ^ *a1);
}
main:😒_3::operator函数
把上一个函数异或的结果返回一下,跟main:😒_2::operator函数 “ 异曲同工 ” 。
char __fastcall main::$_3::operator()(__int64 a1, char a2)
{
int v2; // eax
int v3; // eax
__int64 v5; // [rsp+0h] [rbp-50h]
int v6; // [rsp+Ch] [rbp-44h]
int v7; // [rsp+10h] [rbp-40h]
int v8; // [rsp+14h] [rbp-3Ch]
int v9; // [rsp+18h] [rbp-38h]
int v10; // [rsp+1Ch] [rbp-34h]
__int64 v11; // [rsp+20h] [rbp-30h]
char v12; // [rsp+2Fh] [rbp-21h]
int v13; // [rsp+30h] [rbp-20h]
bool v14; // [rsp+35h] [rbp-1Bh]
bool v15; // [rsp+36h] [rbp-1Ah]
char v16; // [rsp+37h] [rbp-19h]
v14 = (((x_15 - 1) * x_15) & 1) == 0;
v15 = y_16 < 10;
v13 = -538471561;
v12 = a2;
v11 = a1;
while ( 1 )
{
while ( 1 )
{
v10 = v13;
v9 = v13 + 2065325572;
if ( v13 != -2065325572 )
break;
v5 = v11;
*(&v5 - 16) = v12;
LOBYTE(v5) = *(&v5 - 16);
v13 = 975002192;
}
v8 = v10 + 983538015;
if ( v10 == -983538015 )
break;
v7 = v10 + 538471561;
if ( v10 == -538471561 )
{
v2 = -2065325572;
if ( v15 || v14 )
v2 = 975002192;
v13 = v2;
}
else
{
v6 = v10 - 975002192;
if ( v10 == 975002192 )
{
v3 = -2065325572;
v5 = v11;
*(&v5 - 16) = v12;
LOBYTE(v5) = *(&v5 - 16);
v16 = v5;
if ( y_16 < 10 || (((x_15 - 1) * x_15) & 1) == 0 )
v3 = -983538015;
v13 = v3;
}
}
}
return v16;
}
main:😒_3::operator() const(char)::{lambda(char)#1}::operator()函数
与3相乘。
__int64 __fastcall main::$_3::operator() const(char)::{lambda(char)#1}::operator()(char *a1, char a2)
{
return (a2 * *a1);
}
main:😒_0::operator函数
返回
char __fastcall main::$_0::operator()(__int64 a1, char a2)
{
return a2;
}
main:😒_0::operator() const(char)::{lambda(char)#1}::operator()
__int64 __fastcall main::$_0::operator() const(char)::{lambda(char)#1}::operator()(__int64 a1, char a2)
{
int v2; // eax
int v3; // eax
char *v5; // [rsp+0h] [rbp-40h]
int v6; // [rsp+8h] [rbp-38h]
int v7; // [rsp+Ch] [rbp-34h]
int v8; // [rsp+10h] [rbp-30h]
int v9; // [rsp+14h] [rbp-2Ch]
char *v10; // [rsp+18h] [rbp-28h]
char v11; // [rsp+23h] [rbp-1Dh]
int v12; // [rsp+24h] [rbp-1Ch]
bool v13; // [rsp+2Ah] [rbp-16h]
bool v14; // [rsp+2Bh] [rbp-15h]
unsigned int v15; // [rsp+2Ch] [rbp-14h]
v13 = (((x_5 - 1) * x_5) & 1) == 0;
v14 = y_6 < 10;
v12 = 0x3D016016;
v11 = a2;
v10 = a1;
do
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
v9 = v12;
v8 = v12 + 2037067308;
if ( v12 != -2037067308 )
break;
v5 = v10;
*(&v5 - 16) = v11;
v12 = -1418698808;
}
v7 = v9 + 1418698808;
if ( v9 != -1418698808 )
break;
v3 = -2037067308;
v5 = v10;
*(&v5 - 16) = v11;
v15 = *(&v5 - 16) + *v5; // 关键
if ( y_6 < 10 || (((x_5 - 1) * x_5) & 1) == 0 )
v3 = 1456142001;
v12 = v3;
}
v6 = v9 - 1023500310;
if ( v9 != 1023500310 )
break;
v2 = -2037067308;
if ( v14 || v13 )
v2 = -1418698808;
v12 = v2;
}
HIDWORD(v5) = v9 - 1456142001;
}
while ( v9 != 1456142001 );
return v15;
}
main:😒_0::operator() const(char)::{lambda(char)#1}::operator()函数
参数相加后返回。
__int64 __fastcall main::$_0::operator() const(char)::{lambda(char)#1}::operator()(__int64 a1, char a2)
{
int v2; // eax
int v3; // eax
char *v5; // [rsp+0h] [rbp-40h]
int v6; // [rsp+8h] [rbp-38h]
int v7; // [rsp+Ch] [rbp-34h]
int v8; // [rsp+10h] [rbp-30h]
int v9; // [rsp+14h] [rbp-2Ch]
char *v10; // [rsp+18h] [rbp-28h]
char v11; // [rsp+23h] [rbp-1Dh]
int v12; // [rsp+24h] [rbp-1Ch]
bool v13; // [rsp+2Ah] [rbp-16h]
bool v14; // [rsp+2Bh] [rbp-15h]
unsigned int v15; // [rsp+2Ch] [rbp-14h]
v13 = (((x_5 - 1) * x_5) & 1) == 0;
v14 = y_6 < 10;
v12 = 0x3D016016;
v11 = a2;
v10 = a1;
do
{
while ( 1 )
{
while ( 1 )
{
while ( 1 )
{
v9 = v12;
v8 = v12 + 2037067308;
if ( v12 != -2037067308 )
break;
v5 = v10;
*(&v5 - 16) = v11;
v12 = -1418698808;
}
v7 = v9 + 1418698808;
if ( v9 != -1418698808 )
break;
v3 = -2037067308;
v5 = v10;
*(&v5 - 16) = v11;
v15 = *(&v5 - 16) + *v5; // 关键
if ( y_6 < 10 || (((x_5 - 1) * x_5) & 1) == 0 )
v3 = 1456142001;
v12 = v3;
}
v6 = v9 - 1023500310;
if ( v9 != 1023500310 )
break;
v2 = -2037067308;
if ( v14 || v13 )
v2 = -1418698808;
v12 = v2;
}
HIDWORD(v5) = v9 - 1456142001;
}
while ( v9 != 1456142001 );
return v15;
}
main:😒_2::operator() const(char)::{lambda(char)#1}::operator()
异或。
__int64 __fastcall main::$_2::operator() const(char)::{lambda(char)#1}::operator()(_BYTE *a1, char a2)
{
return (a2 ^ *a1);
}
也就是说,每相邻两个字符进行加密操作,最后跟enc的字符相比较,得一个可知所有,而我们已经知道第一个字符是 ’ # '就可以写exp了
先整理一下enc数组。
enc[]={0xF3,0x2E,0x18,0x36,0xE1,0x4C,0x22,0xD1,0xF9,0x8C,0x40,0x76,0xF4,0x0E,0x0,0x05,0xA3,0x90,0x0E,0xA5}
EXP
enc=[0xf3,0x2e,0x18,0x36,0xe1,0x4c,0x22,0xd1,0xf9,0x8c,0x40,0x76,0xf4,0xe,0x0,0x5,0xa3,0x90,0xe,0xa5]
flag='#'
for i in range(0,20):
flag+=chr(((enc[i]^((ord(flag[-1])^18)*3+2))-(ord(flag[-1])%7)) &0xff)
print(flag)
flag{mY-CurR1ed_Fns}