各种小巧的Hello World
发布日期:2021-08-12 02:36:33 浏览次数:4 分类:技术文章

本文共 1945 字,大约阅读时间需要 6 分钟。

在Reddit看到这篇文章: ,觉得挺有趣,然后又想起以前看过的各种相关资料,在此做一个整理。注意所有实验环境都为Linux。

版本一:

实际上是用汇编重写_start入口,具体说明请看文章开头提供的连接,汇编代码如下,命名为stubstart.S

 

[cpp]
  1. _start:  
  2.     call main  
  3.     movl $1, %eax  
  4.     xorl %ebx, %ebx  
  5.     int $0x80  
然后与普通hello.c连接(hello.c)的代码我就不用写出来了吧。。命令如下:
gcc -nostdlib stubstart.S -o hello hello.c
OK,一个不需要libc的helloworld程序就完成了。只是简单的跳过了_start的各种初始化

版本二:

与版本一其实差不多,只是用shellcode来完成了,代码如下
[cpp]
  1. typedef int (*sc_fun)(int,int,int,int,int,int,int);  
  2.   
  3. void _start(void) {  
  4.   
  5.     char syscall[] = "/x60/x83/xc4/x24/x58/x5b/x59/x5a/x5e/x5f/x5d/xcd/x80/x83/xec/x40/x61/xc3";  
  6.   
  7.     ((sc_fun)syscall)(4, 0, "Hello, World/n", 13, 0, 0, 0);  
  8.   
  9.     ((sc_fun)syscall)(1, 0, 0, 0, 0, 0, 0);  
  10.   
  11. }  
连接命令如下:
gcc -o nostdlib hello.c -m32 -z execstack –nostdlib
嗯,完成了,也是-nostdlib,至于shellcode调用的是什么系统函数,我猜是write吧:)

版本三:

[cpp]
  1. char *str = "Hello world!/n";  
  2. void print()  
  3. {  
  4.     asm( "movl $13, %%edx /n/t"  
  5.         "movl %0, %%ecx /n/t"  
  6.         "movl $0, %%ebx /n/t"  
  7.         "movl $4, %%eax /n/t"  
  8.         "int $0x80 /n/t"  
  9.         :: "r"(str):"edx","ecx","ebx");  
  10. }  
  11. void exit()  
  12. {  
  13.     asm( "movl $42,%ebx /n/t"  
  14.          "movl $1,%eax /n/t"  
  15.          "int $0x80 /n/t");  
  16. }  
  17. void nomain()  
  18. {  
  19.     print();  
  20.     exit();  
  21. }  

关于gcc内联汇编,可参考下相关书籍,代码大概意思是nomain()是入口,然后调用print()函数,打印"Hello world”,接着调用exit()函数,结束进程。这里的print函数使用了Linux的WRITE系统调用,exit使用了EXIT系统调用,都是用内联汇编实现。

连接命令如下:

gcc –c hello.c

ld –static –e nomain –o hello hello.o

注意,这里控制了连接器的行为,用-e指定了入口函数为nomain

版本四:

接着版本三,我们用objdump来查看hello,会发现他有四个段:.text .rodata .data .comment。

那么可不可以把他们都合并到一个段里面,该段的属性是可执行,可读的,包含程序的数据和指令? 可以的,此时需要使用ld连接脚本创建脚本hello.lds如下:

[c-sharp]
  1. ENTRY(nomain)  
  2. SECTIONS  
  3. {  
  4.     . = 0x804800 + SIZEOF_HEADERS;  
  5.     tinytext : { *(.text) *(.data) *(.rodata) }  
  6.     /DISCARD/ : { *(.comment) }  
  7. }  

这是很简单的连接脚本,就是设置当前位置0x804800 + SIZEOF_HEADERS,后面紧跟着tinytext段,没有其他段了。使用入下命令连接

gcc –c  hello.c

ld –static – T hello.lds –o hello hello.o

OK,一个更小巧的HelloWorld完成了。

版本五:

版本四是最小的了吗?差远了。。。早就有人专门研究过最小的可执行文件了,从ELF文件的各个字节下手。。点这里: 。。很牛B,很geek的东西。。理论上那就是最小的可执行文件了。

 

以上各个版本的helloworld大小,自己生成后用wc –c hello看吧:)。再配合objdump能学到更多~

转载于:https://www.cnblogs.com/SZLLQ2000/p/5110005.html

转载地址:https://blog.csdn.net/weixin_30642561/article/details/97319261 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:跨时钟域设计的一点总结
下一篇:Android多线程(一)

发表评论

最新留言

做的很好,不错不错
[***.243.131.199]2024年03月30日 05时14分45秒

关于作者

    喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!

推荐文章