前言

通过本文介绍怎么对一个 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 时要注意校验。

转载于:https://www.cnblogs.com/hac425/p/10772834.html

SG Input 软件安全分析之逆向分析相关推荐

  1. [安全攻防进阶篇] 一.什么是逆向分析、逆向分析应用及经典扫雷游戏逆向

    从2019年7月开始,我来到了一个陌生的专业--网络空间安全.初入安全领域,是非常痛苦和难受的,要学的东西太多.涉及面太广,但好在自己通过分享100篇"网络安全自学"系列文章,艰难 ...

  2. 专访丰生强:Android软件安全与逆向分析

    [专家简介]   丰生强(@非虫)   Android软件安全专家:看雪论坛Android安全版版主,安卓巴士开发进阶板块版主.对Android软件与系统安全有狂热的爱好和独到的见解,对Android ...

  3. [系统安全] 二十四.逆向分析之OllyDbg调试INT3断点、反调试、硬件断点与内存断点

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  4. [安全攻防进阶篇] 六.逆向分析之OllyDbg逆向CrackMe01-02及加壳判断

    前文作者讲解了OllyDbg和在线沙箱的逆向分析过程,分享了恶意软件如何通过宏脚本发送勒索信息或密码至用户邮箱.这篇文件将带领大家逆向分析两个CrackMe程序,包括逆向分析和源码还原,基础性文章,希 ...

  5. [安全攻防进阶篇] 四.逆向分析之条件语句和循环语句源码还原及流程控制逆向

    从2019年7月开始,我来到了一个陌生的专业--网络空间安全.初入安全领域,是非常痛苦和难受的,要学的东西太多.涉及面太广,但好在自己通过分享100篇"网络安全自学"系列文章,艰难 ...

  6. [安全攻防进阶篇] 二.如何学好逆向分析、逆向路线推荐及吕布传游戏逆向案例

    从2019年7月开始,我来到了一个陌生的专业--网络空间安全.初入安全领域,是非常痛苦和难受的,要学的东西太多.涉及面太广,但好在自己通过分享100篇"网络安全自学"系列文章,艰难 ...

  7. [系统安全] 二十三.逆向分析之OllyDbg动态调试复习及TraceMe案例分析

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  8. [系统安全] 六.逆向分析之条件语句和循环语句源码还原及流程控制

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  9. [系统安全] 二.如何学好逆向分析及吕布传游戏逆向案例

    您可能之前看到过我写的类似文章,为什么还要重复撰写呢?只是想更好地帮助初学者了解病毒逆向分析和系统安全,更加成体系且不破坏之前的系列.因此,我重新开设了这个专栏,准备系统整理和深入学习系统安全.逆向分 ...

  10. 【JavaScript 逆向】网易易盾滑块逆向分析

    声明 本文章中所有内容仅供学习交流,相关链接做了脱敏处理,若有侵权,请联系我立即删除! 案例目标 验证码:aHR0cHM6Ly9kdW4uMTYzLmNvbS90cmlhbC9qaWdzYXc= 以上 ...

最新文章

  1. monkeyrunner无法运行的问题解决方案总结
  2. communication for making more gains or simply a leisure?
  3. 接口自动化测试系列(二):深入分析HTTP状态码502
  4. php include path pear,关于php:pear include_path数据文件夹不再有效
  5. Linux文本编辑器之vim
  6. 基于dijsktra算法的最短路径求解_基于dijkstra算法的AGV路径规划(含C++代码)
  7. 宝塔linux搭建环境注意事项
  8. 简单实现查找题库随机出题, 且可点击查看对应答案
  9. win10卸载ie11后安装不上
  10. Web前端_邮箱的正则表达式
  11. Python扫码登录保存和验证cookies值——网易云音乐篇(九)
  12. lammps案例:Fe原子辐照轰击多层石墨烯模拟
  13. 让孩子赢在起跑线。。。
  14. 从前你错过了BTC,现在还要错过我吗?快来烤仔小店抄底
  15. 数智化浪潮中,IT部门如何实现变革?
  16. 苹果AppStore应用商店生存之道:国内iOS开发者创业经验分享(二)
  17. Python程序设计第六章测验总结
  18. win10笔记本怎么重装系统?win10重装系统快捷方式
  19. 同济大学计算机access,同济大学access答案完美版
  20. 易语言QQ关键词监控自动回复源码

热门文章

  1. 人生的意义无非就是在平淡中活着
  2. 随笔:《像火箭科学家一样思考:将不可能变成可能》观书有感
  3. 串口调试常见问题和排查方法
  4. 机器学习(1)-项目 0: 预测泰坦尼克号乘客生还率
  5. GDSOI 2016 T2 星际穿越
  6. angularJS入门与进阶(笔记1)
  7. 机器学习模型效果评估指标与方法介绍
  8. jQuery插件实现瀑布流
  9. 高德地图获取城市所有小区的POI
  10. Web爬虫|入门教程之爬虫简介