Sono nuovo per la sicurezza e attualmente mi riferisco a Coding sicuro in C e C ++. Nel capitolo 2 dello stesso, l'autore parla dell'iniezione ad arco, in cui passa il flusso di controllo nel seguente programma dalla routine isPasswordOK()
al ramo else() {puts ("Access granted!");};
in main()
sovrascrivendo il Password
buffer in gets()
chiama con una stringa tainted: 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!");
}
}
Qui j = 0x6A
, > = 0x10
(questo è il simbolo di fuga del collegamento dati), * = 0x2A
e ! = 0x21
Questa sequenza di 4 caratteri corrisponde quindi a un indirizzo a 4 byte, che presumo sia 0x6A102A21
. Questo indirizzo, penso, punta alla riga else
nella funzione main()
e reindirizziamo il controllo sovrascrivendo l'indirizzo di ritorno nello stack in base all'indirizzo di questa riga.
Sto provando a riprodurre lo stesso sulla mia macchina (architettura x86-64). Ho disattivato la protezione dello stack e la randomizzazione, quindi non penso che dovrebbe essere un problema. In effetti, il programma si blocca come previsto quando provo a danneggiare l'indirizzo di ritorno. Il mio problema è: come posso fornire come input a gets
la stringa contaminata? Se disassembro main
usando gdb, ottengo il seguente risultato:
(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.
Dato che voglio passare alla seconda chiamata puts()
, penso di dover fornire 0x0000000000400680
come parte della mia stringa tainted perché questo è l'indirizzo del secondo puts()
in base allo smontaggio di gdb.
Come posso fare questo? Nel libro, l'indirizzo era di lunghezza 8, ma qui ne ho uno di lunghezza 16. Inoltre, non esiste una rappresentazione ASCII per 0x80
, quindi cosa dovrei fornire come input a gets
? Fondamentalmente, quello che sto chiedendo sono i personaggi che dovrei fornire a ? :
1234567890123456 ????
Sono completamente confuso, quindi ogni aiuto è apprezzato, grazie!