逆向工程核心原理读书笔记-API钩取之IE浏览器连接控制
来源:互联网 发布:sql2000数据库快速备份 编辑:程序博客网 时间:2024/05/21 15:06
我们通过一个示例来练习钩取IE8的InternetConnect函数,用IE8连接指定网站时,使之连接到另一个网站。和以前钩取CreateProcess不同,这次我们钩取更低级的ZwResumeThread来实现全局API钩取。
我们来分析一下源代码,看看是怎么实现的。
InjDll.cpp源代码与DLL注入的代码基本结构类似。
// InjDll.cpp// reversecore@gmail.com// www.reversecore.com#include "windows.h"#include "stdio.h"#include "tlhelp32.h"#include "io.h"#include "tchar.h"enum {INJECTION_MODE = 0, EJECTION_MODE};BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; if( !OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { _tprintf(L"OpenProcessToken error: %u\n", GetLastError()); return FALSE; } if( !LookupPrivilegeValue(NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid) ) // receives LUID of privilege { _tprintf(L"LookupPrivilegeValue error: %u\n", GetLastError() ); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if( bEnablePrivilege ) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) { _tprintf(L"AdjustTokenPrivileges error: %u\n", GetLastError() ); return FALSE; } if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ) { _tprintf(L"The token does not have the specified privilege. \n"); return FALSE; } return TRUE;}BOOL IsVistaLater(){ OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); if( osvi.dwMajorVersion >= 6 ) return TRUE; return FALSE;}typedef DWORD (WINAPI *PFNTCREATETHREADEX)( PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, DWORD dwStackSize, DWORD dw1, DWORD dw2, LPVOID Unknown ); BOOL MyCreateRemoteThread( HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf){ HANDLE hThread = NULL; FARPROC pFunc = NULL; if( IsVistaLater() ) // Vista, 7, Server2008 { pFunc = GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtCreateThreadEx"); if( pFunc == NULL ) { _tprintf(L"MyCreateRemoteThread() : "\ L"GetProcAddress(\"NtCreateThreadEx\") failed!!! [%d]\n", GetLastError()); return FALSE; } ((PFNTCREATETHREADEX)pFunc)(&hThread, 0x1FFFFF, NULL, hProcess, pThreadProc, pRemoteBuf, FALSE, NULL, NULL, NULL, NULL); if( hThread == NULL ) { _tprintf(L"MyCreateRemoteThread() : NtCreateThreadEx() failed!!! [%d]\n", GetLastError()); return FALSE; } } else // 2000, XP, Server2003 { hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL); if( hThread == NULL ) { _tprintf(L"MyCreateRemoteThread() : CreateRemoteThread() failed!!! [%d]\n", GetLastError()); return FALSE; } }if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) ) { _tprintf(L"MyCreateRemoteThread() : WaitForSingleObject() failed!!! [%d]\n", GetLastError()); return FALSE; } return TRUE;}LPCTSTR GetProcName(DWORD dwPID){HANDLE hSnapshot = INVALID_HANDLE_VALUE;PROCESSENTRY32 pe; BOOL bMore = FALSE;// Get the snapshot of the systempe.dwSize = sizeof(PROCESSENTRY32);hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL); if( hSnapshot == INVALID_HANDLE_VALUE ) { _tprintf(L"GetProcName() : CreateToolhelp32Snapshot() failed!!! [%d]", GetLastError()); return NULL; }// find processbMore = Process32First(hSnapshot, &pe);for( ; bMore; bMore = Process32Next(hSnapshot, &pe) ){if( dwPID == pe.th32ProcessID ) { CloseHandle(hSnapshot); return pe.szExeFile; }}CloseHandle(hSnapshot); return NULL;}BOOL CheckDllInProcess(DWORD dwPID, LPCTSTR szDllPath){BOOL bMore = FALSE;HANDLE hSnapshot = INVALID_HANDLE_VALUE;MODULEENTRY32 me = { sizeof(me), };if( INVALID_HANDLE_VALUE == (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) ) { _tprintf(L"CheckDllInProcess() : CreateToolhelp32Snapshot(%d) failed!!! [%d]\n", dwPID, GetLastError()); return FALSE; }bMore = Module32First(hSnapshot, &me);for( ; bMore ; bMore = Module32Next(hSnapshot, &me) ){if( !_tcsicmp(me.szModule, szDllPath) || !_tcsicmp(me.szExePath, szDllPath) ) { CloseHandle(hSnapshot);return TRUE; }} CloseHandle(hSnapshot); return FALSE;}BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath){HANDLE hProcess = NULL; HANDLE hThread = NULL;LPVOID pRemoteBuf = NULL;DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);LPTHREAD_START_ROUTINE pThreadProc = NULL; BOOL bRet = FALSE; HMODULE hMod = NULL; DWORD dwDesiredAccess = 0; TCHAR szProcName[MAX_PATH] = {0,}; dwDesiredAccess = PROCESS_ALL_ACCESS; //dwDesiredAccess = MAXIMUM_ALLOWED;if ( !(hProcess = OpenProcess(dwDesiredAccess, FALSE, dwPID)) ) { _tprintf(L"InjectDll() : OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());goto INJECTDLL_EXIT; }pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); if( pRemoteBuf == NULL ) { _tprintf(L"InjectDll() : VirtualAllocEx() failed!!! [%d]\n", GetLastError()); goto INJECTDLL_EXIT; }if( !WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL) ) { _tprintf(L"InjectDll() : WriteProcessMemory() failed!!! [%d]\n", GetLastError()); goto INJECTDLL_EXIT; } hMod = GetModuleHandle(L"kernel32.dll"); if( hMod == NULL ) { _tprintf(L"InjectDll() : GetModuleHandle(\"kernel32.dll\") failed!!! [%d]\n", GetLastError()); goto INJECTDLL_EXIT; }pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW"); if( pThreadProc == NULL ) { _tprintf(L"InjectDll() : GetProcAddress(\"LoadLibraryW\") failed!!! [%d]\n", GetLastError()); goto INJECTDLL_EXIT; } if( !MyCreateRemoteThread(hProcess, pThreadProc, pRemoteBuf) ) { _tprintf(L"InjectDll() : MyCreateRemoteThread() failed!!!\n"); goto INJECTDLL_EXIT; } bRet = CheckDllInProcess(dwPID, szDllPath);INJECTDLL_EXIT: wsprintf(szProcName, L"%s", GetProcName(dwPID)); if( szProcName[0] == '\0' ) _tcscpy_s(szProcName, L"(no_process)"); _tprintf(L"%s(%d) %s!!! [%d]\n", szProcName, dwPID, bRet ? L"SUCCESS" : L"-->> FAILURE", GetLastError()); if( pRemoteBuf ) VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE); if( hThread ) CloseHandle(hThread); if( hProcess ) CloseHandle(hProcess);return bRet;}BOOL EjectDll(DWORD dwPID, LPCTSTR szDllPath){BOOL bMore = FALSE, bFound = FALSE, bRet = FALSE;HANDLE hSnapshot = INVALID_HANDLE_VALUE; HANDLE hProcess = NULL; HANDLE hThread = NULL;MODULEENTRY32 me = { sizeof(me), };LPTHREAD_START_ROUTINE pThreadProc = NULL; HMODULE hMod = NULL; DWORD dwDesiredAccess = 0; TCHAR szProcName[MAX_PATH] = {0,};if( INVALID_HANDLE_VALUE == (hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID)) ) { _tprintf(L"EjectDll() : CreateToolhelp32Snapshot(%d) failed!!! [%d]\n", dwPID, GetLastError()); goto EJECTDLL_EXIT; }bMore = Module32First(hSnapshot, &me);for( ; bMore ; bMore = Module32Next(hSnapshot, &me) ){if( !_tcsicmp(me.szModule, szDllPath) || !_tcsicmp(me.szExePath, szDllPath) ){bFound = TRUE;break;}}if( !bFound ){ _tprintf(L"EjectDll() : There is not %s module in process(%d) memory!!!\n", szDllPath, dwPID); goto EJECTDLL_EXIT;} dwDesiredAccess = PROCESS_ALL_ACCESS;if( !(hProcess = OpenProcess(dwDesiredAccess, FALSE, dwPID)) ){_tprintf(L"EjectDll() : OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());goto EJECTDLL_EXIT;} hMod = GetModuleHandle(L"kernel32.dll"); if( hMod == NULL ) { _tprintf(L"EjectDll() : GetModuleHandle(\"kernel32.dll\") failed!!! [%d]\n", GetLastError()); goto EJECTDLL_EXIT; }pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "FreeLibrary"); if( pThreadProc == NULL ) { _tprintf(L"EjectDll() : GetProcAddress(\"FreeLibrary\") failed!!! [%d]\n", GetLastError()); goto EJECTDLL_EXIT; } if( !MyCreateRemoteThread(hProcess, pThreadProc, me.modBaseAddr) ) { _tprintf(L"EjectDll() : MyCreateRemoteThread() failed!!!\n"); goto EJECTDLL_EXIT; } bRet = TRUE;EJECTDLL_EXIT: _tcscpy_s(szProcName, GetProcName(dwPID)); _tprintf(L"%s(%d) %s!!! [%d]\n", szProcName, dwPID, bRet ? L"SUCCESS" : L"-->> FAILURE", GetLastError()); if( hThread ) CloseHandle(hThread); if( hProcess ) CloseHandle(hProcess); if( hSnapshot != INVALID_HANDLE_VALUE ) CloseHandle(hSnapshot);return bRet;}BOOL InjectDllToAll(int nMode, LPCTSTR szDllPath){DWORD dwPID = 0;HANDLE hSnapShot = INVALID_HANDLE_VALUE;PROCESSENTRY32 pe; BOOL bMore = FALSE;// Get the snapshot of the systempe.dwSize = sizeof(PROCESSENTRY32);hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL); if( hSnapShot == INVALID_HANDLE_VALUE ) { _tprintf(L"InjectDllToAll() : CreateToolhelp32Snapshot() failed!!! [%d]", GetLastError()); return FALSE; }// find processbMore = Process32First(hSnapShot, &pe);for( ; bMore; bMore = Process32Next(hSnapShot, &pe) ){dwPID = pe.th32ProcessID; if( dwPID < 100 || !_tcsicmp(pe.szExeFile, L"smss.exe") || !_tcsicmp(pe.szExeFile, L"csrss.exe") ) { _tprintf(L"%s(%d) => System Process... DLL %s is impossible!\n", pe.szExeFile, dwPID, nMode==INJECTION_MODE ? L"Injection" : L"Ejection"); continue; } if( nMode == INJECTION_MODE ) InjectDll(dwPID, szDllPath); else EjectDll(dwPID, szDllPath);}CloseHandle(hSnapShot);return TRUE;}BOOL InjectDllToOne(LPCTSTR szProc, int nMode, LPCTSTR szDllPath){ int i = 0, nLen = (int)_tcslen(szProc);DWORD dwPID = 0;HANDLE hSnapShot = INVALID_HANDLE_VALUE;PROCESSENTRY32 pe; BOOL bMore = FALSE; // check if ProcName or PID for(i = 0; i < nLen; i++) if( !_istdigit(szProc[i]) ) break; if( i == nLen ) // PID { dwPID = (DWORD)_tstol(szProc); if( nMode == INJECTION_MODE ) InjectDll(dwPID, szDllPath); else EjectDll(dwPID, szDllPath); } else // ProcName { // Get the snapshot of the system pe.dwSize = sizeof(PROCESSENTRY32); hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL); if( hSnapShot == INVALID_HANDLE_VALUE ) { _tprintf(L"InjectDllToOne() : CreateToolhelp32Snapshot() failed!!! [%d]", GetLastError()); return FALSE; } // find process bMore = Process32First(hSnapShot, &pe); for( ; bMore; bMore = Process32Next(hSnapShot, &pe) ) { dwPID = pe.th32ProcessID; if( dwPID < 100 ) continue; if( !_tcsicmp(pe.szExeFile, szProc) ) { if( nMode == INJECTION_MODE ) InjectDll(dwPID, szDllPath); else EjectDll(dwPID, szDllPath); } } CloseHandle(hSnapShot); } return TRUE;}BOOL Initialize(LPCTSTR szOption, LPCTSTR szDllPath){ // check Option (Injection/Ejection) if( _tcsicmp(szOption, L"-i") && _tcsicmp(szOption, L"-e") ) return FALSE; // check DLL Pathif( _taccess(szDllPath, 0) == -1 ) return FALSE; return TRUE;}int _tmain(int argc, TCHAR *argv[]){ #define BUFSIZE (1024) int nMode = INJECTION_MODE; TCHAR szPath[BUFSIZE] = L""; if( (argc != 4) || ( _tcsicmp(argv[2], L"-i") && _tcsicmp(argv[2], L"-e")) ){ _tprintf(L"\n %s (Ver 1.1.1) - Dll Injection/Ejection Utility!!!\n"\ L" www.reversecore.com\n"\ L" reversecore@gmail.com\n"\ L"\n USAGE : %s <procname|pid|*> <-i|-e> <dll path>\n\n", argv[0], argv[0]);return 1;} if( !GetFullPathName(argv[3], BUFSIZE, szPath, NULL) ) { _tprintf(L"GetFullPathName() failed! [%d]", GetLastError()); return 1; } // check DLL Pathif( _taccess(szPath, 0) == -1 ) { _tprintf(L"There is no \"%s\" file!\n", szPath); return FALSE; }// change privilegeif( !SetPrivilege(SE_DEBUG_NAME, TRUE) ) return 1; // Mode (Injection/Ejection) if( !_tcsicmp(argv[2], L"-e") ) nMode = EJECTION_MODE; // Inject Dll if( !_tcsicmp(argv[1], L"*") ) InjectDllToAll(nMode, szPath); else InjectDllToOne(argv[1], nMode, szPath);return 0;}下面详细讲解redirect.dll的源代码(redirect.cpp)。
DLLMain的代码非常简单。若模块未加载就钩取其内部API,将导致失败。为防止出现这类问题,进程为iexplore.exe时,钩取InternetConnectW之前必须加载wininet.dll文件。
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){ char szCurProc[MAX_PATH] = {0,}; char *p = NULL; switch( fdwReason ) { case DLL_PROCESS_ATTACH : DebugLog("DllMain() : DLL_PROCESS_ATTACH\n"); GetModuleFileNameA(NULL, szCurProc, MAX_PATH); p = strrchr(szCurProc, '\\'); if( (p != NULL) && !_stricmp(p+1, "iexplore.exe") ) { DebugLog("DllMain() : current process is [iexplore.exe]\n"); // 钩取wininet!InternetConnectW() API之前 // 预先加载wininet.dll if( NULL == LoadLibrary(L"wininet.dll") ) { DebugLog("DllMain() : LoadLibrary() failed!!! [%d]\n", GetLastError()); } } // hook hook_by_code("ntdll.dll", "ZwResumeThread", (PROC)NewZwResumeThread, g_pZWRT); hook_by_code("wininet.dll", "InternetConnectW", (PROC)NewInternetConnectW, g_pICW); break; case DLL_PROCESS_DETACH : DebugLog("DllMain() : DLL_PROCESS_DETACH\n"); // unhook unhook_by_code("ntdll.dll", "ZwResumeThread", g_pZWRT); unhook_by_code("wininet.dll", "InternetConnectW", g_pICW); break; } return TRUE;}下面看看NewInternetConnect函数。函数的第二个参数lpszServerName字符串即是要连接的网站地址。监视该连接地址,IE连接特定网站时,就把连接地址修改为www.reversecore.com。
HINTERNET WINAPI NewInternetConnectW( HINTERNET hInternet, LPCWSTR lpszServerName, INTERNET_PORT nServerPort, LPCTSTR lpszUsername, LPCTSTR lpszPassword, DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext){ HINTERNET hInt = NULL; FARPROC pFunc = NULL; HMODULE hMod = NULL; // unhook if( !unhook_by_code("wininet.dll", "InternetConnectW", g_pICW) ) { DebugLog("NewInternetConnectW() : unhook_by_code() failed!!!\n"); return NULL; } // call original API hMod = GetModuleHandle(L"wininet.dll"); if( hMod == NULL ) { DebugLog("NewInternetConnectW() : GetModuleHandle() failed!!! [%d]\n", GetLastError()); goto __INTERNETCONNECT_EXIT; } pFunc = GetProcAddress(hMod, "InternetConnectW"); if( pFunc == NULL ) { DebugLog("NewInternetConnectW() : GetProcAddress() failed!!! [%d]\n", GetLastError()); goto __INTERNETCONNECT_EXIT; } if( !_tcsicmp(lpszServerName, L"www.naver.com") || !_tcsicmp(lpszServerName, L"www.daum.net") || !_tcsicmp(lpszServerName, L"www.nate.com") || !_tcsicmp(lpszServerName, L"www.yahoo.com") ) { DebugLog("[redirect] naver, daum, nate, yahoo => reversecore\n"); hInt = ((PFINTERNETCONNECTW)pFunc)(hInternet, L"www.reversecore.com", nServerPort, lpszUsername, lpszPassword, dwService, dwFlags, dwContext); } else { DebugLog("[no redirect]\n"); hInt = ((PFINTERNETCONNECTW)pFunc)(hInternet, lpszServerName, nServerPort, lpszUsername, lpszPassword, dwService, dwFlags, dwContext); }__INTERNETCONNECT_EXIT: // hook if( !hook_by_code("wininet.dll", "InternetConnectW", (PROC)NewInternetConnectW, g_pICW) ) { DebugLog("NewInternetConnectW() : hook_by_code() failed!!!\n"); } return hInt;}接下来分析NewZwResumeThread函数,它用来对ZwResumeThread进行全局钩取。先调用ZwQueryInformationThread获取子进程的PID,然后使用该PID注入redirect.dll文件,最后正常调用ZwResumeThread将子进程的主线程恢复运行。
NTSTATUS WINAPI NewZwResumeThread(HANDLE ThreadHandle, PULONG SuspendCount){ NTSTATUS status, statusThread; FARPROC pFunc = NULL, pFuncThread = NULL; DWORD dwPID = 0;static DWORD dwPrevPID = 0; THREAD_BASIC_INFORMATION tbi; HMODULE hMod = NULL; TCHAR szModPath[MAX_PATH] = {0,}; DebugLog("NewZwResumeThread() : start!!!\n"); hMod = GetModuleHandle(L"ntdll.dll"); if( hMod == NULL ) { DebugLog("NewZwResumeThread() : GetModuleHandle() failed!!! [%d]\n", GetLastError()); return NULL; } // call ntdll!ZwQueryInformationThread() pFuncThread = GetProcAddress(hMod, "ZwQueryInformationThread"); if( pFuncThread == NULL ) { DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]\n", GetLastError()); return NULL; } statusThread = ((PFZWQUERYINFORMATIONTHREAD)pFuncThread) (ThreadHandle, 0, &tbi, sizeof(tbi), NULL); if( statusThread != STATUS_SUCCESS ) { DebugLog("NewZwResumeThread() : pFuncThread() failed!!! [%d]\n", GetLastError()); return NULL; } dwPID = (DWORD)tbi.ClientId.UniqueProcess; if ( (dwPID != GetCurrentProcessId()) && (dwPID != dwPrevPID) ) { DebugLog("NewZwResumeThread() => call InjectDll()\n"); dwPrevPID = dwPID; // change privilege if( !SetPrivilege(SE_DEBUG_NAME, TRUE) ) DebugLog("NewZwResumeThread() : SetPrivilege() failed!!!\n"); // get injection dll path GetModuleFileName(GetModuleHandle(STR_MODULE_NAME), szModPath, MAX_PATH); if( !InjectDll(dwPID, szModPath) ) DebugLog("NewZwResumeThread() : InjectDll(%d) failed!!!\n", dwPID); } // call ntdll!ZwResumeThread() if( !unhook_by_code("ntdll.dll", "ZwResumeThread", g_pZWRT) ) { DebugLog("NewZwResumeThread() : unhook_by_code() failed!!!\n"); return NULL; } pFunc = GetProcAddress(hMod, "ZwResumeThread"); if( pFunc == NULL ) { DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]\n", GetLastError()); goto __NTRESUMETHREAD_END; } status = ((PFZWRESUMETHREAD)pFunc)(ThreadHandle, SuspendCount); if( status != STATUS_SUCCESS ) { DebugLog("NewZwResumeThread() : pFunc() failed!!! [%d]\n", GetLastError()); goto __NTRESUMETHREAD_END; }__NTRESUMETHREAD_END: if( !hook_by_code("ntdll.dll", "ZwResumeThread", (PROC)NewZwResumeThread, g_pZWRT) ) { DebugLog("NewZwResumeThread() : hook_by_code() failed!!!\n"); } DebugLog("NewZwResumeThread() : end!!!\n"); return status;}
完整的代码如下。
// redirect.cpp#include "windows.h"#include "wininet.h"#include "stdio.h"#include "tchar.h"#define STR_MODULE_NAME (L"redirect.dll")#define STATUS_SUCCESS(0x00000000L) typedef LONG NTSTATUS;typedef struct _CLIENT_ID {HANDLE UniqueProcess;HANDLE UniqueThread;} CLIENT_ID;typedef struct _THREAD_BASIC_INFORMATION {NTSTATUS ExitStatus;PVOID TebBaseAddress;CLIENT_ID ClientId;ULONG AffinityMask;LONG Priority;LONG BasePriority;} THREAD_BASIC_INFORMATION;typedef NTSTATUS (WINAPI *PFZWRESUMETHREAD)( HANDLE ThreadHandle, PULONG SuspendCount);typedef NTSTATUS (WINAPI *PFZWQUERYINFORMATIONTHREAD)( HANDLE ThreadHandle, ULONG ThreadInformationClass, PVOID ThreadInformation, ULONG ThreadInformationLength, PULONG ReturnLength);typedef HINTERNET (WINAPI *PFINTERNETCONNECTW)( HINTERNET hInternet, LPCWSTR lpszServerName, INTERNET_PORT nServerPort, LPCTSTR lpszUsername, LPCTSTR lpszPassword, DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext);BYTE g_pZWRT[5] = {0,};BYTE g_pICW[5] = {0,};void DebugLog(const char *format, ...){va_list vl;FILE *pf = NULL;char szLog[512] = {0,};va_start(vl, format);wsprintfA(szLog, format, vl);va_end(vl); OutputDebugStringA(szLog);}BOOL SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; if( !OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { DebugLog("OpenProcessToken error: %u\n", GetLastError()); return FALSE; } if( !LookupPrivilegeValue(NULL, // lookup privilege on local system lpszPrivilege, // privilege to lookup &luid) ) // receives LUID of privilege { DebugLog("LookupPrivilegeValue error: %u\n", GetLastError() ); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if( bEnablePrivilege ) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; // Enable the privilege or disable all privileges. if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) { DebugLog("AdjustTokenPrivileges error: %u\n", GetLastError() ); return FALSE; } if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ) { DebugLog("The token does not have the specified privilege. \n"); return FALSE; } return TRUE;}BOOL hook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PROC pfnNew, PBYTE pOrgBytes){FARPROC pFunc = NULL;DWORD dwOldProtect = 0, dwAddress = 0;BYTE pBuf[5] = {0xE9, 0, };PBYTE pByte = NULL; HMODULE hMod = NULL; hMod = GetModuleHandleA(szDllName); if( hMod == NULL ) { DebugLog("hook_by_code() : GetModuleHandle(\"%s\") failed!!! [%d]\n", szDllName, GetLastError()); return FALSE; }pFunc = (FARPROC)GetProcAddress(hMod, szFuncName); if( pFunc == NULL ) { DebugLog("hook_by_code() : GetProcAddress(\"%s\") failed!!! [%d]\n", szFuncName, GetLastError()); return FALSE; }pByte = (PBYTE)pFunc;if( pByte[0] == 0xE9 ) { DebugLog("hook_by_code() : The API is hooked already!!!\n");return FALSE; }if( !VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect) ) { DebugLog("hook_by_code() : VirtualProtect(#1) failed!!! [%d]\n", GetLastError()); return FALSE; }memcpy(pOrgBytes, pFunc, 5);dwAddress = (DWORD)pfnNew - (DWORD)pFunc - 5;memcpy(&pBuf[1], &dwAddress, 4);memcpy(pFunc, pBuf, 5);if( !VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect) ) { DebugLog("hook_by_code() : VirtualProtect(#2) failed!!! [%d]\n", GetLastError()); return FALSE; }return TRUE;}BOOL unhook_by_code(LPCSTR szDllName, LPCSTR szFuncName, PBYTE pOrgBytes){FARPROC pFunc = NULL;DWORD dwOldProtect = 0;PBYTE pByte = NULL; HMODULE hMod = NULL; hMod = GetModuleHandleA(szDllName); if( hMod == NULL ) { DebugLog("unhook_by_code() : GetModuleHandle(\"%s\") failed!!! [%d]\n", szDllName, GetLastError()); return FALSE; }pFunc = (FARPROC)GetProcAddress(hMod, szFuncName); if( pFunc == NULL ) { DebugLog("unhook_by_code() : GetProcAddress(\"%s\") failed!!! [%d]\n", szFuncName, GetLastError()); return FALSE; }pByte = (PBYTE)pFunc;if( pByte[0] != 0xE9 ) { DebugLog("unhook_by_code() : The API is unhooked already!!!"); return FALSE; }if( !VirtualProtect((LPVOID)pFunc, 5, PAGE_EXECUTE_READWRITE, &dwOldProtect) ) { DebugLog("unhook_by_code() : VirtualProtect(#1) failed!!! [%d]\n", GetLastError()); return FALSE; }memcpy(pFunc, pOrgBytes, 5);if( !VirtualProtect((LPVOID)pFunc, 5, dwOldProtect, &dwOldProtect) ) { DebugLog("unhook_by_code() : VirtualProtect(#2) failed!!! [%d]\n", GetLastError()); return FALSE; }return TRUE;}BOOL IsVistaLater(){ OSVERSIONINFO osvi; ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osvi); if( osvi.dwMajorVersion >= 6 ) return TRUE; return FALSE;}typedef DWORD (WINAPI *PFNTCREATETHREADEX)( PHANDLE ThreadHandle, ACCESS_MASK DesiredAccess, LPVOID ObjectAttributes, HANDLE ProcessHandle, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, BOOL CreateSuspended, DWORD dwStackSize, DWORD dw1, DWORD dw2, LPVOID Unknown ); BOOL MyCreateRemoteThread(HANDLE hProcess, LPTHREAD_START_ROUTINE pThreadProc, LPVOID pRemoteBuf){ HANDLE hThread = NULL; FARPROC pFunc = NULL; if( IsVistaLater() ) // Vista, 7, Server2008 { pFunc = GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtCreateThreadEx"); if( pFunc == NULL ) { DebugLog("MyCreateRemoteThread() : GetProcAddress() failed!!! [%d]\n", GetLastError()); return FALSE; } ((PFNTCREATETHREADEX)pFunc)(&hThread, 0x1FFFFF, NULL, hProcess, pThreadProc, pRemoteBuf, FALSE, NULL, NULL, NULL, NULL); if( hThread == NULL ) { DebugLog("MyCreateRemoteThread() : NtCreateThreadEx() failed!!! [%d]\n", GetLastError()); return FALSE; } } else // 2000, XP, Server2003 { hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL); if( hThread == NULL ) { DebugLog("MyCreateRemoteThread() : CreateRemoteThread() failed!!! [%d]\n", GetLastError()); return FALSE; } }if( WAIT_FAILED == WaitForSingleObject(hThread, INFINITE) ) { DebugLog("MyCreateRemoteThread() : WaitForSingleObject() failed!!! [%d]\n", GetLastError()); return FALSE; } return TRUE;}BOOL InjectDll(DWORD dwPID, LPCTSTR szDllPath){HANDLE hProcess = NULL; HANDLE hThread = NULL;LPVOID pRemoteBuf = NULL; DWORD dwBufSize = (DWORD)(_tcslen(szDllPath) + 1) * sizeof(TCHAR);LPTHREAD_START_ROUTINE pThreadProc = NULL; BOOL bRet = FALSE; HMODULE hMod = NULL;if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) ) { DebugLog("InjectDll() : OpenProcess(%d) failed!!! [%d]\n", dwPID, GetLastError());goto INJECTDLL_EXIT; }pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE); if( pRemoteBuf == NULL ) { DebugLog("InjectDll() : VirtualAllocEx() failed!!! [%d]\n", GetLastError()); goto INJECTDLL_EXIT; }if( !WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllPath, dwBufSize, NULL) ) { DebugLog("InjectDll() : WriteProcessMemory() failed!!! [%d]\n", GetLastError()); goto INJECTDLL_EXIT; } hMod = GetModuleHandle(L"kernel32.dll"); if( hMod == NULL ) { DebugLog("InjectDll() : GetModuleHandle() failed!!! [%d]\n", GetLastError()); goto INJECTDLL_EXIT; }pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryW"); if( pThreadProc == NULL ) { DebugLog("InjectDll() : GetProcAddress() failed!!! [%d]\n", GetLastError()); goto INJECTDLL_EXIT; } if( !MyCreateRemoteThread(hProcess, pThreadProc, pRemoteBuf) ) { DebugLog("InjectDll() : MyCreateRemoteThread() failed!!!\n"); goto INJECTDLL_EXIT; } bRet = TRUE;INJECTDLL_EXIT: if( pRemoteBuf ) VirtualFreeEx(hProcess, pRemoteBuf, 0, MEM_RELEASE); if( hThread ) CloseHandle(hThread); if( hProcess ) CloseHandle(hProcess);return bRet;}NTSTATUS WINAPI NewZwResumeThread(HANDLE ThreadHandle, PULONG SuspendCount){ NTSTATUS status, statusThread; FARPROC pFunc = NULL, pFuncThread = NULL; DWORD dwPID = 0;static DWORD dwPrevPID = 0; THREAD_BASIC_INFORMATION tbi; HMODULE hMod = NULL; TCHAR szModPath[MAX_PATH] = {0,}; DebugLog("NewZwResumeThread() : start!!!\n"); hMod = GetModuleHandle(L"ntdll.dll"); if( hMod == NULL ) { DebugLog("NewZwResumeThread() : GetModuleHandle() failed!!! [%d]\n", GetLastError()); return NULL; } // call ntdll!ZwQueryInformationThread() pFuncThread = GetProcAddress(hMod, "ZwQueryInformationThread"); if( pFuncThread == NULL ) { DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]\n", GetLastError()); return NULL; } statusThread = ((PFZWQUERYINFORMATIONTHREAD)pFuncThread) (ThreadHandle, 0, &tbi, sizeof(tbi), NULL); if( statusThread != STATUS_SUCCESS ) { DebugLog("NewZwResumeThread() : pFuncThread() failed!!! [%d]\n", GetLastError()); return NULL; } dwPID = (DWORD)tbi.ClientId.UniqueProcess; if ( (dwPID != GetCurrentProcessId()) && (dwPID != dwPrevPID) ) { DebugLog("NewZwResumeThread() => call InjectDll()\n"); dwPrevPID = dwPID; // change privilege if( !SetPrivilege(SE_DEBUG_NAME, TRUE) ) DebugLog("NewZwResumeThread() : SetPrivilege() failed!!!\n"); // get injection dll path GetModuleFileName(GetModuleHandle(STR_MODULE_NAME), szModPath, MAX_PATH); if( !InjectDll(dwPID, szModPath) ) DebugLog("NewZwResumeThread() : InjectDll(%d) failed!!!\n", dwPID); } // call ntdll!ZwResumeThread() if( !unhook_by_code("ntdll.dll", "ZwResumeThread", g_pZWRT) ) { DebugLog("NewZwResumeThread() : unhook_by_code() failed!!!\n"); return NULL; } pFunc = GetProcAddress(hMod, "ZwResumeThread"); if( pFunc == NULL ) { DebugLog("NewZwResumeThread() : GetProcAddress() failed!!! [%d]\n", GetLastError()); goto __NTRESUMETHREAD_END; } status = ((PFZWRESUMETHREAD)pFunc)(ThreadHandle, SuspendCount); if( status != STATUS_SUCCESS ) { DebugLog("NewZwResumeThread() : pFunc() failed!!! [%d]\n", GetLastError()); goto __NTRESUMETHREAD_END; }__NTRESUMETHREAD_END: if( !hook_by_code("ntdll.dll", "ZwResumeThread", (PROC)NewZwResumeThread, g_pZWRT) ) { DebugLog("NewZwResumeThread() : hook_by_code() failed!!!\n"); } DebugLog("NewZwResumeThread() : end!!!\n"); return status;}HINTERNET WINAPI NewInternetConnectW( HINTERNET hInternet, LPCWSTR lpszServerName, INTERNET_PORT nServerPort, LPCTSTR lpszUsername, LPCTSTR lpszPassword, DWORD dwService, DWORD dwFlags, DWORD_PTR dwContext){ HINTERNET hInt = NULL; FARPROC pFunc = NULL; HMODULE hMod = NULL; // unhook if( !unhook_by_code("wininet.dll", "InternetConnectW", g_pICW) ) { DebugLog("NewInternetConnectW() : unhook_by_code() failed!!!\n"); return NULL; } // call original API hMod = GetModuleHandle(L"wininet.dll"); if( hMod == NULL ) { DebugLog("NewInternetConnectW() : GetModuleHandle() failed!!! [%d]\n", GetLastError()); goto __INTERNETCONNECT_EXIT; } pFunc = GetProcAddress(hMod, "InternetConnectW"); if( pFunc == NULL ) { DebugLog("NewInternetConnectW() : GetProcAddress() failed!!! [%d]\n", GetLastError()); goto __INTERNETCONNECT_EXIT; } if( !_tcsicmp(lpszServerName, L"www.naver.com") || !_tcsicmp(lpszServerName, L"www.daum.net") || !_tcsicmp(lpszServerName, L"www.nate.com") || !_tcsicmp(lpszServerName, L"www.yahoo.com") ) { DebugLog("[redirect] naver, daum, nate, yahoo => reversecore\n"); hInt = ((PFINTERNETCONNECTW)pFunc)(hInternet, L"www.reversecore.com", nServerPort, lpszUsername, lpszPassword, dwService, dwFlags, dwContext); } else { DebugLog("[no redirect]\n"); hInt = ((PFINTERNETCONNECTW)pFunc)(hInternet, lpszServerName, nServerPort, lpszUsername, lpszPassword, dwService, dwFlags, dwContext); }__INTERNETCONNECT_EXIT: // hook if( !hook_by_code("wininet.dll", "InternetConnectW", (PROC)NewInternetConnectW, g_pICW) ) { DebugLog("NewInternetConnectW() : hook_by_code() failed!!!\n"); } return hInt;}BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved){ char szCurProc[MAX_PATH] = {0,}; char *p = NULL; switch( fdwReason ) { case DLL_PROCESS_ATTACH : DebugLog("DllMain() : DLL_PROCESS_ATTACH\n"); GetModuleFileNameA(NULL, szCurProc, MAX_PATH); p = strrchr(szCurProc, '\\'); if( (p != NULL) && !_stricmp(p+1, "iexplore.exe") ) { DebugLog("DllMain() : current process is [iexplore.exe]\n"); // 钩取wininet!InternetConnectW() API之前 // 预先加载wininet.dll if( NULL == LoadLibrary(L"wininet.dll") ) { DebugLog("DllMain() : LoadLibrary() failed!!! [%d]\n", GetLastError()); } } // hook hook_by_code("ntdll.dll", "ZwResumeThread", (PROC)NewZwResumeThread, g_pZWRT); hook_by_code("wininet.dll", "InternetConnectW", (PROC)NewInternetConnectW, g_pICW); break; case DLL_PROCESS_DETACH : DebugLog("DllMain() : DLL_PROCESS_DETACH\n"); // unhook unhook_by_code("ntdll.dll", "ZwResumeThread", g_pZWRT); unhook_by_code("wininet.dll", "InternetConnectW", g_pICW); break; } return TRUE;}
0 0
- 逆向工程核心原理读书笔记-API钩取之IE浏览器连接控制
- 逆向工程核心原理读书笔记-API钩取之IE浏览器连接控制
- 逆向工程核心原理读书笔记-API钩取之记事本小写转大写
- 逆向工程核心原理读书笔记-API钩取之计算器显示中文数字
- 逆向工程核心原理读书笔记-API钩取之隐藏进程(一)
- 逆向工程核心原理读书笔记-API钩取之隐藏进程(二)
- 逆向工程核心原理读书笔记-API钩取之记事本小写转大写
- 逆向工程核心原理读书笔记-API钩取之计算器显示中文数字
- 逆向工程核心原理读书笔记-API钩取之隐藏进程(一)
- 逆向工程核心原理读书笔记-API钩取之隐藏进程(二)
- 《逆向工程核心原理》<04-30> 通过Debug修改代码实现API钩取的技术
- 《逆向工程核心原理》<04-34> 高级全局API钩取
- 《逆向工程核心原理》<04-33> 通过DLL注入修改API代码实现API钩取的技术
- 逆向工程核心原理读书笔记-代码注入
- 逆向工程核心原理读书笔记-代码注入
- 《逆向工程核心原理》
- 《逆向工程核心原理》
- 逆向工程核心原理
- js获取table中的td宽度并赋值到另一个table的td中,实现宽度对齐
- oracle调用存储过程
- ios 在release时屏蔽掉NSlog()的几个方法
- 表头固定内容滚动【css笔记】
- 【C语言】LeetCode 152. Maximum Product Subarray
- 逆向工程核心原理读书笔记-API钩取之IE浏览器连接控制
- oracle存储过程调用游标例子
- Linux驱动--并发和竞争
- POJ 2431Expedition(优先队列解题)
- Android中实现滑动的七种方法
- Gradle实战系列(三)__多模块项目
- 报错:The specified child already has a parent. You must call removeView
- springIoc之注解方式
- Darwin Streaming Server程序结构分析