20120524

Пилим дальше трейнер на C# - учимся работать с указателями.

Ребята, я написал немного кода, но он такой небольшой, что на видеоурок явно не тянет - ну не знаю я, о чём там рассказывать вслух, поэтому напишу здесь.

Задача у нас такая - есть указатель вида 0x12345+0x1+0x5+0x7, надо суметь его прочитать. Что такое указатель - все помнят? Смотрите:

0x12345 - по этому адресу будет лежать другой адрес (это ведь указатель!). Допустим, 0xA.
Прибавляем к результату первое смещение, получаем 0xA+0x1. Читаем получившийся адрес:

[0xA+0x1] = второй адрес, скажем, 0xB

[0xB+0x2 (второе смещение)] = 0xC.

...
...

[0xD+0x7] = 123 - нужное нам значение, на которое указатель и указывает. Вот код:


public int ReadBytes()
        {          
            if (pID != 0) //Проверяем, что игра найдена
            {
                var dwAddress = 0x55D804; //Базовый адрес указателя
                byte[] buffer = new byte[4]; //Буфер, массив из четырёх байт, куда будут читаться значения
                int bytesread; //Переменная-заглушка, хранящая количество прочитанных байт
                var handle = OpenProcess(0x001F0FFF, false, pID); //Получаем хэндл процесса игры
                ReadProcessMemory(handle, (IntPtr)dwAddress, buffer, 4, out bytesread); //Читаем значение базового адреса
                var result = BitConverter.ToInt32(buffer, 0); //Конвертируем массив байт в циферки
                result += 0x70; //Прибавляем первое смещение
                ReadProcessMemory(handle, (IntPtr)result, buffer, 4, out bytesread); //Читаем получившийся адрес
                var temp = BitConverter.ToSingle(buffer, 0); //Конвертируем результат во float
                CloseHandle(handle); //Закрываем хэндл игры
                return temp; //Возвращаем результат
            }
            return -1; //Если не нашли игру - возвращаем -1.
        }

Тут у нас указатель такой - 0x55D804 + 0x70 = Значение, причём это float. Читаем значение базового адреса, конвертируем из массива байт в цифры, прибавляем смещение, читаем получившийся адрес, конвертируем во float - вуаля! Всё просто. Но код можно улучшить, если у нас много смещений. Смотрите:

//В аргументах присылаем базовый адрес указателя + массив смещений
public int ReadBytes(int baseAddress, byte[] offsets)
        {          
            if (pID != 0 && baseAddress != 0 && offsets.Length != 0) //Проверяем, что всё на месте
            {              
                byte[] buffer = new byte[4]; //Буфер для чтения
                int bytesread; //Заглушка
                var handle = OpenProcess(0x001F0FFF, false, pID); //Получаем хэндл
                ReadProcessMemory(handle, (IntPtr)baseAddress, buffer, 4, out bytesread); //Читаем базовый адрес
                for (var i = 0; i < offsets.Length; i++) //Бежим в цикле, пока не кончатся смещения
                {
                    baseAddress = BitConverter.ToInt32(buffer, 0); //Конвертируем результат в циферки
                    baseAddress += offsets[i]; //Прибавляем смещение
                    ReadProcessMemory(handle, (IntPtr)baseAddress, buffer, 4, out bytesread); //Читаем
                }
//Как только смещения в массиве закончились
CloseHandle(handle); //Закрываем хэндл
                var result = BitConverter.ToSingle(buffer, 0); //Конвертируем результат во float               
                return result; //Возвращаем результат
            }
            return -1; //Иначе - ошибка
        }



В принципе, всё довольно просто, если не понимаете - почитайте что-нибудь про циклы, там всё понятно. Вызывать эту функцию нужно вот так:


var address = 0x55D804; //Базовый адрес
var offsets = new byte[] {0x70}; //Массив со смещениями
var myFloat = ReadBytes(address, offsets); //Читаем!





Комментариев нет:

Отправить комментарий

Не люблю мат и низкий уровень грамотности. Чем конкретнее поставите свой вопрос и чем лучше он будет выглядеть - тем большая вероятность на мой ответ. :)