Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Added instrumentation of static method

  • Loading branch information...
commit 25c30c129abcfa385ce1ce3390919574c6b62775 1 parent 0c9a834
Kun Yang authored

Showing 2 changed files with 207 additions and 9 deletions. Show diff stats Hide diff stats

  1. +187 2 apkil/monitor.py
  2. +20 7 test.py
189 apkil/monitor.py
@@ -24,6 +24,9 @@ def __repr__(self):
24 24 pass
25 25
26 26 def add_stub_method(self, m):
  27 + segs = m.split(':', 1)
  28 + method_type = segs[0]
  29 + m = segs[1]
27 30 segs = m.rsplit("->", 1)
28 31
29 32 if self.stub_classes.has_key(segs[0]):
@@ -60,10 +63,13 @@ def add_stub_method(self, m):
60 63 stub_class.add_method(method)
61 64
62 65 method_name = segs[1][:segs[1].find("(")]
63   - if method_name == "<init>":
  66 + if method_type == "constructor":
64 67 self.__add_stub_cons(stub_class, m)
65   - else:
  68 + elif method_type == "instance":
66 69 self.__add_stub_inst(stub_class, m)
  70 + elif method_type == "static":
  71 + self.__add_stub_static(stub_class, m)
  72 +
67 73
68 74 def __add_stub_inst(self, stub_class, m):
69 75 segs = m.rsplit("->", 1)
@@ -419,4 +425,183 @@ def __add_stub_cons(self, stub_class, m):
419 425 self.method_map[m] = "L" + PKG_PREFIX + "/" + segs[0][1:] + "->" + \
420 426 method.get_desc()
421 427
  428 +#invoke-static {v1}, Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;
  429 + def __add_stub_static(self, stub_class, m):
  430 + segs = m.rsplit("->", 1)
  431 +
  432 + method = MethodNode()
  433 + method.set_desc(segs[1])
  434 + method.add_access(["public", "static"])
  435 +
  436 + para_num = len(method.paras)
  437 + ri = 1
  438 +
  439 + if para_num <= 5:
  440 + i = "invoke-static {%s}, %s" % \
  441 + (", ".join(["p%d" % k for k in range(para_num)]), m)
  442 + else:
  443 + i = "invoke-static/range {p0 .. p%d}, %s" % (opcode, para_num - 1, m)
  444 +
  445 + method.add_insn(InsnNode(i))
  446 +
  447 + if not method.ret.void:
  448 + if method.ret.basic:
  449 + if method.ret.words == 1:
  450 + method.add_insn(InsnNode("move-result v1"))
  451 + ri += 1
  452 + else:
  453 + method.add_insn(InsnNode("move-result-wide v1"))
  454 + ri += 2
  455 + else:
  456 + method.add_insn(InsnNode("move-result-object v1"))
  457 + ri += 1
  458 +
  459 + method.add_insn(InsnNode("new-instance \
  460 +v%d, Ljava/lang/StringBuilder;" % ri))
  461 + method.add_insn(InsnNode("invoke-direct \
  462 +{v%d}, Ljava/lang/StringBuilder;-><init>()V" % ri))
  463 +
  464 + method.add_insn(InsnNode("const-string v%d,\"%s(\"" % \
  465 + (ri + 1, m.split('(', 1)[0])))
  466 + append_i = InsnNode("invoke-virtual \
  467 +{v%d, v%d}, Ljava/lang/StringBuilder;->\
  468 +append(Ljava/lang/String;)Ljava/lang/StringBuilder;" % \
  469 + (ri, ri + 1))
  470 + method.add_insn(append_i)
  471 +
  472 + # print parameters
  473 + conds = []
  474 + pi = 0
  475 + for k in range(0, para_num):
  476 + p = method.paras[k]
  477 + method.add_insn(InsnNode("const-string v%d, \"%s=\"" % (ri + 1,
  478 + p.get_desc())))
  479 + method.add_insn(append_i)
  480 +
  481 + if p.basic:
  482 + if p.words == 1:
  483 + method.add_insn(InsnNode("invoke-static {p%d}, \
  484 +Ljava/lang/String;->valueOf(%s)Ljava/lang/String;" % \
  485 + (pi, p.get_desc())))
  486 + pi += 1
  487 + else:
  488 + method.add_insn(InsnNode("invoke-static \
  489 +{p%d, p%d}, Ljava/lang/String;->valueOf(%s)Ljava/lang/String;" % \
  490 + (pi, pi + 1, p.get_desc())))
  491 + pi += 2
  492 + method.add_insn(InsnNode("move-result-object v%d" % (ri + 1)))
  493 + method.add_insn(append_i)
  494 + else:
  495 + cond_tag = len(method.insns)
  496 + conds.append(cond_tag)
  497 + method.add_insn(InsnNode("if-eqz p%d, :droidbox_cond_%d" %\
  498 + (pi, cond_tag)))
  499 + method.add_insn(InsnNode("invoke-virtual {p%d}, \
  500 +%s->toString()Ljava/lang/String;" % (pi, p.get_desc())))
  501 + pi += 1
  502 + method.add_insn(InsnNode("move-result-object v%d" % (ri + 1)))
  503 + method.add_insn(append_i)
  504 + index = len(method.insns)
  505 + cond = LabelNode(":droidbox_goto_%d" % cond_tag, index)
  506 + method.add_label(cond)
  507 +
  508 + if k < para_num - 1:
  509 + method.add_insn(InsnNode("const-string v%d, \" | \"" % \
  510 + (ri + 1)))
  511 + method.add_insn(append_i)
  512 +
  513 + method.add_insn(InsnNode("const-string v%d, \")\"" % (ri + 1)))
  514 + method.add_insn(append_i)
  515 +
  516 + # print return value
  517 + p = method.ret
  518 + if p.void:
  519 + method.add_insn(InsnNode("const-string v%d, \"%s\"" % (ri + 1,
  520 + p.get_desc())))
  521 + method.add_insn(append_i)
  522 + else:
  523 + method.add_insn(InsnNode("const-string v%d, \"%s=\"" % (ri + 1,
  524 + p.get_desc())))
  525 + method.add_insn(append_i)
  526 + if p.basic:
  527 + if p.words == 1:
  528 + method.add_insn(InsnNode("invoke-static {v1}, \
  529 +Ljava/lang/String;->valueOf(%s)Ljava/lang/String;" % \
  530 + p.get_desc()))
  531 + else:
  532 + method.add_insn(InsnNode("invoke-static \
  533 +{v1, v2}, Ljava/lang/String;->valueOf(%s)Ljava/lang/String;" % \
  534 + p.get_desc()))
  535 + method.add_insn(InsnNode("move-result-object v%d" % (ri + 1)))
  536 + method.add_insn(append_i)
  537 + else:
  538 + cond_tag = len(method.insns)
  539 + conds.append(cond_tag)
  540 + method.add_insn(InsnNode("if-eqz v1, :droidbox_cond_%d" %\
  541 + cond_tag))
  542 + method.add_insn(InsnNode("invoke-virtual {v1}, \
  543 +%s->toString()Ljava/lang/String;" % p.get_desc()))
  544 + method.add_insn(InsnNode("move-result-object v%d" % (ri + 1)))
  545 + method.add_insn(append_i)
  546 + index = len(method.insns)
  547 + cond = LabelNode(":droidbox_goto_%d" % cond_tag, index)
  548 + method.add_label(cond)
  549 +
  550 + method.add_insn(InsnNode("const-string v%d, \"DroidBox\"" % \
  551 + (ri + 1)))
  552 + method.add_insn(InsnNode("invoke-virtual {v%d}, \
  553 +Ljava/lang/StringBuilder;->toString()Ljava/lang/String;" % ri))
  554 + method.add_insn(InsnNode("move-result-object v%d" % (ri + 2)))
  555 + method.add_insn(InsnNode("invoke-static {v%d, v%d}, \
  556 +Landroid/util/Log;->v(Ljava/lang/String;Ljava/lang/String;)I" % \
  557 + (ri + 1, ri + 2)))
  558 + if not method.ret.void:
  559 + if method.ret.basic:
  560 + if method.ret.words == 1:
  561 + method.add_insn(InsnNode("return v1"))
  562 + else:
  563 + method.add_insn(InsnNode("return-wide v1"))
  564 + else:
  565 + method.add_insn(InsnNode("return-object v1"))
  566 + else:
  567 + method.add_insn(InsnNode("return-void"))
  568 +
  569 + start = LabelNode(":droidbox_try_start", 0)
  570 + end = LabelNode(":droidbox_try_end", 1)
  571 + index = len(method.insns)
  572 + ret = LabelNode(":droidbox_return", index - 1)
  573 + handler = LabelNode(":droidbox_handler", index)
  574 + line = ".catch Ljava/lang/Exception; {:droidbox_try_start .. \
  575 +:droidbox_try_end} :droidbox_handler"
  576 + TryNode(line, start, end, handler)
  577 + method.add_label([start, end, ret, handler])
  578 +
  579 + method.add_insn(InsnNode("move-exception v0"))
  580 + method.add_insn(InsnNode("invoke-virtual {v0}, \
  581 +Ljava/lang/Exception;->printStackTrace()V"))
  582 + if not method.ret.void:
  583 + if method.ret.basic:
  584 + if method.ret.words == 1:
  585 + method.add_insn(InsnNode("const/4 v1, 0x0"))
  586 + else:
  587 + method.add_insn(InsnNode("const-wide/16 v1, 0x0"))
  588 + else:
  589 + method.add_insn(InsnNode("const/4 v1, 0x0"))
  590 + method.add_insn(InsnNode("goto :droidbox_return"))
  591 +
  592 + for t in conds:
  593 + index = len(method.insns)
  594 + cond = LabelNode(":droidbox_cond_%d" % t, index)
  595 + method.add_label(cond)
  596 + method.add_insn(InsnNode("const-string v%d, \"null\"" %\
  597 + (ri + 1)))
  598 + method.add_insn(append_i)
  599 + method.add_insn(InsnNode("goto :droidbox_goto_%d" % t))
  600 +
  601 + method.set_registers(para_num + ri + 3)
  602 + stub_class.add_method(method)
  603 +
  604 + i = m.find('(')
  605 + self.method_map[m] = "L" + PKG_PREFIX + "/" + segs[0][1:] + "->" + \
  606 + method.get_desc()
