Domanda:
Stai scrivendo intestazioni ELF in Radare?
Evan Carroll
2018-11-20 04:06:00 UTC
view on stackexchange narkive permalink

Leggendo Keith Makan, "Introduzione al formato ELF: l'intestazione ELF" , modifica e_entry ,

Il campo e_entry elenca l'offset nel file in cui il programma dovrebbe iniziare l'esecuzione. Normalmente punta al tuo metodo _start (ovviamente se lo hai compilato con le solite cose). Puoi puntare l'e_entry ovunque tu voglia, ad esempio mostrerò che puoi chiamare una funzione che altrimenti sarebbe impossibile durante la normale esecuzione.

Documentato anche in man 5 elf , mi chiedo se Radare abbia qualche funzionalità per riscrivere intestazioni specifiche di ELF o se scrivere manualmente i bit sia il modo corrente per farlo? Ad esempio, so che mostrerà il punto di ingresso con ie .

Vuoi assolutamente farlo con radare2? In caso contrario, dai un'occhiata al progetto bfd (usato da binutils).
@0xC0000022L Non sono sicuro che ci sia un modo per farlo, in generale presumo che Radare non possa fare qualcosa, quindi chiedo e scopro che può (un valore enorme di questo sito). Presumo che possa analizzare solo ELF. Se può analizzare solo ELF, penso che una soluzione alternativa sia un grande contributo perché sono abbastanza nuovo di RE, e sono sicuro che altri stanno testando le acque proprio come me. Se Radare accresce l'abilità in seguito, tornerò indietro e contrassegnerò la risposta più recente come scelta.
Due risposte:
Megabeets
2018-11-20 13:36:58 UTC
view on stackexchange narkive permalink

Sì, ovviamente puoi. radare2 ha funzionalità integrate per gestire gli header binari. Ciò include la lettura, l'analisi e la modifica delle intestazioni del file binario. E questo non è diverso per i file elf o pe , funzionerà benissimo con entrambi.

TL; DR

  $ ./example.elf[*] hai eseguito questo binario! $ r2 -w -nn example.elf [0x00000000] > .pf.elf_header.entry = 0x0000063a [0x00000000] > q $ ./example.elf[* ] wow come sei riuscito a chiamarlo?  

Creazione del nostro file di prova

Come descritto nell'articolo che hai collegato nella tua domanda, è facile creare un binario con una funzione che non dovrebbe mai essere eseguita in circostanze normali. Ecco il codice esatto utilizzato nell'articolo collegato:

  $ cat example.c # include <stdio.h>void never_call (void) {printf ("[*] wow come sei riuscito a chiamare questo? \ n "); return;} int main (int argc, char ** argv) {printf ("[*] hai eseguito questo binario! \ n"); return 0;}  

Come puoi vedere, la funzione never_call , beh ... non verrebbe mai chiamata. Il programma eseguirà l'entrypoint che eseguirà la funzione main e tornerà.

Ora compiliamolo usando la riga di comando usata nell'articolo ed eseguiamo il programma:

  $ gcc -Wall -o example.elf example.c $ ./example.elf[*] hai eseguito questo binario!  

Come abbiamo detto, solo main () è stato eseguito. Ora apriamo il binario in radare2 per vedere la magia che accade.


radare2 time!

Trovare l'indirizzo della funzione

Come richiesto, vogliamo modificare il punto di ingresso del binario modificando l'indirizzo puntato nell'intestazione elf in modo che sia la nostra funzione never_call . Quindi prima dobbiamo trovare l'indirizzo di never_call nel binario.

  $ r2 example.elf [0x00000530] > f ~ never_call0x0000063a 19 sym.never_call  codice> 

Possiamo vedere che la funzione never_call è all'indirizzo 0x0000063a . Come probabilmente saprai, il comando f viene utilizzato per elencare i flag contrassegnati da radare2, inclusi i simboli come nomi di funzioni. Quindi, abbiamo utilizzato ~ che è il grep interno di r2 e grep per la funzione pertinente.

Analisi dell'intestazione ELF

Per prima cosa, dobbiamo cercare di indirizzare 0 usando s 0 e poi e solo allora possiamo analizzare l'intestazione con un nuovo comando pf . Il comando pf viene utilizzato per stampare dati formattati come strutture, enumerazioni e tipi. Carichiamo la definizione del formato per elf64 usando pfo elf64 e usiamo il comando pf. per elencare le definizioni del formato:

  [0x00002400] > s 0 # Cerca la posizione 0 nel binario [0x00000000] > pfo elf64 # Carica un file di definizione del formato per elf [0x00000000] > pf.pf.elf_header [16] z [2] E [2 ] Exqqqxwwwwww ident (elf_type) tipo (elf_machine) immissione versione macchina phoff shoff flags ehsize phentsize phnum shentsize shnum shstrndxpf.elf_phdr [4] E [4] Eqqqqqq (elf_p_type) tipo (elf_p_flags paddrelf offset [flagdrf] file xdrf offset. 4] E [8] Eqqqxxqq nome (elf_s_type) tipo (elf_s_flags_64) flags addr offset dimensione link info addralign entsize  

