├── resources ├── META-INF │ └── MANIFEST.MF └── Demo.class ├── README.md └── src ├── com └── Demo.java ├── domain ├── SymbolTableDo.java ├── SectionHeaderDo.java └── ElfFileHeaderDO.java ├── tools ├── LibPathFinder.java ├── MapsParser.java ├── Memory.java └── ElfParser.java └── T2.java /resources/META-INF/MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Main-Class: T2 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Java_agent_without_file 2 | 无文件Java agent的Demo。T2是入口。resources下存放的`Demo.class`是jdk1.8.202编译的。 3 | -------------------------------------------------------------------------------- /resources/Demo.class: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xiaopan233/Java_agent_without_file/HEAD/resources/Demo.class -------------------------------------------------------------------------------- /src/com/Demo.java: -------------------------------------------------------------------------------- 1 | package com; 2 | 3 | public class Demo { 4 | public void print(){ 5 | System.out.println("[+] Info........"); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /src/domain/SymbolTableDo.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | public class SymbolTableDo { 4 | public byte[] st_name = new byte[4]; 5 | public byte[] st_info= new byte[1]; 6 | public byte[] st_other = new byte[1]; 7 | public byte[] st_shndx = new byte[2]; 8 | public byte[] st_value = new byte[8]; 9 | public byte[] st_size = new byte[8]; 10 | 11 | /* 12 | * custom 13 | * */ 14 | public long symbolTableName; 15 | public long type; /*2 FUNC*/ 16 | } 17 | -------------------------------------------------------------------------------- /src/tools/LibPathFinder.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import java.util.Properties; 4 | 5 | public class LibPathFinder { 6 | public static String getLibPath() throws Exception{ 7 | Properties properties = System.getProperties(); 8 | String libPath = properties.getProperty("sun.boot.library.path"); 9 | if (libPath == null){ 10 | throw new Exception("[-] LibPath Error"); 11 | } 12 | System.out.println("[+] Find lib path: " + libPath); 13 | return properties.getProperty("sun.boot.library.path"); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/domain/SectionHeaderDo.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | public class SectionHeaderDo { 4 | public byte[] sh_name = new byte[4]; 5 | public byte[] sh_type = new byte[4]; 6 | public byte[] sh_flags = new byte[8]; 7 | public byte[] sh_addr = new byte[8]; 8 | public byte[] sh_offset = new byte[8]; 9 | public byte[] sh_size = new byte[8]; 10 | public byte[] sh_link = new byte[4]; 11 | public byte[] sh_info = new byte[4]; 12 | public byte[] sh_addralign = new byte[8]; 13 | public byte[] sh_entsize = new byte[8]; 14 | /* 15 | * custom 16 | * */ 17 | public long sectionHeaderName; 18 | public long sectionHeaderOffset; 19 | public long sectionHeaderSize; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/domain/ElfFileHeaderDO.java: -------------------------------------------------------------------------------- 1 | package domain; 2 | 3 | public class ElfFileHeaderDO { 4 | public byte[] e_ident = new byte[16]; 5 | public byte[] e_type = new byte[2]; 6 | public byte[] e_machine = new byte[2]; 7 | public byte[] e_version = new byte[4]; 8 | public byte[] e_entry = new byte[8]; 9 | public byte[] e_phoff = new byte[8]; 10 | public byte[] e_shoff = new byte[8]; 11 | public byte[] e_flags = new byte[4]; 12 | public byte[] e_ehsize = new byte[2]; 13 | public byte[] e_phentsize = new byte[2]; 14 | public byte[] e_phnum = new byte[2]; 15 | public byte[] e_shentsize = new byte[2]; 16 | public byte[] e_shnum = new byte[2]; 17 | public byte[] e_shstrndx = new byte[2]; 18 | /* 19 | * cunstom data 20 | * */ 21 | public long sectionHeaderSectionNameIndex; 22 | public long sectionHeaderNumber; 23 | public long sectionHeaderOffset; 24 | } 25 | -------------------------------------------------------------------------------- /src/tools/MapsParser.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import java.io.RandomAccessFile; 4 | 5 | public class MapsParser { 6 | private RandomAccessFile mapsReader; 7 | 8 | public MapsParser() throws Exception{ 9 | mapsReader = new RandomAccessFile("/proc/self/maps", "r"); 10 | } 11 | 12 | public long getLibMemoryAddress(String libname) throws Exception{ 13 | mapsReader.seek(0L); 14 | long libMemeryAddress = 0L; 15 | String procSelfMem; 16 | 17 | while((procSelfMem = mapsReader.readLine()) != null) { 18 | if (procSelfMem.contains(libname)) { 19 | String[] address = procSelfMem.split(" "); 20 | String[] addressArr1 = address[0].split("-"); 21 | libMemeryAddress = Long.valueOf(addressArr1[0], 16); 22 | break; 23 | } 24 | } 25 | if (libMemeryAddress == 0L){ 26 | throw new Exception("[-] maps parser error!"); 27 | } 28 | return libMemeryAddress; 29 | } 30 | 31 | public void close() throws Exception{ 32 | mapsReader.close(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/tools/Memory.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import sun.misc.Unsafe; 4 | 5 | import java.io.RandomAccessFile; 6 | import java.lang.reflect.Field; 7 | 8 | public class Memory { 9 | private RandomAccessFile memoryIO; 10 | private byte[] codeOverwrite; 11 | private byte[] codeOriginal; 12 | 13 | public Memory(long jni_getCreatedJavaVMsAddress) throws Exception{ 14 | memoryIO = new RandomAccessFile("/proc/self/mem", "rw"); 15 | 16 | //hard code payload 17 | byte[] codeInsert1 = new byte[]{ 18 | (byte)0x55,(byte)0x48,(byte)0x89,(byte)0xe5,(byte)0x6a,(byte)0x01,(byte)0x48,(byte)0x83,(byte)0xec,(byte)0x18,(byte)0x48,(byte)0x8d,(byte)0x54,(byte)0x24,(byte)0x18,(byte)0x48,(byte)0xc7,(byte)0xc6,(byte)0x01,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x48,(byte)0x8d,(byte)0x7c,(byte)0x24,(byte)0x10,(byte)0x48,(byte)0xb8 19 | }; 20 | byte[] codeInsert2 = new byte[8]; 21 | String hexString = Long.toHexString(jni_getCreatedJavaVMsAddress); 22 | byte[] codeInsert3 = new byte[]{ 23 | (byte)0xff,(byte)0xd0,(byte)0x48,(byte)0xc7,(byte)0xc2,(byte)0x00,(byte)0x02,(byte)0x01,(byte)0x30,(byte)0x4c,(byte)0x8d,(byte)0x44,(byte)0x24,(byte)0x08,(byte)0x4c,(byte)0x89,(byte)0x04,(byte)0x24,(byte)0x48,(byte)0x8d,(byte)0x34,(byte)0x24,(byte)0x48,(byte)0x8b,(byte)0x7c,(byte)0x24,(byte)0x10,(byte)0x4c,(byte)0x8b,(byte)0x44,(byte)0x24,(byte)0x10,(byte)0x4d,(byte)0x8b,(byte)0x08,(byte)0x4d,(byte)0x8b,(byte)0x41,(byte)0x30,(byte)0x41,(byte)0xff,(byte)0xd0,(byte)0x48,(byte)0x8b,(byte)0x04,(byte)0x24,(byte)0x48,(byte)0x83,(byte)0xc4,(byte)0x20,(byte)0x5d,(byte)0xc3 24 | }; 25 | 26 | int codeInsert2Offset = 0; 27 | for (int i = hexString.length(); i >= 2; i-=2) { 28 | String substring = hexString.substring(i - 2, i); 29 | Integer decode = Integer.decode("0x" + substring); 30 | byte aByte = decode.byteValue(); 31 | codeInsert2[codeInsert2Offset++] = aByte; 32 | } 33 | 34 | codeOverwrite = new byte[codeInsert1.length + codeInsert2.length + codeInsert3.length]; 35 | codeOriginal = new byte[codeOverwrite.length]; 36 | System.arraycopy(codeInsert1, 0, codeOverwrite, 0, codeInsert1.length); 37 | System.arraycopy(codeInsert2, 0, codeOverwrite, codeInsert1.length, codeInsert2.length); 38 | System.arraycopy(codeInsert3, 0, codeOverwrite, codeInsert1.length+codeInsert2.length, codeInsert3.length); 39 | } 40 | 41 | /* 42 | * read to codeOriginal for resume 43 | * */ 44 | public void read(long offset) throws Exception{ 45 | memoryIO.seek(offset); 46 | memoryIO.read(codeOriginal); 47 | } 48 | 49 | /* 50 | * put codeOverwrite to memory 51 | * */ 52 | public void write(long offset, boolean overwrite) throws Exception{ 53 | memoryIO.seek(offset); 54 | if (overwrite) 55 | memoryIO.write(codeOverwrite); 56 | else 57 | memoryIO.write(codeOriginal); 58 | } 59 | 60 | public long GenerateJPLISAgent(long jvmtiEnv) throws Exception{ 61 | Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); 62 | theUnsafe.setAccessible(true); 63 | Unsafe unsafe = (Unsafe) theUnsafe.get(null); 64 | 65 | long JPLISAgent = unsafe.allocateMemory(25L); 66 | //JavaVM* 67 | unsafe.putLong(JPLISAgent, 0L); 68 | 69 | //_JPLISEnvironment 70 | unsafe.putLong(JPLISAgent+8L, jvmtiEnv); 71 | unsafe.putLong(JPLISAgent+16L, JPLISAgent); 72 | unsafe.putByte(JPLISAgent+24L, (byte)0x1); 73 | //can_redefine_classes 74 | unsafe.putByte(jvmtiEnv + 361L, (byte)0x2); 75 | //jdk11.0.13, jdk12.0.2 377 76 | //jdk 1.8.202, jdk10.0.2 361 77 | return JPLISAgent; 78 | } 79 | 80 | public void close() throws Exception{ 81 | memoryIO.close(); 82 | } 83 | } 84 | -------------------------------------------------------------------------------- /src/T2.java: -------------------------------------------------------------------------------- 1 | import com.Demo; 2 | import domain.SymbolTableDo; 3 | import tools.ElfParser; 4 | import tools.LibPathFinder; 5 | import tools.MapsParser; 6 | import tools.Memory; 7 | 8 | import java.io.File; 9 | import java.io.FileInputStream; 10 | import java.lang.instrument.ClassDefinition; 11 | import java.lang.reflect.Constructor; 12 | import java.lang.reflect.Method; 13 | import java.net.URL; 14 | 15 | public class T2 { 16 | public static void main(String[] args) throws Exception{ 17 | MapsParser mapsParser = new MapsParser(); 18 | long libjvmBaseAddress = mapsParser.getLibMemoryAddress("libjvm.so"); 19 | long libjavaBaseAddress = mapsParser.getLibMemoryAddress("libjava.so"); 20 | mapsParser.close(); 21 | 22 | String libPath = LibPathFinder.getLibPath(); 23 | ElfParser libjvmElfParser = new ElfParser(libPath + "/server/libjvm.so"); 24 | SymbolTableDo jni_getCreatedJavaVMsSymbolTableDo = libjvmElfParser.findSymbolTable("JNI_GetCreatedJavaVMs", ".dynsym"); 25 | long jni_getCreatedJavaVMsOffset = ElfParser.byteToLong(jni_getCreatedJavaVMsSymbolTableDo.st_value, true); 26 | long jni_getCreatedJavaVMsAddress = libjvmBaseAddress + jni_getCreatedJavaVMsOffset; 27 | System.out.println("[+] libjvm.so JNI_GetCreatedJavaVMs address is: 0x" + Long.toHexString(jni_getCreatedJavaVMsAddress)); 28 | 29 | ElfParser libjavaElfParser = new ElfParser(libPath + "/libjava.so"); 30 | SymbolTableDo java_java_io_fileInputStream_skip0SymbolTableDo = libjavaElfParser.findSymbolTable("Java_java_io_FileInputStream_skip0", ".symtab"); 31 | long java_java_io_fileInputStream_skip0SymbolTableDoOffset = ElfParser.byteToLong(java_java_io_fileInputStream_skip0SymbolTableDo.st_value, true); 32 | long java_java_io_fileInputStream_skip0SymbolTableDoAddress = libjavaBaseAddress + java_java_io_fileInputStream_skip0SymbolTableDoOffset; 33 | System.out.println("[+] libjava.so Java_java_io_FileInputStream_skip0 address is: 0x" + Long.toHexString(java_java_io_fileInputStream_skip0SymbolTableDoAddress)); 34 | 35 | Memory memory = new Memory(jni_getCreatedJavaVMsAddress); 36 | memory.read(java_java_io_fileInputStream_skip0SymbolTableDoAddress); 37 | memory.write(java_java_io_fileInputStream_skip0SymbolTableDoAddress, true); 38 | 39 | FileInputStream fileInputStream = new FileInputStream("/proc/self/maps"); 40 | long jvmtiEnvPointer = fileInputStream.skip(1L); 41 | 42 | memory.write(java_java_io_fileInputStream_skip0SymbolTableDoAddress, false); 43 | memory.close(); 44 | 45 | System.out.println("[+] jvmtiEnvPointer: 0x" + Long.toHexString(jvmtiEnvPointer)); 46 | 47 | long JPLISAgent = memory.GenerateJPLISAgent(jvmtiEnvPointer); 48 | 49 | /* 50 | * Test no file Java Agent 51 | * */ 52 | Demo demo = new Demo(); 53 | demo.print(); 54 | 55 | URL demoClassURL = T2.class.getResource("/Demo.class"); 56 | String demoClassURLPathath = demoClassURL.getPath(); 57 | byte[] evilClassClassBytes = readFile(demoClassURLPathath); 58 | 59 | /* 60 | * InstrumentationImpl.redefineClasses() 61 | * */ 62 | Class instrumentationImplClass = Class.forName("sun.instrument.InstrumentationImpl"); 63 | Constructor instrumentationImplConstructor = instrumentationImplClass.getDeclaredConstructor(long.class, boolean.class, boolean.class); 64 | instrumentationImplConstructor.setAccessible(true); 65 | Object instrumentationImpl = instrumentationImplConstructor.newInstance(JPLISAgent, true, false); 66 | 67 | ClassDefinition[] classDefinitions = new ClassDefinition[1]; 68 | classDefinitions[0] = new ClassDefinition(com.Demo.class, evilClassClassBytes); 69 | 70 | Method redefineClassesMethod = instrumentationImplClass.getDeclaredMethod("redefineClasses", ClassDefinition[].class); 71 | redefineClassesMethod.setAccessible(true); 72 | redefineClassesMethod.invoke(instrumentationImpl, new Object[]{classDefinitions}); 73 | 74 | demo.print(); 75 | } 76 | 77 | private static byte[] readFile(String path) throws Exception{ 78 | File file = new File(path); 79 | FileInputStream fileInputStream = new FileInputStream(file); 80 | byte[] b = new byte[(int)file.length()]; 81 | int off = 0; 82 | int step = 200; 83 | int tmp = 0; 84 | while (true){ 85 | if(off+step > b.length){ 86 | tmp = b.length - off; 87 | fileInputStream.read(b,off,tmp); 88 | break; 89 | } 90 | tmp=fileInputStream.read(b,off,step); 91 | off += tmp; 92 | } 93 | return b; 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /src/tools/ElfParser.java: -------------------------------------------------------------------------------- 1 | package tools; 2 | 3 | import domain.ElfFileHeaderDO; 4 | import domain.SectionHeaderDo; 5 | import domain.SymbolTableDo; 6 | 7 | import java.io.RandomAccessFile; 8 | import java.lang.reflect.Field; 9 | import java.nio.ByteBuffer; 10 | import java.nio.ByteOrder; 11 | import java.util.ArrayList; 12 | import java.util.HashMap; 13 | 14 | public class ElfParser { 15 | private String fileName; 16 | private RandomAccessFile randomAccessFile; 17 | private ElfFileHeaderDO elfFileHeaderDO; 18 | private HashMap sectionHeaderDoHashMap; 19 | private boolean encoding; /* true little-endian; false big-endian */ 20 | 21 | private byte[] sectionTableString; 22 | private byte[] symStrTableString; 23 | private byte[] dynSymTableString; 24 | 25 | public ElfParser(String fileName) throws Exception{ 26 | this.fileName = fileName; 27 | this.randomAccessFile = new RandomAccessFile(fileName, "r"); 28 | this.elfFileHeaderDO = new ElfFileHeaderDO(); 29 | this.sectionHeaderDoHashMap = new HashMap<>(); 30 | //parse file header 31 | fileHeaderParser(); 32 | sectionHeaderParser(); 33 | 34 | //parse symbol table names string and dynsym table names string 35 | stringTableParser(sectionHeaderDoHashMap.get(".strtab"), "symStrTableString"); 36 | stringTableParser(sectionHeaderDoHashMap.get(".dynstr"), "dynSymTableString"); 37 | } 38 | 39 | private void fileHeaderParser() throws Exception{ 40 | randomAccessFile.seek(0); 41 | randomAccessFile.read(elfFileHeaderDO.e_ident); 42 | randomAccessFile.read(elfFileHeaderDO.e_type); 43 | randomAccessFile.read(elfFileHeaderDO.e_machine); 44 | randomAccessFile.read(elfFileHeaderDO.e_version); 45 | randomAccessFile.read(elfFileHeaderDO.e_entry); 46 | randomAccessFile.read(elfFileHeaderDO.e_phoff); 47 | randomAccessFile.read(elfFileHeaderDO.e_shoff); 48 | randomAccessFile.read(elfFileHeaderDO.e_flags); 49 | randomAccessFile.read(elfFileHeaderDO.e_ehsize); 50 | randomAccessFile.read(elfFileHeaderDO.e_phentsize); 51 | randomAccessFile.read(elfFileHeaderDO.e_phnum); 52 | randomAccessFile.read(elfFileHeaderDO.e_shentsize); 53 | randomAccessFile.read(elfFileHeaderDO.e_shnum); 54 | randomAccessFile.read(elfFileHeaderDO.e_shstrndx); 55 | 56 | encoding = elfFileHeaderDO.e_ident[5] == 0x1; 57 | 58 | elfFileHeaderDO.sectionHeaderSectionNameIndex = byteToLong(elfFileHeaderDO.e_shstrndx, encoding); 59 | elfFileHeaderDO.sectionHeaderOffset = byteToLong(elfFileHeaderDO.e_shoff, encoding); 60 | elfFileHeaderDO.sectionHeaderNumber = byteToLong(elfFileHeaderDO.e_shnum, encoding); 61 | } 62 | 63 | private void sectionHeaderParser() throws Exception{ 64 | long filePoint = elfFileHeaderDO.sectionHeaderOffset; 65 | ArrayList sectionHeaderDoArrayList = new ArrayList<>(); 66 | 67 | for (int i = 1; i <= elfFileHeaderDO.sectionHeaderNumber; i++){ 68 | SectionHeaderDo sectionHeader = new SectionHeaderDo(); 69 | randomAccessFile.seek(filePoint); 70 | 71 | randomAccessFile.read(sectionHeader.sh_name); 72 | randomAccessFile.read(sectionHeader.sh_type); 73 | randomAccessFile.read(sectionHeader.sh_flags); 74 | randomAccessFile.read(sectionHeader.sh_addr); 75 | randomAccessFile.read(sectionHeader.sh_offset); 76 | randomAccessFile.read(sectionHeader.sh_size); 77 | randomAccessFile.read(sectionHeader.sh_link); 78 | randomAccessFile.read(sectionHeader.sh_info); 79 | randomAccessFile.read(sectionHeader.sh_addralign); 80 | randomAccessFile.read(sectionHeader.sh_entsize); 81 | 82 | //byte[] to long 83 | sectionHeader.sectionHeaderOffset = byteToLong(sectionHeader.sh_offset, encoding); 84 | sectionHeader.sectionHeaderSize = byteToLong(sectionHeader.sh_size, encoding); 85 | sectionHeader.sectionHeaderName = byteToLong(sectionHeader.sh_name, encoding); 86 | 87 | filePoint = randomAccessFile.getFilePointer(); 88 | sectionHeaderDoArrayList.add(sectionHeader); 89 | } 90 | 91 | //Get section names table 92 | SectionHeaderDo sectionNamesTable = sectionHeaderDoArrayList.get((int) elfFileHeaderDO.sectionHeaderSectionNameIndex); 93 | stringTableParser(sectionNamesTable, "sectionTableString"); 94 | 95 | //Re-composer section tables with names 96 | for (SectionHeaderDo sectionHeaderDo : sectionHeaderDoArrayList) { 97 | String tableNameString = addressAssociateString(sectionHeaderDo.sectionHeaderName, "sectionTableString"); 98 | sectionHeaderDoHashMap.put(tableNameString, sectionHeaderDo); 99 | } 100 | } 101 | 102 | 103 | 104 | public SymbolTableDo findSymbolTable(String symbolName, String tableName) throws Exception{ 105 | String strTableName; 106 | String strTableString; 107 | if (tableName.equals(".symtab")){ 108 | strTableName = ".strtab"; 109 | strTableString = "symStrTableString"; 110 | }else if (tableName.equals(".dynsym")){ 111 | strTableName = ".dynstr"; 112 | strTableString = "dynSymTableString"; 113 | }else{ 114 | throw new Exception("[-] Symtable name error"); 115 | } 116 | SectionHeaderDo symbolTableSectionHeader = sectionHeaderDoHashMap.get(tableName); 117 | SectionHeaderDo stringTableSectionHeader = sectionHeaderDoHashMap.get(strTableName); 118 | SymbolTableDo resSymbolTableDo = new SymbolTableDo(); 119 | 120 | //size and offset 121 | long symbolTableOffset = byteToLong(symbolTableSectionHeader.sh_offset, encoding); 122 | long number = byteToLong(symbolTableSectionHeader.sh_size, encoding) / byteToLong(symbolTableSectionHeader.sh_entsize, encoding); 123 | randomAccessFile.seek(symbolTableOffset); 124 | 125 | for (int i = 1; i <= number; i++) { 126 | randomAccessFile.read(resSymbolTableDo.st_name); 127 | randomAccessFile.read(resSymbolTableDo.st_info); 128 | randomAccessFile.read(resSymbolTableDo.st_other); 129 | randomAccessFile.read(resSymbolTableDo.st_shndx); 130 | randomAccessFile.read(resSymbolTableDo.st_value); 131 | randomAccessFile.read(resSymbolTableDo.st_size); 132 | resSymbolTableDo.symbolTableName = byteToLong(resSymbolTableDo.st_name, encoding); 133 | 134 | //Just parse FUNC 135 | long type = byteToLong(resSymbolTableDo.st_info, encoding) & 0xf; 136 | if (type != 2L){ 137 | continue; 138 | } 139 | String name = addressAssociateString(resSymbolTableDo.symbolTableName, strTableString); 140 | if (symbolName.equals(name)){ 141 | break; 142 | } 143 | } 144 | return resSymbolTableDo; 145 | } 146 | 147 | private void stringTableParser(SectionHeaderDo namesTable, String tableString) throws Exception{ 148 | //section names string 149 | byte[] sectionTableString = new byte[(int) namesTable.sectionHeaderSize]; 150 | randomAccessFile.seek(namesTable.sectionHeaderOffset); 151 | randomAccessFile.read(sectionTableString); 152 | 153 | Field sectionTableStringField = this.getClass().getDeclaredField(tableString); 154 | sectionTableStringField.setAccessible(true); 155 | sectionTableStringField.set(this, sectionTableString); 156 | } 157 | 158 | 159 | public static long byteToLong(byte[] b0, boolean byteEncoding){ 160 | byte[] b; 161 | if (b0.length < 8){ 162 | 163 | b = new byte[8]; 164 | }else{ 165 | b = new byte[b0.length]; 166 | } 167 | System.arraycopy(b0, 0, b, 0, b0.length); 168 | 169 | ByteBuffer wrap = ByteBuffer.wrap(b); 170 | ByteBuffer order; 171 | 172 | //little-endian 173 | if (byteEncoding){ 174 | order = wrap.order(ByteOrder.LITTLE_ENDIAN); 175 | } 176 | //big-endian 177 | else { 178 | order = wrap.order(ByteOrder.BIG_ENDIAN); 179 | } 180 | return order.getLong(); 181 | } 182 | 183 | private String addressAssociateString(long stringOffset, String tableString) throws Exception{ 184 | int readOffset = (int) stringOffset; 185 | StringBuilder stringBuilder = new StringBuilder(); 186 | 187 | //which table name string 188 | Field tableStringField = this.getClass().getDeclaredField(tableString); 189 | tableStringField.setAccessible(true); 190 | byte[] tableStringBytes = (byte[]) tableStringField.get(this); 191 | 192 | while (true){ 193 | byte b = tableStringBytes[readOffset]; 194 | if (b == 0x00){ 195 | break; 196 | } 197 | char c = (char) b; 198 | stringBuilder.append(c); 199 | readOffset++; 200 | } 201 | return stringBuilder.toString(); 202 | } 203 | } 204 | --------------------------------------------------------------------------------