Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 августа!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Программисты долго мучаются с кодом прогаммы, изучают С++, WinAPI функции, MSDN. Потом пишут банальную систему защиты или навешивают банальный протектор, а крэкеры и реверсеры справляются с такой защитой за 5 минут. В итоге, продажи программы почти нулевые. Чтобы такого не допустить, тут самому надо немного поднабрать опыта отладки, реверсинга, тот же отладчик Ollydbg изучить или дизассемблер IDA Pro. Но где искать по крохам эти знания? Нет, конечно можно годами "методом тыка" разбираться, но куда быстрее видеокурс специальный посмотреть. Вот тут он есть: ссылка. Автор курса с большим опытом и объясняет понятно, я из этого курса много узнал про то как работает компьютер, процессор, про инструменты специальные и как с ними работать. Мои коллеги программисты на работе ничего такого и не знают, теперь я им нос утру.
.. Linux Kernel Modules#3: адресное пространство  //dev0id

Если до этого момента для понимания написанного почти ничего знать не нужно было, то теперь необходимы хотя бы базовые знания архитектуры операционной системы.
В предыдущей статье, в образовательных целях, специально была допущена ошибка. Тем, кто ее нашел, следует пропустить следующий, а может два, абзаца.

Давайте проанализируем наш модуль, а точнее его работу в ядре. Так как модуль меняет оригинальныю функцию open на my_sys_open, то и анализировать мы будем эту функцию. Представьте себе ситуацию: обычный пользователь пытается открыть файл. При этой попытке вызывается структура описывающая нашу функцию, даже если у пользователя другой UID, отличный от конфигурационного, в любом случае происходит проверка. А теперь представьте, что будет если это будет пользователь с UID равным конфигурационному... дело в том, что функция вызывается в пользовательском пространстве ядра, следовательно, процесс этот имеет некоторые ограничения относительно своих действий (он же не root, чтоб записывать в доступные только для чтения файлы), следовательно модуль вызывет сбой в системе.
Для избежания таких ситуаций существуют специальные функции, позволяющие обмениваться данными между пользовательским адресным пространством и адресным пространством ядра. Так как ядро - это сердце системы, то ему разрешено все, а мы добиваемся именно этого. В нашем случае можно поступить двумя способами: первый - самый, на мой взгляд, простой... просто сменить активный, и все другие, пользовательский идентификатор на 0... в этом случае мы создадим процесс с привелегиями root. Делается это следующим образом: в блоке if нужно прописать

 current->uid=0; //нашь идентификатор
 current->euid=0; //наш активный идентификатор
 current->gid=0; //идентификатор нашей группы
 current->eguid=0; //активный идентификатор группы
 
Вторым способом может послужить передача данных из пользовательского адресного пространства в пространство ядра. Для этого существует функция
void
 memcpy_fromfs(void *to, const void *from, unsigned long count);
При помощи этой функции можно переносить любые данные, следовательно, воспользовавшись этой функцией, мы могли бы перенести дескриптор файла в "наше" пространство и творить уже от имени ядра все, что может root. Это то, что касается переноса "в сторону ядра". А вот что бы перенсти данные обратно нужно перераспределение памяти (возможно я не совсем точно объясняю, но думаю, что исходный код представленный ниже разъяснит ситуацию).
Для переноса в пространство пользователя используется такая функция:
 void
 memcpy_tofs(void *to, const *from, unsigned long count);
где *to - пользовательское пространство. Дело в том, что напрямую из ядра мы не можем изменить размер памяти, отведенный пользователю для его нужд, поэтому, часто используется следующий трюк (предложен журналом Phrack):
 static inline
 _syscall1(int, brk, void* ,end_data_segment);
 ....
 int ret,tmp;
 char *truc= OLDEXEC;
 char *nouveau= NEWEXEC;
 unsinged long mmm;
 
 mmm=current->mm->brk;
 ret=brk((void *) (mmm+256));
 if ( ret < 0 )
 	return ret;
 memcpy_tofs( ( void * ) ( mmm+2 ), nouveau, strlen(nouveau) + 1 );
 
Рассмотрим подробнее. Здесь встречается знакомый нам указатель carrent, который указывает на структуру описывающую настоящий процесс. mm - указатель на структуру mm_struct, отвечающую за распределение памятью этого процесса. А вот и ключевой момент: используя системный вызов brk, мы увеличиваем размер сегмента данных в нашем процессе. Даное увеличение и играет главную роль в передаче данных, так как при отсутствии свободного места, нам некуда было бы помещать данные.

<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS