スタックは通常、同じアドレスで始まるので、攻撃者はバッファの開始点を推測してオーバーフローする可能性があることを読みました。これは、悪意のあるコードを実行するためにこのアドレスを知るために必要です。数行のコードでプログラムを作成し、起動するたびにスタックポインタのアドレスを取得して画面に出力しました。
int * get_stack_pointer(){
__asm__("mov %esp,%eax");
}
void main(){
printf("Address: %p\n",get_stack_pointer());
}
そして、これはプログラムの逆アセンブルです:
<get_stack_pointer>:
Push %rbp
mov %rsp,%rbp
mov %esp,%eax
pop %rbp
retq
<main>:
Push %rbp
mov %rsp,%rbp
mov $0x0,%eax
callq 40050c <get_stack_pointer>
mov %rax,%rsi
mov $0x4005ec,%edi
mov $0x0,%eax
callq 4003e0 <printf@plt>
pop %rbp
retq
しかし、プログラムを開始するたびに、異なるアドレスを取得します。これらの一部は次のとおりです。
Address: 0xc31b2c80
Address: 0x2e041e0
Address: 0x7b003190
Address: 0xb3fd1350
では、この場合、攻撃者はどのようにして脆弱なプログラムでコードを実行することができるのでしょうか。 (私のOSはLinux 64ビットです)
編集:いくつかの単純な行を含む別のプログラムをアセンブリで作成しました。デバッガーで起動するたびにRSPの値を確認するだけで、RSPの値は常に同じですが、cで記述されたプログラムではありません。
問題は [〜#〜] aslr [〜#〜] プログラムがロードされる場所をランダムに選択することです。 LinuxでASLRをオフにするには、Sudo sysctl -w kernel.randomiz_va_space=0
を使用します。
これが私のプログラムです。 EAXの代わりにRAXを使用しており、unsigned long *
ではなくint *
を使用しています。
#include <stdio.h>
#include <stdlib.h>
unsigned long *get_stack_ptr(void) {
__asm__(
"mov %rsp, %rax"
);
}
int main(int argc, char **argv) {
unsigned long *stack_ptr = get_stack_ptr();
printf("Size Of Ptr: %d bytes\n", sizeof(unsigned long *));
printf("Stack Pointer: %llX\n", stack_ptr);
return 0;
}
ASLRでの私のプログラムは次のとおりです。
@narrator:$ ./stackptr
Size Of Ptr: 8 bytes
Stack Pointer: 7FFD328233D0
@narrator:$ ./stackptr
Size Of Ptr: 8 bytes
Stack Pointer: 7FFC2B5F07E0
@narrator:$ ./stackptr
Size Of Ptr: 8 bytes
Stack Pointer: 7FFFE3A2FF10
@narrator:$ ./stackptr
Size Of Ptr: 8 bytes
Stack Pointer: 7FFE5F0795F0
今私は実行します:Sudo sysctl -w kernel.randomize_va_space=0
ASLRなしの私のプログラムは次のとおりです。
@narrator:$ ./stackptr
Size Of Ptr: 8 bytes
Stack Pointer: 7FFFFFFFDF70
@narrator:$ ./stackptr
Size Of Ptr: 8 bytes
Stack Pointer: 7FFFFFFFDF70
@narrator:$ ./stackptr
Size Of Ptr: 8 bytes
Stack Pointer: 7FFFFFFFDF70
@narrator:$ ./stackptr
Size Of Ptr: 8 bytes
Stack Pointer: 7FFFFFFFDF70