freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

HITCON2022--ctf驱动逆向题
极安御信安全研究院 2022-12-28 15:54:36 200154
所属地 辽宁省

HITCON CTF 2022 Writeup-checker

挺有意思的一道题,这里的关键函数是使用的动态生成执行操作,按照特定参数序列进行解密才能正常执行,否则一定会报错异常

checker

一共给了两个文件:checker.exe和checker_drv.sys

是一道驱动逆向的题,查壳,无壳,有签名的Windows 10 x64驱动

先看用户程序checker.exe:

逻辑很简单,就是打开符号链接发送IRP请求,控制码是0x222080,没有输入参数,接收1个字节的输出

接下来看驱动程序checker_drv.sys:

DriverEntry里面就这么一个函数,进来后,可以看到,先是创建驱动对象和符号链接,然后填充IRP处理函数

接下来往全局变量里填充了映射的内存地址,

•qword_140013170:里的是dword_140003000函数地址

•addr_140003030_qword:里的是dword_140003000+48数组地址

•qword_140013188:里的是sub_140001430函数地址

•qword_140013180:里的是sub_140001B30函数地址

最后就是一系列异或操作:

对qword_140013180里头的前16字节异或了两轮,使用的是qword_140013188里的前32字节的内容

qword_140013180地址的内容:

qword_140013188地址的内容:

可以看到这两个地址都是函数,这里用一个函数去异或另一个函数emmm

这大概是某种保护手段,阻碍静态分析,真正的函数是运行中动态生成的(实测,异或这两轮的结果并不是可执行的代码)

之前用户程序里看到,传入给驱动了一个控制码,这里到驱动里去看看这个控制码的作用:

除了这个控制码,上面还有8个控制码,等会再看

当用户传入0x222080的时候,驱动进入这个分支,如果数组byte_140013190里的8个值均为1,则会跳转到LABEL_21,很显然,这里验证的内容是dword_140003000的开头是否是hitcon,这说明这里会出现flag

byte_140013190的值是在哪里改变的呢?往上看:

上面的其他8个控制码分支,分别修改该数组的每一位为1,同时也会执行一个相同的处理函数(参数不同)

随便点进去一个看看:

首先是进行了对刚刚那个函数的又一轮异或操作,异或的值取决于函数的参数

然后对qword_140013170地址,也就是dword_140003000数组里的值进行修改,一共修改48个字节,修改方式是调用sub_140001B30函数(被异或了好几轮的那个)

最后再次异或一轮

整理一下思路:

•flag的生成,是在函数中通过调用一个奇怪的东西sub_140001B30生成出来的

•flag是否完成生产的判定是,是否走完了其他8个控制码的处理分支

那么是不是只需要依次把这8个函数都调用一遍,生成出来的内容就是flag了呢?经测试,根本执行不了,直接报错地址异常,应该是函数异或出来的东西就不是可执行的内容,在Windows 10 x64虚拟机上安装驱动实测则会蓝屏崩溃

这里我卡住了,感觉很接近了,但就是总差一点

休息了一下突然意识到,有没有可能是这8次函数调用的顺序问题?如果程序一定能执行成功的话,就一定能一个一个把8个函数执行出结果

于是经过一番倒腾测试,发现执行一个函数,只有最后一个函数能执行下去,能行,一定是顺序问题,经过又一番测试,得到最终测试顺序,

flag生成:

#include

#include

#define _BYTE BYTE

// qword_140013180 = sub_140001B30

unsigned char* pFunc;

DWORD oldprotect;

typedef BYTE(_cdecl* g_pFunc)(BYTE a);

g_pFunc sub_140001B30;

unsigned char* qword_140013180;

// qword_140013170 = dword_140003000

unsigned char qword_140013170[304] = {

0x63, 0x60, 0xA5, 0xB9, 0xFF, 0xFC, 0x30, 0x0A, 0x48, 0xBB, 0xFE, 0xFE, 0x32, 0x2C, 0x0A, 0xD6,

0xE6, 0xFE, 0xFE, 0x32, 0x2C, 0x0A, 0xD6, 0xBB, 0x4A, 0x4A, 0x32, 0x2C, 0xFC, 0xFF, 0x0A, 0xFD,

0xBB, 0xFE, 0x2C, 0xB9, 0x63, 0xD6, 0xB9, 0x62, 0xD6, 0x0A, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00,

0x19, 0xBC, 0x8F, 0x82, 0xD0, 0x2C, 0x61, 0x34, 0xC0, 0x9F, 0xF6, 0x50, 0xD5, 0xFB, 0x0C, 0x6E,

0xD0, 0xEB, 0xE5, 0xE3, 0xCE, 0xB5, 0x4C, 0xCA, 0x45, 0xAA, 0x11, 0xB2, 0x3E, 0x62, 0x6F, 0x7D,

0xD0, 0xEB, 0xA9, 0xE3, 0xB2, 0x2F, 0x06, 0x47, 0x7C, 0x28, 0xC5, 0xDE, 0xDE, 0x1A, 0x4E, 0xD6,

0xD8, 0x2D, 0x93, 0x4F, 0x82, 0x65, 0x64, 0xFD, 0x08, 0x62, 0x4B, 0x87, 0x7E, 0x52, 0x47, 0x30,

0xB7, 0xBA, 0xD0, 0x39, 0x68, 0x53, 0x50, 0xAB, 0x20, 0xD5, 0xCA, 0x84, 0x26, 0x71, 0x6F, 0x91,

0x1B, 0x36, 0x46, 0x11, 0xA5, 0xF1, 0x4E, 0x58, 0x6C, 0x74, 0xD4, 0x9C, 0x15, 0xE2, 0x28, 0xD5,

0xD9, 0x0F, 0x3D, 0x83, 0xF3, 0xFC, 0xD1, 0x13, 0x1A, 0x62, 0x12, 0x40, 0xAA, 0xEA, 0xCD, 0xCB,

0xE1, 0xC6, 0x08, 0x81, 0x98, 0xF6, 0x68, 0x88, 0xBE, 0x23, 0xB5, 0x9E, 0x55, 0xB9, 0xE2, 0x7D,

0x5A, 0xDA, 0x39, 0x07, 0xF0, 0x2E, 0x32, 0x20, 0x59, 0x56, 0x4C, 0xB4, 0x8F, 0x3E, 0x07, 0x61,

0xD9, 0x0F, 0x2D, 0x61, 0xF1, 0x91, 0x33, 0x14, 0xCB, 0x49, 0x68, 0xFE, 0x1F, 0xD4, 0x8A, 0xFE,

0xE1, 0xC6, 0x18, 0x63, 0x9A, 0x9B, 0x8A, 0x8A, 0x7F, 0x08, 0xC3, 0xE8, 0xE1, 0xEC, 0x0B, 0x8F,

0x3B, 0x00, 0x94, 0xA5, 0x11, 0xE7, 0x47, 0x66, 0xC4, 0x9F, 0x98, 0x18, 0x70, 0xF0, 0x30, 0xF6,

0x94, 0x71, 0xB1, 0x95, 0xD1, 0xF0, 0x6F, 0xB7, 0xD9, 0x3D, 0x05, 0x9E, 0xC1, 0x53, 0x33, 0x76,

0x9B, 0x4B, 0x69, 0xCA, 0xDE, 0xFD, 0x7D, 0x67, 0xB8, 0x29, 0x2B, 0xC7, 0xC5, 0x84, 0x2C, 0xD1,

0x87, 0x87, 0xF1, 0x98, 0x97, 0x74, 0xAD, 0x4B, 0x32, 0xF0, 0x4A, 0x51, 0x72, 0xEA, 0x09, 0xF7,

0x38, 0xFD, 0x27, 0xBD, 0x1C, 0x52, 0x71, 0x43, 0x95, 0x9C, 0x1A, 0x86, 0xF2, 0xC0, 0xF9, 0xF8

};

// addr_140003030_qword = dword_140003030

unsigned char* qword_140003030 = qword_140013170 + 48;

// qword_140013188 = sub_140001430

void init() {

unsigned char sub_140001B30_init[20] = {

0x80, 0xE9, 0x22, 0x80, 0xF1, 0xAD, 0x0F, 0xB6, 0xC1, 0x6B, 0xC8, 0x11, 0xB8, 0x9E, 0x00, 0x00,

0x00, 0x2A, 0xC1, 0xC3

};

unsigned char sub_140001430[88] = {

0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, 0x05, 0x3B, 0x0C, 0x00, 0x00, 0x48, 0x8B, 0xDA,

0x48, 0x8B, 0x4A, 0x10, 0x48, 0x39, 0x08, 0x75, 0x37, 0x48, 0x8B, 0x4A, 0x08, 0xFF, 0x15, 0x1D,

0x0C, 0x00, 0x00, 0x48, 0x8D, 0x0D, 0x16, 0x1D, 0x00, 0x00, 0x80, 0x3C, 0x08, 0x00, 0x74, 0x20,

0x8B, 0x03, 0x83, 0xF8, 0x01, 0x74, 0x05, 0x83, 0xF8, 0x02, 0x75, 0x14, 0x48, 0x8B, 0x4B, 0x20,

0x8B, 0x41, 0x04, 0x83, 0xE0, 0x01, 0x84, 0xC0, 0x74, 0x06, 0xC7, 0x01, 0x00, 0x00, 0x00, 0x00,

0x33, 0xC0, 0x48, 0x83, 0xC4, 0x20, 0x5B, 0xC3

};

pFunc = (unsigned char*)malloc(20);

VirtualProtect((LPVOID)pFunc, 20, PAGE_EXECUTE_READWRITE, &oldprotect);

memcpy(pFunc, sub_140001B30_init, 20);

sub_140001B30 = (g_pFunc)pFunc;

qword_140013180 = pFunc;

for (int i = 0, j = 0; i < 32; i++,j++)

{

if (j == 16)j = 0;

pFunc[j] ^= sub_140001430[i];

}

}

void __fastcall sub_1400014D0(unsigned int a1)

