Loading... > 本篇是关于《IDApro权威代码破解揭秘》的笔记。这一部分主要是逆向分析恶意代码和IDC脚本的编写与应用。 ## 实例分析 例子是一个广告程序,MFC写的,UPX加壳。先脱壳,这里我不用OD,直接用IDA插件自动脱壳了。之后要根据编译器手动加载签名库,首选的是`MS Visual C++ runtime`,再尝试MFC的签名库,但是我试过了还是有函数不能识别出来,可能是版本的问题,我也没有全部都试。接下来就是调试了,比较烦,这里就不记了,主要的流程就是从`AfxWinMain`开始寻找交叉引用,然后逐步分析,包括线程之间的通信,识别`mutex`变量,`CDialog`的构造函数,以及网络通信部分,包括网址的访问和下载文件的方式。具体就不写了( ̄\_, ̄ ) ## IDC 脚本 上次写了idapython的,这次是IDC,IDC是IDA的内置脚本,语法类似C,但是是脚本语言,不需要编译。 ### 变量 IDC中所有变量都是auto类型。 - 整数是32位,在IDA64中是64位 - 字符串最多包含1023个字符 - 浮点变量可以最逗有25个十进制位 **变量的声明和赋值必须在不同的语句中进行** **特殊常量:BADADDR** ### 条件 可以使用`if`、`if else`、`? :`等语句,但是没有`switch`语句。 ### 函数 IDC中的所有函数均是静态函数,例如: ```c static outputCurrentAddress(myString) { auto currAddress; currAddress = ScreenEA(); Message("%x %s \n", currAddress, myString); return currAddress; } ``` ### 全局变量 IDC不支持直接定义全局变量。不过可以通过数组来模拟全局变量。下面讲一下IDC里面全局变量的id用法,以及获取id来进行操作。 首先创建一个全局的数组变量。 ```c long CreateArray(string str); e.g: auto gArray; gArray = CreateArray("myGlobals"); ``` 注意的是,`CreateArray()`返回的是数组的id值,如果创建失败则返回-1。即`gArray`中保存了数组的id值,然后对该数组进行变量添加。 ```c success SetArrayLong(long id, long idx, long value); //根据某个数组id来设置索引为idx处的值 success SetArrayString(long id, long idx, string str); //根据某个数组id来设置索引为idx处的值 e.g: SetArrayLong(gArray, 23, 415); //将415插入到gArray数组的23索引处 SetArrayString(gArray, 0, "some string name"); //将"some string name"插入到gArray数组的0索引处 ``` 数组创建完成后,即可通过API进行访问。为了访问数组的成员,需要其id确定是哪个数组,然后通过索引来获取成员数据。 ```c long GetArrayId(string name); //根据数组名获取数组id string or long GetArrayElement(long tag, long id, long idx) //通过tag标志和数组id以及下标来获取数组元素 e.g: auto arrayid, strItem, longItem; arrayid = GetArrayId("myGlobals"); strItem = GetArrayElement(AR_STR, arrayid, 0); longItem = GetArrayElement(AR_LONG, arrayid, 23); ``` 下面我们使用common.idc来完成基本的IDC框架。 ```C #define GLOBAL_VARS "GLOBALS" #define GetGlobalVarLong(gvar) GetArrayElement(AR_LONG, GetArrayId(GLOBAL_VARS), gvar) #define SetGlobalVarLong(gvar, val) SetArrayLong(GetArrayId(GLOBAL_VARS), gvar, val) #define GetGlobalVarString(gvar) GetArrayElement(AR_STR, GetArrayId(GLOBAL_VARS), gvar) #define SetGlobalVarString(gvar, val) SetArrayString(GetArrayId(GLOBAL_VARS), gvar, val) ``` 下次使用的时候就很简单了,经过宏定义了。 ### IDC脚本框架 ```c #include <idc.idc> static function() { } static main() { } ``` 其中idc.idc定义了IDC函数中的基本原型和常量。 **补**:这里贴上一个做题用到的代码,应对程序自修改等情况。 ```c #include <idc.idc> static main() { auto a = 0x0020004b; auto i; for (i=0; i<0x2a5;) { PatchDword(a+i,Dword(a+i)^0x3f5479f1); //Message("%#x %#x\n",a+i,Dword(a+i)); i=i+4; } } ``` ### C++逆向 关于C++逆向,主要是分析虚表吧,这部分目前我还不是很懂,之后再学习了。相关链接 [C++逆向1](http://www.openrce.org/articles/full_view/21) [C++逆向2](http://www.openrce.org/articles/full_view/23) ### 有用的IDC函数 关于数据读写的函数如下。 ```c long Byte(long ea); //获取某个地址的字节 long Word(long ea); //获取某个地址的字 long Dword(long ea); //获取某个地址的双字 void PatchByte(long ea, long value); //修改某个地址的字节 void PatchWord(long ea, long value); //修改某个地址的字 void PatchDword(long ea, long value); //修改某个地址的双字 ``` 关于注释和代码遍历的函数如下。 ```c success MakeComm(long ea, string comment); success MakeRptCmt(long ea, string comment); ……还有好多。 long NextAddr(long ea); long NextFunction(long ea); long NextHead(long ea, long maxea); long NextSeg(long ea); long PrevAddr(long ea); long PrevFunction(long ea); long PrevHead(long ea, long minea); # 迭代输出本段中的所有函数 auto currAddr, func, endSeg, funcName, counter; currAddr = ScreenEA(); func = SegStart(currAddr); endSeg = SegEnd(currAddr); counter = 0; while (func != BADADDR && func < endSeg) { funcName = GetFunctionName(func); if (funcName != " ") { Message("%x: %s\n", func, funcName); counter++; } funcName = NextFunction(func); } Message("%d functions in segment: %s\n", counter, SegName(currAddr)); ``` 关于其他的交叉引用的函数、数据表示的函数、输入输出的函数,比较冗杂,需要用的时候查就行了。 ### 关于IDA插件编写 这部分暂时用不到,而且IDA7.0更新了SDK,导致之前版本的插件都要重写,没有学习的必要,先掌握IDC和idapython就好了。 ``` ``` Last modification:January 16th, 2021 at 01:58 pm © 允许规范转载 Support 确定不打赏一下支持博主吗 ×Close Appreciate the author Sweeping payments Pay by AliPay