@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连接控制的更多相关文章

  1. x64 下记事本WriteFile() API钩取

    <逆向工程核心原理>第30章 记事本WriteFile() API钩取 原文是在x86下,而在x64下函数调用方式为fastcall,前4个参数保存在寄存器中.在原代码基础上进行修改: 1 ...

  2. 调试钩取技术 - 记事本WriteFile() API钩取

    @author: dlive 0x01 简介 本章将讲解前面介绍过的调试钩取技术,钩取记事本的kernel32!WriteFile() API 调试钩取技术能进行与用户更具有交互性(interacti ...

  3. c#使用easyhook库进行API钩取

    目标:使calc程序输入的数自动加1 (当别人使用时,总会得不到正确的结果,哈哈) 编写注入程序 ————————————————————————————————— class Program中的方法 ...

  4. 通过注入DLL修改API代码实现钩取(一)

    通过注入DLL修改API代码实现钩取(一) Ox00 大致思路 通过CreateRemoteThread函数开辟新线程,并将DLL注入进去 通过GetProcessAddress函数找到需钩取的API ...

  5. 通过注入DLL后使用热补丁钩取API

    通过注入DLL后使用热补丁钩取API 0x00 对比修改API的前五个字节钩取API 对前一种方法钩取API的流程梳理如下: 注入相应的DLL 修改原始AI的函数的前五个字节跳往新函数(钩取API) ...

  6. 通过调试对WriteFile()API的钩取

    通过调试对WriteFile()API的钩取 0x00 目标与思路 目标:钩取指定的notepad.exe进程writeFile()API函数,对notepad.exe进程的写入的字符保存时保存为大写 ...

  7. 利用 Java 操作 Jenkins API 实现对 Jenkins 的控制详解

    本文转载自利用 Java 操作 Jenkins API 实现对 Jenkins 的控制详解 导语 由于最近工作需要利用 Jenkins 远程 API 操作 Jenkins 来完成一些列操作,就抽空研究 ...

  8. 《逆向工程核心原理》Windows消息钩取

    DLL注入--使用SetWindowsHookEx函数实现消息钩取 MSDN: SetWindowsHookEx Function The SetWindowsHookEx function inst ...

  9. Vue基础(环境配置、内部指令、全局API、选项、内置组件)

    1.环境配置 安装VsCode 安装包管理工具:直接下载 NodeJS 进行安装即可,NodeJS自带 Npm 包管理工具,下载地址:https://nodejs.org/en/download/安装 ...

随机推荐

  1. strak组件(5):为列表定制预留钩子方法

    效果图:  新增函数 def get_list_display(self): 获取页面上应该显示的列,预留的自定义扩展,例如:以后根据用户的不同显示不同的 一.stark组件 stark/servic ...

  2. [KMP][BZOJ1355][Baltic2009]Radio Transmission

    题面 Description 给你一个字符串,它是由某个字符串不断自我连接形成的. 但是这个字符串是不确定的,现在只想知道它的最短长度是多少. Input 第一行给出字符串的长度,\(1 < L ...

  3. ElasticSearch 环境安装

    1)官网安装教程: http://www.elasticsearch.org/guide/reference/setup/installation/   2)简单安装: http://log.medc ...

  4. 4 Django简介

    MVC与MTV模型 MVC Web服务器开发领域里著名的MVC模式,所谓MVC就是把Web应用分为模型(M),控制器(C)和视图(V)三层,他们之间以一种插件式的.松耦合的方式连接在一起,模型负责业务 ...

  5. WCF入门二[WCF的配置文件]

    一.概述 往往在很多项目中数据库连接字符串.变量和一些动态的加载类会写在配置文件中.WCF也会在配置文件中写入一些配置参数,比如服务的地址.服务用于发送和接收消息的传输和消息编码等,通过配置文件可以灵 ...

  6. C#学习你需要知道的---(For和Foreach)

    本文章由cartzhang编写,转载请注明出处. 所有权利保留. 文章链接:http://blog.csdn.net/cartzhang/article/details/52577283 作者:car ...

  7. Spring Boot :Request请求处理流程

    技术交流群:233513714

  8. Django的Field(字段)

    字段 1.models.AutoField 自增列 = int(11) 如果没有的话,默认会生成一个名称为 id 的列,如果要显示的自定义一个自增列,必须将给列设置为主键 primary_key=Tr ...

  9. Eclipse 窗口说明---Eclipse教程第03课

    Eclipse 工作台(Workbench) 首先,让我们来看一下Eclipse 作台用户界面,和它里面的各种组件. 工作台是多个窗口的集合.每个窗口包含菜单栏,工具栏,快捷方式栏,以及一个或者多个透 ...

  10. asp.net 常用几种下载方式

    protected void Button1_Click(object sender, EventArgs e) { /* 微软为Response对象提供了一个新的方法TransmitFile来解决使 ...