Una delle definizioni caricate è elf_header che contiene la struttura per l'intestazione elf64. Possiamo stampare l'intestazione in questo modo:

  [0x00000000] > pf.elf_header ident: 0x00000000 = .ELF ... type: 0x00000010 = type (enum elf_type) = 0x3; ET_DYN macchina: 0x00000012 = macchina (enum elf_machine) = 0x3e; Versione EM_AMD64: 0x00000014 = 0x00000001 voce: 0x00000018 = (qword) 0x0000000000000530 phoff: 0x00000020 = (qword) 0x0000000000000040 shoff: 0x00000028 = (qword) 0x0000000000001900 flags30 = 0x0000
ehsize: 0x00000034 = 0x0040 phentsize: 0x00000036 = 0x0038 phnum: 0x00000038 = 0x0009 shentsize: 0x0000003a = 0x0040 shnum: 0x0000003c = 0x001d shstrndx: 0x0000003e = 0x0009 shentsize: 0x0000003a = 0x0040 shnum: 0x0000003c = 0x001d shstrndx: 0x0000003e = 0x00003c intestazione in un formato leggibile, così ora possiamo vedere che  entry , a 0x18, punta a  0x530  che è la nostra funzione di entrypoint originale. Possiamo verificarlo utilizzando  ie , un comando radare2 per stampare l'entrypooint:  
  [0x00000000] > ie [Entrypoints] vaddr = 0x00000530 paddr = 0x00000530 baddr = 0x00000000 laddr = 0x00000000 haddr = 0x00000018 hvaddr = 0x00000018 type = program  

In effetti, puoi vedere che il punto di ingresso è 0x530 e haddr , che è l'indirizzo dell'intestazione , è 0x18.

Modifica del punto di ingresso

Per modificare questa voce, avremmo bisogno di aprire il file in modalità di scrittura. Possiamo semplicemente eseguire oo + dalla nostra sessione corrente per riaprire il file in modalità di scrittura, oppure utilizzare l'argomento -w per radare2 .

Quindi, possiamo semplicemente usare il comando pf per scrivere nella struttura analizzata l'indirizzo della funzione never_call .

  [0x00000000] > oo + [0x00000000] > pf.elf_header.entry = 0x0000063awv8 0x0000063a @ 0x00000018  

Questo ci ha stampato un comando radare2 da eseguire che modificherà questo indirizzo nell'intestazione. Possiamo eseguirlo da soli o utilizzare il comando . per "interpretare l'output del comando come comandi r2".

Quindi invece di eseguire wv8 ... , faremo semplicemente:

  [0x00000000] > .pf.elf_header.entry = 0x0000063a  

E ora entry dovrebbe essere sovrascritto con 0x63a che è la nostra funzione never_call .

  [0x00000000] > pf.elf_header ident: 0x00000000 = .ELF ... type: 0x00000010 = tipo (enum elf_type) = 0x3; ET_DYN
macchina: 0x00000012 = macchina (enum elf_machine) = 0x3e; Versione EM_AMD64: 0x00000014 = 0x00000001 entry: 0x00000018 = (QWORD) 0x000000000000063a phoff: 0x00000020 = (QWORD) 0x0000000000000040 Shoff: 0x00000028 = (QWORD) 0x0000000000001948 bandiere: 0x00000030 = 0x00000000 ehsize: 0x00000034 = 0x0040 phentsize: 0x00000036 = 0x0038 Phnum: 0x00000038 = 0x0009 shentsize: 0x0000003a = 0x0040 shnum: 0x0000003c = 0x001d shstrndx: 0x0000003e = 0x001c [0x00000000] > pf.elf_header.entry entry: 0x00000018 = (qword) 0x00000000   Executing  >  

Ottimo! Ora possiamo uscire da Radare ed eseguire il programma.

  $ ./example.elf[*] wow come hai fatto a chiamarlo?  

Ultime parole

Questa lunga risposta spiega ogni passaggio del percorso, ma può davvero essere ristretta a un semplice comando .pf.elf_header.entry = 0x0000063a che imposta il voce nell'intestazione elf per essere l'indirizzo desiderato. Nella versione TL; DR ho dimostrato l'uso di -w per aprire il binario in write-mode e l'uso di - nn per caricare la struttura binaria ( pfo elf64 , ecc ...). Quindi, semplicemente, aprire radare2 in questo modo r2 -w -nn example.elf ed eseguire .pf.elf_header.entry = <address> risolverebbe il tuo problema.

Non aver paura di chiedere come fare le cose in radare2. Sebbene sia un framework piuttosto spaventoso, è davvero potente e con una conoscenza adeguata, può fare molte più cose di quanto sembri all'inizio.

Leggi di più

Wow, è davvero fantastico. Dal punto di vista dell'interfaccia utente, sarebbe bello se `.pf.elf_header.entry = 0x0000063a` non scrivesse a` $$ `ma a` @ 0`. Azzeccato la seconda volta però.
L'ho appena usato per rispondere a un'altra domanda sul sito, grazie ancora per aver risposto a tutte le mie domande su re.se. Li farò venire. =) https://reverseengineering.stackexchange.com/a/19936/22669
wisk
2018-11-20 05:36:41 UTC
view on stackexchange narkive permalink

Non credo che questa funzione sia supportata in base al codice sorgente. Modifica: mi sbagliavo, mi dispiace.

Tuttavia , se hai davvero bisogno di una libreria / strumento per farlo, ti consiglio LIEF.



Questa domanda e risposta è stata tradotta automaticamente dalla lingua inglese. Il contenuto originale è disponibile su stackexchange, che ringraziamo per la licenza cc by-sa 4.0 con cui è distribuito.
Loading...