DalvikBytecodeAnalysis/src/main/scala/Main.scala

92 lines
2.5 KiB
Scala

import java.io.{File, PrintWriter}
import java.time.{Duration, Instant, LocalTime}
import java.util
import analysis.{Analyzer, PreAnalyzer}
import ch.qos.logback.classic.{Level, Logger}
import com.microsoft.z3._
import com.typesafe.scalalogging.StrictLogging
import constraints.Z3Constraint
import domain._
import org.slf4j.LoggerFactory
import parser.Parser
object Main extends App with StrictLogging {
val help = """Usage:
-apk=FILE Apk file to analyze
-print-rules Print the textual description of the constraints
-print-goal Print the Z3 goal
"""
// Check parameters
if (args.length == 0) {
println(help)
System.exit(1)
}
val apkArg = args.find(a => a.startsWith("-apk"))
if (apkArg.isEmpty) {
println("No apk given")
System.exit(1)
}
val apkLocation: String = apkArg.get.split("=")(1)
val printRules: Boolean = args.exists(a => a.startsWith("-print-rules"))
val printGoal: Boolean = args.exists(a => a.startsWith("-print-goal"))
val parser = new Parser(apkLocation)
var start = Instant.now()
logger.info(s"Start: ${LocalTime.now()}")
// Context
val cfg = new util.HashMap[String, String]
cfg.put("model", "true")
val ctx = new Context(cfg)
// Goal
val g = ctx.mkGoal(true, false, false)
val domainsCollection =
AbstractDomainsCollection(
new TopDomain(ctx),
new ReferenceDomain(ctx),
new TaintDomain(ctx)
)
val app = parser.dexApp
val preAnalysisResult = new PreAnalyzer(app.classes).analyze
val analyzer =
new Analyzer(ctx, domainsCollection, app, preAnalysisResult)
val constraints: Seq[Z3Constraint] = analyzer.analyze
g.add(
ctx.mkAnd(
constraints.map(c => c.boolExpr): _*
)
)
if (printRules) {
println("Rules:")
println(
constraints
.map(c => s"${c.pp.m.shortName}-${c.pp.pc} ${c.description}")
.mkString("\n")
)
}
if (printGoal) {
println("Goal:")
println(g)
}
var end = Instant.now()
logger.info(
s"Time to generate goal: ${Duration.between(start, end).getSeconds} seconds")
start = Instant.now()
val solver = ctx.mkSolver
g.getFormulas.foreach(solver.add(_))
val status = solver.check()
end = Instant.now()
logger.info(
s"Time to check goal: ${Duration.between(start, end).getSeconds} seconds")
status match {
case Status.SATISFIABLE => println("OK")
case Status.UNSATISFIABLE => println("LEAK")
case Status.UNKNOWN => println(s"UNKNOWN: ${solver.getReasonUnknown}")
}
}