Soy nuevo en seguridad y actualmente me refiero a Codificación segura en C y C ++. En el capítulo 2 de la misma, el autor habla sobre la inyección de arco, en la que pasa el flujo de control en el siguiente programa desde la rutina isPasswordOK()
a la rama else() {puts ("Access granted!");};
en main()
sobrescribiendo el Password
buffer en la llamada gets()
con una cadena contaminada: 1234567890123456j>*!
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
bool isPasswordOK(void) {
char Password[12];
gets(Password);
return 0 == strcmp(Password, "goodpass");
}
int main(void) {
bool pwStatus;
puts("Enter Password: ");
pwStatus = isPasswordOK();
if (pwStatus == false) {
puts("Access denied");
exit(-1);
}
else {
puts("Access granted!");
}
}
Aquí, j = 0x6A
, > = 0x10
(Este es el símbolo de escape del enlace de datos), * = 0x2A
y ! = 0x21
Esta secuencia de 4 caracteres corresponde a una dirección de 4 bytes, que supongo que es 0x6A102A21
. Creo que esta dirección apunta a la línea else
en la función main()
, y redirigimos el control al sobrescribir la dirección de retorno en la pila por la dirección de esta línea.
Estoy intentando reproducir lo mismo en mi máquina (arquitectura x86-64). He desactivado la protección de la pila y la aleatorización, así que no creo que eso deba ser un problema. De hecho, el programa se bloquea como se esperaba cuando intento corromper la dirección de retorno. Mi problema es: ¿cómo proporciono como entrada para gets
la cadena contaminada? Si desmonto main
usando gdb, obtengo el siguiente resultado:
(gdb) disassemble main
Dump of assembler code for function main:
0x0000000000400642 <+0>: push %rbp
0x0000000000400643 <+1>: mov %rsp,%rbp
0x0000000000400646 <+4>: sub $0x10,%rsp
0x000000000040064a <+8>: mov $0x40071d,%edi
0x000000000040064f <+13>: callq 0x4004c0 <puts@plt>
0x0000000000400654 <+18>: callq 0x400616 <isPasswordOK>
0x0000000000400659 <+23>: mov %al,-0x1(%rbp)
0x000000000040065c <+26>: movzbl -0x1(%rbp),%eax
0x0000000000400660 <+30>: xor $0x1,%eax
0x0000000000400663 <+33>: test %al,%al
0x0000000000400665 <+35>: je 0x40067b <main+57>
0x0000000000400667 <+37>: mov $0x40072e,%edi
0x000000000040066c <+42>: callq 0x4004c0 <puts@plt>
0x0000000000400671 <+47>: mov $0xffffffff,%edi
0x0000000000400676 <+52>: callq 0x400510 <exit@plt>
0x000000000040067b <+57>: mov $0x40073c,%edi
0x0000000000400680 <+62>: callq 0x4004c0 <puts@plt>
0x0000000000400685 <+67>: leaveq
0x0000000000400686 <+68>: retq
End of assembler dump.
Ya que quiero saltar a la segunda llamada puts()
, creo que necesito proporcionar 0x0000000000400680
como parte de mi cadena contaminada porque esta es la dirección del segundo puts()
según el desmontaje gdb.
¿Cómo puedo hacer esto? En el libro, la dirección era de longitud 8, pero aquí tengo una de longitud 16. Además, no hay una representación ASCII para 0x80
, así que, ¿qué se supone que debo proporcionar como entrada para gets
? Básicamente, lo que pido son los caracteres que debo proporcionar en ? :
1234567890123456 ????
Estoy completamente confundido, por lo que se agradece cualquier ayuda, ¡gracias!