Loading... 创建DLL ![image.png](http://www.irohane.top/usr/uploads/2021/03/1165521676.png) ## 测试用弹框![image.png](http://www.irohane.top/usr/uploads/2021/03/285185591.png) ## IATHOOK IAT实现原理, 1. 首先确定是在哪一个DLL中的【某个函数】,GetModuleHandle/GetProcAddress得到该模块和该函数的基址。 2. 遍历目标程序的导入表,比对导入表中IAT 函数ul.Function地址和我们获取的地址是否相等。 3. 如果相等就修改目标程序的内存属性【如果不修改会导致页属性错误】。 4. 修改ul.Function原本的函数地址【将原本函数强转为DWORD类型地址】。 1. 注意:调用函数本来就是CALL一个地址,参数会先PUSH入栈,之后会CALL函数地址按照顺序 函数名就是地址。 IAT中有函数名字,也可以根据IAT中函数名来进行判断。 --- IATHook.h DLL动态链接库方式生成 DLL main 中 ``` case DLL_PROCESS_ATTACH: { //获取自己的句柄 LPVOID ExeBase = GetModuleHandle(0); IATHook((char*)ExeBase, (DWORD)MymessageBoxW, "MessageBoxW", "User32.dll"); break; } ``` IATHook.h ``` void IATHook(char* lpMoudel, DWORD FunAddress, const char* szTarFunName, const char* szTarDllName); int WINAPI MymessageBoxW ( HWND hwnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType ); ``` IATHook.cpp ``` #include "pch.h" #include "IATHook.h" #include <Windows.h> typedef int (WINAPI* MESSAGEBOX)( _In_opt_ HWND hWnd, _In_opt_ LPCWSTR lpText, _In_opt_ LPCWSTR lpCaption, _In_ UINT uType); MESSAGEBOX g_OldMessageBox; void IATHook(char* lpMoudel, DWORD FunAddress, const char* szTarFunName, const char* szTarDllName) { //获取导入表 PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)lpMoudel; PIMAGE_NT_HEADERS pNt = (PIMAGE_NT_HEADERS)(pDos->e_lfanew + lpMoudel); PIMAGE_DATA_DIRECTORY dwImportDir = &pNt->OptionalHeader.DataDirectory[1]; //获取导入表结构 PIMAGE_IMPORT_DESCRIPTOR pImportTab = (PIMAGE_IMPORT_DESCRIPTOR)(dwImportDir->VirtualAddress + lpMoudel); //开始解析导入表 while (pImportTab->Name!=NULL) { char* pDllName = (pImportTab->Name + lpMoudel); char* pbuf = new char[strlen(pDllName) + 1]{ 0 }; strcpy_s(pbuf, strlen(pDllName)+1, pbuf); _strlwr_s(pbuf, strlen(pDllName) + 1); if (szTarDllName != NULL) { if (strcmp(szTarDllName,pbuf)==0) { //得到目标函数的地址 HMODULE hModule = GetModuleHandleA(pDllName); //获取函数Messagebox 的地址 DWORD dwTarAddress = (DWORD)GetProcAddress(hModule, szTarDllName); //在IAT中寻找这个函数的地址 PIMAGE_THUNK_DATA32 pIat = (PIMAGE_THUNK_DATA32)(pImportTab->FirstThunk + lpMoudel); while (pIat->u1.Function!=0) { //比对两个地址是否相等 if (pIat->u1.Function = dwTarAddress) { //保存 原来的属性 g_OldMessageBox = (MESSAGEBOX)pIat->u1.Function; //修改Hook的属性 DWORD dwOldProctect = 0; VirtualProtect(&pIat->u1.Function, 4, PAGE_EXECUTE_READWRITE, &dwOldProctect); //如果地址相等就替换 pIat->u1.Function = FunAddress; VirtualProtect(&pIat->u1.Function, 4, dwOldProctect, &dwOldProctect); } pIat++; } } } pImportTab++; } } int WINAPI MymessageBoxW ( HWND hwnd, LPCWSTR lpText, LPCWSTR lpCaption, UINT uType ) { lpText = (wchar_t*)L"你被打劫了"; DWORD dwReturnCode = 0; dwReturnCode = g_OldMessageBox(hwnd, lpText, lpCaption, uType); return dwReturnCode; return 0; } ``` ## 注册表-HOOK ``` //写入DLL #include "windows.h" #include "tchar.h" #pragma comment(lib, "urlmon.lib") #define DEF_URL (L"http://www.naver.com/index.html") #define DEF_FILE_NAME (L"index.html") HMODULE g_hMod = NULL; DWORD WINAPI ThreadProc(LPVOID lParam) { TCHAR szPath[_MAX_PATH] = {0,}; if( !GetModuleFileName( g_hMod, szPath, MAX_PATH ) ) return FALSE; TCHAR *p = _tcsrchr( szPath, '\\' ); if( !p ) return FALSE; _tcscpy_s(p+1, _MAX_PATH, DEF_FILE_NAME); URLDownloadToFile(NULL, DEF_URL, szPath, 0, NULL); return 0; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { HANDLE hThread = NULL; g_hMod = (HMODULE)hinstDLL; switch( fdwReason ) { case DLL_PROCESS_ATTACH : OutputDebugString(L"<myhack.dll> Injection!!!"); hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); CloseHandle(hThread); break; } return TRUE; } #include "windows.h" #include "tchar.h" #pragma comment(lib, "urlmon.lib") #define DEF_URL (L"http://www.naver.com/index.html") #define DEF_FILE_NAME (L"index.html") HMODULE g_hMod = NULL; DWORD WINAPI ThreadProc(LPVOID lParam) { TCHAR szPath[_MAX_PATH] = {0,}; if( !GetModuleFileName( g_hMod, szPath, MAX_PATH ) ) return FALSE; TCHAR *p = _tcsrchr( szPath, '\\' ); if( !p ) return FALSE; _tcscpy_s(p+1, _MAX_PATH, DEF_FILE_NAME); URLDownloadToFile(NULL, DEF_URL, szPath, 0, NULL); return 0; } BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { HANDLE hThread = NULL; g_hMod = (HMODULE)hinstDLL; switch( fdwReason ) { case DLL_PROCESS_ATTACH : OutputDebugString(L"<myhack.dll> Injection!!!"); hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL); CloseHandle(hThread); break; } return TRUE; } ``` ## 提权代码 ``` void systemUp() { HANDLE hToken = NULL; HANDLE hProcess = GetCurrentProcess();//该函数获取该进程的伪句柄 //权限可以填入 TOKEN_ALL_ACCESS 全部权限打开 OpenProcessToken(hProcess, TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);//打开自己进程的锁,hToken 返回的是信息的结构体 //记录的信息的结构体 TOKEN_PRIVILEGES tp = { 0 }; //查看进程里面的特权信息 返回值FALSE 失败 LookupPrivilegeValue(0, SE_SHUTDOWN_NAME, &tp.Privileges[0].Luid); tp.PrivilegeCount = 1; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //调用函数提升权限 调节进程的权限 AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(tp), NULL, NULL); } bool SysTemUp() { HANDLE hToken; LUID Luid; TOKEN_PRIVILEGES tp; if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))return FALSE; if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &Luid)) { CloseHandle(hToken); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = Luid; tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; if (!AdjustTokenPrivileges(hToken, false, &tp, sizeof(tp), NULL, NULL)) { CloseHandle(hToken); return FALSE; } CloseHandle(hToken); return TRUE; } ``` ## inlineHook ``` // dllmain.cpp : 定义 DLL 应用程序的入口点。 #include "stdafx.h" #include <TlHelp32.h> // 通过进程名获取进程id DWORD GetPid(const wchar_t* filePath); // 获取helloworld程序pid DWORD g_dwPid = GetPid(L"test.exe"); // 旧的函数地址 DWORD* g_pOldAddr = (DWORD*)OpenProcess; // 旧的函数数据 char g_oldCode[5] = {}; void OnHook(); void UnHook(); // 编写自己的OpenProcess函数 HANDLE WINAPI MyOpenProcess( _In_ DWORD dwDesiredAccess, _In_ BOOL bInheritHandle, _In_ DWORD dwProcessId ) { // 比对pid是否与helloworld程序相等 if (dwProcessId == g_dwPid) return false; else { // 如果不相等,重新调用原来的OpenProcess函数 // 先恢复原来函数数据 UnHook(); HANDLE hProcess = OpenProcess( dwDesiredAccess, bInheritHandle, dwProcessId); // 调用完之后重新hook OnHook(); return hProcess; } } BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { OnHook(); MessageBox(NULL, L"注入成功", L"提示", NULL); break; } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; } void OnHook() { // 1.先保存OpenProcess原来的数据 memcpy(g_oldCode, g_pOldAddr, 5); // 2.设置新的指令,jmp char opcode[5] = { 0xE9 }; // 2.1 计算偏移并赋值 因为是小端方式存储最先的看到的其实是最后 计算的所以要-5 *(DWORD*)((DWORD)opcode + 1) = (DWORD)MyOpenProcess - (DWORD)OpenProcess - 5; // 3.修改保护属性 DWORD dwOldProtect = 0; VirtualProtect(g_pOldAddr, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect); // 4.写入跳转指令 memcpy(g_pOldAddr, opcode, 5); // 5.还原保护属性 VirtualProtect(g_pOldAddr, 5, dwOldProtect, &dwOldProtect); } void UnHook() { // 1.修改保护属性 DWORD dwOldProtect = 0; VirtualProtect(g_pOldAddr, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect); // 2.还原旧的指令数据 memcpy(g_pOldAddr, g_oldCode, 5); // 3.还原保护属性 VirtualProtect(g_pOldAddr, 5, dwOldProtect, &dwOldProtect); } DWORD GetPid(const wchar_t* szExeName) { // 创建进程快照 HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // 判断快照句柄是否有效 if (hSnapshot != INVALID_HANDLE_VALUE) { //定义进程结构体,第一个元素必须赋值为结构体大小 PROCESSENTRY32 stcPe32 = { sizeof(PROCESSENTRY32) }; //查找第一个进程 Process32First(hSnapshot, &stcPe32); do { // 如果进程名一致,返回进程id if (!wcscmp(stcPe32.szExeFile, szExeName)) return stcPe32.th32ProcessID; //查找下一个进程 } while (Process32Next(hSnapshot, &stcPe32)); //关闭快照句柄 CloseHandle(hSnapshot); } return -1; } ``` 最后修改:2021 年 03 月 29 日 © 允许规范转载 赞 0 如果觉得我的文章对你有用,请随意赞赏