Как определить местоположение дизассемблированного кода в исполняемом файле?

StackOverflow https://stackoverflow.com/questions/1647979

Вопрос

У меня есть исполняемый файл (C ++, i386, скомпилированный под MacOS / X Tiger, если это имеет значение), который содержит ошибку. Исправление этой ошибки простое - в коде есть место, где он вызывает fork (), а этого не должно быть. Поскольку исправление является простым, и поскольку на этом этапе будет трудно перекомпилировать исполняемый файл с нуля (не спрашивайте), я хотел бы просто напрямую исправить исполняемый / двоичный файл.

В качестве первого шага к этому я запустил " otool -tV MyExecutableName " на моем исполняемом файле и вуаля, я нашел это в выводе дизассемблирования:

./MyExecutableName:
(__TEXT,__text) section
[... many lines omitted ...]
0002ce0d        subl    <*>x10,%esp
0002ce10        calll   0x0051adac
0002ce15        movzbl  0x14(%ebp),%esi
0002ce19        calll   0x00850ac9      ; symbol stub for: _fork
0002ce1e        cmpl    <*>x00,%eax
0002ce21        jll     0x0002cf02
0002ce27        jle     0x0002ce34
[... many more lines omitted ...]

Итак, я хотел бы заменить код операции в строке 0002ce19, чтобы вместо вызова _fork он просто безоговорочно переходил к случаю сбоя (т.е. он должен действовать так, как будто fork () вернул -1 )

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

1) Какие байты я должен записать в местоположения с 0002ce19 по 0002xe1d, чтобы получить то, что я хочу? Я предполагаю, что это будет собранный эквивалент "jmp 0x0002cf02", но как мне выяснить, что это за байты?

2) Смещения, напечатанные как "otool -tV"; кажется смещением в сегмент __TEXT исполняемого файла. Как я могу определить дельту байта между напечатанными смещениями и верхней частью файла, чтобы я мог редактировать / исправлять правильные байты в файле?

Спасибо за любой совет, который вы можете дать!

Это было полезно?

Решение

Я не знаком с MacOS / X, но могу дать вам несколько советов.

Правильный способ исправить это - использовать дизассемблер для исправления вашего файла.

0002ce19        calll   0x00850ac9

можно заменить на

0002ce19        movl   eax, -1 ; mov eax, 0xFFFFFFFF

Смещения, которые вы видите, относительны, поэтому вы не можете найти их в файле.
Например, jll 0x0002cf02 фактически является jll 0x000000DF

Если я прав, приведенный ниже блок кода

0002ce19        calll   0x00850ac9      ; symbol stub for: _fork
0002ce1e        cmpl    
0x  E8   AB3C8200
    83F8 00
    0F8C DF000000
    0F84 0B000000
x00,%eax 0002ce21 jll 0x0002cf02 0002ce27 jle 0x0002ce34

будет иметь эту собранную форму (20 байтов):

<*>

Если эта последовательность уникальна в файле, вы можете попробовать изменить E8AB3C8200 на B8FFFFFFFF , если вы не можете использовать дизассемблер.

Другие советы

Вероятно, проще всего было бы поместить mov $ -1,% eax вместо вызова. Вы можете узнать, каким байтам это соответствует, поместив его в файл .s, скомпилировав его и выгрузив результат, заполнив его nops, если он короче, чем местоположение патча. Я получаю "b8 ff ff ff ff", который просто подходит.

Вы можете найти начало __ TEXT , запустив otool -l и найдя смещение.

otx и Hex Fiend станут вашими друзьями. otx даст вам разборку со смещением относительно файла, а Hex Fiend позволит вам исправить переход. Помните, что 0x90 - это (x86) код операции для NOP, поэтому 9090909090 - подходящая замена для вызова fork (). (Имейте в виду, что он не будет генерировать возвращаемое значение, поэтому что-то странное может закончиться в eax.)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top