View Single Post
Old 20-11-2006, 09:46   #14
71104
Bannato
 
L'Avatar di 71104
 
Iscritto dal: Feb 2005
Città: Roma
Messaggi: 7029
appendice: generazione del codice clandestino

ricordiamoci che il nostro scopo è chiamare LoadLibraryA passandogli l'indirizzo di una stringa situata nel codice stesso, e subito dopo fare un JMP all'entry point originale.

possiamo strutturare il codice come segue:
  • PUSH
  • CALL
  • JMP
  • nome del file della DLL

cominciamo dal PUSH, già abbiamo un problema: con una rapida consultatina al manuale Intel vediamo che la versione che dovremmo usare è PUSH imm32, opcode 0x68 seguito da 4 bytes di valore immediato. calcolare il valore immediato è banale, basta sommare l'RVA della stringa al base address dell'eseguibile; il problema è che avremmo (in teoria) bisogno di un fixup in quel punto... possibili soluzioni?

1) ce ne freghiamo - tanto è un eseguibile, verrà sicuramente caricato al suo base address predefinito, a meno che il programmatore sadico non l'abbia definito come 0x7C800000 (il base address di kernel32.dll) o come >= 0x80000000 (base address in kernel space).

2) pur di essere sicuri di non doverci rilocare spostiamo tutto l'eseguibile al base address standard, 0x00400000
e a dire il vero non è neanche una soluzione tanto difficile: basta rilocare tutto il file utilizzando (0x00400000 - il suo base address) come delta

col PUSH siamo quindi (più o meno ) a posto: iniziamo a scrivere 0x68 e lasciamo 4 byte vuoti perché l'RVA della stringa ancora non lo sappiamo.

ora passiamo al CALL: stavolta, al contrario del caso precedente, se vogliamo usare un valore immediato nella chiamata non abbiamo a disposizione una versione absolute dell'istruzione, ma solo relative; peccato che adesso invece ci serviva proprio la absolute (eccheppalle ).

abbiamo due casi:
1) l'eseguibile importa LoadLibraryA da kernel32.dll
2) l'eseguibile non importa LoadLibraryA

nel primo caso siamo fortunati: dobbiamo usare CALL r/m32 specificando l'indirizzo della entry relativa a LoadLibraryA nella Import Address Table. non entro in dettagli perché dal manuale non ho capito la codifica di quella versione di CALL ^__^''

nel secondo caso invece, considerando che nello spazio di indirizzamento di qualsiasi processo il base address di kernel32.dll non cambia mai (e quindi neanche l'indirizzo di LoadLibraryA), utilizzeremo CALL rel32: scriviamo 0xE8 e subito dopo un delta così calcolato:

(indirizzo di LoadLibraryA ottenuto da una GetProcAddress chiamata in qualsiasi processo) - (VA a cui stiamo scrivendo il CALL) - (dimensione del CALL, cioè 5)

e la cosa bella è che qui non ci serve il fixup

andiamo avanti: il JMP. caso analogo: ciò che dobbiamo usare è JMP rel32, opcode 0xE9 seguito dai 4 bytes di delta così calcolati:

(valore originale del membro AddressOfEntryPoint dell'header principale) - (VA del JMP) - (dimensione del JMP, cioè 5)

dopodiché scriviamo la stringa e a questo punto, conoscendo anche l'RVA della stringa stessa, possiamo ultimare il PUSH iniziale. occhio però: ai 4 bytes immediati del PUSH non dobbiamo scrivere l'RVA, ma il VA (l'RVA sommato al base address predefinito, sperando che sia sempre anche quello effettivo ).
71104 è offline   Rispondi citando il messaggio o parte di esso