1

kernel32.dllに関数名を列挙する際に問題があります。私はそのIMAGE_EXPORT_DIRECTORY構造体を取り出し、各関数名のchar配列へのポインタの配列を格納した:char** name_table = (char**)(image+pExp_dir->AddressOfNames); //pExp_dir is a pointer to the IMAGE_EXPORT_DIRECTORY structure。私は今、関数名を反復して、必要なRVAの関数名を含む文字列にマッチさせようとしています。IMAGE_EXPORT_DIRECTORY構造体のAddressOfNamesメンバーによる繰り返しの問題

for(int i=0;i<pExp_dir->NumberOfNames;i++) //until i is 1 less than how many names there are to iterate through elements 
    { 
     printf("%s ", (char*)(image+(DWORD)(uintptr_t)name_table[i])); //print the name of each function iterated through, I went back and read through these names and didn't see GetProcAddress anywhere 
     if(proc_name == image+(DWORD)(uintptr_t)name_table[i]) //if(strcmp(proc_name, (const char*)image+(DWORD)(intptr_t)name_table[i]) == 0) //Is it the function we're looking for? 
     { 
      address = (DWORD)(uintptr_t)func_table[ord_table[i]];//If so convert the address of the function into a DWORD(hexadecimal) 
      system("pause"); 
      system("CLS"); //Clear the screen 
      return address; //return the address of the function 
     } 

しかし、機能が見つからない場合は、プログラムがクラッシュします。 DBGデバッガのメモリダンプを調べたところ、name_tablesには、私が探している関数を含むすべての関数名が含まれていますが、私のプログラムはいくつかの要素をスキップしていますが、時間。ユーザーstijn suggested私はintptr_tchar*DWORDにキャストしてポインタ演算に使用しないでください。だから私の質問は実際にはname_tableを反復する正しい方法についてです。これはあたかもポインタの算術上の問題のようです。すべてのヘルプははるかに高く評価されるだろう

void* GetFileImage(char path[]) //Get maps the image of the file into memory and returns the beginning virtual address of the file in memory 
{ 
    HANDLE hFile = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);//Get a handle to the dll with read rights 
    if(hFile == INVALID_HANDLE_VALUE){printf("Error getting file handle: %d", (int)GetLastError());return NULL;} //Check whether or not CreateFile succeeded 

    HANDLE file_map = CreateFileMapping(hFile, NULL, PAGE_READONLY|SEC_IMAGE, 0, 0, "KernelMap"); //Create file map 
    if(file_map == INVALID_HANDLE_VALUE){printf("Error mapping file: %d", (int)GetLastError());return NULL;} //Did it succeed 

    LPVOID file_image = MapViewOfFile(file_map, FILE_MAP_READ, 0, 0, 0); //Map it into the virtual address space of my program 
    if(file_image == 0){printf("Error getting mapped view: %d", (int)GetLastError());return NULL;} //Did it succeed 

    return file_image; //return the base address of the image 
} 

DWORD RVAddress(char* image, const char* proc_name) //Gets the relative virtual address of the function and returns a DWORD to be cast to void*. 
{ 
    DWORD address = 0xFFFFFFFF; 

    PIMAGE_DOS_HEADER pDos_hdr = (PIMAGE_DOS_HEADER)image; //Get dos header 
    PIMAGE_NT_HEADERS pNt_hdr = (PIMAGE_NT_HEADERS)(image+pDos_hdr->e_lfanew); //Get PE header by using the offset in dos header + the base address of the file image 
    IMAGE_OPTIONAL_HEADER opt_hdr = pNt_hdr->OptionalHeader; //Get the optional header 
    IMAGE_DATA_DIRECTORY exp_entry = opt_hdr.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; 
    PIMAGE_EXPORT_DIRECTORY pExp_dir = (PIMAGE_EXPORT_DIRECTORY)(image+exp_entry.VirtualAddress); //Get a pointer to the export directory 

    void** func_table = (void**)(image+pExp_dir->AddressOfFunctions); //Get an array of pointers to the functions 
    WORD* ord_table = (WORD*)(image+pExp_dir->AddressOfNameOrdinals); //Get an array of ordinals 
    char** name_table = (char**)(image+pExp_dir->AddressOfNames); //Get an array of function names 

    for(int i=0;i<pExp_dir->NumberOfNames;i++) //until i is 1 less than how many names there are to iterate through elements 
    { 
     printf("%s ", (char*)(image+(DWORD)(uintptr_t)name_table[i])); //print the name of each function iterated through, I went back and read through these names and didn't see GetProcAddress anywhere 
     if(proc_name == image+(DWORD)(uintptr_t)name_table[i]) //if(strcmp(proc_name, (const char*)image+(DWORD)(intptr_t)name_table[i]) == 0) //Is it the function we're looking for? 
     { 
      address = (DWORD)(uintptr_t)func_table[ord_table[i]];//If so convert the address of the function into a DWORD(hexadecimal) 
      system("pause"); 
      system("CLS"); //Clear the screen 
      return address; //return the address of the function 
     } 
    } 

    return (DWORD)0; //Other wise return 0 
} 

