Модераторы: feodorv, GremlinProg, xvr, Fixin
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Таблицы экспорта и импорта, Прошу помощи в реализации примера 
:(
    Опции темы
Alexey68
Дата 12.4.2013, 00:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Alexey
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 10.4.2013

Репутация: нет
Всего: нет



Здравствуйте, прошу объяснить как получить список экспортируемых и импортируемых функций?

Код

#include <windows.h>
#include <stdio.h>
#include <winnt.h>

int main()
{
    HANDLE hFile;
    BYTE *BaseAddress;
    WORD x;
    DWORD FileSize, BR, PE, OEP, Export_RVA ;
    int i;

    IMAGE_DOS_HEADER *ImageDosHeader;
    IMAGE_NT_HEADERS32 *ImageNtHeaders;
    IMAGE_OPTIONAL_HEADER32 *ImageOptionalHeader;
    IMAGE_DATA_DIRECTORY *ImageDataDirectory;
    IMAGE_EXPORT_DIRECTORY *ImageExportDirectory;
    IMAGE_SECTION_HEADER *ImageSectionHeader;


    char FileName[MAX_PATH];
    //char FileName []="test.exe";
    char SectionName[9] = { 0 };


    printf("%s\n","Enter filename...");
    scanf("%s", FileName);

    printf("%s\n","Open file...");

    hFile = CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

    if (hFile == INVALID_HANDLE_VALUE)
    {
        printf("%s\n","Cannot open file...");
        return 0;
    }

    FileSize = GetFileSize(hFile, NULL);
    BaseAddress = (BYTE *) malloc(FileSize);

    if (!ReadFile(hFile, BaseAddress, FileSize, &BR, NULL))
    {
        printf("Cannot read file...\n");
        free(BaseAddress);
        CloseHandle(hFile);
        return 0;
    }

    ImageDosHeader = (IMAGE_DOS_HEADER *) BaseAddress;



    if (ImageDosHeader->e_magic != IMAGE_DOS_SIGNATURE)
    {
        printf("Invalid Dos Header\n");
        free(BaseAddress);
        CloseHandle(hFile);
        return -1;
    }

    ImageNtHeaders = (IMAGE_NT_HEADERS *)
    (ImageDosHeader->e_lfanew + (DWORD) ImageDosHeader);

    printf("This PE Signature - %x\n ", ImageNtHeaders->Signature);


    //Как получить экспортируемые функции?
    Export_RVA = IMAGE_DATA_DIRECTORY[IMAGE_DIRECTORY_ENTRY_EXPORT];


    //

    free(BaseAddress);
    CloseHandle(hFile);

    system("pause");

    return 0;
}

С Уважением Алексей. 

M
GremlinProg
Пользуйтесь кнопкой Код, пожалуйста


Это сообщение отредактировал(а) GremlinProg - 12.4.2013, 07:31
PM MAIL   Вверх
DarthTon
Дата 12.4.2013, 12:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 7.2.2009

Репутация: 5
Всего: 6



Касательно теории рекомендую почитать оригинальную спецификацию PE формата MSDN или же что-нибудь вроде этого RSDN.

Практическая реализация:

Мой старый код для получения адреса экспортируемой функции модуля. Работает с уже отмапленым в память образом. Чтобы заработало для данных из файла необходимо подправить соответствующие виртуальные адреса, либо же подгрузить файл в память как PE образ (CreateFileMapping + SEC_IMAGE).

Код

#include <windows.h>
#include <winternl.h>
#include <string>
#include <stdint.h>

FARPROC GetProcAddressEx(HMODULE hMod, LPCSTR pSearchName)
{
    IMAGE_DOS_HEADER       *phdrDos  = {0};
    IMAGE_NT_HEADERS       *phdrNt32 = {0};
    uint8_t                *pExpDir  = nullptr;
    void                   *pFunc    = nullptr;

    //
    // Sanity checks
    //
    phdrDos  = (IMAGE_DOS_HEADER*)hMod;
    if(phdrDos->e_magic != IMAGE_DOS_SIGNATURE)
        return nullptr;

    phdrNt32 = (IMAGE_NT_HEADERS*)((size_t)hMod + phdrDos->e_lfanew);
    if(phdrNt32->Signature != IMAGE_NT_SIGNATURE)
        return nullptr;

    pExpDir  = (uint8_t*)phdrNt32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;

    // Exports are present
    if(pExpDir != nullptr)
    {
        IMAGE_EXPORT_DIRECTORY *pExpData = (IMAGE_EXPORT_DIRECTORY*)(pExpDir + (size_t)hMod);
        size_t expSize = phdrNt32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;

        WORD  *pAddressOfOrds   = (WORD*) (pExpData->AddressOfNameOrdinals + (size_t)hMod); 
        DWORD *pAddressOfNames  = (DWORD*)(pExpData->AddressOfNames        + (size_t)hMod);
        DWORD *pAddressOfFuncs  = (DWORD*)(pExpData->AddressOfFunctions    + (size_t)hMod);

        for( DWORD i = 0; i < pExpData->NumberOfFunctions; ++i )
        {
            WORD OrdIndex   = 0xFFFF;
            char *pName     = nullptr;

            if(i < pExpData->NumberOfNames)
            {
                pName       = (char*)(pAddressOfNames[i]);
                OrdIndex    = (WORD)pAddressOfOrds[i];
            }
            else
            {
                OrdIndex    = (WORD)i;
            }

            // Check by ordinal or by name
            if(((size_t)pSearchName < 0xFFFF && (WORD)pSearchName == (OrdIndex + (WORD)pExpData->Base)) || 
                ((size_t)pSearchName > 0xFFFF && pName && strcmp(pSearchName, pName + (size_t)hMod) == 0))
            {
                pFunc = (void*)(pAddressOfFuncs[OrdIndex]);

                // Invalid function pointer
                if(pFunc == nullptr)
                    continue;

                // Check chained export(function address belongs to export directory address range)
                if((size_t)pFunc >= (size_t)pExpDir && (size_t)pFunc <= (size_t)pExpDir + expSize)
                {
                    std::string chainExp((char*)pFunc + (size_t)hMod);

                    std::string strDll  = chainExp.substr(0, chainExp.find(".")) + ".dll";
                    std::string strName = chainExp.substr(chainExp.find(".") + 1, strName.npos);

                    // Load target dll
                    HMODULE hChainMod = (HMODULE)GetModuleHandleA(strDll.c_str());

                    if(hChainMod == NULL)
                        hChainMod = LoadLibraryA(strDll.c_str());

                    return GetProcAddressEx(hChainMod, strName.c_str());
                }

                return (FARPROC)((size_t)pFunc + (size_t)hMod);
            }
        }
    }

    return nullptr;
}


Аналог для импорта (Код выдран из функции класса поэтому надо допилить немного). Так же требует проекции файла как PE образа.

Код

const IMAGE_SECTION_HEADER      *pSection   = nullptr;
const IMAGE_IMPORT_DESCRIPTOR   *pImportTbl = nullptr;

if(!pFileBase)
    return false;

// Get DOS header
m_pFileBase = pFileBase;
m_pDosHdr   = (const IMAGE_SECTION_HEADER*)m_pFileBase;

// File not a valid PE file
if(m_pDosHdr->e_magic != IMAGE_DOS_SIGNATURE)
    return false;

// Get image header
m_pImageHdr = (const IMAGE_IMPORT_DESCRIPTOR*)((uint8_t*)m_pDosHdr + m_pDosHdr->e_lfanew);

// File not a valid PE file
if(m_pImageHdr->Signature != IMAGE_NT_SIGNATURE)
    return false;

// Import base
uint8_t* pImportBase  = (uint8_t*)m_pImageHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

// No import section
if(pImportBase == nullptr)
    return false;

pImportTbl = (const IMAGE_IMPORT_DESCRIPTOR*)((size_t)m_pFileBase + pImportBase);

// Imports
for (; pImportTbl->Name; ++pImportTbl)
{
    IMAGE_THUNK_DATA* rva   = {0};

    // Name of import DLL
    std::string strDllName((char*)m_pFileBase + pImportTbl->Name);

    // Choose appropriate thunk
    if (pImportTbl->OriginalFirstThunk)
        rva = (IMAGE_THUNK_DATA*)((size_t)m_pFileBase + pImportTbl->OriginalFirstThunk);
    else
        rva = (IMAGE_THUNK_DATA*)((size_t)m_pFileBase + pImportTbl->FirstThunk);

    while (rva->u1.AddressOfData)
    {
        void* addr                           = 0;   // Function address
        IMAGE_IMPORT_BY_NAME* pAddressTable  = (IMAGE_IMPORT_BY_NAME*)((uint8_t*)m_pFileBase + rva->u1.AddressOfData);
        HMODULE hMod                         = GetModuleHandleA(strDllName.c_str());

        if(!hMod)
            hMod = LoadLibraryA(strDllName.c_str());

        // import by name
        // sizeof(size_t) * 8 - 1 = 0x80000000 (x86) or 0x8000000000000000 (x64)
        if ((size_t)pAddressTable < (1LL << (sizeof(size_t) * 8 - 1) ) && pAddressTable->Name[0])
        {
            addr = GetProcAddress(hMod, pAddressTable->Name);
        }
        // import by ordinal
        else 
        {
            addr = GetProcAddress(hMod, (char*)((USHORT)pAddressTable & 0xFFFF));
        }

        rva++;
    }
}

PM MAIL   Вверх
Alexey68
Дата 12.4.2013, 22:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Alexey
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 10.4.2013

Репутация: нет
Всего: нет



Спасибо, попробую...,
>>Чтобы заработало для данных из файла необходимо подправить соответствующие виртуальные адреса
Не знаю как(
Применительно к моему коду... на си


Это сообщение отредактировал(а) Alexey68 - 13.4.2013, 00:10
PM MAIL   Вверх
DarthTon
Дата 15.4.2013, 15:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 7.2.2009

Репутация: 5
Всего: 6



Код

#include <tchar.h>
#include <windows.h>
#include <DbgHelp.h>

#pragma comment(lib, "dbghelp.lib")

void Parse(const TCHAR *pszFile)
{
    HANDLE hFile = INVALID_HANDLE_VALUE;

    if(!pszFile)
        return;

    hFile = CreateFile(pszFile, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);

    if(hFile != INVALID_HANDLE_VALUE)
    {
        IMAGE_DOS_HEADER        *pDosHdr = NULL;
        IMAGE_NT_HEADERS        *pNtHdr  = NULL;
        IMAGE_IMPORT_DESCRIPTOR *pImport = NULL;
        IMAGE_EXPORT_DIRECTORY  *pExport = NULL;

        DWORD size    = GetFileSize(hFile, NULL);
        DWORD dwBytes = 0;
        DWORD expSize = 0;
        DWORD expPtr  = 0;
        DWORD impPtr  = 0;
        BYTE* pData   = (BYTE*)malloc(size);

        if(!pData)
        {
            CloseHandle(hFile);
            return;
        }

        if(!ReadFile(hFile, pData, size, &dwBytes, NULL) || dwBytes != size)
            goto clean;

        pDosHdr = (IMAGE_DOS_HEADER*)pData;
        if(pDosHdr->e_magic != IMAGE_DOS_SIGNATURE)
            goto clean;

        pNtHdr = (IMAGE_NT_HEADERS*)(pData + pDosHdr->e_lfanew);
        if(pNtHdr->Signature != IMAGE_NT_SIGNATURE)
            goto clean;

        //
        // Import
        //
        impPtr = pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;

        if(impPtr != 0)
        {
            pImport = (IMAGE_IMPORT_DESCRIPTOR*)ImageRvaToVa(pNtHdr, pData, impPtr, NULL);

            for (; pImport->Name; ++pImport)
            {
                IMAGE_THUNK_DATA *pRVA = NULL;

                // Name of import DLL
                char *pDllName = (char*)ImageRvaToVa(pNtHdr, pData, (ULONG)pImport->Name, NULL);

                // Choose appropriate thunk
                if (pImport->OriginalFirstThunk)
                    pRVA = (IMAGE_THUNK_DATA*)ImageRvaToVa(pNtHdr, pData, (ULONG)pImport->OriginalFirstThunk, NULL);
                else
                    pRVA = (IMAGE_THUNK_DATA*)ImageRvaToVa(pNtHdr, pData, (ULONG)pImport->FirstThunk, NULL);

                while (pRVA->u1.AddressOfData)
                {
                    void* addr                           = 0;   // Function address
                    IMAGE_IMPORT_BY_NAME* pAddressTable  = (IMAGE_IMPORT_BY_NAME*)ImageRvaToVa(pNtHdr, pData, (ULONG)pRVA->u1.AddressOfData, NULL);
                    HMODULE hMod                         = GetModuleHandleA(pDllName);

                    if(!hMod)
                        hMod = LoadLibraryA(pDllName);

                    // Import by name (most significant bit is 0)
                    if ((size_t)pAddressTable < ((size_t)1 << (sizeof(size_t) * 8 - 1)) && pAddressTable->Name[0])
                    {
                        addr = GetProcAddress(hMod, pAddressTable->Name);
                    }
                    // Import by ordinal
                    else 
                    {
                        addr = GetProcAddress(hMod, (char*)((USHORT)pAddressTable & 0xFFFF));
                    }

                    pRVA++;
                }
            }
        }

        //
        // Export
        //
        expPtr = pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress;

        if(expPtr != 0)
        {
            WORD  *pAddressOfOrds   = NULL;
            DWORD *pAddressOfNames  = NULL;
            DWORD *pAddressOfFuncs  = NULL;
            DWORD  i;

            pExport = (IMAGE_EXPORT_DIRECTORY*)ImageRvaToVa(pNtHdr, pData, expPtr, NULL);
            expSize = pNtHdr->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size;

            pAddressOfOrds   = (WORD*) ImageRvaToVa(pNtHdr, pData, pExport->AddressOfNameOrdinals, NULL); 
            pAddressOfNames  = (DWORD*)ImageRvaToVa(pNtHdr, pData, pExport->AddressOfNames,        NULL);
            pAddressOfFuncs  = (DWORD*)ImageRvaToVa(pNtHdr, pData, pExport->AddressOfFunctions,    NULL);

            for( i = 0; i < pExport->NumberOfFunctions; ++i )
            {
                WORD OrdIndex   = 0xFFFF;
                char *pName     = NULL;
                size_t pFunc    = 0;

                // Export by name
                if(i < pExport->NumberOfNames)
                {
                    pName       = (char*)(pAddressOfNames[i]);
                    OrdIndex    = (WORD)pAddressOfOrds[i];
                }
                // Export by index
                else
                {
                    OrdIndex    = (WORD)i;
                }

                // Function rva
                pFunc = pAddressOfFuncs[OrdIndex];

                // Invalid function pointer
                if(pFunc == 0)
                    continue;

                // Check chained export(function address belongs to export directory address range)
                if(pFunc >= expPtr && pFunc <= expPtr + expSize)
                {
                    HMODULE hChainMod = NULL;

                    char* chainExp = (char*)ImageRvaToVa(pNtHdr, pData, (ULONG)pFunc, NULL);
                    char *strDll   = 0;
                    char *strName  = 0;

                    strDll = strtok_s(chainExp, ".", &strName);

                    // Load target dll
                    hChainMod = (HMODULE)GetModuleHandleA(strDll);
                    if(hChainMod == NULL)
                        hChainMod = LoadLibraryA(strDll);

                    pFunc = (size_t)GetProcAddress(hChainMod, strName);
                }
                else
                    pFunc = (size_t)ImageRvaToVa(pNtHdr, pData, (ULONG)pFunc, NULL);
            }
        }

    clean:
        free(pData);
        CloseHandle(hFile);
    }
}


Это сообщение отредактировал(а) DarthTon - 15.4.2013, 16:12
PM MAIL   Вверх
Alexey68
Дата 15.4.2013, 20:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Alexey
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 10.4.2013

Репутация: нет
Всего: нет



компилятор выдаёт:
[ILINK32 Error] Error: Unresolved external '_strtok_s' referenced from C:\DOCUMENTS AND SETTINGS\ADMIN\¦L+++Lг TT+T\C_AND_ASM\PE_INFO_C_IMPORT_MAIN\DEBUG\MAIN.OBJ
использую C++Builder 2007, проект консольный си

Это сообщение отредактировал(а) Alexey68 - 15.4.2013, 22:25
PM MAIL   Вверх
DarthTon
Дата 16.4.2013, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 7.2.2009

Репутация: 5
Всего: 6



Замените 
Код

strDll = strtok_s(chainExp, ".", &strName);

на
Код

strDll  = strtok(chainExp, ".");
strName = strDll + strlen(strDll) + 1; 

PM MAIL   Вверх
Alexey68
Дата 18.4.2013, 23:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Alexey
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 10.4.2013

Репутация: нет
Всего: нет



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

// Export by name
                if(i < pExport->NumberOfNames)
                {
                    pName       = (char*)(pAddressOfNames[i]);
                    OrdIndex    = (WORD)pAddressOfOrds[i];
                    printf("%x\n", pName);

                }
                // Export by index
                else
                {
                    OrdIndex    = (WORD)i;
                    printf("%x\n", OrdIndex);
                }
                // Function rva
                pFunc = pAddressOfFuncs[OrdIndex];
                printf("%x\n", pFunc);
                // Invalid function pointer
                if(pFunc == 0)
                    continue;
                // Check chained export(function address belongs to export directory address range)
                if(pFunc >= expPtr && pFunc <= expPtr + expSize)
                {
                    HMODULE hChainMod = NULL;
                    char* chainExp = (char*)ImageRvaToVa(pNtHdr, pData, (ULONG)pFunc, NULL);
                    char *strDll   = 0;
                    char *strName  = 0;
                    strDll  = strtok(chainExp, ".");
                    strName = strDll + strlen(strDll) + 1;
                    printf("%s\n", strName);
                    // Load target dll
                    hChainMod = (HMODULE)GetModuleHandleA(strDll);
                    if(hChainMod == NULL)
                        hChainMod = LoadLibraryA(strDll);
                    pFunc = (size_t)GetProcAddress(hChainMod, strName);

                    printf("%x\n", pFunc);
                }
                else
                    pFunc = (size_t)ImageRvaToVa(pNtHdr, pData, (ULONG)pFunc, NULL);
                    printf("%x\n", pFunc);
            }
        }
    clean:


