Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Замена кода С++ на ходу, нужно менять код во время выполнения 
:(
    Опции темы
anthony
Дата 19.7.2007, 09:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Обновленный код (устранены ошибки и предупреждения, сокращен объем, изменен стиль).

Протестировано на Win XP PE/HE SP 2 с включенным и выключенным DEP (процессоры без поддержки DEP).

Проверена большая часть настроек компиляции для MSVC 2005 PE SP 1, для других компиляторов нужно аккуратно проверять настройки.

Код

/*    Purpose: Stacked function calling.
    About: This example shows how could be organized function call from program stack.
        Example shows method of self-modification program in C.
    Algorithm:
        1. Creating 'stacked' char (byte) array - buffer for function body placement.
        2. Resolving target function address and function body size in bytes.
        3. Copying target function body into stack.
        4. Resolving 'stacked' function address and indirect call.

    Language: Ansi C.

    Environment: MSVC 2005 PE - ENU Service Pack 1.
    Options (for MSVC 2005 PE - ENU Service Pack 1 only):
        compiler -> Basic Runtime Checks -> Stack Frames (/RTCs) enabled - program works improper,
        all other options - not influencing factors.
    Program compiled with 'warning level 4' and 'treat warnings as errors' properties. */
#include "stdio.h"

/* Pointer to stackedFunction type definition. */
typedef void ( * StackedFunctionPointer ) ( int ( * printf ) ( const char *, ... ) );
/* Pointer type definition. */
typedef size_t Pointer;

/* Simple function definition. */
void stackedFunction ( int ( * _printf ) ( const char *, ... ) ) {
    _printf ( "Stacked function executed\n" );
}

int main ( void ) {

    /* Stacked char array. */
    char stackArea [ 1000 ];
    /* Pointer to stackedFunction interpreted as char array. */
    char *directPointer = ( char * ) ( ( Pointer ) stackedFunction );
    /* Pointer to stacked char array interpreted as pointer to stackedFunction. 
        Stacked char array will be filled with stackedFunction body data, 
        so this pointer points to the stackedFunction copy.*/
    StackedFunctionPointer indirectPointer = ( StackedFunctionPointer ) ( ( Pointer ) stackArea );

    /* Size of stackedFunction in bytes determination.*/
    size_t marker = ( Pointer ) main - ( Pointer ) stackedFunction;

    /* Copying stackedFunction body into stacked char array.*/
    while ( marker-- ) {
        stackArea [ marker ] = directPointer [ marker ];
    }

    /* Calling stackedFunction copy from stack.*/
    indirectPointer ( printf );

    return 0;
}


Это сообщение отредактировал(а) anthony - 19.7.2007, 11:23
PM MAIL ICQ   Вверх
bsa
Дата 19.7.2007, 10:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

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



anthony, какой у тебя процессор? Он поддеживает DEP?
PM   Вверх
JackYF
Дата 19.7.2007, 11:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

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



Вот теперь лучше.
g++ [-O2] -Wall, 4.1.3, Debian lenny - полет нормальный.

DEP, естественно, не стоит.
С ним не должно работать, так как программа пытается выполнить инструкции, находящиеся в стеке.


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Daevaorn
Дата 19.7.2007, 14:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Комодератор
Сообщений: 2155
Регистрация: 29.11.2004
Где: Москва

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



fish9370, продолжай в том же духе и получишь предупреждение.
PM MAIL WWW   Вверх
fish9370
Дата 19.7.2007, 19:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 663
Регистрация: 15.4.2007
Где: Москва

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




Добавлено @ 20:04
обсуждаем дальше..

Цитата

Использование WriteProcessMemory

Если требуется изменить некоторое количество байт своего (или чужого) процесса, самый простой способ сделать это - вызвать функцию WriteProcessMemory. Она позволяет модифицировать существующие страницы памяти, чей флаг супервизора не взведен, т.е., все страницы, доступные из кольца 3, в котором выполняются прикладные приложения. Совершенно бесполезно с помощью WriteProcessMemory пытаться изменить критические структуры данных операционной системы (например, page directory или page table) - они доступны лишь из нулевого кольца. Поэтому, эта функция не представляет никакой угрозы для безопасности системы и успешно вызывается независимо от уровня привилегий пользователя (автору этих строк доводилось слышать утверждение, дескать, WriteProcessMemory требует прав отладки приложений, но это не так). 

Процесс, в память которого происходит запись, должен быть предварительно открыт функцией OpenProcess с атрибутами доступа "PROCESS_VM_OPERATION" и "PROCESS_VM_WRITE". Часто программисты, ленивые от природы, идут более коротким путем, устанавливая все атрибуты - "PROCESS_ALL_ACCESS". И это вполне законно, хотя справедливо считается дурным стилем программирования.



Код

int WriteMe(void *addr, int wb)
  {
    HANDLE h=OpenProcess(PROCESS_VM_OPERATION
          |PROCESS_VM_WRITE,
          true,GetCurrentProcessId());
    return WriteProcessMemory(h, addr,&wb,1,NULL);
  }

  int main(int argc, char* argv[])
  {
    _asm {
      push 0x74    ; JMP --> > JZ
      push offset Here
      call WriteMe
      add esp,8
  Here:    JMP short here
    }

    printf("#JMP SHORT $-2  was changed to JZ $-2\n");
    return 0;
  }


PS. надеюсь, это никому не придет в голову, компилить под линукс.. )

