[原创]常见语言基础逆向方法合集
6小时前 454
初学逆向的我,每次都是拿着OD与IDA对源程序一顿撸,走了不少弯路。后面了解到各种语言编译的程序有其独特的特点与逆向方法,故这里归纳整理了自己学习到的一些方法,与大家分享,欢迎大家指正与补充。
Delphi,是Windows平台下著名的快速应用程序开发工具(Rapid Application Development,简称RAD)。它的前身,即是DOS时代盛行一时的“BorlandTurbo Pascal”,最早的版本由美国Borland(宝兰)公司于1995年开发。主创者为Anders Hejlsberg。经过数年的发展,此产品也转移至Embarcadero公司旗下。Delphi是一个集成开发环境(IDE),使用的核心是由传统Pascal语言发展而来的Object Pascal,以图形用户界面为开发环境,透过IDE、VCL工具与编译器,配合连结数据库的功能,构成一个以面向对象程序设计为中心的应用程序开发工具。
delphi字符串形式,使用Pascal形式,在字符串前存放字符串长度。
delphi函数调用约定:参数顺序为eax为第一个参数、edx为第二个参数、ecx为第三个参数,大于3个的参数通过堆栈传递,使用edx存放返回值。
IDR,针对delphi的反编译工具,反编译效果很好,该工具主要用于生成IDC文件(供IDA使用)与MAP文件(供x64dbg使用)。
PE Explorer,寻找RC数据,查看程序按钮对应的事件名称。
DarkDe,分析程序按钮和与之对应的按钮事件。
.NET框架是一个多语言组件开发和执行环境,它提供了一个跨语言的统一编程环境。.NET框架的目的是便于开发人员更容易地建立Web应用程序和Web服务,使得Internet上的各应用程序之间,可以使用Web服务进行沟通。从层次结构来看,.NET框架又包括三个主要组成部分:公共语言运行库(CLR:Common Language Runtime)、服务框架(Services Framework)和上层的两类应用模板——传统的Windows应用程序模板(Win Forms)和基于ASP.NET的面向Web的网络应用程序模板(Web Forms和Web Services)。
无论上层采用什么编程语言(C#或VB),其都会被翻译成微软中间语言(MSIL,简称IL)。对于.NET程序编译成的EXE程序,EXE程序中保存的是IL指令和元数据,并不是机器码,故无法使用IDA、OD这种工具去分析。
.Net reflector 反汇编工具,支持导出源程序源代码,但不支持动态调试功能。
Dnspy强大的反编译工具,操作界面与快捷键类似VS,支持对程序的动态调试、修改IL语言和附加进程进行调试。
dedot强大的.Net反混淆和脱壳工具
Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆于1990年代初设计,作为一门叫做ABC语言的替代品。Python提供了高效的高级数据结构,还能简单有效地面向对象编程。Python语法和动态类型,以及解释型语言的本质,使它成为多数平台上写脚本和快速开发应用的编程语言,随着版本的不断更新和语言新功能的添加,逐渐被用于独立的、大型项目的开发。
执行特点:先编译再解释执行
关键文件:.pyc文件
程序中含有大量以Py_开头的字符串
将.py文件打包成exe
本次实验使用python的pyinstaller模块(nuitka亦可),命令如下
-F:生成结果是一个exe文件,所有的第三方依赖、资源和代码均被打包进该exe内
-w:不显示命令行窗口
其它参数请读者自行查阅相关资料。
1 |
|
使用pyinstaller自带的archiv_viewer.py脚本,将exe文件反编译成.pyc文件。
1 |
|
生成的pyc文件对比原pyc文件少了头部的16个字节的信息,故此处需要用二进制编辑工具补充上(插入PYC文件头:55 0D 0D 0A 01 00 00 00 00 00 00 00 00 00 00 00 )。
最后,将pyc文件解密为源码文件,这里我使用的是该在线网站进行解密(或者使用uncompyle、easy python decompiler等工具)。
微软基础类库(英语:Microsoft Foundation Classes,简称MFC)是微软公司提供的一个类库(class libraries),以C++类的形式封装了Windows API,并且包含一个应用程序框架,以减少应用程序开发人员的工作量。其中包含大量Windows句柄封装类和很多Windows的内建控件和组件的封装类。
在VS2019中,新建一个MFC程序,在我们自己编写的事件处理函数处下断点,并查看调用堆栈信息,发现_AfxDispatchCmdMsg函数的第四个参数pfn的值即为事件处理函数的指针。
使用x64dbg加载应用程序,在MessageBoxA函数出下断点,程序断下后,查看堆栈调用信息,寻找_AfxDispatchCmdMsg函数。
接着,我们在_AfxDispatchCmdMsg函数处下断点,并运行程序,程序断下来后,第4个参数(esp+0x10)的值即为消息处理函数的地址。
此处我们可以将_AfxDispatchCmdMsg函数的特征提取为特征码,上次直接搜索定位即可,特征码为:558BEC81EC????????56578DBD????????B9????????B8CCCCCCCCF3:AB6A3368????????8B450850E8????????。
AFX_MSGMAP_ENTRY数组的声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
|
pfn的值即为回调函数的地址。同时在MFC程序中,消息映射机制分别是GetMessageMap()和GetThisMessageMap()函数。GetMessageMap()调用本类的GetThisMessageMap()函数,而GetThisMessageMap()函数中,声明了2个静态全局变量,_messageEntries数组和messageMap变量,_messageEntries数组元素的类型就是是AFX_MSGMAP_ENTRY,也就是说,在程序初始化完成后,_messageEntries数组元素的成员的pfn部门已被初始化完成。
针对按钮事件,其各个成员的值为:
nMessage=0x0111,nCode=0,nID=按钮ID,nLastID=按钮ID,nSig=58,
当ID是1000=0x03e8因此应当搜索
11 01 00 00 00 00 00 00 e8 03 00 00 e8 03 00 00 3a 00 00 00
利用WINDOWS消息处理机制
消息本身是作为一个记录传递给应用程序的,这个记录(一般在 C/C++/汇编 中称为“结构体”)中包含了消息的类型以及其他信息。例如,对单击鼠标所产生的消息来说,这个记录(结构体)中包含了单击鼠标的消息号(WM_LBUTTONDOWN)、单击鼠标时的坐标(由X,Y值连接而成的一个32位整数)。这个记录类型叫做TMsg。
当按钮有事件产生时,会给父窗口消息处理程序发送一个WM_COMMAND消息
按钮------------>系统提供WinProc---------->父窗口的WinProc
单击按钮转换 WM_COMMAND
在按钮处,下消息断点WM_LBUTTONUP或WM_LBUTTONDOWN,点击出发按钮后,在主要程序代码区下内存访问断点,同时判断程序跳转至用户代码区时,消息类型是否为WM_COMMAND。