M
feodorv
Пожалуйста, пользуйтесь кнопочкой "Код"


Это сообщение отредактировал(а) feodorv - 19.4.2013, 09:35
PM MAIL   Вверх
DarthTon
Дата 19.4.2013, 10:21 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 7.2.2009

Репутация: 5
Всего: 6



Ну printf'ы правильные. Может у анализируемого файла нету таблицы экспорта?   smile 
PM MAIL   Вверх
Alexey68
Дата 19.4.2013, 17:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Alexey
*


Профиль
Группа: Участник
Сообщений: 98
Регистрация: 10.4.2013

Репутация: нет
Всего: нет



пробую подгрузить файлы из system32, например regedit и выскакивает исключение на
строку:
if((size_t)pAddressTable < ((size_t)1 << (sizeof(size_t) * 8 - 1)) && pAddressTable->Name[0])
при получении списка импортируемых функций, причём несколько (итераций в цикле проходит) функций  всё же считывает.
Причём если я подгружаю "обычный" exe (не системный), то всё читает, также попробовал сторонние приложения и результат тот-же.
В чём может быть проблема, в отладчике тоже ошибка
из отладчика:
Код

00401422  |.  8B55 C4       ||MOV EDX, [LOCAL.pAddressTable]
00401425  |.  807A 02 00    ||CMP BYTE PTR DS:[EDX+2], 0    //здесь исключение
00401429  |.  74 28         ||JE SHORT main.00401453




