Форум для программистов - задавайте интересные вопросы - получайте квалифицированные ответы
как записать компактнее?, динамический импорт функции
  • beos92beos92 June 2011
    msvc9-10, win32
    надо чтобы при первом вызове функция импортировалась, а при последующих - вызывалась через переходник jmp rel32
    как уменьшить код в переходнике на функцию (MessageBoxImp)?
    ExpandedWrap disabled

    void __stdcall DoImport(FARPROC fnptr, int* jmp_end)
    {
    DWORD oldProtect;
    VirtualProtect(jmp_end - 1, 4, PAGE_EXECUTE_READWRITE, &oldProtect);
    *(jmp_end - 1) = (int)fnptr - (int)jmp_end;
    VirtualProtect(jmp_end - 1, 4, oldProtect, &oldProtect);
    }

    inline __declspec(naked)
    void __stdcall MessageBoxImp(int unused, const char* text, const char* caption, int reserved)
    {
    import_thunk:
    __asm _emit 0xE9 __asm _emit 0 __asm _emit 0 __asm _emit 0 __asm _emit 0
    do_import:
    static FARPROC fnptr = GetProcAddress(LoadLibraryA("user32"), "MessageBoxA");
    __asm push offset do_import
    __asm push fnptr
    __asm call DoImport
    goto import_thunk;
    }
  • bootflasherbootflasher June 2011
    Тебе именно уменьшить код? Наверное никак, окромя перетещить _emit под call DoImport и избавиться от goto. Тем более, что ты забыл ещё один goto do_import; в самом начале.
    Или тебе всё-таки что-то другое нужно? Производительность можно поднять, например.

    P.S. Интересно, что это за жёсткий код такой? Обфусцируем, пишем трояна, обманываем антивиря или готовимся работать в чужом процессе?
  • beos92beos92 June 2011
    bootflasher, это самый обычный "ленивый" динамический импорт функции

    __asm _emit 0xE9 __asm _emit 0 __asm _emit 0 __asm _emit 0 __asm _emit 0
    - это jmp do_import, записано байтами, т.к. я хз как указать msvc что надо jmp near а не jmp short
    оно должно стоять именно в начале функции, чтобы после того как функция импортирована, она бы выглядела как "jmp MessageBoxA"

    записать код компактнее - это например было бы
    ExpandedWrap disabled

    do_import:
    DoImport(GetProcAddress(LoadLibraryA("user32"), "MessageBoxA"), &do_import);
    goto import_thunk;


    но msvc дает взять адрес метки только в asm-коде, а в C\C++ коде она пишет "идентификатор не найден" для &do_import
  • bootflasherbootflasher June 2011
    Это-то понятно. В таком случае у меня идей больше нет. Разве что немножко буковок поменьше:
    ExpandedWrap disabled

    inline __declspec(naked)
    void __stdcall MessageBoxImp(int unused, const char* text, const char* caption, int reserved)
    {
    for(;;) {
    __asm _emit 0xE9 __asm _emit 0 __asm _emit 0 __asm _emit 0 __asm _emit 0
    do_import:
    static FARPROC fnptr = GetProcAddress(LoadLibraryA("user32"), "MessageBoxA");
    __asm push offset do_import
    __asm push fnptr
    __asm call DoImport
    }
    }
Webparadox - разработка мобильных приложений под iOS и Android.