当前位置:首页 > 0AOOUT反汇编CLASS初级教程
它。但是我们现在要说的是逆向反汇编分析的过程。显然,我们应该在具有包含了DataInputStream这样的类中查找,因为这样才能找到源代码中关于读取的部分。看来类有点多,从a开始逐一打开,没有引用io包的类可以简单不看。首先,在c.class中我们找到了蛛丝马迹:
public c(Image image, DataInputStream datainputstream, Font font,int i, int j)
呃,有个Image,貌似和我们读取文本没关系。继续看下去,看起来是绘制图片的。这一点我们简单忽略。接下来的几个部分也差不多。接下来我们遇到了DCTuxedo.class,这个类大概30多K,看起来很大,应该是游戏的重要部分,但我们不清楚它到底是干什么的。查找DataInputStream。发现很多函数有利用,首先是:private static void n(){……….. 其中有这样的代码:
if((abyte0 = f.a(\try { ByteArrayInputStreambytearrayinputstream = new ByteArrayInputStream(abyte0); DataInputStreamdatainputstream; a_byte_static_fld =(datainputstream = new DataInputStream(bytearrayinputstream)).readByte(); g_int_static_fld =datainputstream.readByte(); i_int_static_fld =datainputstream.readInt(); j_int_static_fld =datainputstream.readInt();
for(int i1 = 0; i1 for(int k1 = 0; k1 f_int_static_fld =datainputstream.readByte(); break label0; } 我们已经确定资源文件至少有偏移量表+utf-8文本组成,想到这一点,也许再加个条件,寻找如readUTF这样的系统调用。这个DC类中是没有了。再注意看上面的代码,其中有f.a(―g‖)这样的调用,我们知道一个良好的系统中很少出现硬编码,也许我们可以在f中寻找蛛丝马迹。简单的浏览一遍e,并没有上面发现。打开f,眼前一亮:它从GameCanvas中继承过来并实现了KeyPressed事件。也许我们可以从它来修改键盘J.但这不是这里要讨论的。查找readutf ,果然,装了个马甲躲这里!函数原本如下: public staticString a(int l) { String s = null; if(l != -1) try { int i1 = l >>> 16; int j1 = l & 0xffff; String s1; a(s1 = \ byte abyte0[] = b(j1); DataInputStreamdatainputstream; s=(datainputstream=new DataInputStream(newByteArrayInputStream(abyte0))).readUTF(); datainputstream.close(); } catch(Exception _ex) { } return s; } 这里我们看到一个更重要的函数重载调用:a(s1= \i1);,我们已经知道,语言包的名字是lx_0,看来这个a(string)的调用就是读取字符串指定的语言包。其中k指定了语言,0就是英文了。i1这里总是0的。(也许我们一开始在HALO中寻找有‖l‖的文本会快一些J) 很遗憾DJ并没有右键转到定义之类的便捷功能,我们只能在下方的函数列表中寻找,在众多的a,b,c,d函数重载中,我们找到了void a(string)这个(或许直接搜索‖void a(string‖ 会更快): private staticvoid a(String s) { if(s.equals(c_java_lang_String_static_fld)) return; e.b(); c_java_lang_String_static_fld = s; try { switch(j) { case 0: // '\\0' a_byte_array1d_static_fld = newbyte[4]; InputStream inputstream; (inputstream =a_f_static_fld.getClass().getResourceAsStream(s)).read (a_byte_array1d_static_fld,0, 4); int l = b(0); int i1 = 4; a_byte_array1d_static_fld = newbyte[l]; for(; i1 < l; i1 +=inputstream.read(a_byte_array1d_static_fld, i1, l - i1)); inputstream.close(); break; case 1: // '\\001' a_byte_array1d_static_fld =a(s); // fall through case 2: // '\\002' default: return; } } 这个显然是修改语言调用的函数。首先和已经使用的语言比较,如果相同,没有必要更换则返回。接着,e.b()是挂起游戏或者类似排他锁之类的东西,和这里的分析无关。接下来改变静态字符串c_java_lang_String_static_fld。接着在开关语句中,我们找到了要找的,已经用黑色斜体标记出来。首先读取资源,接着将资源放入内存缓冲数组,就不用再次读了。显然静态字段a_byte_array1d_static_fld储存的是这些数据,我们只要在文件中查找这个也许能找到解读方式。注意到for语句中的read的偏移初始值为4,长度为l-4,也就是从文件4字节以后开始读。前面4个字节保存在l中,a_byte_array1d_static_fld的长度是l,显然,l是整个文件的长度。但是在第一次分析中,前面4个字节是00 00 29 3E,经典的―little endian‖,在这里没用,也许需要其他的解码方式?我们再往前看一行 a_byte_array1d_static_fld = new byte[4]; 这里验证了我们的想法,首先读取文件的开始4个字节。接下来关注的是对l赋值的b(0) 函数。找到函数int b(int): private staticint b(int l) { return (a_byte_array1d_static_fld[l]& 0xff) << 24 | (a_byte_array1d_static_fld[l + 1] & 0xff)<< 16 | (a_byte_array1d_static_fld[l + 2] & 0xff) << 8 |a_byte_array1d_static_fld[l + 3] & 0xff; } 很好,这里将操作了缓冲区。将连续位置l后连续4个字节作为整数打包:其格式是数组低位字节在整数的高字节,很好,原来是Big Enidan。(众人:一开始这么想就不会看这么多了。。。呃,凡事总有个成长过程嘛..) 回到UE中,我们计算出00 00 29 3E实际上就是10058,和UE下方给出的文件总长度一致!好了我们又迈出了一步。这立即让我想起了handy-games公司的 lng 格式,只不过其字节顺序相反而已。顺着这样的思路,接下来4个字节00 00 00 C4,极可能是文本数量。然后是文本偏移表,当然我不会笨的来去数到底有多少个字符串以验证这一点,不过立即可以操作的是看后面的偏移表的总长度。如果猜测正确,其长度不会和C4*4=(784)差异多少,由于每个表项是Big Endian 的4字节,所以如果有误差也只会是4的倍数。用UE全选偏移表,立即计算出刚好是 784 个字节!尝试定位第一个字符串:00 00 03 18,结果在318H处找到了字符串English的开头处: 下载 (9.75 KB) 2007-10-25 00:28 看来,依赖于修改版UTF-8的优势,并没有出现偏移需要修正的情况。同时我们也注意到偏移表的最末字节00 00 29 38,到达02938H这里,刚好是最后一个字符串的开头。于是每个字符串的长度就可以用偏移量来求,得出公式: 文本i的长度 = 偏移量 i+1 – 偏移量 (1) 然而这里有n个字符串,显然最后一个字符串无法用这个公式计算,但是我们知道文件总长度,于是得出计算最后一个文本长度的公式: 最后一个文本的长度 = 文件长度-偏移量n (2) 好了,用UE简单验证下公式的正确性,继续我们的decompiling. 函数a(string)接下来就完了,b(int)也就做了打包整数的工作,我们没有找到完全读取的算法,我们知道缓冲区叫a_byte_array1d_static_fld,接着寻找这个串就可以了。很幸运的,在前面一点的距离,我们找到了函数 byte[] b(int l): private staticbyte[] b(int l) { int i1 = a_byte_array1d_static_fld.length; int j1 = b(4); int k1 = b(8 + l * 4); int l1; if(l == j1 - 1) l1 = i1 - k1; else l1 = b(8 + l * 4 + 4) - k1;
共分享92篇相关文档