[HDCTF 2023]enc re题解
一.详细解题步骤
依旧是先查壳,再丢进ida查看,找到这个主函数。

接下来就是耐心查看每一个函数的代码了,比较明显可疑的就是sub_411523,sub_4113DE,ub_4110E1,sub_411302。我们挨个去看:
首先是,sub_411523函数。噢,这个函数里面还有一层,像套娃一样,那就一层一层的拆到底:

这是一个明显的XTEA加密,找全XTEA解密需要的所有数据,而TEA最主要的就是解密需要的数组,key,delta和sum。在主函数中,v7和v8是key,v9是解密需要的数组。在TEA函数中,v4 -= 0x61C88647;能够看出是对0x61C88647取负,作为delta,则根据加密逻辑,这里的sum,就是0xC6EF3720。不知道为什么的可以去学一下TEA加密逻辑,了解一下TEA加密常见的代码特征。

怎么算出sum值的?
由于解密是对加密逆向,已知加密时sum初始值都是0,进行32轮加密,每一轮对sum的处理都是-delta,所以解密时初始sum=-0x61C88647 * 32。
结合两个函数再解释为什么v7.v8为key?
是因为,在主函数中调用sub_411523函数时,将v7,v8作为实参传入,一直到sub_415100函数中,而在sub_415100函数中将a1,a2作为形参,通过a1,a2在XTEA加密函数中的调用特征,判断这两个变量作为key。
最后,可以套用XTEA解密的模板写一个脚本,先解开这个XTEA加密。
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include<iostream>
using namespace std;
void tea(uint32_t *v, uint32_t *k7_8) {
uint32_t v0 = v[0], v1 = v[1], sum = 0xC6EF3720, i;
uint32_t delta = 0x9e3779b9;
for (i = 0; i < 32; i++) {
v1 -= ((v0 << 4) + k7_8[2]) ^ (v0 + sum) ^ ((v0 >> 5) + k7_8[3]);
v0 -= ((v1 << 4) + k7_8[0]) ^ (v1 + sum) ^ ((v1 >> 5) + k7_8[1]);
sum -= delta;
}
v[0] = v0;
v[1] = v1;
}
int main() {
uint32_t enc[2]={0x60FCDEF7,0x236DBEC};
uint32_t key[]={0x12,0x34,0x56,0x78};
tea(enc,key);
cout<<enc[0];
return 0;
}
解密结果是3
我们继续看下一个函数sub_4113DE,这是一个PE文件解析函数。

深入查看一下sub_411221函数
现在我们确定,这个函数目前没有能够和前面联系的加密信息,不影响我们解题,暂且放一下继续解题。
查看下一个函数sub_4110E1,当然查看后你会发现这是一个自定义输入的函数,那我们继续查看下一个函数sub_411302:
有一个坏消息是,这个函数点进去后发现了爆红,那这里第一时间就想到了花指令这个方向。返回到汇编代码,让我们看看这是怎么回事。
追踪到爆红的代码段,发现出现了大量的数据,这是SMC的特征。解决方法就是,将数据转换一下,然后全部分析为代码:shift+F12,写入一个脚本。
for i in range(0x41D000,0x41E600):
patch_byte(i,get_wide_byte(i)^3)

为什么要用脚本先转换数据再分析为代码?
是因为SMC加密后,我们看到的是错误数据,结合sub_4113DE函数中,.hdctf是这个部分解密后的结果,但数据在sub_411221和3异或,所以这里要先改变数据回到原本的样子,再转变为代码。
之后按C快捷键,将转变好的数据全部重新分析为代码

此时F5还是无法查看到反汇编代码,是因为函数还没有被承认,所以需要我们再使用快捷键P重新识别一下函数。

