收获

  • UPX 壳存在特征码,特征码被修改会导致 UPX 脱壳失败

(2023年6月10日)【安洵杯 2023】ezr3


思路

用 IDA 打开,发现不对劲:

安洵杯2023-ez_ezr3 1.png

函数很少,而且 start() 函数中参数爆红,应该是有壳

用 DIE 打开:(exeinfo pe 无法检测)

安洵杯2023-ez_ezr3 2.png

发现 UPX 壳,但是 UPX 脱壳失败,提示没有 UPX 壳:

安洵杯2023-ez_ezr3 3.png

用 010Editor 打开:

安洵杯2023-ez_ezr3 4.png

发现 UPX 的特征码被改为 HCK,并且还有 Android 字样,根据架构 AARCH64 这应该是一个 Android 程序

在 IDA 中同样可以看到:

安洵杯2023-ez_ezr3 5.png

在 010Editor 中将 HCK 全部替换为 UPX,并保存文件:

安洵杯2023-ez_ezr3 6.png

不过由于是 UPX 4.02,我的版本不够,更新后脱壳成功:
UPX v4.0.2 下载地址:Release v4.0.2 · upx/upx (github.com)

安洵杯2023-ez_ezr3 7.png

安洵杯2023-ez_ezr3 8.png

再次用 IDA 打开,恢复正常:

安洵杯2023-ez_ezr3 9.png

定位到主函数:

安洵杯2023-ez_ezr3 10.png

一开始会先运行 v() 函数:

安洵杯2023-ez_ezr3 11.png

有一些异或操作,不过逻辑看不大懂,只能看个大概

int8x16_t 是一个数据类型,通常用于表示包含 16 个 8 位整数的向量。它是一种矢量类型,可以在特定的硬件架构(如 SIMD 指令集)中进行并行计算,以提高程序的性能
这里的 v3 做什么用的暂时不清楚,不过可以看到代码 v4 = &auth + v1auth 做了处理

跟进 auth

安洵杯2023-ez_ezr3 13.png

按照形式,使用 IDA 提取 auth

auth = [0x0003BC69, 0x000D3FA0, 0x0003A94A, 0x00044AFF, 0x00045254, 0x0000CDD1, 0x00001815, 0x00003B08, 0x00070868,
        0x000C6560, 0x00065662, 0x000855C8, 0x0000DCF6, 0x00004CE6, 0x0014EEC2, 0x0002CFD6, 0x00032766, 0x0014F6BA,
        0x00025E69, 0x0006A9A3, 0x00121EBD, 0x0005991C, 0x00050016, 0x00004A3D, 0x00097485, 0x0008D0A0, 0x0003B916,
        0x00054C58, 0x00096F94, 0x00010334, 0x000DAD22, 0x0004B234, 0x0002FE96, 0x000F33CC, 0x0012C1E8, 0x00148F9E]

主要经过的处理:

v1 = 0LL;
v2 = &off_B6D0;
do
{
  v4 = &auth + v1;
  v1 += 24LL;

  v6 = *(v4 + 4) ^ v2[12];
  v7 = *(v4 + 5) ^ v2[24];
  
  v2 += 2;
  
  *(v4 + 4) = v6;
  *(v4 + 5) = v7;
}
while ( v1 != 144 );

根据 v1 可知总共循环了 6 次,对应的逆向脚本:

v2 = 0
for i in range(0, len(auth), 6):
    for j in range(6):
        auth[i + j] ^= mere[v2 + j * 12]
    v2 += 2

其中 mere 的数据如下:

mere = [0x00000D21, 0x00000000, 0x0000009D, 0x00000000, 0x0000094B, 0x00000000, 0x000003C9, 0x00000000, 0x00000C3F,
        0x00000000, 0x000017E9, 0x00000000, 0x0000130E, 0x00000000, 0x00000088, 0x00000000, 0x00000486, 0x00000000,
        0x0000202F, 0x00000000, 0x00002230, 0x00000000, 0x000024B4, 0x00000000, 0x000008B1, 0x00000000, 0x00000A9F,
        0x00000000, 0x00001AD2, 0x00000000, 0x000023EB, 0x00000000, 0x00000C7E, 0x00000000, 0x0000042B, 0x00000000,
        0x000005BF, 0x00000000, 0x0000113C, 0x00000000, 0x00000449, 0x00000000, 0x00001751, 0x00000000, 0x00000ACE,
        0x00000000, 0x00001894, 0x00000000, 0x0000208A, 0x00000000, 0x00000E82, 0x00000000, 0x000006BD, 0x00000000,
        0x00000CEE, 0x00000000, 0x00002386, 0x00000000, 0x000013D4, 0x00000000, 0x00000111, 0x00000000, 0x00000D1C,
        0x00000000, 0x0000238E, 0x00000000, 0x00001759, 0x00000000, 0x0000012B, 0x00000000, 0x0000214D, 0x00000000,
        0x00000040]

