wow64ext v1.0.0.7

New version of wow64ext library is available for download:


  • All 64bit APIs are now properly setting last Win32 error, thanks goes to Dreg ( who implemented this feature.

This is actually unexpected benefit from hosting wow64ext on github (google code is dead, long live github), so if some of you want to add something to this library do not hesitate to do pull requests. I can’t promise that I’ll accept everything, but at least you may try :) Here is the address:

Comments (62)

  1. 00:55, September 1, 2015Carlos  / Reply

    There is an error in VirtualQueryEx64, sometimes returns 0 depending on the number of variables previously declared. I think it should be a problem in the stack, it is curious that when you declare a variable type BOOL, is sufficient for VirtualQueryEx64 fail.


    • 01:10, September 1, 2015ReWolf  / Reply

      Hi, thanks for the report. Can you send me some simple code snippet, so I can reproduce this issue ?

  2. 19:05, September 1, 2015Carlos  / Reply

    OK. This is an example of code that fails

    #pragma hdrstop
        ULONGLONG BaseAddress;
        ULONGLONG AllocationBase;
        DWORD     AllocationProtect;
        DWORD     __alignment1;
        ULONGLONG RegionSize;
        DWORD     State;
        DWORD     Protect;
        DWORD     Type;
        DWORD     __alignment2;
    extern "C"
      SIZE_T VirtualQueryEx64(HANDLE hProcess, DWORD64 lpAddress, MEMORY_BASIC_INFORMATION64* lpBuffer, SIZE_T dwLength);
      BOOL ReadProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesRead);
      BOOL WriteProcessMemory64(HANDLE hProcess, DWORD64 lpBaseAddress, LPVOID lpBuffer, SIZE_T nSize, SIZE_T *lpNumberOfBytesWritten);
      BOOL Result = false;
      MEMORY_BASIC_INFORMATION64 mbi64 = { 0 };
      DWORD64 Start = 0;
      PBYTE   Buffer;
      SIZE_T  nBytesRead;
      while(VirtualQueryEx64(hProc, Start, &mbi64, sizeof(mbi64))){
        if(mbi64.Protect && !(mbi64.Protect & (PAGE_NOACCESS | PAGE_GUARD))){
           Buffer = (PBYTE)VirtualAlloc(0, mbi64.RegionSize, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
             if(ReadProcessMemory64(hProc, mbi64.BaseAddress, Buffer, (SIZE_T)mbi64.RegionSize, &nBytesRead) && (nBytesRead == mbi64.RegionSize)){
               //some code...
             VirtualFree(Buffer, 0, MEM_RELEASE);
        Start += mbi64.RegionSize;
      return Result;
    #pragma argsused
    int main(int argc, char* argv[])
      PROCESSENTRY32 Proc;
      HANDLE hSysSnapshot;
      Proc.dwSize = sizeof(PROCESSENTRY32);
      hSysSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
      if(Process32First(hSysSnapshot, &Proc)){
          if(!lstrcmpi(Proc.szExeFile, "notepad.exe"))
        }while(Process32Next(hSysSnapshot, &Proc));
      return 0;

    The compiler is BCB5 over Win10
    Similar code in delphi7 also fail.


    • 20:48, September 1, 2015ReWolf  / Reply

      I think that I know what is the issue here. MEMORY_BASIC_INFORMATION64 mbi64 has address aligned to 4 instead of 8 and x64 version of NT API refuse to work (it probably returns STATUS_DATATYPE_MISALIGNMENT 0x80000002). To prove that I’m right, you can printf address of mbi64 before VirtualQueryEx64 call:

      printf("%pn", &mbi64);

      I’ve no idea if BCB5/Delphi7 has any directive to force alignment of the local variable, but if it has, then address of mbi64 should be aligned to 8. I wasn’t able to trigger this problem with Visual Studio as it seems it always properly align this structure on the stack. I assume that it might be because of the way how it is declared:

          ULONGLONG BaseAddress;
          ULONGLONG AllocationBase;
          DWORD     AllocationProtect;
          DWORD     __alignment1;
          ULONGLONG RegionSize;
          DWORD     State;
          DWORD     Protect;
          DWORD     Type;
          DWORD     __alignment2;
  3. 19:08, September 1, 2015Carlos  / Reply

    Lo siento las etiquetas de código han borrado

    y han deshecho la indentación.


  4. 01:51, September 2, 2015Carlos  / Reply

    I tried to force alignment MEMORY_BASIC_INFORMATION64 to 8 and the error persists. MEMORY_BASIC_INFORMATION64 size is 48 and its direction is 0x0019FDCC

    #pragma pack( push )
    #pragma pack( 8 )
    typedef struct _MEMORY_BASIC_INFORMATION64 {
        ULONGLONG BaseAddress;
        ULONGLONG AllocationBase;
        DWORD     AllocationProtect;
        DWORD     __alignment1;
        ULONGLONG RegionSize;
        DWORD     State;
        DWORD     Protect;
        DWORD     Type;
        DWORD     __alignment2;
    #pragma pack( pop )


    • 02:16, September 2, 2015ReWolf  / Reply

      #pragma pack won’t help as it only affects the internal layout of the structure, not the stack allocation address. In VC there is __declspec(align(n)) (DECLSPEC_ALIGN macro) and it guarantee that the address of the structure on the stack will be aligned to n (in our case it is 16). Your address 0x0019FDCC is obviously aligned to 4, that’s why it’s not working.

  5. 21:08, September 2, 2015Carlos  / Reply

    Ok, that’s the problem, but I can´t configure the compiler to align to 8.
    I have located a pointer to VirtualAlloc, instead of declaring a variable in the stack MEMORY_BASIC_INFORMATION64 and with this works fine. I dont know if VirtualAlloc always performs an alignment to 8 or 16, you who you think?

    • 23:05, September 2, 2015ReWolf  / Reply

      VirtualAlloc allocates always at the page boundary so it is aligned not only to 8 and 16 but even to 0x1000. It will work, however I think that it is not necessary. You can try below code:

      #define ALIGNUP(addr, alignment) (((addr) + (alignment) - 1) - ((size_t)(addr) + (alignment) - 1) % (alignment))
      	char mbi64_buf[sizeof(MEMORY_BASIC_INFORMATION64) + 16];

      ALIGNUP macro simply adjusts pointer, so it is aligned to requested value (in this case 16), I’ve taken it from
      mbi64_buf is simple buffer, size of this buffer should be bigger than sizeof(MEMORY_BASIC_INFORMATION64). Adding alignment value to the size is sufficient, so it will always have enough memory for the structure. Then you can put mbi64_buf to ALIGNUP macro and cast it to MEMORY_BASIC_INFORMATION64 reference or pointer (whatever you prefer most). This will reduce overhead of VirtualAlloc and it should work fine.

      • 00:03, September 3, 2015Carlos  / Reply

        Very good trick, in fact I was thinking of doing something similar. Both VirtualAlloc, as ALIGNUP, works fine.

        Thank you very much, you’ve done a good job with your wow64ext library

        • 00:49, September 3, 2015ReWolf  / Reply

          I’m glad that it works :) Thanks for the kind words!

  6. 09:17, November 22, 2015Terry  / Reply

    Hi Rewolf,

    I found an error when use: GetProcAddress64(GetModuleHandle64(L”wow64cpu.dll”),”X86SwitchTo64BitMode”)

    please help to confirm this error.

    • 10:18, November 22, 2015ReWolf  / Reply

      I guess you’re trying it on Windows 10. It won’t work on Windows 10, because Microsoft removed wow64cpu!X86SwitchTo64BitMode export. Far jump to wow64cpu!CpupReturnFromSimulatedCode is placed inside wow64 NTDLL in not exported Wow64SystemServiceCall function. You can find address of this function by simply disassembling any NT api:

          mov     eax, 1A0006h    ; NtReadFile
          mov     edx, offset _Wow64SystemServiceCall@0 ; Wow64SystemServiceCall()
          call    edx ; Wow64SystemServiceCall() ; Wow64SystemServiceCall()
          retn    24h
      • 11:56, November 22, 2015Terry  / Reply

        OS: Windows Server 2008 R2 Enterprise.

        • 12:35, November 22, 2015ReWolf  / Reply

          Ok, in this case I would like to ask you to send me wow64cpu.dll (you can put it on some shared hosting). You can also print the results of GetModuleHandle64(L”wow64cpu.dll”);

          • 13:12, November 22, 2015Terry 

            Hi Rewolf,
            wow64cpu.dll download link:

            It works to get the handle by GetModuleHandle64(L”wow64cpu.dll”)

            also works on your sample:

          • 13:53, November 22, 2015ReWolf 

            I can’t download this file, try to send it to my email: rewolf []

        • 15:14, November 22, 2015Terry  / Reply

          Failed to send mail.

          please try new link:


          • 17:25, November 22, 2015ReWolf 

            Well, it seems that this DLL doesn’t contain X86SwitchTo64BitMode export and it’s quite fresh: 0x562593AB (GMT: Tue Oct 20 01:06:51 2015). They probably changed something with the recent update.

          • 19:05, November 22, 2015ReWolf 

            Alright, I was a bit mistaken in my previous comments. Obviously, you can’t use GetProcAddress64 to obtain address of X86SwitchTo64BitMode, because it was NEVER exported :), so they didn’t change anything. I thought that it was exported in the past, but apparently not. It’s as simple as that.

  7. 06:28, December 1, 2015Mark  / Reply

    Do you think you can port rewolf-wow64ext to be complied in MSVC? I’ve tried to compile it in a project of mine in MSVC2005 and I couldn’t :(

    • 09:21, December 1, 2015ReWolf  / Reply

      It should compile with VS2010 and newer, VS2005 is kind of ancient compiler nowadays.

    • 15:05, December 6, 2015Mark  / Reply


      Regarding VirtualQueryEx64 I’ve changed the size parameter as you told me, so now it works, here is the informations about the process that can’t be read via ReadProcessMemory64 completely :

      C:\Users\Mike\robot\La2Robot.exe (0x0000000000010000)
      B[0x0000000000010000] AB[0x0000000000010000] MB[0x0000000000010000] S[319488] RS[4096] ST[0x00001000] AP[0x00000080] P[0x00000002] T[0x01000000] C[0] R/FAIL x86_64[299]

      I think for the main process, I must use the base address provided by VirtualQueryEx64 instead ? Because probably the one returned by PEB/LDR (for .net executables) is being fooled by windows ? :D

      • 15:12, December 6, 2015Mark  / Reply

        Hm my last question didn’t made sense lol, the base address is the same everywhere even when returned by VirtualQueryEx, just that I can’t read it :P

        The report by VirtualQueryEx says it is a valid allocation with read access, who knows what’s up :P

        • 09:06, December 8, 2015ReWolf  / Reply

          Sorry for late answer, there is a possibility that the image memory is not continuous, in that case you need to read process memory in chunks. Information about each chunk can be obtained by consecutive calls to VirtualQueryEx.

  8. 14:09, December 1, 2015Mark  / Reply

    How we can call methods such as EnumProcessModulesEx via rewolf ? (In 64-bit mode ?)

    • 14:35, December 1, 2015Mark  / Reply

      Seems like we must call it from psapi.dll, but I can’t get the address the same way that is done with ntdll.dll (the dll is not found in 64-bit address space), any clue if this could be done ?

      • 14:46, December 1, 2015Mark  / Reply

        The purpose here is that I want to enumerate the process modules in a 64 bit process, from a 32 bit process (But currently now, there is no “official way” to do this hehehe).

        • 15:10, December 1, 2015ReWolf  / Reply

          You need to use NtQuerySystemInformation with the SystemProcessInformation class.

          • 15:15, December 1, 2015Mark 

            Oh, ok, so we must be doing it all by ntdll.dll, another question can we do it via PEB/TEB of the open process handle too ?

          • 15:41, December 1, 2015ReWolf 

            Alright, I misread your earlier comment and I thought that you want to enum processes :) As for the process modules, yes, you can use modules list from PEB.

          • 16:06, December 1, 2015Mark 

            Actually I need to do both things ! :D

            However it seems windows already provides the module handle, just that you can’t enumerate modules or anything because it is a 64-bit process.

          • 16:07, December 1, 2015Mark 

            But the question is, how one would get PEB/TEB of a process handle ? Your example shows how to do it in the current process, but in this case I’ll have a process Handle for the process I want to access it.

          • 16:47, December 1, 2015ReWolf 

            You can call NtQueryInformationProcess with ProcessBasicInformation, check out MSDN for further details as this particular case is documented. I’m not sure at this moment if you can call standard NtQueryInformationProcess or you have to call it through wow64ext, but I’m sure you’ll figure it out.

        • 19:03, December 1, 2015Mark  / Reply

          Hm, I’m having lots of troubles, isn’t there any way to call EnumProcessModulesEx but in 64-bit mode ? So this way it could read the proper informations and fill the output buffers ? It is all I want, so I can read the memory of the process and its modules using the ReadProcessMemory64 you’ve implemented :O

          • 19:19, December 1, 2015ReWolf 

            There is no way to load 64bit psapi.dll (and 64bit kernelbase.dll as well) into 32bit process.EnumProcessModulesEx internally calls NtQueryInformationProcess with ProcessBasicInformation and then it uses ReadProcessMemory to read PEB and other data from the target process. If you want the same behavior then you have to emulate it on your own.

          • 19:49, December 1, 2015Mark 

            Ok, is there an alternative to OpenProcess in ntdll ? Because it seems the handle I’m passing to NtqueryInformationProcess in wow64 doesn’t work (probably because it is open in the 32 bit space).

          • 20:59, December 1, 2015ReWolf 

            Standard OpenProcess should work fine, look at the sample directory in wow64ext project (alternative would be NtOpenProcess, but it isn’t necessary).

          • 22:53, December 1, 2015Mark 

            Ok, but when I try to useNtQueryInformationProccess in 32 bit environment (not via wow64) it returns this value : FFFFFFFFC0000004
            And when I try it via wow64, I get :

            In any case, no clue why but I can’t get PEB through it :(

          • 22:58, December 1, 2015ReWolf 

            0xC0000004 – STATUS_INFO_LENGTH_MISMATCH, so you’re probably passing wrong arguments
            0xC0000005 – STATUS_ACCESS_VIOLATION, no idea what can cause it atm

            If you want, you can send me your code by e-mail and I’ll look at it when I’ll have some spare time.

          • 00:04, December 2, 2015Mark 

            I had to call : NtWow64QueryInformationProcess64, now it worked and I get a valid PEB Address, now I’ll need to use ReadProcessMemory64 all the way It seems. (At least in every pointer I want to access stuff :P)

      • 01:37, December 2, 2015Mark  / Reply


        Ok, that’s it, almost 100% working (I’ve used the iteration method you’ve used to GetProcAddress however, using ReadProcessMemory between the pointers, so I could “navigate” through PEB/Lists, however, how we can get the Image Size for the modules now ? Any ideas ?

        • 02:07, December 2, 2015Mark  / Reply

          Found it too (Ldr Entry) ;), all sorted, thanks for the help on all questions.

        • 02:41, December 2, 2015Mark  / Reply

          One last question actually, regarding x64 .net processes :

          C:\Users\Fred\Downloads\TRENDNET\robot\La2Robot.exe (0x0000000000360000)
          READ ERROR 1 – x86_64
          C:\WINDOWS\SYSTEM32\ntdll.dll (0x00007FFA42A60000)
          Success, Bytes Read (x86_64) : 1839104 – 1839104
          C:\WINDOWS\SYSTEM32\MSCOREE.DLL (0x00007FFA33710000)
          Success, Bytes Read (x86_64) : 425984 – 425984
          C:\WINDOWS\system32\KERNEL32.dll (0x00007FFA409D0000)
          Success, Bytes Read (x86_64) : 708608 – 708608

          I can read basically all the modules loaded by it, but the main process does not allow me to be reading it, what could be causing it ? For native processes it works nicely, just .net ones aren’t good.

          • 10:06, December 2, 2015ReWolf 

            Try using VirtualQueryEx64 on that address and check the access rights and real size of the region.

          • 16:09, December 5, 2015Mark 

            Hi, I forget to ask, but should the wowext64 work in any x86_64 version of windows ? Such as : xp sp3 / vista / w7 / 8 / 8.1 and 10 ? Or is this specific only to certain builds of windows ?

          • 18:46, December 5, 2015ReWolf 

            I’m not sure about xp64, but it should definitely work on Vista+ (up to Win10 TH2, tested).

          • 18:48, December 5, 2015Mark 


            Ok great, I have asked because I’ll deploy it in production ;)

          • 18:59, December 5, 2015ReWolf 

            Cool :) Can you share (privately) some details about your project ? I’m always curious about the projects that uses wow64ext.

          • 21:54, December 5, 2015Mark 


            It is a small antihack for a gameserver :), btw I’m having issues with ReadProcessMemory64 in AMD CPU, the same code works 100% stable in Intel, however any PC with AMD CPU is causing an access violation, trying to discover what could be the problem right now.

          • 01:20, December 6, 2015Mark 


            VirtualQueryEx64 returns error 299 (partial copy) for that particular process. (It doesn’t completes properly).

        • 22:11, December 5, 2015Mark  / Reply


          READ NAME
          READ NAME – OK
          Name: c:\windows\system32\actxprxy.dll
          Base: 0x00007FFED3D30000 (PEB/Module Base)
          Alloc Address: 0x00007FFEDBF90000
          Base: 0x00007FFEDBF90000 (Base reported by VirtualQuery)
          Size:2813952 – 4096
          State: 0x00001000
          Protect: 0x00000080 – 0x00000002
          Type: 0x01000000
          READ (It stops here, it doesn’t even return it crashes calling ReadProcessMemory64)

          Here is some data, of the location I’m trying to read :)

          • 02:22, December 6, 2015Mark 


            Indeed, not sure why but all users with AMD x86_64 CPU cannot run the code properly, eventually it will crash somewhere hehe, probably something different with these CPUs.

          • 02:32, December 6, 2015Mark 


            Here is the code sample:

            PBI64 _pbi;
            DWORD nRetLen = 0;
            typedef NTSTATUS (__stdcall *_NtQueryInformationProcess)(HANDLE ProcessHandle,PROCESSINFOCLASS ProcessInformationClass,PVOID ProcessInformation,ULONG ProcessInformationLength,PULONG ReturnLength OPTIONAL);
            _NtQueryInformationProcess NTQ = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtWow64QueryInformationProcess64");
            if ( NTQ && NTQ(hProcess, PROCESSINFOCLASS::ProcessBasicInformation, &_pbi, sizeof(PBI64), &nRetLen) == STATUS_SUCCESS ) {
            	PEB64 _peb;
            	DWORD nBytesRead = 0;
            	if ( ReadProcessMemory64(hProcess, _pbi.PebBaseAddress, &_peb, sizeof(PEB64), &nBytesRead) && nBytesRead == sizeof(PEB64) ) {
            		PEB_LDR_DATA64 _ldr;
            		nBytesRead = 0;
            		if ( ReadProcessMemory64(hProcess, _peb.Ldr, &_ldr, sizeof(PEB_LDR_DATA64), &nBytesRead) && nBytesRead == sizeof(PEB_LDR_DATA64) ) {
            			DWORD nModCount = 0;
            			DWORD64 LastEntry = _peb.Ldr + offsetof(PEB_LDR_DATA64, InLoadOrderModuleList);
            			LDR_DATA_TABLE_ENTRY64 cursor;
            			cursor.InLoadOrderLinks.Flink = _ldr.InLoadOrderModuleList.Flink;
            				nBytesRead = 0;
            				if ( ReadProcessMemory64(hProcess, cursor.InLoadOrderLinks.Flink, &cursor, sizeof(LDR_DATA_TABLE_ENTRY64), &nBytesRead) &&
            					nBytesRead == sizeof(LDR_DATA_TABLE_ENTRY64) ) {
            					wchar_t* wDllName = (wchar_t*)malloc(cursor.FullDllName.MaximumLength);
            					if ( wDllName ) {
            						nBytesRead = 0;
            						if ( ReadProcessMemory64(hProcess, cursor.FullDllName.Buffer, wDllName, cursor.FullDllName.MaximumLength, &nBytesRead) ) {
            							/* Scanning Signatures - Heuristic Module */
            							DWORD nImageSize = cursor.SizeOfImage;
            							if ( nImageSize > AB_MAX_IMG_SIZE )
            								nImageSize = AB_MAX_IMG_SIZE-1;
            							MEMORY_BASIC_INFORMATION64 _mbi;
            							DWORD nVQBufSize = VirtualQueryEx64(hProcess, cursor.DllBase, &_mbi, nImageSize);
            							DWORD nGLE = GetLastError();
            							wprintf(L"XNAME: %s %d %dn", wDllName, nVQBufSize, nGLE);
            			while (cursor.InLoadOrderLinks.Flink != LastEntry);

            It is quite simple, I provide the process handle with all the necessary permissions and loop through the modules, eventually it crashes, it is not related to ReadProcessMemory64 or VirtualQueryEx64 seems like to be something “generic” causing the problem I guess…

          • 13:02, December 6, 2015ReWolf 

            I’ve no idea what might be causing the crashes on AMD, but I see one problem in your usage of VirtualQueryEx, fourth argument should be sizeof(_mbi):

            DWORD nVQBufSize = VirtualQueryEx64(hProcess, cursor.DllBase, &_mbi, sizeof(_mbi));

            Regarding the crash, do you use the latest wow64ext sources/dll ?

    • 14:45, December 6, 2015Mark  / Reply


      Yes, I’m using the latest one from GitHub, seems like some stack corruption or something like that, because the crash happens randomly, literally. (Even if you remove VirtualQueryEx out of the code, and just keep the PEB/LDR looping it will crash eventually (by just using ReadProcessMemory64).

      I thought it was something wrong, but then when all AMD users complaint about not being able to keep the game running (because it was closing itself) then I figured something was a bit crazy hehehe. Then I made the test with only the loop, without anything else inside, but the problem persisted as well.

      • 14:46, December 6, 2015ReWolf  / Reply

        Yup, I’ve reproduced it on some amd machine, I’m already looking at the crashdumps, so hopefully I’ll be able to fix it :)

        • 14:56, December 6, 2015Mark  / Reply


          Oh very nice :D

        • 18:26, December 10, 2015Mark  / Reply

          Hi, looks like this one is a bit complex, having lucky ?

          • 18:38, December 10, 2015ReWolf 

            I’ve tried to contact you by e-mail, but maybe it went to spam :) I’ve possible fix, please send me an e-mail to rewolf [] and hopefully you’ll be able to receive my reply (or check your spam folder :) )

          • 18:52, December 10, 2015Mark 

            Oh, lol, that’s because this box is spammed as hell as I use it only for posting everywhere, but not to anything else (so not checking it frequently), but now I’ve checked it :D

    • 14:48, December 6, 2015Mark  / Reply


      Right now the code is being used by 200+ users simultaneously in Intel CPU, just not in AMD. So the code seems to be working, at least for these users.

Leave a Reply

Allowed Tags - You may use these HTML tags and attributes in your comment.

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

Pingbacks (0)

› No pingbacks yet.