逆向工程核心原理——第三十四章
高级全局API钩取:IE链接控制
在上一章,API钩取虽然成功了,但是重新打开任务管理器,进程又会显示出来。
为了解决这个问题,书本引出了”高级全局API“这个概念。
钩取常规API,我们需要在进程创建时钩取其API:
全局API钩取,则是在创建进程之前就钩取API:
相对于低级API钩取,高级API钩取虽然可以保证效果,但是并不是万能的。
几位下来我们利用实验,进行IE浏览器的全局API钩取:
首先,我们先了解一下IE浏览器(包括现在大部分的浏览器)的选下卡,为了实现这个选项卡功能,IE浏览器使用了父子进程的运行形式(所有的选项卡都是子程序):
因此我们只需要钩取父进程的ntdll!ZwResumeThread()API,那么子程序都会被自动钩取:
cmd显示钩取成功,我们添加新的选项卡,在processxp中查看子程序是否钩取成功:
子程序成功钩取,那么我们输入书上给出的地址,看看选项卡是否可以转跳到我们特定的地址:
(转跳过程太快,只能截图到已经转跳过后的图片)
最后附上代码:
InjDll.cpp
// 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 system
pe.dwSize = sizeof(PROCESSENTRY32);
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
if (hSnapshot == INVALID_HANDLE_VALUE)
{
_tprintf(L"GetProcName() : CreateToolhelp32Snapshot() failed!!! [%d]",
GetLastError());
return NULL;
}
// find process
bMore = 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 system
pe.dwSize = sizeof(PROCESSENTRY32);
hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPALL, NULL);
if (hSnapShot == INVALID_HANDLE_VALUE)
{
_tprintf(L"InjectDllToAll() : CreateToolhelp32Snapshot() failed!!! [%d]",
GetLastError());
return FALSE;
}
// find process
bMore = 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 Path
if (_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 Path
if (_taccess(szPath, 0) == -1)
{
_tprintf(L"There is no \"%s\" file!\n", szPath);
return FALSE;
}
// change privilege
if (!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.cpp
// 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;
}