Trix Опубликовано 3 мая, 2017 Поделиться Опубликовано 3 мая, 2017 (изменено) Здравствуйте) Тренируюсь в написании скриптов, для примера взял gta vice city, ибо адреса функций уже даны(нашел на сайте с материалами для моддинга) Записал вот такой скрипт(думаю, как-то криво, но работает. Другого решения не нашел, если подскажете, буду оч рад) Скрытый текст [ENABLE] alloc(code, 4048) createthread(code) code: push ebx push esi push edi mov ecx,gta-vc.exe+54B220 sub esp,20 mov esi,000000A2 jmp gta-vc.exe+AE8FF ret [DISABLE] dealloc(code) Вот скрипт для CE автоассемблера, работает, не жалуется) функция чит-вызова транспорта расположен по адресу 0x004AE8F0 А номер транспорта (000000A2) = 162(танк) помещается в регистр ESI В целом, у меня все сработало, перенес по битам в свой отдельный код, только вот ничего не вышло, игра вылетела, в чем заключается подвох и как можно оптимизировать код? PS программа инъектит код в игру исправно, пробовал простейший код, работает. Изменено 3 мая, 2017 пользователем Trix Ссылка на комментарий Поделиться на другие сайты Поделиться
srg91 Опубликовано 3 мая, 2017 Поделиться Опубликовано 3 мая, 2017 Привет. А почему не вызов функции через call? Я в целом писал недавно про спавн машин в GTA Vice City через вызов чит-функции, возможно это поможет: Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 3 мая, 2017 Поделиться Опубликовано 3 мая, 2017 Если честно, то ничего не понятно) 2 часа назад, Trix сказал: Вот скрипт для CE автоассемблера, работает, не жалуется) В чем тогда проблема? 2 часа назад, Trix сказал: перенес по битам в свой отдельный код, только вот ничего не вышло, игра вылетела, Какой еще отдельный код? О чем речь? Ссылка на комментарий Поделиться на другие сайты Поделиться
Trix Опубликовано 4 мая, 2017 Автор Поделиться Опубликовано 4 мая, 2017 22 часа назад, uhx сказал: Если честно, то ничего не понятно) В чем тогда проблема? Какой еще отдельный код? О чем речь? кхх... Скрытый текст using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Windows; using System.Text; using System.Threading; namespace RemoteThread { class Program { [DllImport("kernel32.dll")] public static extern IntPtr OpenProcess(ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, int dwProcessId); [DllImport("kernel32.dll")] public static extern bool CloseHandle(IntPtr hObject); [DllImport("kernel32.dll")] public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, uint nSize, out UIntPtr lpNumberOfBytesWritten); [DllImport("kernel32.dll")] public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, uint dwSize, AllocationType flAllocationType, MemoryProtection flProtect); [DllImport("kernel32.dll")] public static extern IntPtr CreateRemoteThread(IntPtr hProcess, IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, out uint lpThreadId); internal class Win32 { // Use DllImportAttribute to inport the Win32 MessageBox // function. Set the SetLastError flag to true to allow // the function to set the Win32 error. [DllImportAttribute("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern int MessageBox(IntPtr hwnd, String text, String caption, uint type); } //[DllImportAttribute("user32.dll", SetLastError = true, CharSet = CharSet.Unicode)] //public static extern int MessageBox(IntPtr hwnd, String text, String caption, uint type); [Flags] public enum ProcessAccessFlags : uint { Terminate = 0x00000001, CreateThread = 0x00000002, VMOperation = 0x00000008, VMRead = 0x00000010, VMWrite = 0x00000020, DupHandle = 0x00000040, SetInformation = 0x00000200, QueryInformation = 0x00000400, Synchronize = 0x00100000, All = 0x001F0FFF } [Flags] public enum AllocationType { Commit = 0x00001000, Reserve = 0x00002000, Decommit = 0x00004000, Release = 0x00008000, Reset = 0x00080000, TopDown = 0x00100000, WriteWatch = 0x00200000, Physical = 0x00400000, LargePages = 0x20000000 } [Flags] public enum MemoryProtection { NoAccess = 0x0001, ReadOnly = 0x0002, ReadWrite = 0x0004, WriteCopy = 0x0008, Execute = 0x0010, ExecuteRead = 0x0020, ExecuteReadWrite = 0x0040, ExecuteWriteCopy = 0x0080, GuardModifierflag = 0x0100, NoCacheModifierflag = 0x0200, WriteCombineModifierflag = 0x0400 } public delegate int ThreadProc(IntPtr param); static void Main(string[] args) { byte[] asm = new byte[] { 0x53, 0x56, 0x57, 0xB9, 0x20, 0xB2, 0x94, 0x00, 0x83, 0xEC, 0x20, 0xBE, 0xA2, 0x00, 0x00, 0x00, 0xE9, 0xEA, 0xE8, 0x84, 0xFD, 0xC3 }; int iProcessId = 2096; IntPtr hHandle = OpenProcess(ProcessAccessFlags.All, false, iProcessId); if (hHandle == IntPtr.Zero) throw new ApplicationException("Cannot get process handle."); IntPtr hAlloc = VirtualAllocEx(hHandle, IntPtr.Zero, (uint)asm.Length, AllocationType.Commit, MemoryProtection.ExecuteReadWrite); if (hAlloc == IntPtr.Zero) throw new ApplicationException("Cannot allocate memory."); UIntPtr bytesWritten = UIntPtr.Zero; if (!WriteProcessMemory(hHandle, hAlloc, asm, (uint)asm.Length, out bytesWritten)) throw new ApplicationException("Cannot write process memory."); if (asm.Length != (int)bytesWritten) throw new ApplicationException("Invalid written size."); uint iThreadId = 0; IntPtr hThread = CreateRemoteThread(hHandle, IntPtr.Zero, 0, hAlloc, IntPtr.Zero, 0, out iThreadId); //Console.WriteLine("___"); //int error = Marshal.GetLastWin32Error(); // Console.WriteLine(error.ToString()); if (hThread == IntPtr.Zero) throw new ApplicationException("Cannot create and execute remote thread."); CloseHandle(hThread); CloseHandle(hHandle); Console.ReadKey(); } } } Сомневаюсь, что ты поможешь, конечно... Вот такой вод, я заинъектил байты в игру и вызвал поток Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 Только что, Trix сказал: Сомневаюсь, что ты поможешь, конечно... У тебя прыжок 0xE9. Память выделяется в произвольном месте. Сечешь о чем я? Тебе надо пересчитывать адрес прыжка относительно адреса, который тебе отдает VirtualAlloc. Только что, Trix сказал: 0xEA, 0xE8, 0x84, 0xFD Я говорю про эти байты. Не забывай так же, что прыжок строится относительно адреса следующей инструкции. Этот занимает 5 байт, значит их и прибавляй. Ссылка на комментарий Поделиться на другие сайты Поделиться
Trix Опубликовано 4 мая, 2017 Автор Поделиться Опубликовано 4 мая, 2017 4 минуты назад, uhx сказал: Я говорю про эти байты. Не забывай так же, что прыжок строится относительно адреса следующей инструкции. Этот занимает 5 байт, значит их и прибавляй. Можно сейчас немного по-подробнее ? Разве такое возможно? на сколько я понял, jmp выполняет прыжок к метке, то есть к какому-либо адресу Игра перезагрузилась, адреса поменялись... я вас немного не понял Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 (изменено) Только что, Trix сказал: Можно сейчас немного по-подробнее ? Разве такое возможно? на сколько я понял, jmp выполняет прыжок к метке, то есть к какому-либо адресу Игра перезагрузилась, адреса поменялись... я вас немного не понял В Вашем случае используется относительный прыжок ( relative jump, jump near... ), т.е. опкод E9. Т.е. если Вы скажете ему прыгнуть на 0x05, то это значит что он прыгнет на 5 ячеек вперед. Относительно окончания этой инструкции. Так как память (VirtualAlloc) выделяется в случайном месте, то значит и прыжок надо пересчитывать. Чтоб он прыгал на адрес вашей функции, а не хрен пойми куда. А вообще используйте в таком случае call, а не jmp... как Вам советовал @srg91 Или используйте jump far, раз Вам так нравятся прыжки. Погуглите, а то времени мне не хватит с телефона все напечатать Изменено 4 мая, 2017 пользователем uhx Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 Напрмер, если Вы сделаете прыжок на 00 00 00 00, то он попадет на Ваш же ret (C3), который находится прямо после прыжка. Если зададите прыжок на -5, то поток зациклится на этом же прыжке) В этом весь jump near. В jump far же абсолютная адресация, но он и больше. Вроде 6 байт, не помню. Ссылка на комментарий Поделиться на другие сайты Поделиться
Trix Опубликовано 4 мая, 2017 Автор Поделиться Опубликовано 4 мая, 2017 2 часа назад, uhx сказал: Напрмер, если Вы сделаете прыжок на 00 00 00 00, то он попадет на Ваш же ret (C3), который находится прямо после прыжка. Если зададите прыжок на -5, то поток зациклится на этом же прыжке) В этом весь jump near. В jump far же абсолютная адресация, но он и больше. Вроде 6 байт, не помню. окей, я дошел вот до такой конструкции, однако, все равно код терпит неудачу Скрытый текст byte[] asm = new byte[] { 0x68, 0xB1, 0x00, 0x00, 0x00 , // - push 000000B1 { 177 } 0xE8, 0xE6, 0xE8, 0x5D, 0xFF, // - call gta-vc.exe+AE8F0 0x59, // - pop ecx 0xC3 // - ret }; Так ли это делается? Ссылка на комментарий Поделиться на другие сайты Поделиться
srg91 Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 (изменено) 1 hour ago, Trix said: ли это делается? Мне кажется, что слегка не так. Возможно тут лучше подскажет @uhx. У тебя точно функция находится по адресу 0xff5de8e6? Я предполагаю, что тебе нужно через какой-нибудь EnumProcessModules (никогда не писал такого, поэтому просто предполагаю) найти адрес модуля gta-vc.exe, после к этому числу прибавить 0xAE8F0 и получившееся число записывать после call (0xFF XX XX XX XX). Либо найдя точно местоположение функции (только если ты делаешь для себя и тебе хочется удостовериться в результате) через CE найти правильный адрес (будет что-то типа 0x12345678 и записать его как ты и делаешь - 0xFF 0x78 0x56 0x34 0x12. Изменено 4 мая, 2017 пользователем srg91 1 Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 (изменено) del//// Изменено 4 мая, 2017 пользователем uhx Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 Только что, srg91 сказал: gta-vc.exe, после к этому числу прибавить 0xAE8F0 и получившееся число записывать после call (0xE8 XX XX XX XX). Хрень в том что 0xE8 принимает тоже относительный адрес (call near), как и 0xE9. Который он хардкодит) А относительный адрес надо выстраивать относительно адреса инструкции, с которой происходит прыжок. Ссылка на комментарий Поделиться на другие сайты Поделиться
srg91 Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 8 minutes ago, uhx said: Хрень в том что Благодарю, посмотрел внимательнее, действительно Похоже тут нужен 9A, подправил сообщение выше. Либо да, вычислять относительно Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 В 03.05.2017 в 10:15, Trix сказал: 0x004AE8F0 relativeAddress = function_address - ( hAlloc + 10 ) Почему 10? Потому что там заканчивается инструкция прыжка. И оттуда мы должны считать его. Посчитали? Теперь записывай relativeAddress вместо твоего адреса прыжка. Т.е. после 0xE8 Ссылка на комментарий Поделиться на другие сайты Поделиться
uhx Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 Только что, srg91 сказал: Благодарю, посмотрел внимательнее, действительно Похоже тут нужен 9A, подправил сообщение выше. Либо да, вычислять относительно Та я блин тоже сначала проглядел. Пришлось стирать то, что настрочил. На счет дальних переходов я не знаю. Я справочники по асму читать не умею)) Но насколько я понял, для дальнего перехода нужно использовать FF. Ибо 9A требует адрес в операнде) Ссылка на комментарий Поделиться на другие сайты Поделиться
srg91 Опубликовано 4 мая, 2017 Поделиться Опубликовано 4 мая, 2017 (изменено) 6 minutes ago, uhx said: Ибо 9A требует адрес в операнде ну ptr же, точно еще раз поправил. моя тоже не уметь читать справочники, судя по всему )) Изменено 4 мая, 2017 пользователем srg91 Ссылка на комментарий Поделиться на другие сайты Поделиться
Рекомендуемые сообщения