高级全局API钩取 - IE连接控制
@author: dlive
@date: 2017/02/14
0x01 调试IE进程
常见网络连接库:ws2_32.dll(套接字),wininet.dll,winhttp.dll
使用Process Explorer查看IE加载的DLL
IE不仅加载了ws2_32.dll还加载了wininet.dll,wininet.dll中提供的API中有个名为InternetConnect()的API,这个API用来连接网站。
HINTERNET InternetConnect(
_In_ HINTERNET hInternet,
_In_ LPCTSTR lpszServerName,
_In_ INTERNET_PORT nServerPort,
_In_ LPCTSTR lpszUsername,
_In_ LPCTSTR lpszPassword,
_In_ DWORD dwService,
_In_ DWORD dwFlags,
_In_ DWORD_PTR dwContext
);
使用OD附加IE进程,但是发现IE有两个进程,不知道该附加哪个,那就都附加上。
在wininet!InternetConnect起始处下断点,使用IE访问www.zhihu.com
可以看到OD断在InternetConnect函数开始处,修改栈上的www.zhihu.com为www.163.com,然后去掉断点
可以看到最后访问的网站是www.163.com
0x02 IE的进程结构
IE的每个选项卡对应一个进程,统一由一个父进程管理。所以钩取API时需要使用全局钩取。
这里通过钩取ntdll!ZwResumeThread钩取子进程
0x03 全局钩取ntdll!ResumeThread API
因为最终目的是控制IE的网络连接,所以dll注入时仅需向所有的iexplore.exe进程中注入即可,无需对其他无关进程注入dll。
1.DllMain
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");
//为了防止在Dll注入时wininet.dll还未被加载,所以手动加载一下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;
}
2.NewInternetConnectW
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;
}
//修改原API调用时的第二个参数
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;
}
3.NewZwResumeThread
//ThreadHandle是要恢复运行的线程的句柄(即子进程的主线程)
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;
}
// 调用ntdll!ZwQueryInformationThread(),通过线程句柄获取其对应进程PID
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;
}
//子进程PID
dwPID = (DWORD)tbi.ClientId.UniqueProcess;
if ( (dwPID != GetCurrentProcessId()) && (dwPID != dwPrevPID) )
{
DebugLog("NewZwResumeThread() => call InjectDll()\n");
dwPrevPID = dwPID;
// change privilege
// 打开SeDebugPrivilege特权
if( !SetPrivilege(SE_DEBUG_NAME, TRUE) )
DebugLog("NewZwResumeThread() : SetPrivilege() failed!!!\n");
// 获取要注入的dll的路径
GetModuleFileName(GetModuleHandle(STR_MODULE_NAME),
szModPath,
MAX_PATH);
// 注入dll
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;
}
高级全局API钩取 - IE连接控制的更多相关文章
- x64 下记事本WriteFile() API钩取
<逆向工程核心原理>第30章 记事本WriteFile() API钩取 原文是在x86下,而在x64下函数调用方式为fastcall,前4个参数保存在寄存器中.在原代码基础上进行修改: 1 ...
- 调试钩取技术 - 记事本WriteFile() API钩取
@author: dlive 0x01 简介 本章将讲解前面介绍过的调试钩取技术,钩取记事本的kernel32!WriteFile() API 调试钩取技术能进行与用户更具有交互性(interacti ...
- c#使用easyhook库进行API钩取
目标:使calc程序输入的数自动加1 (当别人使用时,总会得不到正确的结果,哈哈) 编写注入程序 ————————————————————————————————— class Program中的方法 ...
- 通过注入DLL修改API代码实现钩取(一)
通过注入DLL修改API代码实现钩取(一) Ox00 大致思路 通过CreateRemoteThread函数开辟新线程,并将DLL注入进去 通过GetProcessAddress函数找到需钩取的API ...
- 通过注入DLL后使用热补丁钩取API
通过注入DLL后使用热补丁钩取API 0x00 对比修改API的前五个字节钩取API 对前一种方法钩取API的流程梳理如下: 注入相应的DLL 修改原始AI的函数的前五个字节跳往新函数(钩取API) ...
- 通过调试对WriteFile()API的钩取
通过调试对WriteFile()API的钩取 0x00 目标与思路 目标:钩取指定的notepad.exe进程writeFile()API函数,对notepad.exe进程的写入的字符保存时保存为大写 ...
- 利用 Java 操作 Jenkins API 实现对 Jenkins 的控制详解
本文转载自利用 Java 操作 Jenkins API 实现对 Jenkins 的控制详解 导语 由于最近工作需要利用 Jenkins 远程 API 操作 Jenkins 来完成一些列操作,就抽空研究 ...
- 《逆向工程核心原理》Windows消息钩取
DLL注入--使用SetWindowsHookEx函数实现消息钩取 MSDN: SetWindowsHookEx Function The SetWindowsHookEx function inst ...
- Vue基础(环境配置、内部指令、全局API、选项、内置组件)
1.环境配置 安装VsCode 安装包管理工具:直接下载 NodeJS 进行安装即可,NodeJS自带 Npm 包管理工具,下载地址:https://nodejs.org/en/download/安装 ...
随机推荐
- 24-webhost的配置
1-新建asp.net core空项目 2-创建setting.json文件 3- 配制Progrom类中CreateWebHostBuilder 4-获取配置的文件 5-显示结果
- 4 . GET方法实现文章分类
复习:博客站点 <!DOCTYPE html> {% load staticfiles %} <html> <head> <meta charset=&quo ...
- 1911: [Apio2010]特别行动队(斜率优化)
链接 思路 斜率优化dp. 代码 #include<cstdio> #include<algorithm> #include<cstring> #include&l ...
- MySQL之查询性能优化(二)
查询执行的基础 当希望MySQL能够以更高的性能运行查询时,最好的办法就是弄清楚MySQL是如何优化和执行查询的.MySQL执行一个查询的过程,根据图1-1,我们可以看到当向MySQL发送一个请求时, ...
- Java-数据结构之二叉树练习
本来这个随笔应该在4月17号就应该发出来的.不巧的是,那天晚上收到了offer,然后接下去两天为入职到处跑,20号入职后一直忙,直到最近几天才有时间看看书.然而20多天前就看完的了二叉树,然后17号那 ...
- CentOS 7 安装Oracle 11gR2
概述 Oracle 在Linux和window上的安装不太一样,公司又是Linux系统上的Oracle,实在没辙,研究下Linux下Oracle的使用,oracle默认不支持CentOS系统安装,所以 ...
- 腾讯QQ空间穿越时光轴3D特效
<DOCTYPE html> <html> <head> <title>腾讯QQ空间穿越光轴3D特效</title> <style&g ...
- 《Cracking the Coding Interview》——第4章:树和图——题目8
2014-03-19 05:04 题目:给定两棵二叉树T1和T2,判断T2是否是T1的子树.子树的定义是,以T1的某个节点(可以是T1的根)作为根节点,得到的这棵树和T2一模一样. 解法:首先可以根据 ...
- python3 打印九九乘法口诀表
for i in range(1, 10): for j in range(1, i+1): # print(f'{i}×{j}={i*j}', end='\t') print('%d×%d=%d' ...
- 基于vue 2.X和高德地图的vue-amap组件获取经纬度
今天我就讲了一下怎么通过vue和高德地图开发的vue-amap组件来获取经纬度. 这是vue-amap的官网文档:https://elemefe.github.io/vue-amap/#/ 这是我的码 ...