0

can anyone help me with this ERROR. i'm basically reading an exe file, decrypt it and copy it to memory and then executing it using createthread() but it seems that i've made some mistake when implementing this method.


unsigned char key[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
AES aes(128);
unsigned char* decipheredBuffer = aes.DecryptECB((unsigned char*)buffer, exeSize, key);


DWORD old_protect;

void* executable_area = VirtualAlloc(0, sizeof(decipheredBuffer), MEM_COMMIT, PAGE_EXECUTE_READWRITE);

if (executable_area == 0) {
    return 0;
}

memcpy(executable_area, decipheredBuffer, sizeof(decipheredBuffer));
//((void(*)())executable_area)();

bool protectTrue = VirtualProtect(executable_area, sizeof(decipheredBuffer), PAGE_EXECUTE_READWRITE, &old_protect);


if(protectTrue){
    void* hThread = CreateThread(NULL, sizeof(decipheredBuffer), (LPTHREAD_START_ROUTINE)executable_area, NULL, 0, NULL);
    if (hThread != 0) {
        WaitForSingleObject(hThread, 0xFFFFFFFF);//acess violation
    }
}

VirtualProtect(executable_area, sizeof(decipheredBuffer), old_protect, &old_protect);
VirtualFree(executable_area, 0, MEM_RELEASE);
  • 1
    `sizeof(decipheredBuffer)` doesn't do what you think it does in this situation. It is only the size of a pointer (4 bytes for a 32bit app, 8 bytes for a 64bit app), it is not the size of the buffer being pointed at. You need to get the actual buffer size from the decrypter that created it. – Remy Lebeau Oct 06 '21 at 16:45
  • 1
    After fixing that, note that setting a thread's stack size to be the total size of the whole executable is not a good idea. Just use the default stack size, or smaller, but certainly not bigger. But more importantly, there is a lot more involved to running an EXE from memory than just spawning a thread for it. There are lookups that have to be resolved/patched, etc. You should use a 3rd party library that is specifically designed for the task of running EXEs from memory. Otherwise, just save the EXE to a temp file and run it normally with `CreateProcess()` and let the OS loader do its work. – Remy Lebeau Oct 06 '21 at 16:52
  • i've used the exe size a you said, it points to a different position in assembly but the same error. the size is from file handler: exe.open(encExePath, ios::binary); exe.seekg(0, ios::end); exeSize = exe.tellg(); exe.seekg(0, ios::beg); // allocate memory: buffer = new char[exeSize]; // read data as a block: exe.read(buffer, exeSize); exe.close(); i'd love to use a library after this but i'm focusing on learning a bit about memory. but thank you for your suggestion i'll look for a library after this. – solideCode Oct 06 '21 at 18:39
  • Again, you can't just run an arbitrary EXE image as-is from memory, there is a lot more involved to setup and prepare the image for proper execution. There is a reason why the OS has to use a specialized loader when running EXE files and loading DLL files. you have to replicate what that loader does. DO NOT try to handle this manually, use an existing library that does the hard work for you. – Remy Lebeau Oct 06 '21 at 18:44
  • i don't know why it's so hard to do in c++ while c# made it very easy to allocate and inject bytes of an exe and works pretty well. – solideCode Oct 06 '21 at 19:30
  • here is the code i've wrote with c# and it works like charm: `byte[] resultP = decode(Sky, pp_list_bb); //byte[] resultP = { 33, 43, 65, 23}; UInt32 addres= VirtualAlloc(0, 257, MEM_COMMIT, PAGE_EXECUTE_READWRITE); Marshal.Copy(resultP, 0, (IntPtr)(addres), resultP.Length); //Console.WriteLine(addres); UInt32 thrId = 11; IntPtr hThr = CreateThread(0, 2, addres, IntPtr.Zero, 1, ref thrId); WaitForSingleObject(hThr, 1290957295);` – solideCode Oct 06 '21 at 19:38
  • That C# code is doing the same thing as the C++ code above (assuming you fix the buffer size issue). Assuming the *buffer data* is the same in both codes (did you verify that?), the ONLY differences between the codes are 1) omission of `VirtualProtect()` in the C# code, which is redundant in the C++ code; 2) different parameters values on `CreateThread()`; 3) different timeouts on `WaitForSingleObject()`. Either way, you simply CANT RUN AN EXE IMAGE THIS WAY, even in C#. So clearly the buffer is not an actual EXE, it is just a block of executable code, which is not the same thing as an EXE – Remy Lebeau Oct 06 '21 at 19:45
  • oh so this way is not legit for executing exe bytes? and what do you mean by executable code is it just c++ code in bytes? – solideCode Oct 06 '21 at 20:00
  • Are you dealing with an *actual* [PE-formatted](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format) EXE file (which has a PE header, section tables, resources, etc)? You kept mentioning an EXE file, which has those kind of things in it. But the code you have is not prepared to handle actual EXE files, only straight up executable code by itself (ie, basically a standalone function). It would really help if you clarify what it is you are actually trying to run. – Remy Lebeau Oct 06 '21 at 20:07
  • But in any case, short of a buffer overflow corrupting memory, I don't see anything in the C++ code above that would cause `WaitForSingleObject()` to crash the way you have described. – Remy Lebeau Oct 06 '21 at 20:10
  • the exe i tried to run is actually a c++ code that i wrote myself and still have the source code. how can i get the executable code from that? – solideCode Oct 06 '21 at 20:11
  • i just read the exe file in binary with ifstream and used that buffer to write to memory. – solideCode Oct 06 '21 at 20:34
  • you CAN'T read an `.exe` file into memory and run it AS-IS. You CAN'T get executable code from source code WITHOUT compiling it first. Maybe reading an `.obj` file would suit your needs? Hard to say since you haven't explained your GOAL yet. – Remy Lebeau Oct 06 '21 at 21:00
  • basically, I want to encrypt my software and add it as a resource then decrypt it on the fly and run it from memory. what I understand from you is that I should compile my software in a different format to get the executable code. – solideCode Oct 06 '21 at 21:11
  • Then your current approach will not work *as-is*, you need to prepare the decrypted EXE's PE data before running it. 3rd party code can handle that, for example [Run-PE](https://github.com/codecrack3/Run-PE---Run-Portable-Executable-From-Memory). Or, if you change your software to be a DLL instead of an EXE, then look at [fancycode/MemoryModule](https://github.com/fancycode/MemoryModule). Lots of choices available, if you [search around](https://www.google.com/search?q=c%2B%2B+run+exe+from+memory). – Remy Lebeau Oct 06 '21 at 21:58
  • i guess exe is simpler. does it accept the sam exe buffer that i used in my rubbish code? – solideCode Oct 06 '21 at 22:26
  • i works with an error inside the exe i try to run, but when i decrypt the encrypted one and run it i get read access violation again, the AES encryption returns an address. how do i get the whole buffer using an address. – solideCode Oct 06 '21 at 22:37
  • Are you saying that the *original* (not the decrypted) EXE, when saved to a file and run normally, generates errors? Have you verified that your AES code is even working properly? Have you tested it by itself? You can't get the size given only an address. The encryption/decryption has to tell you the size – Remy Lebeau Oct 06 '21 at 22:38
  • yes when i decode it and save it as another exe it works fine. i guess the ofstream kows how to handle the address that the decryption func returns – solideCode Oct 06 '21 at 22:40
  • The ofstream simply writes whatever you give it, but you still have to tell it how much to write. – Remy Lebeau Oct 06 '21 at 22:41
  • oh it finally worked, thank you so much, I've been struggling for two days with this. this is exactly what i needed – solideCode Oct 06 '21 at 22:43
  • do you know how to get the data from a binary resource using the pointer `lockresource()` gives you. – solideCode Oct 06 '21 at 22:49
  • ok, i used `str.assign()` thanks for your help again – solideCode Oct 06 '21 at 22:58

0 Answers0