# 载入第二个Ntdll绕Hook

## 简介

我不知道有没有人写过这个东西， 之前和我的亲兄弟[snowming](http://blog.leanote.com/post/snowming/a0366d1d01bf)师傅交流时回想起来用[CreateFileMapping->MapViewOfFile](https://idiotc4t.com/code-and-dll-process-injection/mapping-injection)以文件映射的形式打开，如果被打开文件时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)。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MK4qsKoV0QA1K_WQyi_%2F-MK4sUyGPhkrHxVLUpYR%2Fimage.png?alt=media\&token=c5de6d78-613b-4c6f-908d-65b1c5f0c4d9)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MK4qsKoV0QA1K_WQyi_%2F-MK4t_P7FlxrBdxwDlhX%2Fimage.png?alt=media\&token=bad77e5f-c2b3-412f-abfb-74506de63de4)

如果使用windows api GetProcAddress函数获取函数地址的话会报错0126 找不到指定的模块。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MK50AFs6jyMZsHJVLfu%2F-MK51fyPmJRaSMvEkXFO%2Fimage.png?alt=media\&token=092b96fb-c3b5-44b0-910d-2b7a57297a10)

具体分析过程参考开源的reactos项目的代码。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MK5Ef3gMp_87CJu-DIP%2F-MK5EvnllVIhbfknQOlw%2Fimage.png?alt=media\&token=ff0f31a4-2398-4804-acd2-c643cbec10d2)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MK5Ef3gMp_87CJu-DIP%2F-MK5Erg0FbkBaWBu66Kh%2Fimage.png?alt=media\&token=2dfafe33-ef61-4b9f-806f-ef6ac281c5d5)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MK5Ef3gMp_87CJu-DIP%2F-MK5EzxLEmecRXk4eM9J%2Fimage.png?alt=media\&token=416beb46-18bd-4dc4-8946-2d8681facc01)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MK5P9v3txbw2zNeqh7d%2F-MK5PDoBcVZ6vE2Bty2R%2Fimage.png?alt=media\&token=1dfaa289-df89-4518-9cd0-1d4be949699e)

![errorcode 126](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MK5P9v3txbw2zNeqh7d%2F-MK5PNuGc-MyDszhnij1%2Fimage.png?alt=media\&token=094a60f8-ad2a-416c-a1a2-367a76fad7d2)

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MK5Ef3gMp_87CJu-DIP%2F-MK5F8KIgnawP5gywS4I%2Fimage.png?alt=media\&token=85af03e8-ef46-4d3e-8025-46bd4ac342ba)

但是如果我们直接自己编写一个GetProcAddress函数就可以获取到这个自己加载的ntdll内的函数地址并且执行成功。

![](https://3969710588-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M3GuIlaAXU8NbJTCRei%2F-MK51nnfSA_TWOlD2ycj%2F-MK526WhGHuPdDC0XoFz%2Fimage.png?alt=media\&token=f60e171a-6449-4f5e-ac3d-c6ea6144cf9e)

## 代码

```
#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);

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() {

	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;
};
```

## LINKS

{% embed url="<http://blog.leanote.com/post/snowming/a0366d1d01bf>" %}

{% embed url="<https://github.com/stephenfewer/ReflectiveDLLInjection>" %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://idiotc4t.com/defense-evasion/load-ntdll-too.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
