Byte Code Injection for Dalvik through modified...

Deng Yao Deng Yao
Mar 12, 2012 at 1:43 pm
Sorry for bumping this old thread.

Tez, is there any progress on the injection? I need to do something
similar. But my problem is more difficult: I cannot build a customized
dalvik vm, I can only inject the "monitor" java code by native code
injection, which means firstly I have to inject native code into libdvm.so
like a virus, then the injected libdvm.so would load extra "monitor" java
code.
Currently I can inject instructions on the entry of any function whose
address is known. Which function from libdvm.so should I inject to get this
job done? Although with different versions the function name may be
different, I can handle this problem by injecting different native code
according to the version number.

Thanks
-Yao
- Show quoted text -
reply

Tweet

Search Discussions

All GroupsAndroidandroid-platform

13 responses

Nested Oldest
  • Tez Tez at Mar 12, 2012 at 4:58 pm
    can you explain your mechanism in more detail?
    my arch. is different.

    -Earlence
    - Show quoted text -
    reply | permalink
  • 邓尧 邓尧 at Mar 13, 2012 at 10:34 am
    My approach works on arm-linux.

    1. Attach to the target process with ptrace() system call.
    2. Create a break point in the target process like a debugger.
    3. When the break point is hit, copy some bootstrap code (more on bootstrap
    code below) on the stack of the target process. The stack of the target
    process can be found by parsing /proc/<pid>/maps, the corresponding line
    entry ends with "[stack]"
    4. Replace the break point with a "bx ip" instruction (similar to "jmp" in
    x86), modify the value of register "ip", then resume the target process.
    The target process will execute the injected bootstrap code.

    About the bootstrap code:
    a). The first instruction of the bootstrap code is a break point. When this
    break point is hit, do the following:
    * Clear the break point created in step 2.
    * Replace the break point created in step a) with a "nop" instruction.
    * Replace the first instruction of the injected function with any illegal
    instruction, I picked "0xdead" for THUMB code, "0xdeaddead" for ARM code.
    * Resume the target process
    b) The bootstrap code just register a signal handler for SIGILL with
    sigaction() system call. The third argument of the signal handler is a
    pointer to a "struct ucontext_t" structure (This structure isn't defined in
    android NDK, but can simply copy one from a gnu cross toolchain). In side
    the signal handler we can do anything we like.
    c) Modify the "pc" register of the "ucontext_t" register and return from
    the signal handler, the target process will jump to the corresponding
    address.
    d) After the jump in step c), first restore the registers (the values of
    the registers are saved in the "ucontext_t" structure), then execute the
    first instruction of the injected function if the instruction is position
    independent, otherwise interpret it (I haven't implemented this part yet,
    better to do the interpretation before returning from the signal handler).
    e) execute the rest of the injected function or return to its caller.

    BTW, according to C standard the behavior of returning from a SIGILL
    handler is undefined, but on arm-linux it just works.

    Thanks
    -Yao
    - Show quoted text -
    reply | permalink
  • 邓尧 邓尧 at Mar 13, 2012 at 11:26 am
    - Show quoted text -

    I made a mistake, the kernel will restore the registers according to the
    values saved in the "ucontext_t" structure automatically, sorry for this.

    Thanks
    -Yao
    - Show quoted text -
    reply | permalink
  • Tez Tez at Mar 13, 2012 at 4:25 pm
    as far as a linux process is concerned, this may work.
    but I am afraid that this is not going to work as far as Java is
    concerned.
    The VM interprets instructions, and thus the injection should
    manipulate the VM state.
    From the point of view of a linux process, this information is not
    accessible.

    from a process point of view, the address of an instruction could be
    the same in 2 cases, but the java code being executed at that point is
    something else altogether.

    this is a wrong approach. you have to inject into the bytecode stream
    and not native code stream

    -Earlence
    - Show quoted text -
    reply | permalink
  • Tez Tez at Mar 13, 2012 at 4:29 pm
    but if you still want to try,
    you can use the following function

    dvmGetMethodCode

    this is called to load a methods code when it is about to be executed.

    -Earlence
    - Show quoted text -
    reply | permalink
  • 邓尧 邓尧 at Mar 14, 2012 at 9:17 am
    I understand this problem. Since I cannot build a customized dalvikvm, I
    cannot get access to the bytecode stream unless native code is injected
    first.
    dvmGetMethodCode isn't a good function to inject, it's an inline function
    defined in a header file, it could be easy inlined into its caller. IMO,
    it's better to modify the bytecode stream right after loading it, but I
    haven't figured out how dalvik loads a bytecode stream.

    -Yao
    - Show quoted text -
    reply | permalink
  • Tez Tez at Mar 14, 2012 at 2:49 pm
    inject in the caller of dvmGetMethodCode in that case.

    -Earlence
    - Show quoted text -
    reply | permalink
  • Tez Tez at Mar 14, 2012 at 5:08 pm
    the other thing that came to mind is that this could be inefficient.
    essentially, the injection point would stop execution each time the
    function is called, since you have to check which method is going to
    be executed.

    -Earlence
    - Show quoted text -
    reply | permalink
  • 邓尧 邓尧 at Mar 14, 2012 at 6:02 pm
    True, that's why I want to modify the bytecode stream right after loading
    it. Class loading happens just once, but execution could be thousands of
    times.

    -Yao
    - Show quoted text -
    reply | permalink
  • Tez Tez at Mar 14, 2012 at 7:02 pm
    I am interested in how this turns out.
    If you manage to do it, can you post about it here?

    -Earlence
    - Show quoted text -
    reply | permalink
  • 邓尧 邓尧 at Mar 16, 2012 at 1:15 pm
    Sure, but I'm now on a different project, so it would take sometime.
    -Yao
    - Show quoted text -
    reply | permalink
  • Yuru Shao Yuru Shao at Jan 28, 2013 at 11:57 pm
    hi Yao, any updates?

    在 2012年3月16日星期五UTC+8下午1时15分25秒,Deng Yao写道:
    - Show quoted text -
    reply | permalink
  • 邓尧 邓尧 at Mar 13, 2012 at 9:49 am
    Since apk decompilers already exist, I believe the information in a
    pre-compiled library should be rich enough to identify any Java method.
    - Show quoted text -
    reply | permalink

你可能感兴趣的:(Byte Code Injection for Dalvik through modified...)