0%

printf实现还隐藏了很多参数,例如%n,printf返回值是啥你知道吗?格式化字符串漏洞成因何在?这里分析Linux内核中的printf实现,而非glibc库中的标准实现(我们用的肯定是标准库咯,不过很复杂_),因为这里没有%f等浮点类型的匹配,简单一些.

Read more »

昨天又请教了熊老板关于网络安全的基本要素,当时他上课的时候听了课然后又忘记了,现在总结如下,具体含义可参考各种百科和博文(以下定义源自百度百科)

Read more »

今天方小白童鞋笔试了CVTE,遇到了很多Linux开发的问题,其实不乏有关于内核配置,boot启动分析相关试题等等,在这里主要分析一下C语言中宏定义的问题.主要侧重于实战了,具体的还是要根据标准来。我用的实验平台是ubuntu 16.04 i386。


gcc编译过程分析

gcc_program

如上图所示,上图是在《程序员自我修养》这本书里面看到的,首先头文件和源文件在预处理阶段会融合在一起,生成.i文件。然后经过编译会生成.s文件,内容是汇编语言形式,之后经过汇编过程后变成.o的目标文件,这个文件其实已经成为了机器码了,但是缺乏加载地址以及函数符号问题未解决等,最后经过和库文件等进行链接生成可执行的二进制文件。在Linux下为elf格式,Windows下为PE格式。执行的时候将由各自的加载器对可执行文件中的代码和数据等进行解析并加载至内存中相应的属性页。当然如果直接一步gcc sources -o target是看不到这些过程的,gcc会一次性完成这些操作。下面我们就来实战一下吧。测试的源代码如下,有兴趣的还可以改用++a看看结果。

1
2
3
4
5
6
7
8
9
#include <stdio.h>

#define F(x) ((x)*(x))
void main(void)
{
int a = 4;
//printf("%d\n", F(++a));
printf("%d\n", F(a++));
}

预处理

首先我们看下图的源文件,其中就是涉及到了主要矛盾,宏定义。这个在C语言中用得相当多的一个技巧。在C++中会推荐使用const。具体缘由请自行搜索。像这种运算会产生问题的地方就是将变量填充为单目运算符的时候会发生问题。
compile
接下来我们键入

1
gcc -E mocro_define.c -o mocro_define.i

define_E
我们可以看到在生在.i文件之后,最后的几行代码被改变了,其中就是define被展开了。而且gcc在.i文件中插入了大量的外部引用和声明。总计有800多行。接下来我们看怎么编译。

编译

我们键入以下命令,其中的-masm=intel选项是让生成的汇编代码为intel格式的而非AT&T格式的,个人还是习惯看intel格式的。

1
gcc -S mocro_define.i -o mocro_define.s -masm=intel

define_S
主要的部分如下图所示,其中很多.开头的都是一些符号,不必在意。程序段在开辟新的空间之后直接将4赋值给了[ebp-12],即a。然后再将它的值送到edx寄存器,之后编译器利用lea指令优化使得a++执行,而后立即回送至内存中的a。之后又使得a++执行并回送至内存中。但是注意到,imul指令执行的时候仍然用的是edxeax的值,即4*5,而ecx值虽然为6(最后的a)但是并不参与运算。最后直接将eax压栈call printf即可打印出来结果。在这里可以看出两个a++仅仅只有一个值是参与了乘法运算,详情可以参考优先级策略,可以深刻地理解编译器是如何处理这个类似a++运算符的。
define_S_main

汇编

之后我们键入以下命令继续这个过程:

1
gcc -c mocro_define.s -o mocro_define.o

define_c
我们用readelf工具可以知道已经生成了与平台相关的目标代码了,这一步gcc内部封装的是as工具,当然我们也可以单独用as命令来执行汇编过程。特别是开发asm程序的时候可能会用到。接下来进行最后的链接过程。

链接

键入以下命令并执行可执行程序:

1
2
gcc mocro_define.o -o mocro_define
./mocro_define

define_o
最后的结果就是汇编当中的代码分析过程。当然这一步也是gcc内部封装的ld工具,我们也可以手动执行,但是太麻烦,还要解决引入的库文件等问题。

总结

这篇文章主要还是从C程序的编译过程来逐步拆解分析。宏定义本身还是不严格的直接替换式地插入,对于类型检查不严格,对于表达式不计算,才会导致问题的发生。我们稍微调试一下明白了。建议还是从C语言的运算符优先级入手,分析这个过程可能容易很多,因为编译器也是遵照标准来实现的。