[SUCTF2019]hardcpp

题目:[SUCTF2019]hardcpp

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}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Em0s_Er1t

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值