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
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
vectorfilled 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 thevectorinto the executable memory, eg: