Перейти к содержанию

Рекомендуемые сообщения

Здравствуйте, на жуке 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;}
Ссылка на комментарий
Поделиться на другие сайты

у ассемблерной функции объяви еще __declspec(naked), чтобы компилятр свой код в тело функции не добавлял. Не факт, что это поможет, но, по крайней мере, инжектнется ровно то, что у тебя в __asm прописано, и ничего сверх того.

Ссылка на комментарий
Поделиться на другие сайты

все ещё актуально, кто подскажет, почему процесс зависает после createRemoteThread?

Изменено пользователем vladimir777
Ссылка на комментарий
Поделиться на другие сайты

Привет! Пара хороших вопросов:

0. Почему при выделении памяти под функцию не используется флаг EXECUTE?

1. Почему для функции не передаются аргументы (NULL вместо них), но они все равно пытаются записаться в память и скормиться потоку?

2. Почему нет проверки на то, можно ли писать в память (VirtualProtectEx)?

3. Точно ли ты понимаешь, что делает этот код?


В общем, я передал вместо параметров ноль при создании потока и у меня инжект отработал корректно. Единственное НО - работает это только на х32-процессах.
Ссылка на комментарий
Поделиться на другие сайты

Привет! Пара хороших вопросов:

0. Почему при выделении памяти под функцию не используется флаг EXECUTE?

1. Почему для функции не передаются аргументы (NULL вместо них), но они все равно пытаются записаться в память и скормиться потоку?

2. Почему нет проверки на то, можно ли писать в память (VirtualProtectEx)?

3. Точно ли ты понимаешь, что делает этот код?

В общем, я передал вместо параметров ноль при создании потока и у меня инжект отработал корректно. Единственное НО - работает это только на х32-процессах.

 

спасибо за ответ!

 

0. так в оригинале было.

1. тоже в оригинале так было

2. ну вроде сам память создаю, где читать\писать можно

3. немного)

 

я поставил ноль вместо параметров, и это не сработало, пробовал на x32 программах(скайп например), в VirtualAllocEx место PAGE_readwrite поставил PAGE_EXECUTE_READWRITE , хотя в память и так записывается, программа зависает при создании потока, скинь пожалуйста свой рабочий код, хотя если там только ноль вместо параметров в createRemoteThread, то почему у меня не работает.

 

и ещё вопрос: с помощью CreateRemoteThread можно создавать потоки только в функциях, всмысле нельзя просто создать поток, если будут одни nop'ы?

Изменено пользователем vladimir777
Ссылка на комментарий
Поделиться на другие сайты

Не совсем корректно ты выразился. Поток не создается в функциях. Адрес функции - это место, откуда начинается ее код, так? В момент ее вызова игра передает процессору управление по этому самому адресу. Процессор выполняет код функции и выходит обратно, туда, откуда управление передали. Обычно это через стек делается, но не суть. Сами exe-файлы работают схожим образом - у них есть так называемая точка входа - адрес, по которому передается управление, когда ехе-файл запускается. Обычно это функция main. Потом - это, можно сказать, мини-процесс, как бы отдельный. У него есть точка входа и (но не обязательно) параметры. Точка входа - это адрес памяти, по которому должен (логично же) находиться код. Поток создается, процессор (когда у него находится свободное время) передает управление на его "точку входа", а затем поток завершается. При этом для потока создается свой контекст - данные, с которыми он работает в процессе работы (звучит туповато, знаю). Собственно, что приведенный тобой код делает:

 

0. Ищем в запущенных процессах процесс игры, используя thelp32-api.

1. Если находим - получаем на него хэндл для записи\чтения, используя OpenProcess.

2. Выделяем, используя полученный хэндл, в адресном пространстве этого процесса два куска памяти - один для тела функции, другой для ее аргументов. Почему-то для тела всегда выделяется 4096 байт, а для параметров - 256. В приведенном примере тело функции куда меньше, а параметров нет вовсе, но это тоже пофиг.

3. Когда выделили память, при помощи WriteProcessMemory записываем тело и аргументы. Указатель на тело и на аргументы нам передались в функцию инжекта.

4. Сделав все приготовления, мы получаем два куска памяти в адресном пространстве процесса игры - тело функции и аргументы этой функции. Создаем в процессе игры поток, указываем ему в качестве точки входа записанное в память игры тело функции, а так же аргументы.

