vladimir777 Опубликовано 1 апреля, 2015 Поделиться Опубликовано 1 апреля, 2015 Здравствуйте, на жуке zhyk.ru/forum/showthread.php?t=274071 взял код для вставки своего кода в чужой процесс, но он у меня почему то не работает, после CreateRemoteThread процесс(куда я вставил код) сразу зависает, брекпойнт который я ставлю на начало функции(которую я вставил), не срабатывает, да и выглядит вставленная функция странно. Да и вообще я не как не смог с помощью CreateRemoteThread создать поток в чужом процессе...в чем может быть проблема? код в оригинале был для c++ builder, но я пишу в visual studio, вот код:NullAlex: для кода есть специальный тег, для большого кода - спойлер. Устное предупреждение.//---------------------------------------------------------------------------#include <Windows.h>#include <TlHelp32.h>//---------------------------------------------------------------------------//---------------------------------------------------------------------------//---------------------------------------------------------------------------#define INJECT_OK 0x00#define INJECT_NO_PROCESS 0x01#define INJECT_NO_ACCESS 0x02#define INJECT_BAD_VERSION 0x03#define INJECT_THREAD_FAIL 0x04//--------------------------------------------------------------------------- DWORD GetprocessbyName(char* process_name){HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);PROCESSENTRY32 process;DWORD proc_id = 0;if (Process32First(snapshot, &process)){while (Process32Next(snapshot, &process)){if (_stricmp(process.szExeFile, process_name) == 0){proc_id = process.th32ProcessID;break;}}}CloseHandle(snapshot);return proc_id;}BYTE InjectAndExecute(void* Func, void* Params){DWORD pId = GetprocessbyName("elementclient.exe");if (!pId)return INJECT_NO_PROCESS; // нет такого процесса HANDLE hProc;HANDLE hProcThread;void* pFunction;void* pParams; hProc = OpenProcess(PROCESS_ALL_ACCESS, false, pId);if (hProc == INVALID_HANDLE_VALUE) // не удалось открыть процессreturn INJECT_NO_ACCESS; //if (!IsGameVersionValid(hProc))// return INJECT_BAD_VERSION; // не та версия игры pFunction = VirtualAllocEx(hProc, NULL, 4096, MEM_COMMIT, PAGE_READWRITE);pParams = VirtualAllocEx(hProc, NULL, 256, MEM_COMMIT, PAGE_READWRITE);WriteProcessMemory(hProc, pFunction, Func, 4096, NULL);WriteProcessMemory(hProc, pParams, Params, 256, NULL); hProcThread = CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)pFunction, pParams, NULL, NULL);if (hProcThread == INVALID_HANDLE_VALUE) // не удалось создать поток{VirtualFreeEx(hProc, pFunction, 4096, MEM_RELEASE);VirtualFreeEx(hProc, pParams, 256, MEM_RELEASE);CloseHandle(hProc);return INJECT_THREAD_FAIL;} WaitForSingleObject(hProcThread, INFINITE); // ожидаем завершения работы потокаCloseHandle(hProcThread); // освобождаем память VirtualFreeEx(hProc, pFunction, 4096, MEM_RELEASE);VirtualFreeEx(hProc, pParams, 256, MEM_RELEASE);CloseHandle(hProc);return INJECT_OK;}//---------------------------------------------------------------------------//---------------------------------------------------------------------------void __stdcall Attack_THREAD(){__asm{pushadmov edx, 0x0044FE60//mov ecx, dword ptr ds : [BA]//mov ecx, dword ptr ds : [ecx + 0x1C]//mov ecx, dword ptr ds : [ecx + 0x20]//push - 1//push 0//push 0//push 0//call edxpopad}}//---------------------------------------------------------------------------class CHostPlayer{public:bool SelectSomething(DWORD GlobalId){//return (InjectAndExecute(&Target_THREAD, &GlobalId) == INJECT_OK);}bool AttackSelectedTarget(){return (InjectAndExecute(&Attack_THREAD, NULL) == INJECT_OK);}} *HostPlayer; int main(){HostPlayer->AttackSelectedTarget(); return 0;} Ссылка на комментарий Поделиться на другие сайты Поделиться
Xipho Опубликовано 1 апреля, 2015 Поделиться Опубликовано 1 апреля, 2015 у ассемблерной функции объяви еще __declspec(naked), чтобы компилятр свой код в тело функции не добавлял. Не факт, что это поможет, но, по крайней мере, инжектнется ровно то, что у тебя в __asm прописано, и ничего сверх того. Ссылка на комментарий Поделиться на другие сайты Поделиться
vladimir777 Опубликовано 3 апреля, 2015 Автор Поделиться Опубликовано 3 апреля, 2015 (изменено) все ещё актуально, кто подскажет, почему процесс зависает после createRemoteThread? Изменено 3 апреля, 2015 пользователем vladimir777 Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 3 апреля, 2015 Поделиться Опубликовано 3 апреля, 2015 Привет! Пара хороших вопросов:0. Почему при выделении памяти под функцию не используется флаг EXECUTE?1. Почему для функции не передаются аргументы (NULL вместо них), но они все равно пытаются записаться в память и скормиться потоку?2. Почему нет проверки на то, можно ли писать в память (VirtualProtectEx)?3. Точно ли ты понимаешь, что делает этот код?В общем, я передал вместо параметров ноль при создании потока и у меня инжект отработал корректно. Единственное НО - работает это только на х32-процессах. Ссылка на комментарий Поделиться на другие сайты Поделиться
vladimir777 Опубликовано 3 апреля, 2015 Автор Поделиться Опубликовано 3 апреля, 2015 (изменено) Привет! Пара хороших вопросов:0. Почему при выделении памяти под функцию не используется флаг EXECUTE?1. Почему для функции не передаются аргументы (NULL вместо них), но они все равно пытаются записаться в память и скормиться потоку?2. Почему нет проверки на то, можно ли писать в память (VirtualProtectEx)?3. Точно ли ты понимаешь, что делает этот код?В общем, я передал вместо параметров ноль при создании потока и у меня инжект отработал корректно. Единственное НО - работает это только на х32-процессах. спасибо за ответ! 0. так в оригинале было.1. тоже в оригинале так было2. ну вроде сам память создаю, где читать\писать можно3. немного) я поставил ноль вместо параметров, и это не сработало, пробовал на x32 программах(скайп например), в VirtualAllocEx место PAGE_readwrite поставил PAGE_EXECUTE_READWRITE , хотя в память и так записывается, программа зависает при создании потока, скинь пожалуйста свой рабочий код, хотя если там только ноль вместо параметров в createRemoteThread, то почему у меня не работает. и ещё вопрос: с помощью CreateRemoteThread можно создавать потоки только в функциях, всмысле нельзя просто создать поток, если будут одни nop'ы? Изменено 3 апреля, 2015 пользователем vladimir777 Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 3 апреля, 2015 Поделиться Опубликовано 3 апреля, 2015 Не совсем корректно ты выразился. Поток не создается в функциях. Адрес функции - это место, откуда начинается ее код, так? В момент ее вызова игра передает процессору управление по этому самому адресу. Процессор выполняет код функции и выходит обратно, туда, откуда управление передали. Обычно это через стек делается, но не суть. Сами exe-файлы работают схожим образом - у них есть так называемая точка входа - адрес, по которому передается управление, когда ехе-файл запускается. Обычно это функция main. Потом - это, можно сказать, мини-процесс, как бы отдельный. У него есть точка входа и (но не обязательно) параметры. Точка входа - это адрес памяти, по которому должен (логично же) находиться код. Поток создается, процессор (когда у него находится свободное время) передает управление на его "точку входа", а затем поток завершается. При этом для потока создается свой контекст - данные, с которыми он работает в процессе работы (звучит туповато, знаю). Собственно, что приведенный тобой код делает: 0. Ищем в запущенных процессах процесс игры, используя thelp32-api.1. Если находим - получаем на него хэндл для записи\чтения, используя OpenProcess.2. Выделяем, используя полученный хэндл, в адресном пространстве этого процесса два куска памяти - один для тела функции, другой для ее аргументов. Почему-то для тела всегда выделяется 4096 байт, а для параметров - 256. В приведенном примере тело функции куда меньше, а параметров нет вовсе, но это тоже пофиг.3. Когда выделили память, при помощи WriteProcessMemory записываем тело и аргументы. Указатель на тело и на аргументы нам передались в функцию инжекта.4. Сделав все приготовления, мы получаем два куска памяти в адресном пространстве процесса игры - тело функции и аргументы этой функции. Создаем в процессе игры поток, указываем ему в качестве точки входа записанное в память игры тело функции, а так же аргументы.5. Поток отрабатывает и завершается. Ждем этого через WaitForSingleObject.6. Чистим за собой мусор, закрывая открытые хэндлы и освобождая выделенную память.7. Выходим. Я прикрепил к посту чуть подправленный мной код, он у меня корректно отработал на х32-процессе. В качестве инъекции я использовал опкод брейкпоинта (INT 3). Синтаксис inline-ассемблера - G++, компилятор тот же.test.zip Ссылка на комментарий Поделиться на другие сайты Поделиться
vladimir777 Опубликовано 3 апреля, 2015 Автор Поделиться Опубликовано 3 апреля, 2015 Не совсем корректно ты выразился. Поток не создается в функциях. Адрес функции - это место, откуда начинается ее код, так? В момент ее вызова игра передает процессору управление по этому самому адресу. Процессор выполняет код функции и выходит обратно, туда, откуда управление передали. Обычно это через стек делается, но не суть. Сами exe-файлы работают схожим образом - у них есть так называемая точка входа - адрес, по которому передается управление, когда ехе-файл запускается. Обычно это функция main. Потом - это, можно сказать, мини-процесс, как бы отдельный. У него есть точка входа и (но не обязательно) параметры. Точка входа - это адрес памяти, по которому должен (логично же) находиться код. Поток создается, процессор (когда у него находится свободное время) передает управление на его "точку входа", а затем поток завершается. При этом для потока создается свой контекст - данные, с которыми он работает в процессе работы (звучит туповато, знаю). Собственно, что приведенный тобой код делает: 0. Ищем в запущенных процессах процесс игры, используя thelp32-api.1. Если находим - получаем на него хэндл для записи\чтения, используя OpenProcess.2. Выделяем, используя полученный хэндл, в адресном пространстве этого процесса два куска памяти - один для тела функции, другой для ее аргументов. Почему-то для тела всегда выделяется 4096 байт, а для параметров - 256. В приведенном примере тело функции куда меньше, а параметров нет вовсе, но это тоже пофиг.3. Когда выделили память, при помощи WriteProcessMemory записываем тело и аргументы. Указатель на тело и на аргументы нам передались в функцию инжекта.4. Сделав все приготовления, мы получаем два куска памяти в адресном пространстве процесса игры - тело функции и аргументы этой функции. Создаем в процессе игры поток, указываем ему в качестве точки входа записанное в память игры тело функции, а так же аргументы.5. Поток отрабатывает и завершается. Ждем этого через WaitForSingleObject.6. Чистим за собой мусор, закрывая открытые хэндлы и освобождая выделенную память.7. Выходим. Я прикрепил к посту чуть подправленный мной код, он у меня корректно отработал на х32-процессе. В качестве инъекции я использовал опкод брейкпоинта (INT 3). Синтаксис inline-ассемблера - G++, компилятор тот же.спасибо! работает. попробую завтра методом тыка определить, почему раньше не работал). Брекпойнт в чит енжине всё равно не срабатывает, хоть я теперь точно ставлю брекпойнт на инструкцию, которую я и должен был записать: mov dword ptr ds : [0x05CC03C1], 777 , и по адресу 0x05CC03C1 записалась нужная цифра Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 4 апреля, 2015 Поделиться Опубликовано 4 апреля, 2015 Ну и отлично. Код внутри потока можно отладить при помощи, например, Olly Debugger или того же Cheat Engine. При первом вызове VirtualAllocEx (на 4096 байт) выделяется кусок памяти, куда запишется код функции, который будет выполнять поток после создания. Первой командой можно поставить "INT 3" - это опкод брейкпоинта, так что если к процессу игры будет подключен отладчик, он прервется. Если не подключен - обычно процесс игры просто завершится с ошибкой. Варианта у тебя, в общем, два - или использовать адрес памяти, куда записалось тело функции и ставить на этот адрес брейкпоинт на исполнение (сработает, т.к. при создании потока управление передастся на этот адрес и код, по нему находящийся, будет выполнен, или же вручную, поставив "INT 3", тогда брейкпоинт ставить не нужно - он уже будет в коде. Ссылка на комментарий Поделиться на другие сайты Поделиться
vladimir777 Опубликовано 4 апреля, 2015 Автор Поделиться Опубликовано 4 апреля, 2015 не знаю почему не работало вначале, но вчера не работало из за __declspec(naked) Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 4 апреля, 2015 Поделиться Опубликовано 4 апреля, 2015 Прочитай вот [это]. Тут проще статью дать, чем писать самому. Не уверен, что не работает из-за naked-соглашения, оно как раз необходимо в этом случае. Ссылка на комментарий Поделиться на другие сайты Поделиться
vladimir777 Опубликовано 5 апреля, 2015 Автор Поделиться Опубликовано 5 апреля, 2015 (изменено) ну наконец то получилось вызвать функцию из другой программы(хоть и моей).как оказалось, если писать __declspec(naked) , то в ассемблерной вставки в конце нужно "ret" писать получается. И если я вызываю функцию:push eaxpush ecxcall edx то потом нужно ещё написать :pop ecxpop eax а если не напишу, то потом программа зависает, а в оригинале кода такого не было. Ещё хотел спросить, если я вызываю с помощью createRemoteThread функцию в чужой программе, то как параметры передать(те, которые я передаю с помощью push)? Изменено 5 апреля, 2015 пользователем vladimir777 Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 5 апреля, 2015 Поделиться Опубликовано 5 апреля, 2015 Они у тебя передаются в CreateRemoteThread в 5-м аргументе, если смотреть твой код, то это pParams, указатель на участок памяти. До этого в функцию передается Params, это и есть аргументы. Ссылка на комментарий Поделиться на другие сайты Поделиться
RockHammer Опубликовано 5 апреля, 2015 Поделиться Опубликовано 5 апреля, 2015 (изменено) Этот код висит уже давно там. Попробуй написать инжектор по уроку Flip'a. (в серии написания чита на с++, помоему первая серия уроков).Почти все инжекторы используют CreateRemoteThread (создание удаленного потока), попробуй написать инжектор с перехватом потока. Изменено 5 апреля, 2015 пользователем RockHammer Ссылка на комментарий Поделиться на другие сайты Поделиться
afro228offical Опубликовано 5 апреля, 2015 Поделиться Опубликовано 5 апреля, 2015 Они у тебя передаются в CreateRemoteThread в 5-м аргументе, если смотреть твой код, то это pParams, указатель на участок памяти. До этого в функцию передается Params, это и есть аргументы.Кенг, а как отменить инъекцию кода? А то сделал инъекцию кода в игре , а как отменить её хз... Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 5 апреля, 2015 Поделиться Опубликовано 5 апреля, 2015 Поток можно создавать в приостановленном (THREAD_CREATE_SUSPENDED, вроде бы) состоянии, а потом запускать вызовом другой функции. Ссылка на комментарий Поделиться на другие сайты Поделиться
vladimir777 Опубликовано 6 апреля, 2015 Автор Поделиться Опубликовано 6 апреля, 2015 (изменено) никто не знает,как поставить брейпойнт на потоки созданные с помощью createRemoteThread, если в настройках чин енжина стоит VEH отладчик? с windows отладчиком ставится, но он играми палится Изменено 6 апреля, 2015 пользователем vladimir777 Ссылка на комментарий Поделиться на другие сайты Поделиться
keng Опубликовано 6 апреля, 2015 Поделиться Опубликовано 6 апреля, 2015 Судя по документации, есть lua-команда debug_setBreakpoint(address). Точнее ничего не могу сказать, т.к. не люблю этот язык. Думаю, подробности может знать MasterGH. Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения