elf hook c语言版本
从网上 低端码农大哥处
http://blog.csdn.net/l173864930/article/details/40507359
下载而来,
为c++版本,编译也过不去
只怪自己水平太菜
改成c语言版本,并且没有在java端的hook,只是自己hook自己
30|shell@astar-dvk3:/ # test_dlclose_destruction1
inject.c main.
target_pid = 1676.
[+] Injecting process: 1676
[+] Remote mmap address: 400b0cf9
[+] Calling mmap in target process.
[+] Target process returned from mmap, return value=404cc000, pc=0
map_base: 404cc000
[+] Get imports: dlopen: 40083f4d, dlsym: 40083e9d, dlclose: 40083e19, dlerror: 40083dc9
library path = /system/lib/libtest_hello.so
[+] Calling dlopen in target process.
[+] Target process returned from dlopen, return value=4019224c, pc=0
[+] Calling dlsym in target process.
[+] Target process returned from dlsym, return value=404d18e9, pc=0
hook_entry_addr = 0x404d18e9
[+] Calling hook_entry in target process.
g_com_fd = 12
in hook_entry2, param is I'm parameter!
global_strlen1 = 0x400c0ec1
global_strlen2 = 0x400c0ec1
local_strlen1 = 0x400c0ec1
local_strlen2 = 0x400c0ec1
strlen = 0x400c0ec1
hook before:
len0 is 10
len1 is 10
len2 is 10
len3 is 10
len4 is 10
len5 is 10
base = 404d0000.
info->handle = 4123c7d0.
info->elf_base = 404d0000.
info->ehdr = 404d0000.
[+] sym 0x404d04e8, symidx 58.
op 1.
[+] old_func is 0x400c0ec1, replace_func is 0x404d0e6d, new_func 0x404d0e6d.
op 2.
[+] old_func is 0x400c0ec1, replace_func is 0x404d0e6d, new_func 0x404d0e6d.
op 2.
[+] old_func is 0x400c0ec1, replace_func is 0x404d0e6d, new_func 0x404d0e6d.
op 2.
[+] old_func is 0x400c0ec1, replace_func is 0x404d0e6d, new_func 0x404d0e6d.
global_strlen1 = 0x404d0e6d
global_strlen2 = 0x404d0e6d
local_strlen1 = 0x400c0ec1
local_strlen2 = 0x400c0ec1
strlen = 0x400c0ec1
strlen was called 1111111111111111111111.
strlen was called 1111111111111111111111.
hook after:len0 is 40
len1 is 40
len2 is 10
len3 is 10
len4 is 10
len5 is 10
[+] Target process returned from hook_entry, return value=0, pc=0
Press enter to dlclose and detach
[+] Calling dlclose in target process.
[+] Target process returned from dlclose, return value=4019224c, pc=40034e18
shell@astar-dvk3:/ #
lib_hello.c ->生成自己hook自己的lib_hello.so
#if 0
#include <stdio.h>
#include <stdlib.h>
#include <asm/user.h>
#include <asm/ptrace.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <elf.h>
#include <android/log.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
#include <utils/Log.h>
//#include "AudioResamplerSinc.h"
#if defined(__i386__)
xxxxxxxxxxxxx
#define pt_regs user_regs_struct
#endif
#define ENABLE_DEBUG 1
#if ENABLE_DEBUG
#define LOG_TAG "INJECT"
//#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)
#define LOGD(fmt, args...) printf(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)
//dddd
#define DEBUG_PRINT(format,args...) \
LOGD(format, ##args)
#else
#define DEBUG_PRINT(format,args...)
#endif
#define CPSR_T_MASK ( 1u << 5 )
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
//#include <android/log.h>
#include <elf.h>
#include <fcntl.h>
#include <cutils/klog.h>
#define TAG "htfsk"
#define LOGE(x...) do { KLOG_ERROR("events", x); } while (0)
#define LOGI(x...) do { KLOG_INFO("events", x); } while (0)
#define LOGV(x...) do { KLOG_DEBUG("events", x); } while (0)
#if 0
int debug_msg(const char *format, ...)
{
char tmpbuf[4096];
unsigned int send_len;
va_list vArgs;
va_start(vArgs, format);
vsnprintf( (char *)&tmpbuf[0], sizeof(tmpbuf), (char const *)format, vArgs );
va_end(vArgs);
send_len = strlen(&tmpbuf[0]);
__android_log_write( ANDROID_LOG_DEBUG, TAG, tmpbuf );
return 0;
}
#endif
int hook_entry(char * a){
//debug_msg("Hook success, pid = %d\n", getpid());
//debug_msg("Hello %s\n", a);
unsigned char * teststr="12345";
__android_log_write( ANDROID_LOG_DEBUG, TAG, "hook_entry 123" );
system("echo mabid 12345 >/dev/ttyS0");
setenv("teststr", teststr, 1);
system("echo hahah$teststr >/dev/ttyS0");
return 19;
}
#endif
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
#include <elf.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <termios.h>
#include <sys/stat.h>
#include "lib_hello.h"
#define LOG_TAG "DEBUG"
#define LOGD(fmt, args...) my_printf(fmt, ##args)
#define LOGI(fmt, args...) my_printf(fmt, ##args)
#define LOGE(fmt, args...) my_printf(fmt, ##args)
#define Ser_Printf my_printf
#define macdbg_prser my_printf
//#define my_printf printf
static int g_com_fd = -1;
#if 1
int my_printf( const char *fmt, ... )
{
char *tmp_buf;
int g_printf_switch = 1;
unsigned char buffer[4096];
va_list vArgs;
if( g_printf_switch == 0x00 ){
return 1;
}
va_start(vArgs, fmt);
vsnprintf((char *)buffer, sizeof(buffer), (char const *)fmt, vArgs);
va_end(vArgs);
if( g_com_fd != -1 ){
write(g_com_fd, (unsigned char *)buffer, strlen((unsigned char *)buffer) );
}
//Ser_WrStr(( unsigned char *) buffer);
//setenv( "tmp_buf", buffer, 1 );
//system( "echo $tmp_buf > /dev/ttyS0" );
return 3;
}
#endif
int macdbg_dmphex(const char* buff, int len)
{
int retval = 0;
int x, y, tot, lineoff;
const char* curr;
//Ser_Printf("buff %x.\r\n", buff );
Ser_Printf("\r\n" );
lineoff = 0;
curr = buff;
tot = 0;
for( x = 0; x+16 < len; ){
Ser_Printf("%x\t", lineoff);
for( y = 0; y < 16; y++ ){
macdbg_prser("%02x ", (unsigned char)*(curr + y));
}
macdbg_prser(" ");
for( y = 0; y < 16; y++ ){
char c;
c = *(curr + y);
if( c > 31 && c < 127 ){
macdbg_prser("%c", c);
}else{
macdbg_prser("%c", '.');
}
tot++;
}
curr += 16;
x += 16;
lineoff+=16;
macdbg_prser("\r\n");
}
//do last line
//Ser_Printf("tot %d.\r\n", tot );
//Ser_Printf("len %d.\r\n", len );
if( tot < len ){
curr = (buff + tot);
macdbg_prser("%x\t", lineoff);
for( y = 0; y < (len - tot); y++ ){
macdbg_prser("%02x ", (unsigned char)*(curr + y));
}
//padding with spaces
//Ser_Printf("(len - tot) %d.\r\n", (len - tot) );
if( (len - tot) < 16 ){
for( y = 0; y < (32 - ((len - tot)*2)); y++ ){
macdbg_prser(" ");
}
}
for( y = 0; y < 16-(len - tot); y++ ){
macdbg_prser(" ");
}
macdbg_prser(" ");
//Ser_Printf("(len - tot) %d.\r\n", (len - tot) );
for( y = 0; y < (len - tot); y++ ){
char c;
c = *(curr + y);
if( c >31 && c < 127 ){
macdbg_prser("%c", c);
}else{
macdbg_prser("%c", '.');
//macdbg_prser("%c", c);
}
}
}
macdbg_prser("\r\n");
return retval;
}
EGLBoolean (*old_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surf) = -1;
EGLBoolean new_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
{
LOGD("New eglSwapBuffers\n");
if (old_eglSwapBuffers == -1)
LOGD("error\n");
return old_eglSwapBuffers(dpy, surface);
}
void* get_module_base(pid_t pid, const char* module_name)
{
FILE *fp;
long addr = 0;
char *pch;
char filename[32];
char line[1024];
if (pid < 0) {
/* self process */
snprintf(filename, sizeof(filename), "/proc/self/maps", pid);
} else {
snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
}
fp = fopen(filename, "r");
if (fp != NULL) {
while (fgets(line, sizeof(line), fp)) {
if (strstr(line, module_name)) {
pch = strtok( line, "-" );
addr = strtoul( pch, NULL, 16 );
if (addr == 0x8000)
addr = 0;
break;
}
}
fclose(fp) ;
}
return (void *)addr;
}
//shell@astar-dvk3:/data/app-lib/com.example.asus.myapplication-2 #
//#define LIBSF_PATH "/data/app-lib/com.example.fengzi.xdntest-1/libuart.so"
#define LIBSF_PATH1 "/data/app-lib/com.example.asus.myapplication-2/libhello-jni.so"
#define LIBSF_PATH "/system/lib/libtest_hello.so"
#if 0
static int lib_hook_hello()
{
//old_funpoint = NULL;
//LOGD("Orig eglSwapBuffers = %p\n", old_funpoint);
void * base_addr = hello_get_module_base(getpid(), HELLO_LIBSF_PATH);
LOGD("asmhello address = %p\n", base_addr);
//macdbg_dmphex(base_addr, 0x1000);
int fd;
fd = open(LIBSF_PATH, O_RDONLY);
if( -1 == fd ){
LOGD("error\n");
return -1;
}
Elf32_Ehdr ehdr;
read(fd, &ehdr, sizeof(Elf32_Ehdr));
//macdbg_dmphex(&ehdr, sizeof(Elf32_Ehdr));
//ÒÔÏ´úÂëÖ÷Òª·ÖÎö¶ÎÍ·Êý¾Ý½á¹¹
unsigned long shdr_addr = ehdr.e_shoff;
int shnum = ehdr.e_shnum;
//Number of section headers
//¶ÎÍ·ÏîÄ¿µÄ¸öÊý
int shent_size = ehdr.e_shentsize;
//Section header entry size
//ÿһ¸ö¶ÎÍ·ÏîÄ¿µÄ´óС
unsigned long stridx = ehdr.e_shstrndx;
Elf32_Shdr shdr;
//my_printf( "ehdr.e_phoff = %x\n", ehdr.e_phoff );
//³ÌÐòÍ·Æ«ÒƵØÖ·,Ö±½Ó¸úËæELF Header 0x34
//ELF HeaderÕ¼ÓÃ52×Ö½Ú,ÃèÊö³ÌÐòÍ·,¶ÎÍ·,Ìåϵ½á¹¹µÈÐÅÏ¢
//my_printf( "ehdr.e_phnum = %x\n", ehdr.e_phnum );
//³ÌÐòÍ·½á¹¹ÌåµÄ¸öÊý
//my_printf( "ehdr.e_phentsize = %x\n", ehdr.e_phentsize );
//³ÌÐòÍ·½á¹¹Ìåÿһ¸öµÄ´óС
//my_printf( "shdr_addr = %x\n", shdr_addr );
//¶ÎÍ·µÄÆ«ÒƵØÖ·
//my_printf( "shnum = %x\n", shnum );
//¶ÎÍ·½á¹¹ÌåµÄ¸öÊý
//my_printf( "shent_size = %x\n", shent_size );
//ÿһ¸ö¶ÎÍ·½á¹¹ÌåµÄ´óС
//my_printf( "stridx = %x\n", stridx );
//Section header string table index: 23
//ÔÚËùÓжÎÍ·½á¹¹ÌåÄÚ,ÓÐÒ»¸ö½Ð"´®±í"µÄ½á¹¹Ìå
//´Ë½á¹¹ÌåÔÚËùÓжÎÍ·½á¹¹ÌåµÄ¸öÊýÖеÄË÷ÒýÖµ Ö¸Ïò×îºóÒ»¸ö¶ÎÍ·½á¹¹Ìå
//´Ëµ÷ÊÔÐÅÏ¢¿ÉÒÔ¿´³ö-->shnum = 18 shent_size = 28 stridx = 17
//my_printf( "shdr_addr = %x\n", shdr_addr );
//my_printf( "shdr_addr + stridx * shent_size = %x\n", shdr_addr + stridx * shent_size );
lseek(fd, shdr_addr + stridx * shent_size, SEEK_SET);
//ÎļþÖ¸Õ붨λµ½"´®±í"¶ÎÍ·½á¹¹Ìå
read(fd, &shdr, shent_size);
//¶ÁÈ¡"´®±í"¶ÎÍ·½á¹¹Ìå
char *string_table = (char *)malloc(shdr.sh_size);
//my_printf( "string_table = %x\n", string_table );
//my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
//section size,´®±íµÄ´óС ÃèÊöÁË´®±íÕ¼ÓõĴ洢¿Õ¼äµÄ´óС
//my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
//file offset ´®±íÔÚÕû¸öelfÎļþÖеÄÆ«ÒÆλÖÃ
lseek(fd, shdr.sh_offset, SEEK_SET);
read(fd, string_table, shdr.sh_size);
lseek(fd, shdr_addr, SEEK_SET);
//Ö¸Ïò¶ÎÍ·½á¹¹Ìå´æ´¢µÄÊ×µØÖ·
//elfÄÚ´æ½á¹¹ÃèÊöÈçÏÂ:
//-->¿ªÊ¼
//ELF Header 0x34
//³ÌÐòÍ·½á¹¹Ìå´æ´¢Î»ÖÃ:
//PHDR->µÚÒ»¸ö³ÌÐòÍ·½á¹¹Ìå
//ÃèÊöÁË×ܹ²ÓжàÉÙ¸ö³ÌÐòÍ·½á¹¹Ìå
//INTERP->µÚ¶þ¸ö³ÌÐòÍ·½á¹¹Ìå
//ÃèÊöÁËlinkerÔÚϵͳÖеÄλÖÃ
//Õû¸ö´®±í
//¶ÎÍ·½á¹¹Ìå´æ´¢Î»ÖÃ:
//µÚÒ»¸ö¶ÎÍ·±íÈë¿ÚΪ¿Õ
//->Section header table entry unused
//.interp
//.dynsym
//.dynstr
//.hash
//.rel.dyn
//.rel.plt
//.plt
//.text
//->º¯ÊýÖ´ÐдúÂë
//.note.android.ident
//.ARM.exidx
//->²¿·Öº¯ÊýµØÖ·¿ÉÒÔÔÚ´ËÓù«Ê½»ñÈ¡
//.ARM.extab
//.rodata
//->È«¾Öconst±äÁ¿ ×Ö·û´®µÈ printf("test string");
//->³ÌÐò±¾ÉíµÄһЩ±í ¿´Çé¿ö
//.preinit_array
//.init_array
//.fini_array
//.dynamic
//.got
//->¶¯Ì¬¿âÏà¹ØµÄº¯ÊýµØÖ·
//.bss
//->δ³õʼ»¯µÄÈ«¾Ö±äÁ¿
//.comment
//.note.gnu.gold-version
//.ARM.attributes
//.gnu_debuglink
//.shstrtab
//->´®±íÃèÊö
//-->½áÊø
int i,j;
uint32_t out_addr = 0;
uint32_t out_size = 0;
uint32_t got_item = 0;
int32_t got_found = 0;
int32_t get_off = 0;
//my_printf( "shnum = %x\n", shnum );
//¶ÎÍ·½á¹¹ÌåµÄ¸öÊý 0x18
//my_printf( "shent_size = %x\n", shent_size );
//ÿһ¸ö¶ÎÍ·½á¹¹ÌåµÄ´óС 0x28
for( j = 0; j < shnum; j++ ){
read(fd, &shdr, shent_size);
//macdbg_dmphex(&shdr, sizeof(Elf32_Shdr));
//my_printf( "shdr.sh_type = %x\n", shdr.sh_type );
int name_idx = shdr.sh_name;
if( shdr.sh_type == SHT_PROGBITS ){
//my_printf( "get Section header entry %s\n", &string_table[name_idx] );
//my_printf( "shdr.sh_addr = %x\n", shdr.sh_addr );
//my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
//my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
//my_printf( "shdr.sh_entsize = %x\n", shdr.sh_entsize );
if( strcmp(&(string_table[name_idx]), ".got.plt") == 0 ||
strcmp(&(string_table[name_idx]), ".got") == 0 ){
out_addr = base_addr + shdr.sh_addr;
out_size = shdr.sh_size;
LOGD("out_addr = %lx, out_size = %lx\n", out_addr, out_size);
//my_printf( "old_funpoint = %x\n", old_funpoint );
//my_printf( "new_funpoint = %x\n", new_funpoint );
my_printf( "base_addr = %x\n", base_addr );
my_printf( "main = %x\n", main );
//macdbg_dmphex( base_addr, 0x40000);
for (i = 0; i < out_size; i += 4) {
got_item = *(uint32_t *)(out_addr + i);
my_printf( "got_item = %x\n", got_item );
if (got_item == old_funpoint) {
LOGD("Found eglSwapBuffers in got\n");
got_found = 1;
uint32_t page_size = getpagesize();
uint32_t entry_page_start = (out_addr + i) & (~(page_size - 1));
mprotect((uint32_t *)entry_page_start, page_size, PROT_READ | PROT_WRITE);
*(uint32_t *)(out_addr + i) = new_funpoint;
my_printf( "shnum = %x\n", shnum );
break;
} else if (got_item == new_funpoint) {
LOGD("Already hooked\n");
break;
}
}
if (got_found) {
//break;
}
}else if( strcmp(&(string_table[name_idx]), ".rodata") == 0 ) {
//const,¹Ì¶¨×Ö·û´®µÈÔڴ˶ÎÕÒ
my_printf("get .rodata\n");
macdbg_dmphex(&shdr, sizeof(Elf32_Shdr));
}
}else if (shdr.sh_type == SHT_NULL) {
//Section header table entry unused
//µÚÒ»¸ö¶ÎÍ·±íÈë¿ÚΪ¿Õ
my_printf("get null\n");
}else if (shdr.sh_type == PT_ARM_EXIDX) {
//Section header table entry unused
//µÚÒ»¸ö¶ÎÍ·±íÈë¿ÚΪ¿Õ
my_printf( "macdbg_dmphex = %x\n", macdbg_dmphex );
my_printf( "old_funpoint = %x\n", old_funpoint );
my_printf( "new_funpoint = %x\n", new_funpoint );
my_printf( "hello_get_module_base = %x\n", hello_get_module_base );
my_printf( "hook_hello = %x\n", hook_hello );
my_printf( "main = %x\n", main );
my_printf( "my_tgkill = %x\n", my_tgkill );
//my_printf( "get .ARM.exidx\n" );
//my_printf( "string_table[name_idx] = %s\n", &string_table[name_idx] );
//my_printf( "shdr.sh_addr = %x\n", shdr.sh_addr );
//my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
//my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
//my_printf( "shdr.sh_entsize = %x\n", shdr.sh_entsize );
out_addr = base_addr + shdr.sh_addr;
out_size = shdr.sh_size;
my_printf("out_addr = %lx, out_size = %lx\n", out_addr, out_size);
for( i = 0; i < out_size; i += 8 ){
get_off = *(int32_t *)(out_addr+i);
got_item = *(uint32_t *)(out_addr + i + 4);
//my_printf( "get_off = %x\n", get_off );
//my_printf( "get_off1 = %x\n", shdr.sh_addr - (~get_off +1)&0xffff )+i;
my_printf( "func point = %x\n", shdr.sh_addr + i - ((~get_off +1)&0xffff) + base_addr );
//shdr.sh_addr + i ÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÆ«ÒÆλÖõÄÐéÄâµØÖ·
//*(shdr.sh_addr + i)ÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÆ«ÒÆλÖÃ
//(Ïà¶ÔÓÚÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÐéÄâµØÖ·) Ϊ¸ºÊý
//base_addr ¸Ã½ø³ÌÄÚºËÄÚ´æÓ³ÉäµÄ»ùµØÖ·
//my_printf( "got_item = %x\n\n", got_item );
//my_printf( "got_item = %d\n", got_item );
}
}else{
//int name_idx = shdr.sh_name;
//section name (.shstrtab index)
//my_printf( "name_idx = %x\n", name_idx );
my_printf( "Section header entry %s\n", &string_table[name_idx] );
my_printf( "shdr.sh_addr = %x\n", shdr.sh_addr );
my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
my_printf( "shdr.sh_entsize = %x\n", shdr.sh_entsize );
}
}
free(string_table);
//ÒÔÏ´úÂëÖ÷Òª·ÖÎö³ÌÐòÍ·Êý¾Ý½á¹¹
shdr_addr = ehdr.e_phoff;
//Ê׸ö³ÌÐòÍ·ÏîÄ¿µÄÆ«ÒÆ
shnum = ehdr.e_phnum;
//³ÌÐòÍ·ÏîÄ¿µÄ¸öÊý
shent_size = ehdr.e_phentsize;
//ÿһ¸ö³ÌÐòÍ·ÏîÄ¿µÄ´óС
//stridx = ehdr.e_shstrndx;
Elf32_Phdr program_shdr;
my_printf( "ehdr.e_phoff = %x\n", ehdr.e_phoff );
//³ÌÐòÍ·Æ«ÒƵØÖ·,Ö±½Ó¸úËæELF Header 0x34
//ELF HeaderÕ¼ÓÃ52×Ö½Ú,ÃèÊö³ÌÐòÍ·,¶ÎÍ·,Ìåϵ½á¹¹µÈÐÅÏ¢
my_printf( "ehdr.e_phnum = %x\n", ehdr.e_phnum );
//³ÌÐòÍ·½á¹¹ÌåµÄ¸öÊý
my_printf( "ehdr.e_phentsize = %x\n", ehdr.e_phentsize );
shnum = ehdr.e_phnum;
lseek(fd, ehdr.e_phoff, SEEK_SET);
char *p_type_tmp;
for( j = 0; j < shnum; j++ ){
read(fd, &program_shdr, sizeof(Elf32_Phdr));
macdbg_dmphex(&program_shdr, sizeof(Elf32_Phdr));
p_type_tmp = get_p_type(program_shdr.p_type);
my_printf( "program_shdr.p_type = %s\n", p_type_tmp );
my_printf( "program_shdr.p_offset = %x\n", program_shdr.p_offset );
my_printf( "program_shdr.p_vaddr = %x\n", program_shdr.p_vaddr );
my_printf( "program_shdr.p_paddr = %x\n", program_shdr.p_paddr );
my_printf( "program_shdr.p_filesz = %x\n", program_shdr.p_filesz );
my_printf( "program_shdr.p_memsz = %x\n", program_shdr.p_memsz );
my_printf( "program_shdr.p_flags = %x\n", program_shdr.p_flags );
my_printf( "program_shdr.p_align = %x\n", program_shdr.p_align );
if( strcmp(p_type_tmp, PT_INTERP_STR) == 0 ){
//³ÌÐò½âÊÍÆ÷ ¼ÓÔØÆ÷
//ÃèÊöÁ˴˳ÌÐòµÄ¼ÓÔØÆ÷ÔÚϵͳÖеÄλÖÃ
long temp_file_position;
temp_file_position = lseek(fd, 0, SEEK_CUR);
char *linker = (char *)malloc(program_shdr.p_memsz);
lseek(fd, program_shdr.p_offset, SEEK_SET);
read(fd, linker, program_shdr.p_memsz);
my_printf( "program loader = %s\n", linker );
free(linker);
lseek(fd, temp_file_position, SEEK_SET);
}else if( strcmp(p_type_tmp, PT_PHDR_STR) == 0 ){
//ÃèÊöÁ˴˳ÌÐòµÄ³ÌÐòÍ·µÄÕûÌå´óС
my_printf( "get program head = %x\n", program_shdr.p_memsz );
}
}
//lseek(fd, shdr_addr, SEEK_SET);
//Ö¸Ïò¶ÎÍ·½á¹¹Ìå´æ´¢µÄÊ×µØÖ·
close(fd);
return 0;
}
#endif
//´ÓÎļþ´ò¿ªELF
struct ElfHandle *openElfByFile(const char *path);
//ÊÍ·Å×ÊÔ´
void closeElfByFile( ElfHandle *handle);
//´Ó¸ø¶¨µÄsoÖлñÈ¡»ùÖ·,Èç¹ûsonameΪNULL,Ôò±íʾµ±Ç°½ø³Ì×ÔÉí
ElfHandle *openElfBySoname(const char *soname);
//ÊÍ·Å×ÊÔ´
void closeElfBySoname(struct ElfHandle *handle);
//elf¹Ø¼üÐÅÏ¢
struct ElfInfo{
const ElfHandle *handle;
uint8_t *elf_base;
Elf32_Ehdr *ehdr;
Elf32_Phdr *phdr;
Elf32_Shdr *shdr;
Elf32_Dyn *dyn;
Elf32_Word dynsz;
Elf32_Sym *sym;
Elf32_Word symsz;
Elf32_Rel *relplt;
Elf32_Word relpltsz;
Elf32_Rel *reldyn;
Elf32_Word reldynsz;
uint32_t nbucket;
uint32_t nchain;
uint32_t *bucket;
uint32_t *chain;
const char *shstr;
const char *symstr;
};
//·ûºÅhashº¯Êý
unsigned elf_hash(const char *name);
//´ÓsectionÊÓͼ»ñÈ¡info
void getElfInfoBySectionView(struct ElfInfo *info, const ElfHandle *handle);
//´ÓsegmentÊÓͼ»ñÈ¡info
void getElfInfoBySegmentView(struct ElfInfo *info, const ElfHandle *handle);
//¸ù¾Ý·ûºÅÃûÑ°ÕÒSym
void findSymByName(struct ElfInfo *info, const char *symbol, Elf32_Sym **sym, int *symidx);
//´òÓ¡sectionÐÅÏ¢
void printSections(struct ElfInfo *info);
//´òÓ¡segmentÐÅÏ¢
void printSegments(struct ElfInfo *info);
//´òÓ¡dynamicÐÅÏ¢
void printfDynamics(struct ElfInfo *info);
//´òÓ¡ËùÓзûºÅÐÅÏ¢
void printfSymbols(struct ElfInfo *info);
//´òÓ¡Öض¨Î»ÐÅÏ¢
void printfRelInfo(struct ElfInfo *info);
void printfRelInfo(struct ElfInfo *info)
{
int i,j;
Elf32_Rel* rels[] = {info->reldyn, info->relplt};
Elf32_Word resszs[] = {info->reldynsz, info->relpltsz};
Elf32_Sym *sym = info->sym;
LOGI("rel section info:\n");
for( i=0; i<sizeof(rels)/sizeof(rels[0]); i++){
Elf32_Rel *rel = rels[i];
Elf32_Word relsz = resszs[i];
for(j=0; j<relsz; j++){
const char *name = sym[ELF32_R_SYM(rel[j].r_info)].st_name + info->symstr;
LOGI("[%.2d-%.4d] 0x%-.8x 0x%-.8x %-10s\n", i, j, rel[j].r_offset, rel[j].r_info, name);
}
}
}
struct ElfHandle *openElfByFile(const char *path) {
void *base = NULL;
ElfHandle *handle = NULL;
//´Ë´¦Ò»¶¨²»ÄÜÊÇstruct ElfHandle1 *handle = NULL;
//·ñÔò»á±¨dereferencing pointer to incomplete type
int fd = open(path, O_RDWR);
if (fd < 0) {
LOGE("[-] open %s fails.\n", path);
exit(-1);
}
struct stat fs;
fstat(fd, &fs);
base = mmap(NULL, fs.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (base == MAP_FAILED) {
LOGE("[-] mmap fails.\n");
exit(-1);
}
close(fd);
handle = ( ElfHandle *) malloc(sizeof( ElfHandle));
handle->base = base;
handle->space_size = fs.st_size;
handle->fromfile = 1;
return handle;
}
void closeElfByFile(ElfHandle *handle) {
unsigned char * temp;
if (handle) {
temp = (unsigned char * )(handle->base);
if ( temp && handle->space_size > 0) {
msync(handle->base, handle->space_size, MS_SYNC);
munmap(handle->base, handle->space_size);
free(handle);
}
}
}
//²éÕÒsonameµÄ»ùÖ·,Èç¹ûΪNULL,ÔòΪµ±Ç°½ø³Ì»ùÖ·
static void *findLibBase(const char *soname) {
FILE *fd = fopen("/proc/self/maps", "r");
char line[256];
void *base = 0;
while (fgets(line, sizeof(line), fd) != NULL) {
if (soname == NULL || strstr(line, soname)) {
line[8] = '\0';
base = (void *) strtoul(line, NULL, 16);
break;
}
}
fclose(fd);
return base;
}
//´Ó¸ø¶¨µÄsoÖлñÈ¡»ùÖ·
ElfHandle *openElfBySoname(const char *soname)
{
void *base = findLibBase(soname);
if(!base){
LOGE("[-] could find %s. \n", soname);
exit(-1);
}
ElfHandle *handle = (ElfHandle *) malloc(sizeof(ElfHandle));
handle->base = base;
LOGE( "base = %x.\n", base );
handle->space_size = -1;
handle->fromfile = 0;
return handle;
}
//ÊÍ·Å×ÊÔ´
void closeElfBySoname(struct ElfHandle *handle){
//only free the base
free(handle);
}
//#define LIBSF_PATH "/system/lib/libsurfaceflinger.so"
//#define LIBSF_PATH "/system/lib/libtest_hello.so"
#ifndef PT_ARM_EXIDX
#define PT_ARM_EXIDX 0x70000001
#endif
//comm_spi_data_send_and_rev
//extern comm_spi_data_send_and_rev;
int hook_eglSwapBuffers()
{
old_eglSwapBuffers = eglSwapBuffers;
//old_eglSwapBuffers = comm_spi_data_send_and_rev;
//LOGD("Orig eglSwapBuffers = %p\n", old_eglSwapBuffers);
void * base_addr = get_module_base(getpid(), LIBSF_PATH);
// LOGD("libsurfaceflinger.so address = %p\n", base_addr);
int fd;
fd = open(LIBSF_PATH, O_RDONLY);
if (-1 == fd) {
LOGD("error\n");
return -1;
}
Elf32_Ehdr ehdr;
read(fd, &ehdr, sizeof(Elf32_Ehdr));
//macdbg_dmphex(&ehdr, sizeof(Elf32_Ehdr));
unsigned long shdr_addr = ehdr.e_shoff;
int shnum = ehdr.e_shnum;
int shent_size = ehdr.e_shentsize;
unsigned long stridx = ehdr.e_shstrndx;
Elf32_Shdr shdr;
//my_printf( "shdr_addr = %x\n", shdr_addr );
//my_printf( "stridx = %x\n", stridx );
//my_printf( "shent_size = %x\n", shent_size );
lseek(fd, shdr_addr + stridx * shent_size, SEEK_SET);
read(fd, &shdr, shent_size);
char * string_table = (char *)malloc(shdr.sh_size);
//my_printf( "string_table = %x\n", string_table );
//my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
//my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
lseek(fd, shdr.sh_offset, SEEK_SET);
read(fd, string_table, shdr.sh_size);
lseek(fd, shdr_addr, SEEK_SET);
int i,j,k,l;
uint32_t out_addr = 0;
uint32_t out_size = 0;
uint32_t got_item = 0, get_off=0;
int32_t got_found = 0;
//my_printf( "shnum = %x\n", shnum );
for (k = 0; k < shnum; k++) {
read(fd, &shdr, shent_size);
int name_idx = shdr.sh_name;
//my_printf( "shdr.sh_type = %x\n", shdr.sh_type );
if (shdr.sh_type == SHT_PROGBITS) {
//my_printf( "name_idx = %x\n", name_idx );
//my_printf( "string_table[name_idx] = %s\n", &string_table[name_idx] );
if (strcmp(&(string_table[name_idx]), ".got.plt") == 0 ||
strcmp(&(string_table[name_idx]), ".got") == 0) {
out_addr = base_addr + shdr.sh_addr;
out_size = shdr.sh_size;
//LOGD("out_addr = %lx, out_size = %lx\n", out_addr, out_size);
//my_printf("base_addr = %lx, shdr.sh_addr = %lx\n", base_addr, shdr.sh_addr);
for( j = 0; j < out_size; j += 4 ){
get_off = *(int32_t *)(out_addr+j);
//my_printf( "get_off.0 = %x\n", get_off );
//if(j>0x100)
my_printf( "get_off.1 = %x\n", get_off - (uint32_t)base_addr );
}
#if 0
for (i = 0; i < out_size; i += 4) {
got_item = *(uint32_t *)(out_addr + i);
if (got_item == old_eglSwapBuffers) {
LOGD("Found eglSwapBuffers in got\n");
got_found = 1;
uint32_t page_size = getpagesize();
uint32_t entry_page_start = (out_addr + i) & (~(page_size - 1));
mprotect((uint32_t *)entry_page_start, page_size, PROT_READ | PROT_WRITE);
*(uint32_t *)(out_addr + i) = new_eglSwapBuffers;
break;
} else if (got_item == new_eglSwapBuffers) {
LOGD("Already hooked\n");
break;
}
}
if (got_found) {
//break;
}
#endif
}
}else if (shdr.sh_type == PT_ARM_EXIDX) {
//Section header table entry unused
//µÚÒ»¸ö¶ÎÍ·±íÈë¿ÚΪ¿Õ
//my_printf( "macdbg_dmphex = %x\n", macdbg_dmphex );
//my_printf( "old_funpoint = %x\n", old_funpoint );
//my_printf( "new_funpoint = %x\n", new_funpoint );
//my_printf( "hello_get_module_base = %x\n", hello_get_module_base );
//my_printf( "hook_hello = %x\n", hook_hello );
//my_printf( "main = %x\n", main );
//my_printf( "my_tgkill = %x\n", my_tgkill );
//my_printf( "get .ARM.exidx\n" );
//my_printf( "string_table[name_idx] = %s\n", &string_table[name_idx] );
//my_printf( "shdr.sh_addr = %x\n", shdr.sh_addr );
//my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
//my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
//my_printf( "shdr.sh_entsize = %x\n", shdr.sh_entsize );
out_addr = base_addr + shdr.sh_addr;
out_size = shdr.sh_size;
// my_printf("out_addry = %lx, out_size = %lx\n", out_addr, out_size);
// my_printf("shdr.sh_addry = %lx, base_addr = %lx\n", shdr.sh_addr, base_addr);
for( i = 0; i < out_size; i += 8 ){
get_off = *(int32_t *)(out_addr+i);
got_item = *(uint32_t *)(out_addr + i + 4);
uint32_t fun_offset,fun_addr;
//my_printf( "get_off = %x\n", get_off );
//my_printf( "got_item = %x\n", got_item );
//my_printf( "get_off1 = %x\n", shdr.sh_addr - (~get_off +1)&0xffff )+i;
//my_printf( "func point.0 = %x\n", shdr.sh_addr + i - ((~get_off +1)&0xfffffff) + base_addr );
//my_printf( "func point.1 = %x\n", shdr.sh_addr + i - ((~get_off +1)&0xfffffff) + base_addr - base_addr );
fun_offset = shdr.sh_addr + i - ((~get_off +1)&0xfffffff);
fun_addr = fun_offset + base_addr;
my_printf( "fun_offset = %x\n", fun_offset );
my_printf( "fun_addr = %x\n", fun_addr );
if( fun_offset == 0xea4 ){
macdbg_dmphex(fun_addr, 100);
}
//shdr.sh_addr + i ÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÆ«ÒÆλÖõÄÐéÄâµØÖ·
//*(shdr.sh_addr + i)ÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÆ«ÒÆλÖÃ
//(Ïà¶ÔÓÚÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÐéÄâµØÖ·) Ϊ¸ºÊý
//base_addr ¸Ã½ø³ÌÄÚºËÄÚ´æÓ³ÉäµÄ»ùµØÖ·
//my_printf( "got_item = %x\n\n", got_item );
//my_printf( "got_item = %d\n", got_item );
}
}else{
//my_printf( "name_idx1 = %x\n", name_idx );
// my_printf( "string_table[name_idx]1 = %s\n", &string_table[name_idx] );
}
}
free(string_table);
close(fd);
return 0;
}
#define DEVICE_COM "/dev/ttyS0"
void init_ttyS(int fd)
{
struct termios options;
memset( &options, 0, sizeof(options) );
cfsetispeed( &options, B115200 );
cfsetospeed( &options, B115200 );
options.c_cflag |=(CS8|CLOCAL|CREAD);
options.c_iflag &=IGNPAR;
options.c_lflag &= ~ICANON;
//raw Added by czj²»µÈ»Ø³µÊäÈë
options.c_lflag &= ~ECHO;
//raw Added by czj²»»ØÏÔ
tcflush(fd,TCIFLUSH);
tcsetattr(fd, TCSANOW, &options);
//fcntl(fd, F_SETFL, 0);
}
int com_appstart(void)
{
int fd;
//fd = open( DEVICE_COM, O_RDWR|O_NOCTTY|O_NONBLOCK );
fd = open( DEVICE_COM, O_RDWR |O_NOCTTY|O_NONBLOCK);
if( fd == -1 ){
perror("open DEVICE_COM");
}else{
//init_ttyS( fd );
}
//fcntl(fd,F_SETFL,0);
return fd;
}
#define SAFE_SET_VALUE(t, v) if(t) *(t) = (v)
static inline Elf32_Shdr *findSectionByName(struct ElfInfo *info, const char *sname){
Elf32_Shdr *target = NULL;
int i;
Elf32_Shdr *shdr = info->shdr;
for( i=0; i<info->ehdr->e_shnum; i++){
const char *name = (const char *)(shdr[i].sh_name + info->shstr);
if(!strncmp(name, sname, strlen(sname))){
target = (Elf32_Shdr *)(shdr + i);
break;
}
}
return target;
}
static inline void getSectionInfo(struct ElfInfo *info, const char *name, Elf32_Word *pSize, Elf32_Shdr **ppShdr, void **data){
Elf32_Shdr *_shdr = findSectionByName(info, name);
if(_shdr){
SAFE_SET_VALUE(pSize, _shdr->sh_size / _shdr->sh_entsize);
//SAFE_SET_VALUE(data, reinterpret_cast<T>(info.elf_base + _shdr->sh_offset));
SAFE_SET_VALUE(data, (info->elf_base + _shdr->sh_offset) );
//if(data) *(data) = (123);
}else{
LOGE("[-] Could not found section %s\n", name);
exit(-1);
}
SAFE_SET_VALUE(ppShdr, _shdr);
}
static inline Elf32_Phdr *findSegmentByType(struct ElfInfo *info, const Elf32_Word type){
Elf32_Phdr *target = NULL;
Elf32_Phdr *phdr = info->phdr;
int i;
for( i=0; i<info->ehdr->e_phnum; i++){
if(phdr[i].p_type == type){
target = phdr + i;
break;
}
}
return target;
}
static void getSegmentInfo( struct ElfInfo *info, const Elf32_Word type, Elf32_Phdr **ppPhdr,
Elf32_Word *pSize, Elf32_Dyn **data){
Elf32_Phdr *_phdr = findSegmentByType(info, type);
if(_phdr){
if(info->handle->fromfile){ //Îļþ¶ÁÈ¡
//SAFE_SET_VALUE(data, reinterpret_cast<T>(info.elf_base + _phdr->p_offset));
SAFE_SET_VALUE(data, (info->elf_base + _phdr->p_offset));
SAFE_SET_VALUE(pSize, _phdr->p_filesz);
}else{ //´ÓÄÚ´æ¶ÁÈ¡
//SAFE_SET_VALUE(data, reinterpret_cast<T>(info.elf_base + _phdr->p_vaddr));
SAFE_SET_VALUE(data, (info->elf_base + _phdr->p_vaddr) );
SAFE_SET_VALUE(pSize, _phdr->p_memsz);
}
}else{
LOGE("[-] Could not found segment type is %d\n", type);
exit(-1);
}
SAFE_SET_VALUE(ppPhdr, _phdr);
}
void getElfInfoBySegmentView(struct ElfInfo *info, const ElfHandle *handle){
int i=0;
info->handle = handle;
info->elf_base = (uint8_t *) handle->base;
LOGE( "info->handle = %x.\n", info->handle );
LOGE( "info->elf_base = %x.\n", info->elf_base );
//info->ehdr = reinterpret_cast<Elf32_Ehdr *>(info.elf_base);
info->ehdr = (Elf32_Ehdr *)info->elf_base;
LOGE( "info->ehdr = %x.\n", info->ehdr );
// may be wrong
info->shdr = (Elf32_Shdr *)(info->elf_base + info->ehdr->e_shoff);
info->phdr = (Elf32_Phdr *)(info->elf_base + info->ehdr->e_phoff);
//info.shdr = reinterpret_cast<Elf32_Shdr *>(info.elf_base + info.ehdr->e_shoff);
//info.phdr = reinterpret_cast<Elf32_Phdr *>(info.elf_base + info.ehdr->e_phoff);
info->shstr = NULL;
Elf32_Phdr *dynamic = NULL;
Elf32_Word size = 0;
uint32_t *rawdata = NULL;
getSegmentInfo(info, PT_DYNAMIC, &dynamic, &size, &info->dyn);
if(!dynamic){
LOGE("[-] could't find PT_DYNAMIC segment");
exit(-1);
}
info->dynsz = size / sizeof(Elf32_Dyn);
Elf32_Dyn *dyn = info->dyn;
for(i=0; i<info->dynsz; i++, dyn++){
switch(dyn->d_tag){
case DT_SYMTAB:
info->sym = (Elf32_Sym *)(info->elf_base + dyn->d_un.d_ptr);
break;
case DT_STRTAB:
info->symstr = (const char *)(info->elf_base + dyn->d_un.d_ptr);
break;
case DT_REL:
info->reldyn = (Elf32_Rel *)(info->elf_base + dyn->d_un.d_ptr);
break;
case DT_RELSZ:
info->reldynsz = dyn->d_un.d_val / sizeof(Elf32_Rel);
break;
case DT_JMPREL:
info->relplt = (Elf32_Rel *)(info->elf_base + dyn->d_un.d_ptr);
break;
case DT_PLTRELSZ:
info->relpltsz = dyn->d_un.d_val / sizeof(Elf32_Rel);
break;
case DT_HASH:
rawdata = (uint32_t *)(info->elf_base + dyn->d_un.d_ptr);
info->nbucket = rawdata[0];
info->nchain = rawdata[1];
info->bucket = rawdata + 2;
info->chain = info->bucket + info->nbucket;
info->symsz = info->nchain;
break;
}
}
}
unsigned elf_hash(const char *name) {
const unsigned char *tmp = (const unsigned char *) name;
unsigned h = 0, g;
while (*tmp) {
h = (h << 4) + *tmp++;
g = h & 0xf0000000;
h ^= g;
h ^= g >> 24;
}
return h;
}
void findSymByName(struct ElfInfo *info, const char *symbol, Elf32_Sym **sym, int *symidx) {
Elf32_Sym *target = NULL;
unsigned hash = elf_hash(symbol);
uint32_t index = info->bucket[hash % info->nbucket];
if (!strcmp(info->symstr + info->sym[index].st_name, symbol)) {
target = info->sym + index;
}
if (!target) {
do {
index = info->chain[index];
if (!strcmp(info->symstr + info->sym[index].st_name, symbol)) {
target = info->sym + index;
break;
}
} while (index != 0);
}
if(target){
SAFE_SET_VALUE(sym, target);
SAFE_SET_VALUE(symidx, index);
}
}
#define PAGE_START(addr) (~(getpagesize() - 1) & (addr))
static int modifyMemAccess(void *addr, int prots){
void *page_start_addr = (void *)PAGE_START((uint32_t)addr);
return mprotect(page_start_addr, getpagesize(), prots);
}
static int clearCache(void *addr, size_t len){
void *end = (uint8_t *)addr + len;
syscall(0xf0002, addr, end);
return 0;
}
static int replaceFunc(void *addr, void *replace_func, void **old_func){
int res = 0;
if(*(void **)addr == replace_func){
LOGE("addr %p had been replace.\n", addr);
goto fails;
}
if(!*old_func){
*old_func = *(void **)addr;
}
if(modifyMemAccess((void *)addr, PROT_EXEC|PROT_READ|PROT_WRITE)){
LOGE("[-] modifymemAccess fails, error %s.", strerror(errno));
res = 1;
goto fails;
}
*(void **)addr = replace_func;
clearCache(addr, getpagesize());
LOGI("[+] old_func is %p, replace_func is %p, new_func %p.\n", *old_func, replace_func, *(uint32_t *)addr);
fails:
return res;
}
//#define R_ARM_ABS32 0x02
//#define R_ARM_GLOB_DAT 0x15
//#define R_ARM_JUMP_SLOT 0x16
int elfHook(const char *soname, const char *symbol, void *replace_func, void **old_func){
//assert(old_func);
//assert(replace_func);
//assert(symbol);
int i;
ElfHandle* handle = openElfBySoname(soname);
struct ElfInfo info;
Elf32_Rel rel;
getElfInfoBySegmentView(&info, handle);
Elf32_Sym *sym = NULL;
int symidx = 0;
findSymByName(&info, symbol, &sym, &symidx);
if(!sym){
LOGE("[-] Could not find symbol %s\n", symbol);
goto fails;
}else{
LOGI("[+] sym %p, symidx %d.\n", sym, symidx);
}
for (i = 0; i < info.relpltsz; i++) {
rel = info.relplt[i];
if (ELF32_R_SYM(rel.r_info) == symidx && ELF32_R_TYPE(rel.r_info) == R_ARM_JUMP_SLOT) {
LOGI("op 1.\n");
void *addr = (void *) (info.elf_base + rel.r_offset);
if (replaceFunc(addr, replace_func, old_func))
goto fails;
//only once
break;
}
}
for (i = 0; i < info.reldynsz; i++) {
rel = info.reldyn[i];
if (ELF32_R_SYM(rel.r_info) == symidx &&
(ELF32_R_TYPE(rel.r_info) == R_ARM_ABS32
|| ELF32_R_TYPE(rel.r_info) == R_ARM_GLOB_DAT)) {
LOGI("op 2.\n");
void *addr = (void *) (info.elf_base + rel.r_offset);
if (replaceFunc(addr, replace_func, old_func))
goto fails;
}
}
fails:
closeElfBySoname(handle);
return 0;
}
int hook_entry1(char * a)
{
//
g_com_fd = com_appstart();
my_printf( "g_com_fd = %d\n", g_com_fd );
my_printf( "in hook_entry2, param is %s\n", a );
//hook_eglSwapBuffers();
//write(g_com_fd,"stdout\n",7);
ElfHandle* handle = openElfBySoname(LIBSF_PATH);
struct ElfInfo info;
getElfInfoBySegmentView(&info, handle);
Elf32_Sym *sym = NULL;
int symidx = 0;
//findSymByName(&info, "strlen", &sym, &symidx);
findSymByName(&info, "test_fun0", &sym, &symidx);
if(!sym){
LOGE("[-] Could not find symbol %s", "strlen");
goto fails;
}else{
LOGI("[+] sym %p, symidx %d.", sym, symidx);
}
fails:
my_printf( "mypid = %d\n", getpid() );
my_printf("gogogogogogo234!\n");
close(g_com_fd);
return 0;
}
typedef int (*strlen_fun)(const char *);
strlen_fun old_strlen = NULL;
size_t my_strlen(const char *str){
LOGI("strlen was called 1111111111111111111111.\n");
int len = old_strlen(str);
return len * 4;
}
strlen_fun global_strlen1 = (strlen_fun)strlen;
strlen_fun global_strlen2 = (strlen_fun)strlen;
#define SHOW(x) LOGI("%s is %d\n", #x, x)
//extern "C" jint Java_com_example_allhookinone_HookUtils_elfhook(JNIEnv *env, jobject thiz){
int hook_entry(char * a)
{
const char *str = "helloworld";
g_com_fd = com_appstart();
my_printf( "g_com_fd = %d\n", g_com_fd );
my_printf( "in hook_entry2, param is %s\n", a );
strlen_fun local_strlen1 = (strlen_fun)strlen;
strlen_fun local_strlen2 = (strlen_fun)strlen;
int len0 = global_strlen1(str);
int len1 = global_strlen2(str);
int len2 = local_strlen1(str);
int len3 = local_strlen2(str);
int len4 = strlen(str);
int len5 = strlen(str);
LOGI( "global_strlen1 = %p\n", global_strlen1 );
LOGI( "global_strlen2 = %p\n", global_strlen2 );
LOGI( "local_strlen1 = %p\n", local_strlen1 );
LOGI( "local_strlen2 = %p\n", local_strlen2 );
LOGI( "strlen = %p\n", strlen );
LOGI("hook before:\n");
SHOW(len0);
SHOW(len1);
SHOW(len2);
SHOW(len3);
SHOW(len4);
SHOW(len5);
//elfHook("libonehook.so", "strlen", (void *)my_strlen, (void **)&old_strlen);
elfHook(LIBSF_PATH, "strlen", (void *)my_strlen, (void **)&old_strlen);
LOGI( "global_strlen1 = %p\n", global_strlen1 );
LOGI( "global_strlen2 = %p\n", global_strlen2 );
LOGI( "local_strlen1 = %p\n", local_strlen1 );
LOGI( "local_strlen2 = %p\n", local_strlen2 );
LOGI( "strlen = %p\n", strlen );
len0 = global_strlen1(str);
len1 = global_strlen2(str);
len2 = local_strlen1(str);
len3 = local_strlen2(str);
len4 = strlen(str);
len5 = strlen(str);
LOGI("hook after:");
SHOW(len0);
SHOW(len1);
SHOW(len2);
SHOW(len3);
SHOW(len4);
SHOW(len5);
close(g_com_fd);
return 0;
}
inject.c -->自己的hook程序
#include <stdio.h>
#include <stdlib.h>
#include <asm/user.h>
#include <asm/ptrace.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <elf.h>
#include <android/log.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
#include <utils/Log.h>
//#include "AudioResamplerSinc.h"
#if defined(__i386__)
xxxxxxxxxxxxx
#define pt_regs user_regs_struct
#endif
#define ENABLE_DEBUG 1
#if ENABLE_DEBUG
#define LOG_TAG "INJECT"
//#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)
#define LOGD(fmt, args...) printf(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)
//dddd
#define DEBUG_PRINT(format,args...) \
LOGD(format, ##args)
#else
#define DEBUG_PRINT(format,args...)
#endif
#define CPSR_T_MASK ( 1u << 5 )
const char *libc_path = "/system/lib/libc.so";
const char *linker_path = "/system/bin/linker";
int ptrace_readdata(pid_t pid, uint8_t *src, uint8_t *buf, size_t size)
{
uint32_t i, j, remain;
uint8_t *laddr;
union u {
long val;
char chars[sizeof(long)];
} d;
j = size / 4;
remain = size % 4;
laddr = buf;
for (i = 0; i < j; i ++) {
d.val = ptrace(PTRACE_PEEKTEXT, pid, src, 0);
memcpy(laddr, d.chars, 4);
src += 4;
laddr += 4;
}
if (remain > 0) {
d.val = ptrace(PTRACE_PEEKTEXT, pid, src, 0);
memcpy(laddr, d.chars, remain);
}
return 0;
}
int ptrace_writedata(pid_t pid, uint8_t *dest, uint8_t *data, size_t size)
{
uint32_t i, j, remain;
uint8_t *laddr;
union u {
long val;
char chars[sizeof(long)];
} d;
j = size / 4;
remain = size % 4;
laddr = data;
//printf( "j = %x\n", j);
//printf( "remain = %x\n", remain );
//printf( "laddr = %x\n", laddr );
for (i = 0; i < j; i ++) {
memcpy(d.chars, laddr, 4);
ptrace(PTRACE_POKETEXT, pid, dest, d.val);
dest += 4;
laddr += 4;
}
if (remain > 0) {
d.val = ptrace(PTRACE_PEEKTEXT, pid, dest, 0);
//printf( "d.val = %x\n", d.val );
for (i = 0; i < remain; i ++) {
d.chars[i] = *laddr ++;
}
//printf( "d.val = %x\n", d.val );
ptrace(PTRACE_POKETEXT, pid, dest, d.val);
}
return 0;
}
#if defined(__arm__)
int ptrace_call(pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct pt_regs* regs)
{
uint32_t i;
for (i = 0; i < num_params && i < 4; i ++) {
regs->uregs[i] = params[i];
}
//
// push remained params onto stack
//
if (i < num_params) {
regs->ARM_sp -= (num_params - i) * sizeof(long) ;
ptrace_writedata(pid, (void *)regs->ARM_sp, (uint8_t *)¶ms[i], (num_params - i) * sizeof(long));
}
regs->ARM_pc = addr;
if (regs->ARM_pc & 1) {
/* thumb */
regs->ARM_pc &= (~1u);
regs->ARM_cpsr |= CPSR_T_MASK;
} else {
/* arm */
regs->ARM_cpsr &= ~CPSR_T_MASK;
}
regs->ARM_lr = 0;
if (ptrace_setregs(pid, regs) == -1
|| ptrace_continue(pid) == -1) {
printf("error\n");
return -1;
}
int stat = 0;
waitpid(pid, &stat, WUNTRACED);
while (stat != 0xb7f) {
if (ptrace_continue(pid) == -1){
printf("error\n");
return -1;
}
waitpid(pid, &stat, WUNTRACED);
}
return 0;
}
#elif defined(__i386__)
long ptrace_call(pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct user_regs_struct * regs)
{
regs->esp -= (num_params) * sizeof(long) ;
ptrace_writedata(pid, (void *)regs->esp, (uint8_t *)params, (num_params) * sizeof(long));
long tmp_addr = 0x00;
regs->esp -= sizeof(long);
ptrace_writedata(pid, regs->esp, (char *)&tmp_addr, sizeof(tmp_addr));
regs->eip = addr;
if (ptrace_setregs(pid, regs) == -1
|| ptrace_continue( pid) == -1) {
printf("error\n");
return -1;
}
   int stat = 0;
   waitpid(pid, &stat, WUNTRACED);
   while (stat != 0xb7f) {
       if (ptrace_continue(pid) == -1) {
           printf("error\n");
           return -1;
       }
       waitpid(pid, &stat, WUNTRACED);
   }
return 0;
}
#else
#error "Not supported"
#endif
int ptrace_getregs(pid_t pid, struct pt_regs * regs)
{
if (ptrace(PTRACE_GETREGS, pid, NULL, regs) < 0) {
perror("ptrace_getregs: Can not get register values");
return -1;
}
return 0;
}
int ptrace_setregs(pid_t pid, struct pt_regs * regs)
{
if (ptrace(PTRACE_SETREGS, pid, NULL, regs) < 0) {
perror("ptrace_setregs: Can not set register values");
return -1;
}
return 0;
}
int ptrace_continue(pid_t pid)
{
if (ptrace(PTRACE_CONT, pid, NULL, 0) < 0) {
perror("ptrace_cont");
return -1;
}
return 0;
}
int ptrace_attach(pid_t pid)
{
if (ptrace(PTRACE_ATTACH, pid, NULL, 0) < 0) {
perror("ptrace_attach");
return -1;
}
int status = 0;
waitpid(pid, &status , WUNTRACED);
return 0;
}
int ptrace_detach(pid_t pid)
{
if (ptrace(PTRACE_DETACH, pid, NULL, 0) < 0) {
perror("ptrace_detach");
return -1;
}
return 0;
}
void* get_module_base(pid_t pid, const char* module_name)
{
FILE *fp;
long addr = 0;
char *pch;
char filename[32];
char line[1024];
if (pid < 0) {
/* self process */
snprintf(filename, sizeof(filename), "/proc/self/maps", pid);
} else {
snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
}
fp = fopen(filename, "r");
//printf("filename = %s\n", filename);
if (fp != NULL) {
while (fgets(line, sizeof(line), fp)) {
if (strstr(line, module_name)) {
//printf("line = %s\n", line);
pch = strtok( line, "-" );
addr = strtoul( pch, NULL, 16 );
if (addr == 0x8000)
addr = 0;
break;
}
}
fclose(fp) ;
}
return (void *)addr;
}
void* get_remote_addr(pid_t target_pid, const char* module_name, void* local_addr)
{
void* local_handle, *remote_handle;
local_handle = get_module_base(-1, module_name);
remote_handle = get_module_base(target_pid, module_name);
//printf("[+] get_remote_addr: local[%x], remote[%x]\n", local_handle, remote_handle);
//printf("[+] get_remote_addr: local_addr[%x], local_addr[%x]\n", local_addr, local_addr);
void * ret_addr = (void *)((uint32_t)local_addr + (uint32_t)remote_handle - (uint32_t)local_handle);
#if defined(__i386__)
if (!strcmp(module_name, libc_path)) {
ret_addr += 2;
}
#endif
return ret_addr;
}
int find_pid_of(const char *process_name)
{
int id;
pid_t pid = -1;
DIR* dir;
FILE *fp;
char filename[32];
char cmdline[256];
struct dirent * entry;
if (process_name == NULL)
return -1;
dir = opendir("/proc");
if (dir == NULL)
return -1;
while((entry = readdir(dir)) != NULL) {
id = atoi(entry->d_name);
//printf("entry->d_name = %s.\n", entry->d_name);
//printf("id = %d.\n", id);
if (id != 0) {
sprintf(filename, "/proc/%d/cmdline", id);
fp = fopen(filename, "r");
if (fp) {
fgets(cmdline, sizeof(cmdline), fp);
fclose(fp);
if (strcmp(process_name, cmdline) == 0) {
/* process found */
pid = id;
break;
}
}
}
}
closedir(dir);
return pid;
}
long ptrace_retval(struct pt_regs * regs)
{
#if defined(__arm__)
return regs->ARM_r0;
#elif defined(__i386__)
xxxxxx
return regs->eax;
#else
vvxxxxxx
#error "Not supported"
#endif
}
long ptrace_ip(struct pt_regs * regs)
{
#if defined(__arm__)
return regs->ARM_pc;
#elif defined(__i386__)
return regs->eip;
#else
#error "Not supported"
#endif
}
int ptrace_call_wrapper(pid_t target_pid, const char * func_name, void * func_addr, long * parameters, int param_num, struct pt_regs * regs)
{
printf("[+] Calling %s in target process.\n", func_name);
if (ptrace_call(target_pid, (uint32_t)func_addr, parameters, param_num, regs) == -1)
return -1;
if (ptrace_getregs(target_pid, regs) == -1)
return -1;
printf("[+] Target process returned from %s, return value=%x, pc=%x \n",
func_name, ptrace_retval(regs), ptrace_ip(regs));
return 0;
}
int inject_remote_process(pid_t target_pid, const char *library_path, const char *function_name, const char *param, size_t param_size)
{
int ret = -1;
void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr, *dlerror_addr;
void *local_handle, *remote_handle, *dlhandle;
uint8_t *map_base = 0;
uint8_t *dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr;
struct pt_regs regs, original_regs;
extern uint32_t _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, _dlsym_addr_s, \
_dlsym_param2_s, _dlclose_addr_s, _inject_start_s, _inject_end_s, _inject_function_param_s, \
_saved_cpsr_s, _saved_r0_pc_s;
uint32_t code_length;
long parameters[10];
printf("[+] Injecting process: %d\n", target_pid);
if (ptrace_attach(target_pid) == -1){
//½á»é
goto exit;
}
if (ptrace_getregs(target_pid, ®s) == -1){
//»éÇ°²Æ²ú¹«Ö¤
goto exit;
}
//save original registers
memcpy(&original_regs, ®s, sizeof(regs));
//ΪÀë»é×ö×¼±¸
mmap_addr = get_remote_addr(target_pid, libc_path, (void *)mmap);
printf("[+] Remote mmap address: %x\n", mmap_addr);
//»ñÈ¡mmapº¯ÊýµÄÖ´ÐÐÐéµØÖ·
//call mmap
parameters[0] = 0;
//addr
parameters[1] = 0x4000;
//size
parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC;
//prot
parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE;
//flags
parameters[4] = 0;
//fd
parameters[5] = 0;
//offset
if( ptrace_call_wrapper(target_pid, "mmap", mmap_addr, parameters, 6, ®s) == -1 ){
goto exit;
}
map_base = ptrace_retval(®s);
printf( "map_base: %x\n", map_base );
dlopen_addr = get_remote_addr( target_pid, linker_path, (void *)dlopen );
dlsym_addr = get_remote_addr( target_pid, linker_path, (void *)dlsym );
dlclose_addr = get_remote_addr( target_pid, linker_path, (void *)dlclose );
dlerror_addr = get_remote_addr( target_pid, linker_path, (void *)dlerror );
printf("[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x, dlerror: %x\n",
dlopen_addr, dlsym_addr, dlclose_addr, dlerror_addr);
printf("library path = %s\n", library_path);
ptrace_writedata(target_pid, map_base, library_path, strlen(library_path) + 1);
parameters[0] = map_base;
parameters[1] = RTLD_NOW| RTLD_GLOBAL;
if( ptrace_call_wrapper(target_pid, "dlopen", dlopen_addr, parameters, 2, ®s) == -1 ){
//´ò¿ª¶¯Ì¬Á´½Ó¿â
goto exit;
}
void * sohandle = ptrace_retval(®s);
//·µ»Ø¶¯Ì¬Á´½Ó¿âµÄ¿ØÖƾä±ú
#define FUNCTION_NAME_ADDR_OFFSET 0x100
ptrace_writedata(target_pid, map_base + FUNCTION_NAME_ADDR_OFFSET, function_name, strlen(function_name) + 1);
//½«¹³×Óº¯ÊýµÄº¯ÊýÃûдÈëÄÚ´æ
parameters[0] = sohandle;
parameters[1] = map_base + FUNCTION_NAME_ADDR_OFFSET;
if( ptrace_call_wrapper(target_pid, "dlsym", dlsym_addr, parameters, 2, ®s) == -1 ){
//µ÷ÓÃϵͳº¯Êýdlsym,²ÎÊýΪ°üº¬¹³×Óº¯Êý¶¯Ì¬¿âµÄÊ×µØÖ·,¹³×Óº¯ÊýµÄÃû³Æ
goto exit;
}
void * hook_entry_addr = ptrace_retval(®s);
//Æä½á¹û¾ÍÊÇ·µ»Ø¹³×Óº¯ÊýµÄ¾ä±ú,¼´º¯ÊýµÄÖ´ÐеØÖ·
printf("hook_entry_addr = %p\n", hook_entry_addr);
#define FUNCTION_PARAM_ADDR_OFFSET 0x200
ptrace_writedata(target_pid, map_base + FUNCTION_PARAM_ADDR_OFFSET, param, strlen(param) + 1);
//½«Óûµ÷ÓõĹ³×Óº¯ÊýµÄ²ÎÊýдÈëÄÚ´æ
parameters[0] = map_base + FUNCTION_PARAM_ADDR_OFFSET;
if( ptrace_call_wrapper(target_pid, "hook_entry", hook_entry_addr, parameters, 1, ®s) == -1 ){
//µ÷Óù³×Óº¯Êý
goto exit;
}
printf("Press enter to dlclose and detach\n");
getchar();
//´Ó¿ØÖÆ̨»ñÈ¡Ò»¸ö×Ö·û
parameters[0] = sohandle;
if( ptrace_call_wrapper(target_pid, "dlclose", dlclose, parameters, 1, ®s) == -1 ){
//¹Ø±Õ¹³×Óº¯Êý¶¯Ì¬Á´½Ó¿â
goto exit;
}
//restore
ptrace_setregs(target_pid, &original_regs);
//¹é»¹½á»é½äÖ¸,»Ö¸´³ÌÐòÏÖ³¡
ptrace_detach(target_pid);
//ˑȎ
ret = 0;
exit:
return ret;
}
//dd
int main(int argc, char** argv) {
pid_t target_pid;
printf("inject.c main.\n");
//target_pid = find_pid_of("com.example.fengzi.xdntest");
//target_pid = find_pid_of("/system/bin/surfaceflinger");
//target_pid = find_pid_of("com.example.asus.myapplication");
target_pid = find_pid_of("/system/bin/rild");
if (-1 == target_pid) {
printf("Can't find the process\n");
return -1;
}
printf("target_pid = %d.\n", target_pid);
//target_pid = find_pid_of("/data/test");
//inject_remote_process(target_pid, "/data/libhello.so", "hook_entry", "I'm parameter!", strlen("I'm parameter!"));
//inject_remote_process(target_pid, "/system/lib/libtest_hello.so", "hook_entry", "I'm parameter!", strlen("I'm parameter!"));
inject_remote_process(target_pid, "/system/lib/libtest_hello.so", "hook_entry", "I'm parameter!", strlen("I'm parameter!"));
return 0;
}
inject hook "/system/bin/rild"进程
然后把lib_hello.so注入到该进程,
修改strlen的系统调用
从网上 低端码农大哥处
http://blog.csdn.net/l173864930/article/details/40507359
下载而来,
为c++版本,编译也过不去
只怪自己水平太菜
改成c语言版本,并且没有在java端的hook,只是自己hook自己
30|shell@astar-dvk3:/ # test_dlclose_destruction1
inject.c main.
target_pid = 1676.
[+] Injecting process: 1676
[+] Remote mmap address: 400b0cf9
[+] Calling mmap in target process.
[+] Target process returned from mmap, return value=404cc000, pc=0
map_base: 404cc000
[+] Get imports: dlopen: 40083f4d, dlsym: 40083e9d, dlclose: 40083e19, dlerror: 40083dc9
library path = /system/lib/libtest_hello.so
[+] Calling dlopen in target process.
[+] Target process returned from dlopen, return value=4019224c, pc=0
[+] Calling dlsym in target process.
[+] Target process returned from dlsym, return value=404d18e9, pc=0
hook_entry_addr = 0x404d18e9
[+] Calling hook_entry in target process.
g_com_fd = 12
in hook_entry2, param is I'm parameter!
global_strlen1 = 0x400c0ec1
global_strlen2 = 0x400c0ec1
local_strlen1 = 0x400c0ec1
local_strlen2 = 0x400c0ec1
strlen = 0x400c0ec1
hook before:
len0 is 10
len1 is 10
len2 is 10
len3 is 10
len4 is 10
len5 is 10
base = 404d0000.
info->handle = 4123c7d0.
info->elf_base = 404d0000.
info->ehdr = 404d0000.
[+] sym 0x404d04e8, symidx 58.
op 1.
[+] old_func is 0x400c0ec1, replace_func is 0x404d0e6d, new_func 0x404d0e6d.
op 2.
[+] old_func is 0x400c0ec1, replace_func is 0x404d0e6d, new_func 0x404d0e6d.
op 2.
[+] old_func is 0x400c0ec1, replace_func is 0x404d0e6d, new_func 0x404d0e6d.
op 2.
[+] old_func is 0x400c0ec1, replace_func is 0x404d0e6d, new_func 0x404d0e6d.
global_strlen1 = 0x404d0e6d
global_strlen2 = 0x404d0e6d
local_strlen1 = 0x400c0ec1
local_strlen2 = 0x400c0ec1
strlen = 0x400c0ec1
strlen was called 1111111111111111111111.
strlen was called 1111111111111111111111.
hook after:len0 is 40
len1 is 40
len2 is 10
len3 is 10
len4 is 10
len5 is 10
[+] Target process returned from hook_entry, return value=0, pc=0
Press enter to dlclose and detach
[+] Calling dlclose in target process.
[+] Target process returned from dlclose, return value=4019224c, pc=40034e18
shell@astar-dvk3:/ #
lib_hello.c ->生成自己hook自己的lib_hello.so
#if 0
#include <stdio.h>
#include <stdlib.h>
#include <asm/user.h>
#include <asm/ptrace.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <elf.h>
#include <android/log.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
#include <utils/Log.h>
//#include "AudioResamplerSinc.h"
#if defined(__i386__)
xxxxxxxxxxxxx
#define pt_regs user_regs_struct
#endif
#define ENABLE_DEBUG 1
#if ENABLE_DEBUG
#define LOG_TAG "INJECT"
//#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)
#define LOGD(fmt, args...) printf(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)
//dddd
#define DEBUG_PRINT(format,args...) \
LOGD(format, ##args)
#else
#define DEBUG_PRINT(format,args...)
#endif
#define CPSR_T_MASK ( 1u << 5 )
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
//#include <android/log.h>
#include <elf.h>
#include <fcntl.h>
#include <cutils/klog.h>
#define TAG "htfsk"
#define LOGE(x...) do { KLOG_ERROR("events", x); } while (0)
#define LOGI(x...) do { KLOG_INFO("events", x); } while (0)
#define LOGV(x...) do { KLOG_DEBUG("events", x); } while (0)
#if 0
int debug_msg(const char *format, ...)
{
char tmpbuf[4096];
unsigned int send_len;
va_list vArgs;
va_start(vArgs, format);
vsnprintf( (char *)&tmpbuf[0], sizeof(tmpbuf), (char const *)format, vArgs );
va_end(vArgs);
send_len = strlen(&tmpbuf[0]);
__android_log_write( ANDROID_LOG_DEBUG, TAG, tmpbuf );
return 0;
}
#endif
int hook_entry(char * a){
//debug_msg("Hook success, pid = %d\n", getpid());
//debug_msg("Hello %s\n", a);
unsigned char * teststr="12345";
__android_log_write( ANDROID_LOG_DEBUG, TAG, "hook_entry 123" );
system("echo mabid 12345 >/dev/ttyS0");
setenv("teststr", teststr, 1);
system("echo hahah$teststr >/dev/ttyS0");
return 19;
}
#endif
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <android/log.h>
#include <EGL/egl.h>
#include <GLES/gl.h>
#include <elf.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <termios.h>
#include <sys/stat.h>
#include "lib_hello.h"
#define LOG_TAG "DEBUG"
#define LOGD(fmt, args...) my_printf(fmt, ##args)
#define LOGI(fmt, args...) my_printf(fmt, ##args)
#define LOGE(fmt, args...) my_printf(fmt, ##args)
#define Ser_Printf my_printf
#define macdbg_prser my_printf
//#define my_printf printf
static int g_com_fd = -1;
#if 1
int my_printf( const char *fmt, ... )
{
char *tmp_buf;
int g_printf_switch = 1;
unsigned char buffer[4096];
va_list vArgs;
if( g_printf_switch == 0x00 ){
return 1;
}
va_start(vArgs, fmt);
vsnprintf((char *)buffer, sizeof(buffer), (char const *)fmt, vArgs);
va_end(vArgs);
if( g_com_fd != -1 ){
write(g_com_fd, (unsigned char *)buffer, strlen((unsigned char *)buffer) );
}
//Ser_WrStr(( unsigned char *) buffer);
//setenv( "tmp_buf", buffer, 1 );
//system( "echo $tmp_buf > /dev/ttyS0" );
return 3;
}
#endif
int macdbg_dmphex(const char* buff, int len)
{
int retval = 0;
int x, y, tot, lineoff;
const char* curr;
//Ser_Printf("buff %x.\r\n", buff );
Ser_Printf("\r\n" );
lineoff = 0;
curr = buff;
tot = 0;
for( x = 0; x+16 < len; ){
Ser_Printf("%x\t", lineoff);
for( y = 0; y < 16; y++ ){
macdbg_prser("%02x ", (unsigned char)*(curr + y));
}
macdbg_prser(" ");
for( y = 0; y < 16; y++ ){
char c;
c = *(curr + y);
if( c > 31 && c < 127 ){
macdbg_prser("%c", c);
}else{
macdbg_prser("%c", '.');
}
tot++;
}
curr += 16;
x += 16;
lineoff+=16;
macdbg_prser("\r\n");
}
//do last line
//Ser_Printf("tot %d.\r\n", tot );
//Ser_Printf("len %d.\r\n", len );
if( tot < len ){
curr = (buff + tot);
macdbg_prser("%x\t", lineoff);
for( y = 0; y < (len - tot); y++ ){
macdbg_prser("%02x ", (unsigned char)*(curr + y));
}
//padding with spaces
//Ser_Printf("(len - tot) %d.\r\n", (len - tot) );
if( (len - tot) < 16 ){
for( y = 0; y < (32 - ((len - tot)*2)); y++ ){
macdbg_prser(" ");
}
}
for( y = 0; y < 16-(len - tot); y++ ){
macdbg_prser(" ");
}
macdbg_prser(" ");
//Ser_Printf("(len - tot) %d.\r\n", (len - tot) );
for( y = 0; y < (len - tot); y++ ){
char c;
c = *(curr + y);
if( c >31 && c < 127 ){
macdbg_prser("%c", c);
}else{
macdbg_prser("%c", '.');
//macdbg_prser("%c", c);
}
}
}
macdbg_prser("\r\n");
return retval;
}
EGLBoolean (*old_eglSwapBuffers)(EGLDisplay dpy, EGLSurface surf) = -1;
EGLBoolean new_eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
{
LOGD("New eglSwapBuffers\n");
if (old_eglSwapBuffers == -1)
LOGD("error\n");
return old_eglSwapBuffers(dpy, surface);
}
void* get_module_base(pid_t pid, const char* module_name)
{
FILE *fp;
long addr = 0;
char *pch;
char filename[32];
char line[1024];
if (pid < 0) {
/* self process */
snprintf(filename, sizeof(filename), "/proc/self/maps", pid);
} else {
snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
}
fp = fopen(filename, "r");
if (fp != NULL) {
while (fgets(line, sizeof(line), fp)) {
if (strstr(line, module_name)) {
pch = strtok( line, "-" );
addr = strtoul( pch, NULL, 16 );
if (addr == 0x8000)
addr = 0;
break;
}
}
fclose(fp) ;
}
return (void *)addr;
}
//shell@astar-dvk3:/data/app-lib/com.example.asus.myapplication-2 #
//#define LIBSF_PATH "/data/app-lib/com.example.fengzi.xdntest-1/libuart.so"
#define LIBSF_PATH1 "/data/app-lib/com.example.asus.myapplication-2/libhello-jni.so"
#define LIBSF_PATH "/system/lib/libtest_hello.so"
#if 0
static int lib_hook_hello()
{
//old_funpoint = NULL;
//LOGD("Orig eglSwapBuffers = %p\n", old_funpoint);
void * base_addr = hello_get_module_base(getpid(), HELLO_LIBSF_PATH);
LOGD("asmhello address = %p\n", base_addr);
//macdbg_dmphex(base_addr, 0x1000);
int fd;
fd = open(LIBSF_PATH, O_RDONLY);
if( -1 == fd ){
LOGD("error\n");
return -1;
}
Elf32_Ehdr ehdr;
read(fd, &ehdr, sizeof(Elf32_Ehdr));
//macdbg_dmphex(&ehdr, sizeof(Elf32_Ehdr));
//ÒÔÏ´úÂëÖ÷Òª·ÖÎö¶ÎÍ·Êý¾Ý½á¹¹
unsigned long shdr_addr = ehdr.e_shoff;
int shnum = ehdr.e_shnum;
//Number of section headers
//¶ÎÍ·ÏîÄ¿µÄ¸öÊý
int shent_size = ehdr.e_shentsize;
//Section header entry size
//ÿһ¸ö¶ÎÍ·ÏîÄ¿µÄ´óС
unsigned long stridx = ehdr.e_shstrndx;
Elf32_Shdr shdr;
//my_printf( "ehdr.e_phoff = %x\n", ehdr.e_phoff );
//³ÌÐòÍ·Æ«ÒƵØÖ·,Ö±½Ó¸úËæELF Header 0x34
//ELF HeaderÕ¼ÓÃ52×Ö½Ú,ÃèÊö³ÌÐòÍ·,¶ÎÍ·,Ìåϵ½á¹¹µÈÐÅÏ¢
//my_printf( "ehdr.e_phnum = %x\n", ehdr.e_phnum );
//³ÌÐòÍ·½á¹¹ÌåµÄ¸öÊý
//my_printf( "ehdr.e_phentsize = %x\n", ehdr.e_phentsize );
//³ÌÐòÍ·½á¹¹Ìåÿһ¸öµÄ´óС
//my_printf( "shdr_addr = %x\n", shdr_addr );
//¶ÎÍ·µÄÆ«ÒƵØÖ·
//my_printf( "shnum = %x\n", shnum );
//¶ÎÍ·½á¹¹ÌåµÄ¸öÊý
//my_printf( "shent_size = %x\n", shent_size );
//ÿһ¸ö¶ÎÍ·½á¹¹ÌåµÄ´óС
//my_printf( "stridx = %x\n", stridx );
//Section header string table index: 23
//ÔÚËùÓжÎÍ·½á¹¹ÌåÄÚ,ÓÐÒ»¸ö½Ð"´®±í"µÄ½á¹¹Ìå
//´Ë½á¹¹ÌåÔÚËùÓжÎÍ·½á¹¹ÌåµÄ¸öÊýÖеÄË÷ÒýÖµ Ö¸Ïò×îºóÒ»¸ö¶ÎÍ·½á¹¹Ìå
//´Ëµ÷ÊÔÐÅÏ¢¿ÉÒÔ¿´³ö-->shnum = 18 shent_size = 28 stridx = 17
//my_printf( "shdr_addr = %x\n", shdr_addr );
//my_printf( "shdr_addr + stridx * shent_size = %x\n", shdr_addr + stridx * shent_size );
lseek(fd, shdr_addr + stridx * shent_size, SEEK_SET);
//ÎļþÖ¸Õ붨λµ½"´®±í"¶ÎÍ·½á¹¹Ìå
read(fd, &shdr, shent_size);
//¶ÁÈ¡"´®±í"¶ÎÍ·½á¹¹Ìå
char *string_table = (char *)malloc(shdr.sh_size);
//my_printf( "string_table = %x\n", string_table );
//my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
//section size,´®±íµÄ´óС ÃèÊöÁË´®±íÕ¼ÓõĴ洢¿Õ¼äµÄ´óС
//my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
//file offset ´®±íÔÚÕû¸öelfÎļþÖеÄÆ«ÒÆλÖÃ
lseek(fd, shdr.sh_offset, SEEK_SET);
read(fd, string_table, shdr.sh_size);
lseek(fd, shdr_addr, SEEK_SET);
//Ö¸Ïò¶ÎÍ·½á¹¹Ìå´æ´¢µÄÊ×µØÖ·
//elfÄÚ´æ½á¹¹ÃèÊöÈçÏÂ:
//-->¿ªÊ¼
//ELF Header 0x34
//³ÌÐòÍ·½á¹¹Ìå´æ´¢Î»ÖÃ:
//PHDR->µÚÒ»¸ö³ÌÐòÍ·½á¹¹Ìå
//ÃèÊöÁË×ܹ²ÓжàÉÙ¸ö³ÌÐòÍ·½á¹¹Ìå
//INTERP->µÚ¶þ¸ö³ÌÐòÍ·½á¹¹Ìå
//ÃèÊöÁËlinkerÔÚϵͳÖеÄλÖÃ
//Õû¸ö´®±í
//¶ÎÍ·½á¹¹Ìå´æ´¢Î»ÖÃ:
//µÚÒ»¸ö¶ÎÍ·±íÈë¿ÚΪ¿Õ
//->Section header table entry unused
//.interp
//.dynsym
//.dynstr
//.hash
//.rel.dyn
//.rel.plt
//.plt
//.text
//->º¯ÊýÖ´ÐдúÂë
//.note.android.ident
//.ARM.exidx
//->²¿·Öº¯ÊýµØÖ·¿ÉÒÔÔÚ´ËÓù«Ê½»ñÈ¡
//.ARM.extab
//.rodata
//->È«¾Öconst±äÁ¿ ×Ö·û´®µÈ printf("test string");
//->³ÌÐò±¾ÉíµÄһЩ±í ¿´Çé¿ö
//.preinit_array
//.init_array
//.fini_array
//.dynamic
//.got
//->¶¯Ì¬¿âÏà¹ØµÄº¯ÊýµØÖ·
//.bss
//->δ³õʼ»¯µÄÈ«¾Ö±äÁ¿
//.comment
//.note.gnu.gold-version
//.ARM.attributes
//.gnu_debuglink
//.shstrtab
//->´®±íÃèÊö
//-->½áÊø
int i,j;
uint32_t out_addr = 0;
uint32_t out_size = 0;
uint32_t got_item = 0;
int32_t got_found = 0;
int32_t get_off = 0;
//my_printf( "shnum = %x\n", shnum );
//¶ÎÍ·½á¹¹ÌåµÄ¸öÊý 0x18
//my_printf( "shent_size = %x\n", shent_size );
//ÿһ¸ö¶ÎÍ·½á¹¹ÌåµÄ´óС 0x28
for( j = 0; j < shnum; j++ ){
read(fd, &shdr, shent_size);
//macdbg_dmphex(&shdr, sizeof(Elf32_Shdr));
//my_printf( "shdr.sh_type = %x\n", shdr.sh_type );
int name_idx = shdr.sh_name;
if( shdr.sh_type == SHT_PROGBITS ){
//my_printf( "get Section header entry %s\n", &string_table[name_idx] );
//my_printf( "shdr.sh_addr = %x\n", shdr.sh_addr );
//my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
//my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
//my_printf( "shdr.sh_entsize = %x\n", shdr.sh_entsize );
if( strcmp(&(string_table[name_idx]), ".got.plt") == 0 ||
strcmp(&(string_table[name_idx]), ".got") == 0 ){
out_addr = base_addr + shdr.sh_addr;
out_size = shdr.sh_size;
LOGD("out_addr = %lx, out_size = %lx\n", out_addr, out_size);
//my_printf( "old_funpoint = %x\n", old_funpoint );
//my_printf( "new_funpoint = %x\n", new_funpoint );
my_printf( "base_addr = %x\n", base_addr );
my_printf( "main = %x\n", main );
//macdbg_dmphex( base_addr, 0x40000);
for (i = 0; i < out_size; i += 4) {
got_item = *(uint32_t *)(out_addr + i);
my_printf( "got_item = %x\n", got_item );
if (got_item == old_funpoint) {
LOGD("Found eglSwapBuffers in got\n");
got_found = 1;
uint32_t page_size = getpagesize();
uint32_t entry_page_start = (out_addr + i) & (~(page_size - 1));
mprotect((uint32_t *)entry_page_start, page_size, PROT_READ | PROT_WRITE);
*(uint32_t *)(out_addr + i) = new_funpoint;
my_printf( "shnum = %x\n", shnum );
break;
} else if (got_item == new_funpoint) {
LOGD("Already hooked\n");
break;
}
}
if (got_found) {
//break;
}
}else if( strcmp(&(string_table[name_idx]), ".rodata") == 0 ) {
//const,¹Ì¶¨×Ö·û´®µÈÔڴ˶ÎÕÒ
my_printf("get .rodata\n");
macdbg_dmphex(&shdr, sizeof(Elf32_Shdr));
}
}else if (shdr.sh_type == SHT_NULL) {
//Section header table entry unused
//µÚÒ»¸ö¶ÎÍ·±íÈë¿ÚΪ¿Õ
my_printf("get null\n");
}else if (shdr.sh_type == PT_ARM_EXIDX) {
//Section header table entry unused
//µÚÒ»¸ö¶ÎÍ·±íÈë¿ÚΪ¿Õ
my_printf( "macdbg_dmphex = %x\n", macdbg_dmphex );
my_printf( "old_funpoint = %x\n", old_funpoint );
my_printf( "new_funpoint = %x\n", new_funpoint );
my_printf( "hello_get_module_base = %x\n", hello_get_module_base );
my_printf( "hook_hello = %x\n", hook_hello );
my_printf( "main = %x\n", main );
my_printf( "my_tgkill = %x\n", my_tgkill );
//my_printf( "get .ARM.exidx\n" );
//my_printf( "string_table[name_idx] = %s\n", &string_table[name_idx] );
//my_printf( "shdr.sh_addr = %x\n", shdr.sh_addr );
//my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
//my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
//my_printf( "shdr.sh_entsize = %x\n", shdr.sh_entsize );
out_addr = base_addr + shdr.sh_addr;
out_size = shdr.sh_size;
my_printf("out_addr = %lx, out_size = %lx\n", out_addr, out_size);
for( i = 0; i < out_size; i += 8 ){
get_off = *(int32_t *)(out_addr+i);
got_item = *(uint32_t *)(out_addr + i + 4);
//my_printf( "get_off = %x\n", get_off );
//my_printf( "get_off1 = %x\n", shdr.sh_addr - (~get_off +1)&0xffff )+i;
my_printf( "func point = %x\n", shdr.sh_addr + i - ((~get_off +1)&0xffff) + base_addr );
//shdr.sh_addr + i ÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÆ«ÒÆλÖõÄÐéÄâµØÖ·
//*(shdr.sh_addr + i)ÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÆ«ÒÆλÖÃ
//(Ïà¶ÔÓÚÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÐéÄâµØÖ·) Ϊ¸ºÊý
//base_addr ¸Ã½ø³ÌÄÚºËÄÚ´æÓ³ÉäµÄ»ùµØÖ·
//my_printf( "got_item = %x\n\n", got_item );
//my_printf( "got_item = %d\n", got_item );
}
}else{
//int name_idx = shdr.sh_name;
//section name (.shstrtab index)
//my_printf( "name_idx = %x\n", name_idx );
my_printf( "Section header entry %s\n", &string_table[name_idx] );
my_printf( "shdr.sh_addr = %x\n", shdr.sh_addr );
my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
my_printf( "shdr.sh_entsize = %x\n", shdr.sh_entsize );
}
}
free(string_table);
//ÒÔÏ´úÂëÖ÷Òª·ÖÎö³ÌÐòÍ·Êý¾Ý½á¹¹
shdr_addr = ehdr.e_phoff;
//Ê׸ö³ÌÐòÍ·ÏîÄ¿µÄÆ«ÒÆ
shnum = ehdr.e_phnum;
//³ÌÐòÍ·ÏîÄ¿µÄ¸öÊý
shent_size = ehdr.e_phentsize;
//ÿһ¸ö³ÌÐòÍ·ÏîÄ¿µÄ´óС
//stridx = ehdr.e_shstrndx;
Elf32_Phdr program_shdr;
my_printf( "ehdr.e_phoff = %x\n", ehdr.e_phoff );
//³ÌÐòÍ·Æ«ÒƵØÖ·,Ö±½Ó¸úËæELF Header 0x34
//ELF HeaderÕ¼ÓÃ52×Ö½Ú,ÃèÊö³ÌÐòÍ·,¶ÎÍ·,Ìåϵ½á¹¹µÈÐÅÏ¢
my_printf( "ehdr.e_phnum = %x\n", ehdr.e_phnum );
//³ÌÐòÍ·½á¹¹ÌåµÄ¸öÊý
my_printf( "ehdr.e_phentsize = %x\n", ehdr.e_phentsize );
shnum = ehdr.e_phnum;
lseek(fd, ehdr.e_phoff, SEEK_SET);
char *p_type_tmp;
for( j = 0; j < shnum; j++ ){
read(fd, &program_shdr, sizeof(Elf32_Phdr));
macdbg_dmphex(&program_shdr, sizeof(Elf32_Phdr));
p_type_tmp = get_p_type(program_shdr.p_type);
my_printf( "program_shdr.p_type = %s\n", p_type_tmp );
my_printf( "program_shdr.p_offset = %x\n", program_shdr.p_offset );
my_printf( "program_shdr.p_vaddr = %x\n", program_shdr.p_vaddr );
my_printf( "program_shdr.p_paddr = %x\n", program_shdr.p_paddr );
my_printf( "program_shdr.p_filesz = %x\n", program_shdr.p_filesz );
my_printf( "program_shdr.p_memsz = %x\n", program_shdr.p_memsz );
my_printf( "program_shdr.p_flags = %x\n", program_shdr.p_flags );
my_printf( "program_shdr.p_align = %x\n", program_shdr.p_align );
if( strcmp(p_type_tmp, PT_INTERP_STR) == 0 ){
//³ÌÐò½âÊÍÆ÷ ¼ÓÔØÆ÷
//ÃèÊöÁ˴˳ÌÐòµÄ¼ÓÔØÆ÷ÔÚϵͳÖеÄλÖÃ
long temp_file_position;
temp_file_position = lseek(fd, 0, SEEK_CUR);
char *linker = (char *)malloc(program_shdr.p_memsz);
lseek(fd, program_shdr.p_offset, SEEK_SET);
read(fd, linker, program_shdr.p_memsz);
my_printf( "program loader = %s\n", linker );
free(linker);
lseek(fd, temp_file_position, SEEK_SET);
}else if( strcmp(p_type_tmp, PT_PHDR_STR) == 0 ){
//ÃèÊöÁ˴˳ÌÐòµÄ³ÌÐòÍ·µÄÕûÌå´óС
my_printf( "get program head = %x\n", program_shdr.p_memsz );
}
}
//lseek(fd, shdr_addr, SEEK_SET);
//Ö¸Ïò¶ÎÍ·½á¹¹Ìå´æ´¢µÄÊ×µØÖ·
close(fd);
return 0;
}
#endif
//´ÓÎļþ´ò¿ªELF
struct ElfHandle *openElfByFile(const char *path);
//ÊÍ·Å×ÊÔ´
void closeElfByFile( ElfHandle *handle);
//´Ó¸ø¶¨µÄsoÖлñÈ¡»ùÖ·,Èç¹ûsonameΪNULL,Ôò±íʾµ±Ç°½ø³Ì×ÔÉí
ElfHandle *openElfBySoname(const char *soname);
//ÊÍ·Å×ÊÔ´
void closeElfBySoname(struct ElfHandle *handle);
//elf¹Ø¼üÐÅÏ¢
struct ElfInfo{
const ElfHandle *handle;
uint8_t *elf_base;
Elf32_Ehdr *ehdr;
Elf32_Phdr *phdr;
Elf32_Shdr *shdr;
Elf32_Dyn *dyn;
Elf32_Word dynsz;
Elf32_Sym *sym;
Elf32_Word symsz;
Elf32_Rel *relplt;
Elf32_Word relpltsz;
Elf32_Rel *reldyn;
Elf32_Word reldynsz;
uint32_t nbucket;
uint32_t nchain;
uint32_t *bucket;
uint32_t *chain;
const char *shstr;
const char *symstr;
};
//·ûºÅhashº¯Êý
unsigned elf_hash(const char *name);
//´ÓsectionÊÓͼ»ñÈ¡info
void getElfInfoBySectionView(struct ElfInfo *info, const ElfHandle *handle);
//´ÓsegmentÊÓͼ»ñÈ¡info
void getElfInfoBySegmentView(struct ElfInfo *info, const ElfHandle *handle);
//¸ù¾Ý·ûºÅÃûÑ°ÕÒSym
void findSymByName(struct ElfInfo *info, const char *symbol, Elf32_Sym **sym, int *symidx);
//´òÓ¡sectionÐÅÏ¢
void printSections(struct ElfInfo *info);
//´òÓ¡segmentÐÅÏ¢
void printSegments(struct ElfInfo *info);
//´òÓ¡dynamicÐÅÏ¢
void printfDynamics(struct ElfInfo *info);
//´òÓ¡ËùÓзûºÅÐÅÏ¢
void printfSymbols(struct ElfInfo *info);
//´òÓ¡Öض¨Î»ÐÅÏ¢
void printfRelInfo(struct ElfInfo *info);
void printfRelInfo(struct ElfInfo *info)
{
int i,j;
Elf32_Rel* rels[] = {info->reldyn, info->relplt};
Elf32_Word resszs[] = {info->reldynsz, info->relpltsz};
Elf32_Sym *sym = info->sym;
LOGI("rel section info:\n");
for( i=0; i<sizeof(rels)/sizeof(rels[0]); i++){
Elf32_Rel *rel = rels[i];
Elf32_Word relsz = resszs[i];
for(j=0; j<relsz; j++){
const char *name = sym[ELF32_R_SYM(rel[j].r_info)].st_name + info->symstr;
LOGI("[%.2d-%.4d] 0x%-.8x 0x%-.8x %-10s\n", i, j, rel[j].r_offset, rel[j].r_info, name);
}
}
}
struct ElfHandle *openElfByFile(const char *path) {
void *base = NULL;
ElfHandle *handle = NULL;
//´Ë´¦Ò»¶¨²»ÄÜÊÇstruct ElfHandle1 *handle = NULL;
//·ñÔò»á±¨dereferencing pointer to incomplete type
int fd = open(path, O_RDWR);
if (fd < 0) {
LOGE("[-] open %s fails.\n", path);
exit(-1);
}
struct stat fs;
fstat(fd, &fs);
base = mmap(NULL, fs.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (base == MAP_FAILED) {
LOGE("[-] mmap fails.\n");
exit(-1);
}
close(fd);
handle = ( ElfHandle *) malloc(sizeof( ElfHandle));
handle->base = base;
handle->space_size = fs.st_size;
handle->fromfile = 1;
return handle;
}
void closeElfByFile(ElfHandle *handle) {
unsigned char * temp;
if (handle) {
temp = (unsigned char * )(handle->base);
if ( temp && handle->space_size > 0) {
msync(handle->base, handle->space_size, MS_SYNC);
munmap(handle->base, handle->space_size);
free(handle);
}
}
}
//²éÕÒsonameµÄ»ùÖ·,Èç¹ûΪNULL,ÔòΪµ±Ç°½ø³Ì»ùÖ·
static void *findLibBase(const char *soname) {
FILE *fd = fopen("/proc/self/maps", "r");
char line[256];
void *base = 0;
while (fgets(line, sizeof(line), fd) != NULL) {
if (soname == NULL || strstr(line, soname)) {
line[8] = '\0';
base = (void *) strtoul(line, NULL, 16);
break;
}
}
fclose(fd);
return base;
}
//´Ó¸ø¶¨µÄsoÖлñÈ¡»ùÖ·
ElfHandle *openElfBySoname(const char *soname)
{
void *base = findLibBase(soname);
if(!base){
LOGE("[-] could find %s. \n", soname);
exit(-1);
}
ElfHandle *handle = (ElfHandle *) malloc(sizeof(ElfHandle));
handle->base = base;
LOGE( "base = %x.\n", base );
handle->space_size = -1;
handle->fromfile = 0;
return handle;
}
//ÊÍ·Å×ÊÔ´
void closeElfBySoname(struct ElfHandle *handle){
//only free the base
free(handle);
}
//#define LIBSF_PATH "/system/lib/libsurfaceflinger.so"
//#define LIBSF_PATH "/system/lib/libtest_hello.so"
#ifndef PT_ARM_EXIDX
#define PT_ARM_EXIDX 0x70000001
#endif
//comm_spi_data_send_and_rev
//extern comm_spi_data_send_and_rev;
int hook_eglSwapBuffers()
{
old_eglSwapBuffers = eglSwapBuffers;
//old_eglSwapBuffers = comm_spi_data_send_and_rev;
//LOGD("Orig eglSwapBuffers = %p\n", old_eglSwapBuffers);
void * base_addr = get_module_base(getpid(), LIBSF_PATH);
// LOGD("libsurfaceflinger.so address = %p\n", base_addr);
int fd;
fd = open(LIBSF_PATH, O_RDONLY);
if (-1 == fd) {
LOGD("error\n");
return -1;
}
Elf32_Ehdr ehdr;
read(fd, &ehdr, sizeof(Elf32_Ehdr));
//macdbg_dmphex(&ehdr, sizeof(Elf32_Ehdr));
unsigned long shdr_addr = ehdr.e_shoff;
int shnum = ehdr.e_shnum;
int shent_size = ehdr.e_shentsize;
unsigned long stridx = ehdr.e_shstrndx;
Elf32_Shdr shdr;
//my_printf( "shdr_addr = %x\n", shdr_addr );
//my_printf( "stridx = %x\n", stridx );
//my_printf( "shent_size = %x\n", shent_size );
lseek(fd, shdr_addr + stridx * shent_size, SEEK_SET);
read(fd, &shdr, shent_size);
char * string_table = (char *)malloc(shdr.sh_size);
//my_printf( "string_table = %x\n", string_table );
//my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
//my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
lseek(fd, shdr.sh_offset, SEEK_SET);
read(fd, string_table, shdr.sh_size);
lseek(fd, shdr_addr, SEEK_SET);
int i,j,k,l;
uint32_t out_addr = 0;
uint32_t out_size = 0;
uint32_t got_item = 0, get_off=0;
int32_t got_found = 0;
//my_printf( "shnum = %x\n", shnum );
for (k = 0; k < shnum; k++) {
read(fd, &shdr, shent_size);
int name_idx = shdr.sh_name;
//my_printf( "shdr.sh_type = %x\n", shdr.sh_type );
if (shdr.sh_type == SHT_PROGBITS) {
//my_printf( "name_idx = %x\n", name_idx );
//my_printf( "string_table[name_idx] = %s\n", &string_table[name_idx] );
if (strcmp(&(string_table[name_idx]), ".got.plt") == 0 ||
strcmp(&(string_table[name_idx]), ".got") == 0) {
out_addr = base_addr + shdr.sh_addr;
out_size = shdr.sh_size;
//LOGD("out_addr = %lx, out_size = %lx\n", out_addr, out_size);
//my_printf("base_addr = %lx, shdr.sh_addr = %lx\n", base_addr, shdr.sh_addr);
for( j = 0; j < out_size; j += 4 ){
get_off = *(int32_t *)(out_addr+j);
//my_printf( "get_off.0 = %x\n", get_off );
//if(j>0x100)
my_printf( "get_off.1 = %x\n", get_off - (uint32_t)base_addr );
}
#if 0
for (i = 0; i < out_size; i += 4) {
got_item = *(uint32_t *)(out_addr + i);
if (got_item == old_eglSwapBuffers) {
LOGD("Found eglSwapBuffers in got\n");
got_found = 1;
uint32_t page_size = getpagesize();
uint32_t entry_page_start = (out_addr + i) & (~(page_size - 1));
mprotect((uint32_t *)entry_page_start, page_size, PROT_READ | PROT_WRITE);
*(uint32_t *)(out_addr + i) = new_eglSwapBuffers;
break;
} else if (got_item == new_eglSwapBuffers) {
LOGD("Already hooked\n");
break;
}
}
if (got_found) {
//break;
}
#endif
}
}else if (shdr.sh_type == PT_ARM_EXIDX) {
//Section header table entry unused
//µÚÒ»¸ö¶ÎÍ·±íÈë¿ÚΪ¿Õ
//my_printf( "macdbg_dmphex = %x\n", macdbg_dmphex );
//my_printf( "old_funpoint = %x\n", old_funpoint );
//my_printf( "new_funpoint = %x\n", new_funpoint );
//my_printf( "hello_get_module_base = %x\n", hello_get_module_base );
//my_printf( "hook_hello = %x\n", hook_hello );
//my_printf( "main = %x\n", main );
//my_printf( "my_tgkill = %x\n", my_tgkill );
//my_printf( "get .ARM.exidx\n" );
//my_printf( "string_table[name_idx] = %s\n", &string_table[name_idx] );
//my_printf( "shdr.sh_addr = %x\n", shdr.sh_addr );
//my_printf( "shdr.sh_offset = %x\n", shdr.sh_offset );
//my_printf( "shdr.sh_size = %x\n", shdr.sh_size );
//my_printf( "shdr.sh_entsize = %x\n", shdr.sh_entsize );
out_addr = base_addr + shdr.sh_addr;
out_size = shdr.sh_size;
// my_printf("out_addry = %lx, out_size = %lx\n", out_addr, out_size);
// my_printf("shdr.sh_addry = %lx, base_addr = %lx\n", shdr.sh_addr, base_addr);
for( i = 0; i < out_size; i += 8 ){
get_off = *(int32_t *)(out_addr+i);
got_item = *(uint32_t *)(out_addr + i + 4);
uint32_t fun_offset,fun_addr;
//my_printf( "get_off = %x\n", get_off );
//my_printf( "got_item = %x\n", got_item );
//my_printf( "get_off1 = %x\n", shdr.sh_addr - (~get_off +1)&0xffff )+i;
//my_printf( "func point.0 = %x\n", shdr.sh_addr + i - ((~get_off +1)&0xfffffff) + base_addr );
//my_printf( "func point.1 = %x\n", shdr.sh_addr + i - ((~get_off +1)&0xfffffff) + base_addr - base_addr );
fun_offset = shdr.sh_addr + i - ((~get_off +1)&0xfffffff);
fun_addr = fun_offset + base_addr;
my_printf( "fun_offset = %x\n", fun_offset );
my_printf( "fun_addr = %x\n", fun_addr );
if( fun_offset == 0xea4 ){
macdbg_dmphex(fun_addr, 100);
}
//shdr.sh_addr + i ÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÆ«ÒÆλÖõÄÐéÄâµØÖ·
//*(shdr.sh_addr + i)ÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÆ«ÒÆλÖÃ
//(Ïà¶ÔÓÚÃèÊöº¯ÊýÖ¸ÕëµÄÐéÄâµØÖ·µÄÐéÄâµØÖ·) Ϊ¸ºÊý
//base_addr ¸Ã½ø³ÌÄÚºËÄÚ´æÓ³ÉäµÄ»ùµØÖ·
//my_printf( "got_item = %x\n\n", got_item );
//my_printf( "got_item = %d\n", got_item );
}
}else{
//my_printf( "name_idx1 = %x\n", name_idx );
// my_printf( "string_table[name_idx]1 = %s\n", &string_table[name_idx] );
}
}
free(string_table);
close(fd);
return 0;
}
#define DEVICE_COM "/dev/ttyS0"
void init_ttyS(int fd)
{
struct termios options;
memset( &options, 0, sizeof(options) );
cfsetispeed( &options, B115200 );
cfsetospeed( &options, B115200 );
options.c_cflag |=(CS8|CLOCAL|CREAD);
options.c_iflag &=IGNPAR;
options.c_lflag &= ~ICANON;
//raw Added by czj²»µÈ»Ø³µÊäÈë
options.c_lflag &= ~ECHO;
//raw Added by czj²»»ØÏÔ
tcflush(fd,TCIFLUSH);
tcsetattr(fd, TCSANOW, &options);
//fcntl(fd, F_SETFL, 0);
}
int com_appstart(void)
{
int fd;
//fd = open( DEVICE_COM, O_RDWR|O_NOCTTY|O_NONBLOCK );
fd = open( DEVICE_COM, O_RDWR |O_NOCTTY|O_NONBLOCK);
if( fd == -1 ){
perror("open DEVICE_COM");
}else{
//init_ttyS( fd );
}
//fcntl(fd,F_SETFL,0);
return fd;
}
#define SAFE_SET_VALUE(t, v) if(t) *(t) = (v)
static inline Elf32_Shdr *findSectionByName(struct ElfInfo *info, const char *sname){
Elf32_Shdr *target = NULL;
int i;
Elf32_Shdr *shdr = info->shdr;
for( i=0; i<info->ehdr->e_shnum; i++){
const char *name = (const char *)(shdr[i].sh_name + info->shstr);
if(!strncmp(name, sname, strlen(sname))){
target = (Elf32_Shdr *)(shdr + i);
break;
}
}
return target;
}
static inline void getSectionInfo(struct ElfInfo *info, const char *name, Elf32_Word *pSize, Elf32_Shdr **ppShdr, void **data){
Elf32_Shdr *_shdr = findSectionByName(info, name);
if(_shdr){
SAFE_SET_VALUE(pSize, _shdr->sh_size / _shdr->sh_entsize);
//SAFE_SET_VALUE(data, reinterpret_cast<T>(info.elf_base + _shdr->sh_offset));
SAFE_SET_VALUE(data, (info->elf_base + _shdr->sh_offset) );
//if(data) *(data) = (123);
}else{
LOGE("[-] Could not found section %s\n", name);
exit(-1);
}
SAFE_SET_VALUE(ppShdr, _shdr);
}
static inline Elf32_Phdr *findSegmentByType(struct ElfInfo *info, const Elf32_Word type){
Elf32_Phdr *target = NULL;
Elf32_Phdr *phdr = info->phdr;
int i;
for( i=0; i<info->ehdr->e_phnum; i++){
if(phdr[i].p_type == type){
target = phdr + i;
break;
}
}
return target;
}
static void getSegmentInfo( struct ElfInfo *info, const Elf32_Word type, Elf32_Phdr **ppPhdr,
Elf32_Word *pSize, Elf32_Dyn **data){
Elf32_Phdr *_phdr = findSegmentByType(info, type);
if(_phdr){
if(info->handle->fromfile){ //Îļþ¶ÁÈ¡
//SAFE_SET_VALUE(data, reinterpret_cast<T>(info.elf_base + _phdr->p_offset));
SAFE_SET_VALUE(data, (info->elf_base + _phdr->p_offset));
SAFE_SET_VALUE(pSize, _phdr->p_filesz);
}else{ //´ÓÄÚ´æ¶ÁÈ¡
//SAFE_SET_VALUE(data, reinterpret_cast<T>(info.elf_base + _phdr->p_vaddr));
SAFE_SET_VALUE(data, (info->elf_base + _phdr->p_vaddr) );
SAFE_SET_VALUE(pSize, _phdr->p_memsz);
}
}else{
LOGE("[-] Could not found segment type is %d\n", type);
exit(-1);
}
SAFE_SET_VALUE(ppPhdr, _phdr);
}
void getElfInfoBySegmentView(struct ElfInfo *info, const ElfHandle *handle){
int i=0;
info->handle = handle;
info->elf_base = (uint8_t *) handle->base;
LOGE( "info->handle = %x.\n", info->handle );
LOGE( "info->elf_base = %x.\n", info->elf_base );
//info->ehdr = reinterpret_cast<Elf32_Ehdr *>(info.elf_base);
info->ehdr = (Elf32_Ehdr *)info->elf_base;
LOGE( "info->ehdr = %x.\n", info->ehdr );
// may be wrong
info->shdr = (Elf32_Shdr *)(info->elf_base + info->ehdr->e_shoff);
info->phdr = (Elf32_Phdr *)(info->elf_base + info->ehdr->e_phoff);
//info.shdr = reinterpret_cast<Elf32_Shdr *>(info.elf_base + info.ehdr->e_shoff);
//info.phdr = reinterpret_cast<Elf32_Phdr *>(info.elf_base + info.ehdr->e_phoff);
info->shstr = NULL;
Elf32_Phdr *dynamic = NULL;
Elf32_Word size = 0;
uint32_t *rawdata = NULL;
getSegmentInfo(info, PT_DYNAMIC, &dynamic, &size, &info->dyn);
if(!dynamic){
LOGE("[-] could't find PT_DYNAMIC segment");
exit(-1);
}
info->dynsz = size / sizeof(Elf32_Dyn);
Elf32_Dyn *dyn = info->dyn;
for(i=0; i<info->dynsz; i++, dyn++){
switch(dyn->d_tag){
case DT_SYMTAB:
info->sym = (Elf32_Sym *)(info->elf_base + dyn->d_un.d_ptr);
break;
case DT_STRTAB:
info->symstr = (const char *)(info->elf_base + dyn->d_un.d_ptr);
break;
case DT_REL:
info->reldyn = (Elf32_Rel *)(info->elf_base + dyn->d_un.d_ptr);
break;
case DT_RELSZ:
info->reldynsz = dyn->d_un.d_val / sizeof(Elf32_Rel);
break;
case DT_JMPREL:
info->relplt = (Elf32_Rel *)(info->elf_base + dyn->d_un.d_ptr);
break;
case DT_PLTRELSZ:
info->relpltsz = dyn->d_un.d_val / sizeof(Elf32_Rel);
break;
case DT_HASH:
rawdata = (uint32_t *)(info->elf_base + dyn->d_un.d_ptr);
info->nbucket = rawdata[0];
info->nchain = rawdata[1];
info->bucket = rawdata + 2;
info->chain = info->bucket + info->nbucket;
info->symsz = info->nchain;
break;
}
}
}
unsigned elf_hash(const char *name) {
const unsigned char *tmp = (const unsigned char *) name;
unsigned h = 0, g;
while (*tmp) {
h = (h << 4) + *tmp++;
g = h & 0xf0000000;
h ^= g;
h ^= g >> 24;
}
return h;
}
void findSymByName(struct ElfInfo *info, const char *symbol, Elf32_Sym **sym, int *symidx) {
Elf32_Sym *target = NULL;
unsigned hash = elf_hash(symbol);
uint32_t index = info->bucket[hash % info->nbucket];
if (!strcmp(info->symstr + info->sym[index].st_name, symbol)) {
target = info->sym + index;
}
if (!target) {
do {
index = info->chain[index];
if (!strcmp(info->symstr + info->sym[index].st_name, symbol)) {
target = info->sym + index;
break;
}
} while (index != 0);
}
if(target){
SAFE_SET_VALUE(sym, target);
SAFE_SET_VALUE(symidx, index);
}
}
#define PAGE_START(addr) (~(getpagesize() - 1) & (addr))
static int modifyMemAccess(void *addr, int prots){
void *page_start_addr = (void *)PAGE_START((uint32_t)addr);
return mprotect(page_start_addr, getpagesize(), prots);
}
static int clearCache(void *addr, size_t len){
void *end = (uint8_t *)addr + len;
syscall(0xf0002, addr, end);
return 0;
}
static int replaceFunc(void *addr, void *replace_func, void **old_func){
int res = 0;
if(*(void **)addr == replace_func){
LOGE("addr %p had been replace.\n", addr);
goto fails;
}
if(!*old_func){
*old_func = *(void **)addr;
}
if(modifyMemAccess((void *)addr, PROT_EXEC|PROT_READ|PROT_WRITE)){
LOGE("[-] modifymemAccess fails, error %s.", strerror(errno));
res = 1;
goto fails;
}
*(void **)addr = replace_func;
clearCache(addr, getpagesize());
LOGI("[+] old_func is %p, replace_func is %p, new_func %p.\n", *old_func, replace_func, *(uint32_t *)addr);
fails:
return res;
}
//#define R_ARM_ABS32 0x02
//#define R_ARM_GLOB_DAT 0x15
//#define R_ARM_JUMP_SLOT 0x16
int elfHook(const char *soname, const char *symbol, void *replace_func, void **old_func){
//assert(old_func);
//assert(replace_func);
//assert(symbol);
int i;
ElfHandle* handle = openElfBySoname(soname);
struct ElfInfo info;
Elf32_Rel rel;
getElfInfoBySegmentView(&info, handle);
Elf32_Sym *sym = NULL;
int symidx = 0;
findSymByName(&info, symbol, &sym, &symidx);
if(!sym){
LOGE("[-] Could not find symbol %s\n", symbol);
goto fails;
}else{
LOGI("[+] sym %p, symidx %d.\n", sym, symidx);
}
for (i = 0; i < info.relpltsz; i++) {
rel = info.relplt[i];
if (ELF32_R_SYM(rel.r_info) == symidx && ELF32_R_TYPE(rel.r_info) == R_ARM_JUMP_SLOT) {
LOGI("op 1.\n");
void *addr = (void *) (info.elf_base + rel.r_offset);
if (replaceFunc(addr, replace_func, old_func))
goto fails;
//only once
break;
}
}
for (i = 0; i < info.reldynsz; i++) {
rel = info.reldyn[i];
if (ELF32_R_SYM(rel.r_info) == symidx &&
(ELF32_R_TYPE(rel.r_info) == R_ARM_ABS32
|| ELF32_R_TYPE(rel.r_info) == R_ARM_GLOB_DAT)) {
LOGI("op 2.\n");
void *addr = (void *) (info.elf_base + rel.r_offset);
if (replaceFunc(addr, replace_func, old_func))
goto fails;
}
}
fails:
closeElfBySoname(handle);
return 0;
}
int hook_entry1(char * a)
{
//
g_com_fd = com_appstart();
my_printf( "g_com_fd = %d\n", g_com_fd );
my_printf( "in hook_entry2, param is %s\n", a );
//hook_eglSwapBuffers();
//write(g_com_fd,"stdout\n",7);
ElfHandle* handle = openElfBySoname(LIBSF_PATH);
struct ElfInfo info;
getElfInfoBySegmentView(&info, handle);
Elf32_Sym *sym = NULL;
int symidx = 0;
//findSymByName(&info, "strlen", &sym, &symidx);
findSymByName(&info, "test_fun0", &sym, &symidx);
if(!sym){
LOGE("[-] Could not find symbol %s", "strlen");
goto fails;
}else{
LOGI("[+] sym %p, symidx %d.", sym, symidx);
}
fails:
my_printf( "mypid = %d\n", getpid() );
my_printf("gogogogogogo234!\n");
close(g_com_fd);
return 0;
}
typedef int (*strlen_fun)(const char *);
strlen_fun old_strlen = NULL;
size_t my_strlen(const char *str){
LOGI("strlen was called 1111111111111111111111.\n");
int len = old_strlen(str);
return len * 4;
}
strlen_fun global_strlen1 = (strlen_fun)strlen;
strlen_fun global_strlen2 = (strlen_fun)strlen;
#define SHOW(x) LOGI("%s is %d\n", #x, x)
//extern "C" jint Java_com_example_allhookinone_HookUtils_elfhook(JNIEnv *env, jobject thiz){
int hook_entry(char * a)
{
const char *str = "helloworld";
g_com_fd = com_appstart();
my_printf( "g_com_fd = %d\n", g_com_fd );
my_printf( "in hook_entry2, param is %s\n", a );
strlen_fun local_strlen1 = (strlen_fun)strlen;
strlen_fun local_strlen2 = (strlen_fun)strlen;
int len0 = global_strlen1(str);
int len1 = global_strlen2(str);
int len2 = local_strlen1(str);
int len3 = local_strlen2(str);
int len4 = strlen(str);
int len5 = strlen(str);
LOGI( "global_strlen1 = %p\n", global_strlen1 );
LOGI( "global_strlen2 = %p\n", global_strlen2 );
LOGI( "local_strlen1 = %p\n", local_strlen1 );
LOGI( "local_strlen2 = %p\n", local_strlen2 );
LOGI( "strlen = %p\n", strlen );
LOGI("hook before:\n");
SHOW(len0);
SHOW(len1);
SHOW(len2);
SHOW(len3);
SHOW(len4);
SHOW(len5);
//elfHook("libonehook.so", "strlen", (void *)my_strlen, (void **)&old_strlen);
elfHook(LIBSF_PATH, "strlen", (void *)my_strlen, (void **)&old_strlen);
LOGI( "global_strlen1 = %p\n", global_strlen1 );
LOGI( "global_strlen2 = %p\n", global_strlen2 );
LOGI( "local_strlen1 = %p\n", local_strlen1 );
LOGI( "local_strlen2 = %p\n", local_strlen2 );
LOGI( "strlen = %p\n", strlen );
len0 = global_strlen1(str);
len1 = global_strlen2(str);
len2 = local_strlen1(str);
len3 = local_strlen2(str);
len4 = strlen(str);
len5 = strlen(str);
LOGI("hook after:");
SHOW(len0);
SHOW(len1);
SHOW(len2);
SHOW(len3);
SHOW(len4);
SHOW(len5);
close(g_com_fd);
return 0;
}
inject.c -->自己的hook程序
#include <stdio.h>
#include <stdlib.h>
#include <asm/user.h>
#include <asm/ptrace.h>
#include <sys/ptrace.h>
#include <sys/wait.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <dirent.h>
#include <unistd.h>
#include <string.h>
#include <elf.h>
#include <android/log.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <dlfcn.h>
#include <cutils/compiler.h>
#include <cutils/properties.h>
#include <utils/Log.h>
//#include "AudioResamplerSinc.h"
#if defined(__i386__)
xxxxxxxxxxxxx
#define pt_regs user_regs_struct
#endif
#define ENABLE_DEBUG 1
#if ENABLE_DEBUG
#define LOG_TAG "INJECT"
//#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)
#define LOGD(fmt, args...) printf(ANDROID_LOG_DEBUG,LOG_TAG, fmt, ##args)
//dddd
#define DEBUG_PRINT(format,args...) \
LOGD(format, ##args)
#else
#define DEBUG_PRINT(format,args...)
#endif
#define CPSR_T_MASK ( 1u << 5 )
const char *libc_path = "/system/lib/libc.so";
const char *linker_path = "/system/bin/linker";
int ptrace_readdata(pid_t pid, uint8_t *src, uint8_t *buf, size_t size)
{
uint32_t i, j, remain;
uint8_t *laddr;
union u {
long val;
char chars[sizeof(long)];
} d;
j = size / 4;
remain = size % 4;
laddr = buf;
for (i = 0; i < j; i ++) {
d.val = ptrace(PTRACE_PEEKTEXT, pid, src, 0);
memcpy(laddr, d.chars, 4);
src += 4;
laddr += 4;
}
if (remain > 0) {
d.val = ptrace(PTRACE_PEEKTEXT, pid, src, 0);
memcpy(laddr, d.chars, remain);
}
return 0;
}
int ptrace_writedata(pid_t pid, uint8_t *dest, uint8_t *data, size_t size)
{
uint32_t i, j, remain;
uint8_t *laddr;
union u {
long val;
char chars[sizeof(long)];
} d;
j = size / 4;
remain = size % 4;
laddr = data;
//printf( "j = %x\n", j);
//printf( "remain = %x\n", remain );
//printf( "laddr = %x\n", laddr );
for (i = 0; i < j; i ++) {
memcpy(d.chars, laddr, 4);
ptrace(PTRACE_POKETEXT, pid, dest, d.val);
dest += 4;
laddr += 4;
}
if (remain > 0) {
d.val = ptrace(PTRACE_PEEKTEXT, pid, dest, 0);
//printf( "d.val = %x\n", d.val );
for (i = 0; i < remain; i ++) {
d.chars[i] = *laddr ++;
}
//printf( "d.val = %x\n", d.val );
ptrace(PTRACE_POKETEXT, pid, dest, d.val);
}
return 0;
}
#if defined(__arm__)
int ptrace_call(pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct pt_regs* regs)
{
uint32_t i;
for (i = 0; i < num_params && i < 4; i ++) {
regs->uregs[i] = params[i];
}
//
// push remained params onto stack
//
if (i < num_params) {
regs->ARM_sp -= (num_params - i) * sizeof(long) ;
ptrace_writedata(pid, (void *)regs->ARM_sp, (uint8_t *)¶ms[i], (num_params - i) * sizeof(long));
}
regs->ARM_pc = addr;
if (regs->ARM_pc & 1) {
/* thumb */
regs->ARM_pc &= (~1u);
regs->ARM_cpsr |= CPSR_T_MASK;
} else {
/* arm */
regs->ARM_cpsr &= ~CPSR_T_MASK;
}
regs->ARM_lr = 0;
if (ptrace_setregs(pid, regs) == -1
|| ptrace_continue(pid) == -1) {
printf("error\n");
return -1;
}
int stat = 0;
waitpid(pid, &stat, WUNTRACED);
while (stat != 0xb7f) {
if (ptrace_continue(pid) == -1){
printf("error\n");
return -1;
}
waitpid(pid, &stat, WUNTRACED);
}
return 0;
}
#elif defined(__i386__)
long ptrace_call(pid_t pid, uint32_t addr, long *params, uint32_t num_params, struct user_regs_struct * regs)
{
regs->esp -= (num_params) * sizeof(long) ;
ptrace_writedata(pid, (void *)regs->esp, (uint8_t *)params, (num_params) * sizeof(long));
long tmp_addr = 0x00;
regs->esp -= sizeof(long);
ptrace_writedata(pid, regs->esp, (char *)&tmp_addr, sizeof(tmp_addr));
regs->eip = addr;
if (ptrace_setregs(pid, regs) == -1
|| ptrace_continue( pid) == -1) {
printf("error\n");
return -1;
}
   int stat = 0;
   waitpid(pid, &stat, WUNTRACED);
   while (stat != 0xb7f) {
       if (ptrace_continue(pid) == -1) {
           printf("error\n");
           return -1;
       }
       waitpid(pid, &stat, WUNTRACED);
   }
return 0;
}
#else
#error "Not supported"
#endif
int ptrace_getregs(pid_t pid, struct pt_regs * regs)
{
if (ptrace(PTRACE_GETREGS, pid, NULL, regs) < 0) {
perror("ptrace_getregs: Can not get register values");
return -1;
}
return 0;
}
int ptrace_setregs(pid_t pid, struct pt_regs * regs)
{
if (ptrace(PTRACE_SETREGS, pid, NULL, regs) < 0) {
perror("ptrace_setregs: Can not set register values");
return -1;
}
return 0;
}
int ptrace_continue(pid_t pid)
{
if (ptrace(PTRACE_CONT, pid, NULL, 0) < 0) {
perror("ptrace_cont");
return -1;
}
return 0;
}
int ptrace_attach(pid_t pid)
{
if (ptrace(PTRACE_ATTACH, pid, NULL, 0) < 0) {
perror("ptrace_attach");
return -1;
}
int status = 0;
waitpid(pid, &status , WUNTRACED);
return 0;
}
int ptrace_detach(pid_t pid)
{
if (ptrace(PTRACE_DETACH, pid, NULL, 0) < 0) {
perror("ptrace_detach");
return -1;
}
return 0;
}
void* get_module_base(pid_t pid, const char* module_name)
{
FILE *fp;
long addr = 0;
char *pch;
char filename[32];
char line[1024];
if (pid < 0) {
/* self process */
snprintf(filename, sizeof(filename), "/proc/self/maps", pid);
} else {
snprintf(filename, sizeof(filename), "/proc/%d/maps", pid);
}
fp = fopen(filename, "r");
//printf("filename = %s\n", filename);
if (fp != NULL) {
while (fgets(line, sizeof(line), fp)) {
if (strstr(line, module_name)) {
//printf("line = %s\n", line);
pch = strtok( line, "-" );
addr = strtoul( pch, NULL, 16 );
if (addr == 0x8000)
addr = 0;
break;
}
}
fclose(fp) ;
}
return (void *)addr;
}
void* get_remote_addr(pid_t target_pid, const char* module_name, void* local_addr)
{
void* local_handle, *remote_handle;
local_handle = get_module_base(-1, module_name);
remote_handle = get_module_base(target_pid, module_name);
//printf("[+] get_remote_addr: local[%x], remote[%x]\n", local_handle, remote_handle);
//printf("[+] get_remote_addr: local_addr[%x], local_addr[%x]\n", local_addr, local_addr);
void * ret_addr = (void *)((uint32_t)local_addr + (uint32_t)remote_handle - (uint32_t)local_handle);
#if defined(__i386__)
if (!strcmp(module_name, libc_path)) {
ret_addr += 2;
}
#endif
return ret_addr;
}
int find_pid_of(const char *process_name)
{
int id;
pid_t pid = -1;
DIR* dir;
FILE *fp;
char filename[32];
char cmdline[256];
struct dirent * entry;
if (process_name == NULL)
return -1;
dir = opendir("/proc");
if (dir == NULL)
return -1;
while((entry = readdir(dir)) != NULL) {
id = atoi(entry->d_name);
//printf("entry->d_name = %s.\n", entry->d_name);
//printf("id = %d.\n", id);
if (id != 0) {
sprintf(filename, "/proc/%d/cmdline", id);
fp = fopen(filename, "r");
if (fp) {
fgets(cmdline, sizeof(cmdline), fp);
fclose(fp);
if (strcmp(process_name, cmdline) == 0) {
/* process found */
pid = id;
break;
}
}
}
}
closedir(dir);
return pid;
}
long ptrace_retval(struct pt_regs * regs)
{
#if defined(__arm__)
return regs->ARM_r0;
#elif defined(__i386__)
xxxxxx
return regs->eax;
#else
vvxxxxxx
#error "Not supported"
#endif
}
long ptrace_ip(struct pt_regs * regs)
{
#if defined(__arm__)
return regs->ARM_pc;
#elif defined(__i386__)
return regs->eip;
#else
#error "Not supported"
#endif
}
int ptrace_call_wrapper(pid_t target_pid, const char * func_name, void * func_addr, long * parameters, int param_num, struct pt_regs * regs)
{
printf("[+] Calling %s in target process.\n", func_name);
if (ptrace_call(target_pid, (uint32_t)func_addr, parameters, param_num, regs) == -1)
return -1;
if (ptrace_getregs(target_pid, regs) == -1)
return -1;
printf("[+] Target process returned from %s, return value=%x, pc=%x \n",
func_name, ptrace_retval(regs), ptrace_ip(regs));
return 0;
}
int inject_remote_process(pid_t target_pid, const char *library_path, const char *function_name, const char *param, size_t param_size)
{
int ret = -1;
void *mmap_addr, *dlopen_addr, *dlsym_addr, *dlclose_addr, *dlerror_addr;
void *local_handle, *remote_handle, *dlhandle;
uint8_t *map_base = 0;
uint8_t *dlopen_param1_ptr, *dlsym_param2_ptr, *saved_r0_pc_ptr, *inject_param_ptr, *remote_code_ptr, *local_code_ptr;
struct pt_regs regs, original_regs;
extern uint32_t _dlopen_addr_s, _dlopen_param1_s, _dlopen_param2_s, _dlsym_addr_s, \
_dlsym_param2_s, _dlclose_addr_s, _inject_start_s, _inject_end_s, _inject_function_param_s, \
_saved_cpsr_s, _saved_r0_pc_s;
uint32_t code_length;
long parameters[10];
printf("[+] Injecting process: %d\n", target_pid);
if (ptrace_attach(target_pid) == -1){
//½á»é
goto exit;
}
if (ptrace_getregs(target_pid, ®s) == -1){
//»éÇ°²Æ²ú¹«Ö¤
goto exit;
}
//save original registers
memcpy(&original_regs, ®s, sizeof(regs));
//ΪÀë»é×ö×¼±¸
mmap_addr = get_remote_addr(target_pid, libc_path, (void *)mmap);
printf("[+] Remote mmap address: %x\n", mmap_addr);
//»ñÈ¡mmapº¯ÊýµÄÖ´ÐÐÐéµØÖ·
//call mmap
parameters[0] = 0;
//addr
parameters[1] = 0x4000;
//size
parameters[2] = PROT_READ | PROT_WRITE | PROT_EXEC;
//prot
parameters[3] = MAP_ANONYMOUS | MAP_PRIVATE;
//flags
parameters[4] = 0;
//fd
parameters[5] = 0;
//offset
if( ptrace_call_wrapper(target_pid, "mmap", mmap_addr, parameters, 6, ®s) == -1 ){
goto exit;
}
map_base = ptrace_retval(®s);
printf( "map_base: %x\n", map_base );
dlopen_addr = get_remote_addr( target_pid, linker_path, (void *)dlopen );
dlsym_addr = get_remote_addr( target_pid, linker_path, (void *)dlsym );
dlclose_addr = get_remote_addr( target_pid, linker_path, (void *)dlclose );
dlerror_addr = get_remote_addr( target_pid, linker_path, (void *)dlerror );
printf("[+] Get imports: dlopen: %x, dlsym: %x, dlclose: %x, dlerror: %x\n",
dlopen_addr, dlsym_addr, dlclose_addr, dlerror_addr);
printf("library path = %s\n", library_path);
ptrace_writedata(target_pid, map_base, library_path, strlen(library_path) + 1);
parameters[0] = map_base;
parameters[1] = RTLD_NOW| RTLD_GLOBAL;
if( ptrace_call_wrapper(target_pid, "dlopen", dlopen_addr, parameters, 2, ®s) == -1 ){
//´ò¿ª¶¯Ì¬Á´½Ó¿â
goto exit;
}
void * sohandle = ptrace_retval(®s);
//·µ»Ø¶¯Ì¬Á´½Ó¿âµÄ¿ØÖƾä±ú
#define FUNCTION_NAME_ADDR_OFFSET 0x100
ptrace_writedata(target_pid, map_base + FUNCTION_NAME_ADDR_OFFSET, function_name, strlen(function_name) + 1);
//½«¹³×Óº¯ÊýµÄº¯ÊýÃûдÈëÄÚ´æ
parameters[0] = sohandle;
parameters[1] = map_base + FUNCTION_NAME_ADDR_OFFSET;
if( ptrace_call_wrapper(target_pid, "dlsym", dlsym_addr, parameters, 2, ®s) == -1 ){
//µ÷ÓÃϵͳº¯Êýdlsym,²ÎÊýΪ°üº¬¹³×Óº¯Êý¶¯Ì¬¿âµÄÊ×µØÖ·,¹³×Óº¯ÊýµÄÃû³Æ
goto exit;
}
void * hook_entry_addr = ptrace_retval(®s);
//Æä½á¹û¾ÍÊÇ·µ»Ø¹³×Óº¯ÊýµÄ¾ä±ú,¼´º¯ÊýµÄÖ´ÐеØÖ·
printf("hook_entry_addr = %p\n", hook_entry_addr);
#define FUNCTION_PARAM_ADDR_OFFSET 0x200
ptrace_writedata(target_pid, map_base + FUNCTION_PARAM_ADDR_OFFSET, param, strlen(param) + 1);
//½«Óûµ÷ÓõĹ³×Óº¯ÊýµÄ²ÎÊýдÈëÄÚ´æ
parameters[0] = map_base + FUNCTION_PARAM_ADDR_OFFSET;
if( ptrace_call_wrapper(target_pid, "hook_entry", hook_entry_addr, parameters, 1, ®s) == -1 ){
//µ÷Óù³×Óº¯Êý
goto exit;
}
printf("Press enter to dlclose and detach\n");
getchar();
//´Ó¿ØÖÆ̨»ñÈ¡Ò»¸ö×Ö·û
parameters[0] = sohandle;
if( ptrace_call_wrapper(target_pid, "dlclose", dlclose, parameters, 1, ®s) == -1 ){
//¹Ø±Õ¹³×Óº¯Êý¶¯Ì¬Á´½Ó¿â
goto exit;
}
//restore
ptrace_setregs(target_pid, &original_regs);
//¹é»¹½á»é½äÖ¸,»Ö¸´³ÌÐòÏÖ³¡
ptrace_detach(target_pid);
//ˑȎ
ret = 0;
exit:
return ret;
}
//dd
int main(int argc, char** argv) {
pid_t target_pid;
printf("inject.c main.\n");
//target_pid = find_pid_of("com.example.fengzi.xdntest");
//target_pid = find_pid_of("/system/bin/surfaceflinger");
//target_pid = find_pid_of("com.example.asus.myapplication");
target_pid = find_pid_of("/system/bin/rild");
if (-1 == target_pid) {
printf("Can't find the process\n");
return -1;
}
printf("target_pid = %d.\n", target_pid);
//target_pid = find_pid_of("/data/test");
//inject_remote_process(target_pid, "/data/libhello.so", "hook_entry", "I'm parameter!", strlen("I'm parameter!"));
//inject_remote_process(target_pid, "/system/lib/libtest_hello.so", "hook_entry", "I'm parameter!", strlen("I'm parameter!"));
inject_remote_process(target_pid, "/system/lib/libtest_hello.so", "hook_entry", "I'm parameter!", strlen("I'm parameter!"));
return 0;
}
inject hook "/system/bin/rild"进程
然后把lib_hello.so注入到该进程,
修改strlen的系统调用