知识大全 Linux系统病毒研究之一

Posted

篇首语:谨慎和勤奋带来好运。本文由小常识网(cha138.com)小编为大家整理,主要介绍了知识大全 Linux系统病毒研究之一相关的知识,希望对你有一定的参考价值。

Linux系统病毒研究之一  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!

  作者 Silvio Cesare  编译 nixe n    摘要:本文讨论了一个修改ELF文件实现共享库调用重定向的方法 修改可执行文件的程序连接表(Procedure Linkage Table)可以使被感染的文件调用外部的函数 这要比修改LD_PRELOAD环境变量实现调用的重定向优越的多 首先不牵扯到环境变量的修改 其次是更为隐蔽 本文将提供一个基于x /Linux的实现    前言    这是nixe n搜集的一组有关Linux系统下病毒的研究文章 没有先后的次序 文中的代码可能有破坏性 只能用于研究 如果你用于非法目的 后果自负     感染ELF文件程序连接表实现共享库调用的重定向     简介    本文讨论了一个修改ELF文件实现共享库调用重定向的方法 修改可执行文件的程序连接表(Procedure Linkage Table)可以使被感染的文件调用外部的函数 这要比修改LD_PRELOAD环境变量实现调用的重定向优越的多 首先不牵扯到环境变量的修改 其次是更为隐蔽 本文将提供一个基于x /Linux的实现 如果你对UNIX系统病毒比较感兴趣请参考以下网址     (UNIX病毒邮件列表)  ~silvio (作者主页)     程序连接表(Procedure Linkage Table)    下面是ELF规范中 关于程序连接表的叙述         程序连接表(PLT)    在ELF文件中 全局偏移表(Global Offset Table GOT)能够把位置无关的地址定位到绝对地址 程序连接表也有类似的作用 它能够把位置无关的函数调用定向到绝对地址 连接编辑器(link editor)不能解决程序从一个可执行文件或者共享库目标到另外一个的执行转移 结果 连接编辑器只能把包含程序转移控制的一些入口安排到程序连接表(PLT)中 在system V体系中 程序连接表位于共享正文中 但是它们使用私有全局偏移表(private global offset table)中的地址 动态连接器(例如 ld so)会决定目标的绝对地址并且修改全局偏移表在内存中的影象 因而 动态连接器能够重定向这些入口 而勿需破坏程序正文的位置无关性和共享特性 可执行文件和共享目标文件有各自的程序连接表       表 使用绝对地址的程序连接表   PLT :pushl got_plus_   jmp *got_plus_   nop; nop  nop; nop   PLT :jmp *name _in_GOT  pushl $offset  jmp PLT @PC   PLT :jmp *name _in_GOT  pushl $offset  jmp PLT @PC       表 位置无关的程序连接表   PLT :pushl (%ebx)  jmp * (%ebx)  nop; nop  nop; nop   PLT :jmp *name @GOT(%ebx)  pushl $offset  jmp PLT @PC   PLT :jmp *name @GOT(%ebx)  pushl $offset  jmp PLT @PC         注意 从两个表中可以看出 两种方式的指令使用不同的操作数寻址模式 但是 它们和动态连接器的接口是一样的     下一步 动态连接器和程序本身使用程序连接表和全局偏移表共同解析符号引用     当第一次建立程序的内存影象时 动态连接器会把全局偏移表的第二和第三个入口设置为特定的值 下面会对这些值进行介绍   如果程序连接表是位置无关的 需要把全局偏移表地址保存在%ebx中 进程影象中的每个共享目标文件都有自己的程序连接表 而且程序的执行流程改变时 也只能跳转到同一个目标文件的程序连接表入口 例如 一个程序foo 它的动态连接库为bar so 它们都有自己程序连接表 那么foo正文段调用某个程序连接表入口时 只能跳转到foo文件自己的程序连接表 而不能转到bar so的程序连接表中 因此 在调用程序连接表入口之前 函数调用代码应该设置全局偏移表的基址寄存器   为了便于描述 我们假设程序要调用另一个目标文件的函数name 因此首先需要把程序执行控制权转移到标记为 PLT 的代码处   这段代码的第一条指令就是 跳转到name 在全局偏移表的入口地址 因为name 是在另一个目标文件中的调用 所以在初始化时 全局偏移表没有保存name 的真实地址 而只是保存了这段代码第二条指令pushl的地址   因而 程序会接着执行第二条指令 在栈压入一个重新定位的偏移值(offset) 这个重新定位的偏移值是重定位表中的一个 位的非负字节偏移值 这个特指的重定位入口是R_ _JMP_SLOT类型的 它的偏移值将指定先前jmp指令用到的全局偏移表的入口 重定位入口还有一个符号表索引 告诉动态连接器哪个符号被引用 在这个例子中是name   在栈中压入重定位偏移值以后 程序接着就跳转到 PLT 它是程序连接表的第一个入口 pushl指令在栈中压入第二个全局偏移表的入口(got_plus_ 或者 (%ebx)) 从而给动态连接器一个单字识别信息 程序接着跳转到全局偏移表的第三个入口中的地址(got_plus_ 或者 (%ebx)) 将控制权转移给动态连接器   当动态连接器获得控制权 它就会展开栈 读出指定的重定位入口 找出符号表的值 把name 的真正地址保存到全局偏移表的name 入口中 然后将控制权转移给目的目标   因此 如果再次调用name 就会直接从程序连接表入口转移到name 而不必再次调用动态连接器 也就是说 PLT 的jmp指令将转移到name 而不是接着执行push 指令   LD_BIND_NOW环境变量能够改变动态连接行为 如果这个环境变量不为空 动态连接器在把控制权交给程序之前会先为程序连接表赋值 也就是说 在进程初始化期间 动态连接器为R_ _JMP_SLOT类型的重定位入口赋值 以便在第一次调用时 不必通过动态连接器就能够跳转到目标地址 反之 如果这个环境变量为空 动态连接器就暂不为程序连接表入口赋值 不对符号进行解析和重定位 直到第一次调用一个程序连接表入口 才对其做相应的处理 这种方式叫作后期连接(lazy binding)方式     注意 后期连接(lazy binding)方式一般会大大提高应用程序的性能 因为不必为解析无用的符号浪费动态连接器的开销 不过 有两种情况例外 第一 对一个共享目标函数进行初始化处理花费的时间比调用正式的执行时间长 因为动态连接器会拦截调用以解析符号 而这个函数功能又比较简单 第二 如果发生错误和动态连接器无法解析符号 动态连接器就会终止程序 使用后期连接方式 这种错误可能会在程序执行过程中 随时发生 而有些应用程序对这种不确定性有比较严格的限制 因此 需要关闭后期连接方式 在应用程序接受控制权之前 让动态连接器处理进程初始化期间发生的这些错误     下面将对其细节做一些解释     因为在编译时共享库的调用不能被连接到程序中 所以需要对其做特殊处理 直到程序运行时 共享库才是有效的 PLT就是为了处理这种情况 PLT保存调用动态连接器的有关代码 由动态连接器对所需例程进行定位   可执行目标是调用PLT的某个入口来实现对共享库例程的调用 而不是直接调用共享库例程 然后 由PLT解析符号表示什么以及进行其它操作   下列代码来自ELF规范      PLT :jmp *name _in_GOT  pushl $offset  jmp PLT @PC    从这段代码中可以得到一些重要的信息 这是一个例程调用 而不是库调用 进程初始化之后 name _in_GOT指向后面的push 指令 offset代表一个重定位偏移值(参见ELF规范) 它包含一个符号引用 这个符号表示这个库调用 使后面的jmp指令能够跳转到动态连接器 为了避免下次调用这个共享库例程时重复这个流程 动态连接器接着会修改name _in_GOT 让其直接指向这个例程 这样就能够节约再次调用的时间     上面的叙述总结了PLT在搜索库调用时的重要性 因此 我们可以修改name_in_GOT使其指向我们自己的代码 取代原先库调用 实现病毒的传染 如果在取代之前 我们保存GOT的状态 那么还能够重新调用原来的库调用 而且可以实现任意库调用的重定向      感染ELF文件    为了实现库调用的重定向 需要在可执行目标文件中加入新的代码 本文我们将不涉及这方面的问题 这在~silvio已经有专门的文章论述      PLT重定向    入口点的算法如下     把正文段标记为可写   保存PLT(GOT)入口   使用新的库调用地址代替PLT(GOT)入口   新的库调用算法如下     实现新的库调用的功能   保存原来的PLT(GOT)入口   调用库调用   再次保存PLT(GOT) 如果它被修改了的   使用新的库调用的地址代替PLT(GOT)入口   为了更清楚地解释PLT重定向是如何工作的 我们在此解析一段简单的代码 在这段代码中被重定向的是printf 新的代码是在printf输出一个字符串之前 打印一条消息     好吧 现在开始     首先保存寄存器   x /* pusha */    把正文段标记为rwx 因为正文段通常是不可写的 所以为了能够修改PLT 我们需要把它改为可写的 通过mprotect系统调用    xb x dx x x /* movl $ %eax */   xbbx x x x /* movl $text_start %ebx */   xb x x x x /* movl $ x %ecx */   xbax x x x /* movl $ %edx */   xcdx /* int $ x cha138/Article/program/Oracle/201311/16530

相关参考

知识大全 如何选购Linux可以搭配的机器之一部可能的最佳组合 Linux PC

如何选购Linux可以搭配的机器之一部可能的最佳组合LinuxPC  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一

知识大全 系统启动脚本分析(6)--其它一些脚本简介

  摘要  这段时间在搞一个微型的Linux将它作为一个项目的平台这个过程中看了研究了一下Linux的启动过程同时把启动配置文件看了一下作了一下注释同时和大家共享一下:)我使用的Linux平台是Red

知识大全 在win7系统下安装了linux(deepin2014)系统,开机时发现无选择项就直接进入linux了。如何换回win7系统

在win7系统下安装了linux(deepin2014)系统,开机时发现无选择项就直接进入linux了。如何换回win7系统?你这个就有点复杂了,方法如下:1、下载好windows7系统的光碟映象,并

知识大全 电脑安装linux redhat和win7双系统后,为什么开机时只能进入linux系统,而进不了win7,求解决

电脑安装linuxredhat和win7双系统后,为什么开机时只能进入linux系统,而进不了win7,求解决,安装好双系统linux之后为什么不能进入之前的win7了要是是在着急你就看看grub能不

知识大全 Linux各项系统开机服务的功能

Linux各项系统开机服务的功能  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Linux在启动

知识大全 Linux系统怎么隐藏文件夹和文件

Linux系统怎么隐藏文件夹和文件  以下文字资料是由(本站网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!Linux系统怎么隐

知识大全 如何在硬碟建置Linux系统之系统设定

如何在硬碟建置Linux系统之系统设定  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  刚刚完成的

知识大全 Linux系统安装php扩展cURL

Linux系统安装php扩展cURL  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  Linux作

知识大全 Linux 系统的优化和微调

Linux系统的优化和微调  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  针对系统的优化工作需要

知识大全 Linux简明系统维护手册(1)

Linux简明系统维护手册(1)  以下文字资料是由(全榜网网www.cha138.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!  摘要    本文