Home > Article > Backend Development > How to modify apk in golang
Recently, because I needed to inject some of my own encryption logic into the APK file, I tried to use golang to modify the APK file and successfully achieved the goal.
First, we need to learn how to parse APK files. The APK file is a file in zip format and consists of multiple parts, including AndroidManifest.xml, classes.dex and resource files. Before parsing, we need to first understand the structure of the dex file.
dex file consists of multiple parts, each part has a fixed size and format. You can use the following golang structure to parse dex files:
type DexFileHeader struct { magic [8]byte checksum uint32 signature [20]byte fileSize uint32 headerSize uint32 endianTag uint32 ... }
Among them, magic, checksum, signature, fileSize and headerSize fields represent the meta-information of the dex file, and endianTag represents the byte order of the dex file. For more specific dex file structure, please refer to the dex file specification.
Next, we need to use golang’s archive/zip package to decompress the APK file, and use the dex2jar tool to convert the classes.dex file into a jar file. Finally, we can use golang's jar package to decompile the jar file and modify the source code. After the modification is completed, we need to use the dx tool to recompile the modified source code into a dex file and put it back into the original APK file.
The following is the specific process of modifying the APK file:
apkFile, err := zip.OpenReader(apkPath) if err != nil { panic(err) } defer apkFile.Close() var dexFile *zip.File for _, f := range apkFile.File { if f.Name == "classes.dex" { dexFile = f break } } if dexFile == nil { panic("no classes.dex found") } dexReader, err := dexFile.Open() if err != nil { panic(err) } defer dexReader.Close() tmpDexPath := filepath.Join(tmpDir, "classes.dex") tmpJarPath := filepath.Join(tmpDir, "classes.jar") tmpDexFile, err := os.Create(tmpDexPath) if err != nil { panic(err) } defer tmpDexFile.Close() io.Copy(tmpDexFile, dexReader) cmd := exec.Command("d2j-dex2jar", tmpDexPath, "-f", "-o", tmpJarPath) if err := cmd.Run(); err != nil { panic(err) }
jarFile, err := jar.Open(tmpJarPath) if err != nil { panic(err) } defer jarFile.Close() for _, classFile := range jarFile.Files() { if !strings.HasSuffix(classFile.Name, ".class") { continue } className := strings.TrimSuffix(classFile.Name, ".class") className = strings.ReplaceAll(className, "/", ".") classReader, err := classFile.Open() if err != nil { panic(err) } defer classReader.Close() classBytes, err := ioutil.ReadAll(classReader) if err != nil { panic(err) } // 修改源代码 modifiedClassBytes := modifyClassBytes(classBytes) tmpClassPath := filepath.Join(tmpDir, className+".class") tmpClassFile, err := os.Create(tmpClassPath) if err != nil { panic(err) } defer tmpClassFile.Close() _, err = tmpClassFile.Write(modifiedClassBytes) if err != nil { panic(err) } }
When modifying the source code, you can use golang's go/javaparser package to parse Java code and modify the AST (Abstract Syntax Tree).
unit, err := parser.ParseFile(token.NewFileSet(), "", modifiedSource, parser.ParseComments) if err != nil { panic(err) } // 修改AST var buf bytes.Buffer printer.Fprint(&buf, token.NewFileSet(), unit) return buf.Bytes()
cmd = exec.Command("d2j-jar2dex", tmpJarPath, "-o", tmpDexPath) if err := cmd.Run(); err != nil { panic(err) } outDex, err := os.Open(tmpDexPath) if err != nil { panic(err) } defer outDex.Close() outDexInfo, err := os.Stat(tmpDexPath) if err != nil { panic(err) } outDexHeader := &zip.FileHeader{ Name: "classes.dex", Method: zip.Store, } outDexHeader.SetModTime(outDexInfo.ModTime()) outDexWriter, err := apkWriter.CreateHeader(outDexHeader) if err != nil { panic(err) } if _, err := io.Copy(outDexWriter, outDex); err != nil { panic(err) }
Finally, we can get a modified APK file and successfully inject our own encryption logic into it. The entire process is implemented using golang. The code is concise and easy to understand, and has high maintainability and scalability.
The above is the detailed content of How to modify apk in golang. For more information, please follow other related articles on the PHP Chinese website!