Winrar软件简单功能逆向分析与修改【IDA Pro动静态分析综合】

Winrar软件简单功能逆向分析与修改——IDA Pro动静态分析综合使用

[toc]

1. 问题及相关分析

​ WinRAR压缩软件是老牌经典解压缩软件,电脑装机必备软件之一,WinRAR支持目前绝大多数的压缩文件格式,Winrar包含强力压缩、分卷、加密和自解压模块,简单易用。WinRAR的优点在于压缩率大速度快,它能备份数据,减少E-mail 附件的大小,解压缩从 Internet 上下载的RAR、ZIP和其他格式的压缩文件,并能创建RAR和ZIP格式的压缩文件。

​ 但是在国内中文网站(http://www.winrar.com.cn/)和英文官方网站(https://www.rarlab.com/)下载的简体中文版WinRAR,即使有授权文件,你会发现授权后的WinRAR还是有广告弹窗出现,使用体验大打折扣。

​ 本文就以清除广告弹窗为目标,介绍IDA Pro的动静态分析中的使用。最后介绍一种简单的去除注册提示窗口的方法,可以让未注册版本具有更好的使用体验。

1.1 弹窗问题分析

​ 以上所述的Winrar软件启动的弹窗界面如图1所示,软件打开后,随着主程序界面的打开过程,会弹出一个窗口打开网络上某个网址中的广告信息显示。该过程如果电脑没有连接网络,将会造成Winrar打开过程卡顿,造成使用上的极大不便。

图1 Winrar广告弹窗

​ 从窗口的表现行为,初步判断这是一个非模态的Windows窗口,也可能是一个非模态的对话框,也可能是一个标准的Windows程序窗口,关于这方面的判断,主要依赖读者对Windows编程知识的了解,这里不再深入探讨,可以参考《Windows程序设计第5版珍藏版》。该书是清华大学出版社发行的一本经典的Windows编程圣经,由美Charles Petzold编写的中译本。

​ 通过使用网络抓包分析工具,可以分析得到每次的弹窗都会通过网络连接到互联网上某个Web站点上的广告页面,然后显示。因此可以推测在这个Windows窗口中实现了对某个包含广告的网址的读取并显示。假设在程序的初始化阶段,能够获得这个窗口打开的代码位置,尝试去除这个窗口的调用显示,那么也许就能去除弹窗。

​ 按照这个思路,必须在代码中找到调用构建弹窗的代码。如果使用静态分析,则需要大量的时间分析复杂的反汇编代码,而使用动态调试的方式则可以更有效率的分析。

动态分析要点:

  • 使用添加API断点,对目标代码进行调试代码执行,更方便的分析软件行为,例如本实验中可以使用对CreateWindowExW这个API设置断点,查找所有新建窗口的行为。
  • 为了提高断点捕获的效率,可以使用断点的条件选项设置断点激活的条件,提高分析效率。

1.2 获得关键弹窗参数

​ Windows程序中的一个窗口包含很多参数,可以作为窗口的区别特征。常见包括窗口句柄,窗口类,窗口标题文字,窗口样式等。

​ 使用**Spy++**之类的窗口分析软件可以方便的获得这些参数。下图是WinRar弹窗的一些参数显示界面,使用Spy++软件查找窗口的功能,可以获得所需要的各项参数。

图2 Spy++软件查询窗口参数

Spy++使用方法:

  • Spy++分为32位和64位两个版本,通常在64位环境中选择使用Spy++64这个版本。

  • 启动Spy++软件后,可以使用查找窗口的功能,即点击工具栏上望远镜图标,或使用Ctrl+F快捷键打开查找对话框。

  • 使用鼠标选择对话框中瞄准镜,按住左键,将瞄准镜图标拖动到需要查找分析的窗口上即可。

    注意:如果需要获得顶层窗口,请将瞄准镜托放到窗口的标题栏上。

2. 动态调试分析

​ 动态调试分析就是在受限控制的环境中,逐条执行分析对象代码,通过代码执行的上下文环境,配合调用指令,API,变量数值等信息,综合的分析被调试代码的功能。

通常进行动态调试分析采用工具有:

  • ollydbg
  • windbg
  • x64dbg(x32dbg)
  • ……

​ IDA Pro作为经典的静态代码分析工具,由于其静态分析强大的光环掩盖了其同样可以进行动态分析调试的功能。并且由于动静态分析集成在同一个工具中,在动态分析的过程中,可以同时获得静态分析强大的支持,将对分析工作有更大的帮助。因此,本文以下从IDA Pro工具的这两个方面进行介绍。

2.1 IDA Pro动态调试

​ IDA Pro软件采用了可扩展方式开发,除了基本的静态分析功能,还支持通过扩展方式与常见的调试器协调工作。例如,常规的安装版本中,在“Debug”工具栏的下拉菜单中就能选择一些常见的调试器,例如windbg,Local Windows dubugger,……。

注意:以下的动态调试内容以选择Local Windows Debugger进行。

​ IDA Pro 启动后,通常都会显示一个“Quick start”窗口,让用户选择以前调式过的项目,或者选择“new”项目,引导用户打开新的文件进行调试;另外还可以选择“go”按钮,这样会直接打开空白的程序界面,这时只要将需要分析的程序直接拖进窗口就能进行分析。除了以上的3中方式外,还可以直接把需要调试的exe或dll文件直接拖放到IDA Pro程序的图标上,这种方式也能快速打开IDA Pro程序进行分析工作。

​ IDA Pro加载了需要分析的文件后,会不断弹出一些信息确认窗口,基本上都选择默认或者Yes按钮就可以了。只需要注意其中有一个选项目是让用户是否使用pdb调试文件,这里一般选择“否”,如果选择了“Yes”,后续会弹出对话框要求用户指定pdb格式文件路径。

知识点:IDA Pro数据库。

​ IDA Pro打开文件后,会扫描分析文件,并将文件中的数据全部抽取出来,然后使用其特定的数据格式存储,一般会有一组文件,扩展名是类似id0,id1,id2,nam,……等格式的文件。当IDA Pro退出关闭分析的文件后,这些文件会整体打包成一个文件扩展名为idb。idb文件是IDA Pro数据库文件,IDA Pro程序可以直接加载数据库文件进行逆向代码分析,而不需要源文件。这种设计思路一方面能够方便在对分析数据内容进行标记和修改,另一方面也避免了一些病毒程序被触发执行的风险。因此当第一次打开被分析的exe或dll文件后,程序会自动的分析,并将所有的数据信息记录到数据库文件。当关闭程序的时候,会提示用户保存该数据库文件。

IDA Pro打开后的界面,主要包括反汇编代码窗口,函数清单窗口,工具栏等。如图3所示。

图3 IDA Pro界面

2.1.1 动态调试步骤

  1. 选择调试器
  2. 设置断点
  3. 运行调试,直到断点处,程序停止。
  4. 查看并分析断点处代码
  5. 步骤2或得到调试结果退出。

以下文章将详细介绍每个分析过程。

2.1.2 常用快捷键

​ 调试过程就是逐条运行指令或程序代码,可以使用以下快捷键控制程序的执行:

  • F9:启动调试,如果设置了断点,那么执行到下一个断点暂停。
  • F7:步进调试,逐条执行指令,每按一次该键,执行1条指令,遇到函数调用进入到函数内部逐条执行。
  • F8:步过调试:和F7类似,区别是当遇到函数调用指令,不会进入到函数体内部,把函数执行当作1条指令执行。

2.1.3 调试中的数据

​ 动态调试的核心思想是抛开复杂的静态分析,让程序运行起来,然后对程序运行的状态进行分析,比如某条指令或函数执行的时候,某个变量的数据是否是预期的值,查看某个内存中特定时候的数据等。通过调试过程中获取到的信息,验证对程序功能,实现方式,调用规则等方面的推测。因此动态调试对内存和寄存器中的数据查看分析非常重要。

​ 由前面章节的学习,可知道一般的局部变量和函数传递的参数都使用当前栈帧保存的,部分函数调用规范还会使用ECX,EDX等寄存器传输参数。IDA Pro在进行动态调试时,这些数据都可以从 Stack View窗口读取到。调试时候,栈顶数据会使用高亮度表示。

提示:常见的调用规范是 cdecl, stdcall, fastcall。微软给出支持的调用约定 https://learn.microsoft.com/zh-cn/cpp/cpp/calling-conventions

​ 常见的32位操作系统下,Windows API调用采用的stdcall调用标准,因此当进入函数断点时,第一个参数应当保存在 [ESP+4], 第二个参数在[ESP+8],其他参数依次类推得到,请大家思考此时的[ESP]存放的是什么数据?

​ Windows API 通常有明确的功能性特征,比如当系统中调用了ReadFile这个API函数,就能判断代码读取了文件,也可以查询API中的参数规范,获得当前读取文件的信息。所以在软件逆向分析中,如果遇到了标准的Windows API函数调用,可以辅助对程序的功能和行为的分析。

​ 以下调试过程中,为了确定是否能找到弹窗调用代码,就需要不断查看栈帧对应的参数,通过传输入的参数数据来判断当前执行到的指令是否是所期望的位置代码。

2.2 动态调试查找广告弹窗

​ 经过1.2小节的分析,假设这个广告窗口是通过CreateWindowExW函数创建的。后续的工作可以围绕其相关信息开展。

​ 在1.2节获得弹窗以下信息:

  • 窗口类名:RarReminder
  • 窗口样式:16CB0000
  • 标题文字:Winrar
  • ……

​ 通过这些信息在后续的调试过程中,可以从大量的函数调用中筛选出所需要的函数调用,定位分析的关注点。以下分别从查找API函数,设置断点和调试分析这三个步骤介绍调试过程。

CreateWindowExW是User32.dll中提供的Windows API函数,提供对Windows窗口的创建功能。这里特别需要说明,常见的Windows图形化界面中,除了直接看到的窗口(Window)界面是可以由这个函数构造,其他几乎所有的图形化界面元素都是可以使用这个函数构造。比如常见的按钮,编辑框,下拉菜单等各类控件,本质上都是不同窗口类的窗口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
>HWND CreateWindowExW(  
DWORD dwExStyle,
LPCWSTR lpClassName, //窗口类参数,可选
LPCWSTR lpWindowName, //窗口文本标题,可选
DWORD dwStyle, //窗口样式参数
int X,
int Y,
int nWidth,
int nHeight,
HWND hWndParent,
HMENU hMenu,
HINSTANCE hInstance,
LPVOID lpParam
>);

​ 以上定义中,LPCWSTR是使用了“宽字符”构成的字符串,简单说就是每个符号占用2个字节,而不是经典的C-Style字符串所定义的一个符号使用1字节表示。

2.2.1 查找API函数

​ 通过分析可知创建弹窗的API有可能是CreateWindowExW,那么就可以设置这个API函数断点进行调试分析。使用IDA Pro可以有多种方式查找可以使用设置断点的API函数,这里介绍使用导入表查找可用的API函数。

图4 Import 导入函数列表

​ IDA Pro默认打开分析程序后,会在窗口中自动打开名为Imports的标签页,其中显示的是当前分析PE格式文件的导入函数,表格中包含了常用的“函数地址”,“API函数名”和“函数所在的库”等数据列。在使用过程中可以通过单击列标题实现对数据的排序,方便快速查看所需要的函数。

​ 使用技巧:可以在imports界面输入所需要查找函数的前几个字符,这样导入表会按照输入进行快速筛选。例如图4中输入了createwin,界面中就自动高亮度筛选出了CreateWindowExW函数。

图5 CreateWindowExW函数

​ 查找到所需要的API函数后,可以双击该项目,就会进入到该函数的反汇编代码窗口,如图5所示。通过该界面获得函数的一些基本信息,如函数名,参数个数和类型,函数的返回值等。由于是库函数,这里是显示了函数的声明,并不显示具体的函数反汇编指令。

2.2.2 设置断点

​ 在图3中打开的Windows API函数界面中,具体就是在CreateWindowExW上单击右键,选择右键菜单中的“Add Breakpoint”项目,打开断点设置窗口。

使用技巧:在代码中选择适合的API函数后单击F2键,可以快速打开以上断点设置窗口。

图6 断点设置对话框

​ 在打开的断点设置窗口中Location中已经自动填入了我们选择好的API函数的入口地址,不需要修改。单击OK按钮就能添加CreateWindowExW函数的访问断点。

​ 图6界面中Condition可以填入IDC脚本函数或表达式计算,当计算结果为真时,触发该断点。
例如输入 get_wide_dword(ESP+0x4) == 0x100 表示当代码执行到CreateWindowExW时,如果当前的ESP+0x4这个内存位置中的DWORD数值为0x100,那么断点就触发。

​ IDC函数可以参考:https://www.hex-rays.com/products/ida/support/idadoc/162.shtml

​ 由前文分析可知广告弹窗的窗口样式的数值为16CB0000,是CreateWindowExW函数的第4个参数。函数调用规范是stadcall,因此所需参数可以使用以下方式获得:
​ 栈顶可以使用get_wide_dword(ESP)获得,
​ 第1个参数使用 get_wide_dword(ESP+4),
​ 第2个参数使用 get_wide_dword(ESP+8),
​ …… 。

​ 图6界面中,Condition中填写 get_wide_dword(ESP+0x10) == 0x16CB0000

2.2.3 调试分析

  1. 启动调试

​ 完成以上的断点设置后,可以单击F9启动调试。理想的状态是运行后,触发断点后程序停止在我们所需要的断点位置。但实际情况往往会有各类的警告信息,以及系统的各类异常等情况的中断,因此一般情况下可以单击弹出的对话框确定继续,或者再次按下F9继续调试。

注意:在每次按下F9调试前,请检测以下Stack view,查看一下栈中的数据是否和需要捕获的窗口的数据一致。本例子中,就是需要查看 参数16CB0000是否出现在栈中。

图7 中断界面

​ 图7中右下角的Stack View中,蓝色条标记的是栈顶,即ESP==0x0104BBD8,而ESP+0x10==0x0104BBE8,对应的内存中数据为0x16CB0000,正是我们查找的窗口,此时程序中断在构建广告窗口的代码中CreateWindowExW函数的调用前。

  1. 查看分析代码

​ 以上的断点暂停的位置是CreateWindowExW函数的入口,但此时并不需要分析该函数,需要分析的是调用该指令的代码块,即该函数执行完返回地址。按照函数调用的规范,此时栈顶中数据就是返回后执行代码地址,因此双击栈顶地址就能打开调用的代码。在上图界面中右下角子窗口中,双击Stack View界面中sub_1121410+3D2就进入如图6所示界面。

图8 广告弹窗调用代码

​ 图8中反汇编代码显示的部分就是广告弹窗构造代码,代码使用call ds:CreateWindowExW指令调用CreateWindowExW函数,创建广告弹出窗口。

​ 以上反汇编代码中,call指令前是一系列的push指令,是采用栈传输函数所需的参数,期中就包含了窗口大小,位置以及窗口样式等信息,这些和API函数定义是一致的。

​ 通过以上的断点调试分析,可以初步确定广告弹窗启动代码地址,可以记录下当前的代码位置,然后使用Ctrl-F2快捷键关闭调试。

3.静态分析与破解

3.1 弹窗静态代码分析

​ 由上一节的分析,可以获得广告弹窗的CreateWindowExW函数的调用代码段如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
.text:011217AD loc_11217AD:                            ; CODE XREF: sub_1121410+307↑j
.text:011217AD ; sub_1121410+314↑j
.text:011217AD push 100h ; size_t
.text:011217B2 push offset byte_11A6F18 ; char *
.text:011217B7 call sub_1120AE0
.text:011217BC push 0 ; lpParam --start--
.text:011217BE push hInstance ; hInstance
.text:011217C4 push 0 ; hMenu
.text:011217C6 push 0 ; hWndParent
.text:011217C8 push edi ; nHeight
.text:011217C9 push esi ; nWidth
.text:011217CA push ebp ; Y
.text:011217CB push [esp+1044h+X] ; X
.text:011217CF push ebx ; dwStyle
.text:011217D0 push offset WindowName ; "WinRAR"
.text:011217D5 push offset aRarreminder ; "RarReminder"
.text:011217DA push 0 ; dwExStyle
.text:011217DC call ds:CreateWindowExW ; ---end--
.text:011217E2 test byte ptr dword_11A6BA8, 1
.text:011217E9 pop edi
.text:011217EA pop ebp

​ 查看以上代码6-18行,是调用CreateWindowExW,构造弹窗。如果屏蔽call指令是否能禁止弹窗?按照这个思路下面介绍具体的实验方法,完成广告弹窗的屏蔽操作。

3.2 去弹窗修复

​ IDA Pro作为强大静态反编译分析工具,具有强大的二进制文件修改功能,这里主要使用的是汇编和补丁两个功能。

  1. 修改汇编代码,绕过call指令调用。

​ 在IDA Pro汇编窗口中,找到入栈的第一个参数位置,即以上代码中的第6行代码(标记注释start位置)处。将光标点击这个地址,然后依次打开菜单项目Edit->Patch Program->Assemble...,在弹出的对话框中输入汇编指令,如图9。

图9 汇编修改的指令

​ 以上代码中JMP跳转指令,011217E2是Call指令的下一条指令地址。经过以上的修改,程序将跳过广告窗口的构造指令,实现去除广告弹窗的目的。

  1. 补丁文件输出,实现去弹窗。

​ 以上的修改仅仅是实现了IDA Pro数据库文件的修改,并没有对exe可执行文件进行修改,如果要将修改的结果写入可执行文件,就需要使用IDA Pro的补丁(patch)功能。

​ 操作菜单:Edit->Patch Program->Apply patches to input file...

图10 应用补丁

​ 单击Create backup选项后,单击OK即可补丁程序文件。

注意:如果补丁文件时处于调式状态,将无法写入文件,因此在补丁文件前,需要终止代码调试。具体方法是单击调试工具栏中蓝色方块按钮。或者使用快捷键Ctrl-F2。

​ 经过补丁后的程序启动后,将不再出现广告弹窗,但随之会出现一个软件注册提示框,以下介绍如果清除这个注册提示框。

3.3 注册弹窗静态代码分析与破解

​ 从软件的执行顺序可以推测软件注册对话框的启动应该是在广告弹窗的代码后面,因此重新打开IDA Pro的代码窗口,定位到前面分析的弹窗地址。

如果前面已经把弹窗地址记录下来,只要单击g,然后输入地址,就能打开到弹窗指令所在的代码位置。此时可以逐条向后分析指令,也可以继续使用调试器的F8指令,逐条指令分析。

​ 因为Winrar软件没有使用特殊的加密和混淆手段,所以可以使用更方便的方法,使用IDA Pro的Hex-Rays Decompiler插件,将汇编代码恢复成类C语言的代码分析,大大提高代码的分析效率。

​ Hex-Rays插件的激活快捷按钮为F5,在反汇编窗口单击次快捷键后,将会自动反编译成C语言,如图11。

图11 Hex-Ray反编译引擎反编译

​ 通过逐行阅读代码,注意到142行代码。

1
2
3
4
5
6
if ( v7 )
{
byte_A6A064 = 1;
v20 = GetFocus();
DialogBoxParamW(hInst, L"REMINDER", v20, sub_9C3D40, 0);
}

​ DialogBoxParamW是Windows自带的一个API函数,用于构造一个对话框窗口,其中第4个参数是指向一个窗口指向代码,双击sub_9c3D40这个子程序,得到如下代码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
BOOL __stdcall sub_9C3D40(HWND hDlg, UINT a2, WPARAM a3, LPARAM a4)
{
const wchar_t *v4; // esi
int v6; // eax
WCHAR Filename; // [esp+8h] [ebp-1004h]

if ( (unsigned __int8)sub_8FCD40(hDlg, a2, a3, a4, L"REMINDER", (int)L"HELPLicenseAndRegistering", 0) )
return 1;
if ( a2 == 273 )
{
switch ( (unsigned __int16)a3 )
{
case 1u:
EndDialog(hDlg, 1);
return 1;
case 2u:
EndDialog(hDlg, 0);
return 1;
case 3u:
// ......
// 此处省略部分代码
// ......
case 0x64u:
return 0;
case 0x65u:
GetModuleFileNameW(0, &Filename, 0x800u);
sub_968FB0(&Filename, (int)L"order.htm", 2048);
sub_9782D0(&Filename, &Filename, 2048);
if ( GetFileAttributesW(&Filename) == -1 )
{
v6 = sub_978530(0x1F5u);
sub_9BF640(v6, (unsigned int)&Filename);
}
else
{
ShellExecuteW(0, 0, &Filename, 0, &Directory, 1);
}
return 1;
case 0x66u:
v4 = (const wchar_t *)sub_978530(0x4F7u);
if ( wcschr(v4, 0x20u) )
v4 = (const wchar_t *)sub_978530(0x4F6u);
ShellExecuteW(0, 0, v4, 0, &Directory, 1);
break;
}
return 1;
}
return 0;
}

​ 此时发现第7行,27行代码中,出现的HELPLicenseAndRegistering和order.htm与软件授权注册和订单有关的英文,结合软件注册的功能,可以推测此处为注册对话框。

​ 分析至此,绕过注册对话框的方式可以通过修改142行c代码中的if语言即可。由于不能直接修改c代码,必须切换到IDA View-A反汇编界面,单击右键选择synchronize with菜单,然后选择刚才c语言伪代码窗口,笔者此时窗口为pseudocode-B,反汇编窗口会显示142行c代码中对应汇编代码。

1
2
3
4
5
6
7
8
9
10
11
12
text:00991812 loc_991812:                             ; CODE XREF: sub_991410+117↑j
.text:00991812 test bl, bl
.text:00991814 jz short loc_99183C
.text:00991816 push 0 ; dwInitParam
.text:00991818 push offset sub_9C3D40 ; lpDialogFunc
.text:0099181D mov byte_A6A064, 1
.text:00991824 call ds:GetFocus
.text:0099182A push eax ; hWndParent
.text:0099182B push offset aReminder ; "REMINDER"
.text:00991830 push hInst ; hInstance
.text:00991836 call ds:DialogBoxParamW
.text:0099183C

​ 分析以上代码第2行就是判断是否显示注册窗口,这里将jz修改成jmp指令就可以消除注册对话框。具体修改方法可以参考前面的补丁文件的方式。

4.总结

​ 通过分析Winrar弹窗代码,并进行补丁修改。可以体会到IDA Pro不但是一款强大的静态分析工具,也是具有完整动态分析能力的。由于静态分析的强大,使得在动态分析的时候,可以看到很多软件自动分析出来的辅助信息,极大的方便了代码功能的判断。例如凡是出现一个地址指向了一个字符串的指令,往往都是在后面自动添加上注释。

​ 在软件逆向分析中,分析代码的行为与本次实验中查找弹窗,改变代码功能都有类似的地方。因此可以得到一些简单的结论。

  1. 静态分析软件强大的分析功能可以有效的帮助分析人员了解代码功能和程序走向。
  2. 动态分析需要静态分析的结果会更有助于分析。
  3. 一般动态调试相比静态分析,更容易。

5.实验考核点及问题

  • Spy++软件使用,能正确查找窗口参数,如CreateWindowsExW函数所需要的参数信息。

  • IDA Pro软件断点的设置,能正确对API访问设置断点;会简单的条件断点条件的设置。

  • 掌握IDA Pro软件中正确汇编指令并制作补丁修改文件的能力。

  1. 在绕过Winrar广告窗口的操作中,需要设置断点的API是( )。
  2. IDA Pro中使用( )插件能反编译机器指令,生成的伪C程序代码。
  3. 在设置条件断点时,如果需要对左起第2个长度为4字节的参数值为0x12345678,那么条件断点的条件(Condition处)怎么写( )。
  4. IDA Pro将被分析的程序保存为扩展名为( )的数据库文件,在之后的分析过程中(要/不要)原始程序文件。
  5. IDA Pro中类似sub_1121410+3D2这样标记含义是( )。
  6. IDA Pro中给变量或者函数命名的快捷键是( )。
  7. 实验调试时,针对CreateWindowEx设置的断点,当中断到断点时,可以使用那些方法找到(或者说是返回)到这个函数调用后的用户指令的位置?请给出至少3种方案。

Winrar软件简单功能逆向分析与修改【IDA Pro动静态分析综合】
http://example.com/2024/10/24/111/Winrar软件简单功能逆向分析与修改【IDA Pro动静态分析综合】/
作者
Re1ca1g
发布于
2024年10月24日
许可协议