Страница 3 из 3

Re: Доступ к неэкспортируемым функциям DLL

Добавлено: 16 апр 2009, 15:23
BBB
Я как-то кодировал звук в AAC-формат с помощью DLL, которая шла плагином для WinAmp-а (нажеюсь, ничего не перепутал :) ).
Так там кодировщих был в виде C++ - класса с несколькими методами (причем, помнится, один из которых виртуальный). А далее, вроде как, из DLL вызывалась предназначенная для этого функция, котораявозвращала указатель на экземпляр этого класса. И вызывающая программа делала то, что ей требуется, через методы класса.

Как это все делалось, я нашел примеры в интернете. И на основе этого "руководства к действию" сам сделал. Если кого-то заинтересовало, могу найти свой исходник.

Re: Доступ к неэкспортируемым функциям DLL

Добавлено: 17 апр 2009, 09:49
Decoder
Yes!!! У меня получилось.
Я передаю массив с адресами функций через основную кучу процесса.
Вот код DLL, в которой нет ни одной экспортируемой функции...

Код: Выделить всё

// HeapLib.cpp : Defines the entry point for the DLL application.
#include "stdafx.h"
#include <tchar.h>

BOOL PrintText(LPCTSTR szText)
{
    static HANDLE hConsole = ::GetStdHandle(STD_OUTPUT_HANDLE);
    //
    DWORD dw(0);
    return ::WriteConsole(hConsole, szText, ::lstrlen(szText), &dw, NULL);
}

BOOL SayHello()
{
    return PrintText(_T("Привет всем программерам!\r\n"));
}

BOOL SayGoodBye()
{
    return PrintText(_T("Всем пока! :-)\r\n"));
}

class Global
{
public:
    Global()
    {
        HANDLE hHeap = ::GetProcessHeap();
        m_lpData = (LPBYTE)::HeapAlloc(hHeap, HEAP_ZERO_MEMORY, 80);
        if (m_lpData != NULL)
        {
            char Signature[] = "HEAP :D LL";
            memcpy((LPSTR)m_lpData, Signature, sizeof(Signature));
            FARPROC* lpFarProc = (FARPROC*)(m_lpData+16);
            lpFarProc[0] = (FARPROC)SayHello;
            lpFarProc[1] = (FARPROC)SayGoodBye;
        }
    }
    ~Global()
    {
        if (m_lpData != NULL)
        {
            HANDLE hHeap = ::GetProcessHeap();
            ::HeapFree(hHeap, 0, m_lpData);
        }
    }
private:
    LPBYTE m_lpData;
} _global;

BOOL APIENTRY DllMain( HMODULE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved )
{
    return TRUE;
}
А вот код, который вызывает из неё функции...

Код: Выделить всё

#include "stdafx.h"

typedef BOOL (*SAYHELLO)(void);
typedef BOOL (*SAYGOODBYE)(void);

int _tmain(int argc, _TCHAR* argv[])
{
    HMODULE hModule = ::LoadLibrary(_T("HeapLib.dll"));
    if (hModule != NULL)
    {
        FARPROC* lpFarProc(NULL);
        HANDLE hHeap = ::GetProcessHeap();
        PROCESS_HEAP_ENTRY phe = {NULL};
        BOOL bNext = ::HeapWalk(hHeap, &phe);
        while (bNext != FALSE)
        {
            bNext = ::HeapWalk(hHeap, &phe);
            if (phe.cbOverhead > 0)
            {
                LPCSTR lps = (LPCSTR)phe.lpData;
                if (strcmp(lps, "HEAP :D LL") != 0)
                    continue;
                lpFarProc = (FARPROC*)((LPBYTE)phe.lpData+16);
                break;
            }
        }
        if (lpFarProc != NULL)
        {
           SAYHELLO fhSayHello = (SAYHELLO)lpFarProc[0];
           SAYGOODBYE fhSayGoodBye = (SAYGOODBYE)lpFarProc[1];
           // вызов полученных функций...
           fhSayHello();
           fhSayGoodBye();
        }
        //
        ::FreeLibrary(hModule);
    }
    getc(stdin);
    return 0;
}
При выполнении программы на экране появляются строки:
Привет всем программерам!
Всем пока! :-)

WinMain
, спасибо за прекрасную идею!

.

Добавлено: 17 апр 2009, 11:33
BBB
Decoder писал(а):Yes!!! У меня получилось.
Я передаю массив с адресами функций через основную кучу процесса.
...............
WinMain, спасибо за прекрасную идею!
Хм. Лихо закручено.
Т.е. получился этакий "lib-файл", расположенный в памяти (в Heap-е). Вызывающая программа находит его, "линкует" к себе - т.е. получает адреса "экспортируемых" функций и использует их.

Re: Доступ к неэкспортируемым функциям DLL

Добавлено: 30 июл 2009, 21:08
maxrfon
А вот такую задачу как решить? Нужно вызвать GeNeRator функцию, но со своими параметрами. Есть мысли (если можно практичные) как это можно сделать?

Код: Выделить всё

.text:0526CCA0 CheckMEproc near               ; CODE XREF: LoadGenFiles+85p
.text:0526CCA0
.text:0526CCA0 var_20          = dword ptr -20h
.text:0526CCA0 arg_0           = dword ptr  4
.text:0526CCA0 arg_4           = dword ptr  8
.text:0526CCA0
.text:0526CCA0                 mov     ecx, [ecx+8]
.text:0526CCA3                 sub     esp, 20h
.text:0526CCA6                 test    ecx, ecx
.text:0526CCA8                 jnz     short loc_526CCCB
.text:0526CCAA                 lea     eax, [esp+20h+var_20]
.text:0526CCAE                 push    (offset unk_534B3FF+0AF456B1h) ; Format
.text:0526CCB3                 push    eax             ; int
.text:0526CCB4                 call    sub_526C360
.text:0526CCB9                 add     esp, 8
.text:0526CCBC                 lea     ecx, [esp+20h+var_20]
.text:0526CCC0                 push    (offset unk_5322BFF+0AF4C241h)
.text:0526CCC5                 push    ecx
.text:0526CCC6                 call    __CxxThrowException@8
.text:0526CCCB
.text:0526CCCB loc_526CCCB:                            ; CODE XREF: CheckME+8j
.text:0526CCCB                 mov     eax, [esp+20h+arg_4]
.text:0526CCCF                 mov     edx, [ecx]      ; Pointer to offset of cryptoroutines
.text:0526CCD1                 push    eax             ; EAX = 0x0F
.text:0526CCD2                 mov     eax, [esp+24h+arg_0]
.text:0526CCD6                 push    eax             ; Входные данные
[b].text:0526CCD7                 call    dword ptr [edx+20h] ; GeNeRaTor <- Вот эту функцию мне нужно вызвать... Но как?? [/b]
.text:0526CCDA                 add     esp, 20h
.text:0526CCDD                 retn    8
Головоломка

Re: Доступ к неэкспортируемым функциям DLL

Добавлено: 31 июл 2009, 00:54
WinMain
Зная текущий адрес вызываемой функции, нужно найти её RVA (Relative Virtual Address). Для этого нужно из текущего адреса функции вычесть значение HMODULE (или HINSTANCE) этой DLL.
Значение RVA является постоянным и не меняется с момента последней сборки модуля. А значение HMODULE при каждой новой загрузке DLL может каждый раз отличаться. При следующей загрузке DLL нужно значение RVA прибавить к значению HMODULE загруженной DLL. Получившееся значение и есть адрес вызываемой функции.
Если функция является экспортируемой, то её RVA можно посмотреть с помощью утилиты Dependency Walker.