Что нового
  • Что бы вступить в ряды "Принятый кодер" Вам нужно:
    Написать 10 полезных сообщений или тем и Получить 10 симпатий.
    Для того кто не хочет терять время,может пожертвовать средства для поддержки сервеса, и вступить в ряды VIP на месяц, дополнительная информация в лс.

  • Пользаватели которые будут спамить, уходят в бан без предупреждения. Спам сообщения определяется администрацией и модератором.

  • Гость, Что бы Вы хотели увидеть на нашем Форуме? Изложить свои идеи и пожелания по улучшению форума Вы можете поделиться с нами здесь. ----> Перейдите сюда
  • Все пользователи не прошедшие проверку электронной почты будут заблокированы. Все вопросы с разблокировкой обращайтесь по адресу электронной почте : info@guardianelinks.com . Не пришло сообщение о проверке или о сбросе также сообщите нам.

Lineage II Чтение и нахождение, манипуляция значения здоровья персонажа в Lineage 2 с использованием Delphi

Lomanu4

Команда форума
Администратор
Регистрация
1 Мар 2015
Сообщения
1,406
Баллы
155
Шаг 1: Найти значение здоровья в памяти

Первым шагом является нахождение адреса, где хранится значение здоровья персонажа. Для этого можно использовать инструменты для поиска памяти, такие как Cheat Engine.

  1. Запустите Lineage 2 и Cheat Engine.
  2. Подключитесь к процессу Lineage 2 в Cheat Engine.
  3. Ищите текущее значение здоровья. Например, если здоровье вашего персонажа 500, ищите это значение.
  4. Измените значение здоровья в игре (получите урон или восстановите здоровье) и снова найдите новое значение.
  5. Повторяйте процесс, пока не найдете конкретный адрес памяти, где хранится значение здоровья.

Шаг 2: Использование Delphi для чтения значения здоровья

Теперь, когда вы знаете адрес памяти, где хранится значение здоровья, можно написать программу на Delphi для чтения этого значения.

Пример кода для чтения значения здоровья из памяти процесса Lineage 2:
Код:
uses
  Windows, SysUtils, Classes;

function ReadHealth(ProcessID: DWORD; HealthAddress: Pointer): Integer;
var
  hProcess: THandle;
  HealthValue: Integer;
  BytesRead: SIZE_T;
begin
  hProcess := OpenProcess(PROCESS_VM_READ or PROCESS_QUERY_INFORMATION, False, ProcessID);
  if hProcess <> 0 then
  begin
    if not ReadProcessMemory(hProcess, HealthAddress, @HealthValue, SizeOf(HealthValue), BytesRead) then
      RaiseLastOSError;
    CloseHandle(hProcess);
  end
  else
    RaiseLastOSError;
  Result := HealthValue;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ProcessID: DWORD;
  HealthAddress: Pointer;
  Health: Integer;
begin
  // Укажите идентификатор процесса Lineage 2 и адрес памяти значения здоровья
  ProcessID := 1234; // Замените на фактический идентификатор процесса Lineage 2
  HealthAddress := Pointer($12345678); // Замените на фактический адрес памяти значения здоровья

  Health := ReadHealth(ProcessID, HealthAddress);
  ShowMessage('Текущее значение здоровья: ' + IntToStr(Health));
end;
Скажите Вы! А если память изменяется динамически то что делать?
Если адрес динамический и постоянно меняется, то необходимо использовать более продвинутые техники, такие как "pointer scanning" и "signature scanning". Эти методы позволяют находить адреса в памяти, даже если они изменяются при каждом запуске игры.

Pointer Scanning
Pointer scanning — это метод, который позволяет найти цепочки указателей, ведущих к нужному значению. Для этого можно использовать такие инструменты, как Cheat Engine.

  1. Откройте Cheat Engine и подключитесь к процессу игры.
  2. Найдите значение здоровья и его адрес.
  3. Используйте функцию "Pointer Scan" в Cheat Engine, чтобы найти цепочки указателей, которые ведут к этому адресу.
  4. Сохраните цепочки указателей для использования в вашем коде на Delphi.
Signature Scanning
Signature scanning — это метод, который использует сигнатуры (шаблоны байтов) для поиска нужного значения в памяти. Этот метод полезен, когда значение находится по динамическому адресу, но само значение или его окружение остается неизменным.

Пример кода для использования Signature Scanning в Delphi:
Код:
uses
  Windows, SysUtils;

function FindPattern(ProcessID: DWORD; Pattern: string; Mask: string): Pointer;
var
  hProcess: THandle;
  mbi: MEMORY_BASIC_INFORMATION;
  baseAddress, endAddress: Pointer;
  buffer: array of Byte;
  bytesRead: SIZE_T;
  i, j: Integer;
  found: Boolean;
begin
  Result := nil;
  hProcess := OpenProcess(PROCESS_VM_READ or PROCESS_QUERY_INFORMATION, False, ProcessID);
  if hProcess <> 0 then
  begin
    baseAddress := nil;
    endAddress := Pointer($7FFFFFFF);
    while Cardinal(baseAddress) < Cardinal(endAddress) do
    begin
      if VirtualQueryEx(hProcess, baseAddress, mbi, SizeOf(mbi)) = SizeOf(mbi) then
      begin
        if (mbi.State = MEM_COMMIT) and (mbi.Protect = PAGE_READWRITE) then
        begin
          SetLength(buffer, mbi.RegionSize);
          if ReadProcessMemory(hProcess, mbi.BaseAddress, @buffer[0], mbi.RegionSize, bytesRead) then
          begin
            for i := 0 to mbi.RegionSize - Length(Pattern) do
            begin
              found := True;
              for j := 0 to Length(Pattern) - 1 do
              begin
                if (Mask[j] = 'x') and (Pattern[j] <> Char(buffer[i + j])) then
                begin
                  found := False;
                  Break;
                end;
              end;
              if found then
              begin
                Result := Pointer(Cardinal(mbi.BaseAddress) + i);
                Break;
              end;
            end;
          end;
        end;
        baseAddress := Pointer(Cardinal(mbi.BaseAddress) + mbi.RegionSize);
      end;
    end;
    CloseHandle(hProcess);
  end
  else
    RaiseLastOSError;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  ProcessID: DWORD;
  HealthAddress: Pointer;
begin
  // Укажите идентификатор процесса игры
  ProcessID := 1234; // Замените на фактический идентификатор процесса игры

  // Ищем паттерн байтов для здоровья
  HealthAddress := FindPattern(ProcessID, 'FF FF FF FF', 'xxxx');
  if HealthAddress <> nil then
    ShowMessage('Адрес здоровья: ' + IntToHex(Cardinal(HealthAddress), 8))
  else
    ShowMessage('Адрес здоровья не найден');
end;
Объяснение
  1. Pointer Scanning:
    • Используйте Cheat Engine для поиска цепочек указателей.
    • Сохраните цепочки указателей и используйте их в коде для нахождения динамических адресов.
  2. Signature Scanning:
    • Найдите сигнатуру (шаблон байтов) для нужного значения.
    • Используйте код на Delphi для поиска этого шаблона в памяти процесса.
Эти методы помогут вам найти и читать значения здоровья персонажа в игре, даже если адреса динамически меняются.

Пример кода, показывающий, как следовать цепочке указателей для получения адреса здоровья.
Код:
uses
  Windows, SysUtils, TlHelp32;

function GetHealthPointer(BaseAddress: Pointer; Offsets: array of Cardinal): Pointer;
var
  hProcess: THandle;
  Address: Pointer;
  BytesRead: SIZE_T;
  i: Integer;
begin
  hProcess := OpenProcess(PROCESS_VM_READ or PROCESS_QUERY_INFORMATION, False, GetCurrentProcessId);
  if hProcess = 0 then RaiseLastOSError;
  try
    Address := BaseAddress;
    for i := 0 to High(Offsets) do
    begin
      if not ReadProcessMemory(hProcess, Address, @Address, SizeOf(Address), BytesRead) then RaiseLastOSError;
      Address := Pointer(Cardinal(Address) + Offsets[i]);
    end;
  finally
    CloseHandle(hProcess);
  end;
  Result := Address;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  HealthAddress: Pointer;
  Health: Integer;