{

__int64 v1; // rdi

char* v3; // rbx

unsigned char * v4; // rbx

unsigned char * v5; // rbx

unsigned char * v6; // rbx

unsigned char * v7; // rbx

unsigned char * v8; // rbx

unsigned char * v9; // rbx

unsigned char * v10; // rbx

unsigned char * v11; // rbx

unsigned char * v12; // rbx

unsigned char * v13; // rbx

unsigned char * v14; // rbx

unsigned char * v15; // rbx

unsigned char * v16; // rbx

unsigned char * v17; // rbx

unsigned char * v18; // rbx

unsigned char * v19; // rbx

unsigned char * v20; // rbx

unsigned char * v21; // rbx

unsigned char * v22; // rbx

unsigned char * v23; // rbx

unsigned char * v24; // rbx

unsigned char * v25; // rbx

unsigned char * v26; // rbx

unsigned char * v27; // rbx

unsigned char * v28; // rbx

unsigned char * v29; // rbx

unsigned char * v30; // rbx

unsigned char * v31; // rbx

unsigned char * v32; // rbx

unsigned char * v33; // rbx

unsigned char * v34; // rbx

unsigned char * v35; // rbx

unsigned char * v36; // rbx

unsigned char * v37; // rbx

unsigned char * v38; // rbx

unsigned char * v39; // rbx

unsigned char * v40; // rbx

unsigned char * v41; // rbx

unsigned char * v42; // rbx

unsigned char * v43; // rbx

unsigned char * v44; // rbx

unsigned char * v45; // rbx

v1 = a1;

*(_BYTE*)qword_140013180 ^= *(_BYTE*)(v1 + qword_140003030);// 修改这16个值,dword_140003000+48

*(_BYTE*)(qword_140013180 + 1) ^= *(_BYTE*)((unsigned int)(v1 + 1) + qword_140003030);

*(_BYTE*)(qword_140013180 + 2) ^= *(_BYTE*)((unsigned int)(v1 + 2) + qword_140003030);

*(_BYTE*)(qword_140013180 + 3) ^= *(_BYTE*)((unsigned int)(v1 + 3) + qword_140003030);

*(_BYTE*)(qword_140013180 + 4) ^= *(_BYTE*)((unsigned int)(v1 + 4) + qword_140003030);

*(_BYTE*)(qword_140013180 + 5) ^= *(_BYTE*)((unsigned int)(v1 + 5) + qword_140003030);

*(_BYTE*)(qword_140013180 + 6) ^= *(_BYTE*)((unsigned int)(v1 + 6) + qword_140003030);

*(_BYTE*)(qword_140013180 + 7) ^= *(_BYTE*)((unsigned int)(v1 + 7) + qword_140003030);

*(_BYTE*)(qword_140013180 + 8) ^= *(_BYTE*)((unsigned int)(v1 + 8) + qword_140003030);

*(_BYTE*)(qword_140013180 + 9) ^= *(_BYTE*)((unsigned int)(v1 + 9) + qword_140003030);

*(_BYTE*)(qword_140013180 + 10) ^= *(_BYTE*)((unsigned int)(v1 + 10) + qword_140003030);

*(_BYTE*)(qword_140013180 + 11) ^= *(_BYTE*)((unsigned int)(v1 + 11) + qword_140003030);

*(_BYTE*)(qword_140013180 + 12) ^= *(_BYTE*)((unsigned int)(v1 + 12) + qword_140003030);

*(_BYTE*)(qword_140013180 + 13) ^= *(_BYTE*)((unsigned int)(v1 + 13) + qword_140003030);

*(_BYTE*)(qword_140013180 + 14) ^= *(_BYTE*)((unsigned int)(v1 + 14) + qword_140003030);

*(_BYTE*)(qword_140013180 + 15) ^= *(_BYTE*)((unsigned int)(v1 + 15) + qword_140003030);

v3 = (char*)qword_140013170;                 // 修改这43字节,通过函数1B30(1B30是被篡改过的函数)

*v3 = sub_140001B30(*(_BYTE*)qword_140013170);

v4 = qword_140013170;

*(_BYTE*)(v4 + 1) = sub_140001B30(*(_BYTE*)(qword_140013170 + 1));

v5 = qword_140013170;

*(_BYTE*)(v5 + 2) = sub_140001B30(*(_BYTE*)(qword_140013170 + 2));

v6 = qword_140013170;

*(_BYTE*)(v6 + 3) = sub_140001B30(*(_BYTE*)(qword_140013170 + 3));

v7 = qword_140013170;

*(_BYTE*)(v7 + 4) = sub_140001B30(*(_BYTE*)(qword_140013170 + 4));

v8 = qword_140013170;

*(_BYTE*)(v8 + 5) = sub_140001B30(*(_BYTE*)(qword_140013170 + 5));

v9 = qword_140013170;

*(_BYTE*)(v9 + 6) = sub_140001B30(*(_BYTE*)(qword_140013170 + 6));

v10 = qword_140013170;

*(_BYTE*)(v10 + 7) = sub_140001B30(*(_BYTE*)(qword_140013170 + 7));

v11 = qword_140013170;

*(_BYTE*)(v11 + 8) = sub_140001B30(*(_BYTE*)(qword_140013170 + 8));

v12 = qword_140013170;

*(_BYTE*)(v12 + 9) = sub_140001B30(*(_BYTE*)(qword_140013170 + 9));

v13 = qword_140013170;

*(_BYTE*)(v13 + 10) = sub_140001B30(*(_BYTE*)(qword_140013170 + 10));

v14 = qword_140013170;

*(_BYTE*)(v14 + 11) = sub_140001B30(*(_BYTE*)(qword_140013170 + 11));

v15 = qword_140013170;

*(_BYTE*)(v15 + 12) = sub_140001B30(*(_BYTE*)(qword_140013170 + 12));

v16 = qword_140013170;

*(_BYTE*)(v16 + 13) = sub_140001B30(*(_BYTE*)(qword_140013170 + 13));

v17 = qword_140013170;

*(_BYTE*)(v17 + 14) = sub_140001B30(*(_BYTE*)(qword_140013170 + 14));

v18 = qword_140013170;

*(_BYTE*)(v18 + 15) = sub_140001B30(*(_BYTE*)(qword_140013170 + 15));

v19 = qword_140013170;

*(_BYTE*)(v19 + 16) = sub_140001B30(*(_BYTE*)(qword_140013170 + 16));

v20 = qword_140013170;

*(_BYTE*)(v20 + 17) = sub_140001B30(*(_BYTE*)(qword_140013170 + 17));

v21 = qword_140013170;

*(_BYTE*)(v21 + 18) = sub_140001B30(*(_BYTE*)(qword_140013170 + 18));

v22 = qword_140013170;

*(_BYTE*)(v22 + 19) = sub_140001B30(*(_BYTE*)(qword_140013170 + 19));

v23 = qword_140013170;

*(_BYTE*)(v23 + 20) = sub_140001B30(*(_BYTE*)(qword_140013170 + 20));

v24 = qword_140013170;

*(_BYTE*)(v24 + 21) = sub_140001B30(*(_BYTE*)(qword_140013170 + 21));

v25 = qword_140013170;

*(_BYTE*)(v25 + 22) = sub_140001B30(*(_BYTE*)(qword_140013170 + 22));

v26 = qword_140013170;

*(_BYTE*)(v26 + 23) = sub_140001B30(*(_BYTE*)(qword_140013170 + 23));

v27 = qword_140013170;

*(_BYTE*)(v27 + 24) = sub_140001B30(*(_BYTE*)(qword_140013170 + 24));

v28 = qword_140013170;

*(_BYTE*)(v28 + 25) = sub_140001B30(*(_BYTE*)(qword_140013170 + 25));

v29 = qword_140013170;

*(_BYTE*)(v29 + 26) = sub_140001B30(*(_BYTE*)(qword_140013170 + 26));

v30 = qword_140013170;

*(_BYTE*)(v30 + 27) = sub_140001B30(*(_BYTE*)(qword_140013170 + 27));

v31 = qword_140013170;

*(_BYTE*)(v31 + 28) = sub_140001B30(*(_BYTE*)(qword_140013170 + 28));

v32 = qword_140013170;

*(_BYTE*)(v32 + 29) = sub_140001B30(*(_BYTE*)(qword_140013170 + 29));

v33 = qword_140013170;

*(_BYTE*)(v33 + 30) = sub_140001B30(*(_BYTE*)(qword_140013170 + 30));

v34 = qword_140013170;

*(_BYTE*)(v34 + 31) = sub_140001B30(*(_BYTE*)(qword_140013170 + 31));

v35 = qword_140013170;

*(_BYTE*)(v35 + 32) = sub_140001B30(*(_BYTE*)(qword_140013170 + 32));

v36 = qword_140013170;

*(_BYTE*)(v36 + 33) = sub_140001B30(*(_BYTE*)(qword_140013170 + 33));

v37 = qword_140013170;

*(_BYTE*)(v37 + 34) = sub_140001B30(*(_BYTE*)(qword_140013170 + 34));

v38 = qword_140013170;

*(_BYTE*)(v38 + 35) = sub_140001B30(*(_BYTE*)(qword_140013170 + 35));

v39 = qword_140013170;

*(_BYTE*)(v39 + 36) = sub_140001B30(*(_BYTE*)(qword_140013170 + 36));

v40 = qword_140013170;

*(_BYTE*)(v40 + 37) = sub_140001B30(*(_BYTE*)(qword_140013170 + 37));

v41 = qword_140013170;

*(_BYTE*)(v41 + 38) = sub_140001B30(*(_BYTE*)(qword_140013170 + 38));

v42 = qword_140013170;

*(_BYTE*)(v42 + 39) = sub_140001B30(*(_BYTE*)(qword_140013170 + 39));

v43 = qword_140013170;

*(_BYTE*)(v43 + 40) = sub_140001B30(*(_BYTE*)(qword_140013170 + 40));

v44 = qword_140013170;

*(_BYTE*)(v44 + 41) = sub_140001B30(*(_BYTE*)(qword_140013170 + 41));

v45 = qword_140013170;

*(_BYTE*)(v45 + 42) = sub_140001B30(*(_BYTE*)(qword_140013170 + 42));

*(_BYTE*)qword_140013180 ^= *(_BYTE*)((unsigned int)(v1 + 16) + qword_140003030);// 然后再次修改这16个值

*(_BYTE*)(qword_140013180 + 1) ^= *(_BYTE*)((unsigned int)(v1 + 17) + qword_140003030);

*(_BYTE*)(qword_140013180 + 2) ^= *(_BYTE*)((unsigned int)(v1 + 18) + qword_140003030);

*(_BYTE*)(qword_140013180 + 3) ^= *(_BYTE*)((unsigned int)(v1 + 19) + qword_140003030);

*(_BYTE*)(qword_140013180 + 4) ^= *(_BYTE*)((unsigned int)(v1 + 20) + qword_140003030);

*(_BYTE*)(qword_140013180 + 5) ^= *(_BYTE*)((unsigned int)(v1 + 21) + qword_140003030);

*(_BYTE*)(qword_140013180 + 6) ^= *(_BYTE*)((unsigned int)(v1 + 22) + qword_140003030);

*(_BYTE*)(qword_140013180 + 7) ^= *(_BYTE*)((unsigned int)(v1 + 23) + qword_140003030);

*(_BYTE*)(qword_140013180 + 8) ^= *(_BYTE*)((unsigned int)(v1 + 24) + qword_140003030);

*(_BYTE*)(qword_140013180 + 9) ^= *(_BYTE*)((unsigned int)(v1 + 25) + qword_140003030);

*(_BYTE*)(qword_140013180 + 10) ^= *(_BYTE*)((unsigned int)(v1 + 26) + qword_140003030);

*(_BYTE*)(qword_140013180 + 11) ^= *(_BYTE*)((unsigned int)(v1 + 27) + qword_140003030);

*(_BYTE*)(qword_140013180 + 12) ^= *(_BYTE*)((unsigned int)(v1 + 28) + qword_140003030);

*(_BYTE*)(qword_140013180 + 13) ^= *(_BYTE*)((unsigned int)(v1 + 29) + qword_140003030);

*(_BYTE*)(qword_140013180 + 14) ^= *(_BYTE*)((unsigned int)(v1 + 30) + qword_140003030);

*(_BYTE*)(qword_140013180 + 15) ^= *(_BYTE*)((unsigned int)(v1 + 31) + qword_140003030);

}

int main()

{

// 得到修改后的函数,可能是干扰动态调试的

init();

// 顺序问题!!按照特定顺序执行才能运行成功

sub_1400014D0(0xE0);    // 1

sub_1400014D0(0x40);    // 2

sub_1400014D0(0xC0);    // 3

sub_1400014D0(0x00);    // 4

sub_1400014D0(0x20);    // 5

sub_1400014D0(0x80);    // 6

sub_1400014D0(0x60);    //

sub_1400014D0(0xA0);    //

printf("%s", qword_140013170);

}

运行结果:hitcon{r3ally_re4lly_rea11y_normal_checker}

作者:selph

# 漏洞 # 渗透测试 # 黑客 # web安全 # CTF
本文为 极安御信安全研究院 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
极安御信安全研究院 LV.8
QQ交流群:434238324 官网:http://www.vultop.com/
  • 140 文章数
  • 33 关注者
0ctf babyheap
2023-09-07
世界级黑客丨电脑犯罪界的汉尼拔
2023-09-07
新PWN手必备环境(附详细步骤)
2023-08-31