Сишный базонезависимый код

Тема в разделе "LANGS.C", создана пользователем Quark, 9 фев 2009.

  1. Quark

    Quark New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2007
    Сообщения:
    211
    у меня 2 идеи:

    1. не использовать глобальных переменных и повыёживаться с Апишками. Все глобальные переменные запихнуть в структуру, а указатель на неё будет возвращать функция, что-то типа:
    Код (Text):
    1. void* __declspec(naked) get_global_struct_pointer()
    2. {
    3.  __asm
    4.  {
    5.   call $+5
    6.   pop eax
    7.   sub eax, ...
    8.  }
    9. }
    Что касается Апишек - тут можно заставить линкер сгенерировать их вызов в виде
    Код (Text):
    1. ...
    2. call some_func
    3. ...
    4. some_func:
    5.  db 0bB8, 0, 0, 0
    6.  jmp eax
    помойму, такое возможно. минус - придётся изуродовать сишный код.

    2. Релоки. Тут проблема в том, чтобы сгенерировать "чистый" экзешник, с одной секцией - чтобы потом можно было её легко выдрать. Линкер упорно отказывается совмещать .reloc с другими секциями. Можно, конечно, собрать свой линкер, но не очень-то охота.
     
  2. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    т.к. это Си, то будет малость сложнее. 1 что надо найти - handle of kernel
    1) анализируем seh
    2) анализируем адрес возврата из программы (но т.к. это Си, то с этим будут траблы, хотя этот способ проще и работает даже под Windows 7)
    найдя handle of kernel анализируем PE заголовок kernel32 (ибо handle это и есть указатель на загруженную dll), и ищем 2 API LoadLibraryA и GetProcAddress (ну последнюю можно и не искать, ее аналог придется написать для поиска первой), а дальше все - живи
    Код (Text):
    1. api call
    2.  
    3.   (TAPIName)(GetProcAddress(LoadLibrary(getstr(STR_KERNEL32)), getstr(STR_APINAME)))(api params);
    где getstr - функция возвращающая указатель на нужную строку из динамической памяти
     
  3. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    киньте в меня тапком, если эта тема не поднималась на васме (вроде бы 1-2 года назад).

    п.с.: лучше дельту хранить в ebx, а не eax
     
  4. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    лучше пеб - так надежнее
     
  5. max7C4

    max7C4 New Member

    Публикаций:
    0
    Регистрация:
    17 мар 2008
    Сообщения:
    1.203
    MSoft
    Ну уж извините. Помнить (даже приблизительно) все темы за 1-2 года - тапков не наберешься!
     
  6. Quark

    Quark New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2007
    Сообщения:
    211
    Прошу прощения, но поиск апишек меня не интересует. меня интересует именно базонезависимый код. Что касается "дельту хранить в евх" - не совсем понятно как вы заставите делать это компилятор?
     
  7. MSoft

    MSoft New Member

    Публикаций:
    0
    Регистрация:
    16 дек 2006
    Сообщения:
    2.854
    нда, не подумал :) че-то за асм думал в это время :)
     
  8. roman_pro

    roman_pro New Member

    Публикаций:
    0
    Регистрация:
    9 фев 2007
    Сообщения:
    291
    http://hellknights.void.ru/?r=research&p=2
     
  9. dendi

    dendi New Member

    Публикаций:
    0
    Регистрация:
    3 сен 2007
    Сообщения:
    233
    DWORD __declspec(naked)get_delta()
    {
    __asm
    {
    call __1
    __1: pop eax
    sub eax, offset __1
    ret
    }
    }

    для дельты, вызываю каждый раз когда надо. переменные храню в функцие забитой нулями. для работы с переменными делаю так:

    DWORD get_var(DWORD var)
    {
    return *(PDWORD)((DWORD)&__variables__ + get_delta() + var);
    }

    void set_var(DWORD var, DWORD val)
    {
    *(PDWORD)((DWORD)&__variables__ + get_delta() + var) = val;
    }

    надеюсь идея ясна.
     
  10. rootrat

    rootrat New Member

    Публикаций:
    0
    Регистрация:
    10 фев 2009
    Сообщения:
    16
    Сам сейчас занимаюсь написанием базонезависимого кода на C++. Удалось спроектировать прогу так, что глобальные переменные не потребовались (впрочем, как и секция данных - все данные генерируются кодом). Дельта-смещение понадобилось всего в одном месте - для получения стартового адреса процедуры, которая крутиццо в другом потоке. Адреса API функций загружаю в структуру, указатель на которую в дальнейшем передаю куда надо. Сама структура хранится в стеке текущего потока. На асме в проге написано от силы 10 строк, остальное на С++.

    Код (Text):
    1. void __declspec(naked) EntryPoint() {
    2.     __asm {
    3.         ...
    4.         // исполняем свой код
    5.         call    Main
    6.         ...
    7.     }
    8. }
    9.  
    10. void Main() {
    11.     // инициализируем таблицу вызовов
    12.     CALLTABLE CallTable;
    13.     if (!InitializeCallTable(&CallTable))
    14.         // если во время инициализации таблицы вызовов произошла ошибка - вернем управление
    15.         return;
    16.     ...
    17.     // возвращаем управление
    18.     return;
    19. }
    20.  
    21. // структура таблицы вызовов
    22. struct CALLTABLE {
    23.     // загружаются непосредственно кодом проги
    24.     DWORD (*Kernel32_LoadLibraryA)(PCHAR ModuleName);
    25.     DWORD (*Kernel32_GetProcAddress)(DWORD ModuleHandle,PCHAR ProcedureName);
    26.     // загружаются с использованием LoadLibraryA/GetProcAddress
    27.     DWORD (*Kernel32_CreateThread)(DWORD ThreadAttributes,DWORD StackSize,DWORD StartAddress,PVOID Parameter,DWORD CreationFlags,PDWORD ThreadId);
    28.     DWORD (*Kernel32_Sleep)(DWORD DelayLength);
    29.     ...
    30. };
     
  11. Quark

    Quark New Member

    Публикаций:
    0
    Регистрация:
    7 авг 2007
    Сообщения:
    211
    Кстати, по поводу ebx - есть такая директива register. Вот что говорит о ней microsoft:

    The register keyword specifies that the variable is to be stored in a machine register, if possible.

    The compiler does not accept user requests for register variables; instead, it makes its own register choices when global register-allocation optimization (/Oe option) is on. However, all other semantics associated with the register keyword are honored.

    так и зачем она нужна, эта директива? просто чтобы код позапутаннее был?
     
  12. Yerty

    Yerty New Member

    Публикаций:
    0
    Регистрация:
    6 ноя 2008
    Сообщения:
    107
    Quark кернигана надо было внимательнее читать :)

    Registry нужен для того чтобы компилятор знал что эта переменная будет использоваться очень часто и выделял под неё отдельный регистр.
     
  13. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    по привычке офтоплю

    есть пременная

    __declspec(thread) struct SavedStackRoot *o = 0;

    это стек сохраненных вершин маш стеков (и доп инфы).
    работать с данными по ней приходится полностью на регистрах, тк ни локальные, ни глобальные переменные юзать нельзя. Видимо все должно быть сделано в асм вставке. вопрос такой - как передать в регистр значение "o"? Можно ли решить эту задачу не используя асм (приходится восстанавливать регистры)?

    простите меня, нуба, за дурацкие вопросы
     
  14. TermoSINteZ

    TermoSINteZ Синоби даоса Команда форума

    Публикаций:
    2
    Регистрация:
    11 июн 2004
    Сообщения:
    3.551
    Адрес:
    Russia
    Не извращайтесь. Заюзайте
    Код (Text):
    1.  gcc -fpic
     
  15. pr0mix

    pr0mix New Member

    Публикаций:
    0
    Регистрация:
    30 июл 2008
    Сообщения:
    107
    Зайди на мой сайт:) в раздел souces - там есть пример базонезависимого кода на С++.