Class文件解析(class文件解密)

  本篇文章为你整理了Class文件解析(class文件解密)的详细内容,包含有class文件详解 class文件解密 class文件有什么用 classin解析包出现问题是怎么回事 Class文件解析,希望能帮助你了解 Class文件解析。

  

 public static byte[] getFileBytes(File file) {

 

   try (FileInputStream fileInputStream = new FileInputStream(file)) {

   int available = fileInputStream.available();

   byte[] data=new byte[available];

   fileInputStream.read(data,0,available-1);

   return data;

   } catch (Exception e) {

   e.printStackTrace();

   return null;

  

 

  这里使用jdk的ByteBuffer包装bytes

   ByteBuffer data = ByteBuffer.wrap(getFileBytes(file));

  因为ByteBuffer没有无符号的读取方法,所以自己实现一下,也可以直接用netty的Bytebuf,里面方法齐全

  

 // 图方便直接返回int

 

   private int readUnsignedByte(ByteBuffer data) {

   return data.get() 0xff;

   // 图方便直接返回int

   private int readUnsignedShort(ByteBuffer data) {

   return data.getShort() 0xffff;

   private long readUnsignedInt(ByteBuffer data) {

   return data.getInt() 0xffffffffL;

  

 

  定义class文件结构

  参考: https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html

  

 private static class ClassFileStructure {

 

   long magic;

   int minorVersion;

   int majorVersion;

   int constantPoolCount;

   ConstantPool[] constantPool;

   int accessFlags;

   int thisClass;

   int superClass;

   int interfacesCount;

   int[] interfaces;

   int fieldsCount;

   FieldInfo[] fields;

   int methodsCount;

   MethodInfo[] methods;

   int attributesCount;

   AttributeInfo[] attributes;

  

 

  2 开始解析

  2.1 magic

  

 private void magic(ClassFileStructure structure, ByteBuffer data) {

 

   structure.magic = readUnsignedInt(data);

  

 

  2.2 minorVersion

  

 private void minorVersion(ClassFileStructure structure, ByteBuffer data) {

 

   structure.minorVersion = readUnsignedShort(data);

  

 

  2.3 majorVersion

  

 private void majorVersion(ClassFileStructure structure, ByteBuffer data) {

 

   structure.majorVersion = readUnsignedShort(data);

  

 

  2.4 constantPoolCount

  

 private void constantPoolCount(ClassFileStructure structure, ByteBuffer data) {

 

   structure.constantPoolCount = readUnsignedShort(data);

  

 

  2.5 ConstantPool[]

  ConstantPool不同tag解析方式不同,定义抽象类ConstantPool,子类按规则解析

  

 private abstract static class ConstantPool {

 

   int tag;

   public ConstantPool(int tag) {

   this.tag = tag;

   abstract void parse(ByteBuffer data);

  

 

  子类实现ConstantPool
 

  ConstantUtf8:

  

 private class ConstantUtf8 extends ConstantPool {

 

   int length;

   byte[] bytes;

   public ConstantUtf8(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.length = readUnsignedShort(data);

   bytes = new byte[this.length];

   for (int i = 0; i this.length; i++) {

   bytes[i] = (byte) readUnsignedByte(data);

  

 

  ConstantMethodHandle:

  

 private class ConstantMethodHandle extends ConstantPool {

 

   short referenceKind;

   int referenceIndex;

   public ConstantMethodHandle(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.referenceKind = (short) readUnsignedByte(data);

   this.referenceIndex = readUnsignedShort(data);

  

 

  ConstantMethodType:

  

 private class ConstantMethodType extends ConstantPool {

 

   int descriptorIndex;

   public ConstantMethodType(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.descriptorIndex = readUnsignedShort(data);

  

 

  ConstantClass:

  

private class ConstantClass extends ConstantPool {

 

   int nameIndex;

   public ConstantClass(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.nameIndex = readUnsignedShort(data);

  

 

  ConstantClass:

  

 private class ConstantClass extends ConstantPool {

 

   int nameIndex;

   public ConstantClass(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.nameIndex = readUnsignedShort(data);

  

 

  ConstantFieldref:

  

 

 

  private class ConstantFieldref extends ConstantPool {

   int classIndex;

   int nameAndTypeIndex;

   public ConstantFieldref(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.classIndex = readUnsignedShort(data);

   this.nameAndTypeIndex = readUnsignedShort(data);

  

 

  ConstantMethodref:

  

private class ConstantMethodref extends ConstantPool {

 

   int classIndex;

   int nameAndTypeIndex;

   public ConstantMethodref(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.classIndex = readUnsignedShort(data);

   this.nameAndTypeIndex = readUnsignedShort(data);

  

 

  ConstantInterfaceMethodref:

  

 private class ConstantInterfaceMethodref extends ConstantPool {

 

   int classIndex;

   int nameAndTypeIndex;

   public ConstantInterfaceMethodref(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.classIndex = readUnsignedShort(data);

   this.nameAndTypeIndex = readUnsignedShort(data);

  

 

  ConstantString:

  

 private class ConstantString extends ConstantPool {

 

   int stringIndex;

   public ConstantString(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.stringIndex = readUnsignedShort(data);

  

 

  ConstantInteger:

  

private class ConstantInteger extends ConstantPool {

 

   long bytes;

   public ConstantInteger(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.bytes = readUnsignedInt(data);

  

 

  ConstantFloat:

  

private class ConstantFloat extends ConstantPool {

 

   long bytes;

   public ConstantFloat(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.bytes = readUnsignedInt(data);

  
ConstantNameAndType:

  

 private class ConstantNameAndType extends ConstantPool {

 

   int nameIndex;

   int descriptorIndex;

   public ConstantNameAndType(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.nameIndex = readUnsignedShort(data);

   this.descriptorIndex = readUnsignedShort(data);

  

 

  ConstantInvokeDynamic:

  

 private class ConstantInvokeDynamic extends ConstantPool {

 

   int bootstrapMethodAttrIndex;

   int nameAndTypeIndex;

   public ConstantInvokeDynamic(int tag) {

   super(tag);

   @Override

   void parse(ByteBuffer data) {

   this.bootstrapMethodAttrIndex = readUnsignedShort(data);

   this.nameAndTypeIndex = readUnsignedShort(data);

  

 

  以上是所有 constantPool 子类型,现在开始解析

  坑:“所有 8 字节常量都占用文件constant_pool表中的两个条目class。 如果
 

  CONSTANT_Long_infoorCONSTANT_Double_info结构是constant_pool表中索引n处的项目,则池中的下一个可用项目位于索引n +2 处。
 

  constant_pool 索引n +1 必须有效但被视为不可用 。 回想起来,让 8 字节常量占用两个常量池条目是一个糟糕的选择。”

  

 private void constantPool(ClassFileStructure structure, ByteBuffer data) {

 

   structure.constantPool = new ConstantPool[structure.constantPoolCount - 1];

   for (int i = 0; i structure.constantPool.length; i++) {

   int type = readUnsignedByte(data);

   int index = i;

   switch (type) {

   case 1: //

   structure.constantPool[i] = new ConstantUtf8(type);

   break;

   case 3: //

   structure.constantPool[i] = new ConstantInteger(type);

   break;

   case 4:

   structure.constantPool[i] = new ConstantFloat(type);

   break;

   case 5:

   structure.constantPool[i] = new ConstantLong(type);

   i++;// 占2位

   break;

   case 6:

   structure.constantPool[i] = new ConstantDouble(type);

   i++;// 占2位

   break;

   case 7: //

   structure.constantPool[i] = new ConstantClass(type);

   break;

   case 8: //

   structure.constantPool[i] = new ConstantString(type);

   break;

   case 9: //

   structure.constantPool[i] = new ConstantFieldref(type);

   break;

   case 10: //

   structure.constantPool[i] = new ConstantMethodref(type);

   break;

   case 11: //

   structure.constantPool[i] = new ConstantInterfaceMethodref(type);

   break;

   case 12: //

   structure.constantPool[i] = new ConstantNameAndType(type);

   break;

   case 15: //

   structure.constantPool[i] = new ConstantMethodHandle(type);

   break;

   case 16: //

   structure.constantPool[i] = new ConstantMethodType(type);

   break;

   case 18: //

   structure.constantPool[i] = new ConstantInvokeDynamic(type);

   break;

   default:

   throw new ParserException("class file parser exception");

   structure.constantPool[index].parse(data);

  

 

  2.6 accessFlags

  

 private void accessFlags(ClassFileStructure structure, ByteBuffer data) {

 

   structure.accessFlags = readUnsignedShort(data);

  

 

  2.7 thisClass

  

 private void thisClass(ClassFileStructure structure, ByteBuffer data) {

 

   structure.thisClass = readUnsignedShort(data);

  

 

  2.8 superClass

  

 private void superClass(ClassFileStructure structure, ByteBuffer data) {

 

   structure.superClass = readUnsignedShort(data);

  

 

  2.9 interfacesCount

  

 private void interfacesCount(ClassFileStructure structure, ByteBuffer data) {

 

   structure.interfacesCount = readUnsignedShort(data);

  

 

  2.10 int[] interfaces

  

 private void interfaces(ClassFileStructure structure, ByteBuffer data) {

 

   structure.interfaces = new int[structure.interfacesCount];

   for (int i = 0; i structure.interfacesCount; i++) {

   structure.interfaces[i] = readUnsignedShort(data);

  

 

  2.11 fieldsCount

  

 private ClassFile fieldsCount(ClassFileStructure structure, ByteBuffer data) {

 

   structure.fieldsCount = readUnsignedShort(data);

   return this;

  

 

  2.12 FieldInfo[] fields

  FieldInfo:

  

 private class FieldInfo {

 

   int accessFlags;

   int nameIndex;

   int descriptorIndex;

   int attributesCount;

   AttributeInfo[] attributes;

   public FieldInfo parse(ByteBuffer data) {

   this.accessFlags = readUnsignedShort(data);

   this.nameIndex = readUnsignedShort(data);

   this.descriptorIndex = readUnsignedShort(data);

   this.attributesCount = readUnsignedShort(data);

   this.attributes = new AttributeInfo[attributesCount];

   for (int i = 0; i this.attributesCount; i++) {

   this.attributes[i] = new AttributeInfo().parse(data);

   return this;

  

 

  AttributeInfo:

  

 private class AttributeInfo {

 

   int attributeNameIndex;

   long attributeLength;

   short[] info;

   public AttributeInfo parse(ByteBuffer data) {

   this.attributeNameIndex = readUnsignedShort(data);

   this.attributeLength = readUnsignedInt(data);

   this.info = new short[(int) attributeLength];

   for (int i = 0; i this.attributeLength; i++) {

   this.info[i] = (short) readUnsignedByte(data);

   return this;

  


 private void fields(ClassFileStructure structure, ByteBuffer data) {

 

   structure.fields = new FieldInfo[structure.fieldsCount];

   for (int i = 0; i structure.fieldsCount; i++) {

   structure.fields[i] = new FieldInfo().parse(data);

  

 

  2.13 methodsCount

  

 private ClassFile methodsCount(ClassFileStructure structure, ByteBuffer data) {

 

   structure.methodsCount = readUnsignedShort(data);

   return this;

  
public MethodInfo parse(ByteBuffer data) {

   this.accessFlags = readUnsignedShort(data);

   this.nameIndex = readUnsignedShort(data);

   this.descriptorIndex = readUnsignedShort(data);

   this.attributesCount = readUnsignedShort(data);

   this.attributes = new AttributeInfo[attributesCount];

   for (int i = 0; i this.attributesCount; i++) {

   this.attributes[i] = new AttributeInfo().parse(data);

   return this;

  


 private void methods(ClassFileStructure structure, ByteBuffer data) {

 

   structure.methods = new MethodInfo[structure.methodsCount];

   for (int i = 0; i structure.methodsCount; i++) {

   structure.methods[i] = new MethodInfo().parse(data);

  

 

  2.15 attributesCount

  

 private void attributesCount(ClassFileStructure structure, ByteBuffer data) {

 

   structure.attributesCount = readUnsignedShort(data);

  

 

  2.16 AttributeInfo[]

  

 private void attributes(ClassFileStructure structure, ByteBuffer data) {

 

   structure.attributes = new AttributeInfo[structure.attributesCount];

   for (int i = 0; i structure.attributesCount; i++) {

   structure.attributes[i] = new AttributeInfo().parse(data);

  

 

  以上就是Class文件解析(class文件解密)的详细内容,想要了解更多 Class文件解析的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: