小型elf Hello,World程序

参考链接:http://timelessname.com/elfbin/

 

环境要求:linux gcc nasm hexcurse(用来修改elf文件内容)

 

先尝试用C语言写"Hello,World"程序(名为chello.c):

 

#include <stdio.h>
int main(void)
{printf("Hello,World\n");return 0;
}
 

使用下面命令编译并运行:

 

[host@myhost linker]$ gcc -o chello chello.c
[host@myhost linker]$ ./chello

 输出结果:

 

Hello,World

 可以用下面命令查看chello的ELF头部分:

 

readelf -h chello

 输出结果:

 

ELF Header:Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 Class:                             ELF32Data:                              2's complement, little endianVersion:                           1 (current)OS/ABI:                            UNIX - System VABI Version:                       0Type:                              EXEC (Executable file)Machine:                           Intel 80386Version:                           0x1Entry point address:               0x8048310Start of program headers:          52 (bytes into file)Start of section headers:          1932 (bytes into file)Flags:                             0x0Size of this header:               52 (bytes)Size of program headers:           32 (bytes)Number of program headers:         8Size of section headers:           40 (bytes)Number of section headers:         30Section header string table index: 27

 使用下面命令查看chello链接的动态链接库:

 

ldd chello

  输出结果为:

 

	linux-gate.so.1 =>  (0xb7857000)libc.so.6 => /lib/libc.so.6 (0xb76d2000)/lib/ld-linux.so.2 (0xb7858000)

  使用下面命令查看文件类型:

 

file chello

  输出结果:

 

chello: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.27, not stripped

  使用下面命令查看文件大小,并使用strip取出符号表,然后查看文件大小:

 

[host@myhost linker]$ ls -l chello
[host@myhost linker]$ strip -s chello
[host@myhost linker]$ ls -l chello
 

 输出结果为:

 

-rwxr-xr-x 1 host users 4746 11月  6 23:07 chello
-rwxr-xr-x 1 host users 3036 11月  6 23:15 chello

 

下面使用汇编代码编写该程序(hello.asm),调用linux中断来实现:

 

	SECTION .data
msg:	db "Hello,World",10
len:	equ $-msgSECTION .textglobal main
main:mov edx,lenmov ecx,msgmov ebx,1mov eax,4int 0x80mov ebx,0mov eax,1int 0x80

 使用下面的命令编译链接并取出生成文件的符号表:

 

[host@myhost linker]$ nasm -f elf hello.asm
[host@myhost linker]$ gcc -o hello hello.o -nostartfiles -nostdlib -nodefaultlibs
[host@myhost linker]$ strip -s hello
[host@myhost linker]$ ./hello

 输出结果为:

 

/usr/bin/ld: warning: cannot find entry symbol _start; defaulting to 08048080
Hello,World

 再用gcc命令时会产生一个警告,但该文件仍然能够执行。此时文件大小为360个字节。

此处链接命令“gcc -o hello hello.o -nostartfiles -nostdlib -nodefaultlibs"中几个选项英文注解如下(链接 ):

 

