私は、学生のためのバッファオーバーフロー演習をcに書こうとしています。ebxが単純な関数のスタックフレームに保存されるのはなぜですか?
通常、スタックフレームは、関数パラメータ、リターンアドレス、ベースポインタ、およびローカル変数で構成されます。しかし、私は、時には追加のレジスタがベースポインタと共に保存されることを検出しました。私はクラスから、保存されたレジスタを使用する前に保存しなければならないことを覚えています。しかし、Cコードをコンパイルするとアセンブラが生成され、目的を持たずにレジスタを節約して使用するケースがあります。この行動を私に説明してください。
私はgdbの
break func
run
info frame
で生成される実行可能ファイルをデバッグする場合はすべてがうまくされ、スタックフレームのみEBPが含まれている主な機能
int main (int argc, char** argv) {
func();
return 0;
}
と機能
void func() {
char buf[5];
strcpy(buf,"AAAA");
strcpy(buf,"BBBB");
}
を想定およびeip。
私はそうEBXは、さらに、スタックフレームに保存されている
Saved registers:
ebx at 0xffffd1cc, ebp at 0xffffd1d0, eip at 0xffffd1d4
を取得し、私は
void func() {
char buf[5];
gets(buf);
}
を使用している場合は?どうして?私は
disas func
を実行すると、私はそうEBXが保存されている
Dump of assembler code for function func:
0x56555730 <+0>: push %ebp
0x56555731 <+1>: mov %esp,%ebp
0x56555733 <+3>: push %ebx
0x56555734 <+4>: sub $0x8,%esp
0x56555737 <+7>: call 0x5655576e <__x86.get_pc_thunk.ax>
0x5655573c <+12>: add $0x18c4,%eax
=> 0x56555741 <+17>: lea -0x9(%ebp),%edx
0x56555744 <+20>: push %edx
0x56555745 <+21>: mov %eax,%ebx
0x56555747 <+23>: call 0x56555590 <[email protected]>
0x5655574c <+28>: add $0x4,%esp
0x5655574f <+31>: nop
0x56555750 <+32>: mov -0x4(%ebp),%ebx
0x56555753 <+35>: leave
0x56555754 <+36>: ret
End of assembler dump.
を取得します。 OK。しかし、それは何のために使われていますか? eaxはgets()を呼び出す前にebxで移動します。しかし、その後は使用されません。古いebxはスタックから復元され、退室して戻ってきます。それは役に立たないようです。 Btw。 call get_pc_thunk
ものは何ですか?
同等の振る舞い私はprintfの使用の代わりになれば、:
void func() {
char buf[5];
strcpy(buf, "AAAA");
printf("%s",buf);
}
gdbの出力:
(gdb) info frame
Stack level 0, frame at 0xffffd1d8:
eip = 0x56555741 in func (/home/mischa/stuff/test/test.c:35); saved eip = 0x56555779
called by frame at 0xffffd1e0
source language c.
Arglist at 0xffffd1d0, args:
Locals at 0xffffd1d0, Previous frame's sp is 0xffffd1d8
Saved registers:
ebx at 0xffffd1cc, ebp at 0xffffd1d0, eip at 0xffffd1d4
(gdb) disas func
Dump of assembler code for function func:
0x56555730 <+0>: push %ebp
0x56555731 <+1>: mov %esp,%ebp
0x56555733 <+3>: push %ebx
0x56555734 <+4>: sub $0x8,%esp
0x56555737 <+7>: call 0x56555780 <__x86.get_pc_thunk.ax>
0x5655573c <+12>: add $0x18c4,%eax
=> 0x56555741 <+17>: movl $0x41414141,-0x9(%ebp)
0x56555748 <+24>: movb $0x0,-0x5(%ebp)
0x5655574c <+28>: lea -0x9(%ebp),%edx
0x5655574f <+31>: push %edx
0x56555750 <+32>: lea -0x17f0(%eax),%edx
0x56555756 <+38>: push %edx
0x56555757 <+39>: mov %eax,%ebx
0x56555759 <+41>: call 0x565555a0 <[email protected]>
0x5655575e <+46>: add $0x8,%esp
0x56555761 <+49>: nop
0x56555762 <+50>: mov -0x4(%ebp),%ebx
0x56555765 <+53>: leave
0x56555766 <+54>: ret
End of assembler dump.
を誰かが私にこれを説明していただけますか?
私は、次のCMakeLists.txtをコンパイルするためにcmakeを使用します。
cmake_minimum_required (VERSION 2.8)
# projectname is the same as the main-executable
project(test)
# compile with 32 bit
add_definitions('-m32')
# Disable compiler optimization
add_definitions('-O0')
# include debugging information
add_definitions('-g')
# Align items on the stack to 4 bytes. This makes stuff easier.
# See https://stackoverflow.com/questions/1061818/stack-allocation-padding-and-alignment
add_definitions('-mpreferred-stack-boundary=2')
# disable compiler buffer overflow protection
add_definitions('-z execstack -z norelro -fno-stack-protector')
# executable source code
add_executable(test test.c)
cmakeのは、GCCを使用しているようです。
最適化を無効にしたためですか? –
'ebx'はGOTへのポインタとして使われますが、実際には位置独立コードにのみ関係します。それは、それをあなたがそれほどコンパイルしたかどうか、あなたのcmakeのものからは明らかではありません。振る舞いを再現するためには、 '-fPIC'コマンドラインオプションを' gcc'に渡さなければなりませんでした。 – Jester
'strcpy(buf、" AAAA ");は' movl'の後ろに 'movb'がインライン化されているので、実行する関数はまったく呼び出されません。 (最後の分解で指摘されたコードを参照してください) – rici