[De1CTF2019]Re_Sign

此题的关键在于动调,使我一个只会 F5 的菜鸡受益匪浅

加了 UPX 壳,工具没脱下来,手动脱了后运行不了(悲),看了 wp 说是要用 UpxUnpacker,亲测有效

先查看字符串,看到一个 Success,进去瞧一眼

整不明白,动调试试,首先是函数最开始的 lp 其实就是我们输入,这里我输入了 10 个 1

接下来一直往下走,到 Success 判断的部分,可以看到传入的 v7 是一个疑似 base64 的东西

接下来就需要更严谨地验证一下这个猜想,进入到 sub_401233 中,函数很长,但有一部分很可疑

长这样的语句一般与 base64 码表的生成有关,通过动调看一下

OD 定位到此处,运行几次循环,可以看到正在生成的码表

跳出循环就可以看到生成的新码表了

然后验证一下,与之前得到的数据一致,证明新表就是它

接下来就看到 Success 前的验证函数 sub_401F0A,先看到函数返回的部分

虽然不知道 v34 是个啥,但总之 v6 不能为 0,所以看到前面一个 if 判断,需要这个 if 满足才可以,以及在这个 if 内还有一个会 break 的看起来很可疑的比较

sub_4034D0 进去完全看不懂在干啥,动调看一下返回值,连续试了几个后发现返回的是输入内容加密后(3 变 4)的字符串长度,需要满足长度为 48 也就是说输入长度要在 34~36 之间

接下来继续看 sub_402160

传入的是正经 base64 表和加密后的输入,查看 sub_403500

还是看不懂,继续动调几次发现

  • 当输入为 35 个 1 时,base64 变表加密后第一个字符为 E,函数返回值为 5
  • 当输入为 35 个 a 时,base64 变表加密后第一个字符为 G,函数返回值为 7
  • 当输入为 35 个 b 时,base64 变表加密后第一个字符为 G,函数返回值为 7

即返回的是加密后的每个字符在正经 base64 表中的下标(从 1 开始)

然后看到与之作比较的数组

取出来 48 个写脚本得到变表加密后的密文

#include <bits/stdc++.h>
using namespace std;
int a[50] = {0x08, 0x3B, 0x01, 0x20, 0x07, 0x34, 0x09, 0x1F, 0x18, 0x24, 0x13, 
             0x03, 0x10, 0x38, 0x09, 0x1B, 0x08, 0x34, 0x13, 0x02, 0x08, 0x22,
	     0x12, 0x03, 0x05, 0x06, 0x12, 0x03, 0x0F, 0x22, 0x12, 0x17, 0x08,
	     0x01, 0x29, 0x22, 0x06, 0x24, 0x32, 0x24, 0x0F, 0x1F, 0x2B, 0x24,
	     0x03, 0x15, 0x41, 0x41};
string s = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
int main() {
  for (int i = 0; i < 48; i++) {
    int num = int(a[i]);
    cout << s[num - 1];
  }
  return 0;
}

得到:"H6AfGzIeXjSCP3IaHzSBHhRCEFRCOhRWHAohFjxjOeqjCU",解密即可

flag{E_L4nguag3_1s_K3KeK3_N4Ji4}

posted @ 2022-07-01 19:48  Moominn  阅读(279)  评论(0编辑  收藏  举报