Thursday, January 31, 2013

Android hacking: hooking system functions used by Dalvik

Let's say you need to alter behavior of some Android app you do not have source code for.
For example, you want to redirect all socket connect()s made to badhost.com to myhost.com or perhaps even 127.0.0.1.
How this can be achieved (without having to root the device and recompile system libs) ?

On normal Linux systems one can easily use dynamic linker LD_PRELOAD environment variable to let ld change symbol resolution order and thus inject any code you want. However, on Android it is not possible for following reasons:
  • LD_PRELOAD is not useful because zygote already forked JVM
  • Once an app is running, JVM is already started
  • It not possible to (easily) modify environment variables for JVM invokation 
So, how do we do it? By patching PLT (.rel.plt)  (procedure linkage tables) of a running process in-flight!

I will not be going into describing how PLT works and details on ELF binary format. It is suffice to say that compiled code which imports symbols from other .so-s needs to figure out where these functions are located in memory. Since libraries can be loaded at a different place in memory for different processes, it is impossible to know imported functions addresses at compile time. Detailed description can be found here.

However, Android's Bionic library is different, and code specific to glib/gcc dynamic linker won't work. Fortunately, it is easily possible to access ld's internal structures and fish out relevant data. Consider signature of regular POSIX dlopen call:

 void *dlopen(const char *filename, int flag);

Interestingly, this gives us void* abstract 'handle'. In practice, this handle is pointer to a struct soinfo which contains all the information we ever need to override PLT tables.

From linker/linker.cpp:

 soinfo* do_dlopen(const char* name, int flags)  

Now, all we need to is to simply re-dlopen() shared library we want (in my case it libandroid_runtime.so) and walk through plt table, patch connect() method to our own.

Here is the complete hooking code:
/*
Copyright (C) 2013 Andrey Petrov

Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software 
without restriction, including without limitation the rights to use, copy, modify, 
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit 
persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or 
substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE 
FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
DEALINGS IN THE SOFTWARE.
*/

#define ANDROID_ARM_LINKER  
 #include <dlfcn.h>  
 #include <errno.h>  
 #include <fcntl.h>  
 #include <pthread.h>  
 #include <stdio.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #include <sys/atomics.h>  
 #include <sys/mman.h>  
 #include <sys/stat.h>  
 #include <unistd.h>  
 #include "linker.h"  // get it from bionic
 static unsigned elfhash(const char *_name)  
 {  
   const unsigned char *name = (const unsigned char *) _name;  
   unsigned h = 0, g;  
   while(*name) {  
     h = (h << 4) + *name++;  
     g = h & 0xf0000000;  
     h ^= g;  
     h ^= g >> 24;  
   }  
   return h;  
 }  
 static Elf32_Sym *soinfo_elf_lookup(soinfo *si, unsigned hash, const char *name)  
 {  
   Elf32_Sym *s;  
   Elf32_Sym *symtab = si->symtab;  
   const char *strtab = si->strtab;  
   unsigned n;  
   n = hash % si->nbucket;  
   for(n = si->bucket[hash % si->nbucket]; n != 0; n = si->chain[n]){  
     s = symtab + n;  
     if(strcmp(strtab + s->st_name, name)) continue;  
       return s;  
     }  
   return NULL;  
 }  
 int hook_call(char *soname, char *symbol, unsigned newval) {  
  soinfo *si = NULL;  
  Elf32_Rel *rel = NULL;  
  Elf32_Sym *s = NULL;   
  unsigned int sym_offset = 0;  
  if (!soname || !symbol || !newval)  
     return 0;  
  si = (soinfo*) dlopen(soname, 0);  
  if (!si)  
   return 0;  
  s = soinfo_elf_lookup(si, elfhash(symbol), symbol);  
  if (!s)  
    return 0;  
  sym_offset = s - si->symtab;  
  rel = si->plt_rel;  
  /* walk through reloc table, find symbol index matching one we've got */  
  for (int i = 0; i < si->plt_rel_count; i++, rel++) {  
   unsigned type = ELF32_R_TYPE(rel->r_info);  
   unsigned sym = ELF32_R_SYM(rel->r_info);  
   unsigned reloc = (unsigned)(rel->r_offset + si->base);  
   unsigned oldval = 0;  
   if (sym_offset == sym) {  
    switch(type) {  
      case R_ARM_JUMP_SLOT:  
         /* we do not have to read original value, but it would be good   
           idea to make sure it contains what we are looking for */  
         oldval = *(unsigned*) reloc;  
         *((unsigned*)reloc) = newval;  
         return 1;  
      default:  
         return 0;  
    }  
   }  
  }  
  return 0;  
 }  

So, in order to hook connect call you would need to call:

 hook_call("libandroid_runtime.so", "connect", &my_connect);  

