编写一个最小的ELF程序
介绍
最近分析的都是ELF文件,正好通过自己DIY一个ELF分析结构。
顺便复习一遍之前读过的《程序员的自我修养》 内容。(没读过的朋友想学习ELF相关知识,这本书很有必要学习,能实现书中的实验最好了,很有难度的哦。)
实验程序
- 汇编代码采用 AT&T 格式
这里采用 GCC 内置汇编代码的编写来避免 libc 中自带的库函数代码。
char *str="HELLO\n";
void print(){
asm(
"movl $6,%%edx \n\t" //edx = 6
"movl %0,%%ecx \n\t" //ecx = %0代表任意寄存器
"movl $0,%%ebx \n\t" //ebx = 0
"movl $4,%%eax \n\t" //eax = 4
"int $0x80 \n\t" //系统调用号
::"r"(str):"edx","ecx","ebx" // 输出r(任何通用寄存器)=str,输入edx,ecx,ebx
);
}
void exit(){
asm(
"movl $42,%ebx \n\t"
"movl $1,%eax \n\t"
"int $0x80 \n\t"
);
}
void nomain(){
print();
exit();
}
参考:内联汇编_AT&T语法
编译
gcc -c -m32 -fno-builtin tiny.c
ld -m elf_i386 -static -e nomain -o tiny tiny.o
参考:https://blog.csdn.net/neuq_jtxw007/article/details/78112672
编译链接后文件大小:
查看自动生成的段
-
b9 个段,首先 text 、rodata、data 这三个段可能是需要的,我们可以把他合成为一个段(代码和数据混合),这样就可以缩减描述各自属性段的字节大小。eh_frame 和 comment 可以直接去除。
-
eh_frame 是用于调试的段,没有这个段在 gdb 中调试会出错。
魔改整合ELF段,自定义ld脚本
ENTRY(nomain)
SECTIONS{
. = 0x8048000+SIZEOF_HEADERS;
tinytext : { *(.text) *(.data) *(.nodata) }
/DISCARD/ : { *(.comment) *(.eh_frame)}
}
了解.lds脚本语法学习参考:
https://www.cnblogs.com/li-hao/p/4107964.html
重新编译:
gcc -m32 -c ./tiny.c -fno-builtin -o tiny.o
ld -static -m elf_i386 -T tiny.lds ./tiny.o -o tiny
注:
-fno-builtin 用来关闭GCC内置函数(built-in function)优化功能。
-T 指定链接控制脚本;
-e 是指定程序入口函数为nomain();
-static 表示ld是静态链接的方式链接程序,而不是用默认的动态链接方式;
-o 表示指定输出文件名为”tiny”;(output)
魔改效果: