PDA

Просмотр полной версии : [Статья] "Поиск инжектов" или "Наш код в чужом процессе"


Dinmaite
27.05.2011, 00:34
Тема: Поиск кода для инжекта в игре Perfect World

Для чего это нужно?
В основном для ботов, самый простой пример - выделение моба.\
Наверняка все вы заметили что после обновления с джинами MHS-bot перестал верно выделять мобов.
Все это из за его системы выделения, а именно MHS просто помещает в ячейку цели WID (World IDentificator) цели.
На Делфи это выглядело бы так:
WriteProcessMemory(hProcess,ptr(Target_addr),@WID, ByteCount)
Однако простая запись в ячейку и до обновления была не лучшим выходом (первой атакой должен был быть скилл)
В чем плюс инжекта?
Фактически когда мы делаем иньекцию кода в память, мы заставляем работать функцию самого клиента.
При этом выделение происходит по всем правилам, как со стороны клиента, так и со стороны сервера.

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

Разделим работу на 3 этапа:


1. Находим базовый адрес (как это сделать) ([Ссылки могут видеть только зарегистрированные и активированные пользователи]).
2. Снимаем выделения с моба (если моб был выделен)
Нажимаем на базовом адресе правой и выбираем пункт "Кто получает доступ к адресу" (дело в том что недалеко от большинсва функций, которые мы можем инжектить лежит код получения какой указателя на какую-либо структуру данных).
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Откроется окно и мгновенно наполнится адресами (и соответствующим им кодом) обращения к базовому адресу.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
3. Возвращаемся в окно ПВ, немного побегаем, попрыгаем (но не выделяем мобов, и не ловим на себя агромобов), окошко СЕ в это время заполнится большим количеством записей.
Но среди них все ще не будет нужной.
4. Прокручиваем скроллер вниз. Выделим последнюю строку в списке (для удобства), возвращаемся в ПВ и выделяем моба. Добавились несколько записей, одна из них то нам и нужна.
В поле "Count" указывается число раз, которое была выполнена соответствующая строка кода. Удобно несколько раз выделить моба, дабы точнее определиться с необходимыми строками.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Переписываем адреса "понравившихся" (читай наиболее вероятных) записей в блокнотик, или куда вам удобнее. Выключаем СЕ свою работу он выполнил.
Конец первого этапа.



1. Открываем OllyDbg и цепляем его к PW, для этого нажимаем open>attach, в появившмся окне ищем запись elementclient и 2 раза тыкаем на нее.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
2. Когда OllyDbg подключится к PW в панели состояния будет написано, что поток остановлен на точке останова дебаггера.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Нажимаем F9, тем самым продолжаем выполнени кода PW.
3. Открываем блокнотик, куда мы записали адреса возможных функций, копируем первый.
В OllyDbg нажимаем ctrl+g (горячая клавиша перехода на адрес) и в появившееся окно со строкой ввода вставляем наш адрес, давим enter (так как мы находимся не в основном модуле программы а в ntdll процедуру повторить 2 раза).
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Мы перешли на выбранный адрес.
4. Теперь смотрим что же у нас здесь такое.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

С данного пункта следует полагаться на собственную интуицию, логику и умение читать disasm :)
Нужно предположить как должна выглядеть вызов функции, какое количество и каких параметров должны в обязательном порядке передавать в нее. Поскольку мы разбираем функцию выделения моба в тергет, логично было бы предположить, что одним из обязательных параметров долен быть WID моба.

Интерисует нас вот этот кусок кода (поскольку он представляет собой внутреннюю функцию клиента):

004619CD |. A1 0CB9A500 MOV EAX,DWORD PTR DS:[A5B90C]
004619D2 |. 57 PUSH EDI ; /Arg1
004619D3 |. 8B48 20 MOV ECX,DWORD PTR DS:[EAX+20] ; |
004619D6 |. 81C1 EC000000 ADD ECX,0EC ; |
004619DC |. E8 8F501A00 CALL elementc.00606A70 ; \elementc.00606A70

CALL elementc.00606A70 - вызов функции (CALL - команда перехода в функцию; elementc - имя модуля, содержащего функцию, 00606A70 - адрес функции)
PUSH EDI - передача в функцию параметра, что это за параметр нам еще предстоит понять.
Группа команд:

MOV EAX,DWORD PTR DS:[A5B90C]
MOV ECX,DWORD PTR DS:[EAX+20]
ADD ECX,0EC

Подготовка указателя, на какой-то параметр (опля, пишу статью, а что за параметр представления не имею, однако , в данном случае, это не важно, так как нам предстоит лишь повторить действия клиента).

5. Разберемся с аргументом. Для этого поставим BreakPoint (точка останова) на строку:
004619D2 |. 57 PUSH EDI ; /Arg1
(Выделить строку, нажать F2).
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
Теперь перейдем в окно PW и выделим моба/персонажа.
Видим что клиент встал на точку останова (правый нижний угол, надпись Pause)
[Ссылки могут видеть только зарегистрированные и активированные пользователи]
В комментарии напротив Arg1 теперь написано 80101033, пока что для нас это цифра. Сравним ее с WID того моба, которого мы выделили.
Здесь у нас есть 2 пути:

Я надеюсь вы знаете как ищется адрес таргета.
[BA]+$1C+$20+B0C (для версии на момент написания статьи)


Для этого необходимо запустить elementclient с параметром console:1 .
Откроем консоль (Shift+~) и введем команду d_npcid.
Теперь мы выдим WID всех NPC.
[Ссылки могут видеть только зарегистрированные и активированные пользователи]

Что мы видим? Цифра, указанная в отладчике совпадает с WID NPC.

В общем первую функцию мы разобрали, она достаточно похожа на выделение моба, простая функция, с близким вводом аргумента, значение аргумента совпадает с WID NPC, красиво и лаконично.

В принципе для меня этого было бы достаточно, что бы начинать писать код (интуиция подсказывает что это именно та функция, которая нам нужна).
Особенно учитывая, что остальные не получают аргумента содержащего WID моба/персонажа/NPC.



Для начала нам потребуется инжектор (© BuBucekTop):

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;

Таким образом мы создаем свой поток в памяти выделенной клиенту (тоесть по сути вставить в клиент свой код)
И тип данных:

type
PParams = ^TParams;
TParams = packed record
WID: DWord;
end;


Теперь подготовим код, который и будет кодом нашего потока.
И который будет вызывать функцию клиента.
По сути повторям код клиента (добавив передачу параметров и прочую обвязку):

004619CD |. A1 0CB9A500 MOV EAX,DWORD PTR DS:[A5B90C]
004619D2 |. 57 PUSH EDI ; /Arg1
004619D3 |. 8B48 20 MOV ECX,DWORD PTR DS:[EAX+20] ; |
004619D6 |. 81C1 EC000000 ADD ECX,0EC ; |
004619DC |. E8 8F501A00 CALL elementc.00606A70 ; \elementc.00606A70

на выбранном нами языке программирования (в моем случае - Delphi)

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;


Кидаем на форму кнопку, в обработчике OnClick пишем

procedure TForm1.Button1Click(Sender: TObject);
var
aParams: TParams;
PID, hProcess: DWord;
begin
GetWindowThreadProcessId( FindWindow('ElementClient Window', nil), @PID);
hProcess:= OpenProcess(PROCESS_ALL_ACCESS, False, PID);
aParams.WID:= StrToInt('$' + Edit1.Text); // WID персонажа\моба\NPC
InjectFunc(hProcess, @TargetCall, @aParams, SizeOf(aParams ) );
CloseHandle(hProcess);
end;

Вот это главная проверка, если инжект прошел - значит все верно.
Если инжект не прошел - значит все плохо.
Пример программы - в аттаче.

megasniper
08.07.2011, 20:03
откуда в
GetWindowThreadProcessId( FindWindow('ElementClient Window', nil), @PID);
взялось 'ElementClient Window'? вернее, как это определили?

Dinmaite
08.07.2011, 20:41
откуда в
GetWindowThreadProcessId( FindWindow('ElementClient Window', nil), @PID);
взялось 'ElementClient Window'? вернее, как это определили?

Интересный вопрос.
Функия есть такая в WinApi - GetClassName.

Jok3r666
21.08.2011, 09:12
В комментарии напротив Arg1 теперь написано 80101033, пока что для нас это цифра. Сравним ее с WID того моба, которого мы выделили.
У меня в EDI другое значение и причем в нем присутствует буква, в чем беда может быть? на айди в таргете оно ваще не похоже.

Sirioga
21.08.2011, 09:45
У меня в EDI другое значение и причем в нем присутствует буква, в чем беда может быть? на айди в таргете оно ваще не похоже.
Проверься с помощью консоли. Команда d_npcid.

Jok3r666
21.08.2011, 09:55
шок все правильно, с буквами, тогда в какой тип переменной выкидывать таргет, что бы вывести его правильно в стринги :d ? и кст через CE выдает тоже не правильно получается, или может в таргет не тот id передается?

VeTaL_UA
21.08.2011, 10:00
У меня в EDI другое значение и причем в нем присутствует буква, в чем беда может быть? на айди в таргете оно ваще не похоже.
/facepalm
1)Включи инженерный калькулятор;
2)Выбери там hex;
3)Впиши туда то, что в EDI;
4)Переставь на dec.
5)???????
6)Profit

Fanky3
25.08.2011, 19:50
все бы хорошо но вот как найти инжекты перемещения по карте, или заставить бота двигаться по вейпоинтам с помощью инжектов...

Dinmaite
25.08.2011, 20:11
все бы хорошо но вот как найти инжекты перемещения по карте, или заставить бота двигаться по вейпоинтам с помощью инжектов...

Найти инжект перемещения. Тоесть повторить для перемещения, по аналогии, то что было написано выше.
Составить карту вейпоинтов.

Jok3r666
27.08.2011, 13:28
P1:=aPParams^.WID;
Можно узнать что обозначает этот символ ^ и для чего он служит?

Domin.5
27.08.2011, 21:33
aPParams - принадлежит типу PParams, что является указателем на тип TParams.
короче говоря, переменная aPParams - это 4 байта, ссылающиеся на структуру TParams.
^ обозначает, что обращаешься ты не к адресу, а к структуре, по нему лежащей.
фуф. надеюсь, по-русски получилось.

Dinmaite
27.08.2011, 21:37
Разименование указателя.

Jok3r666
28.08.2011, 09:07
aPParams - принадлежит типу PParams, что является указателем на тип TParams.
короче говоря, переменная aPParams - это 4 байта, ссылающиеся на структуру TParams.
^ обозначает, что обращаешься ты не к адресу, а к структуре, по нему лежащей.
фуф. надеюсь, по-русски получилось.
получилось все класно)) все понял

Посоветуйте, сайт где хорошо разжевано обучение работе с памятью, указателями и т.д. с нуля желательно ибо с памятью дел ваще не имел.

ktulx
30.08.2011, 01:03
Здравствуйте!

Большое спасибо за статью, очень понравилась, всё понятно описано.
Не могли бы вы подсказать мне, желательно на примере, для наглядности, как заинжектить код, выполняющий какое-нибудь элементарное действие? Например есть форма с единственной кнопкой, при нажатии на которую, персонаж выделяет моба с заданным WID, после чего просто перемещается на заданные координаты. Я был бы очень признателен. Руки вроде прямые, чай, сигареты на ночь есть =) Практики почти нет. Ах да, пользуюсь AutoIt.

Dinmaite
30.08.2011, 01:34
На автоите не подскажу, писать на нем я не могу да и не хочу.
А вообще во вложении к певому посту, таки, предоставлен код, выполняющий простейшее действие - выделяющий моба с заданным WID.
А для того что нужно вам, таки, необходимо использовать 2 инжекта (выеление моба и перемещение).

Вообще желаю спокойной ночи.

ktulx
30.08.2011, 02:28
Dinmaite, понял, спасибо. Видимо придётся начать дружить с Делфи, хотя бы для саморазвития. Тем более что на стадии нуба, особой разницы в языках заметно быть не должно.

Добавлено через 15 часов 42 минуты
Подскажите, пожалуйста, кто смыслит. Таки решил я попробовать и на примере примера (лол) в статье, просто повесить на кнопку прыжок. При нажатии на кнопку клиент вылетает с ошибкой. Думаю что где-то с адресами напутал. Привожу весь код, чтобы не цитировать.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

type
PParams = ^TParams;
TParams = packed record
WID: DWord;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

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 JumpCall(aPParams:PParams);Stdcall;
var CallAddress:pointer;
begin
CallAddress:=pointer($00476970);
asm
pushad
push $0
push $C8
push $1
push $3F800000
push $4
mov ecx, dword ptr [$A5B90C]
mov ecx, dword ptr [ecx+$20]
mov eax, $41200000
mov dword ptr[ecx+$B80], $0
mov dword ptr[ecx+$B94], $0
mov dword ptr[ecx+$B98], $0
mov dword ptr[ecx+$B9C], $0
mov dword ptr[ecx+$BA4], eax
mov dword ptr[ecx+$BF4], $1
mov dword ptr[ecx+$BFC], eax
call CallAddress
popad
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
aParams: TParams;
PID, hProcess: DWord;
begin
GetWindowThreadProcessId( FindWindow('ElementClient Window', nil), @PID);
hProcess:= OpenProcess(PROCESS_ALL_ACCESS, False, PID);
InjectFunc(hProcess, @JumpCall, @aParams, SizeOf(aParams ) ); // èíæåêòèì ôóíêöèþ
CloseHandle( hProcess); // çàêðûâàåì õåíäë ïðîöåññà
end;


end.

Подскажите, пожалуйста, в чём проблема? Всю ночь-утро сижу, моск кипит. :omg:

Njkzy80
03.09.2011, 13:32
Уважаемый Dinmaite, подскажите пожалуйсто надо ОЛИ настраивать както просто у меня в столбике где должно быть ARG нету ничего вообще пустой столб ((
И второй вопрос кроме адресов при обнове меняется и весь код инжекта? Тогда какже инжекты работаю после обновы если им просто адреса меняем?

Dinmaite
03.09.2011, 14:11
Уважаемый Dinmaite, подскажите пожалуйсто надо ОЛИ настраивать както просто у меня в столбике где должно быть ARG нету ничего вообще пустой столб ((
И второй вопрос кроме адресов при обнове меняется и весь код инжекта? Тогда какже инжекты работаю после обновы если им просто адреса меняем?

Насколько знаю настраивать ничего не надо. Просто програть анализ.
Иногда меняется код инжекта, чаще просто адрес.

Автопуть работает, использование скиллов пришлось шаманить, пакет колл работает.

iMockBa
23.09.2011, 04:21
Жаль на портале нет темы о Реквием онлайн.

Подскажите по каким критериям искать ВИД моба .

Sirioga
23.09.2011, 08:21
Жаль на портале нет темы о Реквием онлайн.
Действительно.
Подскажите по каким критериям искать ВИД моба.
Что ты имеешь ввиду под критерием? Мне почему-то кажется, что ты таким странным словом обозвал способ поиска))) Если это действительно так, то нужно в CE танцевать от нуля или от неизвестного значения.
Примеры:
Сбрасываем таргет, ищем 0, берём таргет, ищем Increased value, сбрасываем таргет, ищем 0... повторить до посинения.
Сбрасываем таргет, ищем неизвестное значение, берём таргет ищем Increased value, сбрасываем таргет ищем Decreased value.
Оба способы хороши, не забываем вызывать переодически "значение не изменилось" для более быстрого нахождения того, что лежит у тебя в таргете.
критериям
Если же действительно имелись ввиду критерии, то нет никаких признаков у WID моба, это может быть число выдуманное лицом восточной национальности в тёмную безлунную ночь... ID он и в африке ID ;) Хотя если касаться Perfect World, то есть одна отличительная черта, все npc (в том числе и мобы), имеют шаблон 8010XXXX но все значения 8010XXXX принимать за id моба, согласись не совсем корректно:)

iMockBa
23.09.2011, 10:59
Действительно.

Что ты имеешь ввиду под критерием? Мне почему-то кажется, что ты таким странным словом обозвал способ поиска))) Если это действительно так, то нужно в CE танцевать от нуля или от неизвестного значения.
Примеры:
Сбрасываем таргет, ищем 0, берём таргет, ищем Increased value, сбрасываем таргет, ищем 0... повторить до посинения.
Сбрасываем таргет, ищем неизвестное значение, берём таргет ищем Increased value, сбрасываем таргет ищем Decreased value.
Оба способы хороши, не забываем вызывать переодически "значение не изменилось" для более быстрого нахождения того, что лежит у тебя в таргете.

Если же действительно имелись ввиду критерии, то нет никаких признаков у WID моба, это может быть число выдуманное лицом восточной национальности в тёмную безлунную ночь... ID он и в африке ID ;) Хотя если касаться Perfect World, то есть одна отличительная черта, все npc (в том числе и мобы), имеют шаблон 8010XXXX но все значения 8010XXXX принимать за id моба, согласись не совсем корректно:)

Спасиба за быстрый ответ ....именно метод поиска меня и интересовал ))

В данный момент я пытаюсь реализовать выбор моба в таргет на C# в Дельфи я ещё больше нуп чем в си шарпе ))
И для начала взял в помощь уже готовую библиотеку BlackMagic
похоже что она работает отлично но я всётаки уткнулся в этом самом поиске ВИД моба ...так как в одной из линий АСМ кода который я пытаюсь заиньектить (код взят из самого клиента и я просто пытаюсь его повторить как вы и обьясняли в теме ) передача параметра моба которого нужно взять в таргет происходит из статического адреса ....поэтому после иньекта в клиенте происходит появление в таргете ХП Бара без имени моба ....и клиент само собой зависает .....тоесть я так понимаю без передачи параметра в ручную никак не обойтись ?

п.с. кнопку СПАСИБО ненашол видимо у меня недостаточно постов.

Sirioga
23.09.2011, 11:18
И для начала взял в помощь уже готовую библиотеку BlackMagic
Ни о чем не говорит, даже в гугл сходил.

тоесть я так понимаю без передачи параметра в ручную никак не обойтись ?
Допустим MHS бот, даёт возможность выбрать нужных мобов по таргету, т.е. берёшь в таргет жмёшь горячую клавишу, и он заносит в инишник WID этого моба и так до 10 раз, потом запускаешь бота и он атачит всех мобов по заданному ID, если конечно он уже реснулся, при этом хаотично, может побежать и к самому дальнему, в случае с пв после респа мобов их WID не меняется.
Допустим Dinmaite в своём боте обращается к массиву окружающих "тел", вычисляет из них мобов и расстояние до них, вычисляет какой из мобов ближе всего к персонажу, берёт в таргет и атакует его.

п.с. кнопку СПАСИБО ненашол видимо у меня недостаточно постов.
Появится после набора 10 сообщений на форуме.

iMockBa
23.09.2011, 18:01
BlackMagic DLL очень известна ...странно что в гугле ненашол ...
Как тут тема Реквием Онлайн откроется я выставлю обезательно туториал и саму библиотеку.

iMockBa
25.09.2011, 21:56
Доброго времени суток.
Помогите пожалуста разобраться .
[Ссылки могут видеть только зарегистрированные и активированные пользователи] ([Ссылки могут видеть только зарегистрированные и активированные пользователи])

в СЕ нашол адресс по которому начинается вызов моба в таргет .
( ММОРПГ Реквием Онлайн)
при попытке заиньектить и вызвать данную функцию кодом (C#)

pushad
pushfd
mov ecx,[WID] // для чтения ВИД использую ReadInt
mov edx,0x7c29e0 // адресс функции
push ecx // Начинаю повторять действия клиента
mov ecx,[0xa48e40]
call edx // вызываю функцию .
retn

во время иньекта и вызова данной функции в клиенте происходит следующее
в таргете у персонажа появляется ХП бар пустая без имени моба.
и через несколько секунд клиент зависает.

где я мог ошибиться ? учитывая то что адресс 0ха48е40 из которого передаются параметры в есх является статическим .
похоже что в момент вызова функции в коде нехватало аргументов ...которые возможно должны быть переданны в стек ещё до вызова функции ?

если использовать ОллиДбг и поставить точку остановки на линию
mov ecx,[0xa48e40]
то видно что значение аргумента есх не совпадает с ВИД моба полученного с помощью СЕ.

подскажите как быть ...
Нельзя ли усуществить вызов данной функции методом прыжка на неё ?

Dinmaite
25.09.2011, 22:19
Можно осуществить но зачем неясно.
Личто у меня создалось впечатление что ты 2 раза загнал содержимое регистров в стек (pushad) но ни разу не выгрузил их - получив смещение стека.

iMockBa
25.09.2011, 22:36
тоесть похоже что линия
mov ecx,[0xa48e40]
лишняя ?

Dinmaite
25.09.2011, 23:20
тоесть ты забыл в конце процедуры вызвать popad (2 раза судя по коду) и зря используешь edx.

iMockBa
26.09.2011, 02:31
похоже что я передаю неверный параметр ВИД в процедуру ...можно попробовать ваш сампль изменив в нём ВИД моба и имя клиента ?
клиент Requiem.exe или по окну Requiem
адресс с которого читать ВИД 0xa48e40+0x320
если конечно вас не затруднит переделать сэмпль для пробы .я в дельфи полнуй нуб неуверен что сам сумею переделать.

Dinmaite[Work]
26.09.2011, 09:19
iMockBa, возможно вечером.
Часиков в 7 напишите мне в асю, номер в профиле.

iMockBa
26.09.2011, 10:56
спасиб . напишу вечерком .

Добавлено через 11 часов 23 минуты
Уважаемый Динмайт . я тут немного разобрался в моём коде ....
переделал на вот такой
pushad
push 0x258d4178 // значение взятое из ОЛЛИДБГ...скорее всего это и есть тот самый ВИД...хотя значение не совпадает с найденным в СЕ.....
mov ecx, [0xa48e40]
call 0x7c29e0
popad
retn

этот код сработал .функция вызвалась .....осталось только разобраться как читать значение ВИД правильно .....или если это не ВИД есть ли какие нибудь идеи как найти это значение ?

есть ли способ протрассировать где и когда было измененно значение есх ?

BritishColonist
26.09.2011, 22:38
Идея есть.
В общем, полезно будет сделать программку, которая будет отображать данные начиная с определённого адреса по оффсетам (программа будет читать базовый адрес, находить начало структуры игрока/монстра и выводить всю структуру (до определённого места, скажем, до 1000 байт от начала)). Для удобства. Просмотри структуру игрока (а лучше монстра, которого выделяешь) на предмет того непонятного значения.
Вообще, твоя задача сейчас - докопаться, откуда берётся это значение. Отследи все операции, пихающие в регистр данное значение (вероятно, придётся много копаться в коде асма и ставить много-много брейкпоинтов в олли, однако оно того стоит - рано или поздно научишься понимать всё на лету).

iMockBa
27.09.2011, 01:01
)) да я так и пытаюсь вычислить ...но учитывая то что я только совсем недавно начал изучение АСМ что тормозит процесс..а как обычно хочется много и сразу )

Dinmaite[Work]
27.09.2011, 09:23
этот код сработал .функция вызвалась .....осталось только разобраться как читать значение ВИД правильно .....или если это не ВИД есть ли какие нибудь идеи как найти это значение ?

есть ли способ протрассировать где и когда было измененно значение есх ?

Честно говоря я не знаю что передается в этом аргументе (нет у меня клиента данной игры). По сути как найти WID написано в данном гайде.
Вообще способ есть, ставишь брейкпоинт и начинаешь подниматься вверх по присвоениям. Из твоего скрина видно что конкретно сюда он передается в стеке, вероятно в вызове иерархически являющимся родителем (эк я задвинул, но надеюсь понятно) значение и грузится в стек.

BritishColonist
27.09.2011, 13:45
Как говорит один хороший реверсер, в ECX обычно передаётся указатель this для функций, описанных как __thiscall, то бишь для членов классов. Особенно это заметно, когда до этого в ECX ничего не помещалось, а затем вызвалась функция, которая сразу копирует содержимое ECX в другой регистр.
Лично из своего опыта могу сказать, что большинство команд "push ECX" сразу перед вызовом функции (call) отправляют в стек именно структуру игрока.

nicolaiv007
14.01.2012, 09:38
хорошая пословица

alegr
21.04.2012, 20:01
У меня оллидбг не хочет привязываться к пв... делаю аттач, кликаю на пв, и программа критует. от админа запускал - та же беда =( как быть?

Meg(0)
23.05.2012, 21:05
что за "elementclient с параметром console:1 ."? где его найти???
shift + ~ не работает....
вот как сделать это..
Создайте пустой .txt файл в папке где расположен файл elementclient.exe
Скопируйте/Вставьте в него код, представленный ниже:

Код:
elementclient.exe game:cpw console:1

Переименуйте ваш файл в Launcher.bat
Запустите bat файл
Жмите Shift+~ открытия консоли

vogel
23.05.2012, 21:51
1) elementclient.exe - основной исполняемый файл клиента. Если вы не знаете где его найти - эта тема не для вас.
2) запуск с параметром console:1 уже не поможет - включение консоли отключено в конфигах интерфейсов клиента.

Meg(0)
23.05.2012, 22:40
1) elementclient.exe - основной исполняемый файл клиента. Если вы не знаете где его найти - эта тема не для вас.
2) запуск с параметром console:1 уже не поможет - включение консоли отключено в конфигах интерфейсов клиента.

как бы я уже написал,как сделать это..


что я не так нашёл...вроде всё так сделал,но при запуске выбивает с клиента или просто зависает,ичего не происходит..

[Ссылки могут видеть только зарегистрированные и активированные пользователи] ([Ссылки могут видеть только зарегистрированные и активированные пользователи])

P1: DWord; //
begin //
P1:=aPParams^.WID; //
asm
MOV EDI, P1 // Вносим WID моба в регистр EDI
MOV EBX, $0062FD80 // Вносим в свободный регистр адрес функции
MOV EAX,DWORD PTR DS:[$A571E0] //
PUSH EDI //
MOV ECX,DWORD PTR DS:[EAX+$1C] //
ADD ESP,$0C //
CALL EBX // ; \elementc.0062fd80
end;
end;

ECX в этом блоке не нашёл,нашёл в следующем,подставил,всёравно ошибка,заменил его на ESP так же ошибка..

BritishColonist
24.05.2012, 00:10
Meg(0), зачем здесь "ADD ESP, $0C" ?
В отладчике показано, что эта команда находится до предыдущего "RETN 8", т.е. это вообще в другой функции.

Meg(0)
24.05.2012, 00:22
BritishColonist, меня тож это смутило.. но я не мог найти ADD ECX..с CE вроде правельный адрес взял..или искать до следующего Retn? я там какой-то нашёл,подставил,всёравно вылетел клиент

BritishColonist
24.05.2012, 00:29
Meg(0), а зачем вообще увеличивать ECX?
Важно повторить тот же код, что виден в отладчике, взяв при этом лишь необходимую для правильной работы часть.

Необходимо в первую очередь обратить внимание на это:
1) ESP (он может изменяться перед вызовом, но это мы уже отбросили);
2) ECX (он используется для вызова методов класса, хранит в себе this, т.е. указатель на конкретный экземпляр класса - например, на нашего игрока);
3) команды PUSH (они помещают параметры в стек перед вызовом функции через CALL).

Meg(0)
24.05.2012, 00:57
а push только EDI или другие надо использовать?

BritishColonist
24.05.2012, 14:18
Meg(0), можно использовать любые регистры или конкретные числа.
Важно в том же порядке поместить параметры до CALL.

[phallic]
30.05.2012, 13:10
Применим ли этот способ к другим играм, кроме PW? Я пытаюсь искать функции Warspear, но когда
Нажимаем на базовом адресе правой и выбираем пункт "Кто получает доступ к адресу
то игра начинает дико тормозить. В PW так же?

vogel
30.05.2012, 14:21
Применим. Warspear просто написан похуже...

BritishColonist
30.05.2012, 14:30
[phallic], да, у меня такая же ерунда в PW. Ужасные тормоза, если ставить BP на базовый адрес.
Но это не у всех. Наверное, от процессора зависит.

[phallic]
30.05.2012, 15:03
Странно, на ноутбуке i3, на компьютере AMD 3870, тормоза одинаковые :rolleyeyes:

А что делать, если я ловлю в Cheat Engine адрес, смотрю в олли, а там нет Push Arg1 и Call рядом? При этом бряк по тому адресу срабатывает.

dwa83
30.05.2012, 15:45
;3001669"]А что делать, если я ловлю в Cheat Engine адрес, смотрю в олли, а там нет Push Arg1 и Call рядом? При этом бряк по тому адресу срабатывает.
Может параметр через какой-то регистр передаваться без использования стека вроде бы..

BritishColonist
30.05.2012, 19:24
[phallic], в любом случае следует смотреть ниже и выше по коду, ставить ещё много-много BP (в OllyDbg), проверять, чему равны регистры (чтобы понять, где лежит нужное нам значение). Так можно будет во многом разобраться, но для начинающих это является сложной задачей.

P.S. И BP срабатывает в любом случае, а не только на командах PUSH и CALL.

