刚进入破解界,是使用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经常不能识别所有的用户函数,而需要手工去建立,好烦,也想写插件,因为这些都是纯体力劳动。