It is an introduction to the Native Hook mechanism, which is a function hook mechanism in Android. It is implemented in Bionic linker, which is the dynamic linker in Android. With Native Hook mechanism enabled, you can hook any native function with another one, without any modification to the existing libraries.
Booking open Available Pune Call Girls Koregaon Park 6297143586 Call Hot Ind...
Native hook mechanism in Android Bionic linker
1. Android Dynamic Framework :
Native Hook Mechanism in Bionic Linker
Mai-Hsuan Chia
Shih-Wei Liao
Department of Computer Science and Information Engineering
National Taiwan University
10. Android Dynamic Framework
Class A Class B
HookTable
...
class
linker
Method A1
Method A2
Method B1
Method B2
1. Query HookTable
11. Android Dynamic Framework
Class A Class B
HookTable
...
class
linker
Method A1
Method A2
Method B1
Method B2
Replace
ClassA::A1 with
ClassB::B1
1. Query HookTable
12. Android Dynamic Framework
Class A Class B
HookTable
...
class
linker
Method A2
Method B1
Method B2
Method B1
2. Do method hooking
13. ● C library in Android
● Forked from BSDs rather than from GNU/Linux
○ To avoid license problems
● Smaller
● Faster
Bionic
21. Motivation
● (1) method hook can be done in the existing Android Dynamic
Framework
● However, (2) dlopen native hook and (3) native to native hook
cannot not be done.
22. Motivation
● Native hook mechanism can do both (2) dlopen native hook and
(3) native to native hook
23. Motivation
With Native hook mechanism integrated,
Android Dynamic Framework can be more complete and powerful
38. Load needed libraries
liba1.soexe liba2.so libb1.so libb2.so ...
● find_libaries(exe, needed_libraries_names)
○ step 2 : turn dependencies tree into libraries_list in
Breadth First Search(BFS) order
libraries_list
dependencies tree
39. Link the application and all libraries
● find_libaries(exe, needed_libraries_names)
○ step 3 : relocate all to-be-relocated symbols in the
application and libraries
foreach lib in libraries_list {
foreach rel in lib.dynamic_relocation_table {
symbol = rel.sym;
soinfo_do_lookup(symbol, lib, libraries_list);
}
}
40. Link the application and all libraries
● find_libaries(exe, needed_libraries_names)
○ step 3 : relocate all to-be-relocated symbols in the
application and libraries
liba1.soexe liba2.so libb1.so libb2.so ...
libraries_list
exe
sym_1
sym_n
...
if sym_1 is defined in lib:
sym_1 = lib.find(sym)
else:
lib = lib->next;
41. Link the application and all libraries
● find_libaries(exe, needed_libraries_names)
○ step 3 : relocate all to-be-relocated symbols in the
application and libraries
liba1.soexe liba2.so libb1.so libb2.so ...
libraries_list
exe
sym_1
sym_n
...
if sym_1 is defined in lib:
sym_1 = lib.find(sym)
else:
lib = lib->next;
NOT FOUND
42. Link the application and all libraries
● find_libaries(exe, needed_libraries_names)
○ step 3 : relocate all to-be-relocated symbols in the
application and libraries
liba1.soexe liba2.so libb1.so libb2.so ...
libraries_list
exe
sym_1
sym_n
...
if sym_1 is defined in lib:
sym_1 = lib.find(sym)
else:
lib = lib->next;
NOT FOUND
43. Link the application and all libraries
● find_libaries(exe, needed_libraries_names)
○ step 3 : relocate all to-be-relocated symbols in the
application and libraries
liba1.soexe liba2.so libb1.so libb2.so ...
libraries_list
exe
sym_1
sym_n
...
if sym_1 is defined in lib:
sym_1 = lib.find(sym)
else:
lib = lib->next;
FOUND
ok
44. Link the application and all libraries
● find_libaries(exe, needed_libraries_names)
○ step 3 : relocate all to-be-relocated symbols in the
application and libraries
liba1.soexe liba2.so libb1.so libb2.so ...
libraries_list
exe
sym_1
sym_n
...
if sym_k is defined in lib:
sym_k = lib.find(sym)
else:
lib = lib->next;
ok
45. Link the application and all libraries
● find_libaries(exe, needed_libraries_names)
○ step 3 : relocate all to-be-relocated symbols in the
application and libraries
liba1.soexe liba2.so libb1.so libb2.so ...
libraries_list
exe
sym_1
sym_n
...
ok
ok
46. Link the application and all libraries
● find_libaries(exe, needed_libraries_names)
○ step 3 : relocate all to-be-relocated symbols in the
application and libraries
liba1.soexe liba2.so libb1.so libb2.so ...
libraries_list
liba1.so
sym_1
sym_n
...
if sym_1 is defined in lib:
sym_1 = lib.find(sym)
else:
lib = lib->next;
47. Link the application and all libraries
● find_libaries(exe, needed_libraries_names)
○ step 3 : relocate all to-be-relocated symbols in the
application and libraries
liba1.soexe liba2.so libb1.so libb2.so ...
libraries_list
...
sym_1
sym_n
...
if sym_1 is defined in lib:
sym_1 = lib.find(sym)
else:
lib = lib->next;
48. Link the application and all libraries
● find_libaries(exe, needed_libraries_names)
○ step 3 : relocate all to-be-relocated symbols in the
application and libraries
liba1.soexe liba2.so libb1.so libb2.so ...
libraries_list
...
sym_1
sym_n
...
if sym_1 is defined in lib:
sym_1 = lib.find(sym)
else:
lib = lib->next;
It is DONE until all libraries are linked
49. Jump to the application’s entry
/system/bin/linker
high
low
Memory space
executable
liba1.so
liba2.so
libb1.so
...
● jump to executable’s _start.
50. The executable is loaded successfully
● And start to execute
/system/bin/linker
high
low
Memory space
liba1.so
liba2.so
libb1.so
...
.text section
_start:
….
….
executable
53. Native hook mechanism
Modified codes are mainly in two parts
● Load hooking libraries in find_libraries()
○ Init native_hook_table
○ Look up native_hook_table
○ Load hooking_library
● Replace hooked_symbol with hooking_symbol in soinfo_do_lookup()
○ Look up native_hook_table
○ Replace every hooked_symbol in hooked_library with hooking_symbol in
hooking_library
54. Native hook file format
in /system/nh_file.txt
< hooked_lib_name:hooked_symbol:hooking_lib_name:hooking_symbol >
60. Replace hooked_symbol with hooking_symbol
liba1.soexe liba2.so libhooking.s
o
libraries_list
liba1.so:hi:libhooking.so:ha
...
Native Hook Table
exe
hi
hi ha
linker
0. relocate symbol
61. Replace hooked_symbol with hooking_symbol
liba1.soexe liba2.so libhooking.s
o
libraries_list
liba1.so:hi:libhooking.so:ha
...
Native Hook Table
exe
hi ha
linker
NOT FOUND
hi
62. Replace hooked_symbol with hooking_symbol
liba1.soexe liba2.so libhooking.s
o
libraries_list
liba1.so:hi:libhooking.so:ha
...
Native Hook Table
exe
hi ha
linker
FOUND
hi
63. Replace hooked_symbol with hooking_symbol
liba1.soexe liba2.so libhooking.s
o
libraries_list
liba1.so:hi:libhooking.so:ha
...
Native Hook Table
exe
hi ha
linker
FOUND
hi
1. look up native
hook table
liba1.so:hi is to be hooked
64. Replace hooked_symbol with hooking_symbol
liba1.soexe liba2.so libhooking.s
o
libraries_list
liba1.so:hi:libhooking.so:ha
...
Native Hook Table
exe
hi ha
linker
hi
1. look up native
hook table
2. find libhooking.so:ha
65. Replace hooked_symbol with hooking_symbol
liba1.soexe liba2.so libhooking.s
o
libraries_list
liba1.so:hi:libhooking.so:ha
...
Native Hook Table
exe
hi ha
linker
ha
3. relocate hooked_symbol “hi”
with the hooking_symbol “ha”
66. // in libnativehook.so
#include “native_hook.h”
void* find_lib_symbol(char* lib_name, char* symbol)
{
// Using dl_iterate_phdr() to get the symbol’s address
// in the loaded library whose name is lib_name.
…
return ptr_to_symbol;
}
Before/After hook SDK
67. How find_lib_symbol() works ?
With the following facts, we can get the hooked_symbol in hooked_library with
dl_iterate_phdr(callback, void* data)
● hooked_lib is loaded in the memory
● dl_iterate_phdr()iterates all loaded libraries in the process, and get each
library’s program header and base address.
● With library’s program header, we can get .dynamic segment, and therefore we get
.dynstr and .dynsym section
● With .dynsym and .dynstr, we can find the offset of hooked_symbol in hooked_lib.
● hooked_symbol_addr = base address + offset
68. // in libmine.so
#include “native_hook.h”
double my_sin(double x)
{
char hooked_lib[] = "/system/lib/libm.so";
char hooked_symbol[] = "sin";
double (*hooked_sin)(double) = find_lib_symbol(hooked_lib, hooked_symbol);
/*
before hook : you can do something before calling hooked_func
*/
double result = hooked_sin(x);
/*
after hook : you can do something after calling hooked_func
*/
result += 5566;
return result;
}
After hook example
69. After hook example
// in main.c
#include <math.h>
#include <stdio.h>
#define PI 3.14159265
int main(void)
{
double angle = 30.0;
double result = sin((angle * PI) /
180);
printf(“sin(%lf) = %lfn”, angle,
result);
return 0;
}
libm.so:sin:libmine.so:my_sin
...
Native Hook Table
$ ./main
sin(30.000000) = 5566.500000
75. ● Hook functions that affect the performance of applications in
Android
● Scenario
○ Functions in libm.so are not good enough for some special
purpose, we can hook the function with the optimized one.
Boosting apps performance
78. Security sandbox
● Use “before hook” to hook the open()in libc
● Examine the filename and other parameters in advance
○ If the to-be-written file is a critical file, we let the app open another file to write
without consciousness.
80. Security sandbox
f = open(“/data/critical.txt”, ‘w’);
...
modifying critical.txt ...
...
App
Sandbox
/data/critical.txt
should not be
modified.
81. Security sandbox
f = open(“/data/critical.txt”, ‘w’);
...
modifying critical.txt ...
...
App
Sandbox
f = open(“/data/another.txt”, ‘w’);
In the sandbox, app is deceived to write to
“/data/another.txt” instead of
“/data/critical.txt”.
82. Security sandbox
App
Sandbox
f = open(“/data/another.txt”, ‘w’);
f = open(“/data/another.txt”, ‘w’);
...
modifying another.txt ...
...
83. ● Provide more easy-to-use API for Native Hook in Android
○ Native Hook SDK
Future works
84. ● Completely integrate Native Hook into Android Dynamic
Framework
○ Provide hooking between Java method and native functions.
Future works
Integrated Hook Table
liba.so:funca:libb.so:funcb # hook native to native
classA:methoda:classB:methodb # hook java to java
classA:methoda:libb.so:funcb # hook java to native
libb.so:funcb:classA:methoda # hook native to java
...
85. Conclusion
● Native Hook mechanism is a strong and useful framework in
Android allowing developers to replace native functions at
runtime without modifying the existing functions.
● Native Hook is more powerful than Java method hook
mechanisms because it is implemented in Bionic Linker.
● With Before/After hook mechanism, you can do whatever you
want before/after any existing function.
● With Native Hook enabled, it suffers only little overhead to
load nh_file and hooking libraries.
89. void* find_lib_symbol(char* lib_name, char* symbol)
{
// Using dl_iterate_phdr() to get the symbol’s address
// in the loaded library whose name is lib_name.
static void* unordered_map<std::string, void*> cache = nullptr;
std::string lib_symbol = std::string(lib_name) + symbol;
if (cache) {
unordered_map<std::string, void*>::iterator it = cache.find(lib_symbol);
if (it != cache.end()) {
return it->second;
}
}
…
// find ptr_to_symbol
if (ptr_to_symbol) {
cache[lib_symbol] = ptr_to_symbol;
}
return ptr_to_symbol;
}
Before/After hook with cache in find_lib_symbol
90. Replace hooked_symbol with hooking_symbol
liba1.soexe liba2.so libhooking.s
o
libraries_list
liba1.so:hi:libhooking.so:ha
...
Native Hook Table
exe
hi ha
linker
FOUND
hi
1. look up native
hook table
liba1.so:hi is to be hooked
2. find libhooking.so:ha