DLL
的远程注入技术是目前
Win32
病毒广泛使用的一种技术。使用这种技术的病毒体通常
位于一个
DLL
中,在系统启动的时候,一个
EXE
程序会将这个
DLL
加载至某些系统进程
(如
Explorer.exe
)中运行。
 
这样一来,普通的进程管理器就很难发现这种病毒了,而且
即使发现了也很难清除,因为只要病毒寄生的进程不终止运行,那么这个
DLL
就不会在内
存中卸载,用户也就无法在资源管理器中删除这个
DLL
文件,真可谓一箭双雕哉。
 
 
 
记得
2003

QQ
尾巴病毒肆虐的时候,
就已经有些尾巴病毒的变种在使用这种技术了。
到了
2004
年初,我曾经尝试着仿真了一个
QQ
尾巴病毒,但独是跳过了
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
年初我将
QQ
尾巴病毒成功仿真后,
有很多网友询问我如何才能杀毒,不过
我都没有回答
——
因为当时我研究的重点并非病毒的寄生特性。
这一寄生特性直到今天可以
说我才仿真完毕,那么,我就将解毒的方法也一并公开吧。
 
 
 

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)的更多相关文章

  1. DLL的远程注入技术

    DLL的远程注入技术是目前Win32病毒广泛使用的一种技术.使用这种技术的病毒体通常位于一个DLL中,在系统启动的时候,一个EXE程序会将这个DLL加载至某些系统进程(如Explorer.exe)中运 ...

  2. 系统安全攻防战:DLL注入技术详解

    DLL注入是一种允许攻击者在另一个进程的地址空间的上下文中运行任意代码的技术.攻击者使用DLL注入的过程中如果被赋予过多的运行特权,那么攻击者就很有可能会在DLL文件中嵌入自己的恶意攻击代码以获取更高 ...

  3. 架构设计:远程调用服务架构设计及zookeeper技术详解(下篇)

    一.下篇开头的废话 终于开写下篇了,这也是我写远程调用框架的第三篇文章,前两篇都被博客园作为[编辑推荐]的文章,很兴奋哦,嘿嘿~~~~,本人是个很臭美的人,一定得要截图为证: 今天是2014年的第一天 ...

  4. CDN学习笔记二(技术详解)

    一本好的入门书是带你进入陌生领域的明灯,<CDN技术详解>绝对是带你进入CDN行业的那盏最亮的明灯.因此,虽然只是纯粹的重点抄录,我也要把<CDN技术详解>的精华放上网.公诸同 ...

  5. CDN技术详解及实现原理

    CDN技术详解 一本好的入门书是带你进入陌生领域的明灯,<CDN技术详解>绝对是带你进入CDN行业的那盏最亮的明灯.因此,虽然只是纯粹的重点抄录,我也要把<CDN技术详解>的精 ...

  6. Java程序员从笨鸟到菜鸟之(一百)sql注入攻击详解(一)sql注入原理详解

    前段时间,在很多博客和微博中暴漏出了12306铁道部网站的一些漏洞,作为这么大的一个项目,要说有漏洞也不是没可能,但其漏洞确是一些菜鸟级程序员才会犯的错误.其实sql注入漏洞就是一个.作为一个菜鸟小程 ...

  7. Comet技术详解:基于HTTP长连接的Web端实时通信技术

    前言 一般来说,Web端即时通讯技术因受限于浏览器的设计限制,一直以来实现起来并不容易,主流的Web端即时通讯方案大致有4种:传统Ajax短轮询.Comet技术.WebSocket技术.SSE(Ser ...

  8. 转:LoadRunner中参数化技术详解

    LoadRunner中参数化技术详解 LoadRunner在录制脚本的时候,只是忠实的记录了所有从客户端发送到服务器的数据,而在进行性能测试的时候,为了更接近真实的模拟现实应用,对于某些信息需要每次提 ...

  9. 了解iOS消息推送一文就够:史上最全iOS Push技术详解

    本文作者:陈裕发, 腾讯系统测试工程师,由腾讯WeTest整理发表. 1.引言 开发iOS系统中的Push推送,通常有以下3种情况: 1)在线Push:比如QQ.微信等IM界面处于前台时,聊天消息和指 ...

随机推荐

  1. 《算法》第四章部分程序 part 17

    ▶ 书中第四章部分程序,包括在加上自己补充的代码,无环图最短 / 最长路径通用程序,关键路径方法(critical path method)解决任务调度问题 ● 无环图最短 / 最长路径通用程序 pa ...

  2. python中的swapcase

    swapcase()将字符串中的字母小写变大写.大写变小写,举个例子: 1 a = "hELLO wORLD" 2 a1 = a.swapcase() 3 print(a1) 输出 ...

  3. spark historyserver 页面反应很慢 jvm堆调参

    我们的spark historyserver 最近页面打开很慢 jstat -gcutil pid 1000 发现full gc 相当严重 查看堆大小,发现默认堆1G,打算修改到4G jps -lvm ...

  4. java 正则 贪婪匹配 匹配sql语句中的引号内容

    public class Demo { public static void main(String[] args) { String sql1 = "use test;select * f ...

  5. MySQL PID错误,Mysql server PID file could not be found!

    https://blog.csdn.net/u010098331/article/details/50752667/

  6. Selenium2自动化测试实战(基于Python语言)— 编写第一个自动化脚本

    实现效果:执行脚本后启动Firefox浏览器后进入百度主页,输入“Selenium”后,单击搜索按钮,最后关闭浏览器的过程(默认安装了Firefox浏览器),如下图所示: 脚本内容如下: # -*- ...

  7. 结构体中string成员的问题

    在结构体中定义字符串的成员的时候要注意定义成string有时候,在某些程序中给成员赋值会崩溃,但是不确定到底什么情况会崩溃.运行报错如下: Program received signal SIGSEG ...

  8. Django之视图层介绍

    1. 伪静态设置: 路由层: url('^index/$', views.index), url('^article/(?P<id>(\d+)).html/$', views.articl ...

  9. HTML学习-1网页基础知识

    HTML超文本标记语言:HyperText Markup Language. 由浏览器运行解析. 它包括了静态页面.html   .htm.动态页面.php .aspx .jsp,从数据库提取. 今天 ...

  10. li之间的间隙问题

    1.间隙是有代码格式中的换行符产生,对代码进行压缩处理或手动删除换行就好: