Permalink
Browse files

Added instrumentation of static method

  • Loading branch information...
1 parent 0c9a834 commit 25c30c129abcfa385ce1ce3390919574c6b62775 @kelwin committed Aug 3, 2012
Showing with 207 additions and 9 deletions.
  1. +187 −2 apkil/monitor.py
  2. +20 −7 test.py
View
189 apkil/monitor.py
@@ -24,6 +24,9 @@ def __repr__(self):
pass
def add_stub_method(self, m):
+ segs = m.split(':', 1)
+ method_type = segs[0]
+ m = segs[1]
segs = m.rsplit("->", 1)
if self.stub_classes.has_key(segs[0]):
@@ -60,10 +63,13 @@ def add_stub_method(self, m):
stub_class.add_method(method)
method_name = segs[1][:segs[1].find("(")]
- if method_name == "<init>":
+ if method_type == "constructor":
self.__add_stub_cons(stub_class, m)
- else:
+ elif method_type == "instance":
self.__add_stub_inst(stub_class, m)
+ elif method_type == "static":
+ self.__add_stub_static(stub_class, m)
+
def __add_stub_inst(self, stub_class, m):
segs = m.rsplit("->", 1)
@@ -419,4 +425,183 @@ def __add_stub_cons(self, stub_class, m):
self.method_map[m] = "L" + PKG_PREFIX + "/" + segs[0][1:] + "->" + \
method.get_desc()
+#invoke-static {v1}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;
+ def __add_stub_static(self, stub_class, m):
+ segs = m.rsplit("->", 1)
+
+ method = MethodNode()
+ method.set_desc(segs[1])
+ method.add_access(["public", "static"])
+
+ para_num = len(method.paras)
+ ri = 1
+
+ if para_num <= 5:
+ i = "invoke-static {%s}, %s" % \
+ (", ".join(["p%d" % k for k in range(para_num)]), m)
+ else:
+ i = "invoke-static/range {p0 .. p%d}, %s" % (opcode, para_num - 1, m)
+
+ method.add_insn(InsnNode(i))
+
+ if not method.ret.void:
+ if method.ret.basic:
+ if method.ret.words == 1:
+ method.add_insn(InsnNode("move-result v1"))
+ ri += 1
+ else:
+ method.add_insn(InsnNode("move-result-wide v1"))
+ ri += 2
+ else:
+ method.add_insn(InsnNode("move-result-object v1"))
+ ri += 1
+
+ method.add_insn(InsnNode("new-instance \
+v%d, Ljava/lang/StringBuilder;" % ri))
+ method.add_insn(InsnNode("invoke-direct \
+{v%d}, Ljava/lang/StringBuilder;-><init>()V" % ri))
+
+ method.add_insn(InsnNode("const-string v%d,\"%s(\"" % \
+ (ri + 1, m.split('(', 1)[0])))
+ append_i = InsnNode("invoke-virtual \
+{v%d, v%d}, Ljava/lang/StringBuilder;->\
+append(Ljava/lang/String;)Ljava/lang/StringBuilder;" % \
+ (ri, ri + 1))
+ method.add_insn(append_i)
+
+ # print parameters
+ conds = []
+ pi = 0
+ for k in range(0, para_num):
+ p = method.paras[k]
+ method.add_insn(InsnNode("const-string v%d, \"%s=\"" % (ri + 1,
+ p.get_desc())))
+ method.add_insn(append_i)
+
+ if p.basic:
+ if p.words == 1:
+ method.add_insn(InsnNode("invoke-static {p%d}, \
+Ljava/lang/String;->valueOf(%s)Ljava/lang/String;" % \
+ (pi, p.get_desc())))
+ pi += 1
+ else:
+ method.add_insn(InsnNode("invoke-static \
+{p%d, p%d}, Ljava/lang/String;->valueOf(%s)Ljava/lang/String;" % \
+ (pi, pi + 1, p.get_desc())))
+ pi += 2
+ method.add_insn(InsnNode("move-result-object v%d" % (ri + 1)))
+ method.add_insn(append_i)
+ else:
+ cond_tag = len(method.insns)
+ conds.append(cond_tag)
+ method.add_insn(InsnNode("if-eqz p%d, :droidbox_cond_%d" %\
+ (pi, cond_tag)))
+ method.add_insn(InsnNode("invoke-virtual {p%d}, \
+%s->toString()Ljava/lang/String;" % (pi, p.get_desc())))
+ pi += 1
+ method.add_insn(InsnNode("move-result-object v%d" % (ri + 1)))
+ method.add_insn(append_i)
+ index = len(method.insns)
+ cond = LabelNode(":droidbox_goto_%d" % cond_tag, index)
+ method.add_label(cond)
+
+ if k < para_num - 1:
+ method.add_insn(InsnNode("const-string v%d, \" | \"" % \
+ (ri + 1)))
+ method.add_insn(append_i)
+
+ method.add_insn(InsnNode("const-string v%d, \")\"" % (ri + 1)))
+ method.add_insn(append_i)
+
+ # print return value
+ p = method.ret
+ if p.void:
+ method.add_insn(InsnNode("const-string v%d, \"%s\"" % (ri + 1,
+ p.get_desc())))
+ method.add_insn(append_i)
+ else:
+ method.add_insn(InsnNode("const-string v%d, \"%s=\"" % (ri + 1,
+ p.get_desc())))
+ method.add_insn(append_i)
+ if p.basic:
+ if p.words == 1:
+ method.add_insn(InsnNode("invoke-static {v1}, \
+Ljava/lang/String;->valueOf(%s)Ljava/lang/String;" % \
+ p.get_desc()))
+ else:
+ method.add_insn(InsnNode("invoke-static \
+{v1, v2}, Ljava/lang/String;->valueOf(%s)Ljava/lang/String;" % \
+ p.get_desc()))
+ method.add_insn(InsnNode("move-result-object v%d" % (ri + 1)))
+ method.add_insn(append_i)
+ else:
+ cond_tag = len(method.insns)
+ conds.append(cond_tag)
+ method.add_insn(InsnNode("if-eqz v1, :droidbox_cond_%d" %\
+ cond_tag))
+ method.add_insn(InsnNode("invoke-virtual {v1}, \
+%s->toString()Ljava/lang/String;" % p.get_desc()))
+ method.add_insn(InsnNode("move-result-object v%d" % (ri + 1)))
+ method.add_insn(append_i)
+ index = len(method.insns)
+ cond = LabelNode(":droidbox_goto_%d" % cond_tag, index)
+ method.add_label(cond)
+
+ method.add_insn(InsnNode("const-string v%d, \"DroidBox\"" % \
+ (ri + 1)))
+ method.add_insn(InsnNode("invoke-virtual {v%d}, \
+Ljava/lang/StringBuilder;->toString()Ljava/lang/String;" % ri))
+ method.add_insn(InsnNode("move-result-object v%d" % (ri + 2)))
+ method.add_insn(InsnNode("invoke-static {v%d, v%d}, \
+Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I" % \
+ (ri + 1, ri + 2)))
+ if not method.ret.void:
+ if method.ret.basic:
+ if method.ret.words == 1:
+ method.add_insn(InsnNode("return v1"))
+ else:
+ method.add_insn(InsnNode("return-wide v1"))
+ else:
+ method.add_insn(InsnNode("return-object v1"))
+ else:
+ method.add_insn(InsnNode("return-void"))
+
+ start = LabelNode(":droidbox_try_start", 0)
+ end = LabelNode(":droidbox_try_end", 1)
+ index = len(method.insns)
+ ret = LabelNode(":droidbox_return", index - 1)
+ handler = LabelNode(":droidbox_handler", index)
+ line = ".catch Ljava/lang/Exception; {:droidbox_try_start .. \
+:droidbox_try_end} :droidbox_handler"
+ TryNode(line, start, end, handler)
+ method.add_label([start, end, ret, handler])
+
+ method.add_insn(InsnNode("move-exception v0"))
+ method.add_insn(InsnNode("invoke-virtual {v0}, \
+Ljava/lang/Exception;->printStackTrace()V"))
+ if not method.ret.void:
+ if method.ret.basic:
+ if method.ret.words == 1:
+ method.add_insn(InsnNode("const/4 v1, 0x0"))
+ else:
+ method.add_insn(InsnNode("const-wide/16 v1, 0x0"))
+ else:
+ method.add_insn(InsnNode("const/4 v1, 0x0"))
+ method.add_insn(InsnNode("goto :droidbox_return"))
+
+ for t in conds:
+ index = len(method.insns)
+ cond = LabelNode(":droidbox_cond_%d" % t, index)
+ method.add_label(cond)
+ method.add_insn(InsnNode("const-string v%d, \"null\"" %\
+ (ri + 1)))
+ method.add_insn(append_i)
+ method.add_insn(InsnNode("goto :droidbox_goto_%d" % t))
+
+ method.set_registers(para_num + ri + 3)
+ stub_class.add_method(method)
+
+ i = m.find('(')
+ self.method_map[m] = "L" + PKG_PREFIX + "/" + segs[0][1:] + "->" + \
+ method.get_desc()
View
27 test.py
@@ -39,17 +39,21 @@
API_LIST = [ #"Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V", \
#"Landroid/content/ContentValues;->put(Ljava/lang/String;Ljava/lang/Integer;)V", \
#"Landroid/content/ContentValues;->put(Ljava/lang/String;Ljava/lang/String;)V", \
-"Landroid/content/Intent;-><init>(Ljava/lang/String;)V", \
-"Lapkil/tests/APKIL;->openFileOutput(Ljava/lang/String;I)Ljava/io/FileOutputStream;", \
-"Ljava/io/OutputStreamWriter;->write(Ljava/lang/String;)V", \
-"Lapkil/tests/APKIL;->openFileInput(Ljava/lang/String;)Ljava/io/FileInputStream;",
-"Ljava/io/BufferedReader;->readLine()Ljava/lang/String;", \
+"static:Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;", \
+"constructor:Landroid/content/Intent;-><init>(Ljava/lang/String;)V", \
+"instance:Lapkil/tests/APKIL;->openFileOutput(Ljava/lang/String;I)Ljava/io/FileOutputStream;", \
+"instance:Ljava/io/OutputStreamWriter;->write(Ljava/lang/String;)V", \
+"instance:Lapkil/tests/APKIL;->openFileInput(Ljava/lang/String;)Ljava/io/FileInputStream;",
+"instance:Ljava/io/BufferedReader;->readLine()Ljava/lang/String;", \
]
mo = monitor.APIMonitor(API_LIST)
for api in API_LIST:
+ segs = api.split(':', 1)
+ method_type = segs[0]
+ api = segs[1]
segs = api.split("->")
- if segs[1][:segs[1].find('(')] == "<init>":
+ if method_type == "constructor":
for c in s.classes:
for m in c.methods:
for i in range(len(m.insns)):
@@ -62,7 +66,7 @@
m.insert_insn(smali.InsnNode(\
"move-result-object %s" % r), i + 1, 0)
- else:
+ elif method_type == "instance":
for c in s.classes:
for m in c.methods:
for i in range(len(m.insns)):
@@ -71,6 +75,15 @@
insn.opcode_name == "invoke-virtual" and \
insn.obj.method_desc == api :
insn.obj.replace("invoke-static", mo.method_map[api])
+ elif method_type == "static":
+ for c in s.classes:
+ for m in c.methods:
+ for i in range(len(m.insns)):
+ insn = m.insns[i]
+ if insn.fmt == "35c" and \
+ insn.opcode_name == "invoke-static" and \
+ insn.obj.method_desc == api :
+ insn.obj.replace("invoke-static", mo.method_map[api])
for c in mo.stub_classes.values():
s.add_class(c)

0 comments on commit 25c30c1

Please sign in to comment.