422 607
27 test.py
@@ -39,17 +39,21 @@
39 39 API_LIST = [ #"Landroid/widget/TextView;->setText(Ljava/lang/CharSequence;)V", \
40 40 #"Landroid/content/ContentValues;->put(Ljava/lang/String;Ljava/lang/Integer;)V", \
41 41 #"Landroid/content/ContentValues;->put(Ljava/lang/String;Ljava/lang/String;)V", \
42   -"Landroid/content/Intent;-><init>(Ljava/lang/String;)V", \
43   -"Lapkil/tests/APKIL;->openFileOutput(Ljava/lang/String;I)Ljava/io/FileOutputStream;", \
44   -"Ljava/io/OutputStreamWriter;->write(Ljava/lang/String;)V", \
45   -"Lapkil/tests/APKIL;->openFileInput(Ljava/lang/String;)Ljava/io/FileInputStream;",
46   -"Ljava/io/BufferedReader;->readLine()Ljava/lang/String;", \
  42 +"static:Landroid/net/Uri;->parse(Ljava/lang/String;)Landroid/net/Uri;", \
  43 +"constructor:Landroid/content/Intent;-><init>(Ljava/lang/String;)V", \
  44 +"instance:Lapkil/tests/APKIL;->openFileOutput(Ljava/lang/String;I)Ljava/io/FileOutputStream;", \
  45 +"instance:Ljava/io/OutputStreamWriter;->write(Ljava/lang/String;)V", \
  46 +"instance:Lapkil/tests/APKIL;->openFileInput(Ljava/lang/String;)Ljava/io/FileInputStream;",
  47 +"instance:Ljava/io/BufferedReader;->readLine()Ljava/lang/String;", \
47 48 ]
48 49 mo = monitor.APIMonitor(API_LIST)
49 50
50 51 for api in API_LIST:
  52 + segs = api.split(':', 1)
  53 + method_type = segs[0]
  54 + api = segs[1]
51 55 segs = api.split("->")
52   - if segs[1][:segs[1].find('(')] == "<init>":
  56 + if method_type == "constructor":
53 57 for c in s.classes:
54 58 for m in c.methods:
55 59 for i in range(len(m.insns)):
@@ -62,7 +66,7 @@
62 66 m.insert_insn(smali.InsnNode(\
63 67 "move-result-object %s" % r), i + 1, 0)
64 68
65   - else:
  69 + elif method_type == "instance":
66 70 for c in s.classes:
67 71 for m in c.methods:
68 72 for i in range(len(m.insns)):
@@ -71,6 +75,15 @@
71 75 insn.opcode_name == "invoke-virtual" and \
72 76 insn.obj.method_desc == api :
73 77 insn.obj.replace("invoke-static", mo.method_map[api])
  78 + elif method_type == "static":
  79 + for c in s.classes:
  80 + for m in c.methods:
  81 + for i in range(len(m.insns)):
  82 + insn = m.insns[i]
  83 + if insn.fmt == "35c" and \
  84 + insn.opcode_name == "invoke-static" and \
  85 + insn.obj.method_desc == api :
  86 + insn.obj.replace("invoke-static", mo.method_map[api])
74 87
75 88 for c in mo.stub_classes.values():
76 89 s.add_class(c)

0 comments on commit 25c30c1

Please sign in to comment.
Something went wrong with that request. Please try again.