以下のコードは、よく知られている記事Smashing The Stack For Fun And Profitのコードです。オーバーフローコードが機能しない
void function(int a, int b, int c) {
char buffer1[5];
char buffer2[10];
int *ret;
ret = buffer1 + 12;
(*ret)+=8;
}
void main() {
int x;
x=0;
function(1,2,3);
x=1;
printf("%d\n",x);
}
私はこのコードの目標を説明しなければならないと思います。 スタックモデルは以下のとおりです。単語の下の数字は、スタック内の変数のバイト数です。だから、もし私が望む文をスキップするためにRETを書き直したいのであれば、buffer1
からRETまでのオフセットを8 + 4 = 12と計算する。アーキテクチャはx86 Linuxなので
buffer2 buffer1 BSP RET a b c
(12) (8) (4) (4) (4) (4) (4)
私は声明x=1;
をスキップして、画面上printf()
出力0
をさせたいです。
私はコードをコンパイル:
gcc stack2.c -g
とGDBでそれを実行します。
Program received signal SIGSEGV, Segmentation fault.
main() at stack2.c:17
17 x = 1;
私はLinuxの一部を使用思う:
gdb ./a.out
gdbが私にこのような結果を与えますスタックのオーバーフローを防ぐメカニズム。おそらく、LinuxはRETアドレスを別の場所に格納し、関数が返る前にスタックのRETアドレスを比較します。
メカニズムの詳細はなんですか?プログラムの出力を0
にするために、コードをどのように書き直すべきですか?
OK、逆アセンブルコードは以下の通りです.gdbの出力は、あなたのために読みやすくなっています。誰でも私に長いコードシーケンスを貼り付ける方法を教えていただけますか?私も疲れて...
Dump of assembler code for function main:
0x08048402 <+0>: push %ebp
0x08048403 <+1>: mov %esp,%ebp
0x08048405 <+3>: sub $0x10,%esp
0x08048408 <+6>: movl $0x0,-0x4(%ebp)
0x0804840f <+13>: movl $0x3,0x8(%esp)
0x08048417 <+21>: movl $0x2,0x4(%esp)
0x0804841f <+29>: movl $0x1,(%esp)
0x08048426 <+36>: call 0x80483e4 <function>
0x0804842b <+41>: movl $0x1,-0x4(%ebp)
0x08048432 <+48>: mov $0x8048520,%eax
0x08048437 <+53>: mov -0x4(%ebp),%edx
0x0804843a <+56>: mov %edx,0x4(%esp)
0x0804843e <+60>: mov %eax,(%esp)
0x08048441 <+63>: call 0x804831c <[email protected]>
0x08048446 <+68>: mov $0x0,%eax
0x0804844b <+73>: leave
0x0804844c <+74>: ret
Dump of assembler code for function function:
0x080483e4 <+0>: push %ebp
0x080483e5 <+1>: mov %esp,%ebp
0x080483e7 <+3>: sub $0x14,%esp
0x080483ea <+6>: lea -0x9(%ebp),%eax
0x080483ed <+9>: add $0x3,%eax
0x080483f0 <+12>: mov %eax,-0x4(%ebp)
0x080483f3 <+15>: mov -0x4(%ebp),%eax
0x080483f6 <+18>: mov (%eax),%eax
0x080483f8 <+20>: lea 0x8(%eax),%edx
0x080483fb <+23>: mov -0x4(%ebp),%eax
0x080483fe <+26>: mov %edx,(%eax)
0x08048400 <+28>: leave
0x08048401 <+29>: ret
私は、コードをアセンブルし、私のプログラムに関するいくつかの間違いを見つけチェックして、0x08048432 <+48>
マイナス0x0804842b <+41>
は7
アセンブリが生成されていることを確認してください。おそらく、関数がインライン展開されている可能性があります。 – kan
アセンブリコードをチェックしているので、関数がインライン化されていないことを約束します。 –
'x = 1'は8バイトのアセンブリコードを生成し、スタックは表示されたようにレイアウトされていると仮定しています(そこに他のものもあります)。アセンブリリストを追加すれば、その答えは本当に明らかになります。 – Skizz