class字节码修改(以16进制编辑器)


网上有好多都是反编译,然后拷贝到项目下,进行修改。这种只能针对没有混淆源码的class文件。
还有就是用 javassist.jar 包修改的,这种针对混淆源码厉害的,也是无能为力。
下面是我自己的修改方法,在网上找了好多资料才整理出来的。

修改原理

1、使用反编译器查看源码(经测试 luyten 比较好,对于混淆严重的也支持),找到要修改的位置(找不到就不用说了)
2、然后使用 classpy 查看字节码 ,并且可以查看字节码对应的16进制位置 (自己搜索如何查看字节码)
3、找到要修改的代码,并且找到要修改后的字符对应的字节码,再根据字节码转换为16进制
4、将找到的16进制数字替换原16进制数字
5、再反编译修改后的class文件,看是否已经修改正确

需要用到的工具在资源中,也可以自行下载

修改流程

直接看具体例子
我的class文件

1、使用反编译查看源码

下载 luyten.exe 打开class 或者 jar 包即可 ( 资源链接中包含了)
在这里插入图片描述

2、classpy.jar 查看字节码

如果不会看字节码,学习链接
Java虚拟机字节码指令 https://www.cnblogs.com/yelao/p/9492238.html
java 虚拟机字节码指令表 https://blog.csdn.net/YY_xiaozhu/article/details/81108601

首先运行
java -jar classpy-0.6.jar
在这里插入图片描述
打开 CtPrimitiveType.class 文件
在这里插入图片描述
在这里插入图片描述

这里解释下code下这几行的意思:
对应代码

 public void isPrimitive() {
        int a = 32;
        if(a > 100){
            int b = 1000;
        }
    }
代码				16进制数		字节码意思												行意义							
00: bipush 32  		10 20       将单字节的常量值(-128~127) 推送至栈顶     				10 对应 bipush ,32的16进制是20         		    		
02: istore_1		3C          将栈顶 int 型数值存入第二个局部变量						3C 对应	istore_1	      			    		
03: iload_1			1B          将第二个 int 型局部变量推送至栈顶							1B 对应	iload_1	       			    		
04: bipush 100		10 64       将单字节的常量值(-128~127) 推送至栈顶                    10 对应 bipush ,100的16进制是64         		            
06: if_icmple 13	A4 00 07    比较栈顶两 int 型数值大小,当结果小于等于 0 时跳转到13行     A4 对应	if_icmple ,13 我也不清楚为啥用 00 07 表示	                        
09: sipush 1000		11 03 E8    将一个短整型常量值(-32768~32767) 推送至栈顶              11 对应	sipush ,1000的16进制是 03 E8            	            
12: istore_2		3D          将栈顶 int 型数值存入第三个局部变量                        3D 对应	istore_2      			            
13: _return			B1          从当前方法返回 void                                      B1 对应 _return      			                     			            

3、修改字节码

3.1 先修改大于号

在这里插入图片描述
在这里插入图片描述
A4 对应的是 小于等于,然后跳到13行结束,咱们要改为 a<100,就是要 大于等于 的时候结束
大于等于 对应的 16 进制是 A2 ,修改 A4 为 A2
在这里插入图片描述
使用 MadEdit.exe 打开 class 文件修改后保存
在这里插入图片描述
反编译修改后的文件,已经修改成功
在这里插入图片描述

3.2 修改 32 为 2100000000

这个修改需要涉及到常量池,栈顶不能直接存储 2100000000 这个数值,所以只能从常量池中取。
1、存储 2100000000 到常量池
首先修改常量池中常量的个数,由14 改为 15
在这里插入图片描述
然后在常量池的最后添加一个常量:int 类型的 2100000000
int 的16进制字节码是 03 (为什么是03,自己写一段包含常量的代码 如 int a = 2100000000,看看字节码就知道了)
2100000000 的16进制字节码是 7d 2b 75 00 (下图改错了,改为了 7b 2b 75 00 ,意思差不多)
在这里插入图片描述
2、引用常量池中的变量替换32这个数字
在这里插入图片描述
使用 ldc 或者 ldc_w,“宽索引”的意思就是“常量的索引” 用2位“16进制数”无法表示,得用4位
这里使用 ldc 即可
咱们增加常量的时候,是在19后边添加的,所以新加的常量索引是20,用 “ldc 字节码 + 索引号的16进制 ” 即可
应该是 12 14
保存后反编译查看
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4、反编译class文件查看

已经修改成功
在这里插入图片描述

到这里就大功告成了,希望对你有帮助

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值