-nostartfilesDo not use the standard system startup files when linking. The standard system libraries are used normally, unless -nostdlib or -nodefaultlibs is used.
-nodefaultlibsDo not use the standard system libraries when linking. Only the libraries you specify will be passed to the linker, options specifying linkage of the system libraries, such as -static-libgcc or -shared-libgcc, will be ignored. The standard startup files are used normally, unless -nostartfiles is used. The compiler may generate calls to memcmp, memset, memcpy and memmove. These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified.
-nostdlibDo not use the standard system startup files or libraries when linking. No startup files and only the libraries you specify will be passed to the linker, options specifying linkage of the system libraries, such as -static-libgcc or -shared-libgcc, will be ignored. The compiler may generate calls to memcmp, memset, memcpy and memmove. These entries are usually resolved by entries in libc. These entry points should be supplied through some other mechanism when this option is specified.One of the standard libraries bypassed by -nostdlib and -nodefaultlibs is libgcc.a, a library of internal subroutines that GCC uses to overcome shortcomings of particular machines, or special needs for some languages. (See Interfacing to GCC Output, for more discussion of libgcc.a.) In most cases, you need libgcc.a even when you want to avoid other standard libraries. In other words, when you specify -nostdlib or -nodefaultlibs you should usually specify -lgcc as well. This ensures that you have no unresolved references to internal GCC library subroutines. (For example, `__main', used to ensure C++ constructors will be called;

  此处startupfiles指的是crt0.o(/lib/crt0.o),crtbegin.o,crtend.o。据说crt0.o包含调用main函数(windows下调用WinMainCRTStartup (参考链接 ))的代码,这里使用汇编代码(如果是c程序,则需要链接crt0.o),所以不用链接crt0.o.crtbegin.o和crtend.o据说是用来对c++构造和析构函数进行处理。有一个帖子(Is main required for a c program? also see Why are DJGPP .exe files so large? )说明了不用main函数来编写c程序(其实只是把入口名称换换而已,就像Window应用程序使用WinMain来作为入口函数,只不过使用自己的入口函数,相关的一些处理都需要自己来解决)

使用下面命令得到hello的16进制描述:

 

hexdump -x hello

 输出结果:

 

0000000    457f    464c    0101    0001    0000    0000    0000    0000
0000010    0002    0003    0001    0000    8080    0804    0034    0000
0000020    00c8    0000    0000    0000    0034    0020    0002    0028
0000030    0004    0003    0001    0000    0000    0000    8000    0804
0000040    8000    0804    00a2    0000    00a2    0000    0005    0000
0000050    1000    0000    0001    0000    00a4    0000    90a4    0804
0000060    90a4    0804    000c    0000    000c    0000    0006    0000
0000070    1000    0000    0000    0000    0000    0000    0000    0000
0000080    0cba    0000    b900    90a4    0804    01bb    0000    b800
0000090    0004    0000    80cd    00bb    0000    b800    0001    0000
00000a0    80cd    0000    6548    6c6c    2c6f    6f57    6c72    0a64
00000b0    2e00    6873    7473    7472    6261    2e00    6574    7478
00000c0    2e00    6164    6174    0000    0000    0000    0000    0000
00000d0    0000    0000    0000    0000    0000    0000    0000    0000
*
00000f0    000b    0000    0001    0000    0006    0000    8080    0804
0000100    0080    0000    0022    0000    0000    0000    0000    0000
0000110    0010    0000    0000    0000    0011    0000    0001    0000
0000120    0003    0000    90a4    0804    00a4    0000    000c    0000
0000130    0000    0000    0000    0000    0004    0000    0000    0000
0000140    0001    0000    0003    0000    0000    0000    0000    0000
0000150    00b0    0000    0017    0000    0000    0000    0000    0000
0000160    0001    0000    0000    0000 
 

 分析该文件头(前52个字节)可以知道两个比较重要表的内容,第一个是程序头表(54(0x34)个字节开始,大小为2*32(0x20)个字节),另一个是段头表(200(0xc8)个字节开始,大小为2*40(0x28)个字节),然后根据段头表可以知道代码段(0x80开始34个字节内容)和数据段(0xa4开始12个字节内容)相关信息。比较重要的是前176个字节内容,这部分内容可以分为文件头(52个字节),程序头表(64个字节),空白内容(12个字节),代码段(34个字节),数据段(12个字节,"Hello,World\n")。

先使用下面命令提取hello中前176个字节内容修改权限为可执行:

 

dd if=hello of=hello.new bs=176 count=1
chmod u+x hello.new 

 得到文件hello.new,执行该文件可以得到"Hello,World".该文件二进制内容:

 

0000000    457f    464c    0101    0001    0000    0000    0000    0000
0000010    0002    0003    0001    0000    8080    0804    0034    0000
0000020    00c8    0000    0000    0000    0034    0020    0002    0028
0000030    0004    0003    0001    0000    0000    0000    8000    0804
0000040    8000    0804    00a2    0000    00a2    0000    0005    0000
0000050    1000    0000    0001    0000    00a4    0000    90a4    0804
0000060    90a4    0804    000c    0000    000c    0000    0006    0000
0000070    1000    0000    0000    0000    0000    0000    0000    0000
0000080    0cba    0000    b900    90a4    0804    01bb    0000    b800
0000090    0004    0000    80cd    00bb    0000    b800    0001    0000
00000a0    80cd    0000    6548    6c6c    2c6f    6f57    6c72    0a64
  

由于数据段大小刚好为12,而文件中有刚好有12个字节空白,可以将数据段(0xa4开始的12个字解)迁移到空白处(0x74开始的12个字节),并将0x86地址的0xa4改为0x74。可以使用hexcurse hello.new修改文件内容,然后用快捷键crtl+s保存,并改名为hello.res.此时执行hello.res可以得到"Hello,World"。

然后我们可以删除最后的12个字节(使用命令dd if=hello.res of=hello.out bs=164 count=1),得到hello.out即为最后的结果,其大小为164个字节。按照原文中描述,该文件应该可以进一步的压缩,不过这需要对代码段中部分做一些改动,有空时再详细研究)

 

linux进程内存布局

而文件头中还有一个e_entry(0x18地址开始的4个字节,值为0x08048080(0x08048000+0x80(代码段偏移地址))表示程序入口,即从这个地址开始执行指令。代码段中(0x86开始的4个字节(小端法表示,9074 0804)即0x08049074,这个地址是0x08048000+0x1000(代码段虚拟地址所占的空间大小,因为段对齐为0x1000,所以最小为4k大小(分页机制中每个页面的大小))+0x74,这个地址是从原来的地址0x080490a4(这个地址也分别存在于原来的0x0000005c和0x00000060开始的4个字节。但是好像0x0000005c和0x00000060中的值不改业能正常运行,但为了使得数据保持一致,最好还是改掉。)。

另外,hello.out只包含ELF头,程序头,代码段和数据段,并且仍然能正常运行,这也证明了可执行文件中段头表(section Header table)是可选项。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/545990.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spearman相关性_Spearman的相关性及其在机器学习中的意义

spearman相关性This article is about correlation and its implication in the machine learning. In my previous article, I have discussed Pearson’s correlation coefficient and later we have written a code to show the usefulness of finding Pearson’s correlati…

[java] 找出字符串中出现最多的字符和出现的次数

逛园子看到一童鞋做的华为上机题目&#xff0c;写来好长的代码&#xff0c;懒得看&#xff0c;感觉不可能这么难&#xff0c;于是动手敲了下。 import java.util.Scanner;public class StringTest {/*** param args*/public static void main(String[] args) {// TODO Auto-gen…

WIN7开启WIFI

开启windows 7的隐藏功能&#xff1a;虚拟WiFi和SoftAP&#xff08;即虚拟无线AP&#xff09;&#xff0c;就可以让电脑变成无线路由器&#xff0c;实现共享上网&#xff0c;节省网费和路由器购买费。主机设置如下&#xff1a; 【第一步】开始->在搜索栏中输入‘CMD’->右…

被问哭了,一位小姐姐的阿里面经!(附部分答案)

这篇文章是一位 女读者 &#xff08;加粗&#xff01;太难得&#xff09;的面试阿里的经历分享&#xff0c;虽然第二面就失败了&#xff0c;但是这样的经历对自己帮助应该还是很大的。下面的一些问题非常具有代表性&#xff0c;部分问题我简单做了修改&#xff08;有些问题表述…

Python程序不使用函数将字符大写

In this article, we will go for capitalizing the characters i.e. conversion from lowercase to uppercase without using any function. This article is based on the concept that how inbuilt function perform this task for us? 在本文中&#xff0c;我们将大写字符…

C语言,你真的弄懂了么?

程序&#xff08;来源 &#xff09;&#xff1a; #include <stdio.h>int main(void) {int x[4];printf("%p\n", (void*) (x));printf("%p\n", (void*) (x 1));printf("%p\n", (void*) (&x));printf("%p\n", (void*) (&…

Oracle自增序列

SQL Server中数据库可以自增字段&#xff0c;但是Oracle中没有这个选项&#xff0c;实际应用中我们可以使用序列(Sequence)实现想要的功能。创建Sequence语法如下&#xff1a;CREATE SEQUENCE SEQUENCE_NAME? START WITH 1 --从 1 开始INCREMENT BY 1 --每次增加 1NOMA…

阿里《Java开发手册》最新嵩山版发布!

《Java 开发手册》是阿里巴巴集团技术团队的集体智慧结晶和经验总结&#xff0c;经历了多次大规模一线实战的检验及不断完善&#xff0c;公开到业界后&#xff0c;众多社区开发者踊跃参与&#xff0c;共同打磨完善&#xff0c;系统化地整理成册&#xff0c;当前的版本是嵩山版。…

递归转化成非递归过程_8086微处理器中的递归和重入过程

递归转化成非递归过程As we all know that a procedure is a set of instruction written separately which can be used any time in the code when required. A normal procedure execution includes calling of the procedure, shifting the control of the processor to th…

the development of c language(转)

c语言之父Dennis Ritchie 写的关于c语言开发历史的文章&#xff0c;来自这里 lisp专家Richard P.Gabriel 的《the Rise of Worse is Better 》&#xff08;wikipedia入口 &#xff0c;c2入口 &#xff0c;《Worse is Better 》&#xff0c;《软件开发宗旨 》&#xff09;中也…

漫谈软件研发特种部队之中的一个

特种部队&#xff0c;是指进行特殊任务的部队&#xff0c;具有编制灵活、人员精干、装备精良、机动高速、训练有素、战斗力强等特点。 特种部队最早出如今二战期间。德国于1939年9月1日的波兰战役中首次投入了一种被称为“勃兰登堡”部队的特种部队作为德国突击波兰的先锋&…

Oracle创建用户和授权

在OracleXE中创建scott用户1、打开SQL*Plus&#xff0c;以 sys用户登录数据库connect / as sysdba2、依次执行下面命令--DROP USER scott CASCADE;CREATE USER scott IDENTIFIED BY tiger;GRANT connect,resource TO scott;GRANT CREATE DATABASE LINK, CREATE MATERIALIZED VI…

不要一把梭了,这才是SQL优化的正确姿势!|原创干货

这是我的第 83 篇原创文章作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;年少不知优化苦&#xff0c;遇坑方知优化难。——村口王大爷全文内容预览&#xff1a;我之前有很多…

PLSQL_性能优化系列10_Oracle Array数据组优化

2014-09-25 Created By BaoXinjian 一、摘要 集合是Oracle开发中经常遇到的情况&#xff0c;Oracle集合分为三种情况&#xff1a;索引表集合(index by table)、嵌套表集合(nested table)、可变集合(varry table)。 PL/SQL中没有数组的概念&#xff0c;他的集合数据类型和数组是…

最小c编译器

最小c编译器&#xff08;来源 &#xff08;最好在linux下操作&#xff09;&#xff09;代码有好几个版本&#xff0c;我选择otccelfn.c 。 /*Obfuscated Tiny C Compiler with ELF outputCopyright (C) 2001-2003 Fabrice BellardThis software is provided as-is, without any…

在Java中使用Collat​​or和String类进行字符串比较

Given two strings and we have to compare them using Collator and String classed in Java. 给定两个字符串&#xff0c;我们必须使用Java中分类的Collat​​or和String进行比较。 Using Collator class – to compare two strings, we use compare() method – it returns…

Oracle数据库中表格的级联删除问题

数据库表中没有设置级联删除.怎样用SQL语句实现:如:EMP表中有字段DEPT_NO是外键POS表中有字段DEPT_NO是外键DEPT表中有字段DEPT_NO,如何实现删除DEPT表中数据时将EMP表,POS表中的相关数据也删除;这里有两种方法&#xff1a;方法一&#xff1a;触发器解决create or replace trig…

IDEA 2020.2 重磅发布,动画级新功能预览!

Guide 关注了 IDEA 的官推&#xff0c;平时没事就会去看看有没有啥比较好的更新。今天下午看到IntelliJ IDEA 2020.2 都已经发布并且还支持了 Java15。然后&#xff0c;我就去官网简单看了一下新特性。单看新特性&#xff0c;这个新版本还是有一点香的。虽然我还木有升级到这个…

访问控制模型ACL和RBAC

2019独角兽企业重金招聘Python工程师标准>>> 1.ACL ACL是最早也是最基本的一种访问控制机制&#xff0c;它的原理非常简单&#xff1a;每一项资源&#xff0c;都配有一个列表&#xff0c;这个列表记录的就是哪些用户可以对这项资源执行CRUD中的那些操作。当系统试图…

最常见并发面试题整理!(速度收藏)

前言并发编程是面试中必问的知识点之一&#xff0c;所以本文整理了一些最为常见的并发面试题&#xff0c;一起来看吧~1. synchronized的实现原理以及锁优化&#xff1f;synchronized的实现原理synchronized作用于「方法」或者「代码块」&#xff0c;保证被修饰的代码在同一时间…