0

connect() システム コールをインターセプトし、独自のカスタム実装を使用したいと考えています。カスタム実装は、簡単にするためにログを出力するなどのアクションを実行してから、システム実装をさらに呼び出します。

PLT にパッチを適用するというアプローチの Audrey のブログを見ました。しかし残念なことに、再配置テーブルのアドレスを変更しようとすると、このコードがクラッシュします。

しばらくゴーグリングした後、これはすでに質問に答えています。しかし、ここで説明するアプローチでは、次のエラーが発生します。

***** ケース ラベルにジャンプ [-fpermissive] jni/test.cpp:107:20: エラー: 'uint32_t entry_page_start' の初期化を超えています jni/test.cpp:106:15: エラー: 'uint32_t page_size の初期化を超えています'*****

提案された変更の後のAndrey のブログからのフック呼び出しメソッドHereは、次のようになります。

int hook_call(char *soname, char *symbol, unsigned newval) {  
soinfo *si = NULL;  
Elf32_Rel *rel = NULL;  
Elf32_Sym *s = NULL;   
unsigned int sym_offset = 0;  
if (!soname || !symbol || !newval)  
 return 0;  
si = (soinfo*) dlopen(soname, 0);  
if (!si)  
 return 0;  
s = soinfo_elf_lookup(si, elfhash(symbol), symbol);  
if (!s)  
 return 0;  
sym_offset = s - si->symtab;  
rel = si->plt_rel;  
/* walk through reloc table, find symbol index matching one we've got */  
for (int i = 0; i < si->plt_rel_count; i++, rel++) {  
  unsigned type = ELF32_R_TYPE(rel->r_info);  
  unsigned sym = ELF32_R_SYM(rel->r_info);  
  unsigned reloc = (unsigned)(rel->r_offset + si->base);  
  unsigned oldval = 0;  
  if (sym_offset == sym) {  
   switch(type) {  
     case R_ARM_JUMP_SLOT:
      // YOUR LINES
      uint32_t page_size = getpagesize();
      uint32_t entry_page_start = reloc& (~(page_size - 1));
      mprotect((uint32_t *)entry_page_start, page_size, PROT_READ | PROT_WRITE);

      /* we do not have to read original value, but it would be good   
       idea to make sure it contains what we are looking for */  
     oldval = *(unsigned*) reloc;  
     *((unsigned*)reloc) = newval;  
     return 1;  
   default:  
     return 0;  
}  

私は何を間違っていますか、mProtect() メソッドを間違った場所に置いていますか? アンドレイのブログの助けを借りてそれをやった人はいますか? 他のアプローチはありますか?私はブロックされています。どんな助けでも大歓迎です。

4

1 に答える 1

2

エラーは mProtect() とは関係ありません。これは実際、コード スニペットを配置した場所とまったく同じです。これが私のコードで、正常に動作します:

void* hook_call(char *soname, char *symbol, void* newval) {
 soinfo *si = NULL;
   Elf32_Rel *rel = NULL;
   Elf32_Sym *s = NULL;
   unsigned int sym_offset = 0;
   if (!soname || !symbol || !newval)
      return 0;

   si = (soinfo*) dlopen(soname, RTLD_LAZY);
   if (!si)
    return 0;


   s = soinfo_elf_lookup(si, elfhash(symbol), symbol);
   if (!s)
     return 0;

   sym_offset = s - si->symtab;
   rel = si->plt_rel;


   const char *strtab = si->strtab;
   Elf32_Sym *symtab = si->symtab;

   /* walk through reloc table, find symbol index matching one we've got */
   int i;

   for (i = 0; i < si->plt_rel_count; i++, rel++) {
    unsigned type = ELF32_R_TYPE(rel->r_info);
    unsigned sym = ELF32_R_SYM(rel->r_info);
    unsigned reloc = (unsigned)(rel->r_offset + si->base);
    //unsigned oldval = 0;
    void* pOldFun;

    if (sym_offset == sym) {

     switch(type) {
       case R_ARM_JUMP_SLOT:
          //Set appropriate memory access rights
          uint32_t page_size = getpagesize();
          uint32_t entry_page_start = reloc& (~(page_size - 1));
          mprotect((uint32_t *)entry_page_start, page_size, PROT_READ | PROT_WRITE);

         pOldFun = (void *)*((unsigned *)reloc);

          *((unsigned int*)reloc)= (unsigned)newval;  

          return pOldFun;
       default:
          return 0;
     }
    }
   }
   return 0;

}

*jump to case label ... error: crosses initialization は通常、switch ケースを使用するときに変数が正しく初期化されていない場合に発生します。つまり、あるケースで初期化され、別のケースで使用されます。この質問を見てください。同様のエラーが発生し、解決されました。

于 2014-12-04T16:18:15.257 に答える