目录
1. 字节码文件结构
2. 字节码文件实战
2.1 常量池表?
?2.2 访问标记符号
2.3 this class Name,super class name,interfaces_count,fields_count
2.4 fields(TODO)
?2.5 methods_count
2.5.1 code内容?
?2.6 附加属性
1. 字节码文件结构
应用场景:入狱小技巧,通过学懂字节码文件,然后篡改其他服务器上的字节码文件。
使用javap -v *.class 查看字节码文件,字节码文件遵循一定的规律。规律如下图

2. 字节码文件实战
本地随便找的一个字节码文件,用UE打开以后显示如下。解读如下,默认都是16进制。
1.固定魔法值:CA FE BA BE
2.次版本号:00 00
3.主版本号:00 34 (转换成10进制->4*16^0+3*16^1=52 ,52对应jdk1.8 51对应jdk1.7)
?4.常量池个数:00 1B(->27,有27个常量,默认第一个为Null,正常使用javap -v显示常量池26个。)
??
2.1 常量池表?
?5.常量池表:
第一个常量:
0A(->10,Method_info对应下图) 00 05(->5,class_index(类索引)) 00 16 (->22,方法索引)
对应object类,init构造方法。
第二个常量:
09(->field_info字段名称) 00 04(->4,类索引) 00 17(->23)
第三个常量
08(->8,string_info) 00 18(->24,字符串)
第四个常量
07(->7,class info) 00 19(->25,类名object)
第五个常量
07(->7,class info) 00 1A(->26,类名object)
第六个常量
01(->1,标志位) 00 04(->4,长度,往后数4个字节) 6E 61 6D 65(ASCII码值,->n a m e)
第七个常量
01(->1,标志位) 00 12(->18,长度,往后数18个字节) 4C 6A 61 76 61 2F 6C 61 6E 67 2F 53 74 72 69 6E 67 3B (ASCII码值,->L j a v a / l a n g / St r i n g ;)?
第八个常量
01(->1,标志位) 00 06(->6,长度,往后数6个字节) 3C 69 6E 69 74 3E(ASCII码值,->< i n i t >)
第九个常量
01(->1,标志位) 00 03(->3,长度,往后数3个字节) 28 29 56(ASCII码值,->( ) V)
其他都类似,值得注意的:
LineNumberTable-对应原代码行数,打印异常时我们看到的行号
LocalVariableTable-局部变量表,在每个方法区都有一个locals=1,代表this,可以在方法中调用类对象。


?
?
?2.2 访问标记符号
?用UE可以选定常量池范围,在Object后面是访问标记符号
00 21(0x0001-ACC_PUBLIC Ox0020-ACC_SUPER代表公共和父类)


?
2.3 this class Name,super class name,interfaces_count,fields_count
this class Name:00 04(->4,指向常量池第4个常量,也就是类名)
super class Name:00 05(->5,指向常量池第5个常量,也就是object类名)
interfaces_count:00 00(0000代表FFFF->15*16^0+15*16^1+15*16^2+15*16^3=65535,代表类最多实现65535个接口)
interfaces:
fields_count:00 01(->1,代表1个字段name)
2.4 fields(TODO)
描述一个类的字段三要素:访问修饰符,类型,字段名称。?
参照如下field_info字段表结构:
00 02(->2,ACC_PRIVATE):表示私有的
00 06(->6,字段名称,对应常量表第6个常量,name)
00 07(->7,字段类型,对应常量池第7个常量,Ljava/lang/String;也就是string)
00 00(->0,属性表个数,判断是否有volatile等修饰,没有为0)
00 04(->4,attributes,代表属性表个数,暂时不知道什么意思)

?
?2.5 methods_count
推荐使用idea的jclasslib插件也可以查看,plugins直接搜索安装即可。ieda查看视窗路径:View->show bytecode with jclasslib
可以看到下图类中有4个方法:构造方法,3个其他方法。
后面的字节码位置,如果看不懂可以按住ctrl点击即可跳转到jvm规范,查看文档。
?
?类方法结构如下:
00 01(->4,权限修饰符):ACC_PUBLIC
00 08(->8,方法名称,指定常量池第8个常量):<init>
00 09(->9,方法描述索引,指定常量池第9个常量):()V,代表无参数,无返回值
00 01(->1),属性表个数有1个
00 0A(->10,属性名称指向常量值索引的第10个位置):Code
?
?
?
?
2.5.1 code内容?
00 00 00 33(->51,往后属51个字节的内容是code的内容):
00 01(->1,最大操作数桟):code下面有个stack =1就是最大操作数栈,也就是桟帧中的操作数栈的长度。
00 01(->1,局部变量表的个数为1):locals=1
00 00 00 05(->5,指令码长度5,往后数5个字节)
2A B7 00 01 B1(->使用jclasslib工具查看按住ctrl查看如下内容):aload_0,invokespecial 00 01指向常量池第一个变量,B1->
0 aload_0 1 invokespecial #1 <java/lang/Object.<init> : ()V>() 4 return
00 00(->0,不抛出异常)
00 02(->2,code属性表的个数为2)
00 0B(->11,指向常量池第11个位置):LineNumberTable
00 00 00 0A(->10,行号表个数为10,往后数10位为LineNumberTable行号表内容)
00 02(->2,指令码与源码映射的对数,2对)
00 00(->0,指令码行数):0
00 22(->34,源码映射34行)
00 04(->4,指令码行数):4
00 23(->35,源码映射35行)
00 0C(->12,指向常量池第12位):LocalVariableTable
00 00 00 0C(->12,局部变量表长度,往后数12个字节描述LocalVariableTable):12
00 01(->1,局部变量个数1个)
00 00(->0,局部变量偏移量从0开始)
00 05(->5,作用范围覆盖的长度5)
00 0D(->13,指向常量池13位):this
00 0E(->14,局部变量描述符索引):Lorg/apache/myfaces/blank/HelloWorldController;
00 00(->0,这个局部变量在桟帧局部变量表中slot的位置)
?
?
?
?
?
?2.6 附加属性
后面没再数了,字节码如下:
00 01 00 0F 00 10 00 01 00 0A 00 00 00 2F 00 01 00 01 00 00 00 05 2A B4 00 02 B0 00 00 00 02 00 0B 00 00 00 06 00 01 00 00 00 27 00 0C 00 00 00 0C 00 01 00 00 00 05 00 0D 00 0E 00 00 00 01 00 11 00 12 00 01 00 0A 00 00 00 3E 00 02 00 02 00 00 00 06 2A 2B B5 00 02 B1 00 00 00 02 00 0B 00 00 00 0A 00 02 00 00 00 2A 00 05 00 2B 00 0C 00 00 00 16 00 02 00 00 00 06 00 0D 00 0E 00 00 00 00 00 06 00 06 00 07 00 01 00 01 00 13 00 10 00 01 00 0A 00 00 00 2D 00 01 00 01 00 00 00 03 12 03 B0 00 00 00 02 00 0B 00 00 00 06 00 01 00 00 00 32 00 0C 00 00 00 0C 00 01 00 00 00 03 00 0D 00 0E 00 00 00 01 00 14 00 00 00 02 00 15

?
|