Aus diesem Beitrag geht hervor, dass FS:[0x28]
es sich um einen Stapelkanarienvogel handelt. Ich generiere denselben Code mit GCC für diese Funktion.
void foo () {
char a[500] = {};
printf("%s", a);
}
Insbesondere bekomme ich diese Baugruppe.
0x000006b5 64488b042528. mov rax, qword fs:[0x28] ; [0x28:8]=0x1978 ; '(' ; "x\x19"
0x000006be 488945f8 mov qword [local_8h], rax
...stuff...
0x00000700 488b45f8 mov rax, qword [local_8h]
0x00000704 644833042528. xor rax, qword fs:[0x28]
0x0000070d 7405 je 0x714
0x0000070f e85cfeffff call sym.imp.__stack_chk_fail ; void __stack_chk_fail(void)
; CODE XREF from 0x0000070d (sym.foo)
0x00000714 c9 leave
0x00000715 c3 ret
Wofür wird der Wert eingestellt fs:[0x28]
? Der Kernel oder wirft GCC den Code ein? Können Sie den Code im Kernel anzeigen oder in die festgelegte Binärdatei kompilieren fs:[0x28]
? Wird der Kanarienvogel regeneriert - beim Booten oder beim Prozess-Spawn? Wo ist das dokumentiert?
arch_prctl(ARCH_SET_FS..)
Ich sehe das nicht in der ausführbaren Datei? Ist das Kernel-Code?ld-linux
während der TLS-Initialisierung ausgeführt.Was Sie sehen, wird (in GCC) als Stack Smashing Protector (SSP) bezeichnet , eine Form des vom Compiler generierten Pufferüberlaufschutzes . Der Wert ist eine Zufallszahl, die vom Programm beim Start generiert wird und, wie im Wikipedia-Artikel erwähnt, in Thread Local Storage (TLS) abgelegt wird . Andere Compiler verwenden möglicherweise andere Strategien, um diese Art von Schutz zu implementieren.
Warum den Wert in TLS speichern? Da sich der Wert dort befindet, können die CS-, DS- und SS-Register nicht auf seine Adresse zugreifen, was das Erraten des gespeicherten Werts sehr schwierig macht, wenn Sie versuchen, den Stapel von bösartigem Code zu ändern.
quelle