Перейти к содержанию

Рекомендуемые сообщения

Здравствуйте) 

Тренируюсь в написании скриптов, для примера взял 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 программа инъектит код в игру исправно, пробовал простейший код, работает.

Изменено пользователем Trix
Ссылка на комментарий
Поделиться на другие сайты

Привет. А почему не вызов функции через call?

Я в целом писал недавно про спавн машин в GTA Vice City через вызов чит-функции, возможно это поможет: 

 

Ссылка на комментарий
Поделиться на другие сайты

Если честно, то ничего не понятно)

2 часа назад, Trix сказал:

Вот скрипт для CE автоассемблера, работает, не жалуется)

В чем тогда проблема?

 

2 часа назад, Trix сказал:

перенес по битам в свой отдельный код, только вот ничего не вышло, игра вылетела,

Какой еще отдельный код? О чем речь?

Ссылка на комментарий
Поделиться на другие сайты

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();
        }
    }
}
 

Сомневаюсь, что ты поможешь, конечно... 
Вот такой вод, я заинъектил байты в игру и вызвал поток

Ссылка на комментарий
Поделиться на другие сайты

Только что, Trix сказал:

Сомневаюсь, что ты поможешь, конечно... 

;)

У тебя прыжок 0xE9. Память выделяется в произвольном месте. Сечешь о чем я? Тебе надо пересчитывать адрес прыжка относительно адреса, который тебе отдает VirtualAlloc. 

Только что, Trix сказал:

0xEA, 0xE8, 0x84, 0xFD

Я говорю про эти байты. Не забывай так же, что прыжок строится относительно адреса следующей инструкции. Этот занимает 5 байт, значит их и прибавляй.

Ссылка на комментарий
Поделиться на другие сайты

4 минуты назад, uhx сказал:

Я говорю про эти байты. Не забывай так же, что прыжок строится относительно адреса следующей инструкции. Этот занимает 5 байт, значит их и прибавляй.

Можно сейчас немного по-подробнее ?
Разве такое возможно? на сколько я понял, jmp выполняет прыжок к метке, то есть к какому-либо адресу

Игра перезагрузилась, адреса поменялись... я вас немного не понял 

Ссылка на комментарий
Поделиться на другие сайты

Только что, Trix сказал:

Можно сейчас немного по-подробнее ?
Разве такое возможно? на сколько я понял, jmp выполняет прыжок к метке, то есть к какому-либо адресу

Игра перезагрузилась, адреса поменялись... я вас немного не понял 

В Вашем случае используется относительный прыжок ( relative jump, jump near... ), т.е. опкод E9. Т.е. если Вы скажете ему прыгнуть на 0x05, то это значит что он прыгнет на 5 ячеек вперед. Относительно окончания этой инструкции.

Так как память (VirtualAlloc) выделяется в случайном месте, то значит и прыжок надо пересчитывать. Чтоб он прыгал на адрес вашей функции, а не хрен пойми куда.

А вообще используйте в таком случае call, а не jmp... как Вам советовал @srg91

Или используйте jump far, раз Вам так нравятся прыжки. Погуглите, а то времени мне не хватит с телефона все напечатать

Изменено пользователем uhx
Ссылка на комментарий
Поделиться на другие сайты

Напрмер, если Вы сделаете прыжок на 00 00 00 00, то он попадет на Ваш же ret (C3), который находится прямо после прыжка. Если зададите прыжок на -5, то поток зациклится на этом же прыжке) В этом весь jump near. В jump far же абсолютная адресация, но он и больше. Вроде 6 байт, не помню.

Ссылка на комментарий
Поделиться на другие сайты

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 
};

Так ли это делается? 

Ссылка на комментарий
Поделиться на другие сайты

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. 

Изменено пользователем srg91
  • Плюс 1
Ссылка на комментарий
Поделиться на другие сайты

Только что, srg91 сказал:

gta-vc.exe, после к этому числу прибавить 0xAE8F0 и получившееся число записывать после call (0xE8 XX XX XX XX).

Хрень в том что 0xE8 принимает тоже относительный адрес (call near), как и 0xE9. Который он хардкодит) А относительный адрес надо выстраивать относительно адреса инструкции, с которой происходит прыжок. 

Ссылка на комментарий
Поделиться на другие сайты

8 minutes ago, uhx said:

Хрень в том что

 

Благодарю, посмотрел внимательнее, действительно :) Похоже тут нужен 9A, подправил сообщение выше.

Либо да, вычислять относительно :)

Ссылка на комментарий
Поделиться на другие сайты

В 03.05.2017 в 10:15, Trix сказал:

0x004AE8F0

relativeAddress = function_address - ( hAlloc + 10 )

Почему 10? Потому что там заканчивается инструкция прыжка. И оттуда мы должны считать его. Посчитали? Теперь записывай relativeAddress вместо твоего адреса прыжка. Т.е. после 0xE8

Ссылка на комментарий
Поделиться на другие сайты

Только что, srg91 сказал:

 

Благодарю, посмотрел внимательнее, действительно :) Похоже тут нужен 9A, подправил сообщение выше.

Либо да, вычислять относительно :)

Та я блин тоже сначала проглядел. Пришлось стирать то, что настрочил. На счет дальних переходов я не знаю. Я справочники по асму читать не умею)) Но насколько я понял, для дальнего перехода нужно использовать FF. Ибо 9A требует адрес в операнде)

Ссылка на комментарий
Поделиться на другие сайты

6 minutes ago, uhx said:

Ибо 9A требует адрес в операнде

 

ну ptr же, точно :D еще раз поправил. моя тоже не уметь читать справочники, судя по всему ))

Изменено пользователем srg91
Ссылка на комментарий
Поделиться на другие сайты

×
×
  • Создать...

Важная информация

Находясь на нашем сайте, Вы автоматически соглашаетесь соблюдать наши Условия использования.