共享库注射--injectso实例

2008-04-09 04:00:20来源:互联网 阅读 ()

新老客户大回馈,云服务器低至5折




共享库注射--injectso实例

来源:http://www.whitecell.org/forums/viewtopic.php?topic=3885&forum=16&0

共享库注射--injectso实例
Grip2


Joined: Feb 17, 2002
Posts: 139 Posted: 2002-08-20 10:55
--------------------------------------------------------------------------------
Code:
--------------------------------------------------------------------------------

共享库注射--injectso实例


作者:grip2 <gript2@hotmail.com>
日期:2002/08/16


内容:
1 -- 介绍
2 -- injectso -- 共享库注射技术
3 -- injectso的工作步骤及实现方法
4 -- 目标进程调试函数
5 -- 符号解析函数
6 -- 一个简单的后门程序
7 -- 最后
8 -- 参考文献



一、 ** 介绍

本文介绍的是injectso技术,重点是使用现有技术去实际的完成一个injectso程序,
而不是侧重于理论上的探讨。这里希望你在阅读这篇文章的时候对ELF、inject有一
定的了解,当然你也可以选择在看完本文之后再去翻看相关的资料,也许这样能使你
更有针对性。需要说明的是,下面介绍的技术和给出的函数都是特定于X86下的linux
的,在其它环境下可能有一些需要改变的细节,但从基本的概念和步骤上讲应该是相
同的。


二、 ** injectso -- 共享库注射技术

使用injectso技术,我们可以注射共享库到一个运行期进程,这里注射的意思就是通
过某种操作使我们的.so共享库在指定的进程中被装载,这样再配合上函数重定向或
其它技术,我们就可以捕获或改变目标进程的行为,可以做非常多的工作。同其它
inject技术相比,injectso的一些优点是:
1. 简单 -- 仅仅通过C代码就可以完成所有的工作;
2. 扩展性好 -- 在基础代码完成之后,如果要对程序功能进行增加、修改,仅需改动
.so共享库即可;
3. 干净 -- 对目标进程进行注射之后,不需要留下磁盘文件,使用的程序及共享库
都可以删除;
4. 灵活 -- 我们可以使用它完成很多工作,例如:运行期补丁、后门程序等;
5. 目标服务不需要重新启动;
6. 无须改动二进制文件;
7. 可以通过pax, openwall等这样的核心补丁。


三、 ** injectso的工作步骤及实现方法

完成injectso需要以下几个步骤:
1. 关联到目标进程;
2. 发现装载共享库的函数,一般是_dl_open调用,我们将使用它装载我们的.so共享

3. 装载指定的.so;
4. 做我们想做的,一般是通过函数重定向来完成我们需要的功能;
5. 脱离进程;

下面简单介绍一下这几个步骤的实现方法,由于我们是对其它进程进行操作,因此
ptrace这个linux调试API函数将频繁的被我们使用,在<四>中,我将给出一些ptrace
包装函数。

步骤1 -- 关联进程
  简单的调用ptrace(PTRACE_ATTACH,...)即可以关联到目标进程,但此后我们还
需调用waitpid()函数等待目标进程暂停,以便我们进行后续操作。详见<四>中给出
的ptrace_attach()函数。

步骤2 -- 发现_dl_open
  通过遍历动态连接器使用的link_map结构及其指向的相关链表,我们可以完成
_dl_open的符号解析工作,关于通过link_map解析符号在phrack59包的p59_08(见参
考文献)中有详细的描述。

步骤3 -- 装载.so
由于在2中我们已经找到_dl_open的地址,所以我们只需将此函数使用的参数添
入相应的寄存器,并将进程的eip指向_dl_open即可,在此过程中还需做一些其它操
作,具体内容见<四>中的call_dl_open和ptrace_call函数。

步骤4 -- 函数重定向
我们需要做的仅仅是找到相关的函数地址,用新函数替换旧函数,并将旧函数的
地址保存。其中涉及到了PLT和RELOCATION,关于它们的详细内容你应该看ELF规范中
的介绍,在<四>中的函数中有PLT和RELOCATION的相关操作,而且在最后的例子中,
我们将实现函数重定向。关于函数重定向,相关资料很多,这里不再多介绍。

步骤5 -- 脱离进程
  简单的调用ptrace(PTRACE_DETACH,...)可以脱离目标进程。


四、** 目标进程调试函数

在linux中,如果我们要调试一个进程,可以使用ptrace API函数,为了使用起来更
方便,我们需要对它进行一些功能上的封装。
在p59_08中作者给出了一些对ptrace进行封装的函数,但是那太少了,在下面我给出
了更多的函数,这足够我们使用了。要注意在这些函数中我并未进行太多的错误检测
,但做为一个例子使用,它已经能很好的工作了,在最后的例子中你将能看到这一点


/* 关联到进程 */
void ptrace_attach(int pid)
{
if(ptrace(PTRACE_ATTACH, pid, NULL, NULL) < 0) {
perror("ptrace_attach");
exit(-1);
}

waitpid(pid, NULL, WUNTRACED);

ptrace_readreg(pid, &oldregs);
}

/* 进程继续 */
void ptrace_cont(int pid)
{
int stat;

if(ptrace(PTRACE_CONT, pid, NULL, NULL) < 0) {
perror("ptrace_cont");
exit(-1);
}

while(!WIFSTOPPED(stat))
waitpid(pid, &stat, WNOHANG);
}

/* 脱离进程 */
void ptrace_detach(int pid)
{
ptrace_writereg(pid, &oldregs);

if(ptrace(PTRACE_DETACH, pid, NULL, NULL) < 0) {
perror("ptrace_detach");
exit(-1);
}
}

/* 写指定进程地址 */
void ptrace_write(int pid, unsigned long addr, void *vptr, int len)
{
int count;
long word;

count = 0;

while(count < len) {
memcpy(&word, vptr count, sizeof(word));
word = ptrace(PTRACE_POKETEXT, pid, addr count, word);

标签:

版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有

上一篇:securityofprogramer-5

下一篇:如何将多个文件捆绑成一个可执行文件