RockHammer Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 (изменено) Добрый день. Вот в этой теме мне ответил Keng по поводу инъекции кода, а точнее её переноса на с++.Вот цитатка:0. Получаем все нужные права через OpenProcess и VirtualProtectEx.1. Выделяем себе кусок памяти в адресном пространстве игры через VirtualAllocEx.2. Через WriteProcessMemory записываем в него код инъекции (в 16-ричной системе счисления. На конце - jmp. Все ассемблерные команды - в опкодах, т.е. как бы после компиляции).3. Берем адрес для инъекции. Берем место, куда записали код. Нам нужно сделать относительный прыжок, верно? Отнимаем один адрес из другого. Все время путаю, какой откуда, но это можно проверить в отладчике. 4. Разворачиваем задом наперед этот адрес (в 16-ричном представлении!), сохраняем куда-нибудь.5. Берем адрес, куда записали код инъекции + длину инъекции в байтах + 4. Отнимаем этот адрес из адреса для инъекции + еще пять байт. Потому что сначала мы прыгаем из игры в наш код, а потом из нашего кода обратно в игровой. +5, чтобы не прыгнуть на то место, с которого прыгали изначально - прыгать нужно _после_ этого места.6. Записываем через тот же WriteProcessMemory адрес в конец кода инъекции (чтобы было jmp + адрес).7. Записываем в место инъеции "jmp + смещение для кода инъекции + nop".8. Готово! 0. Ok...1. Oook...Я не совсем понимаю, что делает VirtualAllocEx. Он берет процесс, переходит по адресу, задает размер, выделяет память...Но как узнать адрес выделенной памяти?Я пытался провести "опыты" на notepad.exe (я криминален), взял произвольный адрес, и алокнул 16 байт. Знаете? Ничего не произошло с этим адресом (тот, который я взял). Я наблюдал через СЕ за этим регионом.Может быть алокнулось где-то еще, но где?2. Ooook... Через WriteProcessMemory записываем в него код инъекции (в 16-ричной системе счисления. На конце - jmp. Все ассемблерные команды - в опкодах, т.е. как бы после компиляции).Ooook, записываем... В кого в него? В адрес выделеной памяти? Ладно, а как в него записать что-то? Всмысле, асемблерные инструкции через WPM, как занести? На конце jmp чтобы вернуться на оригинальный адресс+5 (это затерли мы под прыжок).3. Ладненько 3. Берем адрес для инъекции. Берем место, куда записали код. Нам нужно сделать относительный прыжок, верно? Отнимаем один адрес из другого. Все время путаю, какой откуда, но это можно проверить в отладчике. Берем адресс для инъекции? Т.е. исходный адрес? Ок, взяли. Алоченая память? Взяли. Какой относительный прыжок?Что из чего отнимаем? И самое главное: зачем?4. Поехали 4. Разворачиваем задом наперед этот адрес (в 16-ричном представлении!), сохраняем куда-нибудь.Разворачиваем? Это как? Было 0x123456 а станет 0x654321 ? 5. Стартуем 5. Берем адрес, куда записали код инъекции + длину инъекции в байтах + 4. Отнимаем этот адрес из адреса для инъекции + еще пять байт. Потому что сначала мы прыгаем из игры в наш код, а потом из нашего кода обратно в игровой. +5, чтобы не прыгнуть на то место, с которого прыгали изначально - прыгать нужно _после_ этого места.Алокнутый адрес? Взяли. + что? Длинну инъекции? Тоесть... Ах, ну да. Насколько жирная наша инъекция. Только тут нюансик: общий жир выделенной памяти или жир только наших инструкций? Если жир наших инструкций, то как их определить? (всмысле, сколько байт мы занимаем)? +4. Зачем отнимать? Смысл? 6. Ok 6. Записываем через тот же WriteProcessMemory адрес в конец кода инъекции (чтобы было jmp + адрес).Тут вопросов нет. Как я понял, мы записываем прыжок на оригинальный адрес + 5 (последствия прыжка), чтобы оригинальный игровой код выполнялся как ни в чем не бывало.7. Ok 7. Записываем в место инъеции "jmp + смещение для кода инъекции + nop".Вот тут не понятно. Зачем записывать это? "в место инъекции" тоесть в алокнутую память? 8. Единственный, пожалуй, шаг - по которому нет вопросов P.s. пытаюсь писать код сам и сам же понимать его смысл. Выходит пока что на 20-30% ))void Memoria(char Process[], int addr) //просто не знаю пока что передавать{ DWORD oldProtect = 0; DWORD pID = GetProcessByName(Process); //получаем процесс из шапке HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); //открываем VirtualProtectEx(hProc, (LPVOID)addr, (size_t)size, PAGE_EXECUTE_READWRITE, &oldProtect); //снимаем защиту ....... //do somethink CloseHandle(hProc); //закрываем хендл}void Memoria(char Process[], int addr) //просто не знаю пока что передавать{ DWORD oldProtect = 0; DWORD pID = GetProcessByName(Process); //получаем процесс из шапке HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pID); //открываем VirtualProtectEx(hProc, (LPVOID)addr, (size_t)size, PAGE_EXECUTE_READWRITE, &oldProtect); //снимаем защиту VirtualAllocEx(hProc, (LPVOID)addr, (size_t)size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); ....... //do somethink CloseHandle(hProc); //закрываем хендл} Изменено 8 марта, 2015 пользователем RockHamer Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 VirtualAllocEx возвращает адрес выделенной памяти. Тебе нужно присвоить его какой-нибудь переменнойДа, в адрес выделенной памяти записать. Записать опкоды, как выше писал кенг. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 8 марта, 2015 Автор Поделиться Опубликовано 8 марта, 2015 VirtualAllocEx возвращает адрес выделенной памяти. Тебе нужно присвоить его какой-нибудь переменнойУгу... Значит, вот так?DWORD NewMemka = VirtualAllocEx(hProc, (LPVOID)addr, (size_t)size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);Тут всё правильно? Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 Чего ж ты до этого момента терпел с вопросами, если не понял, как оно работает? Давай на примере посмотрим. Есть у тебя вот такой участок игрового кода: 0x100: nop0x101: nop0x102: nop0x103: nop0x104: nop 1 инструкция nop = опкод 0x90 = 1 байт памяти. Итого 5 байт. Нам нужно сделать так, чтобы игра, дойдя до адреса 0x100, выполнила наш код, длина которого больше 5 байт, а затем вернулась обратно. Как это сделать? Прежде всего, нужно куда-то записать код, который наш, чтобы игра могла его выполнить. Для этого нужно выделить участок памяти. Допустим, что длина нашего кода будет 10 байт. Дальше я буду писать в псевдокоде: allocated_mem = VIrtualAllocEx(10) После выполнения видим, что allocated_mem присвоилось значение 0x110. Это для примера. Итого получаем: 0x100: nop0x101: nop0x102: nop0x103: nop0x104: nop...0x110: <- отсюда лежит 10 байт выделенной нам памяти, в которую мы можем писать0x1110x1120x1130x1140x1150x1160x1170x1180x119 Так, память выделили, теперь нужно научить игру переходить на нужный нам адрес. Для этого нам понадобится команда безусловного перехода - jmp. Она прыгает на относительный адрес, а не на абсолютный. Показываю, опять же, на примере: 0x10: my_code...0x15: jmp my_code Вместо "my_code" по адресу 0x15 подставится -5. То есть на пять байт выше относительно текущего адреса (15-5 = 10). Прыжки вниз по коду - то есть вперед - прибавляют нужное смещение от текущего адреса. Смотрим еще раз на код игры и выделенную память. Код игры - 0x100, выделенная память - 0x110. То есть нам нужно прыгнуть ниже по коду, а значит вместо игрового кода по адресу 0x100 записать: 0x100: jmp 10 То есть на 0x110, на 10 байт вперед. Итого управление передастся на наш код, но нам нужно будет вернуться обратно. Чтобы вернуться обратно, нам понадобится еще один jmp и адрес, куда прыгать. Опкод команды jmp занимает 1 байт, адрес - 4 байта, итого 5. Так что для нашего кода нам остается 5 байт, ибо всего у нас их 10. То есть в выделенной памяти по адресу 0x115 нам нужно записать "jmp адрес", где адресом будет игровой код, откуда мы прыгнули, +5 байт. Почему +5? Вот почему: Игровой код:0x100: jmp 100x105: ... jmp 10 занимает 5 байт. Нам нужно продолжить выполнение с команды, идущей сразу после нее, то есть 0x105. Если прыгнем опять на 0x100 - получится, что прыгнули снова на jmp 10, в итоге получится рекурсия и игра зависнет. В общем, нам нужно сделать jmp с адреса 0x115 наверх, на 0x105. Итого: 0x115: jmp -10 У нас есть адрес игрового кода (game_addr), адрес, куда нужно прыгнуть (game_addr + 5), адрес нашей выделенной памяти (allocated_mem), ее размер (10 байт) и адрес, откуда прыгать (allocated_mem + 10 - 5). Считаем, получается, что адрес, куда нужно прыгнуть, это 0x105, адрес, откуда прыгать - 0x110+10 - 5 = 0x115, вычитаем, получаем 110 - 115 = -10. Что дает нам: 0x100: jmp 0x1100x105: <- сюда прыгнем обратно...0x110: <- сюда прыгнем из игрового кода0x111:0x112:0x113:0x114:0x115: jmp 0x105 <- отсюда прыгнем обратно И вот, у нас остается еще целых 5 байт для кода, который выполнит игра вместо своего оригинального. Берем WriteProcessMemory и записываем 5 байт по адресу нашей выделенной памяти, то есть 0x110. Как вернуть все на место? Скажем, когда человек нажал кнопку, чтобы функцию трейнера отключить. У нас есть адрес игрового кода, адрес нашей выделенной памяти, и оригинальный игровой код, который мы заблаговременно сохранили перед его изменением. Алгоритм простой: 0. По адресу 0x100 (игрового кода) используя WriteProcessMemory записываем оригинальный игровой код.1. Очищаем выделенную нами память через VirtualFreeEx. Вот как-то так и работает инъекция кода в Cheat Engine. Единственное, каждый вызов WriteProcessMemory лучше оборачивать в Virtual(Un)ProtectEx. 2 Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 8 марта, 2015 Автор Поделиться Опубликовано 8 марта, 2015 (изменено) Чего ж ты до этого момента терпел с вопросами, если не понял, как оно работает?Главное - дотерпеть))) А если серьезно - просто или времени не было... Или ноута нормального. Впринципе, сейчас тоже ноута нормального нет... И монитора... Но, думаю, смогу что-нибудь сделать на своём старом ноуте. Дал процессу студии высший приоритет, она шустрей стала. Начал разбираться в твоих инструкциях. И вот немножко призадумался)Спасибо, постараюсь вникнуть ) Единственное, каждый вызов WriteProcessMemory лучше оборачивать в Virtual(Un)ProtectEx.Это всмысле:VirtualProtectEx(PAGE_EXECUTE_READWRITE)WriteProcessMemoryVirtualProtectEx(oldProtect) ?Вот так? Изменено 8 марта, 2015 пользователем RockHamer Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 Ага. Можешь посмотреть примеры использования этой функции в интернете. А если MSVS медленно работает - поставь себе mingw и не заморачивайся. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 8 марта, 2015 Автор Поделиться Опубликовано 8 марта, 2015 Ага. Можешь посмотреть примеры использования этой функции в интернете. А если MSVS медленно работает - поставь себе mingw и не заморачивайся.Тут даже не в этом деле) Ноут не тянет даж видео на ютубе) А что такое Mingw? Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 MinGW - это портированный набор компиляторов GCC под Windows. PS: Первым делом лучше смотреть все незнакомые слова в гугле. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 8 марта, 2015 Автор Поделиться Опубликовано 8 марта, 2015 MinGW - это портированный набор компиляторов GCC под Windows. PS: Первым делом лучше смотреть все незнакомые слова в гугле.Уже посмотрел, скачал... Но там только инсталятор. Никак не могу запустить саму программу, а не инсталятор. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 Оно работает из командной строки, нужно папку c:\mingw\bin\ положить в переменную PATH, а потом просто набираешь в командной строке "g++ main.cpp -o my_cool_hack.exe", находясь в папке с исходным кодом. MSVS для маломощных компьютеров мало подходит, т.к. жрет много ресурсов и заметно тормозит, если их нет. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 8 марта, 2015 Автор Поделиться Опубликовано 8 марта, 2015 Оно работает из командной строки, нужно папку c:\mingw\bin\ положить в переменную PATH, а потом просто набираешь в командной строке "g++ main.cpp -o my_cool_hack.exe", находясь в папке с исходным кодом. MSVS для маломощных компьютеров мало подходит, т.к. жрет много ресурсов и заметно тормозит, если их нет.Ok, как это сделать?) Я про переменную PATH. Ссылка на комментарий Поделиться на другие сайты Поделиться
Гость Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 Ok, как это сделать?) Я про переменную PATH.Для Windows 7 и выше: Пуск -> Правая кнопка мыши на "Компьютер" -> "Свойства", в открывшемся окне (слева) - Дополнительные параметры системы. В открывшемся окне ("Свойства системы"), на вкладке "Дополнительно" - кнопка "Переменные среды" (в самом низу). В "Системных переменных" (область снизу), есть ключ "Path". Кажется, это имел в виду keng, если я не ошибаюсь. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 Совершенно верно. Вариант для командной строки:setx path "%path%;c:\mingw\bin\" setx - изменяет переменную окружения, %path% возвращает текущее значение переменной path, ; - разделитель. Получается так: path = path + ";c:\mingw\bin" Думаю, что лучше запускать эмулятор командной строки с правами администратора. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 8 марта, 2015 Автор Поделиться Опубликовано 8 марта, 2015 Совершенно верно. Вариант для командной строки:setx path "%path%;c:\mingw\bin\" setx - изменяет переменную окружения, %path% возвращает текущее значение переменной path, ; - разделитель. Получается так: path = path + ";c:\mingw\bin" Думаю, что лучше запускать эмулятор командной строки с правами администратора.Яяяясно... И что я сделал? Взломал пентагон? Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 Вторую команду вводить в консоль было не нужно, я просто показал в псевдокоде, что делает первая. Если перезапустить консоль и ввести "path" еще раз - что она выдаст? Ссылка на комментарий Поделиться на другие сайты Поделиться
Coder Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 Вас куда-то понесло уже не туда. Тема топика внедрение кода в другой процесс посредством C++/WinAPI, а вы здесь уже пошли компиляторы перебирать. Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 Согласен, нужно это обсуждение перенести в отдельную тему. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 8 марта, 2015 Автор Поделиться Опубликовано 8 марта, 2015 Вторую команду вводить в консоль было не нужно, я просто показал в псевдокоде, что делает первая. Если перезапустить консоль и ввести "path" еще раз - что она выдаст?Если ещё раз её ввести, то выдает тоже самое, что и на первом скриншоте вверху. Много много букв, где описываются всяческие пути. Вас куда-то понесло уже не туда. Тема топика внедрение кода в другой процесс посредством C++/WinAPI, а вы здесь уже пошли компиляторы перебирать.Дык ведь попутная же тема, не? Ссылка на комментарий Поделиться на другие сайты Поделиться
Coder Опубликовано 8 марта, 2015 Поделиться Опубликовано 8 марта, 2015 Если ещё раз её ввести, то выдает тоже самое, что и на первом скриншоте вверху. Много много букв, где описываются всяческие пути. Дык ведь попутная же тема, не?Компилятор и реализация алгоритма - не имеют ничего общего. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 9 марта, 2015 Автор Поделиться Опубликовано 9 марта, 2015 Вопросик небольшой... Выделенная память что-то не выделяется. Т.е. я сделал всё как нужно, но почему-то адрес выделенной памяти не печатается в консоли. Может краска закончилась? Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 9 марта, 2015 Поделиться Опубликовано 9 марта, 2015 Зачем ты это сделал, непонятно.При выделении памяти порядок другойНа кодкейвы нужно так писатьVirtualAlloxEx(адрес не указываешь, пусть сам ищет подходящее место для выделения памяти)VirtualProtectEx(адрес, который вернула предыдущая функция) - и даже это, в принципе, необязательно, так как ты нужные права сразу ставишь в выделялке.WriteProcessMemory(и снова адрес, который вернула выделялка памяти)А для затирания оригинальных инструкций прыжком на кейв уже надоVPExWPMVPEx(oldprotect)Как-то так. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 9 марта, 2015 Автор Поделиться Опубликовано 9 марта, 2015 (изменено) Зачем ты это сделал, непонятно.При выделении памяти порядок другойНа кодкейвы нужно так писатьVirtualAlloxEx(адрес не указываешь, пусть сам ищет подходящее место для выделения памяти)VirtualProtectEx(адрес, который вернула предыдущая функция) - и даже это, в принципе, необязательно, так как ты нужные права сразу ставишь в выделялке.WriteProcessMemory(и снова адрес, который вернула выделялка памяти)А для затирания оригинальных инструкций прыжком на кейв уже надоVPExWPMVPEx(oldprotect)Как-то так.Олрайд, бат хау кен ай ду зис? LPVOID NewMem = VirtualAllocEx(hProc, NULL, size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);Вот туточки он просит адрес. Что сделать? Я знаю только NULL, что значит - "пусто". Или нужно как-то по другому это реализовать? И еще вопросик, когда буду VirtualFreeEx делать, то какоой тип памяти брать? MEM_DECOMIT или MEM_RELEASE? Изменено 9 марта, 2015 пользователем RockHamer Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 9 марта, 2015 Поделиться Опубликовано 9 марта, 2015 Вот туточки он просит адрес. Что сделать? Я знаю только NULL, что значит - "пусто". Или нужно как-то по другому это реализовать? Его и ставь И еще вопросик, когда буду VirtualFreeEx делать, то какоой тип памяти брать? MEM_DECOMIT или MEM_RELEASE? Первый. А можешь и оба ) Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 9 марта, 2015 Автор Поделиться Опубликовано 9 марта, 2015 Его и ставь Первый. А можешь и оба )Я когда RELEASE поставил - вообще ничего не произошло. Поставил DECOMIT - все байты и вся память стрелась)))Еще, что удивило - я ставлю в алоке - 32 байта алокнуть, а он алокает вот так: сначала 0x320000 потом 0x330000. По 10.000 алокает)Т.е. ему как бы вообще пофигу, что я напишу. Он сам решает сколько алокать) Он как быть "Fuck the system" Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 9 марта, 2015 Поделиться Опубликовано 9 марта, 2015 Цитирую MSDN: "The pointer that specifies a desired starting address for the region of pages that you want to allocate." Это - про второй аргумент VirtualAllocEx. Если надо выделить память в конкретной области - даем адрес этой области. Аргумент не обязательный. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения