Регистрация Главная Пользователи Все разделы прочитаны
Сообщения за день Справка Регистрация

Чтож вы такое, Оффсеты?

-

Разработка ПО для Perfect World

- Бюро разработчиков Zhyk.Ru: создание ботов, снифферов и прочих программ для Perfect World

Ответ
 
Опции темы Опции просмотра
Старый 18.10.2020, 05:25   #1
 Пехотинец
Аватар для dwa83
 
dwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личностьdwa83 определенно авторитетная личность
Регистрация: 21.03.2012
Сообщений: 83
Популярность: 1178
Сказал(а) спасибо: 18
Поблагодарили 101 раз(а) в 53 сообщениях
 
По умолчанию Чтож вы такое, Оффсеты?

Очень часто на форуме встречаются посты, из которых видно, что многие не могут понять, что такое офсеты.
И я подумал, если попробовать "разжевать" данную тему, вопросов будет меньше.
Я не профессионал в программировании(просто хобби), потому, если будут недочёты, прошу извинить и поправить.

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

Для работы с динамически созданными экземплярами данных и нужны указатели.

Предлагаю написать простенькую программу, и на примере её разобрать что к чему.
Я буду использовать C++Builder6.

Создадим новый проект и сохраним в отдельную папку. Так же для удобства создадим два файла в папке проекта с названиями structs.h и structs.cpp. В них напишем наши тестовые структуры, которые и будем рассматривать.

Тут тестовая структура Party, содержащая указатель на цепочку добавляемых элементов, описывающих параметры членов пати PartyMember.

structs.h
Код:
#ifndef STRUCTS_H
#define STRUCTS_H

#include <vcl.h>


//структура члена пати
class PartyMember
{
public:
    PartyMember();		//конструктор

	int	level;			//уровень
    int hp;				//жизни
    PartyMember * next;	//указатель на следующего члена пати, или NULL, если последний
};

// структура пати
class Party
{
public:
	Party();					//конструктор
    ~Party();					//деструктор
    void AddRandomMember();		//добавление рандомного члена в пати
    void Clear(PartyMember * m);//очистка
    void DecHP(PartyMember * m);//уменьшение на 1 ХП всех членов пати
    void GetInfo(TListBox * lb);//вывод инфы о всех членах
	int	count;					//количество сопартийцев
    PartyMember * chain;		//указатель(адрес) на первого члена пати, либо NULL, если их нет

};

#endif //STRUCTS_H
structs.cpp
Код:
#include "structs.h"

//конструктор структуры пати
Party::Party()
{
	count = 0;		//в начале ни одного члена нет
    chain = NULL;	//обнулим адрес первого члена
}

//деструктор пати
Party::~Party()
{
	if (chain != NULL) Clear(chain); //удалим цепочку членов, если она не пуста
    count = 0;
}

//добавление члена в конец цепочки
void Party::AddRandomMember()
{
	if (chain == NULL)	//если в пати ещё нет членов
    {
    	//динамически выделим память, chain будет содержать адрес первого
    	chain = new PartyMember(); //тут вызовется конструктор члена пати
        count++;
        return;
    }
    //если это не первый член, "присоединим" его к последнему
	PartyMember * m = chain;
    while (m->next != NULL) m = m->next;
    m->next = new PartyMember();
    count++;
}

//очистка пати
void Party::Clear(PartyMember * m)
{
	//рекурсивно удалим членов
	if (m == NULL) return;
    Clear(m->next);
    delete m;	//освободим память, занятую текущим членом
    m = NULL;	//адрес обнулим, чтоб не указывал на уже свободные адреса
}

//уменьшение ХП всех членов в цепочке
void Party::DecHP(PartyMember * m)
{
	if (m == NULL) return;
	DecHP(m->next);
    if (m->hp > 0) m->hp--;
}

void Party::GetInfo(TListBox * lb)
{
	lb->Clear();
	PartyMember * curent = chain;

    int num = 0;
    while (curent != NULL)
    {
    	lb->Items->Add("№" + IntToStr(num) + " Level - " + IntToStr(curent->level) + " HP - " + IntToStr(curent->hp)+ " ADDR - " + IntToStr(int(curent)));
        curent = curent->next;
		num++;
    }
}

//конструктор члена пати
PartyMember::PartyMember()
{
	level = 10 + 90*(rand()/float(RAND_MAX));
    hp = 1000 + 9000*(rand()/float(RAND_MAX));
    next = NULL;	//адрес следущего члена пока обнулён
}

На форму кинем ListBox, в который будем выводить данные по персонажам. А так же адрес переменной структуры пати.
И одну кнопку, при нажатии на которую у членов пати будут убывать ХП и обновляться информация в листбоксе.
Подключим наш заголовочник в главном модуле, а так же подключим файл реализации к проекту.

Код:
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"

#include "structs.h"



//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;




Party party;
...
Тут же в главном модуле объявим глобальную переменную paty.

В событии создания формы мы должны добавить туда к примеру 3 члена, и вывести инфо о них.
Код:
void __fastcall TForm1::FormCreate(TObject *Sender)
{
	party.AddRandomMember();
    party.AddRandomMember();
    party.AddRandomMember();
    party.GetInfo(ListBox1);
    ListBox1->Items->Add("party ADDR = " + IntToStr(int(&party)));
}
А в событии кнопки вызовем функцию уменьшения хп и опять же обновим инфо в листбоксе.
Код:
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	party.DecHP(party.chain);
    party.GetInfo(ListBox1);
    ListBox1->Items->Add("party ADDR = " + IntToStr(int(&party)));
}
Тестовая программка будет представлять собой примерно такое.


