#pragma once
#include <ntifs.h>
#include <ntddk.h>
#include <ntimage.h>
#define RELOC_FLAG64(ReInfo) ((ReInfo>>0x0C)==IMAGE_REL_BASED_DIR64)
#define RELOC_FLAG RELOC_FLAG64
UINT64 g_fnLoadLibrary = 0;
UINT64 g_fnGetProcAddress = 0;
UINT64 g_fnRtlAddFuntion = 0;
void Log(const char* sz_info, bool is_error, ULONG err_code);
EXTERN_C NTSTATUS MmCopyVirtualMemory(
IN PEPROCESS FromProcess,
IN CONST VOID* FromAddress,
IN PEPROCESS ToProcess,
OUT PVOID ToAddress,
IN SIZE_T BufferSize,
IN KPROCESSOR_MODE PreviousMode,
OUT PSIZE_T NumberOfBytesCopied
);
EXTERN_C NTSTATUS NTAPI ZwSetInformationProcess(
__in HANDLE ProcessHandle,
__in PROCESSINFOCLASS ProcessInformationClass,
__in_bcount (ProcessInformationLength) PVOID ProcessInformation,
__in ULONG ProcessInformationLength
);
typedef PVOID HINSTANCE, HMODULE;
using f_LoadLibraryA = HMODULE(_stdcall*)(const char* lpLibFileName);
using f_GetProcAddress = PVOID(_stdcall*)(HMODULE hModule, LPCSTR lpProcName);
using f_DLL_ENTRY_POINT = BOOLEAN(_stdcall*)(PVOID DllHandle, ULONG Reason, PVOID Reserved);
using f_RtlAddFunctionTable = BOOLEAN(_stdcall*)(_IMAGE_RUNTIME_FUNCTION_ENTRY* FunctionTable, DWORD32 EntryCount, DWORD64 BaseAddress);
struct Manual_Mapping_data
{
//用于重定位iat
f_LoadLibraryA pLoadLibraryA;
f_GetProcAddress pGetProcAddress;
//x64专有
f_RtlAddFunctionTable pRtlAddFunctionTable;
char* pBase;
DWORD32 dwReadson; //设置为0线程开始时执行dll
PVOID reserveParam;
BOOLEAN bFirst;//只允许第一次系统调用进入
BOOLEAN bStart;//开始执行shellcode了 可以同步关闭instCallBack
BOOLEAN bContinue;//用于继续执行 去掉pe头后执行dllmain
size_t DllSize;
};
void __stdcall InstruShellCode(Manual_Mapping_data* pData);
#pragma pack(push)
#pragma pack(1)
struct shellcode_t {
private:
char padding[43];
public:
uintptr_t manual_data;
private:
char pdding[47];
public:
uintptr_t rip;
uintptr_t shellcode;
};
char g_instcall_shel1code[] =
{
0x50,
0x51,
0x52,
0x53,
0x55,
0x56,
0x57,
0x41, 0x50,
0x41, 0x51,
0x41, 0x52,
0x41, 0x53,
0x41, 0x54,
0x41, 0x55,
0x41, 0x56,
0x41, 0x57,
0x48,0x89 ,0x25,0x4C,0x00,0x00,0x00,
0x48, 0x83, 0xEC, 0x38,
0x48,0x81,0xE4,0xF0,0xFF,0xFF,0xFF,
0x48,0xB9,0x11,0x11,0x11,0x11,0x11,0x11,0x11,0x11,
0xFF,0x15,0x29,0x00,0x00,0x00,0x90,0x90,0x90,0x90,0x90,0x90,0x90,0x90,//call
0x48, 0x8B, 0x25, 0x22,0x00,0x00,0x00,
0x41, 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x41, 0x5B, 0x41, 0x5A, 0x41, 0x59, 0x41, 0x58, 0x5F,
0x5E, 0x5D, 0x5B, 0x5A, 0x59, 0x58,
0x41, 0xFF, 0xE2,
0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0
};
#pragma pack(pop)
NTSTATUS inst_callback_set_callback(PVOID inst_callback)
{
NTSTATUS status = STATUS_SUCCESS;
PVOID InstCallBack = inst_callback;
PACCESS_TOKEN Token{ 0 };
PULONG TokenMask{ 0 };
Token = PsReferencePrimaryToken(IoGetCurrentProcess());
TokenMask = (PULONG)((ULONG_PTR)Token + 0x40);//取_TOKEN结构下Privileges
TokenMask[0] |= 0x100000;
TokenMask[1] |= 0x100000;
TokenMask[2] |= 0x100000;
status = ZwSetInformationProcess(NtCurrentProcess(), ProcessInstrumentationCallback, &InstCallBack, sizeof(PVOID));
if (!NT_SUCCESS(status))
{
Log("failed to set instrcallback !", true, status);
}
else
{
Log("failed to set instrcallback SUCCESS!", false, 0);
}
return status;
}
void Log(const char* sz_info, bool is_error, ULONG err_code)
{
if (is_error)
{
DbgPrintEx(77, 0, "[instCallBack Error] : %s err_code:%x\n", sz_info, err_code);
}
else
{
DbgPrintEx(77, 0, "[instCallBack] : %s \n", sz_info);
}
}
PUCHAR inst_callback_get_dll_memory(UNICODE_STRING* us_dll_path)
{
NTSTATUS status = STATUS_SUCCESS;
HANDLE hFile = 0;
OBJECT_ATTRIBUTES objattr = { 0 };
IO_STATUS_BLOCK IoStatusBlock = { 0 };
LARGE_INTEGER lainter = { 0 };
LARGE_INTEGER byteOffset = { 0 };
FILE_STANDARD_INFORMATION fileinfo = { 0 };
ULONG64 fileSize = 0;
PUCHAR pDllMemory = 0;
InitializeObjectAttributes(&objattr, us_dll_path, OBJ_CASE_INSENSITIVE, 0, 0);
status = ZwCreateFile(&hFile, GENERIC_READ, &objattr, &IoStatusBlock, &lainter, FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE, FILE_OPEN, 0, 0, 0);
if (!NT_SUCCESS(status))
{
Log("failed to Create File!", true, status);
return 0;
}
status = ZwQueryInformationFile(hFile, &IoStatusBlock, &fileinfo, sizeof(fileinfo), FileStandardInformation);
fileSize = (ULONG)fileinfo.AllocationSize.QuadPart;
if (!NT_SUCCESS(status))
{
Log("failed to get File size!", true, status);
return 0;
}
fileSize += 0x1000;
fileSize = (ULONG64)PAGE_ALIGN(fileSize);
//ExAllocatePoolWithTag
pDllMemory = (PUCHAR)ExAllocatePoolWithTag(PagedPool, fileSize, 'Dllp');
//pDllmem = (PUCHAR)ExAllocatePool3(NonPagedPool, fileSize, 'Dllp', NULL, NULL);//NonPagedPool PagedPool
RtlSecureZeroMemory(pDllMemory, fileSize);
status = ZwReadFile(hFile, 0, 0, 0, &IoStatusBlock, pDllMemory, fileSize, &byteOffset, 0);
ZwFlushBuffersFile(hFile, &IoStatusBlock);
if (!NT_SUCCESS(status))
{
ExFreePool(pDllMemory);
ZwClose(hFile);
Log("failed to read File context!", true, status);
return 0;
}
ZwClose(hFile);
return pDllMemory;
}
NTSTATUS inst_callback_alloc_memory(PUCHAR p_dll_memory, _Out_ PVOID* inst_callbak_addr, PVOID* p_manual_data)
{
PEPROCESS Process{ 0 };
IMAGE_NT_HEADERS* pNtHeader = nullptr;
IMAGE_FILE_HEADER* pFileHeader = nullptr;
IMAGE_OPTIONAL_HEADER* pOptheader = nullptr;
NTSTATUS status = STATUS_SUCCESS;
PVOID pManualMapData = 0,pShellCode = 0;
char* pStartMapAdd = 0;
size_t AllocSize = 0, RETSize;
Manual_Mapping_data ManualMapData{ 0 };
if (reinterpret_cast<IMAGE_DOS_HEADER*>(p_dll_memory)->e_magic != 0x5A4D)
{
status = STATUS_INVALID_PARAMETER;
Log("the dll is not valid pe structure\n", true, status);
return status;
}
pNtHeader = (IMAGE_NT_HEADERS*)((ULONG_PTR)p_dll_memory + reinterpret_cast<IMAGE_DOS_HEADER*>(p_dll_memory)->e_lfanew);
pFileHeader = &pNtHeader->FileHeader;
pOptheader = &pNtHeader->OptionalHeader;
if (pFileHeader->Machine != IMAGE_FILE_MACHINE_AMD64)
{
status = STATUS_INVALID_PARAMETER;
Log("the dll is is x86 structure ,not support!\n", true, status);
return status;
}
AllocSize = pOptheader->SizeOfImage;
status = ZwAllocateVirtualMemory(NtCurrentProcess(), (PVOID*)&pStartMapAdd, 0, &AllocSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(status))
{
Log("failed to alloc Memory!", true, status);
return status;
}
RtlSecureZeroMemory(pStartMapAdd, AllocSize);
ManualMapData.dwReadson = 0;
ManualMapData.pGetProcAddress = (f_GetProcAddress)g_fnGetProcAddress;
ManualMapData.pLoadLibraryA = (f_LoadLibraryA)g_fnLoadLibrary;
ManualMapData.pRtlAddFunctionTable = (f_RtlAddFunctionTable)g_fnRtlAddFuntion;
ManualMapData.pBase = pStartMapAdd;
ManualMapData.bContinue = false;//判断是否抹除了pe标识
ManualMapData.bFirst = true;
ManualMapData.bStart = false;
ManualMapData.DllSize = AllocSize;
Process = IoGetCurrentProcess();
status = MmCopyVirtualMemory(Process, p_dll_memory, Process, pStartMapAdd, PAGE_SIZE, KernelMode, &RETSize);
if (!NT_SUCCESS(status))
{
Log("failed to load pe header!", true, status);
return status;
}
IMAGE_SECTION_HEADER* pSectionHeadr = IMAGE_FIRST_SECTION(pNtHeader);
for (size_t i = 0; i < pFileHeader->NumberOfSections; i++, pSectionHeadr++)
{
if (pSectionHeadr->SizeOfRawData)
{
status = MmCopyVirtualMemory(Process, p_dll_memory + pSectionHeadr->PointerToRawData,
Process, pStartMapAdd + pSectionHeadr->VirtualAddress, pSectionHeadr->SizeOfRawData, KernelMode, &RETSize);
if (!NT_SUCCESS(status))
{
Log("failed to load pe header!", true, status);
return status;
}
}
}
AllocSize = PAGE_SIZE;
status = ZwAllocateVirtualMemory(NtCurrentProcess(), &pManualMapData, 0,
&AllocSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(status))
{
Log("failed to alloc Memory for maunalmapdata!", true, status);
return status;
}
RtlSecureZeroMemory(pManualMapData, AllocSize);
status = MmCopyVirtualMemory(Process, &ManualMapData, Process, pManualMapData, sizeof(ManualMapData), KernelMode, &RETSize);
if (!NT_SUCCESS(status))
{
Log("failed to write Memory for maunalmapdata!", true, status);
return status;
}
//重定位ShellCode
status = ZwAllocateVirtualMemory(NtCurrentProcess(), &pShellCode, 0,
&AllocSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(status))
{
Log("failed to alloc Memory for shellcode!", true, status);
return status;
}
RtlSecureZeroMemory(pShellCode, AllocSize);
status = MmCopyVirtualMemory(Process, InstruShellCode, Process, pShellCode, AllocSize, KernelMode, &RETSize);
if (!NT_SUCCESS(status))
{
Log("failed to write Memory for shellcode!", true, status);
return status;
}
//ShellCode
shellcode_t shell_code;
memset(&shell_code, 0, sizeof shell_code);
memcpy(&shell_code, &g_instcall_shel1code, sizeof shellcode_t);
shell_code.manual_data = (UINT64)pManualMapData;
shell_code.rip = (UINT64)pShellCode;
status = ZwAllocateVirtualMemory(NtCurrentProcess(), inst_callbak_addr, 0,
&AllocSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
if (!NT_SUCCESS(status))
{
Log("failed to alloc Memory for instrcall shellcode!", true, status);
return status;
}
RtlSecureZeroMemory(*inst_callbak_addr, AllocSize);
status = MmCopyVirtualMemory(Process, &shell_code, Process, *inst_callbak_addr, sizeof shell_code, KernelMode, &RETSize);
if (!NT_SUCCESS(status))
{
Log("failed to write Memory for instrcall shellcode!", true, status);
return status;
}
*p_manual_data = pManualMapData;
return status;
}
NTSTATUS inst_callback_inject(HANDLE process_id, UNICODE_STRING* us_dll_path)
{
NTSTATUS status = STATUS_SUCCESS;
PEPROCESS pEhtreadyx = NULL;
KAPC_STATE apc_state;
PUCHAR pDllMem = 0;
PVOID InstCallBack = 0, pManualMapData = 0;
status = PsLookupProcessByProcessId(process_id, &pEhtreadyx);
if (!NT_SUCCESS(status))
{
Log("failed to get process!", true, status);
status = STATUS_UNSUCCESSFUL;
return status;
}
KeStackAttachProcess(pEhtreadyx, &apc_state);
while (true)
{
pDllMem = inst_callback_get_dll_memory(us_dll_path);
if (!pDllMem)
{
status = STATUS_UNSUCCESSFUL;
break;
}
status = inst_callback_alloc_memory(pDllMem, &InstCallBack, &pManualMapData);
if (!NT_SUCCESS(status))break;
//设置instrecallback
status = inst_callback_set_callback(InstCallBack);
break;
}
if (pManualMapData && MmIsAddressValid(pManualMapData))
{
__try {
while (1)
{
if (((Manual_Mapping_data*)pManualMapData)->bStart)break;
}
}
__except (1)
{
Log("process exit! 1", true, 0);
ObDereferenceObject(pEhtreadyx);
KeUnstackDetachProcess(&apc_state);
return status;
}
}
inst_callback_set_callback(0);
if (pManualMapData && MmIsAddressValid(pManualMapData) && PsLookupProcessByProcessId(process_id, &pEhtreadyx) != STATUS_PENDING)
{
__try {
*(PUCHAR)((((Manual_Mapping_data*)pManualMapData))->pBase) = 0;
((Manual_Mapping_data*)pManualMapData)->bContinue = true;
}
__except (1)
{
Log("process exit!", true, 0);
}
}
ObDereferenceObject(pEhtreadyx);
KeUnstackDetachProcess(&apc_state);
if (pDllMem && MmIsAddressValid(pDllMem))ExFreePool(pDllMem);
return status;
}
void __stdcall InstruShellCode(Manual_Mapping_data* pData)
{
if (!pData->bFirst)return;
pData->bFirst = false;
pData->bStart = true;
char* pBase = pData->pBase;
auto* pOptionHeader = &reinterpret_cast<IMAGE_NT_HEADERS*>(pBase + reinterpret_cast<IMAGE_DOS_HEADER*>
((uintptr_t)pBase)->e_lfanew)->OptionalHeader;
char* LocationDelta = pBase - pOptionHeader->ImageBase;//差值
if (LocationDelta)
{
if (pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
{
auto* pRelocData = reinterpret_cast<IMAGE_BASE_RELOCATION*>
(pBase + pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
auto* pRelocEnd = reinterpret_cast<IMAGE_BASE_RELOCATION*>(reinterpret_cast<uintptr_t>(pRelocData)
+ pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size);
while (pRelocData< pRelocEnd && pRelocData->SizeOfBlock)
{
UINT64 AmountOfEntries = (pRelocData->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(short);
unsigned short* pRelativeInfo = reinterpret_cast<unsigned short*>(pRelocData + 1);
for (UINT64 i = 0; i != AmountOfEntries; ++i, ++pRelativeInfo)
{
if (RELOC_FLAG(*pRelativeInfo))
{
//计算出需要重定位的地址
auto* pPatch = reinterpret_cast<UINT_PTR*>(pBase + pRelocData->VirtualAddress + ((*pRelativeInfo) & 0xFFF));
//手动重定位
*pPatch += reinterpret_cast<UINT_PTR>(LocationDelta);
}
}
pRelocData = reinterpret_cast<IMAGE_BASE_RELOCATION*>(reinterpret_cast<char*>(pRelocData) + pRelocData->SizeOfBlock);
}
}
}
if (pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size)
{
IMAGE_IMPORT_DESCRIPTOR* pImportDescr = reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR*>
(pBase+pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (pImportDescr->Name)
{
HMODULE hDll = pData->pLoadLibraryA(pBase + pImportDescr->Name);
//INT IAT
//int
ULONG_PTR* pInt = (ULONG_PTR*)(pBase + pImportDescr->OriginalFirstThunk);
ULONG_PTR* pIat = (ULONG_PTR*)(pBase + pImportDescr->FirstThunk);
//IAT
if (!pInt)pInt = pIat;
for (; *pIat; ++pIat, ++pInt)
{
if (IMAGE_SNAP_BY_ORDINAL(*pInt))
{
*pIat = (ULONG_PTR)pData->pGetProcAddress(hDll, (char*)(*pInt & 0xffff));
}
else
{
IMAGE_IMPORT_BY_NAME* pImport = (IMAGE_IMPORT_BY_NAME*)(pBase + *pInt);
*pIat = (ULONG_PTR)pData->pGetProcAddress(hDll, pImport->Name);
}
}
pImportDescr++;
}
}
#define DLL_PROCESS_ATTACH 1
if (pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].Size)
{
auto* pTLS = reinterpret_cast<IMAGE_TLS_DIRECTORY*>
(pBase + pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS].VirtualAddress);
auto* pCallBack = reinterpret_cast<PIMAGE_TLS_CALLBACK*>(pTLS->AddressOfCallBacks);
for (;pCallBack && *pCallBack; ++pCallBack)
{
(*pCallBack)(pBase, DLL_PROCESS_ATTACH, nullptr);
}
}
auto excep = pOptionHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION];
if (excep.Size)
{
pData->pRtlAddFunctionTable((_IMAGE_RUNTIME_FUNCTION_ENTRY*)
(pBase + excep.VirtualAddress), excep.Size / sizeof(_IMAGE_RUNTIME_FUNCTION_ENTRY),(DWORD64)pBase);
}
while (!pData->bContinue);
//手动调用dllmain
((f_DLL_ENTRY_POINT)(pBase+pOptionHeader->AddressOfEntryPoint))(pBase, DLL_PROCESS_ATTACH, 0);
}
用这些代码注入dll 导致c00005异常
最新发布