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

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

  1. Rel

    Rel Well-Known Member

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

    внимательно прочтите условие задачи...

    мне достаточно получить адрес TEB, дальше раскрутка и поиск делается в несколько строк кода...
     
  2. RET

    RET Well-Known Member

    Публикаций:
    17
    Регистрация:
    5 янв 2008
    Сообщения:
    789
    Адрес:
    Jabber: darksys@sj.ms
    Посмотри дизасмом как NtCurrentTeb реализована в x64 и делай по аналогии, предложенной
    GoldFinch[#16]
     
  3. n0name

    n0name New Member

    Публикаций:
    0
    Регистрация:
    5 июн 2004
    Сообщения:
    4.336
    Адрес:
    Russia
    для x64 - __readgsdword
     
  4. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    да... кстати хорошая идея, спасибо!)))) если кому интересно:
    Код (Text):
    1. mov rax, qword ptr gs:[00000030h] - для x64
    2. mov eax, dword ptr fs:[00000018h] - для x86
    да... я уже понял... просто не был в курсе, что в x64 для этих целей используется gs, а не fs... спасибо, что пояснили!
     
  5. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    RET
    Блоки содержащие инфу, такие как PCR, TEB, PEB и прочие содержат ссылку на адрес блока, так как нет возможности определить базу сегмента по селектору(ну без извлечения дескриптора из ядра).
     
  6. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    хех... чет все руки не доходили до решения этого вопроса... если кому интересно, я сделал реализацию GetModuleHandle (работает как часы, правда пока тестировалось только на Vista на "обоих разрядностях"):
    Код (Text):
    1. PTEB MyCurrentTeb()
    2. {
    3. #ifdef _WIN64
    4.     return (PTEB)__readgsqword(0x30);
    5. #else
    6.     return (PTEB)__readfsdword(0x18);
    7. #endif
    8. }
    9.  
    10. PPEB MyCurrentPeb()
    11. {
    12.     PTEB teb = MyCurrentTeb();
    13.     return teb->Peb;
    14. }
    15.  
    16. HMODULE MyGetModuleHandle(LPCWSTR lpModuleName)
    17. {
    18.     PPEB peb = MyCurrentPeb();
    19.  
    20.     // Если пользователь желает получить базовый адрес текущего модуля
    21.     if(lpModuleName == NULL)
    22.     { return (HMODULE)peb->ImageBaseAddress; }
    23.  
    24.     // Если пользователь желает получить базовый адрес dll, то
    25.     // ищем в цикле по имени модуля
    26.     PPEB_LDR_DATA ldrpeb = peb->LoaderData;
    27.     PLIST_ENTRY pointer  = ldrpeb->InInitializationOrderModuleList.Flink;
    28.     PLIST_ENTRY start    = ldrpeb->InInitializationOrderModuleList.Flink;
    29.     PLDR_MODULE ldrmod   = NULL;
    30.     PWSTR       dllname  = NULL;
    31.     while(1)
    32.     {
    33.         ldrmod  = (PLDR_MODULE)pointer;
    34.         dllname = ldrmod->BaseDllNameBuffer;
    35.         if(_wcsicmp(lpModuleName, dllname) == 0)
    36.         { return (HMODULE)ldrmod->BaseAddress; }
    37.         else { pointer = ldrmod->ModuleList.Flink; }
    38.         if(pointer == start) { break; }
    39.     }
    40.  
    41.     // Модуль не был найден
    42.     return NULL;
    43. }
    спасибо Вам всем за помощь в решении этого вопроса! но есть ещё один маленький косяк, может объясните? делал по описанию PE-формата реализацию функции GetProcAddress, но результат, который она возвращает не точен... такое впечатление, что возвращается адрес не той функции (то есть я думаю, что косяк в моем определении ординала)... вот код:
    Код (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)((DWORD)hModule + pExport->AddressOfNames);
    13.     PDWORD FuncAdr   = (PDWORD)((DWORD)hModule + pExport->AddressOfFunctions);
    14.     PWORD  FuncOrd   = (PWORD) ((DWORD)hModule + pExport->AddressOfNameOrdinals);
    15.     LPSTR  CurName   = NULL;
    16.     for(DWORD t = 0; t < pExport->NumberOfNames; t++)
    17.     {
    18.         CurName = (LPSTR)((DWORD)hModule + FuncNames[t]);
    19.         if(stricmp(lpProcName, CurName) == 0)
    20.         { return (PVOID)((DWORD)hModule + FuncAdr[FuncOrd[t]]); }
    21.     }  
    22.  
    23.     return NULL;
    24. }
     
  7. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    ((DWORD)hModule + pExport->AddressOfNames);

    Вероятно, имелось в виду:

    ((PBYTE)hModule + pExport->AddressOfNames);

    ?
     
  8. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    так более правильно, с точки зрения совместимости x86 и x64... но для одной 32-битной версии особой разницы нет)))

    вот конкретный пример, что на выходе:
    Код (Text):
    1. HMODULE their = GetModuleHandle(L"kernel32.dll");
    2. HMODULE my = MyGetModuleHandle(L"kernel32.dll");
    3. PVOID thadr = GetProcAddress(their, "HeapAlloc");
    4. PVOID myadr = MyGetProcAddress(my, "HeapAlloc");
    результат выполнения:
    Код (Text):
    1. their = 0x0000000077720000
    2. my = 0x0000000077720000
    3. thadr = 0x0000000077897a30
    4. myadr = 0x0000000077808e24
    то есть, как будто бы получен адрес другой функции... мне кажется, что косяк в ординалах)))
     
  9. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Не обратил сразу внимания:

    return (PVOID)((DWORD)hModule + FuncAdr[FuncOrd[t]]);

    Зачем FuncOrd? Должно же быть

    return (PVOID)((DWORD)hModule + FuncAdr[t]);
     
  10. Mika0x65

    Mika0x65 New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2005
    Сообщения:
    1.384
    Ну и кроме того, если нужно по номеру импортировать, то не забываем BaseOfOrdinals прибавить.
     
  11. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    нет... так массив имен функций не имеет четкого соответствия с массивом адресов (поскольку функции могут экспортироваться без имени)... именно для этого, насколько я понял, существует массив, на который указывает AdressOfNameOrdinals... то есть в этом массиве храниться индексы в массиве адресов функции, соответствующие индексам в массиве имен функций... или я что-то неправильно вычитал из документации?
     
  12. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    1) Вроде все правильно.... Укажите, плиз, версию dll.
    2) Возможно, секции файла размещаются не по базовым адресам, хотя a30 - e24... не похоже.
    Насколько я помню таблиц две - одна заполнена непосредственно в dll (соответствует агрузке по базовым адресам), вторая таблица заполняется непосредственно после загрузки (с коррекцией адресов) - надо у Юрова посмотреть (В.Юров, Assembler: Специальный справочник )
     
  13. Rel

    Rel Well-Known Member

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

    не знаю, как это поможет, но версия kernel32.dll - 6.0.6001.18315...
     
  14. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    список всех функций, адреса которых получаются неверными (имя функции - реальный адрес - полученный адрес):
    Код (Text):
    1. AcquireSRWLockExclusive - 0x7788cfd0 - 0x77808b37
    2. AcquireSRWLockShared - 0x77899560 - 0x77808b58
    3. AddVectoredContinueHandler - 0x77912d80 - 0x77808b76
    4. AddVectoredExceptionHandler - 0x77912d70 - 0x77808b9a
    5. CallbackMayRunLong - 0x778925d0 - 0x77808bbf
    6. CancelThreadpoolIo - 0x7791edb0 - 0x77808bda
    7. CloseThreadpool - 0x779142f0 - 0x77808bf9
    8. CloseThreadpoolCleanupGroup - 0x77902480 - 0x77808c0d
    9. CloseThreadpoolCleanupGroupMembers - 0x7791e6a0 - 0x77808c29
    10. CloseThreadpoolIo - 0x7791f070 - 0x77808c4c
    11. CloseThreadpoolTimer - 0x77857b80 - 0x77808c68
    12. CloseThreadpoolWait - 0x778922b0 - 0x77808c7d
    13. CloseThreadpoolWork - 0x77902af0 - 0x77808c91
    14. DecodePointer - 0x7788ee50 - 0x77808ca5
    15. DecodeSystemPointer - 0x7786fb70 - 0x77808cbc
    16. DeleteBoundaryDescriptor - 0x778517b0 - 0x77808cd9
    17. DeleteCriticalSection - 0x7788dc20 - 0x77808cfb
    18. DisassociateCurrentThreadFromCallback - 0x77862520 - 0x77808d1a
    19. EncodePointer - 0x77884df0 - 0x77808d37
    20. EncodeSystemPointer - 0x77874850 - 0x77808d4e
    21. EnterCriticalSection - 0x77897850 - 0x77808d6b
    22. ExitProcess - 0x77872f00 - 0x77808d89
    23. ExitThread - 0x7786b4c0 - 0x77808da2
    24. FlushProcessWriteBuffers - 0x778966b0 - 0x77808dba
    25. FreeLibraryWhenCallbackReturns - 0x779019c0 - 0x77808ddb
    26. GetCurrentProcessorNumber - 0x77894e80 - 0x77808e01
    27. HeapAlloc - 0x77897a30 - 0x77808e24
    28. HeapReAlloc - 0x77881230 - 0x77808e3a
    29. HeapSize - 0x7788fec0 - 0x77808e52
    30. InitOnceInitialize - 0x778e2af0 - 0x77808e64
    31. InitializeConditionVariable - 0x778e2af0 - 0x77808e7f
    32. InitializeCriticalSection - 0x77878110 - 0x77808ea4
    33. InitializeSListHead - 0x7788e090 - 0x77808ec7
    34. InitializeSRWLock - 0x77882810 - 0x77808ee4
    35. InterlockedFlushSList - 0x7788dea0 - 0x77808eff
    36. InterlockedPopEntrySList - 0x77894f50 - 0x77808f1e
    37. InterlockedPushEntrySList - 0x778631f0 - 0x77808f40
    38. InterlockedPushListSList - 0x77895020 - 0x77808f63
    39. IsThreadpoolTimerSet - 0x77853210 - 0x77808f85
    40. LeaveCriticalSection - 0x77897800 - 0x77808f98
    41. LeaveCriticalSectionWhenCallbackReturns - 0x778540a0 - 0x77808fb6
    42. QueryDepthSList - 0x77861620 - 0x77808fe7
    43. ReleaseMutexWhenCallbackReturns - 0x77901b50 - 0x77809000
    44. ReleaseSRWLockExclusive - 0x7788d000 - 0x77809029
    45. ReleaseSRWLockShared - 0x77899530 - 0x7780904a
    46. ReleaseSemaphoreWhenCallbackReturns - 0x77901ce0 - 0x77809068
    47. RemoveVectoredContinueHandler - 0x778ffbd0 - 0x77809095
    48. RemoveVectoredExceptionHandler - 0x778ffbc0 - 0x778090bc
    49. RestoreLastError - 0x778994f0 - 0x778090e4
    50. RtlAddFunctionTable - 0x7790cbc0 - 0x77809103
    51. RtlCaptureContext - 0x77895090 - 0x7780911d
    52. RtlCaptureStackBackTrace - 0x77869740 - 0x77809135
    53. RtlCompareMemory - 0x77897320 - 0x77809154
    54. RtlDeleteFunctionTable - 0x77854700 - 0x7780916b
    55. RtlFillMemory - 0x77897546 - 0x77809188
    56. RtlInstallFunctionTableCallback - 0x77854a70 - 0x7780919c
    57. RtlLookupFunctionEntry - 0x7789b430 - 0x778091c2
    58. RtlPcToFileHeader - 0x778933a0 - 0x778091df
    59. RtlRaiseException - 0x7788ed60 - 0x778091f7
    60. RtlRestoreContext - 0x778951cf - 0x7780920f
    61. RtlUnwind - 0x779016b0 - 0x77809227
    62. RtlUnwindEx - 0x7788e370 - 0x77809237
    63. RtlVirtualUnwind - 0x7789b530 - 0x77809249
    64. RtlZeroMemory - 0x77897578 - 0x77809260
    65. SetCriticalSectionSpinCount - 0x7788e0c0 - 0x77809274
    66. SetEventWhenCallbackReturns - 0x77901e80 - 0x77809299
    67. SetThreadpoolThreadMaximum - 0x77868ab0 - 0x778092be
    68. SetThreadpoolTimer - 0x77859e40 - 0x778092d8
    69. SetThreadpoolWait - 0x778920b0 - 0x778092e9
    70. StartThreadpoolIo - 0x779034c0 - 0x778092f9
    71. SubmitThreadpoolWork - 0x778be7c0 - 0x77809317
    72. TryEnterCriticalSection - 0x778994c0 - 0x77809328
    73. VerSetConditionMask - 0x778702e0 - 0x77809349
    74. WaitForThreadpoolIoCallbacks - 0x77903780 - 0x77809363
    75. WaitForThreadpoolTimerCallbacks - 0x77858380 - 0x7780937f
    76. WaitForThreadpoolWaitCallbacks - 0x77892760 - 0x77809394
    77. WaitForThreadpoolWorkCallbacks - 0x77902db0 - 0x778093a8
    78. WakeAllConditionVariable - 0x778e2a60 - 0x778093bc
    79. WakeConditionVariable - 0x778eea20 - 0x778093de
    80. __C_specific_handler - 0x7788e658 - 0x778093fd
    81. __chkstk - 0x778955f0 - 0x77809418
    82. __misaligned_access - 0x778e3520 - 0x77809427
    83. _local_unwind - 0x77893830 - 0x77809441
    всего 83 штуки из 1234 экспортируемых по имени функций в kernel32.dll...
     
  15. gorodon

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Нет под рукой висты...
    а если DependencyWalker-ом посмотреть на файл? что он кажет?
     
  16. ohne

    ohne New Member

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

    gorodon New Member

    Публикаций:
    0
    Регистрация:
    19 окт 2009
    Сообщения:
    301
    Вот Clerk запостил: http://wasm.ru/forum/viewtopic.php?id=37005
    -вот это надо добавить, видимо...
     
  18. ohne

    ohne New Member

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

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.251
    он показал следующие: похоже для всех 83 функций поле entry point указывает на функции из ntdll... например:
    HeapAlloc (675 - 0x02A3) - NTDLL.RtlAllocateHeap
     
  20. Rel

    Rel Well-Known Member

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

    lurkmore? а в чем шутка? вы видимо хотели мне тему из ядерного форума показать?