发现后面还有一个 p() 函数:

安洵杯2023-ez_ezr3 12.png

进行了一次对数据前四位和后四位的转换,然后进行异或,最后进行验证

写出逆向脚本:

v2 = 0
for i in range(0, len(auth), 6):
    for j in range(6):
        flag.append(auth[i + j] // mere[(v2 + j * 6) * 2])
    v2 += 1

for i in range(len(flag)):
    flag[len(flag) - 1 - i] ^= flag[i]
    flag[len(flag) - 1 - i] = (flag[len(flag) - 1 - i] >> 4 | flag[len(flag) - 1- i] << 4) & 0xff

脚本

auth = [0x0003BC69, 0x000D3FA0, 0x0003A94A, 0x00044AFF, 0x00045254, 0x0000CDD1, 0x00001815, 0x00003B08, 0x00070868,
        0x000C6560, 0x00065662, 0x000855C8, 0x0000DCF6, 0x00004CE6, 0x0014EEC2, 0x0002CFD6, 0x00032766, 0x0014F6BA,
        0x00025E69, 0x0006A9A3, 0x00121EBD, 0x0005991C, 0x00050016, 0x00004A3D, 0x00097485, 0x0008D0A0, 0x0003B916,
        0x00054C58, 0x00096F94, 0x00010334, 0x000DAD22, 0x0004B234, 0x0002FE96, 0x000F33CC, 0x0012C1E8, 0x00148F9E]

mere = [0x00000D21, 0x00000000, 0x0000009D, 0x00000000, 0x0000094B, 0x00000000, 0x000003C9, 0x00000000, 0x00000C3F,
        0x00000000, 0x000017E9, 0x00000000, 0x0000130E, 0x00000000, 0x00000088, 0x00000000, 0x00000486, 0x00000000,
        0x0000202F, 0x00000000, 0x00002230, 0x00000000, 0x000024B4, 0x00000000, 0x000008B1, 0x00000000, 0x00000A9F,
        0x00000000, 0x00001AD2, 0x00000000, 0x000023EB, 0x00000000, 0x00000C7E, 0x00000000, 0x0000042B, 0x00000000,
        0x000005BF, 0x00000000, 0x0000113C, 0x00000000, 0x00000449, 0x00000000, 0x00001751, 0x00000000, 0x00000ACE,
        0x00000000, 0x00001894, 0x00000000, 0x0000208A, 0x00000000, 0x00000E82, 0x00000000, 0x000006BD, 0x00000000,
        0x00000CEE, 0x00000000, 0x00002386, 0x00000000, 0x000013D4, 0x00000000, 0x00000111, 0x00000000, 0x00000D1C,
        0x00000000, 0x0000238E, 0x00000000, 0x00001759, 0x00000000, 0x0000012B, 0x00000000, 0x0000214D, 0x00000000,
        0x00000040]


v2 = 0
flag = []
for i in range(0, len(auth), 6):
    for j in range(6):
        auth[i + j] ^= mere[v2 + j * 12]
    v2 += 2


v2 = 0
for i in range(0, len(auth), 6):
    for j in range(6):
        flag.append(auth[i + j] // mere[(v2 + j * 6) * 2])
    v2 += 1

for i in range(len(flag)):
    flag[len(flag) - 1 - i] ^= flag[i]
    flag[len(flag) - 1 - i] = (flag[len(flag) - 1 - i] >> 4 | flag[len(flag) - 1 - i] << 4) & 0xff

print(bytes(flag))

结果

SYC{1_w4Nn4_buy_4_c4R_G1V3_M3_50w_$}

安洵杯2023-ez_ezr3 14.png