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)
Загрузка 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[7]: Сами исходники
От: Виталий Россия  
Дата: 14.01.04 18:30
Оценка: :)
Здравствуйте, Flamer, Вы писали:

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


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

F>З.Ы. Завтра начну войну с Билдером
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
Оценка:
К сожалению, при этом справедливы те же ограничениями, что и здесь. И то же решение — копание в undoc'ах.

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

SM>К сожалению, при этом справедливы те же ограничениями, что и здесь. И то же решение — копание в 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[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
Re[2]: Не работает SetWindowsHookEx
От: juicy_emad  
Дата: 30.06.08 01:47
Оценка:
0x10000000 — это IBase DLL'ки;
0x00400000 — это IBase exe'ка, который использует DLL'ку;

Вот сама DLL'ка:
[file]http://files.rsdn.ru/61583/nthide.dll[/file]
Re[3]: Не работает SetWindowsHookEx
От: juicy_emad  
Дата: 30.06.08 12:40
Оценка:
Здравствуйте, juicy_emad, Вы писали:

_>0x10000000 — это IBase DLL'ки;

_>0x00400000 — это IBase exe'ка, который использует DLL'ку;

_>Вот сама DLL'ка:

_>[file]http://files.rsdn.ru/61583/nthide.dll[/file]

Я вызвал GetModuleHandle в коде библиотеке:
invoke        GetModuleHandle, NULL


И? Что же она вернула? 0x00400000! А не 0x10000000 как ожидалось!
Почему? Как пофиксить?
Т.е. моё предположение подтверждается — PE loader написан некорректно.
Re[4]: Не работает SetWindowsHookEx
От: gear nuke  
Дата: 06.07.08 08:09
Оценка:
Здравствуйте, juicy_emad, Вы писали:

_>И? Что же она вернула? 0x00400000! А не 0x10000000 как ожидалось!


Результат верный

If this parameter is NULL, GetModuleHandle returns a handle to the file used to create the calling process (.exe file).


_>Почему? Как пофиксить?


Просто — никак. Теоретически, 3м параметром SetWindowsHookEx следует передать адрес загрузки dll. Далее, по нему из PEB будет получено имя dll — оно нужно для загрузки dll в адресные пространства других процессов. Но dll то нет...

_>Т.е. моё предположение подтверждается — PE loader написан некорректно.


В нём есть недоработки (то же добавление в списки загруженных модулей), но в данном случае проблема не в этом.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[2]: Не работает SetWindowsHookEx
От: vdimas Россия  
Дата: 10.07.08 17:48
Оценка:
Здравствуйте, juicy_emad, Вы писали:

_>Здравствуйте, Виталий!


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


И не должен. Глобальный хук должен подгрузить или смапить твою DLL на адресное пространство других процессов, а самой-то DLL и нет.
... << RSDN@Home 1.2.0 alpha rev. 786>>
Re[3]: Не работает SetWindowsHookEx
От: juicy_emad  
Дата: 10.07.08 18:44
Оценка:
Здравствуйте, vdimas, Вы писали:
V>И не должен. Глобальный хук должен подгрузить или смапить твою DLL на адресное пространство других процессов, а самой-то DLL и нет.

Да, я так и понял. Просто, когда писал тот пост ещё не понимал как именно это должно происходит.
А вообще, мне нужно было пропатчить taskmgr.exe, чтобы скрыть свой процесс из его списка.
SetWindowsHookEx мне не подошло, ибо нужно именно наличие DLL'ки (а пихать DLL'ку в ресурсы своего exe'шника и потом дампить в файл — как-то не по-нормальному).
Я решил проблему через создание удалённого потока (CreateRemoteThread в сочетании с WriteProcessMemory) в процессе диспетчера задач и патчингом его таблицы импорта, прописал адрес функции ~NtQuerySystemInformarion на свой собственный.
В результате этого я наткнулся на проблемку: ведь, адреса API-функций, вызываемые в функции, которую я ставлю вместо NtQuerySystemInformarion привязаны к базе моего exe'шника, поэтому пришлось грузить необход. системные библиотеки и получать их адреса (LoadLibrary & ~GetAddressProc) и вручную, в бинарном прописанным в процесс диспетчера коде, менять адреса api-функций на полученные.
=)
Re[4]: Не работает SetWindowsHookEx
От: gear nuke  
Дата: 13.07.08 10:18
Оценка:
Здравствуйте, juicy_emad, Вы писали:

_>В результате этого я наткнулся на проблемку: ведь, адреса API-функций, вызываемые в функции, которую я ставлю вместо NtQuerySystemInformarion привязаны к базе моего exe'шника, поэтому пришлось грузить необход. системные библиотеки и получать их адреса (LoadLibrary & ~GetAddressProc) и вручную, в бинарном прописанным в процесс диспетчера коде, менять адреса api-функций на полученные.


Адреса загрузки основных системных dll одинаковы во всех процессах (для экономии памяти)
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[5]: Не работает SetWindowsHookEx
От: juicy_emad  
Дата: 13.07.08 11:58
Оценка:
Здравствуйте, gear nuke, Вы писали:

GN>Адреса загрузки основных системных dll одинаковы во всех процессах (для экономии памяти)


По идее, да. =) Но у меня почему-то, если я не перетру адрес, полученным через GetProcAddress, то приложение, в котором я перехватывал эту функцию, просто "вылетит".
Я бы мог опубликовать сорец, для выяснения обстоятельств, но он большой (~15 КБ) и я думаю, мало кому это будет интересно.
Re[6]: Не работает SetWindowsHookEx
От: gear nuke  
Дата: 13.07.08 15:50
Оценка:
Здравствуйте, juicy_emad, Вы писали:

_>По идее, да. =) Но у меня почему-то, если я не перетру адрес, полученным через GetProcAddress, то приложение, в котором я перехватывал эту функцию, просто "вылетит".


Какое исключение, что в стеке вызовов? Возможно, дело не в GetProcAddress, а в LoadLibrary (dll нет в АП процесса). Тогда достаточно её замапить. Вообще, всё должно стать понятно, если посмотреть что там за адрес, или немного поотлаживать.

_>Я бы мог опубликовать сорец, для выяснения обстоятельств, но он большой (~15 КБ) и я думаю, мало кому это будет интересно.


А тебе что интересно? По-моему, у тебя просто некоторые пробелы, которые, судя по постам, ты с успехом сам и восполняешь.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Re[4]: Не работает SetWindowsHookEx
От: vdimas Россия  
Дата: 14.07.08 19:27
Оценка:
Здравствуйте, juicy_emad, Вы писали:

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

V>>И не должен. Глобальный хук должен подгрузить или смапить твою DLL на адресное пространство других процессов, а самой-то DLL и нет.

_>Да, я так и понял. Просто, когда писал тот пост ещё не понимал как именно это должно происходит.


Самое прикольное, что по-идее, если DLL уже загружена в память, то при установке глобального хука надо лишь смаппить область уже загруженного кода на память другого процесса. Может быть, если корректно зарегистрировать загруженную DLL в списке загруженных модулей в этом загрузчике, то всё должно сработать.
... << RSDN@Home 1.2.0 alpha rev. 786>>