:ここでは、ファイルの画像と実際にRVAを取得する機能を取得する機能です!

+0

ここではちょっと推測しますが、これは私の説明している問題に関連していると思います[http://stackoverflow.com/questions/18440205/casting-void-to-2d-array- of-int-c/18440456#18440456)。配列の配列は、ポインタへのポインタと同じではありません。 –

+0

@JoachimPileborgあなたがそれを修正するために提案するものは何か、あるいは単に「互換性がない」ものはありますか? –

+0

私は間違っていた*それはポインタの配列がポインタのポインタが動作するかどうかです。しかし、それはCスタイルの文字列の配列ではないようです([このMSDNのドキュメント](https://msdn.microsoft.com/en-us/library/ms809762.aspx)による)型は 'PDWORD * AddressOfNames'。私。基本的に 'DWORD'へのポインタの配列です。私はフォーマットについては何も知らないが、メモリポインターやオフセットなどのように見える場合は、いつでも "ポインタ"をダンプして、どのような値を持っているかを知ることができます。 –

答えて

0

Docs (Section 6.3)は約AddressOfNamesテーブル

エクスポート名ポインタ表 エクスポート名テーブルへのアドレス(RVAs)の配列である。次言いますポインタはそれぞれ32ビットで、 イメージベースを基準にしています。ポインターは、バイナリー の検索を可能にするために字句順に並べられています。

AddressOfFunctions

エクスポートアドレステーブルの各エントリは、2つの 形式のいずれかを使用するフィールドである...指定されたアドレスが輸出セクション (として内にない場合オプションの ヘッダーに記載されているアドレスと長さによって定義されます)、フィールドはエクスポートRVAです。コード内の実際のアドレスまたは データです。それ以外の場合、フィールドはForwarder RVAであり、 のシンボルに別のDLLを指定します。

あなたの変数はvoid**char**ではありませんが、これらのテーブルは、RVAを保持しているため、実際にはすべてDWORD*です。あなたのコードは、32ビットマシン上で実行するときに、それは関係なく、間違ったVaRの種類の動作するはず

DWORD* func_table = (DWORD*)(image+pExp_dir->AddressOfFunctions); //Get an array of pointers to the functions 
    WORD* ord_table = (WORD*)(image+pExp_dir->AddressOfNameOrdinals); //Get an array of ordinals 
    DWORD* name_table = (DWORD*)(image+pExp_dir->AddressOfNames); //Get an array of function names 

    for(int i=0;i<pExp_dir->NumberOfNames;i++) //until i is 1 less than how many names there are to iterate through elements 
    { 
     printf("%s ", (char*)(image+name_table[i])); //print the name of each function iterated through, I went back and read through these names and didn't see GetProcAddress anywhere 
     if(strcmp(proc_name, (const char*)(image+name_table[i])) == 0) //Is it the function we're looking for? 
     { 
      // TODO should we distinguish between normal and forwarded exports? 
      WORD ordinal_base = 1; // TODO read it from export directory 
      address = func_table[ord_table[i] - ordinal_base];//If so convert the address of the function into a DWORD(hexadecimal) 
      system("pause"); 
      system("CLS"); //Clear the screen 
      return address; //return the address of the function 
     } 
    } 

ていますが、64ビットである場合 - ポインタが二倍長くDWORDよりも、それはスキップされます:次のコードを試してみてくださいテーブル内の奇妙なエントリは、配列の境界から外れ、クラッシュする可能性があります。

P.S.名前テーブルが順序付けられているので、バイナリ検索を使用できます。

+0

!どうもありがとうございます!それは私には起こりませんでした、私はそれが最近まで32ビットのラップトップでプログラミングされているためだと思います。とても有難い! –

関連する問題