Ich habe die Grundlagen der Pufferüberlauf-Schwachstellen untersucht und versucht zu verstehen, wie der Stack funktioniert. Dazu wollte ich ein einfaches Programm schreiben, das die Adresse der Rückadresse auf einen Wert ändert. Kann mir jemand helfen, die Größe des Basiszeigers herauszufinden, um den Offset vom ersten Argument zu bekommen?Ändern der Absenderadresse auf dem Stack
void foo(void)
{
char ret;
char *ptr;
ptr = &ret; //add some offset value here
*ptr = 0x00;
}
int main(int argc, char **argv)
{
foo();
return 1;
}
Der erzeugte Assembler-Code sieht wie folgt aus:
.file "test.c"
.text
.globl foo
.type foo, @function
foo:
.LFB0:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
leaq -9(%rbp), %rax
movq %rax, -8(%rbp)
movq -8(%rbp), %rax
movb $0, (%rax)
popq %rbp
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE0:
.size foo, .-foo
.globl main
.type main, @function
main:
.LFB1:
.cfi_startproc
pushq %rbp
.cfi_def_cfa_offset 16
.cfi_offset 6, -16
movq %rsp, %rbp
.cfi_def_cfa_register 6
subq $16, %rsp
movl %edi, -4(%rbp)
movq %rsi, -16(%rbp)
call foo
movl $1, %eax
leave
.cfi_def_cfa 7, 8
ret
.cfi_endproc
.LFE1:
.size main, .-main
.ident "GCC: (GNU) 4.7.1 20120721 (prerelease)"
.section .note.GNU-stack,"",@progbits
Der relevante Teil des foo Rahmensegments sollte wie folgt aussehen:
[char ret] [Basiszeiger] [Rückkehradresse ]
Ich habe die Position der ersten, die nur 1 Byte groß ist. Ist es nur 1 Byte weiter als der Basiszeiger oder die Größe eines Wortes wie in http://insecure.org/stf/smashstack.html erwähnt? Und wie kann ich die Größe des Basiszeigers kennenlernen?
+1 Eine Neukompilierung könnte immer Variablen verschieben. Nur für das Testen des OPs ist in diesem speziellen Fall die Rückkehradresse bei & ret + 17, was sich kaum ändern wird, solange sich die lokalen Variablen in dieser Funktion nicht ändern. – ughoavgfhw
Offset von 17 arbeitet. Kannst du erklären, wie du es bestimmt hast? – fliX
@fliX In der Assembly erhält die Anweisung 'leaq -9 (% rbp),% rax 'eine Adresse auf dem Stack. Da es Byte-ausgerichtet ist und die einzige Adressenberechnung ist, muss dies "ret" sein. Nimmt man diese 9 und addiert 8 für den vorherigen 64-Bit-Basiszeiger, erhält man 17. – ughoavgfhw