系统未建立
分类: LINUX
2016-08-17 11:49:08
创建时间:2001-12-21
文章属性:原创
文章来源:http://xfocus.org/
文章提交:alert7 (sztcww_at_sina.com)
测试环境 redhat 6.2
本文讨论gcc的一些常用编译选项对代码的影响。当然代码变了,
它的内存布局也就会变了,随之exploit也就要做相应的变动。
gcc的编译选项实在太多,本文检了几个最常用的选项。
[alert7@redhat62 alert7]$ cat > test.c
#include
void hi(void)
{
printf("hi");
}
int main(int argc, char *argv[])
{
hi();
return 0;
}
[alert7@redhat62 alert7]$ gcc -o test test.c
[alert7@redhat62 alert7]$ wc -c test
11773 test
[alert7@redhat62 alert7]$ gdb -q test
(gdb) disass main
Dump of assembler code for function main:
0x80483e4
来看看部分的内存映象
(内存高址)
+--------+
|bffffbc4| argv的地址(即argv[0]的地址)
0xbffffb84 +--------+
|00000001| argc的值
0xbffffb80 +--------+
|400309cb|main的返回地址
0xbffffb7c +--------+ <-- 调用main函数前的esp
|bffffb98| 调用main函数前的ebp
0xbffffb78 +--------+ <-- main函数的ebp
|080483ec| hi()的返回地址
0xbffffb74 +--------+
|bffffb78| 调用hi()前的esp
0xbffffb70 +--------+
|08048450| "hi"的地址
0xbffffb6c +--------+
| ...... |
(内存低址)
leave 指令所做的操作相当于MOV ESP,EBP 然后 POP EBP
ret 指令所做的操作相当于POP EIP
With `-O', the compiler tries to reduce code size and execution time.
When you specify `-O', the two options `-fthread-jumps' and
`-fdefer-pop' are turned on
优化,减少代码大小和执行的时间
[alert7@redhat62 alert7]$ gcc -O -o test test.c
[alert7@redhat62 alert7]$ wc -c test
11757 test
[alert7@redhat62 alert7]$ gdb -q test
(gdb) disass main
Dump of assembler code for function main:
0x80483d8
在main()中,把一条jmp指令优化掉了,很显然,这条指令是可以不需要的。
在hi()中,把add $0x4,%esp优化掉了,这会不会使stack不平衡呢?
来看看部分的内存映象
(内存高址)
+--------+
|bffffbc4| argv的地址(即argv[0]的地址)
0xbffffb84 +--------+
|00000001| argc的值
0xbffffb80 +--------+
|400309cb|main的返回地址
0xbffffb7c +--------+ <-- 调用main函数前的esp
|bffffb98| 调用main函数前的ebp
0xbffffb78 +--------+ <-- main函数的ebp
|080483e0| hi()的返回地址
0xbffffb74 +--------+
|bffffb78| 调用hi()前的esp
0xbffffb70 +--------+
|08048440| "hi"的地址
0xbffffb6c +--------+
| ...... |
(内存低址)
leave 指令所做的操作相当于把MOV ESP,EBP 然后 POP EBP
看到leave指令操作了没有,先把ebp-->esp,再pop ebp,这样即使
在过程内堆栈的esp,ebp是不平衡的,但只要返回时候碰到leave指令
就会平衡了,所以把add $0x4,%esp优化掉也是没有问题的。
-O2 Optimize even more. Nearly all supported optimizations that do
not involve a space-speed tradeoff are performed. Loop unrolling
and function inlining are not done, for example. As compared to -O,
this option increases both compilation time and the performance of
the generated code.
[alert7@redhat62 alert7]$ gcc -O2 -o test test.c
[alert7@redhat62 alert7]$ wc -c test
11757 test
[alert7@redhat62 alert7]$ gdb -q test
(gdb) disass main
Dump of assembler code for function main:
0x80483d8
由于程序比较简单,再优化也没有好优化的了,所以跟-O出来的一样。
-fomit-frame-pointer
Don't keep the frame pointer in a register for functions
that don't need one. This avoids the instructions to save,
set up and restore frame pointers; it also makes an extra
register available in many functions. It also makes
debugging impossible on most machines.
忽略帧指针。这样在程序就不需要保存,安装,和恢复ebp了。这样ebp也就是一个
free的register了,在函数中就可以随便使用了。
[alert7@redhat62 alert7]$ gcc -fomit-frame-pointer -o test test.c
[alert7@redhat62 alert7]$ wc -c test
11773 test
[alert7@redhat62 alert7]$ gdb -q test
(gdb) disass main
Dump of assembler code for function main:
0x80483e0
在main()和hi()中都去掉了以下指令
push %ebp
mov %esp,%ebp//这两条指令安装
leave//这条指令恢复
来看看部分的内存映象
(内存高址)
+--------+
|bffffbc4| argv的地址(即argv[0]的地址)
0xbffffb84 +--------+
|00000001| argc的值
0xbffffb80 +--------+
|400309cb|main的返回地址
0xbffffb7c +--------+
|080483e5| hi()的返回地址
0xbffffb78 +--------+
|08048450| "hi"字符串的地址
0xbffffb74 +--------+
| ...... |
(内存低址)
没有保存上层执行环境的ebp.
-fomit-frame-pointer编译选项去掉了
push %ebp
mov %esp,%ebp//这两条指令安装
leave//这条指令恢复
-O2编译选项去掉了
add $0x4,%esp
两个加起来会不会这四条指令一起去掉,从而使stack不平衡呢?
[alert7@redhat62 alert7]$ gcc -fomit-frame-pointer -O2 -o test test.c
[alert7@redhat62 alert7]$ wc -c test
11741 test
[alert7@redhat62 alert7]$ gdb -q test
(gdb) disass main
Dump of assembler code for function main:
0x80483d8
此时就没有把add $0x4,%esp优化掉,如果优化掉的话,整个stack就
会变的不平衡,从而会导致程序出错。
-fPIC If supported for the target machine, emit position-independent
code, suitable for dynamic linking,even if branches need large
displacements.
产生位置无关代码(PIC),一般创建共享库时用到。
在x86上,PIC的代码的符号引用都是通过ebx进行操作的。
[alert7@redhat62 alert7]$ gcc -fPIC -o test test.c
[alert7@redhat62 alert7]$ wc -c test
11805 test
[alert7@redhat62 alert7]$ gdb -q test
(gdb) disass main
Dump of assembler code for function main:
0x80483f8
-static
On systems that support dynamic linking, this prevents
linking with the shared libraries. On other systems,
this option has no effect.
把一些函数都静态的编译到程序中,而无需动态链接了。
[alert7@redhat62 alert7]$ gcc -o test -static test.c
[alert7@redhat62 alert7]$ wc -c test
962808 test
[alert7@redhat62 alert7]$ gdb -q test
(gdb) disass main
Dump of assembler code for function main:
0x80481b4
抛砖引玉般简单的实例描述了下gcc常用的编译选项对代码的影响。
不正之处,还请斧正。谢谢。