Как определить местоположение дизассемблированного кода в исполняемом файле?
-
22-07-2019 - |
Вопрос
У меня есть исполняемый файл (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.)