Теперь давайте запустим её, подцепимся к ней с помощью Cheat Engine и с помощью темы https://zhyk.ru/forum/showthread.php?t=116666 попытаемся найти базовый адрес(и не только).
Сначала найдём ХП последнего члена в списке(если не с первого раза нашли, кнопкой уменьшаем ХП и отсеиваем, пока не останется одно значение).

В поле Description лучше сразу писать те значения, которые прибавляются к значениям регистров в окошке MoreInformation

И далее как в вышеуказаной теме ищем адреса, пока не доберёмся до базового адреса(в данном случае базового адреса модуля Project1.exe, который кстати меняется после перезапуска).

Получится примерно такая картина.

В итоге мы добравшись до базового адреса нашли эту самую цепочку офсетов(смещений), которая ведёт до значения ХП третьего члена пати.
BA + 48C4 + 8 + 8 + 4 = HP
Но что это за значения, и откуда они взялись? Давайте разбираться.

Сначала переведём значение адреса party ADDR (последняя строчка листбокса нашей программки) в HEX и получим 004048C0.
А как мы помним, в программе это адрес нашей глобальной переменной Paty.
Но последняя строчка списке адресов Cheat Engine имеет значение 004048C4.
Ага, почти тоже самое, но на 4 больше. Смотрим на структуру нашей Paty и видим, первое поле int count; 4 байта - это значение лежит в начале нашей структуры(на объявления функций не смотрим), то-есть по адресу 004048C0.
А за ней на 4 байта дальше(по адресу 004048C4) находится PartyMember * chain.
Так как наша переменная party - глобальная, её адрес всегда будет один и тот же, и смещение от базового адреса до неё будет одно и то же. Делаем вывод, что + 48C4 - это и есть оффсет(смещение) до структуры party от базового адреса, но не до начала, а до второго её поля. A там лежит адрес структуры первого члена.

Далее по всей логике стройкой выше идёт смещение +8 от начала структуры первого члена. Смотрим в код и видим, что от начала структуры члена пати на 8 байт у нас описано PartyMember * next - указатель на начало структуры следущего члена. То-есть по этим последовательным смещениям мы идём по цепочке адресов членов пати, но последняя строчка со смещением +04. А в структуре на 4 от начала у нас описано int hp;

Вот и всё сошлось, эти офсеты - это смещение до глобальной переменной, потом смещения до адресов динамических структур, которые по цепочке указывают друг на друга, до последнего. То-есть все эти офсеты - это смещения от начала структуры до её определённых полей. Структура элемента от запуска к запуску не меняется(меняются только адреса расположения), соответственно и офсеты(смещения от начала до нужных полей) тоже не меняются.

Чтоб было нагладнее, можно проилюстрировать наш примёр.
________________
╔═╗
ˑ ˑ ╬ ╬
╚═╝

Последний раз редактировалось dwa83; 22.10.2020 в 01:51. Причина: ранее "Делаем вывод, что BA + 48C4 - это и есть оффсет(смещение) до структуры party" - некорректно
  Ответить с цитированием
4 пользователя(ей) сказали cпасибо:
Kavaii^_^ (17.11.2020), qqsda (18.10.2020), ScythLab (18.10.2020), Sirioga (17.11.2020)
Старый 15.11.2020, 13:26   #2
 Пехотинец
Аватар для monahus
 
monahus излучает ауруmonahus излучает ауруmonahus излучает ауруmonahus излучает ауруmonahus излучает ауруmonahus излучает ауру
Регистрация: 17.02.2010
Сообщений: 61
Популярность: 647
Сказал(а) спасибо: 12
Поблагодарили 43 раз(а) в 14 сообщениях
Отправить сообщение для monahus с помощью ICQ Отправить сообщение для monahus с помощью Skype™
 
По умолчанию Re: Чтож вы такое, Оффсеты?

Мне казалось, что я хорошо понимаю что такое офсеты. Но почитав сей пост перестал понимать.
________________
Мои программы живут [Ссылки могут видеть только зарегистрированные пользователи. ]
  Ответить с цитированием
Старый 18.11.2020, 00:40   #3
 Старший сержант
Аватар для ScythLab
 
ScythLab гордость нацииScythLab гордость нацииScythLab гордость нацииScythLab гордость нацииScythLab гордость нацииScythLab гордость нацииScythLab гордость нацииScythLab гордость нацииScythLab гордость нацииScythLab гордость нацииScythLab гордость нации
Регистрация: 24.10.2014
Сообщений: 205
Популярность: 2780
Сказал(а) спасибо: 17
Поблагодарили 22 раз(а) в 16 сообщениях
 
По умолчанию Re: Чтож вы такое, Оффсеты?

Цитата:
Сообщение от monahusПосмотреть сообщение
Но почитав сей пост перестал понимать.

А тема весьма интересная и годная. По крайней мере если ты действительно понимаешь о чем пишет автор, то все понятно , но вот насколько доходчив этот материал для неподготовленных читателей мне тяжело судить
________________
ScythBot: [Ссылки могут видеть только зарегистрированные пользователи. ].
Не забываем кликать "Спасибо", вам бесплатно, а мне приятно
  Ответить с цитированием
Ответ

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход

Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
оффсеты mskarlik Общение и обсуждение Perfect World 0 10.12.2012 22:33
Оффсеты sasha257 Общение и обсуждение Perfect World 1 13.08.2012 21:49
[Помогите!] Оффсеты firuzikh10 Общение разработчиков 1 21.04.2012 18:03

www.webmoney.ru
Заявление об ответственности / Список мошенников

Часовой пояс GMT +4, время: 23:57.

Пишите нам: [email protected]
Copyright © 2020 vBulletin Solutions, Inc.
Translate: zCarot. Webdesign by DevArt (Fox)
G-gaMe! Team production | Since 2008
Hosted by GShost.net