Como posso determinar a localização de código desmontado dentro de um executável?
-
22-07-2019 - |
Pergunta
Eu tenho um arquivo executável (C ++, i386, compilado sob MacOS / X Tiger, se isso importa) que contém um bug. A correção para o bug é simples - há um lugar no código onde ele chama fork () e que não deveria. Porque a correção é simples, e porque recompilar o executável a partir do zero seria difícil neste momento (não pergunte), eu gostaria de apenas corrigir o arquivo executável / binário diretamente.
Como um primeiro passo para isso, eu corri "otool -TV MyExecutableName" no meu executável, e voila, eu encontrei este na saída desmontagem:
./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 ...]
Então, o que eu gostaria de fazer é substituir o código de operação na linha 0002ce19, de modo que em vez de calll'ing _fork, ele simplesmente salta incondicionalmente para o caso de falha (ou seja, deve agir como se fork () tinha retornado -1 )
Infelizmente, eu sou um novato completo a desmontagem patching / binário, então eu não tenho certeza de como vai fazer sobre isso. Em particular, minhas perguntas são:
1) Qual bytes que eu deveria escrever em locais 0002ce19 através 0002xe1d para conseguir o que eu quero? Eu suponho que seria o equivalente montado de "jmp 0x0002cf02", mas como faço para descobrir o que os bytes são?
2) Os deslocamentos impressos por "otool -TV" parecem ser as compensações para o segmento __TEXT do executável. Como posso descobrir o byte-delta entre os deslocamentos impressos e na parte superior do arquivo, para que eu possa editar / corrigir os bytes corretas dentro do arquivo?
Obrigado por qualquer conselho que você pode dar!
Solução
Eu não estou familiarizado com o MacOS / X, mas eu posso lhe dar algumas dicas.
A maneira correta de corrigi-lo, é usar um desmontador para corrigir seu arquivo.
0002ce19 calll 0x00850ac9
pode ser substituída por
0002ce19 movl eax, -1 ; mov eax, 0xFFFFFFFF
Os deslocamentos que você vê são relativas, então você não pode encontrá-los no arquivo.
Por exemplo, jll 0x0002cf02
é realmente jll 0x000000DF
Se eu estiver correto, a seguir bloco de código
0002ce19 calll 0x00850ac9 ; symbol stub for: _fork
0002ce1e cmpl $0x00,%eax
0002ce21 jll 0x0002cf02
0002ce27 jle 0x0002ce34
terá esta forma montada (20 bytes):
0x E8 AB3C8200
83F8 00
0F8C DF000000
0F84 0B000000
Se essa seqüência é único no arquivo, então você pode tentar mudar o E8AB3C8200
para B8FFFFFFFF
, se você não pode usar um desmontador.
Outras dicas
Provavelmente o mais fácil seria colocar mov $-1, %eax
no lugar da chamada. Você pode descobrir o que bytes que corresponde a, colocando-o em um arquivo .s, compilá-lo e descarregar o resultado, preenchimento com nops se for mais curto do que o local patch. Eu recebo "b8 ff ff ff ff", que só se encaixa.
Você pode encontrar o início da __TEXT
executando otool -l
e olhando para o deslocamento.
OTX e Hex Fiend serão seus amigos. OTX lhe dará uma desmontagem com deslocamentos de arquivo-relativa e Hex Fiend vai deixar você corrigir o salto. Lembre-se que 0x90 é o (x86) código de operação para NOP, de modo 9090909090 é um substituto adequado para a chamada fork (). (Basta ter em mente que não irá gerar um valor de retorno, de modo algo estranho pode acabar em eax.)