80 lines
2.0 KiB
Scala
80 lines
2.0 KiB
Scala
package parser
|
|
|
|
import java.io.File
|
|
|
|
import dex._
|
|
import org.jf.dexlib2.dexbacked.{
|
|
DexBackedClassDef,
|
|
DexBackedDexFile,
|
|
DexBackedField,
|
|
DexBackedMethod
|
|
}
|
|
import org.jf.dexlib2.{DexFileFactory, Opcodes}
|
|
import utils.Utils
|
|
|
|
import scala.collection.JavaConverters._
|
|
|
|
class Parser(apkLocation: String) {
|
|
|
|
val apkFile = new File(apkLocation)
|
|
val dexFile: DexBackedDexFile =
|
|
DexFileFactory.loadDexFile(apkFile, Opcodes.forApi(21))
|
|
|
|
def dexApp: DexApp = {
|
|
val classes = parseClasses
|
|
new DexApp(
|
|
new AndroidXmlParser(apkLocation, classes).parseManifest(),
|
|
classes,
|
|
new EntryPointsProvider(classes).entryPoints(),
|
|
new SourcesSinksProvider().sourcesSinks()
|
|
)
|
|
}
|
|
|
|
private def parseClasses: Seq[DexClass] = {
|
|
dexFile.getClasses.asScala.toSeq
|
|
.filter(classFilter())
|
|
.map(
|
|
c =>
|
|
DexClass(
|
|
c.getType,
|
|
c.getSuperclass,
|
|
c.getInterfaces.asScala,
|
|
classFields(c.getFields.asScala.toSeq),
|
|
classMethods(c.getMethods.asScala.toSeq)
|
|
))
|
|
}
|
|
|
|
private def classFilter(): DexBackedClassDef => Boolean =
|
|
(t: DexBackedClassDef) => !t.getType.startsWith("Landroid/support")
|
|
|
|
private def methodFilter(): DexBackedMethod => Boolean =
|
|
(m: DexBackedMethod) => m.getImplementation != null
|
|
|
|
private def classFields(fields: Seq[DexBackedField]): Seq[DexField] =
|
|
fields
|
|
.map(
|
|
f =>
|
|
DexField(
|
|
f.getName,
|
|
Utils.removeClassPrefix(f.toString),
|
|
DexType(f.getType)
|
|
))
|
|
|
|
private def classMethods(methods: Seq[DexBackedMethod]): Seq[DexMethod] = {
|
|
methods
|
|
.filter(methodFilter())
|
|
.map(
|
|
m =>
|
|
DexMethod(
|
|
m.getName,
|
|
Utils.removeClassPrefix(m.toString),
|
|
m.getParameterTypes.asScala.map(t => DexType(t)),
|
|
DexType(m.getReturnType),
|
|
m.getImplementation.getRegisterCount,
|
|
m.getParameters.size(),
|
|
m.getImplementation.getInstructions.asScala.toSeq
|
|
))
|
|
}
|
|
|
|
}
|