免杀中的unhook手法(持续更新)
2024-04-15 22:42:01

UnhookingPatch

项目地址:https://github.com/SaadAhla/UnhookingPatch

通过syscall stub来判断是否被hook

1
2
3
4
5
6
7
8
9
BOOL isItHooked(LPVOID addr) {
BYTE stub[] = "\x4c\x8b\xd1\xb8";
// syscall stub:
// mov r10, rcx
// mov eax
if (memcmp(addr, stub, 4) != 0)
return TRUE;
return FALSE;
}

unhook的手法,修改内存页属性,将patch内容写入内存,恢复内存页

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
BOOL UnhookPatch(LPVOID addr) {

DWORD oldprotect = 0;

BYTE syscallNum = GetsyscallNum(addr);
DWORD64 syscallInst = GetsyscallInstr(addr);

// mov r10, rcx
// mov eax, SSN
// syscall
// retn

BYTE patch[] = { 0x49, 0x89, 0xCA, 0xB8, 0xBC, 0x00, 0x00, 0x00, 0x0F, 0x05, 0xC3, 0x90, 0x90, 0x90, 0x90 };

// syscall
patch[4] = syscallNum;

// syscall instruction
patch[8] = *(BYTE*)syscallInst;
patch[9] = *(BYTE*)(syscallInst + 0x1);

// 将 addr 指向的内存页的保护属性设置为可执行、可读写,并将原始的保护属性值存储到 oldprotect 变量中,以便将来恢复原始的保护属性
BOOL status1 = VirtualProtect(addr, 4096, PAGE_EXECUTE_READWRITE, &oldprotect);
if (!status1) {
printf("Failed in changing protection (%u)\n", GetLastError());
return FALSE;
}

memcpy(addr, patch, sizeof(patch));

// 恢复
BOOL status2 = VirtualProtect(addr, 4096, oldprotect, &oldprotect);
if (!status2) {
printf("Failed in changing protection back (%u)\n", GetLastError());
return FALSE;
}
return TRUE;
}

LdrLoadDll-Unhooking

项目地址:https://github.com/trickster0/LdrLoadDll-Unhooking

上个项目的思路就是直接修改内存中数据然后patch掉

这个项目的思路:实际上是做一个跳板函数绕过hook

image-20240415210111729

参考

  1. https://killer.wtf/2022/01/19/CustomJmpUnhook.html
Prev
2024-04-15 22:42:01
Next