Это сообщение отредактировал(а) Alexey68 - 19.4.2013, 17:41
PM MAIL   Вверх
DarthTon
Дата 19.4.2013, 19:08 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 106
Регистрация: 7.2.2009

Репутация: 5
Всего: 6



Вы, вероятно, грузите x64 PE файл. Или соберите сам код под х64, или поправьте структуры на их 64 битные версии.

Это сообщение отредактировал(а) DarthTon - 19.4.2013, 19:14
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Системное программирование и WinAPI"
Fixin
GremlinProg
xvr
feodorv
  • Большое количество информации и примеров с использованием функций WinAPI можно найти в MSDN
  • Описание сообщений, уведомлений и примеров с использованием компонент WinAPI (BUTTON, EDIT, STATIC, и т.п.), можно найти в MSDN Control Library
  • Непосредственно, перед созданием новой темы, проверьте заголовок и удостоверьтесь, что он отражает суть обсуждения.
  • После заполнения поля "Название темы", обратите внимание на наличие и содержание панели "А здесь смотрели?", возможно Ваш вопрос уже был решен.
  • Приводите часть кода, в которой предположительно находится проблема или ошибка.
  • Если указываете код, пользуйтесь тегами [code][/code], или их кнопочными аналогами.
  • Если вопрос решен, воспользуйтесь соответствующей ссылкой, расположенной напротив названия темы.
  • Один топик - один вопрос!
  • Перед тем как создать тему - прочтите это .

На данный раздел распространяются Правила форума и Правила раздела С++:Общие вопросы .


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Chipset, Step, Fixin, GremlinProg, xvr. feodorv.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Системное программирование и WinAPI | Следующая тема »


 




[ Время генерации скрипта: 0.0853 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.