Ilyialat
02.09.2012, 21:31
Всем привет =) У меня проблема( Нашёл базовый адрес, пытаюсь просмотреть функции в CE и у меня просто зависает игра( Я её открываю появляется её курсор, но графа не рисуется( Вырубаю её через диспетчер задач, и у меня СЕ функции показывает(вроде как рисования графики)( Что делать?(

Gigabyte88
21.02.2013, 12:22
Всем привет! Руки вроде из правильного места, схватываю на лету, надо лишь подтолкнуть в верном направлении. Искал инжект для копания шахты, ибо старый с обновой стал светофорить.

0046DEBC A1 CCFBB800 MOV EAX,DWORD PTR DS:[B8FBCC]
0046DEC1 52 PUSH EDX
0046DEC2 57 PUSH EDI
0046DEC3 8B48 1C MOV ECX,DWORD PTR DS:[EAX+1C]
0046DEC6 8B41 1C MOV EAX,DWORD PTR DS:[ECX+1C]
0046DEC9 8B48 28 MOV ECX,DWORD PTR DS:[EAX+28]
0046DECC E8 8F6D2000 CALL ELEMENTC.00674C60

00481772 8B0D CCFBB800 MOV ECX,DWORD PTR DS:[B8FBCC] ; ELEMENTC.00B90280
00481778 6A 00 PUSH 0
0048177A 57 PUSH EDI
0048177B 8B51 1C MOV EDX,DWORD PTR DS:[ECX+1C]
0048177E 8B4A 1C MOV ECX,DWORD PTR DS:[EDX+1C]
00481781 E8 1A20FBFF CALL ELEMENTC.004337A0

Оба куска получают верный песочный айди объекта (на моем примере трава) в переменной EDI, но при попытке инжекта ни один из вариантов не работает, но однако и не светофорит.
Где ошибка, господа? Почему в теме с адресами PickWalk 00472EE0 а у меня 004337A0?

procedure mine_drop(aPParams:PParams);Stdcall;
var
P: DWord;
begin
P:=aPParams^.WID;
asm
MOV EDI, P
MOV EBX, $004337A0
MOV ECX,DWORD PTR DS:[$00B8FBCC]
PUSH 0 // как понял это тип копаемой шахты, пробовал и 0 и 1 и 2
PUSH EDI
MOV EDX,DWORD PTR DS:[ECX+$1C]
MOV ECX,DWORD PTR DS:[EDX+$1C]
CALL EBX
end;
end;

P.S., код по памяти писал, ибо оригинал затер за неработоспособностью :nono:

Что это и зачем это нужно?
0046DEC3 8B48 1C MOV ECX,DWORD PTR DS:[EAX+1C]
0046DEC6 8B41 1C MOV EAX,DWORD PTR DS:[ECX+1C]
0046DEC9 8B48 28 MOV ECX,DWORD PTR DS:[EAX+28]
Это же все равно что
a=b+1
b=a+1
a=b+2
как то не логично...

Dinmaite
21.02.2013, 19:48
По поводу копания шахт не подскажу. Вероятнее всего код остался прежним, необходимо заменить адреса.


Что это и зачем это нужно?

Код:
0046DEC3 8B48 1C MOV ECX,DWORD PTR DS:[EAX+1C]
0046DEC6 8B41 1C MOV EAX,DWORD PTR DS:[ECX+1C]
0046DEC9 8B48 28 MOV ECX,DWORD PTR DS:[EAX+28]
Это же все равно что
a=b+1
b=a+1
a=b+2
как то не логично...

Абсолютно не так.
В ECX записывается значение из памяти.
Затем в EAX записывается значение из памяти.
Затем в ECX записывается значение из памяти.

Значения будут совсем не равны единице.

mirakita
22.03.2013, 13:58
та же проблема с пристыковкой СЕ к клиенту ПВ. есть ли альтернативный способ выцепить инжекты?
спасибо

sumikot
22.03.2013, 16:03
та же проблема с пристыковкой СЕ к клиенту ПВ. есть ли альтернативный способ выцепить инжекты?
спасибо
Самый простой - IDA. Но. Если есть адреса инжектов для другого клиента. Дизассемблируешь два клиента, один с известными адресами, другой с неизвестными. И методом поиска и сравнения находишь все, что нужно. Пример ([Ссылки могут видеть только зарегистрированные и активированные пользователи]).

nmartinez
27.07.2013, 19:41
writeprocessmemory не хочет нормально работать у меня =_= что то не нравится с параметрами.

Добавлено через 31 минуту
клиент вылетает при выполнении CreateRemoteThread

Добавлено через 6 часов 11 минут
Фух, разобрался. Все было куда проще.

Xantrax
28.07.2013, 13:13
Фух, разобрался. Все было куда проще.
Ну, что за люди? nmartinez Разобрался с проблемой, сообщи остальным, в чем была проблема и как ты разобрался, чтобы люди не мучались в след. раз столкнувшись с такой же проблемой.

edyapd
28.07.2013, 21:35
Замечательная статья.
Вот только адреса все поменялись. Найти их конечно не проблема. Они все выложены на форуме.
Но подскажите где я туплю, пытаюсь вместо

MOV EBX, $00606A70
MOV EAX,DWORD PTR DS:[$A5B90C]

Написать:

FullTarget: DWord;
BaseAddr: DWord;
FullTarget:= $00693D60;
BaseAddr:= $0B8FBCC;
.......
MOV EBX, FullTarget
MOV EAX,DWORD PTR DS:[BaseAddr]
Пока стоят числа, всё работает. Ставлю переменные игра вылетает.

Dinmaite
28.07.2013, 21:55
MOV EAX,DWORD PTR DS:[$A5B90C]
Указывает на значение, лежащее по адресу A5B90C.


MOV EAX,DWORD PTR DS:[BaseAddr]
Указывает на значение A5B90C.

BritishColonist
29.07.2013, 02:46
edyapd, попробуйте ради интереса сделать BA не переменной, а константой.

update: не уверен насчёт Delphi, но в C++ есть ещё " #define ", который позволяет сделать макрос или константу, но на самом деле код соберётся на этапе компиляции, вместо каждой такой константы подставится указанное изначально значение. Если в дельфи есть аналог этого #define, то это поможет решить данную проблему.
P.S. Но в итоге получится, что везде будет стоять конкретное число.

update2:
Если же нужна возможность менять базовый адрес во время работы программы (например, с помощью загрузки адресов из конфига), то потребуется прибегнуть к некоторым хитростям.
Если выполняемый код находится внутри DLL, загруженной в elementclient.exe, то достаточно прислушаться к тому, что выше написал Dinmaite и дополнительно разыменовать указатель BaseAddress.
Если нет, то попробуйте юзать константу/define или передавать базовый адрес в качестве параметра функции-инжекту.
Ещё можно выделить определённое место в памяти клиента под "служебные данные", такие как GA, BA и т.д., а из инжектов обращаться к этим данным "как к своим".

edyapd
29.07.2013, 10:29
Dinmaite, Спасибо, смысл понял. Теперь бы разобраться как это засунуть в программу в виде указателя на Базовый адрес. Просто последний раз программировал на Паскале, когда Дельфи ещё не было в природе.

BritishColonist, Спасибо. Как константа идёт. Хотя конечно же хотелось бы на будущее запихивать эти значения в ini-файл.

Sorry, для "Спасибо" ещё не набил постов.

Unheilig))
27.09.2013, 19:53
Народ, подскажите, пожалуйста, где я туплю, пытаясь повторить прмер автора статьи?

004778F7 |. A1 6C8BC300 MOV EAX,DWORD PTR DS:[C38B6C]
004778FC |. 52 PUSH EDX
004778FD |. 57 PUSH EDI
004778FE |. 8B48 1C MOV ECX,DWORD PTR DS:[EAX+1C]
00477901 |. 8B41 1C MOV EAX,DWORD PTR DS:[ECX+1C]
00477904 |. 8B48 24 MOV ECX,DWORD PTR DS:[EAX+24]
00477907 |. E8 04342500 CALL elementc.006CAD10




unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;

type
TForm1 = class(TForm)
Button1: TButton;
Edit1: TEdit;
procedure Button1Click(Sender: TObject);
procedure Edit1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

type
PParams = ^TParams;
TParams = packed record
WID: DWord;
end;

var
Form1: TForm1;

implementation

{$R *.dfm}

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; //StdCall - îáÿçàòåëüíî, óêàçûâàåò ÷òî àðãóìåíòû ïîïàäàþò â ñòåê â îáðàòíîì (ñòàíäàðòíîì) ïîðÿäêå
var //
P1: DWord; //
begin //
P1:=aPParams^.WID; //
asm
MOV EDI, P1 // Âíîñèì WID ìîáà â ðåãèñòð EDI
MOV EBX, $006CAD10 // Âíîñèì â ñâîáîäíûé ðåãèñòð àäðåñ ôóíêöèè
MOV EDX, $00000000
MOV EAX,DWORD PTR DS:[$C38B6C] //
PUSH EDX
PUSH EDI // ; /Arg1
MOV ECX,DWORD PTR DS:[EAX+$1C]
MOV EAX,DWORD PTR DS:[ECX+$1C]
MOV ECX,DWORD PTR DS:[EAX+$24] // ; |
CALL EBX // ; \elementc.00606A70
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
aParams: TParams;
PID, hProcess: DWord;
begin
GetWindowThreadProcessId( FindWindow('Perfect World', nil), @PID);
hProcess:= OpenProcess(PROCESS_ALL_ACCESS, False, PID);
aParams.WID:= StrToInt('$' + Edit1.Text); // WID ïåðñîíàæà\ìîáà\NPC
InjectFunc(hProcess, @TargetCall, @aParams, SizeOf(aParams ) ); // èíæåêòèì ôóíêöèþ
CloseHandle( hProcess); // çàêðûâàåì õåíäë ïðîöåññà
end;

procedure TForm1.Edit1Click(Sender: TObject);
begin
Edit1.SelectAll;
end;

end.


Заранее спасибо)

sedrik1992
28.09.2013, 19:34
Unheilig)), у меня вот так работает:
procedure TForm1.Button1Click(Sender: TObject);
var
aParams: TParams;
PID, hProcess: DWord;
kWindow:HWND;
begin
kWindow:=FindWindow(nil,PChar('Perfect World'));
GetWindowThreadProcessId(kWindow, @PID);
hProcess:= OpenProcess(PROCESS_ALL_ACCESS, False, PID);
aParams.WID:= StrToInt('$' + Edit1.Text); // WID персонажа\моба\NPC
InjectFunc(hProcess, @TargetCall, @aParams, SizeOf(aParams ) ); // инжектим функцию
CloseHandle( hProcess); // закрываем хендл процесса
end;