这样F5就能看到反汇编代码了
int __cdecl sub_41D000(char *Str)
{
char v2; // [esp+0h] [ebp-558h]
size_t m; // [esp+190h] [ebp-3C8h]
BOOL v4; // [esp+19Ch] [ebp-3BCh]
signed int k; // [esp+1A8h] [ebp-3B0h]
int v6; // [esp+1B4h] [ebp-3A4h]
int v7; // [esp+1C0h] [ebp-398h]
int i; // [esp+1CCh] [ebp-38Ch]
int j; // [esp+1CCh] [ebp-38Ch]
int v10; // [esp+1CCh] [ebp-38Ch]
char v11; // [esp+1DBh] [ebp-37Dh]
char v12; // [esp+1DBh] [ebp-37Dh]
_BYTE v13[540]; // [esp+1E4h] [ebp-374h]
char v14[24]; // [esp+400h] [ebp-158h] BYREF
signed int v15; // [esp+418h] [ebp-140h]
char v16[264]; // [esp+424h] [ebp-134h] BYREF
char v17[40]; // [esp+52Ch] [ebp-2Ch] BYREF
__CheckForDebuggerJustMyCode(&unk_425036);
v17[0] = 15;
v17[1] = -108;
v17[2] = -82;
v17[3] = -14;
v17[4] = -64;
v17[5] = 87;
v17[6] = -62;
v17[7] = -32;
v17[8] = -102;
v17[9] = 69;
v17[10] = 55;
v17[11] = 80;
v17[12] = -11;
v17[13] = -96;
v17[14] = 94;
v17[15] = -53;
v17[16] = 44;
v17[17] = 22;
v17[18] = 40;
v17[19] = 41;
v17[20] = -2;
v17[21] = -1;
v17[22] = 51;
v17[23] = 70;
v17[24] = 14;
v17[25] = 87;
v17[26] = -126;
v17[27] = 34;
v17[28] = 82;
v17[29] = 38;
v17[30] = 43;
v17[31] = 110;
v17[32] = -28;
v17[33] = -126;
v17[34] = 36;
j_memset(v16, 0, 0x100u);
v15 = j_strlen(Str);
strcpy(v14, "you_are_master");
v13[531] = 0;
v6 = 0;
for ( i = 0; i < 256; ++i )
{
v13[i + 264] = i;
v13[i] = v14[i % j_strlen(v14)];
}
for ( j = 0; j < 256; ++j )
{
v6 = ((unsigned __int8)v13[j] + v6 + (unsigned __int8)v13[j + 264]) % 256;
v11 = v13[j + 264];
v13[j + 264] = v13[v6 + 264];
v13[v6 + 264] = v11;
}
v7 = 0;
v10 = 0;
for ( k = 0; k < v15; ++k )
{
v10 = (v10 + 1) % 256;
v7 = (v7 + (unsigned __int8)v13[v10 + 264]) % 256;
v12 = v13[v10 + 264];
v13[v10 + 264] = v13[v7 + 264];
v13[v7 + 264] = v12;
v16[k] = v13[((unsigned __int8)v13[v7 + 264] + (unsigned __int8)v13[v10 + 264]) % 256 + 264] ^ Str[k];
}
v4 = j_strlen(Str) == 35;
for ( m = 0; m < j_strlen(v17); ++m )
{
if ( v17[m] != v16[m] )
{
v4 = 0;
break;
}
}
if ( v4 )
return sub_41114F("right!!!!", v2);
else
return sub_41114F("please try agin~", v2);
}
很明显这是RC4加密,解RC4需要那个key,而key就是我们前面XTEA解出来的数据。这里的解密脚本来自别的大佬,原文指路:文章 - [HDCTF 2023]enc lingfeng的WriteUp | NSSCTF
#include<stdio.h>
#include<string.h>
void main(){
char Str[]={0xf,0x94,0xae,0xf2,0xc0,0x57,0xc2,0xe0,0x9a,0x45,0x37,0x50,0xf5,0xa0,0x5e,0xcb,0x2c,0x16,0x28,0x29,0xfe,0xff,0x33,0x46,0xe,0x57,0x82,0x22,0x52,0x26,0x2b,0x6e,0xe4,0x82,0x24};
char v2; // [esp+0h] [ebp-558h]
size_t m; // [esp+190h] [ebp-3C8h]
int k; // [esp+1A8h] [ebp-3B0h]
int v6; // [esp+1B4h] [ebp-3A4h]
int v7; // [esp+1C0h] [ebp-398h]
int i; // [esp+1CCh] [ebp-38Ch]
int j; // [esp+1CCh] [ebp-38Ch]
int v10; // [esp+1CCh] [ebp-38Ch]
char v11; // [esp+1DBh] [ebp-37Dh]
char v12; // [esp+1DBh] [ebp-37Dh]
char v13[540]; // [esp+1E4h] [ebp-374h]
char v14[24]; // [esp+400h] [ebp-158h] BYREF
int v15; // [esp+418h] [ebp-140h]
char v16[264]; // [esp+424h] [ebp-134h] BYREF
char v17[40];
strcpy(v14, "you_are_master");
v13[531] = 0;
v6 = 0;
v15 = strlen(Str);
for ( i = 0; i < 256; ++i )
{
v13[i + 264] = i;
v13[i] = v14[i % strlen(v14)];
}
for ( j = 0; j < 256; ++j )
{
v6 = ((unsigned __int8)v13[j] + v6 + (unsigned __int8)v13[j + 264]) % 256;
v11 = v13[j + 264];
v13[j + 264] = v13[v6 + 264];
v13[v6 + 264] = v11;
}
v7 = 0;
v10 = 0;
for ( k = 0; k < v15; ++k )
{
v10 = (v10 + 1) % 256;
v7 = (v7 + (unsigned __int8)v13[v10 + 264]) % 256;
v12 = v13[v10 + 264];
v13[v10 + 264] = v13[v7 + 264];
v13[v7 + 264] = v12;
v16[k] = v13[((unsigned __int8)v13[v7 + 264] + (unsigned __int8)v13[v10 + 264]) % 256 + 264] ^ Str[k];
}
for ( k = 0; k < v15; ++k ){
printf("%C",v16[k]);
}
}
flag就是HDCTF{y0u_ar3_rc4_t3a_smc_m4ster!!}
二.分析代码:
这道题,我选择仔细分析这个PE文件解析函数,因为这是我第一次见到这个函数,一起来学一下。
int __cdecl sub_414B00(int a1, int a2)
{
int result; // eax
int i; // [esp+E8h] [ebp-44h]
char *Str1; // [esp+F4h] [ebp-38h]
__int16 v5; // [esp+118h] [ebp-14h]字节数量
__CheckForDebuggerJustMyCode(&unk_425036);
v5 = *(_WORD *)(*(_DWORD *)(a1 + 60) + a1 + 6);
Str1 = (char *)(a1 + *(_DWORD *)(a1 + 60) + 248);//指向第一个表节
for ( i = 0; ; ++i )
{
result = v5;
if ( i >= v5 )
break;
if ( !j_strcmp(Str1, ".hdctf") )//比较
return sub_411221(*((_DWORD *)Str1 + 3) + a1, *((_DWORD *)Str1 + 4), a2);
//对目标节的处理
Str1 += 40;
}
return result;
}
所以这个函数的作用其实就是在PE文件中查找目标字节,然后对这部分进行一个自定义处理。
当然,这道题中的知识点还包括XTEA和RC4加密原理,和解密逻辑。这部分原先我已经单独学过了,这里放下我简陋的笔记,有需要的师傅们可以通过这个简单了解一下,如果想学明白还是要找一些详细讲解看一看的。
https://www.yuque.com/g/memory-luvcr/whgrxl/hrecgy4gfioy0wll/collaborator/join?token=Wtlgwso4RyN9cjPu&source=doc_collaborator# 《RC4》
https://www.yuque.com/g/memory-luvcr/whgrxl/ulteyg669ogflu2v/collaborator/join?token=WvVgOIICkPyBaqOj&source=doc_collaborator# 《TEA》
OK!这篇结束啦,依旧期待有大佬能够在线指出错误和文章的不足,万分感谢!!!
更多推荐



所有评论(0)