Shellcode from vector into virtualalloc does not work

I am having a hard time figuring out why the payload isn't working after decryption in example2.cpp, when executing the compiled exe with the command 'example2.exe > out.txt' I get the shellcode which is valid and does not cause any problem in example.cpp because I can see the output which is hello world (at least in my case)

example.cpp

unsigned char out[] = "\x00\x00...";
int main()
{
    void *exec = VirtualAlloc(0, sizeof(out), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, out, sizeof(out));
    ((void(*)())exec)();
}

example2.cpp

void decrypt_run(){
    std::vector<unsigned char> decrypted(encrypted.size());
    // the encrypted cipher get decrypted and the vector decrypted is filled with unsigned chars
    unsigned char buf[decrypted.size()];
    // converting the vector to an unsigned char buffer to be passed to memcopy 
    std::copy(decrypted.begin(), decrypted.end(), buf);
    size_t shellcodesize = sizeof(buf);
    cout << buf << endl;  // prints the shellcode to the screen 
    //void *exec = VirtualAlloc(0, shellcodesize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    //memcpy(exec, buf, shellcodesize);
    //((void(*)())exec)();
}
int main()
{
    decrypt_run();
    return 0;
}

when uncommenting the last three lines in decrypt_run() the program finishes without any output other than the shellcode it self

Again the same shellcode in the out.txt is used with example.cpp and it runs flawlessly but not with example2.cpp


Solution 1:

In the first case, you are hard-coding the shellcode in a fixed memory buffer, and then copying those bytes as-is into your allocated executable memory. Which is fine.

But in your second case, you have a dynamic vector filled with the (decrypted) shellcode bytes, and then you are allocating a dynamic array using non-standard VLA syntax, copying the shellcode into that array, and then copying the shellcode from that array into your executable memory. That intermediate array is completely unnecessary and should be removed, you can copy the shellcode bytes directly from the vector into the executable memory, eg:

void decrypt_run(){
    std::vector<unsigned char> decrypted(encrypted.size());
    // the encrypted cipher get decrypted and the vector decrypted is filled with unsigned chars
    // passing the vector to memcopy 
    unsigned char *buf = decrypted.data();
    size_t shellcodesize = decrypted.size();
    cout << buf << endl;  // prints the shellcode to the screen 
    void *exec = VirtualAlloc(0, shellcodesize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(exec, buf, shellcodesize);
    ((void(*)())exec)();
}