feat: add base scripting support
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
// custom deobfuscator example
|
||||
|
||||
val jadx = getJadxInstance()
|
||||
jadx.args.isDeobfuscationOn = false
|
||||
jadx.args.renameFlags = emptySet()
|
||||
|
||||
val regex = """[Oo0]+""".toRegex()
|
||||
var n = 0
|
||||
jadx.rename.all { name, node ->
|
||||
when {
|
||||
name matches regex -> {
|
||||
val newName = "${node.typeName()}${n++}"
|
||||
println("renaming ${node.typeName()} '$node' to '$newName'")
|
||||
newName
|
||||
}
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
jadx.afterLoad {
|
||||
println("Renames count: $n")
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
// customize jadx-gui
|
||||
|
||||
val jadx = getJadxInstance()
|
||||
|
||||
jadx.gui.ifAvailable {
|
||||
addMenuAction("Decompile All") {
|
||||
jadx.decompile.all()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
// logger is preferred for output
|
||||
log.info { "Hello from jadx script!" }
|
||||
|
||||
// println will also work (will be redirected to logger)
|
||||
println("println from script '$scriptName'")
|
||||
|
||||
// get jadx decompiler script instance
|
||||
val jadx = getJadxInstance()
|
||||
|
||||
// adjust options if needed
|
||||
jadx.args.isDeobfuscationOn = false
|
||||
|
||||
// change names
|
||||
jadx.rename.all { name ->
|
||||
when (name) {
|
||||
"HelloWorld" -> "HelloJadx"
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
// run some code after loading is finished
|
||||
jadx.afterLoad {
|
||||
println("Loaded classes: ${jadx.classes.size}")
|
||||
// print first class code
|
||||
jadx.classes.firstOrNull()?.let { cls ->
|
||||
println("Class: '${cls.name}'")
|
||||
println(cls.code)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
// instructions modification example
|
||||
|
||||
import jadx.core.dex.instructions.ConstStringNode
|
||||
import jadx.core.dex.instructions.InvokeNode
|
||||
import jadx.core.dex.instructions.args.InsnArg
|
||||
|
||||
val jadx = getJadxInstance()
|
||||
|
||||
jadx.replace.insns { mth, insn ->
|
||||
if (insn is InvokeNode) {
|
||||
if (insn.callMth.shortId == "println(Ljava/lang/String;)V") {
|
||||
val arg = insn.getArg(1)
|
||||
val newArg = InsnArg.wrapInsnIntoArg(ConstStringNode("Jadx!"))
|
||||
insn.setArg(1, newArg)
|
||||
log.info { "Replace '$arg' with '$newArg' in $mth" }
|
||||
}
|
||||
}
|
||||
null
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
// insert processing passes for different decompilation stages
|
||||
|
||||
import jadx.core.dex.instructions.InsnType
|
||||
import jadx.core.dex.nodes.IRegion
|
||||
import java.lang.Integer.max
|
||||
|
||||
val jadx = getJadxInstance()
|
||||
|
||||
// print raw instructions
|
||||
jadx.stages.rawInsns { mth, insns ->
|
||||
log.info { "Instructions for method: $mth" }
|
||||
for ((offset, insn) in insns.withIndex()) {
|
||||
insn?.let {
|
||||
log.info { " 0x${offset.hex()}: $insn" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// access method basic blocks
|
||||
jadx.stages.mthBlocks { mth, blocks ->
|
||||
// count invoke instructions
|
||||
var invCount = 0
|
||||
for (block in blocks) {
|
||||
for (insn in block.instructions) {
|
||||
if (insn.type == InsnType.INVOKE) {
|
||||
invCount++
|
||||
}
|
||||
}
|
||||
}
|
||||
log.info { "Invokes count in method $mth = $invCount" }
|
||||
}
|
||||
|
||||
// access method regions
|
||||
jadx.stages.mthRegions { mth, region ->
|
||||
// recursively count max depth of nested regions
|
||||
fun countRegionsDepth(region: IRegion): Int {
|
||||
val subBlocks = region.subBlocks
|
||||
if (subBlocks.isEmpty()) {
|
||||
return 0
|
||||
}
|
||||
var depth = 1
|
||||
for (block in subBlocks) {
|
||||
if (block is IRegion) {
|
||||
depth = max(depth, 1 + countRegionsDepth(block))
|
||||
}
|
||||
}
|
||||
return depth
|
||||
}
|
||||
|
||||
val depth = countRegionsDepth(region)
|
||||
log.info { "Max region depth in method $mth = $depth" }
|
||||
if (depth > 5) {
|
||||
jadx.debug.printMethodRegions(mth, printInsns = true)
|
||||
}
|
||||
}
|
||||
|
||||
jadx.afterLoad {
|
||||
/*
|
||||
Start full decompilation (optional):
|
||||
1. jadx-cli start decompilation automatically
|
||||
2. jadx-gui start decompilation only on class open or search, so you might need to force it
|
||||
*/
|
||||
// jadx.decompile.all()
|
||||
}
|
||||
Reference in New Issue
Block a user