5. Поток отрабатывает и завершается. Ждем этого через WaitForSingleObject.

6. Чистим за собой мусор, закрывая открытые хэндлы и освобождая выделенную память.

7. Выходим.

 

Я прикрепил к посту чуть подправленный мной код, он у меня корректно отработал на х32-процессе. В качестве инъекции я использовал опкод брейкпоинта (INT 3). Синтаксис inline-ассемблера - G++, компилятор тот же.

test.zip

Ссылка на комментарий
Поделиться на другие сайты

Не совсем корректно ты выразился. Поток не создается в функциях. Адрес функции - это место, откуда начинается ее код, так? В момент ее вызова игра передает процессору управление по этому самому адресу. Процессор выполняет код функции и выходит обратно, туда, откуда управление передали. Обычно это через стек делается, но не суть. Сами 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 записалась нужная цифра 

Ссылка на комментарий
Поделиться на другие сайты

Ну и отлично. Код внутри потока можно отладить при помощи, например, Olly Debugger или того же Cheat Engine. При первом вызове VirtualAllocEx (на 4096 байт) выделяется кусок памяти, куда запишется код функции, который будет выполнять поток после создания. Первой командой можно поставить "INT 3" - это опкод брейкпоинта, так что если к процессу игры будет подключен отладчик, он прервется. Если не подключен - обычно процесс игры просто завершится с ошибкой. Варианта у тебя, в общем, два - или использовать адрес памяти, куда записалось тело функции и ставить на этот адрес брейкпоинт на исполнение (сработает, т.к. при создании потока управление передастся на этот адрес и код, по нему находящийся, будет выполнен, или же вручную, поставив "INT 3", тогда брейкпоинт ставить не нужно - он уже будет в коде.
Ссылка на комментарий
Поделиться на другие сайты

Прочитай вот [это]. Тут проще статью дать, чем писать самому. Не уверен, что не работает из-за naked-соглашения, оно как раз необходимо в этом случае.
Ссылка на комментарий
Поделиться на другие сайты

ну наконец то получилось вызвать функцию из другой программы(хоть и моей).

как оказалось, если писать __declspec(naked) , то в ассемблерной вставки в конце нужно "ret" писать получается.

 

И если я вызываю функцию:

push eax

push ecx
call edx
 
то потом нужно ещё написать :
pop ecx
pop eax
 
а если не напишу, то потом программа зависает, а в оригинале кода такого не было.
 
Ещё хотел спросить, если я вызываю с помощью createRemoteThread функцию в чужой программе, то как параметры передать(те, которые я передаю с помощью push)? 
Изменено пользователем vladimir777
Ссылка на комментарий
Поделиться на другие сайты

Они у тебя передаются в CreateRemoteThread в 5-м аргументе, если смотреть твой код, то это pParams, указатель на участок памяти. До этого в функцию передается Params, это и есть аргументы.
Ссылка на комментарий
Поделиться на другие сайты

Этот код висит уже давно там. Попробуй написать инжектор по уроку Flip'a. (в серии написания чита на с++, помоему первая серия уроков).

Почти все инжекторы используют CreateRemoteThread (создание удаленного потока), попробуй написать инжектор с перехватом потока. 

Изменено пользователем RockHammer
Ссылка на комментарий
Поделиться на другие сайты

Они у тебя передаются в CreateRemoteThread в 5-м аргументе, если смотреть твой код, то это pParams, указатель на участок памяти. До этого в функцию передается Params, это и есть аргументы.

Кенг, а как отменить инъекцию кода? А то сделал инъекцию кода в игре , а как отменить её хз...

Ссылка на комментарий
Поделиться на другие сайты

никто не знает,как поставить брейпойнт на потоки созданные с помощью createRemoteThread, если в настройках чин енжина стоит VEH отладчик? с windows отладчиком ставится, но он играми палится

Изменено пользователем vladimir777
Ссылка на комментарий
Поделиться на другие сайты

Судя по документации, есть lua-команда debug_setBreakpoint(address). Точнее ничего не могу сказать, т.к. не люблю этот язык. Думаю, подробности может знать MasterGH.
Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.