Загрузка dll из памяти на C++
От: Виталий Россия  
Дата: 09.01.04 05:04
Оценка: 34 (3)
Disclaimer: изначально разрабатывалась на чистом Си, но потом потребовалось немного подправить и получился С++ (правда изменения минимальны).

Собственно предлагаются 3 функции:
    HMODULE MemLoadLibrary(PBYTE data);
    BOOL MemFreeLibrary(HMODULE hDll);
    FARPROC MemGetProcAddress(HMODULE hDll, LPCTSTR fname);
Как пользоваться, думаю, ясно и без моих комментариев.

Исходники идут следующим постом. Или можно тестовый пример скачать здесь
Re: Сами исходники
От: Виталий Россия  
Дата: 09.01.04 05:09
Оценка: 29 (4)
/*
* Loading dll from memory
*
* Written by Vitaliy Shitts (vit@shittz.ru)
* Copyright (c) 2004 Vitaliy Shittz.
*
* THIS CODE IS PROVIDED "AS IS". NO WARRANTY OF ANY KIND IS EXPRESSED
* OR IMPLIED. YOU USE AT YOUR OWN RISK. THE AUTHOR ACCEPTS NO LIABILITY 
* IF IT CAUSES ANY DAMAGE TO YOU OR YOUR COMPUTER WHATSOEVER.
*
* Beware of bugs.
*/

#ifndef MIN
#    define MIN(a,b) ((a)<(b)?(a):(b))
#endif

typedef BOOL (WINAPI *DLLMAIN)(HINSTANCE,DWORD,LPVOID);

#pragma warning (push)
#pragma warning (disable: 4311; disable: 4312; disable: 4018)

DWORD GetSectionProtection(DWORD sc)
{
    DWORD dwResult=0;
    if (sc & IMAGE_SCN_MEM_NOT_CACHED)
        dwResult |= PAGE_NOCACHE;

    if (sc & IMAGE_SCN_MEM_EXECUTE)
    {
        if (sc & IMAGE_SCN_MEM_READ)
        {
            if (sc & IMAGE_SCN_MEM_WRITE)
                dwResult |= PAGE_EXECUTE_READWRITE;
            else
                dwResult |= PAGE_EXECUTE_READ;
        }
        else 
        {
            if (sc & IMAGE_SCN_MEM_WRITE)
                dwResult |= PAGE_EXECUTE_WRITECOPY;
            else
                dwResult |= PAGE_EXECUTE;
        }
    }
    else
    {
        if (sc & IMAGE_SCN_MEM_READ)
        {
            if (sc & IMAGE_SCN_MEM_WRITE)
                dwResult|=PAGE_READWRITE;
            else
                dwResult|=PAGE_READONLY;
        }
        else 
        {
            if (sc & IMAGE_SCN_MEM_WRITE)
                dwResult|=PAGE_WRITECOPY;
            else
                dwResult|=PAGE_NOACCESS;
        }
    }
    
    return dwResult;
}

inline BOOL IsImportByOrdinal(DWORD ImportDescriptor)
{
    return (ImportDescriptor & IMAGE_ORDINAL_FLAG32)!=0;
}


HMODULE MemLoadLibrary(PBYTE data)
{
    IMAGE_FILE_HEADER        *pFileHeader        = NULL;
    IMAGE_OPTIONAL_HEADER    *pOptionalHeader    = NULL;
    IMAGE_SECTION_HEADER    *pSectionHeader        = NULL;
    IMAGE_IMPORT_DESCRIPTOR *pImportDscrtr        = NULL;
    USHORT                    e_lfanew            = *((USHORT*)(data+0x3c));
    PCHAR                    ImageBase            = NULL;
    PCHAR                    SectionBase            = NULL;

    DWORD dwSize, dwOldProt, ImageBaseDelta;
    int i;

    pFileHeader = (IMAGE_FILE_HEADER *)(data+e_lfanew+4);
    pOptionalHeader = (IMAGE_OPTIONAL_HEADER *)(data+e_lfanew+4+sizeof(IMAGE_FILE_HEADER));
    if (pOptionalHeader->Magic!=IMAGE_NT_OPTIONAL_HDR32_MAGIC)
        return NULL;

    //    Let's try to reserv memory
    ImageBase = (PCHAR)VirtualAlloc(
        (PVOID)pOptionalHeader->ImageBase,
        pOptionalHeader->SizeOfImage,
        MEM_RESERVE,PAGE_NOACCESS);

    if(ImageBase==NULL)
    {
        ImageBase=(PCHAR)VirtualAlloc(NULL,
            pOptionalHeader->SizeOfImage,
            MEM_RESERVE,PAGE_NOACCESS);
        if(ImageBase==NULL)
            return NULL;
    }

    //    copy the header
    SectionBase=(PCHAR)VirtualAlloc(ImageBase,
        pOptionalHeader->SizeOfHeaders,
        MEM_COMMIT,PAGE_READWRITE);
    memcpy(SectionBase,data,pOptionalHeader->SizeOfHeaders);
    //    Do headers read-only (to be on the safe side)
    VirtualProtect(SectionBase,pOptionalHeader->SizeOfHeaders,PAGE_READONLY,&dwOldProt);

    //    find sections ...
    pSectionHeader = (IMAGE_SECTION_HEADER *)(pOptionalHeader+1);
    for (i=0; i<pFileHeader->NumberOfSections; i++)
    {
        SectionBase = (PCHAR)VirtualAlloc(
            ImageBase+pSectionHeader[i].VirtualAddress,
            pSectionHeader[i].Misc.VirtualSize,
            MEM_COMMIT,PAGE_READWRITE);
        if (SectionBase==NULL)
        {
            VirtualFree(ImageBase, 0, MEM_RELEASE);
            return NULL;
        }
        //    ... and copy initialization data
        SectionBase = ImageBase+pSectionHeader[i].VirtualAddress;
        dwSize = MIN(pSectionHeader[i].SizeOfRawData,pSectionHeader[i].Misc.VirtualSize);
        memcpy(SectionBase, data+pSectionHeader[i].PointerToRawData,dwSize);
    }

    //    check addersses
    ImageBaseDelta = (DWORD)ImageBase-pOptionalHeader->ImageBase;
    if (ImageBaseDelta!=0 && 
        pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress!=0
        )
    {
        IMAGE_BASE_RELOCATION    *pBaseReloc    = (IMAGE_BASE_RELOCATION *)(ImageBase+
            pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
        IMAGE_BASE_RELOCATION    *pBaseReloc0    = pBaseReloc;
        WORD *wPointer = NULL;
        DWORD dwModCount;
        int i;

        while ((DWORD)pBaseReloc0-(DWORD)pBaseReloc < pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size)
        {
            dwModCount = (pBaseReloc0->SizeOfBlock-sizeof(pBaseReloc))/2;
            wPointer = (WORD *)(pBaseReloc+1);
            for (i=0; i<dwModCount; i++, wPointer++)
                if ((*wPointer & 0xf000) !=0)
                {
                    PDWORD pdw = (PDWORD)(ImageBase+pBaseReloc0->VirtualAddress+((*wPointer)&0xfff));
                    (*pdw)+=ImageBaseDelta;
                }
                pBaseReloc = (IMAGE_BASE_RELOCATION *)wPointer;
        }
    }
    else if (ImageBaseDelta!=0)
    {
        VirtualFree(ImageBase, 0, MEM_RELEASE);
        return NULL;
    }

    pImportDscrtr = (IMAGE_IMPORT_DESCRIPTOR *)(ImageBase+
        pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);

    for (;pImportDscrtr->Name!=0; pImportDscrtr++)
    {
        PCHAR pLibName        = (PCHAR)(ImageBase+pImportDscrtr->Name);
        PCHAR pImortName    = NULL;
        HMODULE hLibModule    = LoadLibrary(pLibName);
        DWORD    *pImport    = NULL,
            *pAddress    = NULL;
        DWORD ProcAddress;

        pAddress=(DWORD *)(ImageBase+pImportDscrtr->/*Original*/FirstThunk);
        if (pImportDscrtr->TimeDateStamp==0)
            pImport=(DWORD *)(ImageBase+pImportDscrtr->FirstThunk);
        else
            pImport=(DWORD *)(ImageBase+pImportDscrtr->OriginalFirstThunk);
        for (i=0; pImport[i]!=0; i++)
        {
            if (IsImportByOrdinal(pImport[i]))
                ProcAddress=(DWORD)GetProcAddress(hLibModule, (PCHAR)(pImport[i]&0xFFFF));
            else  // import by name
            {
                pImortName=(PCHAR)(ImageBase+(pImport[i])+2);
                ProcAddress=(DWORD)GetProcAddress(hLibModule, pImortName);
            }
            pAddress[i]=ProcAddress;
        }
    }

    //    set section protection
    for (i=0; i<pFileHeader->NumberOfSections; i++)
        VirtualProtect((PVOID)(ImageBase+pSectionHeader[i].VirtualAddress),
        pSectionHeader[i].Misc.VirtualSize,
        GetSectionProtection(pSectionHeader[i].Characteristics),
        &dwOldProt);

    //    call DLLMain
    if (pOptionalHeader->AddressOfEntryPoint!=0)
    {
        DLLMAIN dllMain=(DLLMAIN)(ImageBase+pOptionalHeader->AddressOfEntryPoint);
        if (!dllMain((HMODULE)ImageBase, DLL_PROCESS_ATTACH, NULL))
        {
            VirtualFree(ImageBase, 0, MEM_RELEASE);
            return NULL;
        }
    }

    return (HMODULE)ImageBase;
}


BOOL MemFreeLibrary(HMODULE hDll)
{
    PIMAGE_DOS_HEADER        pDosHeader        = NULL;
    PIMAGE_FILE_HEADER        pFileHeader        = NULL;
    PIMAGE_OPTIONAL_HEADER    pOptionalHeader    = NULL;
    
    pDosHeader=(PIMAGE_DOS_HEADER)hDll;
    pFileHeader=(PIMAGE_FILE_HEADER)(((PBYTE)hDll)+pDosHeader->e_lfanew+4);
    pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)(pFileHeader+1);

//    Call to DllMain
    if (pOptionalHeader->AddressOfEntryPoint!=0)
    {
        DLLMAIN dllMain=(DLLMAIN)((PBYTE)hDll+pOptionalHeader->AddressOfEntryPoint);
        dllMain(hDll, DLL_PROCESS_DETACH, NULL);
    }
//    free loaded librares    
    PIMAGE_IMPORT_DESCRIPTOR pImportDscrtr = (IMAGE_IMPORT_DESCRIPTOR *)((PBYTE)hDll+
        pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    for (;pImportDscrtr->Name!=0; pImportDscrtr++)
    {
        PCHAR pLibName = (PCHAR)((PBYTE)hDll+pImportDscrtr->Name);
        HMODULE hLib = GetModuleHandle(pLibName);
        FreeLibrary(hLib);
    }

    return VirtualFree((PVOID)hDll, 0, MEM_RELEASE);
}

FARPROC MemGetProcAddress(HMODULE hDll, LPCTSTR fname)
{
    PIMAGE_DOS_HEADER        pDosHeader        = NULL;
    PIMAGE_FILE_HEADER        pFileHeader        = NULL;
    PIMAGE_OPTIONAL_HEADER    pOptionalHeader    = NULL;

    pDosHeader=(PIMAGE_DOS_HEADER)hDll;
    pFileHeader=(PIMAGE_FILE_HEADER)(((PBYTE)hDll)+pDosHeader->e_lfanew+4);
    pOptionalHeader=(PIMAGE_OPTIONAL_HEADER)(pFileHeader+1);

    DWORD dwExpRVA = pOptionalHeader->DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;
    PBYTE pb = (PBYTE)hDll;
    PIMAGE_EXPORT_DIRECTORY pExportDir=(PIMAGE_EXPORT_DIRECTORY)(pb+dwExpRVA);
    PDWORD pNamesRVA=(PDWORD)(pb+pExportDir->AddressOfNames);
    PDWORD pFuncRVA=(PDWORD)(pb+pExportDir->AddressOfFunctions);
    PWORD ord=(PWORD)(pb+pExportDir->AddressOfNameOrdinals);

    DWORD dwFunc=pExportDir->NumberOfNames;
    for (int i=0; i<dwFunc; i++)
    {
        PCHAR name =((PCHAR)(pb+pNamesRVA[i]));
        if (0==lstrcmp(fname, name))
            return (FARPROC)(pb+pFuncRVA[ord[i]]);
    }

    return NULL;
}

#pragma warning (pop)
Re: Загрузка dll из памяти на C++
От: c-smile Канада http://terrainformatica.com
Дата: 14.01.04 07:17
Оценка:
Здравствуйте, Виталий, Вы писали:

Не понял, а зачем эти пляски с бубном?
В чем смысл глубокий?

Это так модно DLL нонче грузить? Причем по всякому и на Cях и на Паскале...

Андрей.
Re[2]: Загрузка dll из памяти на C++
От: Виталий Россия  
Дата: 14.01.04 10:58
Оценка:
Здравствуйте, c-smile, Вы писали:

CS>Здравствуйте, Виталий, Вы писали:


CS>Не понял, а зачем эти пляски с бубном?

CS>В чем смысл глубокий?
HtmLayout не прячу, чесс слово (Хотя работает, проверял)

Собственно говоря, я это для чего-то вроде защиты использую. Алгоритм следующий — длл с необходимым функционалом хитроумно шифруется и кладется в ресурсы. Когда требуется, расшифровывается, проверяется контрольная сумма и если все в порядке, то считаем эту область длл и спокойно с ней работаем. Очень удобно, да и реализуется за полчаса, причем никаких проблем с выполнением кода (это в преддверии SP2).
Re[2]: Сами исходники
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 14.01.04 11:18
Оценка:
Здравствуйте, Виталий, Вы писали:

[]

Интересует, как насчет поддерживаемых OC? А именно: Win9x, Win2000, Win NT 4.x, WinXP. На всех будет работать?
Re[3]: Сами исходники
От: Виталий Россия  
Дата: 14.01.04 11:33
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Здравствуйте, Виталий, Вы писали:


F>[]


F>Интересует, как насчет поддерживаемых OC? А именно: Win9x, Win2000, Win NT 4.x, WinXP. На всех будет работать?

Лично мной проверялось на WinXP и Win98SE. Чисто террористически, упс теоретически должно на всех. Единственное, что нужно уточнить — у меня нет поддержки "forward export", как-то без надобности было
Re: Загрузка dll из памяти на C++
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 14.01.04 13:34
Оценка:
К сожалению, при этом справедливы те же ограничениями, что и здесь
Автор(ы): Максим М. Гумеров
Дата: 20.03.2003
Не вдаваясь в подробности, скажу лишь, что исследование было начато ради сокрытия использования программой на Delphi некоей DLL (написанной на VC++). То есть оператор видит один только Exe-файл, запускает его, а тот каким-то образом подключает функции, содержащиеся изначально (при компиляции проекта) в некоторой DLL.
. И то же решение — копание в undoc'ах.

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[2]: Загрузка dll из памяти на C++
От: Виталий Россия  
Дата: 14.01.04 14:02
Оценка:
Здравствуйте, Slicer [Mirkwood], Вы писали:

SM>К сожалению, при этом справедливы те же ограничениями, что и здесь
Автор(ы): Максим М. Гумеров
Дата: 20.03.2003
Не вдаваясь в подробности, скажу лишь, что исследование было начато ради сокрытия использования программой на Delphi некоей DLL (написанной на VC++). То есть оператор видит один только Exe-файл, запускает его, а тот каким-то образом подключает функции, содержащиеся изначально (при компиляции проекта) в некоторой DLL.
. И то же решение — копание в undoc'ах.

Угу, совершенно так + не поддерживаю "forward export", ну да его добавить строк по 5 в MemGetProcAddress и MemFreeLibrary. Более того, перед написанием статья даже внимательно читалась Только с исходниками не очень разобрался (там некоторые переменные используются, которые нигде не декларированны) и посему изобретал вилосипед, основываясь на "Inside Windows 2000", кстати говоря этой статьи вполне достаточно.
Re[3]: Загрузка dll из памяти на C++
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 14.01.04 15:37
Оценка:
Здравствуйте, Виталий!

Именно для написания программы достаточно использовать один из источников, приведенных мною в списке ссылок. Но вот для того, чтобы быть уверенным в том, что делаем, приходится их сравнивать. Они, как я уже писал, иногда противоречат друг другу.

А с переменными и впрямь вышел конфуз. То есть, все это легко восстановимо из приведенных в статье рассуждений, но факт остается фактом — пару деклараций я действительно забыл

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[2]: Сами исходники
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 14.01.04 16:07
Оценка:
Здравствуйте, Виталий, Вы писали:

[]

В С++ Builder 5.0 рушится на этом коде:


DLLMAIN dllMain=(DLLMAIN)(ImageBase+pOptionalHeader->AddressOfEntryPoint);
        if (!dllMain((HMODULE)ImageBase, DLL_PROCESS_ATTACH, NULL))


Вот чего я делаю:


    HMODULE hExe = ::GetModuleHandle(NULL);
    if(hExe)
    {
        HRSRC hRes;
        HGLOBAL hResLoad;
        DWORD dwResSize;

        hRes = ::FindResource(hExe, MAKEINTRESOURCE(101), RT_RCDATA);
        if(hRes)
        {
            dwResSize = ::SizeofResource(hExe,hRes);
            if(dwResSize)
            {
                hResLoad = ::LoadResource(hExe, hRes);
                if(hResLoad)
                {
                    LPVOID lpResData = ::LockResource(hResLoad);
                    if(lpResData)
                    {
                      HMODULE hLib = MemLoadLibrary((unsigned char*)lpResData);

                      typedef void (__stdcall *CHello)();

                      if(hLib)
                      {
                         CHello mr = (CHello) MemGetProcAddress(hLib,"SayHello");

                         if(mr)
                          {
                           mr();
                           } // if(mr)


                        MemFreeLibrary(hLib);
                      }  // if(hLib)



                    } // if(lpResData)

                } // if(hResLoad)

            } // if(dwResSize)
        } // if(hRes)
    } // hExe



DLL самая простая, экспортирует только одру функцию, в которой выводится MessageBox. Где порылась собака? Или я чего не понял?
Re[3]: Сами исходники
От: Виталий Россия  
Дата: 14.01.04 17:14
Оценка:
Здравствуйте, Flamer, Вы писали:

F>Здравствуйте, Виталий, Вы писали:


F>В С++ Builder 5.0 рушится на этом коде:

skip
F>DLL самая простая, экспортирует только одну функцию, в которой выводится MessageBox. Где порылась собака? Или я чего не понял?
С первого взгляда должно работать . Не работает вообще никак или только при загрузке из ресурсов? Может дело в packing alignment, они кажись разные для VC и Билдера?
Re[4]: Сами исходники
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 14.01.04 17:25
Оценка:
Здравствуйте, Виталий, Вы писали:

[]

В>С первого взгляда должно работать . Не работает вообще никак или только при загрузке из ресурсов?


Не работает и при использовании CreateFileMapping. Я из вашего примера взял.

В>Может дело в packing alignment, они кажись разные для VC и Билдера?


DLL тоже написана на Билдере, настройки проектов одинаковые... Вот сижу и огорчаюсь Идея класс, но как заставить ее работать под Билдером? Под VC буду юзать однозначно (думаю, там будет все ок). Any idea?
Re[5]: Сами исходники
От: Виталий Россия  
Дата: 14.01.04 18:08
Оценка:
Здравствуйте, Flamer, Вы писали:

В>>С первого взгляда должно работать . Не работает вообще никак или только при загрузке из ресурсов?


F>Не работает и при использовании CreateFileMapping. Я из вашего примера взял.


В>>Может дело в packing alignment, они кажись разные для VC и Билдера?


F>DLL тоже написана на Билдере, настройки проектов одинаковые... Вот сижу и огорчаюсь Идея класс, но как заставить ее работать под Билдером? Под VC буду юзать однозначно (думаю, там будет все ок). Any idea?

Эт нужно поб билдером поотлаживать, чтоб что-нить умное сказать, а его-то у меня и нет.
Re[6]: Сами исходники
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 14.01.04 18:16
Оценка:
Здравствуйте, Виталий, Вы писали:

[]

F>>DLL тоже написана на Билдере, настройки проектов одинаковые... Вот сижу и огорчаюсь

В>Эт нужно поб билдером поотлаживать, чтоб что-нить умное сказать, а его-то у меня и нет.

Я не особо силен в формате PE, поэтому просто сидел и пошагово трейсил функцию MemLoadLibrary. Косяк возникает только на строчке вызова точки входа dll. Такое ощущение, что адрес немножко не тот.

З.Ы. Завтра начну войну с Билдером
Re[7]: Сами исходники
От: Виталий Россия  
Дата: 14.01.04 18:30
Оценка: :)
Здравствуйте, Flamer, Вы писали:

F>Я не особо силен в формате PE, поэтому просто сидел и пошагово трейсил функцию MemLoadLibrary. Косяк возникает только на строчке вызова точки входа dll. Такое ощущение, что адрес немножко не тот.


А если ее просто не вызывать?

F>З.Ы. Завтра начну войну с Билдером
Re[8]: Сами исходники
От: Flamer Кипр http://users.livejournal.com/_flamer_/
Дата: 14.01.04 18:39
Оценка:
Здравствуйте, Виталий, Вы писали:

В>Здравствуйте, Flamer, Вы писали:


F>>Я не особо силен в формате PE, поэтому просто сидел и пошагово трейсил функцию MemLoadLibrary. Косяк возникает только на строчке вызова точки входа dll. Такое ощущение, что адрес немножко не тот.


В>А если ее просто не вызывать?


Тогда MemGetProcAddress проходит успешно, но при попытке вызова функции — обломс в виде старого приятеля AV...
Re[8]: Сами исходники
От: Slicer [Mirkwood] Россия https://ru.linkedin.com/in/maksim-gumerov-039a701b
Дата: 14.01.04 18:39
Оценка:
А с вышеупомянутой статьей сравнивали? В чем отличия?

Slicer
Специалист — это варвар, невежество которого не всесторонне :)
Re[3]: Нашел багу
От: Аноним  
Дата: 12.03.04 22:16
Оценка:
Здравствуйте, Flamer, Вы писали:


F>В С++ Builder 5.0 рушится на этом коде:



F>
F>DLLMAIN dllMain=(DLLMAIN)(ImageBase+pOptionalHeader->AddressOfEntryPoint);
F>        if (!dllMain((HMODULE)ImageBase, DLL_PROCESS_ATTACH, NULL))
F>



А я теперь знаю почему код рушится И даже не из-за того что это билдер.
Поглядите на preferred address вашей dll -ки, наверняка она перемещена из-за конфликта с другой dll-кой и тут и возникает баг.

Лечится либо с помощью rebase (временное пожарное решение), а лучше попросить автора, чтобы исправил багу.
Re[7]: Сами исходники
От: Lepsik Индия figvam.ca
Дата: 02.12.04 21:09
Оценка:
Здравствуйте, Flamer, Вы писали:


очень уж интересуют результаты вашей борьбы с Билдером. Если ли результаты ?

спасибо

F>Я не особо силен в формате PE, поэтому просто сидел и пошагово трейсил функцию MemLoadLibrary. Косяк возникает только на строчке вызова точки входа dll. Такое ощущение, что адрес немножко не тот.


F>З.Ы. Завтра начну войну с Билдером
Re: Не работает SetWindowsHookEx
От: juicy_emad  
Дата: 30.06.08 01:34
Оценка:
Здравствуйте, Виталий!

