በአሮጌ ክራንች ላይ ጥንታዊ ክራንች

ያለምንም ችግር እጀምራለሁ, አንድ ጊዜ ራዕይ ካገኘሁ (በደንብ, በጣም ኃይለኛ አይደለም, እውነቱን ለመናገር) እና ምስልን ከደንበኛ ወደ አገልጋይ የሚያስተላልፍ ፕሮግራም ለማተም ሀሳቡ ተነሳ. ቀላል በቂ ነው? መልካም, ልምድ ላለው ፕሮግራም አውጪ, እንደዚያ ይሆናል. ሁኔታዎቹ ቀላል ናቸው - የሶስተኛ ወገን ቤተ-መጽሐፍቶችን አይጠቀሙ. በመርህ ደረጃ, ትንሽ የተወሳሰበ ነው, ነገር ግን እሱን ማወቅ እና ምሳሌዎችን መፈለግ እንዳለብዎት, ጥሩ, እንደዚህ አይነት ስራ. ይህ ተግባር በእኔ ላይ እንደሆነ ወሰንኩ. በተጨማሪም, እርዳታ ከፈለጉ በመድረኩ ላይ እንዲለጠፍ በቂ ኮድ እንዲኖር ያስፈልጋል. በመጀመሪያ ፣ ዓይኖቼ በኤፍቲፒ ላይ ወድቀዋል ፣ በነገራችን ላይ ዊንዶውስ እየተሰራበት ባለው ስርዓተ ክወና። የኤፍቲፒ ጥቅም ምስልን ብቻ ሳይሆን ማንኛውንም ፋይል በእሱ በኩል ማስተላለፍ ይችላሉ. Filezilla Server ን ካወረድኩ በኋላ ለማንበብ/ለመፃፍ አንድ ማውጫ በማጋራት እና ተጠቃሚን በይለፍ ቃል ከፈጠርኩ በኋላ የፋይልዚላ ደንበኛን ለማገናኘት ሞከርኩ ሁሉም ነገር ሰራ። በC/C++ ውስጥ ቀላል የኮድ ምሳሌ ፈጠርኩ፡-

#include <iostream>
void main()
{
	FILE* fs;
	fopen_s(&fs, "1.txt", "w");
	if (fs)
	{
    fwrite("userrnpasswordrnsend D:\share.txtrnbye", 1, sizeof("userrnpasswordrnsend D:\share.txtrnbye"), fs);
    fwrite("00", 1, sizeof("00"), fs);
    fclose(fs);
	}
	system("ftp -s:1.txt 127.0.0.1");
}

የማስታወስ ችሎታዬ የሚያገለግለኝ ከሆነ, ሁሉም ነገር በ localhost ላይ ሰርቷል, እና በአውታረ መረቡ ላይ ሲሰራጭ, ከላኪው መስመር ላይ ስህተት ተከስቷል. እዚህ ምን ምቹ ነው ሀ) ባጭሩ ለ) ደንበኛን መጫን አያስፈልገዎትም ነገር ግን ቀድሞውንም አብሮ የተሰራውን ለ ftp ከማይክሮሶፍት ይጠቀሙ። ምንም እንኳን በእኔ አስተያየት በፕሮግራሞች እና አካላት አማካኝነት መንቃት አለበት. የዚህ ዘዴ ችግር ምን እንደሆነ ካወቁ እና በአስተያየቶቹ ውስጥ ከጻፉ በጣም ጥሩ ይሆናል.

በበርካታ መድረኮች ላይ መልስ አላገኘሁም ፣ ይህንን ኮድ ትቼ ለሶኬት አውታረ መረቦች በይነገጽ ለመጠቀም ወሰንኩ። ቻርስን ወደ ሌላ ፕሮግራም የማስተላለፍ ልምድ አለኝ። በነገራችን ላይ ስለ ማጓጓዣ ንብርብር በምዕራፉ ውስጥ ከ Tanenbaum, የኮምፒተር ኔትወርኮች ማንበብ ይችላሉ. ለ “ብዙ ደንበኞች - አንድ አገልጋይ” ግንኙነት ባይሆንም የደንበኛ እና የአገልጋይ ምሳሌ አለ ፣ ግን “አንድ ደንበኛ - አንድ አገልጋይ” ብቻ። ስርጭቱ በበይነ መረብ ላይ ስለሆነ ውሂቡን እንደምንም ማመስጠር ያስፈልግዎታል። ለእዚህ, የማገጃ ሲፈር ጥቅም ላይ ይውላል - የ Feitel አውታረመረብ. በተጨማሪም በአገልጋዩ ላይ ብዙ (ከአንድ ደንበኛ በላይ) ደንበኞችን ማድረግ አስፈላጊ ነው. ይህንን ለማድረግ እኛ ክሮች እንጠቀማለን ፣ ለስርጭቱ ምስሉ ከደንበኛው የስክሪኑን ቅጽበታዊ ገጽ እይታ ይወስዳል ፣ ምስጠራ እና ወደ አገልጋዩ ይተላለፋል ፣ ከዚያ ዲክሪፕት ይደረግበታል እና ወዲያውኑ ለመክፈት በነባሪ ፕሮግራሙ በስክሪኑ ላይ ይታያል * .tga ምስሎች.

