Здравствуйте уважаемые форумчане.
До этого написал несколько программ на QT, но сейчас возникла необходимость изучить Visual Studio Visual С++, библиотека MFC.
В принципе код не очень сильно отличается от C++ Builder.
Для поверхностного изучения данной среды и библиотеки решил, кроме всего прочего, еще и бота по гайду написать.
Считывание параметров идет нормально.
Проблемы возникают с инжектом. Получил функцию таргета моба с помощью CheatEngine, после дебага в OLLYDBG нашел ассемблерный код, написал функцию, вроде все правильно, но при запуске бота клиент игры вылетает. Ткните пожалуйста носом, где я что "накосячил", над чем надо подумать и исправить.
Свой проект прикладываю к теме ниже.(Почему-то не смог загрузить на zhyk.ru, загрузил на mail).
[Ссылки могут видеть только зарегистрированные пользователи. ]
Спасибо!
Добавлено через 15 часов 59 минут
Ну, ладно, значит будем разбираться.
Итак, функция DWORD* pfunc = (DWORD*) VirtualAllocEx(hProcess, NULL, 511, MEM_COMMIT, PAGE_READWRITE);
вернула не NULL, а 0x03030000, это уже хорошо, и память таки выделилась.
pfunc теперь хранит адрес начала выделенной нами памяти.
Добавлено через 18 часов 11 минут
Если пройтись debug-ом по программе, то клиент игры вылетает на строчках:
hProcThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)pFunction, pParams, NULL, NULL);
При поверхностном осмотре ничего страшного в этой функции не нашел...
Зачем вообще столько много функций: создаем функцию инжектор, создаем функцию, которая определяет параметры нашего инжекта, а потом еще сверху забиваем все это функцией которая вызывает функцию инжектор, зачем?
Так и вызовем InjectAndExecute Зачем нам еще какая-то функция, которая вызывает функцию инжектор?
Просто будем писать:
inject.InjectAndExecute(&Target_Thread,&wid);
Проблему это не решает, но так по моему мнению будет логичней.
И еще такой вопрос:
Я конечно никогда не вставлял ассемблерный код, но разве так надо вставлять функцию в виде параметра?
inject.InjectAndExecute(&Target_Thread,&wid);
Она же требует указатель на память, где хранится wid моба, который удовлетворил условиям соответствия типу, дальности, ну и собственно не равности 0.
И еще wid мы получаем в цикле, при этом цикл не кончается, пока он не найдет последний wid моба, почему именно последний? Почему мы не берем первый верный wid? По мне так inject.InjectAndExecute(&Target_Thread,&wid); прямо в цикл....
//================================================== =============================
Сдается мне, что виновата вовсе не строка: hProcThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)pFunction, pParams, NULL, NULL); , а ассемблерная вставка...
void Target_Thread(DWORD* WID)
{
DWORD id = *WID;
__asm
{
MOV EDI, id
MOV EBX, 0x00693D60
MOV EAX,DWORD PTR DS:[BA]
PUSH EDI
MOV ECX,DWORD PTR DS:[EAX+0x20]
ADD ECX,0x0EC
CALL EBX //elementic.00693D60
RETN
}
}
Вот тут вот у человека, тоже вылеты, и автор гайда по написанию бота отвечает, что "Адрес функции таргета 00681F50 ", почему ? Ведь ясно же написано, что "\elementc.00606A70", значит адрес функции таргета: 0x00606A70...
Но даже попробовав этот вариант, мне это не помогло, все равно вылет клиента на строчке создания потока: hProcThread = CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)pFunction, pParams, NULL, NULL); ....
//================================================== ====================
Никогда раньше ассемблерных вставок не делал, соответственно как передать в C++ ссемблер не зна. Сегодня посмотрел примеры, там везде написано _asm, а не __asm, ну, что ж исправил. Результата не дало, клиент по прежнему вылетает при попытке программно выделить моба.
//================================================== ====================
А собственно зачем мне все эти HP персонажа, его мана и прочее. НАфиг, перепишу весь проект, создам каркас приложения, закину туда кнопку и напишу лишь те ф-ции которые нужны для выделения моба и вставки ассемблера в клиент игры...
//================================================== ====================
Вчера проверил функцию VirtualAllocEx(), если туда ввести не 511байт, допустим, а 5 мегабайт и посмотреть в диспетчере задач на выделенную память, то память реально выделяется. Есть еще пара мыслей для проверки....
//================================================== ====================
Собственно, когда выделять память? Мне кажется все равно и думаю что при инициализации функции-члена класса отвечающего за наш диалог...
Собственно, новый [Ссылки могут видеть только зарегистрированные пользователи. ], без всякой мишуры, типа HP персонажа, маны и т.д. и т.п. и тоже вылетает. (
Последний раз редактировалось Xantrax; 28.04.2013 в 17:00.
Причина: Добавлено сообщение
Для выделения и прочих плюшек гораздо проще юзать пакеты. К инжектам кода обращаюсь только из-за невозможности реализовать идею пакетами. А выделение моба - пакет из 6 байт 02\00\xx\xx\xx\xx. Сам инжект пакетов такой же, как и инжект кода.
Сейчас тоже ступор с инжектом...
Последний раз редактировалось bsbalex; 03.05.2013 в 17:59.
Не думаю, что у кого-то при первом знакомстве с инжектами их не было
Цитата:
Сообщение от Xantrax
Зачем вообще столько много функций: создаем функцию инжектор, создаем функцию, которая определяет параметры нашего инжекта, а потом еще сверху забиваем все это функцией которая вызывает функцию инжектор, зачем?
Для структуризации проекта, для простоты написания новых прог на основе ранее разработанных структур, для более простого дополнения уже написанных. Сам инжектор не является в итоге независимым, он становится составляющей более общей структуры client, а уже эта структура включает в себя функции не только инжекта, но и считывания памяти и другие, вобщем всё что касается именно клиента. Потому так и сделано: сам инжектор, затем множество функций(в которых происходит подготовка кода для внедрения в клиент и отвечающих за различные действия в игре) которые могут быть изменены/удалены/дополнены. Потому в новосозданном проекте достаточно будет объявить структуру CLIENT, а далее без заморочек писать client.inject.полетели() или client.inject.пиу_по_мобу(вид) а не
inject.InjectAndExecute(&Target_THREAD,&wid);
К тому же эта обёртка сделана для того, чтобы в дальнейшем по статье преобразовать такие функции так, чтоб они готовили уже готовый байткод для исполнения в клиенте с уже "вмонтированными" параметрами, для того чтоб не передавать 2 параметра - адрес функции и адрес параметров, а просто передать исполняемый байткод инжектору(самих их мы инжектить уже не будем и не сможем, и обойтись без них тоже).
Цитата:
Сообщение от Xantrax
Вот тут вот у человека, тоже вылеты, и автор гайда по написанию бота отвечает, что "Адрес функции таргета 00681F50 ", почему ? Ведь ясно же написано, что "\elementc.00606A70", значит адрес функции таргета: 0x00606A70...
Уважаемый, статья писалась давненько, потому после этого были обновления(не знаю сколько их точно было) и оффсеты пеменялись, это надо понимать. Вполне возможно и сам ассемблерный код различных функций теперь отличается от того что указан в теме. Кстати, подобные проблемы уже у кого-то были, поэтому в начале темы я написал строку
Цитата:
Сообщение от dwa83
АДРЕСА И ОФСЕТЫ СЛЕДУЕТ ЗАМЕНИТЬ НА НОВЫЕ
, чтоб народ почаще обращал внимание на дату написания .
Цитата:
Сообщение от Xantrax
Я конечно никогда не вставлял ассемблерный код, но разве так надо вставлять функцию в виде параметра?
inject.InjectAndExecute(&Target_Thread,&wid);
да, а почему нет? Не функцию а её адрес. Понимаете разницу? Target_Thread() (именно со скобками) в готовом коде будет как вызов функции и получения результата её работы, но нам не нужен результат, эта функция вообще никогда не будет работать в нашей программе, она будет выполняться внутри клиента, это функция-заготовка. Потому мы пишем параметр Target_Thread - это не результат работы функции а именно АДРЕС её нахождения в коде НАШЕЙ проги. Причём не просто адрес а указатель на место где хранится адрес, как требует наша функция InjectAndExecute, потому разыменовываем - &адрес_функции.
в итоге наша прога
код..
код...
код_функции_таргета..
код_функции_взлёта
и тд..
код..
код..
причём куски отдельных функций указанных в таком примере являются полноценными функциями, но никогда не вызываются и не работают в нашей проге, они "выдираются" по адресу, полученному указанием имени функции без скобок Target_Thread, и перекопируются в клиент, а потом уже там в клиенте после запуска потока выполняют свою работу.
Цитата:
Сообщение от Xantrax
Вчера проверил функцию VirtualAllocEx(), если туда ввести не 511байт, допустим, а 5 мегабайт и посмотреть в диспетчере задач на выделенную память, то память реально выделяется. Есть еще пара мыслей для проверки....
Что касается 511 байт, это значение осталось с тех пор, как я при каждом инжекте выделял память заново и затем удалял. Так вот мне "шепнули на ушко", что тестировали, и 511 байт почему-то по скорости выделялось намного быстрее чем например даже 512. Сам я этого не тестировал, я просто прислушался и оставил так. Этого вполне достаточно для хранения любой функции и параметров(если инжектятся поотдельности). Но вы можете и 5мб выделять, если это происходит один раз в начале работы программы и не освобождается до закрытия проги.
Ммм, долго я мучился с инжектом асм кода, потом по совету добрых людей попробовал отправлять пакеты, с пакетами дела обстоят гораздо лучше.
С пакетом на выделение моба понятно все, а как быть с атакой моба? Где взять пакет на обычную атаку моба?
А ведь радиус действия обычной атаки находится не в зоне ее, так сказать, действия... Т.е. получается еще нужно подбежать к этому мобу еще...
Ммм, я разобрался, для атаки нужно записать в память пакет вида /х03/х00/х00.
1) Теперь разобраться бы, что с лутом, как его подбирать...
2) И еще хотелось бы понять систему передвижения (по земле) перса в заданные координаты...
Последний раз редактировалось Xantrax2150198; 15.05.2013 в 20:44.
Как вариант поставить действие Поднимать предметы на кнопку и отправлять ее нажатие в окно командой sendmessage
Мы в этой теме разбирали виртуальное нажатие клавиш и как оказалось, нужно сначала разморозить окно (с этим я пока еще не разбирался). Да и как я посмотрел, там два Unfreeze адреса, плюс еще UnfreezeData, какой из них брать - не понятно... Ну, и как это все еще в код добавить, тоже понимания пока нет (так как не думал над этим).
Ну, а с асм кодом на Visual C++ у меня вообще какие-то проблемы большие... Надо будет, что-то простое попробовать сделать с инжектом асм кода, а потом уже переходить к перемещениям по координатам...
Последний раз редактировалось Xantrax2150198; 16.05.2013 в 13:26.
Возрождение династий, ver 1.4.6 build 2305. Ну, я надеюсь сразу же примером отправки нажатия клавиши, чтобы убедиться, что окно действительно разморожено...
Вчера мучился с таймером в библиотеке MFC, кажется в чем-то разобрался...
Я вот думаю над логикой своего бота, сейчас он у меня атакует обычной атакой и выделяет ближайшего моба, соответственно и передвигается к нему, далее ищет в базе опять же ближайшего моба и опять путем обычной атаки бежит к нему. Соответственно забежать таким методом он может у меня фиг знает куда...
Мне бы хотелось, что бы он стоял в одной точке ( с определенными координатами) и если мобов в радиусе R нет, то после убийства последнего моба в этом радиусе - перс возвращается к этой точке... Далее время работы бота, ммм, ну, мне в голову пришла только идея по таймеру (т.е. задать ему (сначала программно 1*60мин*60сек*1000мсек = 1 час)), а потом уже с возможностью из CEdit выбирать время...
Спасибо...
Эммм, я не играю в эту игру (PW), и вот у меня вопрос:
Я создал война, как применить из бота обычную атаку путем отсылки пакета - ясно, я так понимаю, что использовать классовые скиллы можно тоже с помощью отправки пакетов, нужно только указать ID скилла и WID моба в отсылаемом пакете. У война с самого начала есть специальная атака, но названия ее нет, при наведении сверху написано - Уровень 1, а что это за атака, не пойму, соответственно и не могу найти ID скилла из этой темы. Подскажите пожалуйста, правильно ли я думаю, что:
1) Можно отправлять применение скиллов с помощью пакетов?
2) Как узнать что за первый скилл-то у война?
Смотрю через PacketListener применение скилла, вижу:
29 00 01 00 00 00 00 01 63 18 10 80 (желтый - wid моба, красный как я понимаю - ID скилла), меняю WID моба, отсылаю, в игре мне пишут, что умения недоступны, это почему?
Я так полагаю, что нахожусь не на расстоянии действия скилла. Хм, тогда почему обычная атака вызывает перемещение персонажа на дистанцию достаточную для ее применения, а специализированная атака не вызывает перемещение персонажа?
Как переместиться к мобу на расстояние достаточное для применения специализированной атаки?
Последний раз редактировалось Xantrax2150198; 17.05.2013 в 16:36.
Возрождение династий, ver 1.4.6 build 2305. Ну, я надеюсь сразу же примером отправки нажатия клавиши, чтобы убедиться, что окно действительно разморожено...
Код:
const
Unfreeze1=$00436986;
Unfreeze2=$00436988;
var
hprocess,PID,ON: dword;
Wnd: thandle;
BC: size_t; //У меня версия delphi xe3 поэтому у меня "size_t" если у тебя версия ниже то юзай DWORD
begin
on:=1;
wnd:=findwindow('ElementClient Window',nil);
GetWindowThreadProcessId(Wnd,@pid);
hProcess:=OpenProcess(PROCESS_ALL_ACCESS,False,pid);
WriteProcessMemory(hprocess,Ptr(unfreeze1),@on,SizeOf(on),BC);
WriteProcessMemory(hprocess,Ptr(unfreeze2),@on,SizeOf(on),BC);
SendMessage(Wnd,WM_KEYDOWN,VK_TAB,0);
end;
Цитата:
Мне бы хотелось, что бы он стоял в одной точке ( с определенными координатами) и если мобов в радиусе R нет, то после убийства последнего моба в этом радиусе - перс возвращается к этой точке...
Структура мобов:
BA +0x1C +0x1C +0x24 +0x18 +(i*0x4) +0x4 /i = 0 - 0x300/
+0x284 Distance, float
Считываешь дистанцию мобов и заносишь в список тех, кто подходит по радиусу, дальше убиваешь, если мобов больше не осталось возвращаешься на место.
Цитата:
1) Можно отправлять применение скиллов с помощью пакетов?
Не совсем понял вопроса. как отправлять ПРИМЕНЕНИЕ скилов. Может сам скил ? Если именно так то считывай корды моба, подходи на них и бей скилом.
Цитата:
2) Как узнать что за первый скилл-то у война?
Через PWPacketListener ловишь этот самый пакет и переводишь ID кила из 16-ричной СС в 10-тичную
Цитата:
меняю WID моба, отсылаю, в игре мне пишут, что умения недоступны, это почему?
Либо не правильно перевел ID моба в 16 СС, либо расстояние не подходит.
Цитата:
Как переместиться к мобу на расстояние достаточное для применения специализированной атаки?
Использовать инжект движения. пример кода можно найти в теме помощи создания программ на Pw
________________
Хотите как то отблагодарить за помощь?
Не стесняйтесь нажимайте "Спасибо"
Делаю программы на заказ, по всем вопросам в скайп: Ginrey2
Посмотрите в системных ресурсах процедуру WriteProcessMemory и узнаете, что вам требуется. все ресурсы хранятся в папке с программой
Эту фразу вообще не понял, что вы понимаете по системными ресурсами? WriteProcessMemory(...) WinApi функция, последний параметр - указатель на переменную, которая получает число байтов переданных в процесс, его можно указать как NULL.