Trix Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 Думаю, тема не такая и сложная, однако, разобраться с ней сам я не смог, поэтому решил написать данный топик. Дело вот в чем, есть команда CALL gta-vc.exe + AE8F0 || call 004AE8F0 || E8 DD E8 0D 00 Взаимосвязь между командой и байтами я не вижу, как ни крути... Как понял E8 - равносильно команде call, тогда как упаковать мой адрес в эти байты? Вот мой кодец Скрытый текст int iProcessId = 1480; Process proc = Process.GetProcessById(iProcessId); IntPtr hHandle = OpenProcess(ProcessAccessFlags.All, false, iProcessId); int ptr_base = (int)proc.MainModule.BaseAddress; byte[] asm = new byte[] { 0x68, 0xB1, 0x00, 0x00, 0x00 , // - push 000000B1 { 177 } 0xE8, 0xE6, 0xE8, 0x5D, 0xFF, // - call gta-vc.exe+AE8F0 0x59, // - pop ecx 0xC3 // - ret }; нашел базовый адрес модуля игры (если ошибаюсь, поправьте) Собственно, как записать адрес я затрудняюсь.... Подскажите пожалуйста, на сколько мне подсказали, то что я ищу: ptr_base + 0xAE8F0 + 5 //Как это можно записать в код? Действительно ли нужен отступ именно на 5? Как преобразовать это в байты? Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 (изменено) Может проще будет написать дллку на C++ добавить функцию как экспортируемую, и запускать из под C# после импорта? Просто .Net по своей природе не предназначен использовать asm, так что это то ещё извращение. 5 часов назад, Trix сказал: 0xE8, 0xE6, 0xE8, 0x5D, 0xFF А вот это уже хрень какая-то, выходит ты вызываешь ff5de8eb по твоим опкодам, а должен вызывать вроде как физический адрес и программа сама рассчитает положение функции(вроде так называется, если нет прошу поправить, чтобы не создавать путницы), т.е тут должно быть: byte[] asm = new byte[] { 0x68, 0xB1, 0x00, 0x00, 0x00 , // - push 000000B1 { 177 } 0xE8, 0xDD, 0xE8, 0x0D, 0x00, // - call gta-vc.exe+AE8F0 0x59, // - pop ecx 0xC3 // - ret А так все верно и мне кажется должно заработать, если у тебя дллка и она инжектируется в процесс, иначе ты будешь вызывать по этим опкодам функцию внутри своей программы и тогда возможен краш. Но это не точно, т.к не писал на C# и не знаю всех тонкостей. Изменено 4 мая, 2017 пользователем partoftheworlD Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 (изменено) Ну чувак... блин. Че за фигня? На C++ это выглядело бы примерно так: BYTE call[] = { 0xE8, 0x00, 0x00, 0x00, 0x00, /* call relative address */ 0xC3 }; /* ret */ // VirtualAllocEx LPVOID pAlloc = VirtualAlloc( NULL, sizeof( call ), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ); if( pAlloc != NULL ) { // Патчим наш адрес *(DWORD*)( call + 1 ) = (DWORD) foo - ( (DWORD) pAlloc + 5 ); // Тут заменить на WriteProcessMemory memcpy( pAlloc, call, sizeof( call ) ); CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE) pAlloc, NULL, NULL, NULL ); VirtualFree( pAlloc, NULL, MEM_RELEASE ); } В моем случае foo это просто тестовая функция. Код проверил, все работает. Удачи. Изменено 4 мая, 2017 пользователем uhx Ссылка на комментарий Поделиться на другие сайты Поделиться
partoftheworlD Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 (изменено) 13 минуты назад, uhx сказал: В моем случае foo это просто тестовая функция. Код проверил, все работает. Удачи. Почему бы не сделать так? Или твой вариант не использует инжект и проделывает все это как внешний чит? typedef void(*Spawner)(dword); auto *AnyFunction = reinterpret_cast<Spawner>(address); void main() { AnyFunction(A2); } BOOL APIENTRY DllMain(HMODULE hmodule, DWORD reason, LPVOID lpReserved) { switch (reason) { case DLL_PROCESS_ATTACH: CreateThread(0, 0, reinterpret_cast<LPTHREAD_START_ROUTINE>(main), hmodule, 0, 0); break; .... Изменено 4 мая, 2017 пользователем partoftheworlD Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 5 мая, 2017 Поделиться Опубликовано 5 мая, 2017 (изменено) 15 минут назад, partoftheworlD сказал: Почему бы не сделать так? Или твой вариант не использует инжект и проделывает все это как внешний чит? Дык этот чувак пишет на шарпе, и у него там "как внешний чит". Он вообще из этой темы пришел: Поэтому я по его подобию сделал, как у него там примерно. Так то ясен фиг проще дллку закинуть и через нее вызывать, чем внедрять опкоды и выполнять их через CreateRemoteThread Изменено 5 мая, 2017 пользователем uhx Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 5 мая, 2017 Поделиться Опубликовано 5 мая, 2017 Одно дело - смотреть опкоды в дизассемблере, другое - в отладчике, когда он уже загружен в память. Во втором случае все переходы и смещения уже пересчитаны относительно базового адреса, по которому загрузился исполняемый модуль. В первом - нет. Итого: gta-vc.exe + AE8F0 - тот адрес, что тебе показывает отладчик. 004AE8F0 - куда будем прыгнем по факту. Тут 400000 - базовый адрес. E8 DD E8 0D 00 - опкоды из отладчика. E8 - это call, причем относительный, значит прыгать мы будем на 000DE8DD байт вперед (вниз по коду). В общем, посмотри, по какому адресу загрузился gta-vc.exe. Скорее всего, если из этого адреса вычесть 000DE8DD, то получится 000F0E8A. Ссылка на комментарий Поделиться на другие сайты Поделиться
Trix Опубликовано 5 мая, 2017 Автор Поделиться Опубликовано 5 мая, 2017 2 часа назад, keng сказал: Одно дело - смотреть опкоды в дизассемблере, другое - в отладчике, когда он уже загружен в память. Во втором случае все переходы и смещения уже пересчитаны относительно базового адреса, по которому загрузился исполняемый модуль. В первом - нет. Итого: gta-vc.exe + AE8F0 - тот адрес, что тебе показывает отладчик. 004AE8F0 - куда будем прыгнем по факту. Тут 400000 - базовый адрес. E8 DD E8 0D 00 - опкоды из отладчика. E8 - это call, причем относительный, значит прыгать мы будем на 000DE8DD байт вперед (вниз по коду). В общем, посмотри, по какому адресу загрузился gta-vc.exe. Скорее всего, если из этого адреса вычесть 000DE8DD, то получится 000F0E8A. Окей, Кенг, я примерно понял, поковыерялся, дошло что это действительно относительный адрес.. Правда, как его вычислить ух, это непонятно У меня есть следующие значения Смещение на функцию, Базовый адрес, Адрес инъекции, как мне с этим всем можно узнать последующие байты после call? Ссылка на комментарий Поделиться на другие сайты Поделиться
Trix Опубликовано 5 мая, 2017 Автор Поделиться Опубликовано 5 мая, 2017 Окей, нашлось решение, всем спасибо за участие, если кому-то остался актуален этот вопрос, то вот решение jmp - E8, а адрес вычисляется по следующей инструкции: Нужный адрес(в моем случае gta-vc.exe+AE8F0 - адрес инъекции, куда поместили байты - 5 (место на jmp(1байт) + адрес(4байта)) В принципе, пришел к выводу, что как команда call, так и jmp относительна)) Всем еще раз спасибо Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 5 мая, 2017 Поделиться Опубликовано 5 мая, 2017 15 minutes ago, Trix said: Окей, нашлось решение, всем спасибо за участие, если кому-то остался актуален этот вопрос, то вот решение jmp - E8, а адрес вычисляется по следующей инструкции: Нужный адрес(в моем случае gta-vc.exe+AE8F0 - адрес инъекции, куда поместили байты - 5 (место на jmp(1байт) + адрес(4байта)) В принципе, пришел к выводу, что как команда call, так и jmp относительна)) Всем еще раз спасибо call - это push + jmp в одном флаконе. На стеке сохраняется адрес возврата. Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 6 мая, 2017 Поделиться Опубликовано 6 мая, 2017 22 часа назад, Trix сказал: Окей, нашлось решение, всем спасибо за участие, если кому-то остался актуален этот вопрос, то вот решение jmp - E8, а адрес вычисляется по следующей инструкции: Нужный адрес(в моем случае gta-vc.exe+AE8F0 - адрес инъекции, куда поместили байты - 5 (место на jmp(1байт) + адрес(4байта)) В принципе, пришел к выводу, что как команда call, так и jmp относительна)) Всем еще раз спасибо Так я тебе про это две темы затирал) В 05.05.2017 в 03:40, uhx сказал: На C++ это выглядело бы примерно так: BYTE call[] = { 0xE8, 0x00, 0x00, 0x00, 0x00, /* call relative address */ 0xC3 }; /* ret */ // VirtualAllocEx LPVOID pAlloc = VirtualAlloc( NULL, sizeof( call ), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE ); if( pAlloc != NULL ) { // Патчим наш адрес *(DWORD*)( call + 1 ) = (DWORD) foo - ( (DWORD) pAlloc + 5 ); // Тут заменить на WriteProcessMemory memcpy( pAlloc, call, sizeof( call ) ); CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE) pAlloc, NULL, NULL, NULL ); VirtualFree( pAlloc, NULL, MEM_RELEASE ); } В моем случае foo это просто тестовая функция. Код проверил, все работает. Удачи. А это тебе не помогло? Хоть и на плюсах, но принцип тот же. Формула для расчета адреса ведь есть. Я думал после этого хоть понятно станет... Ссылка на комментарий Поделиться на другие сайты Поделиться
Trix Опубликовано 7 мая, 2017 Автор Поделиться Опубликовано 7 мая, 2017 В 06.05.2017 в 13:35, uhx сказал: Так я тебе про это две темы затирал) А это тебе не помогло? Хоть и на плюсах, но принцип тот же. Формула для расчета адреса ведь есть. Я думал после этого хоть понятно станет... Ну, видишь, я отличаюсь интеллектом. В плане доходит оч. долго Первым делом обратил внимание на ассемблерную команду, а потом на байт-код, поэтому и сбился, но зато запомнится Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения