92 lines
2.5 KiB
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}")
|
|
}
|
|
|
|
}
|