и кусок asm кода:
MOV EDI, P1
MOV EBX, $006E8060
MOV EAX,DWORD PTR DS:[$C38B6C]
PUSH EDI
MOV ECX,DWORD PTR DS:[EAX+$20]
ADD ECX,$0F4
CALL EBX

Ты скорее всего неверно нашел функцию.
Если понадобится, написал мини-утилитку для определения ID Моба/NPC. World ID ([Ссылки могут видеть только зарегистрированные и активированные пользователи])

Unheilig))
29.09.2013, 06:35
так светофорит и все

sedrik1992
29.09.2013, 14:39
так светофорит и все

Если у тебя руофф, возьми переделанный исходник под текущую версию:

Unheilig))
30.09.2013, 05:21
Спасибо, оказалось я просто не ту функцию нашел) похожую, но не ту)

bestbeer
08.07.2014, 15:51
Возник вопрос: возможно ли найти нужный инжект в x64 винде, используя OD и CE?
В CE при любом раскладе получаю адрес 0089DFAC, а дальше тупик
[Ссылки могут видеть только зарегистрированные и активированные пользователи] . Сор если что не так, пробую искать инжекты впервые.

iGesha
08.07.2014, 16:25
89DFAC - это базовый адрес в EXE-шнике. При запуске, в памяти к нему добавляется 0x400000 И получается уже С9DFAC.
А что, собственно, пытался найти?
У меня по алгоритму из первого поста этой темы ничего найти не получается, т.к. игра тупо виснет при попытке отловить все доступы к базовому адресу.
Сейчас пошёл с другого конца - искал всё, что пишет в ячейку текущего таргета в структуре персонажа. Сразу же вышел на искомую функцию взятия в таргет (730FD0)...
И, вроде бы, разрядность винды на поиск никак не влияет. Я и на 64х и на 32х находил что-то. Олькой почти не пользуюсь. Всё, что нужно, пока удаётся сделать через СЕ-шку...

bestbeer
08.07.2014, 17:33
Искал инжект на скил.

sedrik1992
08.07.2014, 21:52
Под эту версию руофа:
~Target~

MOV ESI, P1 // Вносим WID моба в регистр EDI
MOV EBX, $730FD0 // Вносим в свободный регистр адрес функции
MOV EAX,DWORD PTR DS:[$C9DFAC] //
PUSH ESI // ; /Arg1
MOV ECX,DWORD PTR DS:[EAX+$20] // ; |
ADD ECX,$0F4 // ; |
CALL EBX // ; \elementc.00730FD0

bestbeer
27.07.2014, 06:29
Вроде нашел нужную функцию SkillCall:

[Ссылки могут видеть только зарегистрированные и активированные пользователи] ([Ссылки могут видеть только зарегистрированные и активированные пользователи])

Но возникли вопросы насчет последней строки.
CALL DWORD PTR DS:[<&ElementSkill.?IsGoblinSkill@ElementSkill@GNET@@SA_ NI@Z>]
Что это за адрес такой? Как реализовать в дельфиях?

Добавлено через 19 минут
Есть подозрение, что теперь этот адрес зависит от класса персонажа( и берется откуда-то.

bestbeer
01.08.2014, 02:35
Таки сумел разобраться.
Инжект на скил(как будто жмем на панели) под текущий руоф.


CallAddress:=Pointer($0047CBF0);
P1:=aPParams^.Param1;//DWord скил
Po1:=Pointer(P1);//pointer
asm
pushad

MOV ECX,DWORD PTR DS:[$0C9DFAC]
MOV EDX,DWORD PTR DS:[ECX+$1C]
MOV ESI,DWORD PTR DS:[EDX+$30]

push -1 // -1
push 0
push 0

mov ecx,Po1 // указатель на скил
push ecx

mov ecx,esi

CALL CallAddress

popad
end;

scitelz
20.08.2014, 11:44
del

Fess88
17.01.2015, 20:25
Пробую по примеру составить инжект таргета, нашел в Olly следующее ставил брейкпойнт на строке PUSH EDI:

[Ссылки могут видеть только зарегистрированные и активированные пользователи]

0048BD75 A1 ACEFCC00 MOV EAX,DWORD PTR DS:[CCEFAC]
0048BD7A 57 PUSH EDI
0048BD7B 8B48 20 MOV ECX,DWORD PTR DS:[EAX+20]
0048BD7E 81C1 F4000000 ADD ECX,0F4
0048BD84 E8 47AE2B00 CALL elementc.00746BD0

составил инжект:


MOV EDI 0x80108594; // вносим WID моба в регистр EDI (переменная)
MOV EBX, 0x00746bd0
MOV EAX,DWORD PTR DS:[0xCCEFAC]
PUSH EDI
MOV ECX,DWORD PTR DS:[EAX+0x20]
ADD ECX,0F4
CALL EBX
RETN



На основе него сделал сгенерировал код через Olly:
BF 11 11 11 11 BB D0 6B 74 00 A1 22 22 22 22 57 8B 48 20 81 C1 F4 00 00 00 FF D3 C3

сформировал из него массив:
char code[29] = "\xBF\x94\x85\x10\x80\xBB\xD0\x6B\x74\x00\xA1\xAC\x EF\xCC\x00\x57\x8B\x48\x20\x81\xC1\xF4\x00\x00\x00 \xFF\xD3\xC3";

но при попытке инжекта вылетает клиент:(

Подскажите, структура на инжект таргета верная, или косяк не в ней?

diagnost
18.01.2015, 23:11
Выкладываю рабочую версию берет target NPC и открывает диалоговое окно! Как то можно оптимизировать?

var
P1: DWord;
begin
P1:=aPParams^.WID;
asm
MOV EDI, P1 // Вносим WID моба в регистр EDI
MOV EBX, $00746BD0 //Call Targeta
MOV EAX,DWORD PTR DS:[$CCEFAC]
PUSH EDI
MOV ECX,DWORD PTR DS:[EAX+$20]
ADD ECX,$0F4
CALL EBX
MOV EDI, P1
MOV EBX, $00747000 // Call открытия диалога
MOV EAX,DWORD PTR DS:[$CCEFAC]
PUSH EDI
MOV ECX,DWORD PTR DS:[EAX+$20]
ADD ECX,$0F4
CALL EBX
end;
end;

Adrev
20.01.2015, 12:03
Взял код таргета внес его в функцию взятую в соседней теме, в итоге вылет клиента. Вот код:
static DWORD WINAPI SelectMonster(LPCVOID lpParam)
{
DWORD BaseAddress= 0xCCEFAC;
DWORD CallAddress=0xCCF74C;
DWORD MonsterID = (DWORD)2148532360;
__try
{
_asm
{
MOV EDI, MonsterID; // Вносим WID моба в регистр EDI
MOV EBX, 0x00746BD0; //Call Targeta
MOV EAX,DWORD PTR DS:[0xCCEFAC];
PUSH EDI ;
MOV ECX,DWORD PTR DS:[EAX+0x20] ;
ADD ECX,0x0F4;
CALL EBX;
}
}
__except(1)
{
}
return 0;
}
//---------------------------------------------------------------------------
bool CallRemoteFunction(int ProcessId)
{
//Remote Thread Handle
HANDLE hProcess1=NULL;
//Inject Thread handle
HANDLE hThread=NULL;
//Inject Fuction Address after allocate
LPVOID ThreadCodeAddr=NULL;
//Inject Function
LPVOID Func=SelectMonster;
//Inject Fuction Stack Address after allocate
LPVOID ThreadDataAddr=NULL;
//Inject Fuction Stack Data
LPCVOID lpParam = NULL;
DWORD Value = 0;
lpParam = &Value;

hProcess1 = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessId);
if (!hProcess1)
{
//Do your Error message (OpenProcess);
return false;
}
ThreadCodeAddr=VirtualAllocEx(hProcess1, NULL, 4096, MEM_COMMIT, PAGE_READWRITE);
ThreadDataAddr=VirtualAllocEx(hProcess1, NULL, 256, MEM_COMMIT, PAGE_READWRITE);
WriteProcessMemory (hProcess1, ThreadCodeAddr, Func, 4096, NULL);
WriteProcessMemory (hProcess1, ThreadDataAddr, lpParam, 256, NULL);
hThread = CreateRemoteThread(hProcess1, NULL, NULL,(LPTHREAD_START_ROUTINE)ThreadCodeAddr, ThreadDataAddr, NULL, NULL);
if (!hThread)
{
//Do your Error message (CreateRemoteThread);
}
else
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
VirtualFreeEx(hProcess1, ThreadCodeAddr, 4096, MEM_RELEASE);
VirtualFreeEx(hProcess1, ThreadDataAddr, 256, MEM_RELEASE);
CloseHandle(hProcess1);
return false;
}
//---------------------------------------------------------------------------



void __fastcall TForm1::sButton2Click(TObject *Sender)
{
CallRemoteFunction(ProcessId);
}
В чём ошибка?