idiotc4t's blog
搜索文档…
GitBook 提供支持
载入第二个Ntdll绕Hook

简介

我不知道有没有人写过这个东西, 之前和我的亲兄弟snowming师傅交流时回想起来用CreateFileMapping->MapViewOfFile以文件映射的形式打开,如果被打开文件时PE格式,那么这个文件会按照内存展开,那么我们猜想是不是这个被第二次载入内存的ntdll是不是就是一个干净的ntdll,能不能帮助我们绕过一些inline hook。

流程

    1.
    使用CreateFileMapping->MapViewOfFile映射一个ntdll
    2.
    自己实现一个GetProcAddress函数
    3.
    使用自写GetProcAddress函数获取nt函数
    4.
    do it

调试

把代码写出来之后windbg调了一下,发现如果没有挂钩,那么这个代码其实和原ntdll是一模一样的,在windbg里面会显示第二个ntdll。(只是显示成ntdll_xxx,在ldr链表里还是叫ntdll)。
如果使用windows api GetProcAddress函数获取函数地址的话会报错0126 找不到指定的模块。
具体分析过程参考开源的reactos项目的代码。
errorcode 126
但是如果我们直接自己编写一个GetProcAddress函数就可以获取到这个自己加载的ntdll内的函数地址并且执行成功。

代码

1
#include <Windows.h>
2
#include <stdio.h>
3
4
#define DEREF( name )*(UINT_PTR *)(name)
5
#define DEREF_64( name )*(DWORD64 *)(name)
6
#define DEREF_32( name )*(DWORD *)(name)
7
#define DEREF_16( name )*(WORD *)(name)
8
#define DEREF_8( name )*(BYTE *)(name)
9
10
typedef NTSTATUS(NTAPI* pNtAllocateVirtualMemory)(
11
HANDLE ProcessHandle,
12
PVOID* BaseAddress,
13
ULONG_PTR ZeroBits,
14
PSIZE_T RegionSize,
15
ULONG AllocationType,
16
ULONG Protect);
17
18
FARPROC WINAPI GetProcAddressR(HANDLE hModule, LPCSTR lpProcName)
19
{
20
UINT_PTR uiLibraryAddress = 0;
21
FARPROC fpResult = NULL;
22
23
if (hModule == NULL)
24
return NULL;
25
uiLibraryAddress = (UINT_PTR)hModule;
26
27
__try
28
{
29
UINT_PTR uiAddressArray = 0;
30
UINT_PTR uiNameArray = 0;
31
UINT_PTR uiNameOrdinals = 0;
32
PIMAGE_NT_HEADERS pNtHeaders = NULL;
33
PIMAGE_DATA_DIRECTORY pDataDirectory = NULL;
34
PIMAGE_EXPORT_DIRECTORY pExportDirectory = NULL;
35
pNtHeaders = (PIMAGE_NT_HEADERS)(uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew);
36
pDataDirectory = (PIMAGE_DATA_DIRECTORY)&pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
37
pExportDirectory = (PIMAGE_EXPORT_DIRECTORY)(uiLibraryAddress + pDataDirectory->VirtualAddress);
38
uiAddressArray = (uiLibraryAddress + pExportDirectory->AddressOfFunctions);
39
uiNameArray = (uiLibraryAddress + pExportDirectory->AddressOfNames);
40
uiNameOrdinals = (uiLibraryAddress + pExportDirectory->AddressOfNameOrdinals);
41
if (((DWORD)lpProcName & 0xFFFF0000) == 0x00000000)
42
{
43
uiAddressArray += ((IMAGE_ORDINAL((DWORD)lpProcName) - pExportDirectory->Base) * sizeof(DWORD));
44
fpResult = (FARPROC)(uiLibraryAddress + DEREF_32(uiAddressArray));
45
}
46
else
47
{
48
DWORD dwCounter = pExportDirectory->NumberOfNames;
49
while (dwCounter--)
50
{
51
char* cpExportedFunctionName = (char*)(uiLibraryAddress + DEREF_32(uiNameArray));
52
if (strcmp(cpExportedFunctionName, lpProcName) == 0)
53
{
54
uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD));
55
fpResult = (FARPROC)(uiLibraryAddress + DEREF_32(uiAddressArray));
56
57
break;
58
}
59
uiNameArray += sizeof(DWORD);
60
uiNameOrdinals += sizeof(WORD);
61
}
62
}
63
}
64
__except (EXCEPTION_EXECUTE_HANDLER)
65
{
66
fpResult = NULL;
67
}
68
69
return fpResult;
70
}
71
72
73
int main() {
74
75
HANDLE hNtdllfile = CreateFileA("c:\\windows\\system32\\ntdll.dll", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
76
HANDLE hNtdllMapping = CreateFileMapping(hNtdllfile, NULL, PAGE_READONLY | SEC_IMAGE, 0, 0, NULL);
77
LPVOID lpNtdllmaping = MapViewOfFile(hNtdllMapping, FILE_MAP_READ, 0, 0, 0);
78
79
pNtAllocateVirtualMemory NtAllocateVirtualMemory = (pNtAllocateVirtualMemory)GetProcAddressR((HMODULE)lpNtdllmaping, "NtAllocateVirtualMemory");
80
81
int err = GetLastError();
82
83
LPVOID Address = NULL;
84
SIZE_T uSize = 0x1000;
85
86
NTSTATUS status = NtAllocateVirtualMemory(GetCurrentProcess(), &Address, 0, &uSize, MEM_COMMIT, PAGE_READWRITE);
87
88
89
90
return 0;
91
};
Copied!

LINKS

使用文件映射进行远程进程注入
GitHub - stephenfewer/ReflectiveDLLInjection: Reflective DLL injection is a library injection technique in which the concept of reflective programming is employed to perform the loading of a library from memory into a host process.
GitHub
最近更新 1yr ago