2017-05-30 4 views
0

現在、Hacking:The Art of ExploitationをJon Ericksonが読んでいます。私はマシンと32ビットと64ビットシステムの違いを研究するように強制して、本書で提供されているバーチャルマシンではなく、x64 Ubuntu 16.04.2システムのエクササイズに従っています。私は現在、本の冒頭に向かっており、スタックフレームアセンブリについて学んでいますが、これを自分のマシンで実行したときの結果については混乱していました。コードをコンパイルするためにGCCを使用する場合:スタックフレームの道を見ることがtest_functionにブレークポイントを設定するには、GDBを使用したスタックフレームアセンブリ - バッファ/ガベージスペースとスタック上の引数の場所 - Ubuntu x64

Dump of assembler code for function main: 
    0x000000000040058b <+0>:  push rbp 
    0x000000000040058c <+1>:  mov rbp,rsp 
    0x000000000040058f <+4>:  mov ecx,0x4 
    0x0000000000400594 <+9>:  mov edx,0x3 
    0x0000000000400599 <+14>: mov esi,0x2 
    0x000000000040059e <+19>: mov edi,0x1 
    0x00000000004005a3 <+24>: call 0x400546 <test_function> 
    0x00000000004005a8 <+29>: mov eax,0x0 
    0x00000000004005ad <+34>: pop rbp 
    0x00000000004005ae <+35>: ret 

Dump of assembler code for function test_function: 
    0x0000000000400546 <+0>:  push rbp 
    0x0000000000400547 <+1>:  mov rbp,rsp 
    0x000000000040054a <+4>:  sub rsp,0x40 
    0x000000000040054e <+8>:  mov DWORD PTR [rbp-0x34],edi 
    0x0000000000400551 <+11>: mov DWORD PTR [rbp-0x38],esi 
    0x0000000000400554 <+14>: mov DWORD PTR [rbp-0x3c],edx 
    0x0000000000400557 <+17>: mov DWORD PTR [rbp-0x40],ecx 
    0x000000000040055a <+20>: mov rax,QWORD PTR fs:0x28 
    0x0000000000400563 <+29>: mov QWORD PTR [rbp-0x8],rax 
    0x0000000000400567 <+33>: xor eax,eax 
    0x0000000000400569 <+35>: mov DWORD PTR [rbp-0x24],0x7a69 
    0x0000000000400570 <+42>: mov BYTE PTR [rbp-0x20],0x41 
    0x0000000000400574 <+46>: nop 
    0x0000000000400575 <+47>: mov rax,QWORD PTR [rbp-0x8] 
    0x0000000000400579 <+51>: xor rax,QWORD PTR fs:0x28 
    0x0000000000400582 <+60>: je  0x400589 <test_function+67> 
    0x0000000000400584 <+62>: call 0x400420 <[email protected]> 
    0x0000000000400589 <+67>: leave 
    0x000000000040058a <+68>: ret 

が、私はメモリを見て:

void test_function(int a, int b, int c, int d) { 
    int flag; 
    char buffer[10]; 

    flag = 31337; 
    buffer[0] = 'A'; 
} 

int main() { 
    test_function(1, 2, 3, 4); 
} 

私は、アセンブリを与えられています建設された。

(gdb) x/20hw $rsp 
0x7fffffffddd0: 0x00000004 0x00000003 0x00000002 0x00000001 
0x7fffffffdde0: 0x00000001 0x00000000 0x004005fd 0x00000000 
0x7fffffffddf0: 0x00000000 0x00000000 0x00000000 0x00000000 
0x7fffffffde00: 0x004005b0 0x00000000 0x00400450 0x00000000 
0x7fffffffde10: 0xffffde20 0x00007fff 0x004005a8 0x00000000 

とレジスタに設定されています

(gdb) i r rip rsp rbp 
rip   0x40055a 0x40055a <test_function+20> 
rsp   0x7fffffffddd0 0x7fffffffddd0 
rbp   0x7fffffffde10 0x7fffffffde10 

私の質問保存されたフレームポインタが0x7fffffffde10でありながら、なぜ0x7fffffffdddfを介してメモリアドレス0x7fffffffddd0に配置された関数への引数でされており、リターンアドレスは0x7fffffffde18にあります。私は、これらの値がメモリ内にお互いにすぐ隣に格納されると思うでしょうが、何らかの理由でコンパイラが完全な64ビットの引数を格納します。

最初は私はこれが整列の問題かもしれないと思っていました。空きスペースはバッファスペースかもしれませんが、私がオンラインで集めたものから、メモリは64ビットではなく16ビット間隔で整列する傾向があります。メモリが16ビット間隔で整列されている場合、0x7fffffffde00〜0x7fffffffde0fに引数が格納されないのはなぜですか?

さらに、リターンアドレスとパラメータの間のスペースには意味がありますか、それともちょうど迷惑データですか? 0x7fffffffdde8、0x7fffffffde00、0x7fffffffde08の値は、メモリのテキストセグメントのメモリアドレスと思われるため、少し面白いようですが、スタックの一般的に使用されているセグメントにバッファスペースを割り当てることの結果である可能性もあります。

+2

語るので、コンパイラは賢明な何かをしようとしません。それは単なる便利なところにものを置くだけです。 –

答えて

0

「赤いゾーン」が表示される可能性があります。

https://stackoverflow.com/tags/x86/infoで、タグのwikiは、偉大なリンクをたくさん持っているhttps://github.com/hjl-tools/x86-psABI/wiki/x86-64-psABI-r252.pdf

を参照してください。

そして、これはあなたが上の最適化でコンパイルしていないレッドゾーンhttps://softwareengineering.stackexchange.com/questions/230089/what-is-the-purpose-of-red-zone

+0

また、私は、空き領域の大部分を占めるtest_functionにいくつかの変数を定義していることに気付きました。 – user2985955

+1

コードは赤いゾーンを使用していません。スタック上のすべてがスタックポインタの上にあります。 –

関連する問題