Имеется такая проблема. Есть код на с++ с забитой руками таблицей rva пары сотен функций одной библиотеки (uDWM.dll). Выглядит примерно так: Код (Text): typedef enum { // names rva_CDesktopManager__s_pDesktopManagerInstance = 0x00030068, rva_CDesktopManager__s_csDwmInstance = 0x000300F0, // functions rva_AccessibleObjectFromWindow = 0x000286EA, rva_AreAllMarginsZero = 0x00008477, rva_AssertW = 0x00027FB6, rva_AvCreateProcessHeap = 0x00018754, rva_AvDestroyProcessHeap = 0x00027B6C, Я не очень хорошо разбираюсь в этом, но uDWM.dll экспортирует эти функции, как минимум без имён (а возможно, что и без ординалов (не знаю может ли такое быть)), так что программы, которые показывают экспорты, выводят пустой список. Код использует эти значения для доступа к данным и вызова функций напрямую. Выглядит это так: Код (Text): #define PE_RvaToVa(handle, rva) ((void *)((DWORD)handle + (DWORD)rva)) HANDLE hUDWM = GetModuleHandle(_T("udwm.dll")); CDesktopManager *pdm = *(CDesktopManager **)PE_RvaToVa(hUDWM, rva_CDesktopManager__s_pDesktopManagerInstance); SuspendThread(pdm->hMessageLoopThread); Код (Text): DWORD CBaseObject::UDWM_CallMethodEAX(void *thisObj, UDWM_RVAs methodRva, ...) { DWORD retVal; void *methodAddr = CBaseObject::UDWM_GetMethodAddr(methodRva); __asm { pushad mov eax, [ebp + 4] // get current ret addr xor ecx, ecx // clear ecx mov cl, [eax + 2] // read the add opcode parameter (which is actually the number of args * 4) sub cl, 8 // don't count thisptr and address sub esp, ecx // reserve the new stack frame shr ecx, 2 // set the counter to the correct number of params lea esi, [methodRva + 4] // set the source (the var args) mov edi, esp // set the destination (the newly created stack frame) rep movsd // copy mov eax, thisObj // mov this call methodAddr mov retVal, eax popad } return (retVal); } int CResource::Initialize(MIL_RESOURCE_TYPE type, MIL_CHANNEL channel) { return (UDWM_CallMethodEAX(this, rva_CResource_Initialize, type, channel)); } Проблема: мне нужно получить таблицу этих rva_* констант для новой версии библиотеки. В идеале вообще научиться находить эти значения в рантайме. Как?
Каким-то образом dll должна что-то экспортировать. Либо по именам, либо по ординалам. Можно, конечно, предположить, что создатели библиотеки были ребятами с юмором и сделали свой экспорт, но это маловероятно. Ну или библиотека упакована, например. Т.к. информации маловато, то предположу, что RVA новой экспортов библиотеки надо получить тем же путем, как были получены RVA старой версии библиотеки . Или просто выложите библиотеку куда-нибудь, можно будет посмотреть, что и как она экспортирует. P.S. А затачиваться на то, что сразу за вызовом идет очистка стека -- нехорошо. gcc, например, может очистку стека передвинуть намного дальше относительно вызова ф-ии.
Очень часто плагинная система на этом и строится, что плагины запрашивают адреса неэкспортируемых функций.
/Windws/System32/uDWM.dll - стандартная библиотека, входящая в Windows Vista и выше. В основном её использует /Windws/System32/dwm.exe (композитный оконный менеджер). Думаю, что здесь всё несложно. Библиотека неупакована. Это и хочется узнать =) Выкладываю четыре версии (6.0.6000.16386, 6.0.6001.18000, 6.0.6002.16670 и 6.1.7100.0), а также хедер с таблицей для 6.0.6000 : http://rapidshare.com/files/229006862/uDWM.rar.html
Посмотрел экспорт, экспортируется только три ф-ии, по ординалу. В самом худшем случае нужен реверс . А как выглядит "CBaseObject::UDWM_GetMethodAddr"? А то не совсем понятно, зачем она нужна -- rva ф-ии и так известен, что там еще считать? Может, в ней какой-то намек есть, как получить адреса наиболее простым путем.
Mika0x65 К сожалению, CBaseObject::UDWM_GetMethodAddr - совсем неинтересная функция: Код (Text): HMODULE CBaseObject::hUDwm = GetModuleHandle(_T("uDWM.dll")); void *CBaseObject::UDWM_GetMethodAddr(UDWM_RVAs methodRva) { // we know what we are doing #pragma warning( push ) #pragma warning( disable : 4311 4312 ) return ((void *)((unsigned int)CBaseObject::hUDwm + (unsigned int)methodRva)); #pragma warning( pop ) } Пробовал дебажить dwm.exe. Он грузит uDWM.dll через LoadLibrary. Дебажить сложно, потому, что при брике интерфейс системы, очевидно, перестаёт работать.
Давайте посмотрим на dwm.exe (у меня его нет, выложите). Может что-то интересное есть в нем. И еще мне непонятна такая вещь: внутренние ф-ии могут быть скопилированы весьма "фривольно", например, ф-ия может ожидать адрес this не в ecx, как требует конвенция, а в esi. Вы это как-то учитываете в своем коде?
Подгузил твою uDWM {6.0.6000.16386}.dll в Иду, получил список(в аттаче) очень похож на твой из .h Поскольку длл от микрософта, для нее есть паблик символы (.pdb), и большинство функций Ида вытягивает оттуда.
Еще можно просто с Debugging Tools for Windows, правда все ли имена есть я не проверял. В аттаче лог того что получилось, а вкратце: symchk "uDWM {6.0.6000.16386}.dll" /s SRV*c:\sym*http://msdl.microsoft.com/download/symbols copy c:\sym\udwm.pdb\38D207C1D60E4414923F1941BA93CB752\udwm.pdb . dbh -v "C:\temp\uDWM {6.0.6000.16386}.dll" :srch globals
bolkin, Mika0x65 Огромное спасибо, dbh всё замечательно сдампил. Я правильно понимаю, что при отсутствии символов, получить адреса было бы намного сложнее?