前言

通过本文介绍怎么对一个 windows 程序进行安全分析。分析的软件版本为 2018-10-9 , 所有相关文件的链接

链接:https://pan.baidu.com/s/1l6BuuL-HPFdkFsVNOLpjUQ
提取码:erml

逆向分析

定位核心代码

拿到一个软件首先需要进行攻击面的探测,即找到尽可能多的可以与程序进行交互的入口点,有数据交互的地方就有可能会出现漏洞。首先对软件的功能做一个大概的了解,发现搜狗输入法能够安装用户自定义的皮肤,这是一个比较好的入口点,于是下面分析分析处理皮肤文件的逻辑。

先从官网随便下个皮肤,然后拿 010editor 简单看看能不能拿到一些有用的信息。

使用 binwalk 也没有识别出文件格式,于是猜测应该是输入法自己实现的格式。

后来在对皮肤相关的功能进行浏览的时候发现有皮肤编辑器这个软件

https://pinyin.sogou.com/skins/design.php

下载下来随便创建一个皮肤,发现此时的皮肤格式为 zip 格式,双击也能正常安装。皮肤编辑器的最近更新在 13 年,估计输入法是为了做兼容,同时支持两种格式的皮肤文件。

下载下来的皮肤双击就可以安装,这样的安装方式我们不好定位具体安装皮肤的程序,这时我们可以使用 api montor 监控当双击皮肤文件时系统所执行的命令,以便进行下一步的分析。

打开 api monitor , 然后打开皮肤文件可以监控到搜狗输入法处理皮肤文件执行的命令

"C:\Program Files (x86)\SogouInput\SogouExe\SogouExe.exe" "C:\Program Files (x86)\SogouInput\9.1.0.2657\SGTool.exe"-line 0 -border --appid=skinreg -list "C:\Users\XinSai\Desktop\test.ssf"

通过使用 Procmon.exe 分析,其实最后调用

"C:\Program Files (x86)\SogouInput\9.1.0.2657\SGTool.exe" -line 0 -border --appid=skinreg -install -c  "C:\Users\XinSai\Desktop\test.ssf" -q -ef

通过执行这条命令就可以把皮肤安装到输入法内部。

下面把 SGTool.exe 拖到 IDA 里面, 使用命令行选项来搜索字符串的交叉引用去找到相关的处理代码。通过对命令行参数的交叉引用逐步向上追溯,在 0x07A04D0 发现程序会根据 appid 参数的值,决定下一步进行处理的函数

然后调试发现一直断不到这,于是用 drrun 看看程序到底走了哪些路径

drrun.exe -t drcov --  "C:\Program Files (x86)\SogouInput\9.1.0.2657\SGTool.exe" -line 0 -border --appid=skinreg -install -c  "C:\Users\XinSai\Desktop\test.ssf" -q -ef

发现直接点击 ssf 文件还是没有进入这个分支。

经过不断的尝试 + 使用一些监控软件,发现在关闭所有搜狗输入法相关进程的情况下,双击 .ssf 文件,会首先使用

"C:\Program Files (x86)\SogouInput\9.1.0.2657\SGTool.exe" -daemon

开启一个类似于服务器的进程,然后在使用

"C:\Program Files (x86)\SogouInput\9.1.0.2657\SGTool.exe" -line 0 -border --appid=skinreg -install -c  "C:\Users\XinSai\Desktop\test.ssf" -q -ef

另外再起一个 SGTool.exe 的进程向刚刚启动服务进程发送消息,后续的皮肤处理在服务进程进行。猜测可能是使用了 windows 本地通信机制实现 C/S 架构

后续在瞎试的时候,将一个非皮肤文件命名成 .ssf 后缀,然后双击会出现报错信息。

根据这些字符串在 od 里面找,可以找到一些信息,最后通过对

皮肤解压失败:skin.ini不存在

交叉引用, 然后不断回溯, 发现了一个有趣的函数 0x07A72D0

这个函数首先 调用 0x7A84F0检测了某些参数。

从我们的参数进行对比,猜测这里校验的应该是最后那两个参数

然后猜测 -q 应该是安静模式,于是删掉 -q 试了一试

发现居然会有提示框,那这个提示框的代码附件应该离处理 皮肤文件的代码更加近了。

对字符串交叉引用,发现其实就是上面的那个代码(0x007A75DC

所以从这里开始,应该就开始对皮肤文件进行处理了。

分析皮肤处理相关的代码

经过不断的调试以及查看函数调用的参数,发现当我们点击 确认 的时候,会调用位于0x914980 的函数。

这个函数传入的参数是一个对象指针,对象内部有我们皮肤文件的路径,这个函数会对传入的 皮肤文件 进行第一次的判断。

函数首先会打开文件, 然后取出开头的4个字节作为文件类型,判断是不是Skin。如果是的话就认为是最新的皮肤格式然后进入后续的操作。

如果不是就认为是第一代皮肤格式 ,即用zip格式打包的皮肤。

调试时,可以看到 type 的值。 下面是打开的官网下载的皮肤文件,所以 typeSkin.

当皮肤文件的type值不为Skin时,程序会进入decompress_skin_ini (0x063F340), 这个函数里面会调用ziplib.dll 里面的函数对皮肤文件进行解压,提取并解析skin.ini文件。

总的来说,0x914980 函数其实只是校验了皮肤文件的版本信息,对于 文件头 不是 Skin 的文件,则认为是第一代皮肤格式文件,然后会使用 ziplib.dll 里面的函数提取 skin.ini 文件并尝试解析它。

在进行完第一次的校验后,会回到 0x7A72D0, 将文件拷贝到用户的皮肤保存目录,然后对皮肤文件进行解析,提取出里面的文件。

其中 0x7A6230 deal_skin 就是解析皮肤文件的入口,它会调用 0x63E3F0 完成具体文件解析流程。

这个函数首先判断文件头 , 如果是 Skin , 表示为最新格式的皮肤文件

则通过 decompress_skinv3 0x053B320 进行解析并提取出皮肤包里面包含的文件。否则就认为是第一代皮肤文件, 使用 ziplib 里面的函数, 把皮肤包里面的文件解压出来。

for ( i = v25 - 3; v28 < v27; ++v28 )
{
..................................................................
..................................................................
..................................................................
.................................................................. if ( decompress_file_from_zip(v46, v65, &path, target, &len, &buf) )
{
v47 = len;
if ( len <= 0x80000000 && len )
{
len = target;
(*v51)(&v51, &len, 0);
v48 = buf;
v54 = v47;
v53 = buf;
sub_53ACE0(obj1, &v50, 0);// 做一些析构操作
sub_49F5C0(ziplib_obj, v65, v47, v48);
}
v24 = v62;
}
..................................................................
..................................................................
..................................................................
..................................................................
}

下面对decompress_skinv3(0x053B320)进行分析,以便理解最新皮肤包的格式

首先打开皮肤包,读取文件内容到内存,然后把文件内容,大小传给 handle_skinv3 0x0053A8C0 进行处理。

通过对这个函数的逆向,可以明白.ssf 文件开头 8个字节的结构为 4字节的 Skin 和 4 字节的 version 字段

校验完版本信息后, 会对文件头部后的数据使用程序自己实现的算法进行解码,然后对解码之后的数据使用zlib再次解码。

zlib 解码完成后,把解码后的数据传入 0x53bf50 (调试时确认)对文件进行提取

这个函数对传入的数据进行解析,提取出相关的文件

// 调用者 0x53AAE1
unsigned int __thiscall skin_v3_step2(int this, unsigned int *buf, unsigned int size, int a4)
{ len = *buf; // 取出 buf 开始的 4 个字节, 表示数据的长度
if ( *buf > size )
return -1;
new_size = size - 4;
sizea = size - 4;
if ( *buf )
{
if ( (**(this + 4))(this + 4, buf + 1, new_size, a4) < 0 )// 调用0x53c110L,第 2, 3个参数为 buf + 4, size-4
// 就是忽略掉头4个字节
// 函数作用复制 zlib 解码后的数据 0x8-0x40 到对象里面 do // 循环的从 zlib 解压过的文件里面提取出文件
{
offset = *(v12 + 4 * v9);
if ( offset < data_len )
{ v17 = (**v15)(cur, sizea, a4); // 调用 0x923f70L, 提取文件名
if ( v17 < 0 )
goto LABEL_19;
v18 = &cur[v17];
v19 = (*v22[3])(v18, sizea - v17, a4);// 调用的是 0x53c1c0L, 提取文件内容 }
++v9;
}
while ( v9 < v11 );

文件格式汇总

老版本的皮肤格式

其实就是一个 zip 包, 里面有配置文件和一些图片。

新版本的皮肤格式

首先是 .ssf 文件

开头 8个字节为 4字节的 Skin 和 4 字节的 version

  • 然后调用 0x0639610文件偏移 8开始进行解码, 解码后的数据 A 偏移 4 字节开始 为 zlib 压缩的数据。
  • 然后对 A + 4 使用 zlib 解码,得到 zlib 解码后的数据 B
  • 然后把 BB 的长度传入 0x53bf50 继续处理

B 的结构为

开头4个字节为数据的总长度

然后根据 0x53C110 , 后面紧跟着的 4 个字节为文件映射表的长度,即 0x38 字节。每一个表项4个字节,代表表项指示其所表示的文件在整个文件中的偏移地址。

如图所示, 第一个表项的值为 0x40, 所以第一个文件应该在 0x40 处。

经过一定的观察发现一个文件的表示方式为

  • 4字节: 文件名的长度
  • 文件名( unicode 编码)
  • 4字节: 文件数据的长度
  • 文件数据

发现漏洞

分析完整个皮肤处理的代码后发现整个代码的逻辑还是不怎么复杂的。于是可以直接读反编译的代码来找找看是否存在什么漏洞。在读代码找漏洞时重点关注缓冲区的操作, 内存的分配大小以及对文件中表示长度的字段的使用是否合理。

经过一番仔细的走查发现在对皮肤文件第一步用自己实现的解密算法解密后的开始 4 个字节为 deocded_data_size , 之后会把它加上 8 然后去分配内存。

deocded_data_size 是从解密后的文件中取出的,当把 deocded_data_size 改成 0xffffffff 时,在分配内存时会整数溢出导致分配比较小的内存块,然后后续的代码在使用这个缓冲区时会造成一个堆溢出。漏洞已于3个月前提交并修复。

总结

在分析软件功能实现时,可以采用一些监控软件比如 api monitor 来辅助定位关键代码。一些程序中的提示,报错信息也可以用来定位。最重要的就是多调试,多调试。程序从文件内容中取 size 时要注意校验。

SG Input 软件安全分析之逆向分析的更多相关文章

  1. SG Input 软件安全分析之fuzz

    前言 前面介绍了通过静态读代码的方式去发现问题,这里介绍两种 fuzz 目标软件的方式. 相关文件 链接:https://pan.baidu.com/s/1l6BuuL-HPFdkFsVNOLpjUQ ...

  2. 病毒木马查杀实战第016篇:U盘病毒之逆向分析

    比对脱壳前后的程序 我们这次所要研究的是经过上次的脱壳操作之后,所获取的无壳病毒样本.其实我们这里可以先进行一下对比,看看有壳与无壳的反汇编代码的区别.首先用IDA Pro载入原始病毒样本: 图1 可 ...

  3. cm3 逆向分析

    目录 cm3 逆向分析 前言 逆向分析 cm3 逆向分析 前言 这道题没加壳,也没加密算法,主要看代码逻辑. 逆向分析 代码很短,一共这么几句. 看提示知道只让我们输入w.s.a.d这几个字符,并且用 ...

  4. cm2 逆向分析

    目录 cm2 逆向分析 前言 查壳 逆向分析 encrypt函数 POC代码 cm2 逆向分析 前言 这是逆向实战之CTF比赛篇的第3篇,在这里我就不再讲的特别小白了,有些简单操作可能会略过. 查壳 ...

  5. IM通信协议逆向分析、Wireshark自定义数据包格式解析插件编程学习

    相关学习资料 http://hi.baidu.com/hucyuansheng/item/bf2bfddefd1ee70ad68ed04d http://en.wikipedia.org/wiki/I ...

  6. Android逆向分析(2) APK的打包与安装背后的故事

    前言 上一次我们反编译了手Q,并遇到了Apktool反编译直接crash的问题,虽然笔者很想在这次解决这个问题,但在解决途中,发现该保护依赖于很多知识,所以本次先插入一下,正所谓知其然知其所以然,授之 ...

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

    http://blog.zhaiyifan.cn/2016/02/13/android-reverse-2/ 2/18日增加对aidl和java编译的描述. 前言 上一次我们反编译了手Q,并遇到了Ap ...

  8. [Android Security] Smali和逆向分析

    copy : https://blog.csdn.net/u012573920/article/details/44034397 1.Smali简介 Smali是Dalvik的寄存器语言,它与Java ...

  9. MacOS微信逆向分析-Frida

    MacOS微信逆向分析-Frida 0.前言 PC下的微信二次开发相信大家都会了,那么本篇文章将带领大家使用Frida框架对Mac下微信来进行二次开发! PS:还有一种静态注入的方式也不错,但是考虑到 ...

随机推荐

  1. [CocoaPods]制作CocoaPod

    创建自己的CocoaPod非常简单.如果你已经有一个单独的组件,那么你就是最重要的.本指南概述了整个过程,本节中的其他指南更适合更高级用户. 我们建议让CocoaPods在这里努力工作.Running ...

  2. bootstrap使用之多个弹窗和拖动效果[开发篇]

    有时开发一些特效,自己感觉挺爽的,像操作自己电脑一样操作你的网页,这里就介绍一个使用bootstrap的一点多窗口和拖动效果吧! 这里,我们不使用静态打开的的方式,low...,1.添加一个a链接 触 ...

  3. druid的关键参数+数据库连接池运行原理

      minEvictableIdleTimeMillis :连接保持空闲而不被驱逐的最长存活时间.(默认30分钟) Destory线程中如果检测到当前连接的最后活跃时间和当前时间的差值大于minEvi ...

  4. [EXP]ThinkPHP 5.0.23/5.1.31 - Remote Code Execution

    # Exploit Title: ThinkPHP .x < v5.0.23,v5.1.31 Remote Code Execution # Date: -- # Exploit Author: ...

  5. C# 根据Combobox控件来动态显示TabControl下的子元素

    根据下来列表来动态显示TabControl下的元素 需要准备两个控件:Combobox (命名为:cbPrjType)和 TabControl (命名为:tabPrjType),TabControl下 ...

  6. [转]idea导入eclipse的web项目

    https://www.cnblogs.com/xiaoBlog2016/archive/2017/05/08/6825014.html 一.导入自己的web项目 步骤:File->New-&g ...

  7. Spring Cloud Zuul 网关使用与 OAuth2.0 认证授权服务

    API 网关的出现的原因是微服务架构的出现,不同的微服务一般会有不同的服务地址,而外部客户端可能需要调用多个服务的接口才能完成一个业务需求,如果让客户端直接与各个微服务通信,会有以下的问题: 客户端会 ...

  8. Nginx 的两种认证方式

    简介: 今天来研究一下 Nginx 的两种认证方式. 1.auth_basic 本机认证 2.ngx_http_auth_request_module 第三方认证 一.安装 Nginx shell & ...

  9. Jenkins之使用Pyinstaller构建Python应用程序

    目录 1. 极简概述 2. Jenkins配置 2.1 安装JDK 2.2 安装Jenkins 3. 安装Docker 4. 使用PyInstaller构建Python应用程序 4.1 Fork 一个 ...

  10. CSS 基础:定位元素(3)<思维导图>

    这段时间利用一下间隙时间学习了CSS的基础知识,主要目的是加深对CSS的理解,虽然个人主要工作基本都是后台开发,但是个人觉得系统学习一下CSS的基础还是很有必要的.下面我学习CSS时做的思维导图(全屏 ...