使用IDA5.0进行VB的逆向分析--如何减轻我的工作量?
    刚进入破解界,是使用OD。糊里糊涂的破了一个软件。后来尝试的几个,都失败了。从那开始,我接触了IDA,喜欢上看汇编来。(老实说,我是程序疯子,比较熟悉VB和汇编)
    汇编看起来就像几年前的QB的低级版本。(QB中大量存在GOTO,和汇编的JMP一样,呵呵)我学过八位、十六位汇编,以及微机原理、计算机组成原理,做过十六位算术运算器及其微指令(就是汇编下一层)设计。看到32位汇编,感觉特别爽,看E文指令总比看实验箱上的那一排排小灯爽吧。因此,我觉得看汇编并不是什么难事,只是某些新增的指令(比如浮点指令)比较难懂点。
    使用IDA反汇编VB做的软件,看到里面的一个个被识别的VB函数,特高兴。在一个函数的图形试图中,鼠标点击选中任意一个call,使得整个函数的call变成黄色底,然后从头往下看,只看VB函数,一般是__vba或rtc开头的,大概就能明白这个函数都做了哪些操作,想干嘛的了。如果觉得这个函数做了一些可以操作,比如操作注册表、操作文件,或者大量字符串运算,那么,这里可能就是注册相关的位置了。我分析的许多VB程序,就是这么干的。
    许多用VB做的系统,绝大多数都是编译成DLL,也就是COM啦。可以供别的程序调用,或者供ASP调用(这种非常多)。对付这种程序,我一般是用VB的对象浏览器查看这个COM(如何注册如果引入就不用我说了吧,对象浏览器就是F2),看看它都有哪些类,哪些属性和方法。一般来说都可以发现注册相关的地方,然后自己用VB写一点代码调用这个COM,生成EXE,再用OD加载,专门调试这个DLL,呵呵,这回就不用因为别的限制而不方便了。用OD调试到目标函数,记住地址,同时用IDA打开DLL,看对应的位置。记得在IDA中把那个函数改名哦,省得下次再看到就不知道是什么函数了。
    上面的方法,我用了很久,慢慢的,觉得很无趣了--太多了,累!
    很喜欢IDA的一些功能:
    1,标签改名。这应该是我最喜欢的了。看那种数字排序的变量名,还真是天书。因此,每当我能确定某个函数的名字的时候,就及时改名,这样所有调用这个函数的地方,名字就跟着变了。
    2,注释。这一点,一点也不比第一点差。我这里说的注释可不是像OD那样的代码注释,而是IDA里面的变量注释,或者标签注释,或者函数注释。在一个变量、标签、函数后写注释,那么,所有引用的地方,后面会紧跟着这些注释。比如你可以给一个函数写一段注释,那么在别的引用这个函数的地方,不仅能看到这个函数的“真实”名字,还能详细看到这个函数是干嘛的。
    3,双击跳转。这个功能也经常使用。近来才发现,不仅代码的标签可以双击跳转,连注释中的也可以。不要怪我孤陋寡闻,本文中我说的用法,都是我自己琢磨出来的。在图形视图中,双击某一根线,就可以跳转到另一段的代码处。对于双击的跳转,如果想回头看前面的代码,按Esc就可以了。
    对付VB的一些技巧:
    1,VB函数的参数压栈方式是从右到左,同时,因为VB是OO语言(尽管不完全是),所以,一般还有一个默认参数,就是对象自身,如果有返回值,返回值的地址,会作为第一个参数压栈。因此,完整的参数压栈方式是:[返回值地址],从右到左的参数,对象自身。
    2,了解参数压栈方式以后,我喜欢进入函数,修改该函数的本地变量名。原来都是var_XX和arg_XX形式的。首先,arg_8就是第一个参数啦,把它改名为this,当然,你要改为me或者self也行,最后一个参数arg,改为return,当然,如果这个函数没有返回值就不要这样改了。如果能通过VB的对象浏览器确定参数名,也可以在这里改名。
    3,如果知道一个函数是否有返回值?一,看调用处,第一个压栈的参数,在函数调用后,时候马上用到这个变量,如果用到,就是有返回值得;二,看函数内部,在图形视图中看,一般来说,VB的函数在图形视图中会分成三截:主题、返回处理、错误处理,一大两小并排在顶头的,看小的那两个,是否用到了最后一个arg,如果用到,就是有返回值得。这里是一般方法,不敢肯定全部都是这样。
    4,在函数头部,一般首先是一大堆var_XX,然后是arg_XX,然后处理esp,然后有一个xor eax, eax,这个eax可以是别的,异或清零,往下应该是许多mov [esp+var_XX], eax,这里就是本地变量初始化了。大多数时候,会看到一个call [XXX+4]的,这里是安装SEH用的。老实说,我不懂SEH是什么东西。不过不用管它。往后,才是正文。
    5,往下看对应着哪些参数,一般都会有copy或者move指令把参数复制一份到本地变量var_XX中,这里也改名为var_参数名,表明这是某个参数的副本。
    6,看顶头的返回处理,就是一大两小中的其中一个小,找到return,一般可以看到:
        mov ecx, [esp+return]
        mov eax, [esp+var_XX]
        mov [ecx], eax
      这里把返回值地址复制到ecx中,可以是别的寄存器,然后把一个本地变量复制到eax中,然后再写入ecx对应的位置。这里也说明了为什么一般的函数即使有指定的返回值,也会在eax中有返回值。好,把这个var_XX改为var_return。这回好了,“两头夹攻”,看中间的代码就容易多了
    7,这回得OD出场了。用OD单步跟这个函数,看看中间会不会出现某些ado.XXXXXX或者capicom.XXXXXX之类的,这些就是ADO和CAPICOM等COM的方法啦。这些方法的地址一般都是固定的,自己平时慢慢积累一些方法地址对应表,就可以在这里时候排上用场啦。
    8,在IDA中定位到这个方法出现的对应位置,往上翻,一般都可以找到一个New2,这里就是ADO对象或者CAPICOM对象的实例化的地方。New2上面的两三行中会复制一个字符串常量,那个字符串常量,就是对应的对象类名了。比如Set obj=CreateObject("ADODB.Connection"),就要复制ADODB.Connection这个字符串。呵呵,这只是我的猜测而已。这回要干的事情,首先是把这个字符串的标签改名,这样,别的要用到这个类的地方,就明显可以看得出来了。然后,New2以后会把结果复制到某个var_XX中,改名改var_对象名。
    9,轮到结构体出场了。这个var_XX,一般会这样用
        mov eax, [esp+var_XX]
        mov edx, [eax]
        call [edx+XXh] ;执行位移为XXh的方法
      这种对象定位,会让我们很郁闷,尽管我们知道绝对地址。不过,强大的IDA给我们以极大的帮助。首先建立一个结构体(比如ADOConn),具体建立方法可以看看雪学院的教程,定义一个位移是XXh的成员(比如Open),写好名字。然后在cal [eax+XXh]中的XXh上点鼠标右键,IDA就会把合适的结构成员列出来,你只需要选择就可以了。比如:ADOConn.Open。需要主意的是,如果这个对象有属性,用法会稍微不一样,比如这样:
        mov edx, [esp+var_XX]
        mov eax, [edx+XXh] ;取位移为XXh的属性
      可以看到,似乎可以理解为:方法列表的首地址就是对象的第一个成员。所以,刚才那个结构体,就不适合用了,新建一个吧,专门放属性的。此外,所有常量用右键,都可以选结构成员。当然,结构体的成员,也可以写注释,同样,出现在每个引用的地方。
    10,一个COM,除了公开的类之外,还有一些类是不公开的,对象浏览器中看不到的。但是,在文件头中,可以看到有这么一个类存在,只不过,可能需要熟悉文件格式才行。不过没关系啦,分析的时候,感觉这个类应该是哪方面的,自己起一个名字就好了,反正都是给自己看的。
    11,这些结构体,如果在每个要分析的文件中都分析一次,那多麻烦呀。没关系,IDA已经为我们准备好了。“文件”-》“创建文件”-》“创建IDC文件”,就可以导出一个文件。在另一个待分析的文件中,“文件”-》“IDC文件”,就可以导入了。这方法是我自己胡弄得知的,不知道实际上应该怎么样。

    好了,上面是我的一些想法,很高兴能和大家分享。可以看出,我可真是菜鸟一只……
    我也遇到许多问题:
    1,像上面的ADO和CAPICOM等常用COM的类库方法位移,如果有一个全面的IDC就好了。比如我在《一个软件逆向分析》一文中写到的那样,如果我有jvm.dll的IDC就好了。
    2,许多字符串常量,我根本搞不懂,IDA也不能给我正确的限制。我查资料发现,VB的字符串,在变量指向的地方的前两个字节是字符串长度,我按照这种方式建立了一个结构体,但还是看不到完整的VB字符串,我自己用VB写代码试过。
    3,IDA插件或脚本,该怎么用?怎么写?论坛上也有一些文章,但是,资料实在太少了。
    4,我想写一个插件或脚本,给常用的VB函数的参数自动写上注释,这样,我只要看注释,就可以看懂大部分内容了。其实,我很早以前就想做一个VB反编译器了,但时间和难度的问题,始终无法解决,也就作罢。现在我想在IDA的基础上做这件事情,正如前文所说,我是一个程序疯子,就喜欢写代码。
    5,VB程序的文件里面,包含着所有类的成员结构,包括属性和方法。COM中所有类(包括不公开的)的名字都有,而公开的类,有所有成员的名字。因此,我想写插件,给这些类建立对应的结构体,然后给代码中相应的地方,直接把位移值换成结构体,也就不需要一个个取选了,后面这一点可能有点难度。
    6,IDA经常不能识别所有的用户函数,而需要手工去建立,好烦,也想写插件,因为这些都是纯体力劳动。
    就写到这吧。这几天不眠不休,破了一个VB做的软件,顺便把一些经验和问题发上来。整理的时候才发现,我几乎逆向了三分之一的汇编,才写出注册机,真丢脸……

  • 标 题:答复
  • 作 者:nnhy
  • 时 间:2007-05-26 02:29

