BUUCTF 逆向工程(reverse)之[MRCTF2020]Transform

用IDA打开,进入到主函数

// local variable allocation has failed, the output may be wrong!
int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rdx
  __int64 v4; // rdx
  char v6[104]; // [rsp+20h] [rbp-70h]
  int j; // [rsp+88h] [rbp-8h]
  int i; // [rsp+8Ch] [rbp-4h]

  sub_402230(argc, argv, envp);
  sub_40E640(argc, (__int64)argv, v3, (__int64)"Give me your code:\n");
  sub_40E5F0(argc, (__int64)argv, (__int64)v6, (__int64)"%s");
  if ( strlen(*(const char **)&argc) != 33 )
  {
    sub_40E640(argc, (__int64)argv, v4, (__int64)"Wrong!\n");
    system(*(const char **)&argc);
    exit(argc);
  }
  for ( i = 0; i <= 32; ++i )
  {
    byte_414040[i] = v6[dword_40F040[i]];
    v4 = i;
    byte_414040[i] ^= LOBYTE(dword_40F040[i]);
  }
  for ( j = 0; j <= 32; ++j )
  {
    v4 = j;
    if ( byte_40F0E0[j] != byte_414040[j] )
    {
      sub_40E640(argc, (__int64)argv, j, (__int64)"Wrong!\n");
      system(*(const char **)&argc);
      exit(argc);
    }
  }
  sub_40E640(argc, (__int64)argv, v4, (__int64)"Right!Good Job!\n");
  sub_40E640(argc, (__int64)argv, (__int64)v6, (__int64)"Here is your flag: %s\n");
  system(*(const char **)&argc);
  return 0;
}

一、这题让我们输入一个flag。该flag的长度为33

if ( strlen(*(const char **)&argc) != 33 )
  {
    sub_40E640(argc, (__int64)argv, v4, (__int64)"Wrong!\n");
    system(*(const char **)&argc);
    exit(argc);
  }

二、然后再进行异或加密

for ( i = 0; i <= 32; ++i )
  {
    byte_414040[i] = v6[dword_40F040[i]];
    v4 = i;
    byte_414040[i] ^= LOBYTE(dword_40F040[i]);
  }

为了防止看不懂。这里化简一下(其中的v4 = i是多余的):

for ( i = 0; i <= 32; ++i )
	byte_414040[i] = v6[dword_40F040[i]] ^ dword_40F040[i];

另外,byte_414040dword_40F040的信息出题人都给了我们。所以我们要求解的是v6的信息
在这里插入图片描述
所以求解v6的时候可以这样写(此时解出来的v6是乱序的):

for ( i = 0; i <= 32; ++i )
	 v6[dword_40F040[i]] = dword_40F040[i] ^ byte_414040[i];

这里用Python3代码演示一下效果:

dword = [ 9, 0xA, 0xF, 0x17, 7, 0x18, 0xC, 6, 1, 0x10, 3, 0x11, 0x20, 0x1D, 0xB, 0x1E, 0x1B, 0x16, 4, 0xD, 0x13, 0x14, 0x15, 2, 0x19, 5, 0x1F, 8, 0x12, 0x1A, 0x1C, 0xE, 0 ]
byte = [ 0x67, 0x79, 0x7B, 0x7F, 0x75, 0x2B, 0x3C, 0x52, 0x53, 0x79, 0x57,0x5E, 0x5D, 0x42, 0x7B, 0x2D, 0x2A, 0x66, 0x42, 0x7E, 0x4C, 0x57,0x79, 0x41, 0x6B, 0x7E, 0x65, 0x3C, 0x5C, 0x45, 0x6F, 0x62, 0x4D ]
ans = [0]*33

for i in range(0,33):
    ans[i] = dword[i] ^ byte[i]
    print(chr(ans[i]),end="")

在这里插入图片描述
三、最后需要考虑把v6的值变回来

  • 如果你够细心的话,你可以看到dword里保存的值正好是从0 ~ 32(十进制)
  • 并且上面的中间变量ans的乱序和dword是一样的
    打个比方就是,如果ans = [ C, D, B, E, A ]。那dword = [ c, d, b, e, a ]

还原v6的代码为:(这里的v6我用了flag来代替。这里有点难理解,但是思考几次就能想明白了…)

for i in range(0,33):
    flag[dword[i]] = ans[i]

所以最终的Payload为:

dword = [ 9, 0xA, 0xF, 0x17, 7, 0x18, 0xC, 6, 1, 0x10, 3, 0x11, 0x20, 0x1D, 0xB, 0x1E, 0x1B, 0x16, 4, 0xD, 0x13, 0x14, 0x15, 2, 0x19, 5, 0x1F, 8, 0x12, 0x1A, 0x1C, 0xE, 0 ]
byte = [ 0x67, 0x79, 0x7B, 0x7F, 0x75, 0x2B, 0x3C, 0x52, 0x53, 0x79, 0x57,0x5E, 0x5D, 0x42, 0x7B, 0x2D, 0x2A, 0x66, 0x42, 0x7E, 0x4C, 0x57,0x79, 0x41, 0x6B, 0x7E, 0x65, 0x3C, 0x5C, 0x45, 0x6F, 0x62, 0x4D ]
ans = [0]*33    # 需要个中间变量,等下需要用到
flag = [0]*33   # 这里的flag就是题目的v6

for i in range(0,33):           # 异或的解密过程
    ans[i] = dword[i] ^ byte[i]

for i in range(0,33):           # 还原v6的顺序
    flag[dword[i]] = ans[i]

for i in range(0,33):           # 打印flag
    print(chr(flag[i]),end="")

在这里插入图片描述
所以最终答案为:flag{Tr4nsp0sltiON_Clph3r_1s_3z}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值