Изменение структур скомпилированных программ

Проект по предмету «Информатика»
Информация о работе
  • Тема: Изменение структур скомпилированных программ
  • Количество скачиваний: 2
  • Тип: Проект
  • Предмет: Информатика
  • Количество страниц: 10
  • Язык работы: Русский язык
  • Дата загрузки: 2021-09-14 10:19:57
  • Размер файла: 470.56 кб
Помогла работа? Поделись ссылкой
Информация о документе

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

Если Вы являетесь автором текста представленного на данной странице и не хотите чтобы он был размешён на нашем сайте напишите об этом перейдя по ссылке: «Правообладателям»

Можно ли скачать документ с работой

Да, скачать документ можно бесплатно, без регистрации перейдя по ссылке:

           Департамент Образования города Москвы


    Индивидуальный проект ученика 10 “Б” класса


            По теме: “Изменение структур скомпилированных программ”






     

                        Руководитель:














Москва 2021


Оглавление:

1.1…Задачи проекта

1.2…Актуальность проекта

1.3…Введение в тему

1.4…Начало

1.5…Написание программы JMP

1.6…Итоги и результаты
























                                               Задачи проекта:

1.Знакомство пользователя с работой программ.

2. Знакомство с ассемблером, базовый реверсинг

3. Написание программы на C++ изменяющей действия другой программы на уровне взаимодействия ассемблерных команд.


                                                       Актуальность:

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


                                                     Введение:

Итак, когда мы нажимаем кнопку “скомпилировать” в нашей IDE среде, никакой магии не происходит и программа в подавляющем большинстве собирается на ассемблер – набор препроцессорных команд и инструкций, требуемый для ее конечного исполнения. Ассемблер можно ассоциировать с привычными языками программирования и на основе с этим воспринимать его и работать с ним. Любую программу можно с помощью таких средств как IDA, OLLYDBG, x64dbg и прочих разобрать на эти команды ассемблера и работать с ними. На этом этапе я и вывожу главную цель проекта.

Создание простой игры(программы для примера) и изменение ее условий с помощью сторонней программы.




                                            Начало:

Итак, начнем с программы для изменения, эта будет простая непроходимая игра в стиле змейки. На карте будет всего 2 монеты, а для ее успешного прохождения потребуется 5, и каждый раз она будет выводить ошибку о недостаточном количестве монет, но в случае набора 5 она выведет успешный результат(что невозможно в условиях простой работы)

Скрины и код проверки ниже:




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


                                             Написание программы JMP:

//Ремарка: весь описанный софт собран в x86 компоновке

Для того, чтобы мы могли работать с программой, нужно взаимодействовать с ее главным потоком, записывать обращения в ее адреса и пересылать в собственные. Для этого нужно создать в процессе программы свой собственный поток, сделать это можно через библиотеку динамической компоновки DLL, которая в случае атаки в процесс программы создаст новый поток.

Для этого этого создаем в нашей IDE новые проект типа dll и сразу в главной win api функции, которая принимает аргумент статуса процесса подключения, если ее сообщение равно DLL_PROCESS_ATTACH, значит dll вошла в область работы с программой, тогда мы и создадим новый поток MainThread, в котором и бдуем проводить манипуляции:

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

Теперь более конкретно разберем задачу нашей программы. Закидываем программу в интерактивный дизассемблер, в моем случае это IDA, и ищем нашу функцию проверки score среди ассемблерных команд, c помощью комментариев от IDA это не составит проблем:

Итак, мы видим 2 сообщения о неуспешном и успешном прохождении игры, а между ними ассемблерную инструкцию cmp, cmp означает сравнение двух регистров, в нашем случае сравнивается некая переменная esi и число 5, нетрудно догадаться что это и есть наша игровая проверка.

Теперь посмотрим на адрес 00424643, там в нашу переменную esi помещается некая другая внешняя переменная dword, получается эта и есть искомая входная переменная score в функцию и наша задача заменить ее на число > или = 5.

