Przyjrzałem się podstawom luk w przepełnieniu bufora i próbowałem zrozumieć, w jaki sposób działa stos. W tym celu chciałem napisać prosty program, który zmienia adres adresu zwrotnego na pewną wartość. Czy ktokolwiek może mi pomóc w określeniu wielkości wskaźnika bazowego, aby uzyskać offset od pierwszego argumentu?Zmodyfikuj adres zwrotny na stosie
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;
}
Wygenerowany kod asemblera wygląda następująco:
.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
Odpowiednia część segmentu ramy bla powinien wyglądać tak jak poniżej:
[znak retencji] [wskaźnik zasada] [adres zwrotny ]
Mam pozycję pierwszego, który ma tylko 1 bajt wielkości. Czy jest to tylko 1 bajt od wskaźnika bazowego lub rozmiar słowa, o którym mowa w http://insecure.org/stf/smashstack.html? A jak mogę poznać rozmiar wskaźnika bazowego?
+1 Rekompilacja zawsze może przenosić zmienne. Tylko dla testów OP, w tym konkretnym przypadku adres zwrotny znajduje się na '& ret + 17', co jest mało prawdopodobne, dopóki zmienne lokalne w tej funkcji nie ulegną zmianie. – ughoavgfhw
offset 17 prac. czy możesz wyjaśnić, jak to określiłeś? – fliX
@fliX W złożeniu instrukcja 'leaq -9 (% rbp),% rax' otrzymuje adres na stosie. Ponieważ jest to bajt wyrównany, a jedynym obliczeniem adresu musi być miejsce, w którym znajduje się 'ret'. Biorąc to 9 i dodając 8 dla poprzedniego 64-bitowego wskaźnika bazowego, otrzymujesz 17. – ughoavgfhw