begin
  HealthAddress := GetHealthPointer(Pointer($12345678), [$4, $8, $C]);
  Health := ReadHealth(GetCurrentProcessId, HealthAddress);
  ShowMessage('Текущее значение здоровья: ' + IntToStr(Health));
end;
  1. Использование подписей для поиска значения здоровья

Код:
function FindSignature(ProcessID: DWORD; Pattern: array of Byte; Mask: string): Pointer;
var
  hProcess: THandle;
  mbi: MEMORY_BASIC_INFORMATION;
  BaseAddress, EndAddress: Pointer;
  Buffer: array of Byte;
  BytesRead: SIZE_T;
  i, j: Integer;
  Found: Boolean;
begin
  Result := nil;
  hProcess := OpenProcess(PROCESS_VM_READ or PROCESS_QUERY_INFORMATION, False, ProcessID);
  if hProcess <> 0 then
  begin
    BaseAddress := nil;
    EndAddress := Pointer($7FFFFFFF);
    while Cardinal(BaseAddress) < Cardinal(EndAddress) do
    begin
      if VirtualQueryEx(hProcess, BaseAddress, mbi, SizeOf(mbi)) = SizeOf(mbi) then
      begin
        if (mbi.State = MEM_COMMIT) and (mbi.Protect = PAGE_READWRITE) then
        begin
          SetLength(Buffer, mbi.RegionSize);
          if ReadProcessMemory(hProcess, mbi.BaseAddress, @Buffer[0], mbi.RegionSize, BytesRead) then
          begin
            for i := 0 to mbi.RegionSize - Length(Pattern) do
            begin
              Found := True;
              for j := 0 to Length(Pattern) - 1 do
              begin
                if (Mask[j] = 'x') and (Pattern[j] <> Buffer[i + j]) then
                begin
                  Found := False;
                  Break;
                end;
              end;
              if Found then
              begin
                Result := Pointer(Cardinal(mbi.BaseAddress) + i);
                Exit;
              end;
            end;
          end;
        end;
        BaseAddress := Pointer(Cardinal(mbi.BaseAddress) + mbi.RegionSize);
      end;
    end;
    CloseHandle(hProcess);
  end
  else
    RaiseLastOSError;
end;
Внутри считанного блока памяти происходит поиск заданного шаблона байтов Pattern с использованием маски Mask. Маска указывает, какие байты должны точно совпадать ('x') и какие можно пропустить ('-'). Если шаблон найден, функция возвращает адрес начала шаблона в памяти.

Манипуляция значением здоровья и нажатием клавиш
Код:
uses
  Windows, SysUtils, TlHelp32;

function GetHealthPointer(BaseAddress: Pointer; Offsets: array of Cardinal): Pointer;
// ... (код функции из предыдущих примеров)

function ReadHealth(ProcessID: DWORD; HealthAddress: Pointer): Integer;
// ... (код функции из предыдущих примеров)

function WriteHealth(ProcessID: DWORD; HealthAddress: Pointer; HealthValue: Integer): Boolean;
// ... (код функции из предыдущих примеров)

procedure SendKeyPress(Key: Word);
// ... (код функции из предыдущих примеров)

procedure TForm1.Button1Click(Sender: TObject);
var
  HealthAddress: Pointer;
  Health: Integer;
  HealthThreshold: Integer;
begin
  HealthAddress := GetHealthPointer(Pointer($12345678), [$4, $8, $C]); // Замените на ваш адрес и смещения
  HealthThreshold := 500; // Порог для нажатия клавиши

  while True do // Бесконечный цикл для постоянного мониторинга
  begin
    Health := ReadHealth(GetCurrentProcessId, HealthAddress);

    if Health < HealthThreshold then
    begin
      SendKeyPress(VK_SPACE); // Нажимаем пробел, если здоровье ниже порога
    end;

    Sleep(100); // Пауза в 100 миллисекунд для экономии ресурсов
  end;
end;
 
Вверх