【问题标题】:Decrypt an encrypted object to a char[] for memcpy将加密对象解密为 char[] for memcpy
【发布时间】:2019-07-07 19:37:07
【问题描述】:

我正在尝试使用 Crypto++ 加密和解密 unsigned char 对象。到目前为止,加密很好。但是,我需要将最终解密的内容以十六进制格式保存在字节数组或字符数组中,以便我可以正确地将其交给 memcpy。

我正在使用带有最新版本 Crypto++ 的 Visual Studio 19。

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++不是很精通,我相信这对你们中的一些人来说是相当反对的,所以这可能是一个简单的修复或不是......?

【问题讨论】:

  • 什么“十六进制形式”?"\xfc\xe8\x89\x00\x00\x00\x60" 只是一个数字数组 ({252, 232, 137, 0, 0, 0, 96, 0})。
  • 内部没有“十六进制形式”这样的东西。这些只是普通的整数。如果你想显示十六进制,那就另当别论了。
  • 当我说十六进制时,我指的是驻留在上述unsigned char 变量中的数据。我只需要最终输出与初始输入的格式相同。
  • 那你根本不需要HexEncoder
  • 例如使用ArraySink

标签: c++ decode crypto++


【解决方案1】:

我永远无法将数据恢复为十六进制形式的原始 unsigned char,以便我可以将数据加载到内存中......

ByteQueueMessageQueue 是更高级别的 Crypto++ 管道对象。当data is flowing from a source to a sink 他们是一个不错的选择。但是当你不使用水槽时,它们可能会有点尴尬,比如你的memcpy

下面是两个做你想做的事的例子。

还要注意这并不完全正确。由于 CBC 模式和 PKCS 填充,密文大小必须是块大小的倍数。在您的情况下,加密的 shellcode 应该是 16 个字节。

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

管道

@zett42 有正确的想法 - 使用 ArraySink,Crypto++ 管道将为您执行 memcpy。事实上,您甚至不需要plainrecover。所以它看起来像下面这样。 (我在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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-29
    • 1970-01-01
    • 2019-06-06
    • 1970-01-01
    • 2015-12-29
    相关资源
    最近更新 更多