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 -
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 -
| Tweet | | |
Search Discussions
-
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 - -
邓尧 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 - -
邓尧 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 - -
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 notaccessible.
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 - -
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 - -
邓尧 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 - -
Tez at Mar 14, 2012 at 2:49 pm ⇧ -
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 - -
邓尧 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 - -
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 - -
邓尧 at Mar 16, 2012 at 1:15 pm ⇧ -
Yuru Shao at Jan 28, 2013 at 11:57 pm ⇧ -
邓尧 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 -