HOOK -- DLL的远程注入技术详解(1)
的远程注入技术是目前
Win32
病毒广泛使用的一种技术。使用这种技术的病毒体通常
位于一个
DLL
中,在系统启动的时候,一个
EXE
程序会将这个
DLL
加载至某些系统进程
(如
Explorer.exe
)中运行。
这样一来,普通的进程管理器就很难发现这种病毒了,而且
即使发现了也很难清除,因为只要病毒寄生的进程不终止运行,那么这个
DLL
就不会在内
存中卸载,用户也就无法在资源管理器中删除这个
DLL
文件,真可谓一箭双雕哉。
记得
2003
年
尾巴病毒肆虐的时候,
就已经有些尾巴病毒的变种在使用这种技术了。
到了
2004
年初,我曾经尝试着仿真了一个
尾巴病毒,但独是跳过了
DLL
的远程加载
技术。
直到最近在学校论坛上看到了几位朋友在探讨这一技术,
便忍不住将这一尘封已久的
技术从我的记忆中拣了出来,以满足广大的技术爱好者们。
必备知识
在阅读本文之前,你需要了解以下几个
API
函数:
·
OpenProcess
-
用于打开要寄生的目标进程。
·
VirtualAllocEx/VirtualFreeEx
-
用于在目标进程中分配
/
释放内存空间。
·
WriteProcessMemory
-
用于在目标进程中写入要加载的
DLL
名称。
·
CreateRemoteThread
-
远程加载
DLL
的核心内容,
用于控制目标进程调用
API
函数。
·
LoadLibrary
-
目标进程通过调用此函数来加载病毒
DLL
。
在此我只给出了简要的函数说明,关于函数的详细功能和介绍请参阅
MSDN
。
示例程序
我将在以下的篇幅中用一个简单的示例
Virus.exe
来实现这一技术。这个示例的界面如
下图:
首先运行
Target.exe
,这个文件是一个用
Win32
Application
向导生成的
“Hello,
Worl
d”
程序,用来作为寄生的目标进程。
然后在界面的编辑控件中输入进程的名称
“Target.exe”
,
单击
“
注入
DLL”
按钮,
这时候
V
irus.exe
就会将当前目录下的
DLL.dll
注入至
Target.exe
进程中。
在注入
DLL.dll
之后,你也可以单击
“
卸载
DLL”
来将已经注入的
DLL
卸载。
模拟的病毒体
DLL.dll
这是一个简单的
Win32
DLL
程序,它仅由一个入口函数
DllMain
组成:
BOOL
WINAPI
DllMain(
HINSTANCE
hinstDLL,
DWORD
fdwReason,
LPVOID
lpvRe
served
)
{switch
(
fdwReason
)
{
case
DLL_PROCESS_ATTACH:
{
MessageBox(
NULL,
_T("DLL
已进入目标进程。
"),
_T("
信息
"),
MB_ICONINFOR
MATION
);
}
break;
case
DLL_PROCESS_DETACH:
{
MessageBox(
NULL,
_T("DLL
已从目标进程卸载。
"),
_T("
信息
"),
MB_ICONINFO
RMATION
);
}
break;
}
return
TRUE;
}
如你所见,这里我在
DLL
被加载和卸载的时候调用了
MessageBox
,这是用来显示我
的远程注入
/
卸载工作是否成功完成。而对于一个真正的病毒体来说,它往往就是处理
DLL
_PROCESS_ATTACH
事件,在其中加入了启动病毒代码的部分:
case
DLL_PROCESS_ATTACH:
{
StartVirus();
}
break;
注入!
现在要开始我们的注入工作了。首先,我们需要找到目标进程:
DWORD
FindTarget(
LPCTSTR
lpszProcess
)
{
DWORD
dwRet
=
0;
HANDLE
hSnapshot
=
CreateToolhelp32Snapshot(
TH32CS_SNAPPROCESS,
0
);
PROCESSENTRY32
pe32;
pe32.dwSize
=
sizeof(
PROCESSENTRY32
);
Process32First(
hSnapshot,
&pe32
);
do
{
if
(
lstrcmpi(
pe32.szExeFile,
lpszProcess
)
==
0
)
{
dwRet
=
pe32.th32ProcessID;
break;
}
}
while
(
Process32Next(
hSnapshot,
&pe32
)
);
CloseHandle(
hSnapshot
);
return
dwRet;
}
这里我使用了
Tool
Help
函数库,当然如果你是
NT
系统的话,也可以选择
PSAPI
函
数库。
这段代码的目的就是通过给定的进程名称来在当前系统中查找相应的进程,
并返回该
进程的
ID
。得到进程
ID
后,就可以调用
OpenProcess
来打开目标进程了:
//
打开目标进程
HANDLE
hProcess
=
OpenProcess(
PROCESS_CREATE_THREAD
|
PROCESS_V
M_OPERATION
|
PROCESS_VM_WRITE,
FALSE,
dwProcessID
);
现在有必要说一下
OpenProcess
第一个参数所指定的三种权限。
在
Win32
系统下,
每
个进程都拥有自己的
4G
虚拟地址空间,
各个进程之间都相互独立。
如果一个进程需要完成
跨进程的工作的话,那么它必须拥有目标进程的相应操作权限。在这里,
PROCESS_CRE
ATE_THREAD
表示我可以通过返回的进程句柄在该进程中创建新的线程,也就是调用
Cr
eateRemoteThread
的权限;
同理,
PROCESS_VM_OPERATION
则表示在该进程中分配
/
释放内存的权限,也就是调用
VirtualAllocEx/VirtualFreeEx
的权限;
PROCESS_VM_WRI
TE
表示可以向该进程的地址空间写入数据,也就是调用
WriteProcessMemory
的权限。
至此目标进程已经打开,那么我们该如何来将
DLL
注入其中呢?在这之前,我请你看
一行代码,是如何在本进程内显式加载
DLL
的:
HMODULE
hDll
=
LoadLibrary(
"DLL.dll"
);
那么,
如果能控制目标进程调用
LoadLibrary
,
不就可以完成
DLL
的远程注入了么?的
确是这样,
我们可以通过
CreateRemoteThread
将
LoadLibrary
作为目标进程的一个线程来
启动,这样就可以完成
“
控制目标进程调用
LoadLibrary”
的工作了。到这里,也许你会想当
然地写下类似这样的代码:
DWORD
dwID;
LPVOID
pFunc
=
LoadLibraryA;
HANDLE
hThread
=
CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START
_ROUTINE)pFunc,
(LPVOID)"DLL.dll",
0,
&dwID
);
不过结果肯定会让你大失所望
——
注入
DLL
失败!
那么现在让我们来分析一下失败的原因吧。我是前说过,在
Win32
系统下,每个进程
都拥有自己的
4G
虚拟地址空间,各个进程之间都是相互独立的。在这里,我们当作参数传
入的字符串
"DLL.dll"
其实是一个数值,它表示这个字符串位于
Virus.exe
地址空间之中的地
址,而这个地址在传给
Target.exe
之后,它指向的东西就失去了有效性。举个例子来说,
譬如
A
、
B
两栋大楼,我住在
A
楼的
401
;那么
B
楼的
401
住的是谁我当然不能确定
——
也就是
401
这个门牌号在
B
楼失去了有效性,而且如果我想要入住
B
楼的话,我就必须请
B
楼的楼长为我在
B
楼中安排新的住处(当然这个新的住处是否
401
也就不一定了)。
由此看来,我就需要做这么一系列略显繁杂的手续
——
首先在
Target.exe
目标进程中
分配一段内存空间,然后向这段空间写入我要加载的
DLL
名称,最后再调用
CreateRemot
eThread
。这段代码就成了这样:
//
向目标进程地址空间写入
DLL
名称
DWORD
dwSize,
dwWritten;
dwSize
=
lstrlenA(
lpszDll
)
+
1;
LPVOID
lpBuf
=
VirtualAllocEx(
hProcess,
NULL,
dwSize,
MEM_COMMIT,
PAGE_R
EADWRITE
);
if
(
NULL
==
lpBuf
)
{
CloseHandle(
hProcess
);
//
失败处理
}
if
(
WriteProcessMemory(
hProcess,
lpBuf,
(LPVOID)lpszDll,
dwSize,
&dwWritten
)
)
{
//
要写入字节数与实际写入字节数不相等,仍属失败
if
(
dwWritten
!=
dwSize
)
{
VirtualFreeEx(
hProcess,
lpBuf,
dwSize,
MEM_DECOMMIT
);
CloseHandle(
hProcess
);
//
失败处理
}
}
else
{
CloseHandle(
hProcess
);
//
失败处理
}
//
使目标进程调用
LoadLibrary
,加载
DLL
DWORD
dwID;
LPVOID
pFunc
=
LoadLibraryA;
HANDLE
hThread
=
CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START
_ROUTINE)pFunc,
lpBuf,
0,
&dwID
);
需要说的有两点,
一是由于我要在目标进程中为
ANSI
字符串来分配内存空间,
所以这
里凡是和目标进程相关的部分,都明确使用了后缀为
“A”
的
API
函数
——
当然,如果要使用
Unicode
字符串的话,可以换作后缀是
“W”
的
API
;第二,在这里
LoadLibrary
的指针我是
取的本进程的
LoadLibraryA
的地址,
这是因为
LoadLibraryA/LoadLibraryW
位于
kernel32.
dll
之中,而
Win32
下每个应用程序都会把
kernel32.dll
加载到进程地址空间中一个固定的
地址,所以这里的函数地址在
Target.exe
中也是有效的。
在调用
LoadLibrary
完毕之后,我们就可以做收尾工作了:
//
等待
LoadLibrary
加载完毕
WaitForSingleObject(
hThread,
INFINITE
);
//
释放目标进程中申请的空间
VirtualFreeEx(
hProcess,
lpBuf,
dwSize,
MEM_DECOMMIT
);
CloseHandle(
hThread
);
CloseHandle(
hProcess
);
在此解释一下
WaitForSingleObject
一句。
由于我们是通过
CreateRemoteThread
在目
标进程中另外开辟了一个
LoadLibrary
的线程,
所以我们必须等待这个线程运行完毕才能够
释放那段先前申请的内存。
好了,
现在你可以尝试着整理这些代码并编译运行。
运行
Target.exe
,
然后开启一个有
模块查看功能的进程查看工具(在这里我使用我的
July
)来查看
Target.exe
的模块,你会
发现在注入
DLL
之前,
Target.exe
中并没有
DLL.dll
的存在:
在调用了注入代码之后,
DLL.dll
就位于
Target.exe
的模块列表之中了:
矛盾相生
记得
2004
年初我将
尾巴病毒成功仿真后,
有很多网友询问我如何才能杀毒,不过
我都没有回答
——
因为当时我研究的重点并非病毒的寄生特性。
这一寄生特性直到今天可以
说我才仿真完毕,那么,我就将解毒的方法也一并公开吧。
和
DLL
的注入过程类似,只不过在这里使用了两个
API
:
GetModuleHandle
和
FreeLi
brary
。出于篇幅考虑,我略去了与注入部分相似或相同的代码:
//
使目标进程调用
GetModuleHandle
,获得
DLL
在目标进程中的句柄
DWORD
dwHandle,
dwID;
LPVOID
pFunc
=
GetModuleHandleA;
HANDLE
hThread
=
CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START
_ROUTINE)pFunc,
lpBuf,
0,
&dwID
);
//
等待
GetModuleHandle
运行完毕
WaitForSingleObject(
hThread,
INFINITE
);
//
获得
GetModuleHandle
的返回值
GetExitCodeThread(
hThread,
&dwHandle
);
//
释放目标进程中申请的空间
VirtualFreeEx(
hProcess,
lpBuf,
dwSize,
MEM_DECOMMIT
);
CloseHandle(
hThread
);
//
使目标进程调用
FreeLibrary
,卸载
DLL
pFunc
=
FreeLibrary;
hThread
=
CreateRemoteThread(
hProcess,
NULL,
0,
(LPTHREAD_START_ROUTIN
E)pFunc,
(LPVOID)dwHandle,
0,
&dwID
);
//
等待
FreeLibrary
卸载完毕
WaitForSingleObject(
hThread,
INFINITE
);
CloseHandle(
hThread
);
CloseHandle(
hProcess
);
用这个方法可以卸载一个进程中的
DLL
模块,当然包括那些非病毒体的
DLL
。所以,
这段代码还是谨慎使用为好。
在完成卸载之后,如果没有别的程序加载这个
DLL
,你就可以将它删除了。
HOOK --
实现
HOOK
其他进程的
Messagebox
、、
思路方法如下
:
1 DLL
的编写
(
实现
IAT hook)
、
2 DLL
注入工具
(
远程线程技术和简单的
MFC
控件知识
)
、
3
简单的测试程序、
1
编写
dll
、
之前有篇文章
HOOK -- IAT HOOK
本进程
MessageBox
、这里部分代码是相同的、毕竟均
为
IAT HOOK
嘛、、
DLL
与跟
exe
有个
main
或者
WinMain
入口函数一样也有一个入口函数
DllMain
、
不过很多
仅仅包含资源信息的
DLL
是没有
DllMain
函数的、其原型如下
BOOL WINAPI DllMain( HINSTANCE hInstance, ULONG ulReason, LPVOID
Reserved);
何时调用
Dllmain
、
DllMain
的第二个参数
fdwReason
指明了系统调用
Dll
的原因、
DLL_PROCESS_ATTACH
、当一个
DLL
文件被映射到进程的地址空间时、用此参数掉
dllmain
当同一
DLL
再次映射时不会再调
DllMain
函数只增加
dll
次
数、
DLL_PROCESS_DETACH
、当
DLL
被从进程的地址空间解除映射时
FreeLibrary
进程结束而解除
DLL
映射
(
若是使用的
TerminateProcess
则
不调
)
DLL_THREAD_ATTACH
、当进程创建一线程时
,
跟
DLL_PROCESS_ATTACH
区别
无论何时创建线程均会用此参数调用
Dllmain
DLL_THREAD_DETACH
如果线程调用了
ExitThread
来结束线程(线程函数返回时,系
统也会自动调用
ExitThread
),若是
TerminateThread
也不会调用
DllMain.
这里选择如下方式编写
DllMain
函数
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID
lpvReserved)
{
If ( fdwReason= =DLL_PROCESS_ATTACH) //
加载
dll
时候调用
DllMain
_beginthread(ThreadProc,0,NULL); //
创建线程
return TRUE;
}
就是说当
dll
被加载的时候
(LoadLirary)
、在
DllMain
中实现创建
ThreadProc
线程函数、、
而
ThreadProc
函数里边是我们
IAT HOOK
的核心代码、、
ThreadProc
函数
:
功能是
一个应用程序定义的函数作为一个线程的起始地址服务
、
要
Hook Messagebox
需写一个自己的
Messagebox
如下
:
int __stdcall HookMBox(HWND hWnd, LPCTSTR lpText, LPCTSTR lpCaption,UINT
uType)
{
return MessageBox(NULL,"
哈哈
! HOOK
到
MessageBox
了
","HOOK",MB_OK); //
证
明一下
Hook
成功
}
在线程函数中完成我们的
ITA HOOK
的代码
:
1
获取本进程的模块基址
HANDLE pBegin = GetModuleHandle(NULL);
2
初始化
PE
结构得到
IAT
的地址
PBYTE pBegin2 = (PBYTE)pBegin;
PIMAGE_DOS_HEADER DOS = PIMAGE_DOS_HEADER(pBegin2);
HOOK -- DLL的远程注入技术详解(1)的更多相关文章
- DLL的远程注入技术
DLL的远程注入技术是目前Win32病毒广泛使用的一种技术.使用这种技术的病毒体通常位于一个DLL中,在系统启动的时候,一个EXE程序会将这个DLL加载至某些系统进程(如Explorer.exe)中运 ...
- 系统安全攻防战:DLL注入技术详解
DLL注入是一种允许攻击者在另一个进程的地址空间的上下文中运行任意代码的技术.攻击者使用DLL注入的过程中如果被赋予过多的运行特权,那么攻击者就很有可能会在DLL文件中嵌入自己的恶意攻击代码以获取更高 ...
- 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)
一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...
- CDN学习笔记二(技术详解)
一本好的入门书是带你进入陌生领域的明灯,<CDN技术详解>绝对是带你进入CDN行业的那盏最亮的明灯.因此,虽然只是纯粹的重点抄录,我也要把<CDN技术详解>的精华放上网.公诸同 ...
- CDN技术详解及实现原理
CDN技术详解 一本好的入门书是带你进入陌生领域的明灯,<CDN技术详解>绝对是带你进入CDN行业的那盏最亮的明灯.因此,虽然只是纯粹的重点抄录,我也要把<CDN技术详解>的精 ...
- Java程序员从笨鸟到菜鸟之(一百)sql注入攻击详解(一)sql注入原理详解
前段时间,在很多博客和微博中暴漏出了12306铁道部网站的一些漏洞,作为这么大的一个项目,要说有漏洞也不是没可能,但其漏洞确是一些菜鸟级程序员才会犯的错误.其实sql注入漏洞就是一个.作为一个菜鸟小程 ...
- Comet技术详解:基于HTTP长连接的Web端实时通信技术
前言 一般来说,Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询.Comet技术.WebSocket技术.SSE(Ser ...
- 转:LoadRunner中参数化技术详解
LoadRunner中参数化技术详解 LoadRunner在录制脚本的时候,只是忠实的记录了所有从客户端发送到服务器的数据,而在进行性能测试的时候,为了更接近真实的模拟现实应用,对于某些信息需要每次提 ...
- 了解iOS消息推送一文就够:史上最全iOS Push技术详解
本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...
随机推荐
- python2.7与3.5版本中:编码格式及编码转换
主要说明编码之间的转换方法 2.7版本: 1 # -*- coding:utf-8 -*- 2 a = "迪丽热巴" 3 a_unicode = a.decode("ut ...
- Spring4 MVC HelloWord实例
一.创建Web项目 我用的eclipse,创建步骤:file=>New=>Other=>Web=>Dynamic Web project,按照操作创建一个完整的Web项目,下载 ...
- MVC基于角色权限控制--用户管理
用户管理模块包括 新增用户.修改用户.展示用户列表.删除用户.用户角色分配.用户角色删除.用户权限分配 这里只介绍关于权限有关的 用户角色分配.用户角色删除.用户权限分配 新建控制器 UserInfo ...
- zipfile模块
在python中操作zip文件, 基本上都是使用zipfile模块,他可以创建.解压文件,获取zip文件的元数据信息. 我们想要操作一个zip文件,第一步就是初始化ZipFile实例. 1.打开tes ...
- day26-保护属性
如果有一个对象,当需要对其进行修改属性时,有2种方法 1.对象名.属性名 = 数据 --->直接修改 2.对象名.方法名() --->间接修改 为了更好的保护属性安全,即不能随意修改,一般 ...
- 网易云音乐api资料
https://github.com/LanFD/music_163 网易云音乐常用API浅析:http://moonlib.com/606.html
- URL中文乱码及特殊字符处理
一.中文乱码 IE高版本(应该是9以上,不确定),在get方式请求中中文传到后台容易出现乱码问题.解决方法如下: 1.第一种,换成post方式 如果可以得话换成post方式就可以.如果采用表单或者aj ...
- django--用户认证组件
用户认证组件 用户认证组件: 功能:用session记录登录验证状态 前提:用户表:django自带的auth_user 创建超级用户: python3 manage.py createsuperus ...
- 笨方法学python之读写文件、open函数的用法
一.python读写文件相关知识点 close:关闭文件 read:读取文件的内容//你可以把结果赋给一个变量 readline:只读取文件中的一行 truncate 美 /trʌŋ'ket/ :清空 ...
- get return value of python in shell
from: https://stackoverflow.com/questions/2115615/assigning-value-to-shell-variable-using-a-function ...