精华内容
下载资源
问答
  • 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

    展开全文
  • 二进制编辑替换 这种hack方式是进行二进制格式的替换,只需要掌握一点ELF格式的基础就可以,so easy!!! kmalloc默认是inline的,它实际调用__kmalloc,我们可以根据module的.rela.text的信息进行替换,所有调用__kmalloc...

    本篇不走寻常路,想要正常的内存调试手段请查阅内核相关的内存debug功能.

    程序开发了很长时间,参与开发的人也很多,今天我想用实验统计来证明我们写的内核module没有产生内存泄露,通常的做法是封装内存的api,中间加上统计逻辑,但是我不想改他们的代码,有什么办法吗?

    我翻了一下code,里面有上百处申请内存的位置,主要使用了两种api,一种是kmalloc,另外一种是创建自己的kmem_cache的方式.后一种自带内存泄露检查,当module卸载时尝试destroy kmem_cache,如果还有slab对象没有归还时会自动报warning,这也是一种方式,创建自己的kmem_cache,通过slabinfo查看使用情况,唯一不好的是创建一大堆kmem_cache.

    而kmalloc/kzalloc有什么方法吗?刚开始我考虑借助gcc宏的方式,可以考虑下面这种实现是否可以成功:

    .#define hook_kmalloc kmalloc
    hook_kmalloc() {
    	do_something();
    #include <linux/slab.h>
    	kmalloc();
    }
    

    这种当然是不成功的,它最终展开的逻辑想要展示成下面这样,当然在宏展开后会发生重复定义的错误:

    	func1() {
    		do_something();
    		func1();
    	}
    

    没有办法在一个module中不修改代码的情况将直接进行func调用的情况变成进行func->hook_func->func的操作.

    最后采用一个折中的方法:
    1.写个调试module1,封装kmalloc成hook_kmalloc,kfree->hook_kfree,加上调试逻辑
    2.module中把不必要的<linux/slab.h>都去掉,然后放到唯一的一个头文件中,大部分都不关心头文件,只要不报警应该没问题.
    之后在这个头文件中做文章,想调试时不调用内核原生的而是调用module1中的接口.

    #ifndef HOOK_SLAB_H
    #define HOOK_SLAB_H
    #ifdef DEBUG
    #define hook_kmalloc kmalloc
    #define hook_kfree kfree
    #else
    # include <linux/slab.h>
    #endif
    #endif
    

    有没有办法一点代码都不修改的情况下进行替换呢?二进制编辑替换
    这种hack方式是进行二进制格式的替换,只需要掌握一点ELF格式的基础就可以,so easy!!!

    kmalloc默认是inline的,它实际调用__kmalloc,我们可以根据module的.rela.text的信息进行替换,所有调用__kmalloc的地方变成hook_kmalloc,我当然不会傻傻的修改重定位段,只需要简单的修改一下字符串就可以完成替换.下面只是提供原型,将__kmalloc替换成1_kmalloc,不写程序直接用工具编辑二进制文件.

    module原始的信息:

    readelf -r test.ko |grep _kmalloc
    000000006203  051300000002 R_X86_64_PC32     0000000000000000 __kmalloc - 4
    ......
    0000000278f2  051300000002 R_X86_64_PC32     0000000000000000 __kmalloc - 4
    

    总共有n个使用__kmalloc的位置,下面是重定位段的信息:

    readelf -S test.ko 
    There are 54 section headers, starting at offset 0x1109688:
    Section Headers:
      [Nr] Name              Type             Address           Offset
           Size              EntSize          Flags  Link  Info  Align
    ...
      [ 3] .rela.text        RELA             0000000000000000  00978450
           00000000000282c0  0000000000000018   I      51     2     8
      [51] .symtab           SYMTAB           0000000000000000  0096ab28
           0000000000007c98  0000000000000018          52   366     8
      [52] .strtab           STRTAB           0000000000000000  009727c0
           0000000000005c90  0000000000000000           0     0     1
           
    # nm test.ko |grep kmalloc
                     U __kmalloc
                     U kmalloc_caches
                     U kmalloc_order_trace 
    

    重定位段的link记录符号表的index,info记录重定位段应用在哪个section上.

    简单捋一捋整个过程:在insmod的过程中会应用重定位段,其中查找需要的符号位置也就是符号表中的项,符号并没有直接保存函数名称而是保存了相关的字符串表的索引和偏移,我们只需要简单对应的字符串的内容就可以完成.
    在这里需要对使用__kmalloc的位置进行重定位,修改字符串表中__kmalloc为1_kmalloc之后,安装时module就不再依赖__kmalloc而是1_kmalloc,我们就成功通过修改二进制程序来完成hook.

    #readelf -r test.ko |grep _kmalloc
    000000006203  051300000002 R_X86_64_PC32     0000000000000000 1_kmalloc - 4
    ......
    0000000278f2  051300000002 R_X86_64_PC32     0000000000000000 1_kmalloc - 4
    
    #nm zsdefend.ko |grep kmalloc
                     U 1_kmalloc
    #dmesg:                 
    [175853.839949] test: Unknown symbol 1_kmalloc (err 0)
    

    限制:
    1.修改二进制module在开启签名之后因为修改内容,也就是数字签名必然会不一致,所以在开启强安全功能的系统上就不能这样搞了
    2.修改的函数名还是有限制的,修改后的函数名长度>原始的函数名长度,否则就越界了.

    当然也可以取任意长度的hook名称,但是需要做一些额外的工作,过程如下:
    2.1.在module的.strtab中追加想要的hook名称,函数名就是一个普通的字符串,以0结尾.

    objcopy --dump-section .strtab=strtab.sec test.ko
    echo -ne "hook_kmalloc\x00" >>strtab.sec
    objcopy --update-section .strtab=strtab.sec test.ko
    

    2.2.修改.symtab中的指针,指向追加的hook名称

    objcopy --dump-section .symtab=symtab.sec test.ko
    我们从这里看符号的偏移051300000002>>32=0x513,之后编辑这个偏移的符号表的st_name
    readelf -r test.ko |grep _kmalloc
    000000006203  051300000002 R_X86_64_PC32     0000000000000000 1_kmalloc - 4
    vim -b symtab.sec              # %!xxd %!xxd -r
    
    更新符号表
    objcopy --update-section .symtab=symtab.sec test.ko
    
    展开全文
  • objcopy 修改 elf 文件中动态库解析器 总共有两个步骤: dump interp section change section component and update 这里我使用 ls 命令作为小白鼠,在其上进行实验。 首先执行如下命令 dump 出 interp section 的...

    我在 低版本 libc 库运行高版本 libc 库编译的程序 这篇博客中描述了,通过修改 elf 中动态库解析器来实现低版本 libc 库环境运行高版本 libc 库编译的程序的方法。

    在使用 objcopy 修改动态库解析器位置时,没有成功,今天重新搞了下终于成功了,在这里记录一下问题。

    objcopy 修改 elf 文件中动态库解析器

    总共有两个步骤:

    1. dump interp section
    2. change section component and update

    这里我使用 ls 命令作为小白鼠,在其上进行实验。

    首先执行如下命令 dump 出 interp section 的内容:

    objcopy --dump-section .interp=interpsection ./ls
    

    使用 od -c 命令查看 dump 出的 section 存储的 interpsection 文件的内容,信息记录如下:

    [longyu@debian-10:16:40:36] tmp $ od -c interpsection 
    0000000   /   l   i   b   6   4   /   l   d   -   l   i   n   u   x   -
    0000020   x   8   6   -   6   4   .   s   o   .   2  \0
    0000034
    

    使用 vim 直接编辑 interpsection 文件带来的问题

    直接用 vim 编辑 interpsection 文件,修改动态链接器位置为 /tmp/ld-linux-x86-64.so.2。

    修改后执行 objcopy --update-section .interp=interpsection ./ls更新 section,更新后无法执行。

    这时 od -c interpsection 查看修改后的 section 内容如下:

    [longyu@debian-10:16:43:08] tmp $ od -c interpsection 
    0000000   /   t   m   p   /   l   d   -   l   i   n   u   x   -   x   8
    0000020   6   -   6   4   .   s   o   .   2  \0  \n
    0000033
    

    可以看到路径确实修改了,不过多了个 ‘\n’ 出来了,看来应该是 vim 还进行了额外的处理。

    使用 sed 进行替换

    了解到上面的问题后,我使用 sed 进行替换,并在替换后查看内容,确认这次没有添加 ‘\n’ 了。

    操作记录如下:

    [longyu@debian-10:16:45:26] tmp $ sed -i 's;/lib64/;/tmp/;' interpsection 
    [longyu@debian-10:16:45:44] tmp $ od -c interpsection 
    0000000   /   t   m   p   /   l   d   -   l   i   n   u   x   -   x   8
    0000020   6   -   6   4   .   s   o   .   2  \0
    0000032
    

    重新 update-section 后运行 ls 命令,这次能够正常运行。操作记录如下:

    [longyu@debian-10:16:45:49] tmp $ objcopy --update-section .interp=interpsection ./ls
    [longyu@debian-10:16:48:59] tmp $ cp /lib64/ld-linux-x86-64.so.2  ./
    [longyu@debian-10:16:49:19] tmp $ ./ls 
    fcitx-socket-:0			      ssh-luhovGjXhxJV
    interpsection			      systemd-private
    

    上面的命令中我首先执行 objcopy 命令更新了 interp section,然后拷贝动态库解析器到 /tmp 目录下来模拟使用不同的动态库链接器的行为。然后运行 ls 命令,这次能够正常运行了。

    为了进一步确认我的修改有效,我删除 /tmp 中的动态库链接器后重新执行 ls 命令,这次执行失败。操作记录如下:

    [longyu@debian-10:16:50:36] tmp $ rm -rf ./ld-linux-x86-64.so.2 
    [longyu@debian-10:16:50:48] tmp $ ./ls 
    bash: ./ls: 没有那个文件或目录
    

    当删除了 /tmp 中的动态库解析器后 ls 命令无法正常运行。

    为什么 vim 会在添加一个 ‘\n’

    我使用 emacs 来编辑 dump 出来的 section 文件,发现也有相同的问题,这个其实是编辑器的正常行为,在这里也没有问题,只是我不应该用这些文本编辑器来直接编辑 section 的内容,section 的内容严格意义上来说应该属于 hex 格式。

    展开全文
  • #!/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文件的入口,让它跳到自己的逻辑”这件事很容易。 真的很容易吗?是的,真的很容易。本文就是要演示这个的。 还记得熊猫烧香病毒吧...
  • ELF = Executable and Linkable Format,可执行连接格式,是...ELF 文件有三种类型:可重定位文件:也就是通常称的目标文件,后缀为.o。共享文件:也就是通常称的库文件,后缀为.so。可执行文件:本文主要讨论的文...
  • ELF文件头读取修改

    千次阅读 2012-03-12 10:30:04
    ELF = Executable and Linkable Format,可执行连接格式,是UNIX...ELF 文件有三种类型:可重定位文件:也就是通常称的目标文件,后缀为.o。共享文件:也就是通常称的库文件,后缀为.so。可执行文件:本文主要讨论的
  • 增加或修改 ELF 文件正是入侵者植入恶意代码的常用途径。本文将描述一种 Linux 下 ELF 文件的代码签名及验证机制的设计与实现,这种机制能有效防止基于 ELF 文件的恶意代码的入侵,并同时提供了灵活的分级验证机制,...
  • 在 Linux 中修改一个现有的 elf 文件

    千次阅读 2018-05-12 20:01:19
    在Linux中下修改一个现有的elf可执行程序 首先了解 elf 文件结构: 可重定位文件: 包含适合于与其他目标文件链接来创建可执行文件或者共享目标文件的代码和数据。 可执行文件: 包含适合于执行的一个程序,此文件...
  • C/C++程序在linux下被编译和连接时,GCC/G++会查找系统默认的include和link的路径,以及自己在... ( yum install chrpath) 不过chrpath 有个缺陷,如果当前系统为x86_64,则修改i386 elf会报错,patchelf则无此问题!
  • ...tar -zxf patchelf-0.8.tar.bz2 cd patchelf-0.8 ./configure --prefix=/usr make && make install ... 不过chrpath 有个缺陷,如果当前系统为x86_64,则修改i386 elf会报错,patchelf则无此问题!

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 328
精华内容 131
关键字:

修改elf文件