Расшифровать зашифрованный объект на символ [] для memcpy - PullRequest
1 голос
/ 07 июля 2019

Я пытаюсь использовать Crypto ++ для шифрования и дешифрования unsigned char объекта.На сегодняшний день шифрование в порядке.Однако мне нужно, чтобы окончательно зашифрованное содержимое было сохранено в формате Hex в байтовом массиве или массиве символов, чтобы я мог передать его должным образом в memcpy.

Я использую Visual Studio 19 с последней версиейCrypto ++.

HexEncoder encoder(new FileSink(cout));
ByteQueue plain, cipher, recover;
unsigned char shellcode[] = "\xfc\xe8\x89\x00\x00\x00\x60";
unsigned char enc_shellcode[] ="\x6D\x30\xEB\x18\xF2\x01\x16";

plain.Put(reinterpret_cast<const byte*>(shellcode), sizeof(shellcode));

//Encryption:
CBC_Mode<AES>::Encryption enc;
enc.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

StreamTransformationFilter f1(enc, new Redirector(cipher));
plain.CopyTo(f1);
f1.MessageEnd();

cout << "Cipher text: ";
cipher.CopyTo(encoder);
encoder.MessageEnd();
cout << endl;

// Decryption
CBC_Mode<AES>::Decryption dec;
dec.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

StreamTransformationFilter f2(dec, new Redirector(recover));
cipher.CopyTo(f2);
f2.MessageEnd();

recover.CopyAllTo(encoder);
encoder.MessageEnd();
cout << endl;

// Allocating memory with EXECUTE writes
void* exec = VirtualAlloc(0, sizeof test, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

// Copying deciphered shellcode into memory as a function
memcpy(exec, /*Decrypted Shellcode..*/, sizeof test);

Я никогда не смогу вернуть данные в исходное unsigned char в шестнадцатеричной форме, чтобы загрузить данные в память ... Я не очень опытен в C ++, и яУверен, что для некоторых из вас это вполне справедливо, так что это может быть простое исправление или нет ...?

1 Ответ

0 голосов
/ 10 июля 2019

Я никогда не смогу вернуть данные в исходный беззнаковый символ в шестнадцатеричной форме, чтобы я мог загрузить данные в память ...

ByteQueue и MessageQueueобъекты конвейера Crypto ++ более высокого уровня.Когда данные передаются из источника в приемник , это хороший выбор.Но их может быть немного неудобно использовать, когда вы не используете приемник, как, например, с вашим memcpy.

Ниже приведены два примера того, что вы хотите сделать.

Такжеобратите внимание, это не совсем правильно.Размер зашифрованного текста должен быть кратным размеру блока из-за режима CBC и заполнения PKCS.В вашем случае зашифрованный шелл-код должен быть 16 байтов.

const byte enc_shellcode[] ="\x6D\x30\xEB\x18\xF2\x01\x16";

Pipeline

@ zett42 имеет правильную идею - используйте ArraySink, а конвейеры Crypto ++ будут делать memcpy для тебя.На самом деле вам даже не нужно plain или recover.Так что это будет выглядеть примерно так:(Я работаю в Linux, поэтому мне нужно подделать VirtualAlloc).

$ cat test.cxx
#include "cryptlib.h"
#include "filters.h"
#include "modes.h"
#include "files.h"
#include "aes.h"
#include "hex.h"

#include <iostream>

int main(int argc, char* argv[])
{
    using namespace CryptoPP;

    HexEncoder encoder(new FileSink(std::cout));
    ByteQueue cipher;

    const byte shellcode[] = "\xfc\xe8\x89\x00\x00\x00\x60";       

    const byte key[16] = {1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4};
    const byte  iv[16] = {8,7,6,5, 8,7,6,5, 8,7,6,5, 8,7,6,5};

    //Encryption
    CBC_Mode<AES>::Encryption enc;
    enc.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

    ArraySource plain(shellcode, 7, true);
    StreamTransformationFilter f1(enc, new Redirector(cipher));
    plain.CopyTo(f1);
    f1.MessageEnd();

    std::cout << "Cipher text: ";
    cipher.CopyTo(encoder);
    encoder.MessageEnd();
    std::cout << std::endl;

    // Allocating memory with EXECUTE writes
    // void* exec = VirtualAlloc(0, sizeof test, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // Proxy for VirtualAlloc
    byte x[7];
    void* exec = reinterpret_cast<void*>(x);

    // Decryption
    CBC_Mode<AES>::Decryption dec;
    dec.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

    ArraySink recover(reinterpret_cast<byte*>(exec), 7);
    StreamTransformationFilter f2(dec, new Redirector(recover));
    cipher.CopyTo(f2);
    f2.MessageEnd();

    // Can't use recover.CopyTo() here. ArraySink is not a source;
    // and the internal pointer is at the end of the array, not
    // the beginning of the array.
    std::cout << "Recover text: ";
    encoder.Put(reinterpret_cast<byte*>(exec), 7);
    encoder.MessageEnd();
    std::cout << std::endl;

    return 0;
}

Запуск кода приводит к выводу ниже.

$ g++ test.cxx ./libcryptopp.a -o test.exe
$ ./test.exe
Cipher text: 88BFA35C6ABF2EDF1FDCDC354721C72C
Recover text: FCE88900000060

C ++ объекты

Вы также можете использовать объекты C ++ вместо Crypto ++ ByteQueue.Это немного проще в использовании.

$ cat test.cxx
#include "cryptlib.h"
#include "filters.h"
#include "osrng.h"
#include "modes.h"
#include "files.h"
#include "aes.h"
#include "hex.h"

#include <string>
#include <iostream>

int main(int argc, char* argv[])
{
    using namespace CryptoPP;

    HexEncoder encoder(new FileSink(std::cout));

    // The embedded NULLs mean we need to use this ctor
    const std::string shellcode("\xfc\xe8\x89\x00\x00\x00\x60", 7);
    std::string cipher;

    const byte key[16] = {1,2,3,4, 1,2,3,4, 1,2,3,4, 1,2,3,4};
    const byte  iv[16] = {8,7,6,5, 8,7,6,5, 8,7,6,5, 8,7,6,5};

    //Encryption
    CBC_Mode<AES>::Encryption enc;
    enc.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

    StreamTransformationFilter f1(enc, new StringSink(cipher));
    StringSource(shellcode, true, new Redirector(f1));

    std::cout << "Cipher text: ";
    StringSource(cipher, true, new Redirector(encoder));
    std::cout << std::endl;

    // Allocating memory with EXECUTE writes
    // void* exec = VirtualAlloc(0, sizeof test, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

    // Proxy for VirtualAlloc
    byte x[7];
    void* exec = reinterpret_cast<void*>(x);

    // Decryption
    CBC_Mode<AES>::Decryption dec;
    dec.SetKeyWithIV(key, sizeof(key), iv, sizeof(iv));

    ArraySink recover(reinterpret_cast<byte*>(exec), 7);
    StreamTransformationFilter f2(dec, new Redirector(recover));
    StringSource(cipher, true, new Redirector(f2));

    // Can't use recover.CopyTo() here. ArraySink is not a source;
    // and the internal pointer is at the end of the array, not
    // the beginning of the array.
    std::cout << "Recover text: ";
    encoder.Put(reinterpret_cast<byte*>(exec), 7);
    encoder.MessageEnd();
    std::cout << std::endl;

    return 0;
}

И те же результаты, используя std::string:

$ g++ test.cxx ./libcryptopp.a -o test.exe
$ ./test.exe
Cipher text: 88BFA35C6ABF2EDF1FDCDC354721C72C
Recover text: FCE8899B7F0000
...