高级全局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/安装 ...
随机推荐
- C语言进阶——循环语句07
循环语句的基本工作方式: 通过条件表达式判定是否执行循环体 条件表达式遵循if语句表达式的原则 do,while,for的区别: do语句先执行后判断,循环体至少执行一次 while语句先判断后执行, ...
- 笔记-python-standard library-17.7 queue
笔记-python-standard library-17.7 queue 1. queue source code:Lib/queue.py 该模块实现了多生产者,多消费者队列. 此模块实现了所有 ...
- js双轴柱状图
<!doctype html><html lang="en"><head> <script type="text/javascr ...
- (A)eclipse搭建springboot项目入门
网上许多资料都是用idea的,但是我个人用eclipse习惯了,所以就在eclipse里面自己尝试着写了一个hello. 然而项目建好后却迟迟不能访问!!!网上搜了许多资料都不靠谱! 虽然最后能看到h ...
- 四大关键步骤掌握CloudOps模型
[TechTarget中国原创] 要让IT运维向云演进,企业必须拥抱自动化,并且改变资源预配的思考方式. 新涌现的术语CloudOps——云运维的简写,指代企业如何运行以及管理基于云的系统.并且,随着 ...
- Erlang中常用的类型转换[转]
转自: http://blog.sina.com.cn/s/blog_53a5047b01018yqv.html 例子 结果 atom_to_list(hello). "hello" ...
- 架构师速成7.3-devops为什么很重要 分类: 架构师速成 2015-07-07 17:22 410人阅读 评论(0) 收藏
evops是一个很高大上的名字,其实说的简单点就是开发和运维本身就是一个团队的,要干就一起把事情干好.谁出了问题,网站都不行.作为一个架构师,必须要devops,而且要知道如何推行devops. 首先 ...
- phpStorm9.0 +xampp+chrome php调试环境配置!
不多说,直接上step by step: 1.xampp配置 看看我的XAMPP版本: 修改配置文件,该打开打开,该加上加上,结果如下(当前需要重新启动apache,配置才会生效): [XDebug] ...
- jmeter察看结果树响应数据中文乱码解决办法
1.到jmeter目录文件中bin文件夹下找到jmeter.properties文件,该文件为jmeter配置文件.使用编辑工具打开它. 2.找到 #sampleresult.default.e ...
- day06_06 字典操作01
1.0 字典操作 dic1 = {'name':'alex'} dic1['age'] = 18 print(dic1) #>>>{'age': 18, 'name': 'alex' ...