- PVSM.RU - https://www.pvsm.ru -
Привет, %username%! Итак, продолжим написание нашего бота. Сегодня мы внедрим наш код в игровой процесс (не без помощи ассемблера), а позже позаботимся и о том, что бы его было не так просто найти, ведь наказывают не за то что жульничаешь, а за то что попался. И если быть до конца честным то даже не совсем в сам процесс игры будем его внедрять, да и 1 раз только за весь жизненный цикл.
Disclaimer: Автор не несет ответственности за применение вами знаний полученных в данной статье или ущерб в результате их использования. Вся информация здесь изложена только в познавательных целях. Особенно для компаний разрабатывающих MMORPG, что бы помочь им бороться с ботоводами. И, естественно, автор статьи не ботовод, не читер и никогда ими не был.
Сегодня мы внедрим наш код в эту функцию без ущерба для нее самой. Ниже я покажу как это будет происходить:
Что бы открыть процесс мы вызовем WinApi OpenProcess и разрешим отладку, а затем нам необходимо открыть главный поток, нашего процесса
var ProcessHandle = OpenProcess(processId);
Process.EnterDebugMode();
var dwThreadId = Process.GetProcessById(dwProcessId).Threads[0].Id;
var ThreadHandle = OpenThread(0x1F03FF, false, (uint)dwThreadId);
var HookAddress = Memory.AllocateMemory(6000);
var argumentAddress1 = Memory.AllocateMemory(80);
Memory.WriteBytes(argumentAddress1, new byte[80]);
var argumentAddress2 = Memory.AllocateMemory(BufferSize);
Memory.WriteBytes(argumentAddress2, new byte[80]);
var resultAddress = Memory.AllocateMemory(4);
Memory.Write<int>(_resultAddress, 0);
где 0x1F03FF — права доступа к потоку. Далее мы выделяем память под наш код и получаем на нее указатель HookAddress, так же резервируем память для двух аргументов argumentAddress1 и argumentAddress2, для результата resultAddress и заполняем все нулями. Теперь как и обещал немножко хардкора:
var asmLine = new List<string> {
"pushfd",
"pushad",
"mov edx, 0",
"mov ecx, " + resultAddress,
"mov [ecx], edx",
"@loop:",
"mov eax, [ecx]",
"cmp eax, " + 80,
"jae @end",
"mov eax, " + argumentAddress1,
"add eax, [ecx]",
"mov eax, [eax]",
"test eax, eax",
"je @out",
"call eax",
"mov ecx, " + resultAddress,
"mov edx, " + argumentAddress2,
"add edx, [ecx]",
"mov [edx], eax",
"mov edx, " + argumentAddress1,
"add edx, [ecx]",
"mov eax, 0",
"mov [edx], eax",
"@out:",
"mov eax, [ecx]",
"add eax, 4",
"mov [ecx], eax",
"jmp @loop",
"@end:",
"popad",
"popfd"
};
Memory.Asm = new ManagedFasm(ProcessHandle);
Memory.Asm.Clear();
foreach (var str in asmLine)
{
Memory.Asm.AddLine(str);
}
Memory.Asm.Inject(HookAddress);
var length = (uint) Memory.Asm.Assemble().Length;
Memory.WriteBytes(HookAddress + length, OpCodes);
Memory.Asm.Clear();
Memory.Asm.AddLine("jmp " + (Address + OpCodes.Length));
Memory.Asm.Inject((uint)((HookAddress + length) + OpCodes.Length));
Memory.Asm.Clear();
Memory.Asm.AddLine("jmp " + HookAddress);
for (var k = 0; k <= ((OpCodes.Length - 5) - 1); k++)
{
Memory.Asm.AddLine("nop");
}
Memory.Asm.Inject(Address);
Ассемблерный код выше, записывается в HookAddress и будет передавать управление нашему коду и согласно таблице, после его отработки мы возвращаем управление в главный поток. Теперь я покажу как этим воспользоваться, пусть имеем:
public byte[] InjectAndExecute(IEnumerable<string> asm, bool returnValue = false, int returnLength = 0)
{
Memory.Asm.Clear();
foreach (var str in asm)
{
Memory.Asm.AddLine(str);
}
dwAddress = Memory.AllocateMemory(Memory.Asm.Assemble().Length + 60);
Memory.Asm.Inject(dwAddress);
Memory.Write<uint>(argumentAddress1, dwAddress);
while (Memory.Read<int>(argumentAddress1) > 0)
{
Thread.Sleep(1);
}
byte[] result = new byte[0];
if (returnValue)
{
result = Memory.ReadBytes(Memory.Read<uint>(argumentAddress2), returnLength);
}
Memory.Write<int>(argumentAddress2, 0);
Memory.FreeMemory(dwAddress);
return result;
}
В итоге у нас значения по адресам argumentAddress1 и argumentAddress2 должны стать нулями когда наша инъекция отработает. Если у вас много потоков которые вызывают InjectAndExecute, то нужно предусмотреть очередь, для этого я и использовал 80 байт размер, как его реализовать, подумайте сами. А в следующей статье, я покажу свою реализацию и как прятать наш код.
Автор: 3axap4eHko
Источник [2]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/programmirovanie/83705
Ссылки в тексте:
[1] Часть 0 — Поиск точки внедрения кода: http://habrahabr.ru/post/251137/
[2] Часть 1 — Внедрение и исполнение стороннего кода: http://habrahabr.ru/post/251149/
Нажмите здесь для печати.