Самопальный GetProcAddress
От: ZakkeR Россия http://znav.narod.ru
Дата: 24.12.02 05:14
Оценка: 40 (3)
В ответ на топик http://www.rsdn.ru/forum/Message.aspx?mid=157597
Автор: mik1
Дата: 19.12.02


Функция-аналог GetProcAddress

На самом деле функция немного отличается, т.к. принимает имя в юникоде, и возвращает адрес через указатель.
Плюс работает медленнее, т.к. я пока решил не оптимизировать поиск по упорядоченному массиву строк, коим является список экспорта библиотек.

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

bool get_proc_address(HMODULE h, void * target, WCHAR *name)
{
    BYTE *hb = (BYTE *)h;

    DWORD na = (DWORD)(hb + *((DWORD *)(hb+0x3C)));

    DWORD ea = (DWORD)(hb + *((DWORD *)(na+0x78)));     //export table
    DWORD eas = *((DWORD *)(na+0x7C));                  //export table size

    int sz = *((DWORD *)(ea+0x18));

    DWORD *fpa = (DWORD *)(hb + (*((DWORD *)(ea+0x1C))));  //addresses
    DWORD *fna = (DWORD *)(hb + (*((DWORD *)(ea+0x20))));  //names
    WORD  *foa = (WORD *)(hb + (*((DWORD *)(ea+0x24))));   //ordinals

    while (sz>0)
    {
        char * fn = (char *)(hb+(*fna));
        WCHAR *ntf = name;
        while(*fn == *((char *)ntf))
        {
            if (*fn == 0)
            {
                DWORD ordinal = (*foa); 
                DWORD   fa = (DWORD)(hb+(*(fpa+ordinal)));  //function address
                if ((fa >= ea) && (fa < (ea+eas)))
                {
                    // address out of this PE module
                    char * a = (char *)fa;

                    DWORD ia = (DWORD)(hb + *((DWORD *)(na+0x80)));     //import table
                    for(;;)
                    {
                        DWORD dllname_rva = *((DWORD *)(ia + 0xC));
                        if (dllname_rva == 0) break;
                        char *dllname = (char *)(hb + dllname_rva);

                        char *aa = a;
                        for(;;)
                        {
                            char c1 = (char)(((*aa>='a') && (*aa<='z'))?(*aa&~32):*aa);
                            char c2 = (char)(((*dllname>='a') && (*dllname<='z'))?(*dllname&~32):*dllname);
                            
                            if (c1!=c2) break;

                            if (c1=='.')
                            {
                                aa++;
                                DWORD *lookup = (DWORD*)(hb + *((DWORD *)(ia)));
                                DWORD *ifa = (DWORD*)(hb + *((DWORD *)(ia + 0x10)));
                                for (;;)
                                {
                                    char *in = (char *)(hb + *lookup + 2);
                                    a = aa;
                                    while(*in == *a)
                                    {
                                        in++;
                                        a++;

                                        if (*in == 0)
                                        {
                                            *((DWORD *)target) = *ifa;
                                            return false;
                                        }
                                    }
                                    lookup++;
                                    ifa++;
                                }

                            }
                            aa++;
                            dllname++;
                        }
                        ia += 0x14;
                    }


                }
                *((DWORD *)target) = fa;
                return false;
            }
            fn++;
            ntf++;
        }

        fna++;
        foa++;
        sz--;
    }

    return true;
}


PS: Модератору: посмотри на for(;). После обработки _ccode_ ... _/ccode_ одна точка с запятой исчезла
regards
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.