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

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

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

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

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

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

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

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

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

Ответы [ 3 ]

3 голосов
/ 30 октября 2009

Я не знаком с 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    $0x00,%eax
0002ce21        jll     0x0002cf02
0002ce27        jle     0x0002ce34

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

0x  E8   AB3C8200
    83F8 00
    0F8C DF000000
    0F84 0B000000

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

2 голосов
/ 30 октября 2009

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

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

1 голос
/ 30 октября 2009

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

...