All you now need is to write appropriate my_connect function which will inspect then modify input parameters and then delegate call to real connect()

Next thing to worry about is how to get this code to be executed on target app start, but perhaps it is a topic for a separate post.

Stay tuned ;-)

update: some people told me this interception does not work anymore. This works fine for 2.3.x and 4.0.x. For >4.1.x you would want to intercept libjavacore.so. Thanks for Madhavi Rao for figuring this out

65 comments:

  1. Does this require root? or can you do it for your own process?

    ReplyDelete
  2. Hi Andrey,

    Did you test this code on a ARM processor or just X86?

    Thanks.

    ATTA

    ReplyDelete
  3. HI Andrey,
    thanks for input, i would ask you if is possible to have some infos plus, like how to implement a basic "my_connect" and how to integrate in android java app.
    i'm a researcher and i'm looking for how to know if apps send personal informations to external server.
    thanks
    Andrea

    ReplyDelete
  4. Hi Andrey,
    I would like to know what all libraries and header files have to included from bionic for the above.
    Thanks.

    ReplyDelete
  5. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. Hey,

      in 4.2.2, when calling *((unsigned*)reloc) = newval using libjavacore.so, I get a segfault.

      Does anyone else have this problem? Is there a solution for newer android systems?
      Thx

      Delete
    2. Maybe you can reference this
      http://stackoverflow.com/questions/23443848/how-to-hook-system-calls-of-my-android-app-non-rooted-device/27099442#27099442

      Delete
  6. Also on android 4.1 memory near the "*(unsigned*) reloc" is protected. And operation:

    *((unsigned*)reloc) = newval;

    causes "signal 11 (SIGSEGV), code 2 (SEGV_ACCERR), fault addr 4e8afd08".
    So to make it work i've changed code:

    mprotect(aligned_pointer, pagesize, PROT_WRITE | PROT_READ);
    oldval = *(unsigned*) reloc;
    *((unsigned*)reloc) = newval;
    mprotect(aligned_pointer, pagesize, PROT_READ);

    ReplyDelete
    Replies
    1. Forgot to write:

      size_t pagesize = sysconf(_SC_PAGESIZE);
      const void* aligned_pointer = (const void*)(reloc & ~(pagesize - 1));

      Delete
  7. This comment has been removed by the author.

    ReplyDelete
  8. I need to read memory value of another app... like which frequency fm radio is listening... please help... and where should i start ???

    ReplyDelete
  9. This comment has been removed by the author.

    ReplyDelete
    Replies
    1. This comment has been removed by the author.

      Delete
    2. This comment has been removed by the author.

      Delete
  10. It is not working in android 6.0 version. Any idea to fix it?

    ReplyDelete
    Replies
    1. I'm really interested in which part this way fails.
      Is the content of the soinfo which is got from dlopen() correct ?

      Delete
    2. dlopen has been changed in the bionic library so it no longer returns a pointer to the soinfo struct, but rather a handle. This renders the technique in this post useless, although there are other methods ;)

      Delete
  11. Given so much info in it, These type of articles keeps the users interest in the website, and keep on sharing more ... good luck.
    Android Training in chennai | Android Training

    ReplyDelete
  12. It is really a great work and the way in which u r sharing the knowledge is excellent.
    Thanks for helping me to understand basic concepts. As a beginner in android programming your post help me a lot.Thanks for your informative article Android Training in velachery | Android Training institute in chennai

    ReplyDelete
  13. I need you to contact me badly buddy, I got a good paid job for you. Give me a mail to ibo1989-regis@yahoo.de

    ReplyDelete
  14. Great Article… I love to read your articles because your writing style is too good, its is very very helpful for all of us and I never get bored while reading your article because, they are becomes a more and more interesting from the starting lines until the end.


    rpa Training in Chennai

    rpa Training in bangalore

    rpa Training in pune

    blueprism Training in Chennai

    blueprism Training in bangalore

    blueprism Training in pune

    rpa online training

    ReplyDelete
  15. Excellant post!!!. The strategy you have posted on this technology helped me to get into the next level and had lot of information in it.
    AWS Training in chennai

    AWS Training in bangalore

    ReplyDelete
  16. Well done! Pleasant post! This truly helps me to discover the solutions for my inquiry. Trusting, that you will keep posting articles having heaps of valuable data. You're the best! 

    java training in tambaram | java training in velachery

    java training in omr | oracle training in chennai

    java training in annanagar | java training in chennai

    ReplyDelete
  17. Fantastic work! This is the type of information that should follow collective approximately the web. Embarrassment captivating position Google for not positioning this transmit higher! Enlarge taking place greater than and visit my web situate
    Blueprism training in Pune

    Blueprism online training

    Blue Prism Training in Pune

    ReplyDelete
  18. Well researched article and I appreciate this. The blog is subscribed and will see new topics soon.
    python training in chennai
    python training in Bangalore

    ReplyDelete
  19. This is most informative and also this post most user friendly and super navigation to all posts... Thank you so much for giving this information to me.. 
    DevOps online Training|DevOps Training in USA
    Devops Training in Chennai
    Devops Training in Bangalore

    ReplyDelete
  20. A very nice guide. I will definitely follow these tips. Thank you for sharing such detailed article. I am learning a lot from you.
    Blueprism training in annanagar

    Blueprism training in velachery

    Blueprism training in marathahalli

    ReplyDelete
  21. Awesome article. It is so detailed and well formatted that i enjoyed reading it as well as get some new information too.
    java training in jayanagar | java training in electronic city

    java training in chennai | java training in USA

    ReplyDelete
  22. Excellent tutorial buddy. Directly I saw your blog and way of teaching was perfect, Waiting for your next tutorial.
    rpa training in chennai | rpa training in velachery | rpa training in chennai omr

    ReplyDelete
  23. myTectra a global learning solutions company helps transform people and organization to gain real, lasting benefits.Join Today.Ready to Unlock your Learning Potential !Read More...

    ReplyDelete
  24. I am really happy with your blog because your article is very unique and powerful for new reader.
    Click here:
    selenium training in chennai
    selenium training in bangalore
    selenium training in Pune
    selenium training in pune
    Selenium Online Training


    http://shreeraj.blogspot.com/2011/11/csrf-with-json-leveraging-xhr-and-cors_28.html

    ReplyDelete
  25. Amazon Web Services (AWS) is the most popular and most widely used Infrastructure as a Service (IaaS) cloud in the world.AWS has four core feature buckets—Compute, Storage & Content Delivery, Databases, and Networking. At a high level, you can control all of these with extensive administrative controls accessible via a secure Web client.For more information visit.
    aws online training
    aws training in hyderabad
    aws online training in hyderabad

    ReplyDelete
  26. Selenium is one of the most popular automated testing tool used to automate various types of applications. Selenium is a package of several testing tools designed in a way for to support and encourage automation testing of functional aspects of web-based applications and a wide range of browsers and platforms and for the same reason, it is referred to as a Suite.

    Selenium Interview Questions and Answers
    Javascript Interview Questions
    Human Resource (HR) Interview Questions

    ReplyDelete
  27. Thanks for sharing this kind of wonderful informative blogs in live. I have bookmarked more article from this website. Such a nice blog you are providing ! Kindly Visit Us R Programming training in Chennai | R Programming Training in Chennai with placement | R Programming Interview Questions and Answers | Trending Software Technologies in 2018

    ReplyDelete
  28. It's really a nice experience to read your post. Thank you for sharing this useful information. If you are looking for more about Roles and reponsibilities of hadoop developer | hadoop developer skills Set | hadoop training course fees in chennai | Hadoop Training in Chennai Omr

    ReplyDelete
  29. I love what you’ve got to say. But maybe you could a little more in the way of content so people could connect with it better.
    safety course in chennai

    ReplyDelete
  30. DevOps is currently a popular model currently organizations all over the world moving towards to it. Your post gave a clear idea about knowing the DevOps model and its importance.

    Good to learn about DevOps at this time.


    devops training in chennai | devops training in chennai with placement | devops training in chennai omr | devops training in velachery | devops training in chennai tambaram | devops institutes in chennai | devops certification in chennai | trending technologies list 2018

    ReplyDelete
  31. Goyal packers and movers in Panchkula is highly known for their professional and genuine packing and moving services. We are top leading and certified relocation services providers in Chandigarh deals all over India. To get more information, call us.


    Packers and movers in Chandigarh
    Packers and movers in Panchkula
    Packers and movers in Mohali
    Packers and movers in Zirakpur
    Packers and movers in Patiala
    Packers and movers in Ambala
    Packers and movers in Ambala cantt
    Packers and movers in Pathankot
    Packers and movers in Jalandhar
    Packers and movers in Ludhiana

    ReplyDelete
  32. Outstanding blog thanks for sharing such wonderful blog with us ,after long time came across such knowlegeble blog. keep sharing such informative blog with us.

    machine learning course in Chennai
    machine learning training center in Chennai
    machine learning with python course in Chennai
    Android training in chennai
    PMP training in chennai

    ReplyDelete
  33. Are you trying to move in or out of Jind? or near rohtak Find the most famous, reputed and the very best of all Packers and Movers by simply calling or talking to Airavat Movers and Packers

    Packers And Movers in Jind

    Packers And Movers in Rohtak

    Movers And Packers in Rohtak

    ReplyDelete
  34. Really useful information. Thank you so much for sharing.It will help everyone.Keep Post. RPA training in chennai | RPA training in Chennai with placement

    ReplyDelete