2016-04-20 7 views
3

Ich habe an einigen Stellen gelesen, dass ASLR den .data Abschnitt an zufälligen Adressen laden soll, jedes Mal wenn ein Programm ausgeführt wird, was bedeutet, dass die Adressen der globalen Variablen unterschiedlich sein sollten. Allerdings, wenn ich den folgenden Code haben:Wie können Adressen von globalen Variablen randomisiert werden, wenn sie innerhalb der ELF fest codiert sind?

int global_var = 42; 

int main() 
{ 
    global_var = 10; 
    return 0; 
} 

und ich kompilieren es mit gcc -fpie -o global global.c, zeigt objdump -d -M intel folgendes:

4004ed: 55      push rbp 
    4004ee: 48 89 e5    mov rbp,rsp 
    4004f1: c7 05 3d 0b 20 00 0a mov DWORD PTR [rip+0x200b3d],0xa  # 601038 <global_var> 

Es scheint, dass global_var immer bei 601038. Tat gestellt werden, wenn ich mit Bugsymbol kompilieren global_var ‚hat s DIE diese Adresse fest einprogrammiert:

$ gcc -ggdb3 -fpie -o global global.c 
$ objdump --dwarf=info global 
... 
<1><55>: Abbrev Number: 4 (DW_TAG_variable) 
    <56> DW_AT_name  : (indirect string, offset: 0x30c): global_var 
    <5a> DW_AT_decl_file : 1 
    <5b> DW_AT_decl_line : 1 
    <5c> DW_AT_type  : <0x4e>  
    <60> DW_AT_external : 1 
    <60> DW_AT_location : 9 byte block: 3 38 10 60 0 0 0 0 0 (DW_OP_addr: 601038) 

Wie funktioniert ASLR Arbeit i In diesen Fällen?

+1

Ich glaube, ASLR funktioniert nur auf den Code, Stack und Heap. Nicht unbedingt auf die Daten. Könnte falsch sein, also nicht als Antwort. –

+0

Haben Sie versucht, mit 'gdb' zu laufen und zu debuggen? Ich bin mir nicht sicher, aber vielleicht gibt es dort eine Art Umsiedlung. – Tomer

Antwort

1

Wenn Sie ein PIE kompilieren, ist die Datei tatsächlich ein gemeinsames Objekt (ET_DYN, Sie können dies mit readelf -h filename überprüfen). Diese Art von ELF-Dateien (sowohl PIEs als auch .so Dateien) sind entworfen, um an jeder Basisadresse ladbar zu sein (gut, normalerweise modulo die Seitengröße).

Für diese Dateien sind die virtuellen Adressen (angegeben in der Abschnitts-Header-Tabelle, Programm-Header-Tabelle, Symboltabelle, in den DWARF-Dateien usw.) Offsets von dieser Basisadresse.

Dies erklärt in the System V ABI:

die virtuellen Adressen in den Programmschriften nicht die tatsächlichen virtuellen Adressen des Programmspeicherbild darstellen könnten. Ausführbare Dateien enthalten in der Regel absoluten Code. [...] Auf der anderen Seite gemeinsame Objektsegmente enthalten positionsunabhängigen Code. Dadurch wird die virtuelle Adresse eines Segments von in einen anderen Prozess geändert, ohne dass das Ausführungsverhalten ungültig wird. Obwohl das System virtuelle Adressen für einzelne Prozesse wählt, hält sie die relativen Positionen der Segmente Da positionsunabhängigen Code zwischen den Segmenten, die Differenz zwischen virtuellen Adressen im Speicher relativen verwendet Adressierung muß die Differenz zwischen dem virtuellen Adressen übereinstimmen in der Datei. Der Unterschied zwischen der virtuellen Adresse eines beliebigen Segments im Speicher und der entsprechenden virtuellen Adresse in der Datei ist somit ein einzelner konstanter Wert für ein ausführbares oder gemeinsames Objekt in einem bestimmten Prozess. Dieser Unterschied ist die Basisadresse.

für dwarf, wird dies in section 7.3 von DWARF 4 erklärt:

die verschobene Adressen in den Debug-Informationen für ein ausführbares Objekt sind virtuelle Adressen und die verschobene Adressen in den Debug-Informationen für Ein gemeinsames Objekt sind Offsets relativ zum Beginn der niedrigsten Region des Speichers geladen von diesem gemeinsamen Objekt.

Da diese Dateien an jeder Basisadresse zugeordnet werden können, kann diese Basisadresse randomisiert werden.

+0

Aber was passiert mit dem eigentlichen Code? Im Beispiel hatte ich 'mov DWORD PTR [rip + 0x200b3d], 0xa', was vom Wert von' rip' abhängt. Dies bedeutet, dass die "zufälligen" Basisadressen von '.data' und' .text' irgendwie miteinander verwandt sind, oder? Könnte sich der generierte Code jemals auf eine globale Variable bezogen auf nur eine Adresse beziehen (im Gegensatz zu einem Register + Offset)? Wenn ja, würde es mit ASLR brechen? – Martin

+0

Ja, die relative Position der verschiedenen Teile einer gegebenen ELF-Datei ist festgelegt. Wenn Sie PIE kompilieren, verwendet der Compiler nur "relative Adressierung" anstelle von absoluten Adressen. Das ist die Kernidee von PIC/PIE (positionsunabhängig). – ysdx

+1

Oh, ich verstehe. Ich dachte, jeder Abschnitt hätte eine unabhängige Basisadresse. Könnte der generierte Code dennoch auf eine globale Variable bezogen auf nur eine Adresse verweisen (im Gegensatz zu einem Register + Offset)? Wenn ja, würde es mit ASLR brechen? – Martin

4

Die Anweisung Ausgabe von der Demontage gibt Ihnen 601038 als eine Bequemlichkeit relativ zu einer beliebigen Basis (0x400000), aber lesen Sie die tatsächliche Anweisung; Es schreibt an DWORD PTR [rip+0x200b3d]. ist der Befehlszeiger. Der Code und die Daten haben einen festen Offset zueinander; Randomisierung der Basisadresse ändert das nicht. Beim Laden mit dem Anweisungszeiger wird eine Adresse verwendet, die bereits die ASLR-Verschiebung enthält.

Die Bequemlichkeit Mapping in der Beschreibung zu 601038 ist, weil die festen Offsets von rip ganzen Code verstreut abhängig sind, wo der Befehl befindet, so dass sie nicht vergleichbar sind, ohne eine Anpassung für die Instruktion Standort zu machen; Der Disassembler kennt zwar den Instruktions-Offset, kann also diesen Instruktions-Offset subtrahieren, um global vergleichbare Adressen für die gemeinsame Basis 0x400000 zu erhalten.

+0

Ja, aber das passiert auch ohne '-fpie'. Ich denke, der Compiler ist nur für den Fall sicher? – Martin

Verwandte Themen