Декомпиляция и вызов функции по адресу

ОГЛАВЛЕНИЕ

Назначение статьи – показать, как вызвать функции другой программы через вашу собственную. Это руководство будет разбито на серию шагов с общим примером, сопровождаемым применением знаний к настоящей программе.

•    Скачать демо - 75.92 Кб
•    Скачать исходный код - 8.36 Кб

Необходимые инструменты

Эта статья использует отладчик (OllyDbg можно бесплатно скачать тут) и инжектор DLL Winject (бесплатно скачивается через интернет и включен в callbin.zip). Нужен компилятор C++ для компиляции кода для DLL. Компиляция тестового приложения и попытка работы над ним, скорее всего, дадут разные результаты из-за настроек компилятора, поэтому лучше всего использовать приложение, включенное в callbin.zip.
Зачем делать это?

Есть много причин для декомпиляции вызовов к внутренним функциям процессов. Например, дополнения или модификации для игр используют прием вызова внутренних функций процесса (игры), чтобы отобразить текст на экране. Возможно, надо расширить функционал горячих клавиш программы или же надо вызвать функцию “win” в игре. Так или иначе, данный прием применяется гораздо шире, чем указано здесь. Это руководство требует хорошего значения ассемблера x86 и некоторого знания Win32 API.

Написание тестового приложения

Сначала пишется приложение, затем оно декомпилируется, чтобы увидеть, как вызывается эта функция. Будет создано простое приложение, выполняющее арифметические действия и выводящее значения с помощью функции. Ниже приведено тестовое приложение:

#undef UNICODE

#include <span class="code-keyword"><windows.h></span>
#include <span class="code-keyword"><stdio.h></span>

void mySecretFunction(int* param1, const char* param2,
                      DWORD param3, BYTE param4)
{
    printf("----------Function Entry----------\n");
    *param1 += 2008;
    printf("param1: %i\n", *param1);
    printf("param2: %s\n", param2);
    param3 *= *param1;
    printf("param3 (param3 *= *param1): %i\n", param3);
    param4 = 0x90;
    printf("param4: %i\n", param4);
    printf("----------Function Exit----------\n");
}
int main(void)
{
    int anArgument = 123;
   
    for(;;)
    {
    if(GetAsyncKeyState(VK_F11) & 1)
        mySecretFunction(&anArgument,
                         "This is the original text!",
                         123456, 4);
    else if(GetAsyncKeyState(VK_F1) & 1)
        break;
    }

    return 0;
}

Эта функция принимает четыре параметра (1 – по ссылке, 3 – по значению). Большое преимущество написания собственного приложения и его декомпиляции заключается в том, что вы уже знаете, что искать. Пытаясь вызвать функцию по адресу приложения, исходного кода которого у вас нет, вы должны быть готовы проделать большую лишнюю работу, так как это трудная задача. Будет декомпилирована отладочная сборка программы (включенная в callbin.zip), чтобы увидеть, что именно происходит по шагам. Почему отладочная сборка, а не выпускаемая сборка с выключенными оптимизациями? Это слегка облегчает анализ для отладчика, но не играет роли. Если посмотреть на выпускаемую сборку программы, в зависимости от оптимизаций компилятора, mySecretFunction(...) может быть встроена в main, и программа может выглядеть иначе, так как параметры могут храниться в статических местах. Плюс, так как функция может быть встроенной, попытка вызвать ее по адресу может быть тщетным поиском. Анализ начинается с открытия OllyDbg.

Читайте также:
  • Встраивание Python в C/C++: первая часть
    • Скачать исходные файлы - 5.23Кб• Скачать демонстрационный проект - 80.6 Кб Введение Статья "Встраивание Python в многопоточные приложения C/C++" (Linux Journal) вдохновила на более глубокое освещение темы встраивания Python. Эта статья написана с двумя целями:1. Она написана для программистов,...
  • Как экспортировать классы C++ из DLL
    •    Скачать исходники - 11.1 Кб Введение Динамически подключаемые библиотеки (DLL) являются составной частью платформы Windows с самого ее начала. DLL позволяют инкапсулировать часть функционала в автономном модуле с точным списком функций C, доступных внешним пользователям. В 1980-е годы, когд...
  • Типобезопасные обратные вызовы в C++
    •    Скачать исходники - 32.39 Кб•    Скачать документацию - 33.08 Кб Обсуждаемый класс добавляет типобезопасные обратные вызовы C++ в проекты. Его свойства заключаются в следующем:•    Любую функцию в любом классе можно вызвать откуда угодно в любом другом классе.•    Можно передать от 0 до 5 ар...
  • Написание приложений Win32 с помощью одних классов C++ (часть 4)
    • Скачать проект и демо - 97.7 Кб Добавленные возможности Макросы NOTIFY_xxx_HANDLER Есть макросы карты сообщений типа ATL, применяемые для отправки сообщений WM_NOTIFY. Благодаря их улучшению они принимают дополнительный параметр "type". Новая форма - GE_NOTIFY_xxx_TYPEDHANDLER( ... , func, t...
  • Написание приложений Win32 с помощью одних классов C++ (часть 3)
    • Скачать проект и демо - 97.7 Кб Введение Изначально это не задумывалось как третья часть главной статьи. Почему? Потому что при разработке стыковочного каркаса был сделан вывод, что при достижении определенной зрелости кода потребуется общая переделка. Во-первых, чтобы исправить ряд ошибок и ...