前置知识
本题主要涉及到了Heaven’s Gate的一种技术,在32位WoW64进程中执行64位代码的过程,以及直接调用64位下win32的API函数
其主要过程便是修改CS的值。将其切换到64位模式,然后使用jmp far来进行远跳转到达64位汇编代码处
CS(代码段选择器)在32位下值为 0x23 ,64位为 0x33
通常情况下一个 0x33 以及 jmp far 是我们判断的主要依据
此处引用一下 Sheng-Hao Ma 大佬的PPT图片来展示其对应的调用过程
以ZwOpenProcess
函数的调用为例:
- a.exe首先调用32位
ntdll.dll
(以下简称ntdll32)中的ZwOpenProcess
函数
- ntdll32调用
wow64cpu.dll
中的X86SwitchTo64BitMode
,顾名思义,调用该函数后进程从32位模式切换到64位模式
- 由
wow64.dll
将32位的系统调用转化为64位
- 调用64位
ntdll.dll
的ZwOpenProcess
函数
- 切换到内核态(Ring0)执行系统调用
学习参考
天堂之门 (Heaven’s Gate) C语言实现-软件逆向-看雪论坛
汇编里看Wow64的原理(浅谈32位程序是怎样在windows 64上运行的?)-软件逆向-看雪论坛
Knockin’ on Heaven’s Gate – Dynamic Processor Mode Switching | RCE.co
逆向分析
我们加载后可以看到main函数处一片的红,无法被ida进行识别
在下面我们可以注意到输入后的一个函数
我们进入分析该函数,可以观察到明显的0x33特征,通过调试分析我们也可以看到对应修改后的数据
修改后有如下jmp far
我们对我们的输入下一个硬件断点,当出现对应的读入或者写的时候便断下来
此时我们进入了第一部分,通过观察汇编我们不难看出来对应功能是每四位一组,加上 operator_data,之后在于其进行异或处理
需要注意的是在下面存在有对operator_data的反调试,当检测到调试时便会得到 operator_data 的值为 0xDEADBEEF,不过影响不是很大,我们可以直接手动解密得到 operator_data 应该为 0x3CA7259D
通过 ds:60 进行访问PEB表,随后[eax+2]拿到调试状态的值
之后我们一步步进行调试,我们可以发现又对输入进行了如下变换
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int __stdcall sub_401200(int a1, int a2) { void *retaddr[2];
if ( byte_40705C ) { *(_DWORD *)(a2 - 3) = __ROL4__(*(_DWORD *)(a2 - 1), 32); *(_DWORD *)(a2 - 6 + 8) = __ROL4__(*(_DWORD *)(a2 - 4 + 8), 32); *(_DWORD *)(a2 - 9 + 16) = __ROL4__(*(_DWORD *)(a2 - 7 + 16), 32); *(_DWORD *)(a2 - 12 + 24) = __ROL4__(*(_DWORD *)(a2 - 10 + 24), 32); } else { *(_DWORD *)(a2 - 3) = __ROL4__(*(_DWORD *)(a2 - 1), 12); *(_DWORD *)(a2 - 6 + 8) = __ROL4__(*(_DWORD *)(a2 - 4 + 8), 34); *(_DWORD *)(a2 - 9 + 16) = __ROL4__(*(_DWORD *)(a2 - 7 + 16), 56); *(_DWORD *)(a2 - 12 + 24) = __ROL4__(*(_DWORD *)(a2 - 10 + 24), 14); } return MK_FP(retaddr[0], retaddr[0])(a1, a2); }
|
之后还经过了如下加密:
最后我们大致可以将主函数修复成如下模样,相对来说会好看一点…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
| int __cdecl main(int argc, const char **argv, const char **envp) { int v3; int v4; char Buf2[44]; int v7; int v8; int v9; int v10; int v11; int v12; int v13; int v14; char v15; int i; int *v17;
sub_401000(); scanf("%99s", input); v3 = decode_0(7u, (int)sub_4011D0); if ( v3 ) v3 = operator_data; operator_data = v3 - 0x21524111; v17 = input; for ( i = 0; i < 8; ++i ) { v17[i] += operator_data; operator_data ^= v17[i]; } MK_FP(*((_WORD *)&byte_40700C + 2), byte_40700C)(input, 0); decode_0(7u, (int)sub_401290); while ( ::i != 33 ) { v4 = ::i - 1; *(_BYTE *)(::i - 1 + 4223072) ^= LOBYTE(dword_407014[(::i - 4) % 4u]); ::i = v4 - 1; } v7 = 0; v8 = 0; v9 = 0; v10 = 0; v11 = 0; v12 = 0; v13 = 0; v14 = 0; v15 = 0; Buf2[0] = -86; Buf2[1] = 79; Buf2[2] = 15; Buf2[3] = -30; Buf2[4] = -28; Buf2[5] = 65; Buf2[6] = -103; Buf2[7] = 84; Buf2[8] = 44; Buf2[9] = 43; Buf2[10] = -124; Buf2[11] = 126; Buf2[12] = -68; Buf2[13] = -113; Buf2[14] = -117; Buf2[15] = 120; Buf2[16] = -45; Buf2[17] = 115; Buf2[18] = -120; Buf2[19] = 94; Buf2[20] = -82; Buf2[21] = 71; Buf2[22] = -123; Buf2[23] = 112; Buf2[24] = 49; Buf2[25] = -77; Buf2[26] = 9; Buf2[27] = -50; Buf2[28] = 19; Buf2[29] = -11; Buf2[30] = 13; Buf2[31] = -54; Buf2[32] = 0; if ( !memcmp(input, Buf2, 0x20u) ) { puts("Right, flag is DASCTF{your input}"); exit(0); } puts("Wrong flag"); return 0; }
|
根据上面的逻辑我们可以写出解密过程:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| def ror(x,n): return ((x>>n) | (x<<(64-n)&0xffffffffffffffff))&0xffffffffffffffff
enc = [0xE20F4FAA, 0x549941E4, 0x7E842B2C, 0x788B8FBC, 0x5E8873D3, 0x708547AE, 0xCE09B331, 0xCA0DF513]
key3 = 0x4A827704 for i in range(8): enc[i] ^= key3
key2 = [0xc,0x22,0x38,0xe] for i in range(0,8,2): tmp=(enc[i+1]<<32 | enc[i]) tmp=ror(tmp,key2[i//2]) enc[i]=tmp&0xffffffff enc[i+1]=tmp>>32
key1 = 0x3CA7259D for i in range(8): tmp=enc[i] enc[i]=(enc[i]-key1+0x100000000)%0x100000000 key1^=tmp
for i in enc: print(int.to_bytes(i,4,'little').decode(),end='')
|
后记
第一次写这种题目,很多地方不是很熟悉,文章必然存在有许多的不足之处,还请师傅们多多指教。