Это сообщение отредактировал(а) chipset - 20.7.2007, 21:36


--------------------
undefined
PM MAIL WWW ICQ   Вверх
JackYF
Дата 20.7.2007, 11:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


полуавантюрист
****


Профиль
Группа: Участник
Сообщений: 5814
Регистрация: 28.8.2004
Где: страна тысячи озё р

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



Цитата(fish9370 @  19.7.2007,  19:56 Найти цитируемый пост)
хорош флудить!!

Daevaorn, вообще-то, модератор этого раздела. Так что не надо здесь разжигать страсти.

Цитата(fish9370 @  19.7.2007,  19:56 Найти цитируемый пост)
обсуждаем дальше..

а, собственно, что мы сейчас обсуждаем?

Теперь. Приведенные участки кода - это хорошо. Однако раздел называется: "С++: Общие вопросы".
И тема называется "Замена кода С++ на ходу". А не "Замена кода С++ на ходу в операционной системе Windows".

Так что последнее полным решением не является. Есть раздел "С++: Системное программирование и WinAPI". Вот там последний код окажется полезен, наверное.


Это сообщение отредактировал(а) JackYF - 20.7.2007, 12:12


--------------------
Пожаловаться на меня как модератора можно здесь.
PM MAIL Jabber   Вверх
Earnest
Дата 20.7.2007, 20:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 5962
Регистрация: 17.6.2005
Где: Рязань

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



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

Ладно, допустим, загрузили, расшифровали, передали управление... Однако это может быть совсем не любой код, а ведь чтобы удовлетворить задумку автора, такой код должен быть a) достаточно объемный (не три оператора), б) критичный для правильной работы приложения...

Ладно, напряглись, преодолели все трудности...
Однако не забываем, что программ с одной версией не бывает; если программа не развивается, причем быстро, кому она нафиг нужна ... А такой способ защиты будет мешать жить прежде всего самому разработчику... Особенно приятно будет изменять и отлаживать код, который вынесен из программы (помним, что он не должен быть совсем уж тривиальным).
И наконец, как уже было сказано, это спасает до получения взломщиком первого же валидного ключа (а у мало-мальски ценной программы они всегда утекают - как только появляются первые пользователи)...
Т.е. само по себе это абсолютно не достаточно. Нужно применять и другие приемы...

Короче, не стоит овчинка выделки. Сложность защиты (в смысле усилий, потраченных как на ее разработку, так и на развитие) должна соответствовать ценности программы.




--------------------
...
PM   Вверх
chipset
Дата 20.7.2007, 21:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 4071
Регистрация: 11.1.2003
Где: Seattle, US

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




 ! 
chipset
Смягчаем тон и становимся более вежливыми во избежаний последствий.
Спасибо :)
Chipset.



--------------------
Цитата(Jimi Hendrix)
Well, I stand up next to a mountain
And I chop it down with the edge of my hand
PM MAIL WWW   Вверх
DDyDog
Дата 21.7.2007, 10:43 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



1. Первый раз запустил программу(скопировал выше), вывело Hello, World!

2. Закоментировал часть кода 

Код

#include <stdio.h>
#include <conio.h>

#pragma pack ( 1 )

void Demo(int (*_printf) (const char *,...) )
{
  _printf("Hello, Word!\n");
  return;
}

int main(int argc, char* argv[])
{
  char buff[1000];
  int (*_printf) (const char *,...);
  int (*_main) (int, char **) = main;
  void (*_Demo) (int (*) (const char *,...)) = Demo;
  _printf=printf;
  /*int func_len = (unsigned int) _main - (unsigned int) _Demo;
  for ( int a=0; a<func_len; a++ ) {
        buff[a]= ((char *) Demo)[a];
  }
  _Demo = (void (*) (int (*) (const char *,...)))&buff[0];*/
  _Demo(_printf);
  getch();
  return 0;
}

Снова вывело Hello, World!
В первом случае выполнялась функция из стека (buf), во втором из сегмента кода

А вопрос такой, где произошла модификация кода? И даже если модифицировать буфер и
выполнить его, чем это будет отличатся от вызова еще одной функции адресс которой присвоен _Demo (вот если бы произвести модификацию  сегмента кода или исполняемого файла)? А стек мы и так постоянно модифицируем  smile 

И так для мыслей, может лучше вместо функций использовать обьекты-функции, и размер легче найти, и скопировать с стек легко? 

PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

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


 




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


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

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