የአገልጋይ ኮድ፡-

#include <iostream>
#include <WinSock.h>
#pragma comment (lib,"WS2_32.lib")

#include <fstream>
#include <algorithm>
#include <string>
#include <iterator>
#include <vector>
void error(const char* msg)
{
    //perror(msg);
    std::cout<<'n'<<WSAGetLastError();
    WSACleanup();
    std::cin.ignore();
    exit(1);
}
void bzero(char*buf, int l)
{
    for (int i = 0; i < l; i++)
        buf[i] = '';
}
struct arg_s
{
    unsigned char* buffer2;
    bool exit;
};
char** buffer;
struct arg_sa
{
    struct arg_s* lalk;
    int current;
};
#define type struct arg_sa
int sockfd, * newsockfd;//слушающий и массив клиентских сокетов
int buflen2 = 10292000;//максимальный размер изображения в байтах для RGBA*Width*Height
struct sockaddr_in *cli_addr;
int* clilen;
int currentclient,cc;//сс-клиент по счету(для записи инкремента имени файла клиента изображения)

typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
#define N 8//размер блока
#define F32 0xFFFFFFFF
uint32_t RK[N];//раундовые ключи
#define size64 sizeof(uint64_t)
#define ROR(x,n,xsize)((x>>n)|(x<<(xsize-n)))
#define ROL(x,n,xsize)((x<<n)|(x>>(xsize-n)))
#define RKEY(r)((ROR(K,r*3,size64*8))&F32)
const uint64_t K = 0x96EA704CFB1CF671;//ключ шифрования
struct hostent* server;
uint32_t F(uint32_t subblk, uint32_t key)
{
    return subblk + key;//функция шифрования
}
void createRoundKeys()
{
    for (int i = 0; i < N; i++)
        RK[i] = (ROR(K, i * 8, size64 * 8)) & F32;
}
uint64_t decrypt(uint64_t c_block)//расшифровка блоков сетью фейстеля
{
    //select subblocks
    uint32_t left = (c_block >> 32) & F32;
    uint32_t right = c_block & F32;
    uint32_t left_, right_;//subblock in the end of round
    for (int r = N - 1; r >= 0; r--)
    {
        uint32_t fk = F(left, RK[r]);
        left_ = left;
        right_ = right ^ fk;
        if (r > 0)//swap places to next round
        {
            left = right_;
            right = left_;
        }
        else //last round not swap
        {
            left = left_;
            right = right_;
        }
    }
    //collect subblock in block
    uint64_t block = left;
    block = (block << 32) | (right & F32);
    return block;
}
void session_(LPVOID args)//функция потока ля каждого клиента
{
    int current = currentclient++;
    bzero((char*)&(cli_addr[current]), sizeof(&(cli_addr[current])));
    newsockfd[current] = accept(sockfd, (struct sockaddr*)&(cli_addr[current]), &(clilen[current]));
    if (newsockfd[current] < 0)
    {
        error("Error on acceptn");
    }
    char* s = new char[100];
    int n = recv(newsockfd[current], s, 100, 0);
    int buflen2 = atoi(s);//получаем число байтов изображения
    FILE* f;
    std::string name = "Screen";
    cc++;
    _itoa_s(cc, s, 100, 10);
    name += s;
    name += ".tga";
    fopen_s(&f,name.c_str(), "wb");//создаем файл изображения с увеличиваещимся на 1 именем, чтобы не перезаписать
    if (f != NULL)
    {
        unsigned char tgaHeader[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        unsigned char header[6];
        n = recv(newsockfd[current], buffer[current], sizeof(tgaHeader), 0);
        fwrite((unsigned char*)buffer[current], 1, sizeof(tgaHeader), f);
        bzero(buffer[current], buflen2);
        n = recv(newsockfd[current], buffer[current],sizeof(header), 0);
        fwrite((unsigned char*)buffer[current], 1, sizeof(header), f);//записали хидеры
        bzero(buffer[current], buflen2);
        n = recv(newsockfd[current], buffer[current], buflen2, 0);//получили байты самого изображения
        //
        //расшифровка байтов
        createRoundKeys();
        unsigned long long id;
        std::vector<uint64_t>* plaintext = new std::vector<uint64_t>();
        int i = 0;
        while (i<buflen2)
        {
            memcpy(&id, (buffer[current]) + i, N);
            plaintext->push_back(decrypt(id));
            i += 8;
        }
        std::cout << "i=" << i << std::endl;
        i = 0;
        char str_[N + 1];
        memset(str_, 0, N);
        str_[N] = '';
        for (std::vector<uint64_t>::iterator it = plaintext->begin(); it != plaintext->end(); ++it)
        {
            memcpy(str_, &*it, N);
            fwrite((unsigned char*)str_, sizeof(unsigned char), N/*strlen(str_)*/, f);
            i += 8;
        }
        std::cout << "i=" << i << std::endl;
        //конец рашифровки байтов
        //fwrite((unsigned char*)buffer[current], sizeof(char), buflen2, f);
        fclose(f);
    }
    system(name.c_str());//открываем изображение *.tga встроенным редактором
}
int main()
{
    cc = 0;
    WSADATA ws = { 0 };
    if (WSAStartup(MAKEWORD(2, 2), &ws) == 0)
    {
        currentclient = 0;
        int maxclients = 2;//максимальное число клиентов
        cli_addr = new struct sockaddr_in[maxclients];
        clilen = new int[maxclients];
        buffer = new char* [maxclients];
        for (int i = 0; i < maxclients; i++)
        {
            clilen[i] = sizeof(cli_addr[i]);
        }
        sockfd = socket(AF_INET, SOCK_STREAM, 0);//tcp сокет
        if (sockfd < 0)
            error("ERROR opening socket");
        struct sockaddr_in serv_addr;
        bzero((char*)&serv_addr, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_addr.s_addr = INADDR_ANY;
        int port = 30000;//порт
        serv_addr.sin_port = htons(port);
        if (bind(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) < 0)
            error("ERROR on binding");
        if (listen(sockfd, 10) < 0)
            error("ERROR listen");
        HANDLE* thread;//массив потоков для каждого клиента отдельный
        struct arg_sa* args;
        while (true)
        {
            newsockfd = new int[maxclients];
            thread = (HANDLE*)malloc(sizeof(HANDLE) * maxclients);
            args = new struct arg_sa[maxclients];
            for (int i = 0; i < maxclients; i++)
            {
                args[i].lalk = new struct arg_s();
                buffer[i] = new char[buflen2];
            }
            int i = -1;
            while (++i < maxclients)
            {
                Sleep(1);
                args[i].current = i;
                args[i].lalk->exit = false;
                thread[i] = CreateThread(0, 0, (LPTHREAD_START_ROUTINE)(session_), args, 0, 0);
            }
                for (int i = 0; i < maxclients; i++)
                    WaitForSingleObject(thread[i], INFINITE);//ждем завершения всех потоков
            i = -1;
            while (++i < maxclients)
            {
                shutdown(newsockfd[i], 0);
                TerminateThread(thread[i], 0);
            }
            //delete[] newsockfd;
            //free(thread);
            currentclient = 0;
            for (int i = 0; i < maxclients; i++)
            {
                //delete args[i].lalk;
                //delete[] args[i].lalk->buffer;
            }
            //delete[] args;
        }
        shutdown(sockfd, 0);
        WSACleanup();
        return 0;
    }
    std::cin.ignore();
}

በአጭሩ፣ በዘላለማዊ ዑደት ውስጥ፣ ለእያንዳንዱ ደንበኛ ክሮች ይፈጠራሉ እና ደንበኞች እስኪገናኙ ድረስ መቀበልን ይጠብቁ። ከዚያ በኋላ WaitForSingleObject ሁሉም እስኪያልፍ ይጠብቃል። እያንዳንዱ ደንበኛ የራሱ ሶኬት እና የራሱ መላኪያ ቋት አለው። ማለትም፣ በአገልጋዩ ላይ M+1 መሰኪያዎች አሉ፣ M የደንበኞች ብዛት ነው። ሁሉም ማስተላለፎች ከተጠናቀቁ በኋላ, ሁሉም ነገር ይደገማል.

አሁን ደንበኛውን አስቡበት፡-

#include <iostream>
#include <WinSock.h>
#include <vector>
#pragma comment (lib,"WS2_32.lib")
void error(const char* msg)
{
    //perror(msg);
    std::cout << 'n' << WSAGetLastError();
    WSACleanup();
    std::cin.ignore();
    exit(1);
}
void bzero(char* buf, int l)
{
    for (int i = 0; i < l; i++)
        buf[i] = '';
}
typedef unsigned long long uint64_t;
typedef unsigned int uint32_t;
#define N 8
#define F32 0xFFFFFFFF
uint32_t RK[N];//раундовые ключи
#define size64 sizeof(uint64_t)
#define ROR(x,n,xsize)((x>>n)|(x<<(xsize-n)))
#define ROL(x,n,xsize)((x<<n)|(x>>(xsize-n)))
#define RKEY(r)((ROR(K,r*3,size64*8))&F32)
const uint64_t K = 0x96EA704CFB1CF671;//ключ шифрования
void createRoundKeys()
{
    for (int i = 0; i < N; i++)
        RK[i] = (ROR(K, i * 8, size64 * 8)) & F32;
}
uint32_t F(uint32_t subblk, uint32_t key)
{
    return subblk + key;//функция шифрования
}
uint64_t encrypt(uint64_t block)//зашифровка блоков сетью Фейстеля
{
    //select subblocks
    uint32_t left = (block >> 32) & F32;
    uint32_t right = block & F32;
    uint32_t left_, right_;//subblock in the end of round
    for (int r = 0; r < N; r++)
    {
        uint32_t fk = F(left, RK[r]);
        left_ = left;
        right_ = right ^ fk;
        if (r < N - 1)//swap places to next round
        {
            left = right_;
            right = left_;
        }
        else//last round not swap
        {
            left = left_;
            right = right_;
        }
    }
    //collect subblock in block
    uint64_t c_block = left;
    c_block = (c_block << 32) | (right & F32);
    return c_block;
}
int main()
{
    keybd_event(VK_LWIN, 0, 0, 0);
    keybd_event('M', 0, 0, 0);
    keybd_event('M', 0, KEYEVENTF_KEYUP, 0);
    keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0);//эти строки сворачивают все приложения
    Sleep(1000);//чтобы сделать скриншот рабочего стола
    WSADATA ws = { 0 };
    if (WSAStartup(MAKEWORD(2, 2), &ws) == 0)
    {
        int sockfd;
        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in serv_addr, cli_addr;
        bzero((char*)&serv_addr, sizeof(serv_addr));
        bzero((char*)&cli_addr, sizeof(cli_addr));
        serv_addr.sin_family = AF_INET;

        const char* add = "127.0.0.1";//адрес сервера
        serv_addr.sin_addr.s_addr = inet_addr(add);
        int port = 30000;//порт
        serv_addr.sin_port = htons(port);
        int servlen = sizeof(serv_addr);
        int n = connect(sockfd, (struct sockaddr*)&serv_addr, servlen);
        
        //ниже код делает скриншот
        HDC ScreenDC = GetDC(0);
        HDC MemoryDC = CreateCompatibleDC(ScreenDC);
        int ScreenHeight = GetSystemMetrics(SM_CYSCREEN);
        int ScreenWidth = GetSystemMetrics(SM_CXSCREEN);
        ScreenWidth = ((ScreenWidth - 1) / 4 + 1) * 4;
        BITMAPINFO BMI;
        BMI.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        BMI.bmiHeader.biWidth = ScreenWidth;
        BMI.bmiHeader.biHeight = ScreenHeight;
        BMI.bmiHeader.biSizeImage = ScreenWidth * ScreenHeight * 3;
        BMI.bmiHeader.biCompression = BI_RGB;
        BMI.bmiHeader.biBitCount = 24;
        BMI.bmiHeader.biPlanes = 1;
        DWORD ScreenshotSize;
        ScreenshotSize = BMI.bmiHeader.biSizeImage;
        unsigned char* ImageBuffer;
        HBITMAP hBitmap = CreateDIBSection(ScreenDC, &BMI, DIB_RGB_COLORS, (void**)&ImageBuffer, 0, 0);
        SelectObject(MemoryDC, hBitmap);
        BitBlt(MemoryDC, 0, 0, ScreenWidth, ScreenHeight, ScreenDC, 0, 0, SRCCOPY);
        DeleteDC(MemoryDC);
        ReleaseDC(NULL, ScreenDC);
        FILE* sFile = 0;
        unsigned char tgaHeader[12] = { 0, 0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
        unsigned char header[6];
        unsigned char tempColors = 0;
        fopen_s(&sFile, "S.tga", "wb");
        if (!sFile) {
            exit(1);
        }
        header[0] = ScreenWidth % 256;
        header[1] = ScreenWidth / 256;
        header[2] = ScreenHeight % 256;
        header[3] = ScreenHeight / 256;
        header[4] = BMI.bmiHeader.biBitCount;
        header[5] = 0;
        fwrite(tgaHeader, 1, sizeof(tgaHeader), sFile);
        fwrite(header, sizeof(header), 1, sFile);
        //конец записали изображение в файл
        
        //шифруем блоками полезную нагрузку изображения кроме хидеров
        createRoundKeys();
        std::vector<uint64_t>* msg = new std::vector<uint64_t>(),*crpt = new std::vector<uint64_t>();
        unsigned long long id;
        int i = 0;
        while (i < BMI.bmiHeader.biSizeImage)
        {
            memcpy(&id, (ImageBuffer + i), N);
            msg->push_back(id);
            i += 8;
        }
        std::cout << "i=" << i << std::endl; 
        uint64_t cipher;
        i = 0;
        char str_[N + 1];
        memset(str_, 0, N);
        str_[N] = '';
        for (std::vector<uint64_t>::iterator it = msg->begin(); it != msg->end(); ++it)
        {
            cipher = encrypt(*it);
            memcpy(str_, &cipher, N);
            fwrite((unsigned char*)str_, sizeof(unsigned char), N, sFile);
            i += 8;
        }
        std::cout << "i=" << i << std::endl;
        //
        //fwrite(ImageBuffer, BMI.bmiHeader.biSizeImage, 1, sFile);
        std::cout << BMI.bmiHeader.biSizeImage << std::endl;
        fclose(sFile);
        DeleteObject(hBitmap);
        FILE* f;
        fopen_s(&f, "S.tga", "rb");
        int count = 0;
        if (f != NULL)
        {
            while (getc(f) != EOF)
                count++;//считаем байты изображения в счетчик чтобы потом передать
            fclose(f);
        }
        count -= 18;
        std::cout << count<< std::endl;
        char* s = new char[100];
        _itoa_s(count, s, 100, 10);
        n = send(sockfd, s, 100, 0);//передаем счетчик
        char* buffer = new char[count];
        fopen_s(&f, "S.tga", "rb");
        size_t bytes;
        if (f != NULL)
        {
            memcpy(buffer, tgaHeader, sizeof(tgaHeader));
            n = send(sockfd, buffer, sizeof(tgaHeader), 0);
            bzero(buffer, count);
            memcpy(buffer, header, sizeof(header));
            n = send(sockfd, buffer, sizeof(header), 0);
            bzero(buffer, count);//передаем хидеры
            for(int i=0;i<18;i++)
                fgetc(f);
            bzero(buffer, count);
            bytes = fread(buffer, sizeof(unsigned char), count, f);
            n = send(sockfd,buffer, count, 0);//передаем шифрованные байты изображения
            fclose(f);
        }
        Sleep(1000);
        shutdown(sockfd, 0);
        WSACleanup();
        //system("del S.tga");
        delete[] buffer,s;
        return 0;
    }
    //std::cin.ignore();
}

የደንበኛው ሥራ ውጤት ይኸውና፣ የS.tga ቅጽበታዊ ገጽ እይታ ፋይል፣ የተመሰጠረ

በአሮጌ ክራንች ላይ ጥንታዊ ክራንች

ዴስክቶፕ ነው የሚመስለው።

እና ወደ አገልጋዩ የተላለፈው እና በ Screen.tga ዲኮድ የተደረገው ውጤት እዚህ አለ።

በአሮጌ ክራንች ላይ ጥንታዊ ክራንች

እንደሚመለከቱት ፣ የተለመደው የፌስቴል አውታረመረብ ለማመስጠር ተስማሚ አይደለም ፣ ግን የ CBC እና CFB ዘዴዎችን መጠቀም ይችላሉ ፣ ምናልባት የተሻለ ኢንክሪፕት የተደረገ ይሆናል ፣ እውነቱን ለመናገር ፣ አላጣራሁትም።

ለሚያደርጉት ጥረት እናመሰግናለን!

ምንጭ: hab.com

አስተያየት ያክሉ