天堂之门

一、天堂之门基础知识

天堂之门(Heaven's Gate) 是一种在32位WoW64进程中执行64位代码以及直接调用64位WIN32 API函数的技术。
天堂之门自带反调试,使IDA不能正常解析
CS段寄存器存放的是段描述符在GDT的索引,CS为0x33在GDT表对应的段描述符为64位,CS为0x23在GDT表对应的段描述符为32位,天堂之门就是通过修改cs段寄存器的值来完成x32与x64之间的切换的
天堂之门64位所用到的api需要我们重写,以达到调用64位函数的目的...
 
 
 
转移指令Mov是不能修改cs段寄存器的,我们可以借助CALL 或 retf来实现cs段的切换
远跳转 CALL FAR(跳转不提权) ,其跳转前后的栈帧图如下:
0
注意,x64跳回的时候要用 _emit 0x48 _emit 0xCB ,即 retfq
 
对此,我们可以编写一个简单的程序来实现天堂之门的切换

二、简单代码实现

//编译器: VC6++
//工具: keystone

// Heaven_s Gate.cpp : Defines the entry point for the console application.
//

#include <stdio.h>
#include <windows.h>
#include <malloc.h>

void Debase64(char* str, int len, char decodeStr[]) {
    char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    char ascill[129];
    int k = 0;
    for (int ii = 0; ii < 64; ii++) {
        ascill[base64[ii]] = k++;
    }
    int decodeStrlen = len / 4 * 3 + 1;
    k = 0;
    for (int i = 0; i < len; i++) {
        decodeStr[k++] = (ascill[str[i]] << 2) | (ascill[str[++i]] >> 4);
        if (str[i + 1] == '=') {
            break;
        }
        decodeStr[k++] = (ascill[str[i]] << 4) | (ascill[str[++i]] >> 2);
        if (str[i + 1] == '=') {
            break;
        }
        decodeStr[k++] = (ascill[str[i]] << 6) | (ascill[str[++i]]);
    }
    decodeStr[k] = '\0';
}

int main(int argc, char* argv[])
{
    char ttt[] = "sGVsbG8gV29lbGQ=";
    char flag[256] = { 0 };
    printf("进入x64\n");
    _asm {

        //push 0x33  //x64 对应的cs段寄存器//
        //push switchX32ToX64
        //retf     //远跳返回

        _emit 0x6A
        _emit 0x33
        _emit 0x68
            _emit 0x7b
            _emit 0x13
            _emit 0x40
            _emit 0x00
        _emit 0xCB
    }

    ttt[0] = 't';
switchX32ToX64:
    ttt[0] = 'S';
    __asm {                //在x64位下执行这一句的话,需要使用硬编码// 我们使用keystne获取//68 1C 20 42// 
        _emit 0x6A
        _emit 0x23
        __emit 0x68
        _emit 0x88
        _emit 0x13
        _emit 0x40
        _emit 0x00                
    
        _emit 0x48
        _emit 0xCB            //retfq中的q表示qword,即返回到64位的地址 x64dbg翻译为 RET FAR
    }

switchX64ToX32:

    printf("切换为32位\n");
    Debase64(ttt, strlen(ttt), flag);
    printf("%s\n", flag);
    getchar();
    return 0;
}
我们利用天堂之门反调试的特性在切换为64位后修改密文,使其能够在之后的32位中解密为 Hello Woeld,IDA打开如下:
可以看到,在伪代码层,密文的修改工作被隐藏的很好
0
0
 

三、CTF实战

在ctf中,天堂之门的使用往往伴随着大量的异常、混淆、反调试,使程序很难通过IDA分析,我们一般可以借助dump的方法,使64位代码在64位IDA中显示出来,或使用windbg硬刚汇编,逆向神器Ghidra 可能也是一种不错的选择,比较困难的题有KCTF 2022 危机四伏
 

CTF Show 月饼杯2 EasyTea

 
这道题目就是利用了天堂之门技术,在32位程序下跑64位魔改xtea加密算法,不过没有异常和其他的混淆,并且提示了tea加密,题目还算简单
 
程序中两处远跳形成了32位到64位的切换
0
我使用IDApython脚本把64位函数dump出来放到了64位IDA里
import idc

data = [
0x48,0x89,0x4c,0x24,0x8,0x55,0x57,0x48,0x81,0xec,0xa8,0x1,0x0,0x0,0x48,0x8d,
0x6c,0x24,0x20,0x48,0x8b,0xfc,0xb9,0x6a,0x0,0x0,0x0,0xb8,0xcc,0xcc,0xcc,0xcc,
0xf3,0xab,0x48,0x8b,0x8c,0x24,0xc8,0x1,0x0,0x0,0x90,0x90,0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90,0x90,0x90,0xc7,0x45,0x8,0x66,0x0,0x0,0x0,0xc7,0x45,0xc,
0x6c,0x0,0x0,0x0,0xc7,0x45,0x10,0x61,0x0,0x0,0x0,0xc7,0x45,0x14,0x67,0x0,
0x0,0x0,0xc7,0x45,0x18,0x69,0x0,0x0,0x0,0xc7,0x45,0x1c,0x73,0x0,0x0,0x0,
0xc7,0x45,0x20,0x6d,0x0,0x0,0x0,0xc7,0x45,0x24,0x65,0x0,0x0,0x0,0xb8,0x4,
0x0,0x0,0x0,0x48,0x6b,0xc0,0x7,0x48,0x8b,0x8d,0xa0,0x1,0x0,0x0,0x8b,0x4,
0x1,0x89,0x45,0x44,0xc7,0x45,0x64,0x0,0x0,0x0,0x0,0xc7,0x85,0x84,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0xeb,0xe,0x8b,0x85,0x84,0x0,0x0,0x0,0xff,0xc0,0x89,
0x85,0x84,0x0,0x0,0x0,0x83,0xbd,0x84,0x0,0x0,0x0,0x20,0xf,0x8d,0x44,0x1,
0x0,0x0,0x8b,0x45,0x64,0x5,0x45,0x11,0x48,0x88,0x89,0x45,0x64,0xc7,0x85,0xa4,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xeb,0xe,0x8b,0x85,0xa4,0x0,0x0,0x0,0xff,
0xc0,0x89,0x85,0xa4,0x0,0x0,0x0,0x83,0xbd,0xa4,0x0,0x0,0x0,0x7,0xf,0x8d,
0x8a,0x0,0x0,0x0,0x48,0x63,0x85,0xa4,0x0,0x0,0x0,0x8b,0x8d,0xa4,0x0,0x0,
0x0,0xff,0xc1,0x48,0x63,0xc9,0x48,0x8b,0x95,0xa0,0x1,0x0,0x0,0x8b,0xc,0x8a,
0xc1,0xe1,0x4,0x8b,0x95,0xa4,0x0,0x0,0x0,0xff,0xc2,0x48,0x63,0xd2,0x4c,0x8b,
0x85,0xa0,0x1,0x0,0x0,0x41,0x8b,0x14,0x90,0xc1,0xfa,0x5,0x33,0xca,0x8b,0x95,
0xa4,0x0,0x0,0x0,0xff,0xc2,0x48,0x63,0xd2,0x4c,0x8b,0x85,0xa0,0x1,0x0,0x0,
0x41,0x3,0xc,0x90,0x8b,0x55,0x64,0x83,0xe2,0x7,0x8b,0xd2,0x8b,0x54,0x95,0x8,
0x44,0x8b,0x45,0x64,0x44,0x3,0xc2,0x41,0x8b,0xd0,0x33,0xca,0x48,0x8b,0x95,0xa0,
0x1,0x0,0x0,0x3,0xc,0x82,0x8b,0xc1,0x48,0x63,0x8d,0xa4,0x0,0x0,0x0,0x48,
0x8b,0x95,0xa0,0x1,0x0,0x0,0x89,0x4,0x8a,0xe9,0x5b,0xff,0xff,0xff,0xb8,0x4,
0x0,0x0,0x0,0x48,0x6b,0xc0,0x7,0xb9,0x4,0x0,0x0,0x0,0x48,0x6b,0xc9,0x0,
0x48,0x8b,0x95,0xa0,0x1,0x0,0x0,0x8b,0xc,0xa,0xc1,0xe1,0x4,0xba,0x4,0x0,
0x0,0x0,0x48,0x6b,0xd2,0x0,0x4c,0x8b,0x85,0xa0,0x1,0x0,0x0,0x41,0x8b,0x14,
0x10,0xc1,0xfa,0x5,0x33,0xca,0xba,0x4,0x0,0x0,0x0,0x48,0x6b,0xd2,0x0,0x4c,
0x8b,0x85,0xa0,0x1,0x0,0x0,0x41,0x3,0xc,0x10,0x8b,0x55,0x64,0x83,0xe2,0x7,
0x8b,0xd2,0x8b,0x54,0x95,0x8,0x44,0x8b,0x45,0x64,0x44,0x3,0xc2,0x41,0x8b,0xd0,
0x33,0xca,0x48,0x8b,0x95,0xa0,0x1,0x0,0x0,0x3,0xc,0x2,0x8b,0xc1,0xb9,0x4,
0x0,0x0,0x0,0x48,0x6b,0xc9,0x7,0x48,0x8b,0x95,0xa0,0x1,0x0,0x0,0x89,0x4,
0xa,0xe9,0xa1,0xfe,0xff,0xff,0x48,0x8d,0x4d,0xe0,0x90,0x90,0x90,0x90,0x90,0x90,
0x90,0x90,0x90,0x90,0x90,0x90,0x48,0x8d,0xa5,0x88,0x1,0x0,0x0,0x5f,0x5d ,0xc3

]
begin = 0x0007FF6E6A71F50
end = 0x0007FF6E6A71F50 + 0x0427C5F - 0x0427A50
for addr in range(begin,end):
    idc.patch_byte(addr,data[addr-begin])



begin = 0x0007FF6E6A71F50
end = 0x0007FF6E6A71F50 + 0x0427C5F - 0x0427A50
for i in range(begin,end):
    idc.create_insn(i)
解密流程十分清晰
0
解密脚本:
#include <stdio.h>
int map[8]={
0xB5ABA743, 0x4C5B3EE0, 0xB70AEB14, 0x6946BC13, 0x906089C4, 0x5B9F98F0, 0x0964B652, 0x78920976
};
void DeTea(int* v) {
    int sum=0;
    for(int i=0;i<32;i++)
    sum+=0x88481145;
    int key[] = { 0x66, 0x6c, 0x61, 0x67, 0x69, 0x73, 0x6d, 0x65 };
    unsigned int tmp = v[7];
    for (int j = 0; j < 32; j++) {
        v[7] -= (((v[0] << 4) ^ (v[0] >> 5)) + v[0]) ^ (sum + key[sum &7]);
        for (int i = 6; i >-1; i--) {
            v[i] -= (((v[i + 1] << 4) ^ (v[i + 1] >> 5)) + v[i + 1]) ^ (sum + key[sum & 7]);
        }
        
        sum -= 0x88481145;
    }    

}

int main(){

    DeTea(map);
    for(int i = 0;i<=7;i++){
        printf("%x\n",map[i]);
    } 
    return 0;
}

//5f616554
//34333231
//32315f35
//5f353433
//5f736579
//67616c66
//5f73695f
//79736165

 

 

posted @ 2022-07-21 12:45  TLSN  阅读(401)  评论(0编辑  收藏  举报