8

I want to transform/instrument Dex files. The goals of transformation include measuring code coverage. Note that the source files are not available. So instrumenting Dex is the only option.

I am wondering if there are any existing code base that I could look at as examples to write a tool to achieve my goal.

I know about the Smali project and a host of other projects that build on Smali. However, none of these projects are good examples for my purpose.

I am looking for code that automatically transforms smali code or the dexlib representation, from which smali is generated. The later option is preferred for my purpose because the overhead of generating smali can be avoided.

Saswat Anand
  • 358
  • 2
  • 10
  • 1
    Have you tried using dex2jar+emma+dx? I'm not sure how well that would work, but it might be worth a shot. – JesusFreke Oct 20 '12 at 17:31
  • 1
    My goal is to build a tool that works on any arbitrary apk in the context of automatic dynamic analysis. My experience so far has been that dex2jar or any other dex-to-java-bytecode translator does not work for arbitrary apks. I feel that a smali/dexlib based solution will be most robust. – Saswat Anand Oct 20 '12 at 20:05
  • I would tend to agree :) – JesusFreke Oct 20 '12 at 20:48

5 Answers5

3

It's a lot of code, but dx's DexMerger is an example program that transforms dex files. It's made quite complicated by the fact that it needs to guess the size of the output in order make forward-references work.

You'd also need to create infrastructure to rewrite dalvik instructions. DexMerger's InstructionTransformer does a shallow rewrite: it adjusts offsets from one mapping to another. To measure code coverage your instruction rewriting would probably need to be much more sophisticated.

Jesse Wilson
  • 39,078
  • 8
  • 121
  • 128
  • Thanks for the pointer to DexMerger! As you guessed, for code coverage I need to insert new instructions inside each method. As a result, I need to fix the code offset values corresponding to jump targets in different types of instructions. I am looking for examples that need to do similar transformation. DexMerger does not seem to need those. – Saswat Anand Oct 20 '12 at 16:55
2

Another option that have become available recently is Dexpler. It is an extension of Soot, which is a framework for analysis and instrumentation of Java programs. Dexpler reads in .apk files and converts to Jimple intermediate format. Jimple code can then be arbitrarily instrumented, and eventually dumped into a new apk.

Saswat Anand
  • 358
  • 2
  • 10
2

(For the record, I am answering my own question here)

Eventually I did not find any tool that fit my requirements. So I ended up building my own tool, called Ella, based on DexLib. Out of the box, it does a few things such as measuring code coverage, recording method traces, etc. But it can be easily extended to do other types of transformations.

Saswat Anand
  • 358
  • 2
  • 10
1

In some cases smali itself does a small amount of instruction rewriting while re-assembling a dex file. Things like replacing a const-string with a const-string/jumbo, or a goto instruction with a "larger" one, if the target is out of range. This involves replacing instructions in the instruction list with potentially larger ones, and the corresponding fixing up of offsets.

CodeItem.fixInstructions is the method responsible for this.


Additionally, there is the asmdex library. I'm not all that familiar with it, but it sounds like it might be relevant to what you're wanting to do.

JesusFreke
  • 19,784
  • 5
  • 65
  • 68
  • Thanks so much! The fixInstructions indeed is a good example for my purpose. – Saswat Anand Oct 20 '12 at 20:09
  • Thanks again! asmdex looks very promising as a tool for sophisticated instrumentation of dex. However, apparently it does not yet support odex format. I wonder if a lot of apk's available from common app-stores have odex code. – Saswat Anand Oct 22 '12 at 03:31
  • No. An odex file is device specific -- an odex file only works on the device it was built for/on. – JesusFreke Oct 22 '12 at 06:12
  • Does smali have to add new registers to a dex method? I am looking for example of how to do so. For my instrumentation, I need to add exactly one new register to hold a int value and use that register as an argument to an external method. amsdex does not currently provide a easy/robust way to add new registers. – Saswat Anand Oct 22 '12 at 20:06
  • Nope, not directly. It the smali code it's fairly easy because all of the parameter register use a separate p0 style of register, so all you have to do is bump the .registers/.locals directive, and then you are free to use the "new" last non-parameter register, which is guaranteed not to be used. But if you're working with dexlib, you'll have to search for any usages of parameter registers and bump them up by one as well. – JesusFreke Oct 23 '12 at 00:57
  • How about instructions that use range of registers? A range that includes some parameters and some non-parameter registers will end up using the newly added register. Isnt it possible? – Saswat Anand Oct 23 '12 at 01:53
0

I know it's a bit late but just in case you're still interested or perhaps for some other readers. ASMDEX has been mentioned already. And I think that's your best bet for the moment for what you're trying to achieve.

As for adding new registers take a look at org.ow2.asmdex.util.RegisterShiftMethodAdapter class. It's not perfect! As a matter of fact as it is it's horrible changing existing 4bit instructions when adding a register would mean some register would end up being 0xF and won't fit in 4 bits.

But it should be a good start.

atta
  • 1