- 创建DLL
- 在Dll DLL_PROCESS_ATTACH 时 OutputDebugString(L"[+] DLL已经注入-----");
- 创建一个程序用来将Dll注入进去
- 获取目标进程的进程ID,打开进程,(注意权限参数)获取进程句柄,
- 通过VirtualAllocEx申请目标进程的一块空间,将注入DLL的路径写进去
- 创建远程线程,注意第四第五个参数,线程函数的地址,和线程参数,这个线程参数回同时就是线程函数的参数,这样的话线程函数是Loadlibrary,参数是DLL地址,开启线程就会执行DLL加载,我们的DLL就会被加载进入.
-
// IATHook.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> #include <tlhelp32.h> #include <stdio.h> #include <cwchar> #include <iostream> #include <cstring> int contains_string_optimized(const TCHAR* target, const TCHAR* substr) { return (target && substr) ? (_tcsstr(target, substr) != NULL) : 0; } PROCESSENTRY32* EnumProcesses() { // 1. 创建进程快照 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if (hSnapshot == INVALID_HANDLE_VALUE) { printf("快照创建失败\n"); return NULL; } // 2. 初始化结构体 PROCESSENTRY32 pe; pe.dwSize = sizeof(PROCESSENTRY32); // 必须初始化大小[2,4](@ref) // 3. 遍历首个进程 if (!Process32First(hSnapshot, &pe)) { printf("遍历失败\n"); CloseHandle(hSnapshot); return NULL; } int size = 0; // 4. 循环输出进程信息 do { size++; } while (Process32Next(hSnapshot, &pe)); // 继续遍历[1,2](@ref) PROCESSENTRY32* ProcessList = (PROCESSENTRY32*)malloc((size + 1)*sizeof(PROCESSENTRY32)); memset(ProcessList, 0, (size + 1)*(sizeof(PROCESSENTRY32))); // 3. 遍历首个进程 if (!Process32First(hSnapshot, &pe)) { printf("遍历失败\n"); CloseHandle(hSnapshot); return NULL; } int i = 0; // 4. 循环输出进程信息 do { memcpy((void*)(ProcessList + i), &pe, sizeof(PROCESSENTRY32)); i++; } while (Process32Next(hSnapshot, &pe)); // 继续遍历[1,2](@ref) memset((void*)(ProcessList + i), 0, sizeof(PROCESSENTRY32)); // 5. 释放资源 CloseHandle(hSnapshot); return ProcessList; } int gethProcessByName(TCHAR* procName){ PROCESSENTRY32* procList = EnumProcesses(); while (*(int*)procList->szExeFile) { if (contains_string_optimized((const TCHAR*)procList->szExeFile, (const TCHAR*)procName)){ return procList->th32ProcessID; } procList++; } return NULL; } int _tmain(int argc, _TCHAR* argv[]) { TCHAR* szDllPath = L"C:\\Users\\dty\\Desktop\\IATHOOKbyDLL.dll"; printf("Hello...\n"); OutputDebugString(L"[+] -----"); HANDLE processId = (HANDLE)gethProcessByName(L"IATHookTarget"); if (processId == NULL){ printf("没有找到进程...\n"); return NULL; } HANDLE hProcess = OpenProcess( PROCESS_VM_OPERATION | // 内存操作权限 PROCESS_VM_WRITE | // 写入内存权限 PROCESS_CREATE_THREAD | // 创建远程线程权限(关键) PROCESS_QUERY_INFORMATION, // 查询进程信息权限 FALSE, // 不继承句柄 (DWORD)processId // 目标进程ID ); if (hProcess == NULL) { DWORD err = GetLastError(); // 处理错误... } LPVOID pRemoteMem = VirtualAllocEx((HANDLE)hProcess, NULL, (wcslen(szDllPath) + 1) * sizeof(WCHAR), MEM_COMMIT , PAGE_READWRITE); WriteProcessMemory(hProcess, pRemoteMem, szDllPath, (wcslen(szDllPath) + 1) * sizeof(WCHAR), NULL); HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(L"kernel32.dll"),"LoadLibraryW") , pRemoteMem,0,NULL ); if (hThread == NULL) { DWORD err = GetLastError(); // 处理错误... } printf("%0X\n",hThread); WaitForSingleObject(hThread,INFINITE); system("pause"); return 0; }
-
- 我们的DLL里 对IAT表处理,将要hook的函数换成我们的函数地址,然后我们的函数里调用原来的函数
- 首先 根据DLL名称和函数名词遍历导入表 获取存放函数地址的地址(IAT表项的地址)
- 定义我们的函数
- 参数和调用方式要和原来的函数一致,然后对参数拦截然后调用原来的函数
- 修改IAT表
- 首先把IAT表变成可写的
- 将我们得函数地址写到IAT表项里,这里注意 第一步获取的是IAT表项的地址 (函数地址的地址)
- 编译后用注入程序注入进去
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include <stdio.h>
typedef int(WINAPI* MessageBoxW_Type)(HWND,LPCWSTR,LPCWSTR,UINT);
MessageBoxW_Type OriginalMessageBoxW = nullptr;
FARPROC* targetAddr;//指向IAT表项 存放函数地址的那个地址
FARPROC* FindIATEntryAddress(LPCSTR szDllName, LPCSTR szFuncName)
{
// 获取当前模块基地址
HMODULE hModule = GetModuleHandle(NULL);
if (!hModule)
return NULL;
// 解析PE头结构
PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
if (pDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
return NULL;
PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)hModule + pDosHeader->e_lfanew);
if (pNtHeaders->Signature != IMAGE_NT_SIGNATURE)
return NULL;
// 获取导入表信息
IMAGE_DATA_DIRECTORY importDir = pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
if (importDir.VirtualAddress == 0 || importDir.Size == 0)
return NULL;
// 遍历导入描述符
PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE*)hModule + importDir.VirtualAddress);
while (pImportDesc->Name)
{
// 获取DLL名称并比较
LPCSTR currentDllName = (LPCSTR)((BYTE*)hModule + pImportDesc->Name);
OutputDebugString(L"[+] DLL名称:");
OutputDebugStringA(currentDllName);
if (_stricmp(currentDllName, szDllName) == 0)
{
// 获取导入名称表(INT)和导入地址表(IAT)
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((BYTE*)hModule +
(pImportDesc->OriginalFirstThunk ?
pImportDesc->OriginalFirstThunk :
pImportDesc->FirstThunk));
// 计算IAT项地址
ULONG_PTR* pIatEntry = (ULONG_PTR*)((BYTE*)hModule + pImportDesc->FirstThunk);
// 遍历函数列表
while (pThunk->u1.AddressOfData)
{
// 检查是否为名称导入
if (!(pThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG))
{
PIMAGE_IMPORT_BY_NAME pImport = (PIMAGE_IMPORT_BY_NAME)(
(BYTE*)hModule + pThunk->u1.AddressOfData);
OutputDebugString(L"[+] 函数名称:");
OutputDebugStringA(pImport->Name);
// 比较函数名称
if (strcmp(pImport->Name, szFuncName) == 0)
{
OutputDebugString(L"[+] 函数名称比对成功-----------");
// 返回IAT项的地址
return (FARPROC*)pIatEntry;
}
}
pThunk++;
pIatEntry++;
}
}
pImportDesc++;
}
return NULL;
}
//我们的函数
//
int WINAPI HookedMessageBoxW(HWND hwnd,LPCWSTR lpText,LPCWSTR lpCaption,UINT uType){
OutputDebugString(L"[+] MessageBoxA被拦截");
DWORD rtn= OriginalMessageBoxW(hwnd, L"内容已被修改", lpCaption, uType);
//卸载hook
//OriginalMessageBoxW = (MessageBoxW_Type)*targetAddr;
*targetAddr = (FARPROC)OriginalMessageBoxW;
return rtn;
}
void* Hook(HMODULE hModule, LPCSTR Dllname, LPCSTR FunName, PROC HookedFun, PROC* OriginFun){
OutputDebugString(L"[+] DLL已经注入-----");
targetAddr = FindIATEntryAddress(Dllname, FunName);
if (!targetAddr){
OutputDebugString(L"[+] 获取函数地址失败-----");
}
// 在修改内存前添加权限修改
DWORD oldProtect = 0;
if (!VirtualProtect(targetAddr, sizeof(FARPROC), PAGE_READWRITE, &oldProtect)) {
OutputDebugString(L"[-] 修改内存权限失败");
return NULL;
}
WCHAR debugMsg[128];
swprintf_s(debugMsg, L"[+] 修改前函数地址: 0x%p", (void*)*targetAddr);
OutputDebugString(debugMsg);
// 保存原来的函数的地址
//将IAT表项的值修改成我们的函数地址
OriginalMessageBoxW = (MessageBoxW_Type)*targetAddr;
*targetAddr = (FARPROC)&HookedMessageBoxW;
WCHAR debugMsg1[128];
swprintf_s(debugMsg1, L"[+] 修改后函数地址: 0x%p", (void*)*targetAddr);
OutputDebugString(debugMsg1);
// 恢复原始保护属性(可选)
//VirtualProtect(targetAddr, sizeof(FARPROC), oldProtect, &oldProtect);
return NULL;
}
BOOL APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
Hook(GetModuleHandle(NULL), "user32.dll", "MessageBoxW", (PROC)HookedMessageBoxW, (PROC*)&OriginalMessageBoxW);
break;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}
效果

hook后

浙公网安备 33010602011771号