elf hook c语言版本

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 *)&params[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, &regs) == -1){ 
        //»éÇ°²Æ²ú¹«Ö¤ 
        goto exit;  
    }
  
    //save original registers  
    memcpy(&original_regs, &regs, 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, &regs) == -1 ){  
        goto exit;  
    }  
    map_base = ptrace_retval(&regs);  
    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, &regs) == -1 ){ 
        //´ò¿ª¶¯Ì¬Á´½Ó¿â
        goto exit;  
    }
    void * sohandle = ptrace_retval(&regs);
    //·µ»Ø¶¯Ì¬Á´½Ó¿âµÄ¿ØÖƾä±ú
  
    #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, &regs) == -1 ){
        //µ÷ÓÃϵͳº¯Êýdlsym,²ÎÊýΪ°üº¬¹³×Óº¯Êý¶¯Ì¬¿âµÄÊ×µØÖ·,¹³×Óº¯ÊýµÄÃû³Æ
        goto exit;  
    } 
    void * hook_entry_addr = ptrace_retval(&regs);
    //Æä½á¹û¾ÍÊÇ·µ»Ø¹³×Óº¯ÊýµÄ¾ä±ú,¼´º¯ÊýµÄÖ´ÐеØÖ·
    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, &regs) == -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, &regs) == -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的系统调用







































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值