driver复现(铁三2024)
# PREFACE:之前看了不少驱动开发,然后发现这题调不起来,静态解不出来,赛后速通 unicorn 写了个模拟看看
首先,可以看到文件的前 0x400 字符是文件头信息,先 rebase+0x400
这里直接贴一个 unicorn 脚本,可以看到 tea 的操作,前后转化了一次端序然后标准 TEA, which is WRONG:
from unicorn import * | |
from unicorn.x86_const import * | |
import struct | |
from capstone import * | |
REAL_BASE_OFFSET = 0x400 | |
md = Cs(CS_ARCH_X86, CS_MODE_64) | |
def read(name): | |
with open(name,'rb') as f: | |
return f.read() | |
def hookDbgPrint(mu,address,size,user_data): | |
code = mu.mem_read(address, size) | |
# for instruction in md.disasm(code, address): | |
# print("0x%x: %s %s" % (instruction.address, instruction.mnemonic, instruction.op_str)) | |
DbgList = [0x1400015C9] | |
if (address in DbgList): | |
mu.reg_write(UC_X86_REG_RIP, address+5) | |
print(f"hook: {address}") | |
if (address == 0x140001940): | |
TEAoutput = mu.mem_read(mu.reg_read(UC_X86_REG_RAX), 32) | |
if (address == 0x1400017DB): | |
# mu.mem_write(mu.reg_read(UC_X86_REG_RSP) + 40, b'12345678') | |
TEAinput = mu.mem_read(mu.reg_read(UC_X86_REG_RSP) + 40, 8) | |
print("tea in: ",bytes(TEAinput)) | |
if (address == 0x14000166D): | |
mu.mem_write(mu.reg_read(UC_X86_REG_RSP) + 144, b'12345678') | |
if (address == 0x14000182D): | |
TEAoutput = mu.mem_read(mu.reg_read(UC_X86_REG_RSP) + 40, 8) | |
print("tea out: ",end='') | |
for i in TEAoutput: | |
print(i,end=',') | |
print() | |
if (address == 0x14000197A): | |
ENCoutput = mu.mem_read(mu.reg_read(UC_X86_REG_RSP) + 40, 8) | |
print("enc out:",end='') | |
for i in ENCoutput: | |
print(i,end=',') | |
print() | |
def hookEND(mu : Uc,address,size,user_data): | |
if (address == 0x14000197A): | |
print("end") | |
# exit(0) | |
mu.emu_stop() | |
mu = Uc (UC_ARCH_X86, UC_MODE_64) | |
BASE = 0x140001000 | |
STACK_ADDR = 0x1000 | |
STACK_SIZE = 1024*1024 | |
mu.mem_map(BASE, 1024*1024) | |
mu.mem_map(STACK_ADDR, STACK_SIZE) | |
mu.mem_write(BASE, read("./ez_driver.sys")) | |
mu.reg_write(UC_X86_REG_RBP, STACK_ADDR + STACK_SIZE // 2) | |
mu.reg_write(UC_X86_REG_RSP, STACK_ADDR + STACK_SIZE // 3) | |
mu.hook_add(UC_HOOK_CODE,hookDbgPrint) | |
mu.hook_add(UC_HOOK_CODE,hookEND) | |
mu.emu_start(0x14000161D, 0x140004000) |
另一个加密就是对称的,其实看了就知道只做了 xor,重写一遍就行:
#include <iostream> | |
#include <Windows.h> | |
BYTE byte_140004000[] = | |
{ | |
0x72, 0x62, 0xAE, 0x34, 0x52, 0x9A, 0x06, 0xAF, | |
0x72, 0xFB, 0x40, 0xC0, 0x10, 0x35, 0xBD, 0xD4, | |
0x22, 0xA5, 0x93, 0x07, 0xB4, 0xFB, 0xB5, 0xCA, | |
0xE8, 0x01, 0xF5, 0xAE, 0xED, 0x7B, 0xB8, 0x6A | |
}; | |
__int64 __fastcall sub_140001A70(unsigned int *input, int a2) | |
{ | |
int j; // [rsp+4h] [rbp-44h] | |
int i; // [rsp+8h] [rbp-40h] | |
unsigned int input_xor; // [rsp+Ch] [rbp-3Ch] BYREF | |
unsigned char *p_input_xor; // [rsp+10h] [rbp-38h] | |
unsigned int v6; // [rsp+18h] [rbp-30h] | |
char v7[16]; // [rsp+20h] [rbp-28h] | |
v7[1] = a2 ^ 0x25; | |
v7[0] = a2 ^ 0x7A; | |
v7[8] = a2 ^ 0x1A; | |
v7[2] = a2 ^ 0x35; | |
v7[9] = a2 ^ 0x6D; | |
v7[3] = a2 ^ 0x23; | |
v7[11] = a2 ^ 0x94; | |
v7[4] = a2 ^ 0xC5; | |
v7[5] = a2 ^ 0x4B; | |
v7[6] = a2 ^ 0x21; | |
v7[7] = a2 ^ 0x35; | |
v7[10] = a2 ^ 0x91; | |
v7[12] = a2 ^ 0x2C; | |
v7[13] = a2 ^ 0xC1; | |
v7[14] = a2 ^ 0x92; | |
v7[15] = a2 ^ 0x51; | |
for ( i = 0; i < 4; ++i ) | |
{ | |
p_input_xor = (unsigned char*)&input_xor; | |
input_xor = *input ^ a2; | |
for ( j = 0; j < 4; ++j ) | |
*p_input_xor++ ^= v7[15 - (((unsigned __int8)i + (unsigned __int8)j) & 0xF)] | ((unsigned __int8)j << j) | j | 4; | |
v6 = ~a2 ^ input_xor; | |
*input++ = v6; | |
} | |
} | |
int main() | |
{ | |
int v8 = 0; | |
BYTE* v17 = byte_140004000; | |
do | |
{ | |
sub_140001A70((unsigned int *)v17, v8++); | |
v17 += 16; | |
} while (v8 < 2); | |
for (unsigned char c : byte_140004000) | |
printf("%d,", c); | |
printf("\n"); | |
} |
然后发现模拟结果和解密明明对得上,但是出不来,结论是藏东西了或者改东西了,毕竟没有真起起来调,然后发现前面有这个 init,寻找特定的结构 shr ecx, 0x5,把 5 改成 6
土里刨一个脚本出来:
#include<bits/stdc++.h> | |
using namespace std; | |
void decrypt(uint32_t *v, uint32_t *key) | |
{ | |
uint32_t l = v[0], r = v[1], sum = 0x9E3779B9 * 33; | |
for (int i = 0; i < 33; ++i) | |
{ | |
r -= (key[(sum >> 11) & 3] + sum) ^ (l + ((l >> 5) ^ (16 * l))); | |
sum += 0x61C88647; | |
l -= (key[sum & 3] + sum) ^ (r + ((r >> 6) ^ (16 * r))); | |
} | |
v[0] = l, v[1] = r; | |
} | |
int main(){ | |
uint32_t key[4]; | |
// 加解密对称!!! | |
// uint8_t enc[] = {0x72, 0x62, 0xAE, 0x34, 0x52, 0x9A, 0x06, 0xAF, | |
// 0x72, 0xFB, 0x40, 0xC0, 0x10, 0x35, 0xBD, 0xD4, | |
// 0x22, 0xA5, 0x93, 0x07, 0xB4, 0xFB, 0xB5, 0xCA, | |
// 0xE8, 0x01, 0xF5, 0xAE, 0xED, 0x7B, 0xB8, 0x6A}; | |
uint8_t enc[] = {216,10,158,244,59,162,215,207,72,43,33,160,195,93,221,84,137,205,162,199,220,195,101,170,211,209,149,206,63,19,217,234}; | |
key[0] = 0x1A2B; | |
key[1] = 0x3A4D; | |
key[2] = 0x5E6F; | |
key[3] = 0xAA33; | |
for (int i=0;i<32;i+=8){ | |
uint32_t *p = (uint32_t *)&enc[i]; | |
p[0] = __builtin_bswap32(p[0]); | |
p[1] = __builtin_bswap32(p[1]); | |
decrypt((uint32_t*)p,key); | |
p[0] = __builtin_bswap32(p[0]); | |
p[1] = __builtin_bswap32(p[1]); | |
} | |
for (int i=0;i<32;i++){ | |
printf("%c",enc[i]); | |
} | |
return 0; | |
} |