Come posso determinare la posizione del codice disassemblato all'interno di un eseguibile?
-
22-07-2019 - |
Domanda
Ho un file eseguibile (C ++, i386, compilato sotto MacOS / X Tiger, se è importante) che contiene un bug. La correzione per il bug è semplice: c'è un posto nel codice in cui si chiama fork () e non dovrebbe. Poiché la correzione è semplice e poiché la ricompilazione dell'eseguibile da zero sarebbe difficile a questo punto (non chiedere), vorrei solo patchare direttamente il file eseguibile / binario.
Come primo passo verso quello, ho corso " otool -tV MyExecutableName " sul mio eseguibile e voilà, l'ho trovato nell'output di smontaggio:
./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 ...]
Quindi quello che mi piacerebbe fare è sostituire il codice operativo alla riga 0002ce19, in modo che invece di chiamare _fork, salti semplicemente incondizionatamente al caso di errore (cioè dovrebbe agire come se fork () avesse restituito -1 )
Sfortunatamente, sono un principiante completo al disassemblaggio / patch binario, quindi non sono sicuro di come procedere. In particolare, le mie domande sono:
1) Quali byte devo scrivere nelle posizioni da 0002ce19 a 0002xe1d per ottenere quello che voglio? Presumo che sarebbe l'equivalente assemblato di "jmp 0x0002cf02", ma come faccio a capire quali sono questi byte?
2) Gli offset stampati da " otool -tV " sembrano essere offset nel segmento __TEXT dell'eseguibile. Come posso capire il delta-byte tra gli offset stampati e la parte superiore del file, in modo da poter modificare / patchare i byte corretti all'interno del file?
Grazie per qualsiasi consiglio tu possa dare!
Soluzione
Non ho familiarità con MacOS / X ma posso darti alcuni suggerimenti.
Il modo corretto per risolverlo è utilizzare un disassemblatore per correggere il file.
0002ce19 calll 0x00850ac9
può essere sostituito con
0002ce19 movl eax, -1 ; mov eax, 0xFFFFFFFF
Gli offset che vedi sono relativi, quindi non puoi trovarli nel file.
Ad esempio, jll 0x0002cf02
è in realtà jll 0x000000DF
Se ho ragione, il seguente blocco di codice
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
avrà questo modulo assemblato (20 byte):
<*> Se quella sequenza è unica nel file, puoi provare a cambiare E8AB3C8200
in B8FFFFFFFF
, se non puoi usare un disassemblatore.
Altri suggerimenti
Probabilmente il più semplice sarebbe mettere mov $ -1,% eax
al posto della chiamata. Puoi scoprire a quali byte corrisponde inserendolo in un file .s, compilandolo e scaricando il risultato, riempiendo con nops se è più corto della posizione della patch. Ottengo " b8 ff ff ff ff " ;, che si adatta perfettamente.
Puoi trovare l'inizio di __TEXT
eseguendo otool -l
e cercando l'offset.
otx e Hex Fiend saranno i tuoi amici. otx ti darà uno smontaggio con offset relativi al file e Hex Fiend ti consentirà di correggere il salto. Ricordare che 0x90 è il codice operativo (x86) per NOP, quindi 9090909090 è un sostituto appropriato per la chiamata fork (). (Tieni presente che non genererà un valore di ritorno, quindi qualcosa di strano potrebbe finire in eax.)