Используя этот PE loader я наткнулся на проблемку. Не устанавливается глобальных хук (код из DLL'ки):

LibMain proc hInstDLL: DWORD, reason: DWORD, unused: DWORD

    push        hInstDLL
    pop        tmp___1
;...
CBTProc proc nCode: DWORD, wParam: DWORD, lParam: DWORD
    xor        eax, eax
    ret
CBTProc endp
;...
    invoke        SetWindowsHookEx, WH_CBT, offset CBTProc, tmp___1, 0


И думается мне, что это происходит из-за неправильного HINSTANCE (см. tmp___1). На самом деле, отладить это всё достаточно сложно — GetLastError() выдаёт NULL, вместа кода ошибки (видимо, это связано с тем, что вызов системных функций происходит через JMP'ы).

У людей вроде подобная проблема возникала при использовании PE loader'ов: http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_20974729.html

Madshi:
A simple MessageBox (without SysUtils) with only Windows.pas in the uses clause worked for me. But I had to set the image base address of your project to something high (I've chosen $60000000) and the image base address of the test exe to $10000000. It didn't work with $400000 because that address was already in use (didn't spend the time to find out why).


Но я пока ImageBase'ы не менял. Попробую потом (ибо хрен знает как это сделать под masm32).

В общем, нужно как-то решить проблему. Пока не знаю как. Но факт остаётся фактом — с обычной загрузкой глобальный хук работает, а с такой загрузкой (через этот PE Loader) — не работает.
pe loader setwindowshookex
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.