专栏名称: 吾爱破解论坛
吾爱破解论坛致力于软件安全与病毒分析的前沿,丰富的技术版块交相辉映,由无数热衷于软件加密解密及反病毒爱好者共同维护,留给世界一抹值得百年回眸的惊艳,沉淀百年来计算机应用之精华与优雅,任岁月流转,低调而奢华的技术交流与探索却
目录
相关文章推荐
猿大侠  ·  Chrome 被强制出售?谷歌或将抛弃 ... ·  2 天前  
猿大侠  ·  Chrome 被强制出售?谷歌或将抛弃 ... ·  2 天前  
大象击股  ·  快看!一个好信号!!! ·  2 天前  
大象击股  ·  快看!一个好信号!!! ·  2 天前  
法学学术前沿  ·  学术 | 郭旨龙:论预备行为的风险评价 ·  4 天前  
法学学术前沿  ·  学术 | 郭旨龙:论预备行为的风险评价 ·  4 天前  
51好读  ›  专栏  ›  吾爱破解论坛

破解 jar 包之直接修改 .class 文件方式

吾爱破解论坛  · 公众号  · 互联网安全  · 2016-12-03 10:17

正文

一、常规 JAVA 软件破解流程

先讲一下常规jar包的破解流程。

1. 快速定位。

         1) 通过procmon监控相关软件,查看程序都访问了些啥。
         2) 用jd-gui反编译 jar 包,得到源码。
         3) 搜索关键字以定位。

这种定位方法只是千万种中的一种,根据不同软件的不同执行特性再具体实施不同的定位方案。

2. 修改破解。

1) 用 dex2jar 将 JAR 包转成 Dex 文件。
         2) 再将 Dex 解出 Smali。
         3) 修改 Smali 代码
         4) 将修改后的文件重新打包回 Dex
         5) 最后转成 JAR 包,破解完成。


二、直接修改 .class 字节码的方式实现破解

上面的方式基本已经可以解决破解JAR包的需求。但最近研究了一下直接修改.class 字节码的形式来实现修改程序流程的方法,总有会用得上的应用场景的。下面进入正题。

很多时候别人的 jar 包,反编译过来后是没办法直接用Eclipse创建java 工程再编译通过的。各种引用及反编译带来的错误会让人抓狂。既然破解的关键点已经找到了,我们可以不可以直接修改.class 字节码以实现破解呢,答案是肯定的。

此处省略定位环节,不是本文重点。


准备工具

1.      jclasslib 源码地址:https://github.com/ingokegel/jclasslib

2.      010 Editor 神器不多说


参考资料

1.      The class file format

https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.6

2.      中文版Class文件结构

http://gityuan.com/2015/10/17/jvm-class-instruction/


Start

假设通过反编译我们已经知道了关键代码的位置。

知道函数路径后,用jclasslib 打开 .class 文件定位的相关函数处。


点击右边的相关指令可以跳转到指令查询页面:


可以看到 aload_0 对应的字节码为 0x2a。以此类推,查询到我们需要的特征指令对应的字节码。

指令:

1

2

3

4

5

aload_0

ifnonnull 6 (+5)

iconst_5

ireturn

aload_0


字节码

1

2a c7 xx xx 08 ac 2a (xx xx 是 ifnonnull 后面跟的 2 字节立即数)


用 010 Editor 打开 .class 文件,会自动加载其文件格式的 .bt 格式解析文件



通过jclasslib 我们知道目标函数在methods 函数表中的19号索引位置,用010找到相应的位置


通过 .class 文件结构我们知道,具体代码在 struct attribute_info attributes 里面 u4attribute_length 描述了代码区长度。接着下面给出了以1字节为单位的代码区数组。通过查询 attribute_info 结构体我们知道这里的 info 数组其实还包含了很多结构信息在里面,我们可以手工对应一下。


因为我们查看的是 Methods表 u2 attribute_name_index 通常指向的是 Code 结构体,表明这段结构体是 Code 结构体。看一下 Code 结构的说明:

01

02

03

04

05

06

07

08

09

10

11

12

13

14

15

16

Code_attribute{

    u2 attribute_name_index;

    u4 attribute_length;

    u2 max_stack;

    u2 max_locals;

    u4 code_length;

    u1 code[code_length];

    u2 exception_table_length;

    {  u2 start_pc;

        u2 end_pc;

        u2 handler_pc;

        u2 catch_type;

    } exception_table[exception_table_length];

    u2 attributes_count;

    attribute_infoattributes[attributes_count];

}



通过jd-gui 反编译时我们已经知道,这个函数返回的是一个Int型数值,函数体内做了一些判断处理,这里我们将把这个函数修改成直接返回我们需要的数值。

比如 return 1000;

上面这句话对应jvm 指令为:

1

2

sipush 1000

ireturn


对应的字节码是:

1

11 03 E8 AC (03 E8= 1000数字是高字节序)


修改完后的样子



然后,结构体后面多余的字节就可以直接删除了。

现在大功告成,将修改后的 .class 文件替换原来的就可以了。


需要注意的细节坑

1.010 Editor在解析 .class 常量池数组时对 01 0000 (空的 CONSTANT_Utf8 类型)的支持不好,可能导致出错。调试时可以先将出错的这三个字节码删除,并对应修改constant_pool_count 常量池个数,再按 F5 重新解析。

注意:此时索引的序号指向可能是错的,可以结合 jclasslib 查看对应值。

2.重新打包 JAR 包,运行时提示"AWT-EventQueue-0" java.lang.SecurityException: SHA-256 digesterror for ***.class 。查看Manifest文件看看有没有RSA 加密设定,如果有直接删除,再打包运行就可以了。


大大们有更好更简洁的方法还请不吝赐教!


--官方论坛

www.52pojie.cn

--推荐给朋友

公众微信号:吾爱破解论坛

或搜微信号:pojie_52