1.自己的尝试
试着写了个最小的ELF程序,如下:
my_tiny.c:
/*
* my_tiny.c
* gcc -c -o my_tiny.o my_tiny.c
* 调用exit系统调用,返回退出码42
*/
void start()
{
__asm__("int $0x80"
::"a"(1),"b"(42):);
}
ld链接脚本,my_tiny.lds:
ENTRY(start)
SECTIONS
{
. = 0x08048000 + SIZEOF_HEADERS;
.text : { *(.text) }
/DISCARD/ : { *(.bss) *(.data) *(.rodata) *(.note.GNU-stack) }
/DISCARD/ : { *(.comment) }
}
Makefile:
my_tiny:my_tiny.o
ld -static -T my_tiny.lds -o my_tiny my_tiny.o
strip my_tiny
my_tiny.o:my_tiny.c
gcc -c -o my_tiny.o my_tiny.c
clean:
rm -f my_tiny my_tiny.o
运行看看
Eruda@chobits[tinyt]$ make
gcc -c -o my_tiny.o my_tiny.c
ld -static -T my_tiny.lds -o my_tiny my_tiny.o
strip my_tiny
Eruda@chobits[tinyt]$ ./my_tiny
查看程序运行返回结果
Eruda@chobits[tinyt]$ echo $?
42
看看ELF程序大小:
Eruda@chobits[tinyt]$ wc -c my_tiny
276 my_tiny
276 bytes!这个是正常处理下我能得到小ELF程序了,也没使用什么技巧。
2.他人的作品
我们来看看目前最小的ELF程序是怎么做的:
http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html
看到了吗?作者从91 bytes 压缩到 45 bytes 采用了多么 hacking 的手法!真是太极限了!!
3.改造成GNU风格
这里作者借用了nasm中的“古老”功能 -f bin 直接产生二进制文件,着实方便。
可是gnu编译链接工具链中却没有工具能直接将(非正常程序)汇编生成纯二进制码(不加编译链接生成的一些附加段)。
但是我们可以采用一个方法欺骗下gnu编译链接工具,让它帮我们生成“纯”二进制文件。Lets hacking!!
tiny.s:
Makefile:
tiny:tiny.o
ld -e_begin -Ttext=0x1000 --oformat binary -o tiny tiny.o
tiny.o:tiny.s
as -o tiny.o tiny.s
clean:
rm -f tiny.o tiny
欺骗下as,让他把我们的程序的2进制码都放在.text段内
并让ld把.text段生成2进制码
Eruda@chobits[test]$ make
as -o tiny.o tiny.s
ld -e_begin -Ttext=0x1000 --oformat binary -o tiny tiny.o
Eruda@chobits[test]$ ./tiny ;echo $? [:(]
42
Eruda@chobits[test]$ wc -c ./tiny
45 ./tiny
Eruda@chobits[test]$ hexdump -C ./tiny
00000000 7f 45 4c 46 01 00 00 00 00 00 00 00 00 10 00 00 |.ELF............|
00000010 02 00 03 00 20 10 00 00 20 10 00 00 04 00 00 00 |.... ... .......|
00000020 b3 2a 31 c0 40 cd 80 00 34 00 20 00 01 |.*1.@...4. ..|
0000002d
果然是45字节,不知道何时能够再hacking到更小?
---------------------------------------------------------------------------------------------------
[:(]你可能会遇到这样的情况:
Eruda@chobits[test]$ ./tiny
Killed
紧接着selinux报错:SELinux is preventing tiny access to a leaked <Unknown> file descriptor.
解决方法:
Eruda@chobits[test]$ sudo vim /etc/selinux/config
修改"SELINUX=enforcing"为"SELINUX=disabled"
然后手动关闭selinux
Eruda@chobits[test]$ sudo setenforce 0