经过一周的努力,对IDA的脚本和插件,总算有了一个初步的认识。
    一般来说,代码量小,不太常用,熟悉IDC的,才写脚本。因为如果没有一定的功底,写脚本简直是天方夜谭。
    而插件就不一样了,一般可以选择使用VC来编写、编译,可以建立工程,构建较大的功能插件。此外,还可以利用VC的编译来检查语法。我比较喜欢这种方式。
    至于我前面说到的国外高手做的用C#和VB写插件,是真的。不过,实际上远没有想象中见到。它首先是用VC建立一个插件工程,这个功能很空,就一些代码,用于调用COM。这个COM嘛,当然就是用VB和C#来实现啦。在这里,有一个很致命的问题:IDA那两三百个函数,怎么办?按照作者的意思,“好办”,在VC工程中对每一个需要用到的IDA函数进行封装,导出,然后VB和C#中导入使用。事实上,VC工程,充当了一个传声筒的作用,只是,为每个内置函数做一个封装,实在是……。
    虽然我比较熟悉C++,但相比之下,更趋向于使用VB和C#来处理实际问题。以后,我一定会使用老外的这种办法来写插件,因为可以使用.Net的类库,以及高效的VS.Net开发环境。但是,现在我会选择传统的做法,使用VC来写插件,算是练好基本功吧。
    近来都比较忙,没太多时间研究。如果写IDA插件,如果编译,如果部署,这些问题都已经搞清楚,也尝试编译例子程序,并且在IDA中测试通过。有兴趣的可以一起交流(各位高手就不要笑话我等小菜了)
    我想我可以定下一步的目标:插件实现,搜索并建立所有函数、纠正被IDA适别为数据的字节码。
    定这个目标,一来是比较检查,但实用;二来是因为晚上有一个论坛里的网友问我怎么样早上函数所在。其实我也不懂,只好告诉他,搜索ebp和esp,看到push esp的多数就是了。