Помогите пожалуйста в этой теме.
Я никак не могу описать простейшего бота. Хочу чтобы выделялся моб. Делал по гайду, но с уклоном в Visual C++ библиотека MFC, да там собственно различий то немного.
Из игры данные получаю отлично, но вот стоит мне написать функцию инжектор и запустить программу, как клиент у меня вылетает. Вылетает на строчке создания потока... А значит возможно неправильно написаны адреса в ассемблерном коде. Я уже долго сижу в недоумении почему не работает программа. Помогите пожалуйста, кто-нибудь.. В чем моя ошибка?
кому лень читать много букв, вот последний мой[Ссылки могут видеть только зарегистрированные пользователи. ].
Спасибо всем, кто хоть как-то поможет...
Дополнительные сведения:
В лаунчере mail.ru написано Возрождение династий, версия игры 154. Сервер: Орион.
Еще Win7x64, если это как-то влияет на смещения памяти...
С этим всё ясно, но перелопачивание проекта весом в 10 МБ, без знания его структуры, в поисках "запоротого" инжекта, совсем лишнее. Отпости инжект, без лишнего кода.
Я собственно сам не понимаю, зачем Visual Studio создал такой громоздкий файл в 10Mb, там в принципе и рыть то нечего, две кнопки и ничего более.
Я удалил весь debug из проекта и он стал занимать всего 41Kb, так что как я и говорил, перелопачивать там нечего. [Ссылки могут видеть только зарегистрированные пользователи. ]...
Весь существенный код заключен в BotDlg.h и BotDlg.cpp, все остальное мишура отвечающая за создание диалогового окна...
Вот то, что я выудил из клиента(ассемблерный код):
00477255 A1 CCFBB800 MOV EAX,DWORD PTR DS:[B8FBCC]
0047725A 57 PUSH EDI
0047725B 8B48 20 MOV ECX,DWORD PTR DS:[EAX+20]
0047725E 81C1 EC000000 ADD ECX,0EC
00477264 E8 F7CA2100 CALL elementc.00693D60
Вот мой код из ассемблера:
void Target_THREAD(DWORD* WID)
{
DWORD Id = *WID;
_asm
{
MOV EDI, Id
MOV EBX, 0x00693D60
MOV EAX,DWORD PTR DS:[BA] //0x00B8FBCC
PUSH EDI
MOV ECX,DWORD PTR DS:[EAX+0x20]
ADD ECX,0x0EC
CALL EBX
}
}
Вот функция инжекта:
BYTE CBotDlg::InjectAndExecute(void* Func, void* Params)
{
HANDLE hProcThread;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if(!hProcess) return 0;
procedure InjectFunc(ProcessID: Cardinal; Func, aParams: Pointer;
aParamsSize: DWord);
var
hThread: THandle;
lpNumberOfBytes: DWord;
ThreadAddr, ParamAddr: Pointer;
begin
if ProcessID<>0 then
begin
// ---- Выделяем место в памяти процесса, и записываем туда нашу функцию
ThreadAddr := VirtualAllocEx(ProcessID, nil, 256, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(ProcessID, ThreadAddr, Func, 256, lpNumberOfBytes);
// ---- Также запишем параметры к ней
ParamAddr := VirtualAllocEx(ProcessID, nil, aParamsSize, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory(ProcessID, ParamAddr, aParams, aParamsSize, lpNumberOfBytes);
// ---- Создаем поток, в котором все это будет выполняться.
hThread := CreateRemoteThread(ProcessID, nil, 0, ThreadAddr, ParamAddr, 0, lpNumberOfBytes);
// ---- Ожидаем завершения функции
WaitForSingleObject(hThread, INFINITE);
// ---- подчищаем за собой
CloseHandle(hThread);
VirtualFreeEx(ProcessID, ParamAddr, 0, MEM_RELEASE);
VirtualFreeEx(ProcessID, ThreadAddr, 0, MEM_RELEASE);
end
end;
Код:
procedure TargetCall(aPParams:PParams);Stdcall;
var
CA,BA:pointer;
P1,P_1,P_2: DWord;
begin
P1:=aPParams^.WID;
CA:=pointer(aPParams^.CallAddr);
BA:=pointer(aPParams^.BaseAddr);
P_1:=aPParams^.Param1;
P_2:=aPParams^.Param2;
asm
MOV EDI, P1 // Вносим WID моба в регистр EDI
MOV EBX, CA //Вносим в свободный регистр EBX адрес функции
MOV EAX, BA //Вносим в EAX базовый адрес
MOV EAX,DWORD PTR DS:[EAX] // $00B8FBCC
ADD EAX,P_1 //прибавляем к EAX $20
MOV ECX,DWORD PTR DS:[EAX]
PUSH EDI //
ADD ECX,P_2 //прибавляем к ECX $0EC ;
CALL EBX // ; \elementc.00693D60
end;
end;
Использование:
Код:
procedure TForm1.Button1Click(Sender: TObject);
var
aParams:TParams;
begin
aParams.WID:=WID; //WID моба
aParams.CallAddr:=$00693D60;
aParams.BaseAddr:=$00B8FBCC;
aParams.Param1:=$20;
aParams.Param2:=$0EC;
InjectFunc(hProcess, @TargetCall, @aParams, SizeOf(aParams ) );
end;
зачем Visual Studio создал такой громоздкий файл в 10Mb
Понятия не имею, не использую Visual Studio, но даже то, что после удаления папки debug он весит меньше, структура проекта осталась для меня загадкой.
Думаю fds255, сказал достаточно, хочу лишь для контраста добавить инжект пакета сброса таргета, написано на FreeBASIC. В архиве исходник и его скомпилированная версия. Кстати и в таргет тоже можно брать таким образом и делать еще много чего полезного, нужно будет просто менять пакет и его размер, хотя ты наверное в курсе... ты же в курсе?
[Ссылки могут видеть только зарегистрированные пользователи. ] | [Ссылки могут видеть только зарегистрированные пользователи. ]
Если в скомпилированной версии нет необходимости можно её просто удалить и не парится по поводу отчета ВТ.
Я в курсе, мне главное сделать первый шаг, сделать правильный инжект, чтобы у меня получилось. А далее уже все понятно будет.
Переписал ассемблерную вставку как у fds255, если я конечно ее правильно понял. Клиент игры все равно вылетает.
Вот ассемблерная вставка:
void Target_THREAD(DWORD* WID)
{
DWORD Id = *WID;
_asm
{
MOV EDI, Id
MOV EBX, 0x00693D60
MOV EAX, BA
MOV EAX,DWORD PTR DS:[EAX]
ADD EAX, 0x20
MOV ECX,DWORD PTR DS:[EAX]
PUSH EDI
ADD ECX,0x0EC
CALL EBX
}
}
Буду пробовать дальше разбираться.
Кроме того, переписал функцию инжекта так, что бы память выделялась в ней:
BYTE CBotDlg::InjectAndExecute(void* Func, void* Params)
{
DWORD* lpthreadid = NULL;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);
DWORD* pfunc = (DWORD*)VirtualAllocEx(hProcess,NULL,512,MEM_COMMI T,PAGE_READWRITE);
WriteProcessMemory(hProcess,pfunc,Func,256,NULL);
DWORD* params = pfunc + 64;
WriteProcessMemory(hProcess,params,Params,256,NULL );
HANDLE hProcThread;
Ребят,
1) собственно по этому гайду я бота и писал;
2) ассемблерный код у него написан с ошибкой, по крайней мере в комментариях; ( адрес функции таргета у него вызывается по одному адресу, а он заносит в регистр совсем другой адрес)... Тогда уж вот тут правильнее:
Цитата:
procedure TargetCall(aPParams:PParams);Stdcall; //StdCall - обязательно, указывает что аргументы попадают в стек в обратном (стандартном) порядке
var //
P1: DWord; //
begin //
P1:=aPParams^.WID; //
asm
MOV EDI, P1 // Вносим WID моба в регистр EDI
MOV EBX, $00606A70 // Вносим в свободный регистр адрес функции
MOV EAX,DWORD PTR DS:[$A5B90C] //
PUSH EDI // ; /Arg1
MOV ECX,DWORD PTR DS:[EAX+$20] // ; |
ADD ECX,$0EC // ; |
CALL EBX // ; \elementc.00606A70
end;
end;
Здесь он какой адрес функции таргерта получает, тот и записывает в регистр.....
3) ошибка то собственно заключается не в ассемблерном коде (скорее всего), там наверняка ошибка в передаче указателей в инжектирующую функцию;
4) прежде чем линковать, что попало вы хоть (относится к dess99) смотрели мой код? Если смотрели, так там аналогичная ассемблерная вставка.
Вывод: Я считаю, что мне надо написать инжектирующую функцию и ассемблерную вставку по-проще(где не надо предварительно получать много параметров об окружении). Например, на подобии снятия выделения с моба или еще какую... Остается только получить ассмеблерную вставку, где есть адрес функции которая вызывается при снятии таргета с моба.
Последний раз редактировалось Xantrax; 30.04.2013 в 19:29.
Ассемблерная вставка та же, только вместо WID моба передаешь 0
Как вариант (причём вполне логичный).
Но на самом деле в клиенте для этого есть отдельная функция (и отдельный пакет), так что в принципе можно и такую ассемблерную вставку сделать. :D
________________
Принимаю реквесты на статьи, программы. Всё будет запилено в лучшем виде :3
Ох, бяда, бяда.
Сделал инжектируемую функцию как рекомендовал BritishColonist, подставил в нее wid моба равным 0(т.е. пишем простейшую ф-цию снятия выделения с моба).
И опять вылет на создании потока в процессе((. Вроде бы все просто, но вылетает зараза и не могу разобраться почему.((
Может попробовать под библиотекой QT тоже самое написать? Только боюсь результат один и тот же будет.
Может кто-нибудь знающий посмотреть мой код в конце концов, откомпилировать, запустить и посмотреть в чем проблема? Ведь это же не сложно...
Последний раз редактировалось Xantrax; 06.05.2013 в 12:57.