Чаще всего нужный адрес в hex-редакторе не находится потому, что пользователь вводит виртуальный адрес из отладчика (например, 0040132A) в поле перехода, а редактор ожидает файловое смещение — и в итоге попадает совершенно не туда. Это главная причина «несовпадающих байтов» при патче исполняемых файлов: адрес в памяти и смещение в файле — разные величины, связанные формулой FileOffset = RVA − SectionRVA + PointerToRawData.
Ниже разберём, как правильно перейти к нужному адресу в популярных hex-редакторах (HxD, 010 Editor, WinHex, Hex Editor Neo), как искать по сигнатуре байтов и текстовой строке, как пересчитать адреса и как проверить, что вы действительно оказались в нужном месте.
Что такое адрес в hex-редакторе и почему их несколько
Hex-редактор показывает содержимое файла или диска в виде шестнадцатеричных байтов. Каждый байт имеет смещение (offset) — порядковый номер от начала файла, начиная с нуля. Именно смещения отображаются в левой колонке окна редактора и в строке состояния.
Проблема возникает, когда адрес взят из другого инструмента: отладчика, дизассемблера, лога ошибки или инструкции с форума. Там могут фигурировать:
- 📍 Файловое смещение (RAW offset) — позиция байта в файле на диске; именно его понимает hex-редактор.
- 🧭 Виртуальный адрес (VA) — адрес в памяти после загрузки программы; для PE-файлов обычно начинается с ImageBase, например 0x400000 у классических 32-битных EXE.
- 🔢 RVA (Relative Virtual Address) — виртуальный адрес минус ImageBase.
- 💾 Физический адрес сектора — при редактировании диска, а не файла; считается в секторах, а не в байтах.
⚠️ Внимание: если ввести виртуальный адрес как файловое смещение, вы почти наверняка попадёте в несуществующую область или в чужие данные. Перед переходом выясните, какой именно тип адреса указан в вашем источнике.
Быстрый переход по известному смещению
Если смещение уже известно и это именно файловый offset, переход занимает пару секунд. В большинстве редакторов используется команда Правка → Перейти (Go To) или сочетание Ctrl+G.
Порядок действий в HxD:
- ⌨️ Откройте файл и нажмите
Ctrl+G— появится диалог перехода. - 🔢 Введите смещение в шестнадцатеричном виде (например,
1A3F) и выберите режим «hex». - ↔️ Укажите точку отсчёта: от начала файла, от текущей позиции или от конца файла.
- ✅ Подтвердите — курсор встанет на нужный байт, а его адрес отобразится в строке состояния.
В 010 Editor аналогичный переход выполняется через Ctrl+G с выбором формата адреса, а в WinHex — через Навигация → Перейти к смещению. Точные названия пунктов могут отличаться в зависимости от версии программы, поэтому ориентируйтесь на слово «Go To» / «Перейти» в меню навигации.
Пересчёт виртуального адреса в файловое смещение
Когда адрес получен из отладчика или дизассемблера (например, x64dbg, OllyDbg, IDA), его нужно пересчитать. Для PE-файлов (EXE, DLL) логика такая: файл разбит на секции (.text, .data и др.), каждая из которых имеет виртуальный адрес размещения в памяти и физическое положение в файле.
Алгоритм пересчёта:
- 1️⃣ Вычтите из виртуального адреса ImageBase — получите RVA. Например,
0040132A − 400000 = 132A. - 2️⃣ Определите, в какую секцию попадает RVA, по таблице секций (её показывают CFF Explorer, PE-bear, DIE).
- 3️⃣ Примените формулу:
FileOffset = RVA − VirtualAddress(секции) + PointerToRawData(секции). - 4️⃣ Перейдите по полученному смещению в hex-редакторе через
Ctrl+G.
| Величина | Обозначение | Где взять |
|---|---|---|
| ImageBase | Базовый адрес загрузки | Заголовок PE (Optional Header) |
| RVA | VA − ImageBase | Вычисляется вручную |
| VirtualAddress секции | Адрес секции в памяти | Таблица секций PE |
| PointerToRawData | Смещение секции в файле | Таблица секций PE |
| FileOffset | Искомое смещение | Результат формулы |
Для простых случаев, когда секция в памяти и в файле выровнены одинаково (что бывает у неупакованных файлов), разница между RVA и файловым смещением может быть небольшой или вообще нулевой. Но полагаться на это нельзя — у упакованных и оптимизированных файлов смещения расходятся существенно.
Поиск нужного места по байтам и строкам
Часто точный адрес неизвестен, зато известно содержимое — последовательность байтов (сигнатура) или текстовая строка рядом с нужным местом. Тогда адрес находится поиском.
Варианты поиска, доступные практически в любом редакторе (Ctrl+F):
- 🔍 Поиск hex-последовательности — вводите байты через пробел, например
8B 45 FC 83. Подходит для поиска машинного кода и сигнатур. - 🔤 Поиск текстовой строки — ANSI или Unicode (UTF-16). Строки в исполняемых файлах Windows часто хранятся в Unicode, поэтому, если ANSI-поиск ничего не нашёл, попробуйте Unicode.
- 🧮 Поиск числа — целое число заданной разрядности (8/16/32/64 бита) с учётом порядка байт little-endian.
⚠️ Внимание: числа в x86/x64 хранятся в формате little-endian — младший байт первым. Значение0x00001388в файле будет выглядеть как88 13 00 00. Ищите байты именно в перевёрнутом порядке.
После нахождения совпадения смотрите адрес в строке состояния — это и есть искомое смещение. Если совпадений несколько, перебирайте их клавишей F3 (найти далее) и сверяйте окружающий контекст с ожидаемым.
Проверка: вы действительно на нужном адресе
Попасть на адрес мало — нужно убедиться, что это то самое место. Ориентируйтесь на контекст вокруг курсора.
Признаки правильного попадания:
- ✅ Байты под курсором совпадают с теми, что указаны в вашем источнике (инструкции, логе, статье).
- 🧩 Соседние байты образуют осмысленную структуру: читаемую строку, начало функции (часто
55 8B ECдля старого кода x86), выровненные данные. - 📊 Адрес попадает в ожидаемую секцию: код — в .text, строки — в .rdata или .data.
Если байты не совпадают — почти всегда дело в неверном пересчёте адреса или в том, что источник описывает другую версию файла. Сверьте размер файла и, если возможно, его хеш с тем, что использовал автор инструкции.
☑️ Проверка перед правкой байтов
Типичные ошибки при поиске адреса
Разберём ситуации, из-за которых «адрес не находится» или «патч не работает».
Первая ошибка — путаница систем счисления. Адрес 132A в hex и 132A в dec — это разные позиции. Всегда проверяйте, в каком режиме работает поле ввода перехода; шестнадцатеричные адреса в источниках обычно помечены префиксом 0x или суффиксом h.
Вторая ошибка — поиск адреса в файле другой версии. Даже минорное обновление программы сдвигает все смещения. Универсальных адресов не существует: каждый адрес привязан к конкретной сборке файла.
Третья ошибка — попытка перейти по смещению, которое больше размера файла. Так бывает, когда виртуальный адрес вводят как файловый: редактор либо сообщит об ошибке, либо встанет в конец данных.
⚠️ Внимание: перед любыми правками в hex-редакторе создайте копию файла. Изменение даже одного байта в исполняемом файле может сделать его неработоспособным, а при редактировании диска — повредить файловую систему.
Как найти адрес строки, на которую ссылается код
Найдите строку поиском (Ctrl+F, режим Unicode/ANSI) и запишите её файловое смещение. Пересчитайте его в RVA по формуле секции, прибавьте ImageBase — получите виртуальный адрес строки. Именно этот адрес будет фигурировать в инструкциях вида push/mov/lea в дизассемблере. Обратный поиск этого адреса как константы (в little-endian) по файлу покажет места, где код ссылается на строку.
FAQ: частые вопросы
Почему Ctrl+G не находит адрес из инструкции?
Скорее всего, в инструкции указан виртуальный адрес из отладчика, а редактор ожидает файловое смещение. Пересчитайте адрес через таблицу секций PE-файла по формуле из статьи. Также проверьте, что в диалоге перехода выбрана правильная система счисления (hex/dec).
Как найти адрес, если известна только текстовая строка рядом?
Используйте поиск строки через Ctrl+F. Если строка на русском или в программе Windows — пробуйте оба режима: ANSI и Unicode (UTF-16), так как строки в PE-файлах часто хранятся в Unicode. Адрес найденного совпадения смотрите в строке состояния редактора.
Чем отличается адрес в колонке слева от адреса в отладчике?
Колонка слева в hex-редакторе показывает файловые смещения — позиции байтов в файле на диске. Отладчик показывает виртуальные адреса — позиции в оперативной памяти после загрузки. Эти значения совпадают только в редких частных случаях.
Можно ли найти адрес числа, например количества жизней в игре?
Да, но hex-редактор работает с файлом на диске, а игровые значения меняются в памяти. Для поиска значений в памяти используются другие инструменты (например, сканеры памяти). В файле сохранения значение можно искать как число в little-endian, но формат сохранений у каждой игры свой.
Адрес найден, но байты не совпадают с описанием. Что делать?
Проверьте три вещи: правильность пересчёта VA в файловое смещение, соответствие версии вашего файла версии из источника (сравните размер и хеш) и систему счисления при вводе адреса. Если всё совпадает, а байты различаются — инструкция написана для другой сборки файла, и применять её нельзя.