Собственная GetModuleHandle без ассемблерных вставок (cpp)

Тема в разделе "WASM.WIN32", создана пользователем Rel, 6 апр 2010.

  1. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    так ты это, глянь или функция не из другой длл подгружается, есть эе такая штука как редирект
     
  2. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    Ну да, так оно и есть! проверяется редирект очень просто: если указатель на адресс функции лежит за пределами секции экспорта, то это редирект (По смещению адреса будет лежать строка вида: "DLLNAME.FUNC_NAME")
     
  3. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Да, mrcrown прав.
    Значит надо вытащить размер секции экспорта (pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size) и проверять адрес FuncAdr[FuncOrd[t]].
    Если адрес за пределами секции(таблицы) экспорта, то это редирект - парсим строку по адресу FuncAdr[FuncOrd[t]], получаем имя dll и имя функции. Находим хендл этой dll и рекурсивно вызываем MyGetProcAddress :)
     
  4. ohne

    ohne New Member

    Публикаций:
    0
    Регистрация:
    28 фев 2009
    Сообщения:
    431
    Export Forwarding
    нужно наверное читать спецификацию, есть на сайте MS + кучи переводов с отсебятиной на васме, и т.п. ресурсах
    DLL.NAME при экспорте по имени
    DLL#ORD при экспорте по ординалу
     
  5. ohne

    ohne New Member

    Публикаций:
    0
    Регистрация:
    28 фев 2009
    Сообщения:
    431
    в пределах
     
  6. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    да... большое спасибо за информацию! как сделаю - выложу сюда вариант с учетом редиректа...
     
  7. ohne

    ohne New Member

    Публикаций:
    0
    Регистрация:
    28 фев 2009
    Сообщения:
    431
    ))))))))
     
  8. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    Что ты этим хотел сказать? :))
    в пределах -- АДРЕСС
    за пределами -- СТРОКА с инфой о редиректе!
     
  9. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    нет, строка с инфой о редиректе лежит в таблице импорта (в пределах)...
     
  10. mrcrown

    mrcrown Member

    Публикаций:
    0
    Регистрация:
    18 янв 2008
    Сообщения:
    227
    а указатель на строку за? Возможно да, уже давно под вин32 ничего не пишу :)
     
  11. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Вот я на скорую руку добавил в код Rel-a:
    Код (Text):
    1.     DWORD dwExportTableSize = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;
    2.     DWORD dwExportTableAddress = pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    3.     PIMAGE_EXPORT_DIRECTORY pExport  = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)hModule + dwExportTableAddress);
    4.     PDWORD FuncNames = (PDWORD)((DWORD)hModule + pExport->AddressOfNames);
    5.     PDWORD FuncAdr   = (PDWORD)((DWORD)hModule + pExport->AddressOfFunctions);
    6.     PWORD  FuncOrd   = (PWORD) ((DWORD)hModule + pExport->AddressOfNameOrdinals);
    7.     LPSTR  CurName   = NULL;
    8.     for(DWORD t = 0; t < pExport->NumberOfNames; t++)
    9.     {
    10.         CurName = (LPSTR)((DWORD)hModule + FuncNames[t]);
    11.         if(stricmp(lpProcName, CurName) == 0)
    12.         {
    13.             DWORD dwFuncAdr = FuncAdr[FuncOrd[t]];
    14.             if((dwFuncAdr >= dwExportTableAddress)&&
    15.                 (dwFuncAdr < dwExportTableAddress+dwExportTableSize))
    16.             {//redirect "DllName.FuncName" or "DllName#Ordinal"
    17.                 TCHAR strDllName_FuncName[256];
    18.                 LPSTR strDllName = strDllName_FuncName;
    19.                 LPSTR strFuncName= NULL;
    20.                 strcpy(strDllName_FuncName,(const char*)((DWORD)hModule + dwFuncAdr));
    21.                 //
    22.                 strFuncName = strchr(strDllName_FuncName,'.');
    23.                 if(strFuncName)
    24.                 {
    25.                     *strFuncName = 0;
    26.                     strFuncName++;
    27.                     //
    28.                     return MyGetProcAddress(MyGetModuleHandle(strDllName),strFuncName);
    29.                 }
    30.                 else
    31.                  return NULL;
    32.             }
    33.             else
    34.                 return (PVOID)((DWORD)hModule + dwFuncAdr);
    35.         }
    36.     }
    Не обрабатывается DllName#Ordinal, но для kernel32 пойдет :)
     
  12. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    да мне наверное и не придется импортировать функцию по ординалу для этой задачи...

    к сожалению все не так тривиально... там надо переводить строку с именем длл в юникод и добавлять ".DLL" в конец... чуток посложнее, вот моя реализация:
    Код (Text):
    1. PVOID MyGetProcAddress(HMODULE hModule, LPCSTR lpProcName)
    2. {
    3.     // Просматриваем DOS-заголовок
    4.     PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)hModule;
    5.     if(pDosHeader->e_magic != IMAGE_DOS_SIGNATURE) { return NULL; }
    6.  
    7.     // Просматриваем NT-заголовок
    8.     PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PBYTE)hModule + pDosHeader->e_lfanew);
    9.     if(pNtHeader->Signature != IMAGE_NT_SIGNATURE) { return NULL; }
    10.  
    11.     PIMAGE_EXPORT_DIRECTORY pExport  = (PIMAGE_EXPORT_DIRECTORY)((PBYTE)hModule + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
    12.     PDWORD FuncNames = (PDWORD)((PBYTE)hModule + pExport->AddressOfNames);
    13.     PDWORD FuncAdr   = (PDWORD)((PBYTE)hModule + pExport->AddressOfFunctions);
    14.     PWORD  FuncOrd   = (PWORD) ((PBYTE)hModule + pExport->AddressOfNameOrdinals);
    15.     LPSTR  CurName   = NULL;
    16.     PBYTE  Result    = NULL;
    17.     for(DWORD t = 0; t < pExport->NumberOfNames; t++)
    18.     {
    19.         CurName = (LPSTR)((PBYTE)hModule + FuncNames[t]);
    20.         if(stricmp(lpProcName, CurName) == 0)
    21.         {
    22.             Result = ((PBYTE)hModule + FuncAdr[FuncOrd[t]]);
    23.             if(Result > (PBYTE)pExport && Result < (PBYTE)pExport + pNtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size)
    24.             {
    25.                 CHAR  RDll[128]; // На самом деле WCHAR, но для удобства CHAR
    26.                 LPSTR Point = strchr((LPSTR)Result, '.');
    27.                 LPSTR RFunc = Point + 1;
    28.  
    29.                 if(Point != NULL)
    30.                 {
    31.                     // Перевод в юникод
    32.                     for(DWORD t = 0; t < (PBYTE)Point - Result; t++)
    33.                     { RDll[2 * t] = Result[t]; RDll[2 * t + 1] = '\0'; }
    34.  
    35.                     // Добавление .DLL\0
    36.                     wcscpy((PWCHAR)&RDll[((PBYTE)Point - Result) * 2], L".DLL");
    37.  
    38.                     return MyGetProcAddress(MyGetModuleHandle((LPCWSTR)RDll), RFunc);
    39.                 }
    40.                 else { return NULL; }
    41.             }
    42.             else { return (PVOID)Result; }
    43.         }
    44.     }
    45.  
    46.     return NULL;
    47. }
     
  13. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    ну и для полной независимости функционала, надо сделать свои реализации для строковых функций, но это уже не составит никакого труда))) спасибо Вам всем за помощь! я чет протупил этот момент с редиректом, мог бы и сам додуматься...
     
  14. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Rel
    Насчет Ordinal и прочего:

    http://msdn.microsoft.com/en-us/library/ms809762.aspx
    Ordinal нужен лишь для того, чтобы скрыть имя экспортируемой ф-ии.
     
  15. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    Mika0x65, они параллельны, если все экспортируемые функции экспортируются по имени (NumberOfNames = NumberOfFunctions)... да и то не обязательно, я думаю... можно перемешать массив AddressOfFunctions, учитывая перемещения в AddressOfNameOrdinals...
     
  16. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    а в чем смысл наличия массива AddressOfNameOrdinals, ведь если массивы параллельны, то
    Код (Text):
    1. AddressOfNameOrdinals[t] = t
     
  17. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Для гибкости, как я понимаю. Т.е. чтобы можно было экспортировать первую ф-ию под номером 200, например.
     
  18. diamond

    diamond New Member

    Публикаций:
    0
    Регистрация:
    21 май 2004
    Сообщения:
    507
    Адрес:
    Russia
    Mika0x65
    Неверно. Советую забить на статью 1994-го года, о которой сам автор пишет
    и руководствоваться более новой версией из двух частей, http://msdn.microsoft.com/en-us/magazine/cc301805.aspx и http://msdn.microsoft.com/en-us/magazine/cc301808.aspx . Из трёх массивов параллельны только два, что отчётливо видно на версии картинки из более поздней статьи http://i.msdn.microsoft.com/Cc301808.PE2fig03(en-us,MSDN.10).gif. Хотя и там есть грубая ошибка - в AddressOfNameOrdinals хранятся индексы в массиве AddressOfFunctions, а не ординалы (которые суть индексы + база ординалов).
    Имелось в виду, что в принципе MS имеет полное право сделать функцию-перенаправление, ссылающуюся на функцию из ntdll по ординалу, а не по имени, так что для абсолютной точности такую ситуацию тоже можно обрабатывать. Но на практике этим правом не пользуется :)
     
  19. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    зачем? то есть экспортировать функцию без имени, но с ординалом, я могу понять зачем... вы полагаете, что для экспорта по ординалу, надо пройти по этому массиву, найти ординал - получить индекс и забрать адрес функции из другого массива? но вам не кажется, что тогда массив бы назывался AddressOfOrdinals и в названии не фигурировало бы слово Name... и вообще я всегда считал, что ординал функции - ее индекс в таблице экспорта...
     
  20. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    да, согласен... ну добавлю потом, это не так сложно...