Как мы это сделаем? Познакомимся с ассемблерной командой JMP, JMP – это безусловный переход по указанному адресу, по адресу 00424643 мы поставим JMP, а адрес укажем на функцию внутри нашей dll, которую мы подключим в главный поток, внутри dll произойдет присвоению esi числа больше 5 и мы снова вернемся на адрес главного потока. Операцию сделаем на ассемблерном коде, благо c++ позволяет.


Итак, вот функция, который реализует это:


Разберем ее код. Входящие значения – адрес внутри функции на который будет ставиться JMP, ну я его уже писал – 0x424643, второе значение – адрес функции внутри dll на которую будет идти переход, и третье – количество байт.

Конкретно расскажу про третий входной аргумент. Ассемблерная команда считается полной и независимой если ее размер выше или равен 5 байтам, если ставить jmp на меньший размер, то это просто приведет к ошибкам ассемблера. Посмотрим снова на ассемблерный код, байтового размера команды mov нам не хватит, чтобы поставить jmp, поэтому придется захватить еще одну команду – push 0, их общий байтовый размер составит: 0x424649 -0x424643 = 6 байт, этого сполна хватит, даже придется 1 байт нопить.

Итак, 9 строка в коде это и есть проверка условия на необходимое кол-во байт,

В 14 мы устанавливаем на блок памяти флаг PAGE_EXECUTE_READWRITE, чтобы мы могли изменять эти байты, сохраняя предыдущий флаг блоков в curprotection и в 24 строке , после изменения байтов, возвращаем старые флаги на блок памяти.

16 строка – ноппинг байтов, мы изменяем каждый из 6 байтов на 0x90, это на ассемблерном коде означает действие nope, то есть в этом месте никаких действий происходить не будет, это не обязательное действие, но нужное для того, чтобы случайно не изменить байты на то, что ненадо.

18 строка – вычисление конечного адреса на который будет происходить JMP, относительного смещения между адресом того, куда ставиться JMP и адресом функции внутри dll.

Теперь более подробно о ассемблерных действиях, первый байт всегда означает саму команду :jmp, add, push, xor и т.д. А остальные это аргументы, с которыми происходит взаимодействие по команде ассемблера (тело команды).

Поэтому в 20 строке я по ссылке на адрес типа байта изменяю его значение на 0xE9, E9 – означает ассемблерную инструкцию JMP, дальше прибавляю к адресу в 21 строке 1 байт, смещаясь к телу команды и по ссылке адреса на значения DWORD устанавливаю адрес на функцию на которую происходит JMP(та самая внутри нашей dll).

На этом функцию установки JMP завершена, осталось лишь написать нашу новую функцию помещения в регистр esi числа больше 5:

Создадим функцию с препроцессорный регистром __declspec, и включим атрибут naked, что даст возможность написать полную функцию на ассемблере, дальше через __asm переключаемся на ассемблер и записываем в регистр esi условную 6, так же незабываем указать push 0 , так как из этой команды и сформировались 6 байтов необходимые для JMP на адрес.

Следующая команда это JMP[jump2], JMP ,как вы уже знаете, это безусловный прыжок на указанный адрес, а jump2 это адрес команды следующей после тех, которые мы заменили на JMP, то есть мы изменяем esi и возвращаемся на ту команду, которая следовала бы, если бы не ставили JMP на оригинальный адрес.

Теперь в созданном раннее потоке от dll, вызываем функцию jmp:

Adr = адрес куда ставим jmp;

Bytel = длина байтов;

Jump2 = команда следующая после места куда мы ставим jmp;

Незабываем все запустить в бесконечный цикл while, чтобы поток не завершался после установки jmp.

На этом можно сказать, что написание окнчено!

Самое время запустить программу, подключить в нее dll и посмотреть на результат:

Успех!

                                                           Итог:

В этом проекте я показал способы работы с ассемблером, на котором работают скомпилированные программы, способы взаимодействия и прочее.

На c++ я создал программу и написал еще одну, благодаря, которой обошел невозможный код проверки и победил. Работайте и подстраивайте программу под свои нужды и теперь уже неважно в каком она ввиде!












Ресурсы:

guidehacking.com

yougame.biz

brokencore.club

youtube.com