diff --git a/app/src/main/assets/SoFixer/SoFixer32 b/app/src/main/assets/SoFixer/SoFixer32 deleted file mode 100644 index 349172e..0000000 Binary files a/app/src/main/assets/SoFixer/SoFixer32 and /dev/null differ diff --git a/app/src/main/assets/SoFixer/SoFixer64 b/app/src/main/assets/SoFixer/SoFixer64 deleted file mode 100644 index db45ef0..0000000 Binary files a/app/src/main/assets/SoFixer/SoFixer64 and /dev/null differ diff --git a/app/src/main/assets/arm64-v8a/fixer b/app/src/main/assets/arm64-v8a/fixer new file mode 100644 index 0000000..aa79d1c Binary files /dev/null and b/app/src/main/assets/arm64-v8a/fixer differ diff --git a/app/src/main/assets/armeabi-v7a/fixer b/app/src/main/assets/armeabi-v7a/fixer new file mode 100644 index 0000000..fa2a9ad Binary files /dev/null and b/app/src/main/assets/armeabi-v7a/fixer differ diff --git a/app/src/main/java/com/dumper/android/core/MainActivity.kt b/app/src/main/java/com/dumper/android/core/MainActivity.kt index d59c8f8..675ee06 100644 --- a/app/src/main/java/com/dumper/android/core/MainActivity.kt +++ b/app/src/main/java/com/dumper/android/core/MainActivity.kt @@ -109,7 +109,7 @@ class MainActivity : AppCompatActivity() { dumpFile: Array, autoFix: Boolean ) { - val soFixerPath = "${filesDir.path}/SoFixer" + val soFixerPath = filesDir.path Toast.makeText(this, "Please wait...", Toast.LENGTH_SHORT).show() @@ -134,7 +134,7 @@ class MainActivity : AppCompatActivity() { dumpFile.forEach { dumper.file = it - dumper.dumpFile(this, autoFix, soFixerPath, outHandler) + dumper.dumpFile(this, autoFix, null, outHandler) } } } diff --git a/app/src/main/java/com/dumper/android/dumper/Dumper.kt b/app/src/main/java/com/dumper/android/dumper/Dumper.kt index 454b604..b9c3155 100644 --- a/app/src/main/java/com/dumper/android/dumper/Dumper.kt +++ b/app/src/main/java/com/dumper/android/dumper/Dumper.kt @@ -2,10 +2,11 @@ package com.dumper.android.dumper import android.content.Context import android.os.Environment -import com.dumper.android.dumper.MemUtils.getArchELF import com.dumper.android.dumper.process.Process import com.dumper.android.utils.DEFAULT_DIR import com.dumper.android.utils.copyToFile +import com.dumper.android.utils.getArchELF +import com.dumper.android.utils.isELF import com.dumper.android.utils.removeNullChar import com.dumper.android.utils.toHex import com.topjohnwu.superuser.Shell @@ -35,7 +36,7 @@ class Dumper(private val pkg: String) { outLog.appendLine("Output: ${outputFile.parent}") } - private fun dumpFileNonRoot(ctx: Context, autoFix: Boolean, fixerPath: String, outLog: OutputHandler) { + private fun dumpFileNonRoot(ctx: Context, autoFix: Boolean, outLog: OutputHandler) { val outputDir = File(ctx.filesDir, "temp") if (!outputDir.exists()) @@ -45,7 +46,7 @@ class Dumper(private val pkg: String) { if (!outputDir.exists()) outputFile.createNewFile() - dump(autoFix, fixerPath, outputFile, outLog) + dump(autoFix, ctx.filesDir.absolutePath, outputFile, outLog) val fileOutPath = listOf( Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), @@ -83,13 +84,7 @@ class Dumper(private val pkg: String) { outLog.appendLine("Fixing...") - val fixerELF = fixerPath + when (archELF) { - Arch.ARCH_32BIT -> "32" - Arch.ARCH_64BIT -> "64" - else -> "" //just to disable the warning - } - - val fixer = Fixer.fixDump(fixerELF, outputFile, mem.sAddress.toHex()) + val fixer = Fixer.fixDump(fixerPath, archELF, outputFile, mem.sAddress.toHex()) // Check output fixer and error fixer if (fixer.first.isNotEmpty()) { outLog.appendLine("Fixer output : \n${fixer.first.joinToString("\n")}") @@ -107,7 +102,7 @@ class Dumper(private val pkg: String) { * @param fixerPath ELFixer path * @return log of the dump */ - fun dumpFile(ctx: Context?, autoFix: Boolean, fixerPath: String, outLog: OutputHandler) { + fun dumpFile(ctx: Context?, autoFix: Boolean, fixerPath: String?, outLog: OutputHandler) { try { mem.pid = Process.getProcessID(pkg) ?: throw Exception("Process not found!") @@ -137,10 +132,14 @@ class Dumper(private val pkg: String) { return } - if (ctx == null) + + if (ctx == null) { + if (fixerPath == null) + throw Exception("Fixer path is null!") dumpFileRoot(autoFix, fixerPath, outLog) + } else - dumpFileNonRoot(ctx, autoFix, fixerPath, outLog) + dumpFileNonRoot(ctx, autoFix, outLog) outLog.appendSuccess("Dump Success") } catch (e: Exception) { @@ -169,7 +168,7 @@ class Dumper(private val pkg: String) { val map = MapParser(it) if (mapStart == null) { if (file.contains(".so")) { - if (map.getPath().contains(file) && MemUtils.isELF(mem.pid, map.getStartAddress())) { + if (map.getPath().contains(file) && isELF(mem.pid, map.getStartAddress())) { mapStart = map } } else { diff --git a/app/src/main/java/com/dumper/android/dumper/Fixer.kt b/app/src/main/java/com/dumper/android/dumper/Fixer.kt index eb1d276..f19f313 100644 --- a/app/src/main/java/com/dumper/android/dumper/Fixer.kt +++ b/app/src/main/java/com/dumper/android/dumper/Fixer.kt @@ -1,32 +1,38 @@ package com.dumper.android.dumper import android.content.Context -import com.topjohnwu.superuser.Shell import java.io.File -enum class Arch { - UNKNOWN, - ARCH_32BIT, - ARCH_64BIT +enum class Arch(val value: String) { + UNKNOWN("Unknown"), + ARCH_32BIT("armeabi-v7a"), + ARCH_64BIT("arm64-v8a") } object Fixer { /** - * Extract SoFixer into filesDir and + * Extract folder assets into filesDir and * set permissions to 777 so the file can be executed */ fun extractLibs(ctx: Context) { - val libs = ctx.assets.list("SoFixer") - libs?.forEach { lib -> - ctx.assets.open("SoFixer/$lib").use { input -> - val out = File(ctx.filesDir, lib) - if (!out.exists()) { - input.copyTo(out.outputStream()) - Shell.cmd("chmod 777 ${out.absolutePath}").exec() + val filesDir = ctx.filesDir + val list = listOf("armeabi-v7a", "arm64-v8a") + list.forEach { arch -> + + val archDir = File(filesDir, arch) + if (!archDir.exists()) + archDir.mkdirs() + + ctx.assets.list(arch) + ?.forEach { v -> + val file = File(archDir, v) + if (!file.exists()) { + ctx.assets.open("$arch/$v").copyTo(file.outputStream()) + file.setExecutable(true, false) + } } - } } } @@ -38,7 +44,8 @@ object Fixer { * @return pair of results inputStream, errorStream */ fun fixDump( - fixerPath: String, + filesDir: String, + arch: Arch, dumpFile: File, startAddress: String ): Pair, List> { @@ -47,12 +54,9 @@ object Fixer { val proc = ProcessBuilder( listOf( - fixerPath, - "-s", + "$filesDir/${arch.value}/fixer", dumpFile.path, - "-o", "${dumpFile.parent}/${dumpFile.nameWithoutExtension}_fix.${dumpFile.extension}", - "-m", "0x$startAddress" ) ) diff --git a/app/src/main/java/com/dumper/android/dumper/MemUtils.kt b/app/src/main/java/com/dumper/android/dumper/MemUtils.kt deleted file mode 100644 index efd9b61..0000000 --- a/app/src/main/java/com/dumper/android/dumper/MemUtils.kt +++ /dev/null @@ -1,52 +0,0 @@ -package com.dumper.android.dumper - -import java.io.File -import java.io.RandomAccessFile -import java.nio.ByteBuffer -import java.nio.channels.FileChannel - -object MemUtils { - - private val ELFMAG = - byteArrayOf(0x7F, 'E'.code.toByte(), 'L'.code.toByte(), 'F'.code.toByte()) - - fun isELF(pid: Int, startAddress: Long): Boolean { - val file = File("/proc/$pid/mem") - val mFile = RandomAccessFile(file, "r") - val channel = mFile.channel - val byteHeader = ByteBuffer.allocate(4) - channel.read(byteHeader, startAddress) - channel.close() - mFile.close() - return byteHeader[0] == ELFMAG[0] && byteHeader[1] == ELFMAG[1] && - byteHeader[2] == ELFMAG[2] && byteHeader[3] == ELFMAG[3] - } - - fun getArchELF(mFile: FileChannel, memory: Memory) : Arch { - val byteHeader = ByteBuffer.allocate(5) - - mFile.read(byteHeader, memory.sAddress) - - if (byteHeader[0] != ELFMAG[0] || byteHeader[1] != ELFMAG[1] || - byteHeader[2] != ELFMAG[2] || byteHeader[3] != ELFMAG[3] - ) { - return Arch.UNKNOWN - } - - - mFile.position(0) //reset pos - return when (byteHeader[4].toInt()) { - 1 -> { - Arch.ARCH_32BIT - } - 2 -> { - Arch.ARCH_64BIT - } - else -> { - Arch.UNKNOWN - } - } - } - - -} \ No newline at end of file diff --git a/app/src/main/java/com/dumper/android/utils/MemUtils.kt b/app/src/main/java/com/dumper/android/utils/MemUtils.kt new file mode 100644 index 0000000..e678d4a --- /dev/null +++ b/app/src/main/java/com/dumper/android/utils/MemUtils.kt @@ -0,0 +1,53 @@ +package com.dumper.android.utils + +import com.dumper.android.dumper.Arch +import com.dumper.android.dumper.Memory +import java.io.File +import java.io.RandomAccessFile +import java.nio.ByteBuffer +import java.nio.channels.FileChannel + +private val hElf = + byteArrayOf(0x7F, 'E'.code.toByte(), 'L'.code.toByte(), 'F'.code.toByte()) + +// Generate documentation + +fun isELF(pid: Int, startAddress: Long): Boolean { + val file = File("/proc/$pid/mem") + val mFile = RandomAccessFile(file, "r") + val channel = mFile.channel + val byteHeader = ByteBuffer.allocate(4) + channel.read(byteHeader, startAddress) + channel.close() + mFile.close() + return byteHeader[0] == hElf[0] && byteHeader[1] == hElf[1] && + byteHeader[2] == hElf[2] && byteHeader[3] == hElf[3] +} + +fun getArchELF(mFile: FileChannel, memory: Memory): Arch { + val byteHeader = ByteBuffer.allocate(5) + + mFile.read(byteHeader, memory.sAddress) + + if (byteHeader[0] != hElf[0] || byteHeader[1] != hElf[1] || + byteHeader[2] != hElf[2] || byteHeader[3] != hElf[3] + ) { + return Arch.UNKNOWN + } + + + mFile.position(0) //reset pos + return when (byteHeader[4].toInt()) { + 1 -> { + Arch.ARCH_32BIT + } + + 2 -> { + Arch.ARCH_64BIT + } + + else -> { + Arch.UNKNOWN + } + } +} \ No newline at end of file