keng Опубликовано 30 октября, 2011 Поделиться Опубликовано 30 октября, 2011 Date: 30.11.2011Author: kengTools needed: Cheat Engine 6.1, Microsoft NotepadНе знаю точно, куда запостить, если что - пните в нужную сторону.Итак, идея проста и избита, но по ней статьи я не нашёл. Задача: Вызвать API-фунцию из самой игры (или приложения). Как нам всем хорошо известно, API-функция - это:1. Читаем статью на вики. Вдумчиво.2. Понимаем, что это, говоря по-человечески, функция (а точнее, их набор), при помощи которой все Windows-приложения (и игры в том числе) контактируют между собой и взаимодействуют с системой. Простые примеры:1. CreateFile. Создаёт файл. Удобно? Да. И из любой программы можно вызвать - создастся файл.2. MessageBox. Показывает окошко с некоторой информацией и кнопками "Ok", "Cancel" и так далее, на выбор. Позволяет добиться какой-то реакции от пользователя. Тоже крутая штука.В общем, прелесть в том, что эти функции стандартизированы, вызываются одинаково и используются в 100% приложений и игр.Тэк-с, теорией немного пропитались, пойдём дальше. Тренироваться будем на всеми любимом Блокноте.Открываем блокнот (Пуск -> Выполнить -> notepad.exe):Открываем Cheat Engine (надеюсь, не нужно показывать, как она выглядит). Присоединяемся к процессу notepad.exe и начинаем думать. В программе есть меню. В меню "Файл" есть пункт "Сохранить как", который вызывает диалоговое окошко, позволяющее сохранить (!) текущий документ. В выполнение этой-то функции мы и внедрим свой замечательный код. Делаем поиск текстового значения, вот так:Находим один-единственный адрес, хранящий эту текстовую строку. Добавляем его в таблицу адресов, жмём правой кнопкой и выбираем опцию "Find out what accessess this address" (Найти, что обращается к этому адресу). Выскакивает окошко отладчика, возвращаемся в блокнот и пробуем сохранить наш документ. В отладчике видим примерно вот такую картину:Первая функция вызвалась обратилась к нашему адресу аж 8 раз, а вот остальные - по одному. Выбираем одну из них (на свой вкус, я взял вторую), жмём кнопку "Show disassembler" (Показать дизассемблер). Открывается окно дизассемблера, в нём ничего не трогаем и идём в меню Tools - Auto Assembler (Инструменты - Автоассемблер), или жмём Ctrl+A. В окне автоассемблера набиваем следующий код:Ага, как же. Ещё немного теории!В ассемблере API-функции вызываются вот таким вот образом:push arg2push arg1push arg0call funcКомандами push мы запихиваем в стек аргументы функции (если нужны), так как это стек - запихиваем их с конца (справа налево), после чего командой call func вызываем функцию, где func - имя или адрес (в 16-й системе счисления, ибо компьютер - глуп и не понимает привычных нам арабских цифр).Попробуем вызвать функцию Beep. Кликом по названию идём в MSDN и читаем о ней статью, а кто не знает английского или не любит читать (), для тех поясняю - эта функция заставляет встроенный в компьютер динамик пищать, а в качестве аргументов принимает частоту и длительность сигнала. Итак, нам остаётся выяснить адрес функции, чтобы вызвать её из блокнота, так как все эти функции хранятся во внешних dll-библиотеках и адреса вызова для разных программ могут быть разные, ибо библиотеки эти подгружаются динамически.Идём в отладчик и выбираем меню View - Enumerate DLL's and Symbols (Вид - Пронумеровать ДЛЛ'ки и Символы). Получаем вот такое окно:Жмём правой кнопкой - Find (Найти) - вводим слово Beep и в выделенной строчке получаем адрес вызова:Возвращаемся в Авто ассемблер и нашему коду! В меню выбираем Template - Code Injection (Шаблон - Инъекция кода) и пишем вот так:alloc(newmem,2048) //2kb should be enoughlabel(returnhere)label(originalcode)label(exit)newmem: //this is allocated memory, you have read,write,execute access//place your code hereoriginalcode:mov eax,[esi+ecx*4-1C]mov [edi+ecx*4-1C],eax//наш кодpushadpush 10push ffcall 75A76DF3popadexit:jmp returnhere"msvcrt.dll"+9CCA:jmp newmemnopnopnopreturnhere:Разберу поподробней то, что мы написали. Вот этот кусочек:pushadpush 10push ffcall 75A76DF3popadPushad - сохраняет текущие значения всех регистров, чтобы мы чего лишнего не поломали нашим хитрым кодом.push 10 и push ff - толкаем в стек длительность (16 мсек) и частоту (255 Гц) в качестве аргументов нашей функции. Напомню прототип функции:Beep(Frequency, Duration)где Frequency - это частота, а Duration - это длительность.Командой call мы вызваем, собственно, нашу пищалку-пищалочку, а затем popad-ом возвращаем значения регистров на свои места.Всё дописали, перепроверили, жмём Execute (Выполнить), пробуем сохранить файл - слышим пищание. Круто!...но зачем это может быть нужно?Если почитать справку по WinAPI-функциям, можно найти немало полезных. Например, MessageBox, который можно вызывать при определённом событии. Скажем, убили нашего игрока - а нам показали значение какого-то адреса, сколько он прожил или ещё что-нибудь полезное. Такой импровизированный отладчик, ага.На этом всё. UP: Прилепил к шапке статью в виде PDF:WinApiInjection_by_keng.zip 4 Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 31 октября, 2011 Поделиться Опубликовано 31 октября, 2011 Это все круто, за исключением пары моментов, о которых не было упомянуто - Dll-ка с необходимой функцией может отсутствовать в таблице импорта игры (да, случается и такое) и, как следствие, игрой не подгружаться. В этом случае инъекцией надо подгружать библиотеку в пространство игры, затем находить в ней необходимую функцию, и затем только вызывать ее. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 31 октября, 2011 Автор Поделиться Опубликовано 31 октября, 2011 Это все круто, за исключением пары моментов, о которых не было упомянуто - Dll-ка с необходимой функцией может отсутствовать в таблице импорта игры (да, случается и такое) и, как следствие, игрой не подгружаться. В этом случае инъекцией надо подгружать библиотеку в пространство игры, затем находить в ней необходимую функцию, и затем только вызывать ее.Мой косяк, согласен. Допишу вторую часть, там покажу как библиотеки подгружать. При написании наивно верил в то, что большинство игр стандартные библиотеки и так цепляют, да и функции мы смотрели через Cheat Engine, а там только список уже подгруженных. Инъекция длл в чужой процесс - тема отдельной статьи, да и не одной. Ссылка на комментарий Поделиться на другие сайты Поделиться
sooqua Опубликовано 31 июля, 2012 Поделиться Опубликовано 31 июля, 2012 А как вызвать MessageBox? Как строку создать?)Что-то вродеinvoke MessageBox,0,'TEST','TEST',MB_OK на фасмеpush 0push "TEST" // так ведьpush "TEST" // нельзя?)push 0call bla-bla-bla<user32.MessageBoxA> Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 31 июля, 2012 Автор Поделиться Опубликовано 31 июля, 2012 Надо строку записать в память и затем push адрес строки. Ты посмотри просто, как это в дизассемблере выглядит. Ссылка на комментарий Поделиться на другие сайты Поделиться
sooqua Опубликовано 31 июля, 2012 Поделиться Опубликовано 31 июля, 2012 Так как создать строку в CE?В дизассемблере ASCII "TEST",0 Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 31 июля, 2012 Автор Поделиться Опубликовано 31 июля, 2012 Так как создать строку в CE?В дизассемблере ASCII "TEST",0Запиши в память, побайтно, а потом адрес первого байта и запихивай в стек. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения