De esta publicación se muestra que FS:[0x28]
es un stack-canary. Estoy generando el mismo código usando GCC en esta función,
void foo () {
char a[500] = {};
printf("%s", a);
}
Específicamente, estoy obteniendo esta asamblea ...
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
¿Qué es establecer el valor de fs:[0x28]
? El núcleo, o GCC está arrojando el código? ¿Puedes mostrar el código en el kernel o compilarlo en el binario que establece fs:[0x28]
? ¿Se regenera el canario en el arranque o engendra proceso? ¿Dónde se documenta esto?
arch_prctl(ARCH_SET_FS..)
No veo eso en el ejecutable? ¿Es ese código del núcleo?ld-linux
durante la inicialización de TLS.Lo que está viendo se llama (en GCC) Stack Smashing Protector (SSP) , que es una forma de protección de desbordamiento de búfer generada por el compilador. El valor es un número aleatorio generado por el programa al inicio y, como menciona el artículo de Wikipedia, se coloca en Thread Local Storage (TLS) . Otros compiladores pueden usar diferentes estrategias para implementar este tipo de protección.
¿Por qué almacenar el valor en TLS? Como el valor se encuentra allí, los registros CS, DS y SS no pueden acceder a su dirección, lo que hace que adivinar el valor almacenado sea muy difícil si está tratando de alterar la pila del código malicioso.
fuente