wow64ext v1.0.0.7

New version of wow64ext library is available for download:
http://rewolf.pl/stuff/rewolf.wow64ext.v1.0.0.7.zip

Changelog

  • All 64bit APIs are now properly setting last Win32 error, thanks goes to Dreg (http://www.fr33project.org/) 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:
https://github.com/rwfpl/rewolf-wow64ext

62 Comments

  1. 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.

    Regards.

    Reply

  2. OK. This is an example of code that fails

    //---------------------------------------------------------------------------
     
    #include 
    #include 
    #pragma hdrstop
     
    //---------------------------------------------------------------------------
     
    typedef struct DECLSPEC_ALIGN(16) _MEMORY_BASIC_INFORMATION64 {
        ULONGLONG BaseAddress;
        ULONGLONG AllocationBase;
        DWORD     AllocationProtect;
        DWORD     __alignment1;
        ULONGLONG RegionSize;
        DWORD     State;
        DWORD     Protect;
        DWORD     Type;
        DWORD     __alignment2;
    } MEMORY_BASIC_INFORMATION64, *PMEMORY_BASIC_INFORMATION64;
     
    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 Read(DWORD PID)
    {
      BOOL Result = false;
      MEMORY_BASIC_INFORMATION64 mbi64 = { 0 };
      DWORD64 Start = 0;
      PBYTE   Buffer;
      SIZE_T  nBytesRead;
     
      HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);
     
      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(Buffer){
             if(ReadProcessMemory64(hProc, mbi64.BaseAddress, Buffer, (SIZE_T)mbi64.RegionSize, &nBytesRead) && (nBytesRead == mbi64.RegionSize)){
               //some code...
             }
             VirtualFree(Buffer, 0, MEM_RELEASE);
           }
        }
        Start += mbi64.RegionSize;
      }
      CloseHandle(hProc);
      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)){
        do{
          if(!lstrcmpi(Proc.szExeFile, "notepad.exe"))
             Read(Proc.th32ProcessID);
        }while(Process32Next(hSysSnapshot, &Proc));
      }
      CloseHandle(hSysSnapshot);
      return 0;
    }
    //---------------------------------------------------------------------------

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

    Regards.

    Reply

    1. 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:

      typedef struct DECLSPEC_ALIGN(16) _MEMORY_BASIC_INFORMATION64 {
          ULONGLONG BaseAddress;
          ULONGLONG AllocationBase;
          DWORD     AllocationProtect;
          DWORD     __alignment1;
          ULONGLONG RegionSize;
          DWORD     State;
          DWORD     Protect;
          DWORD     Type;
          DWORD     __alignment2;
      } MEMORY_BASIC_INFORMATION64, *PMEMORY_BASIC_INFORMATION64;

      Reply

  3. 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;
    } MEMORY_BASIC_INFORMATION64, *PMEMORY_BASIC_INFORMATION64;
    #pragma pack( pop )

    Cheers

    Reply

    1. #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.

      Reply

  4. 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?

    Reply

    1. 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];
      	MEMORY_BASIC_INFORMATION64& mbi64 = *(MEMORY_BASIC_INFORMATION64*)ALIGNUP(mbi64_buf, 16);
      }

      ALIGNUP macro simply adjusts pointer, so it is aligned to requested value (in this case 16), I’ve taken it from http://www.catch22.net/tuts/c-c-tricks
      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.

      Reply

      1. @ReWolf
        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

        Reply

  5. Hi Rewolf,

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

    please help to confirm this error.
    thanks!

    Reply

    1. 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

      Reply

        1. 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”);

          Reply

          1. 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.

            Reply

            1. 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.

              Reply

  6. 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 :(

    Reply

    1. @ReWolf

      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

      Reply

      1. @ReWolf
        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

        Reply

        1. 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.

          Reply

    1. @Mark
      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 ?

      Reply

      1. @Mark
        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).

        Reply

            1. 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.

              Reply

          1. @ReWolf
            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.

            Reply

          2. @ReWolf
            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.

            Reply

            1. 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.

              Reply

        1. @Mark
          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

          Reply

          1. 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.

            Reply

          2. @Mark
            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).

            Reply

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

              Reply

          3. @ReWolf
            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 :
            FFFFFFFFC0000005

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

            Reply

            1. 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.

              Reply

          4. @ReWolf
            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)

            Reply

      2. @ReWolf

        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 ?

        Reply

        1. @Mark
          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.

          Reply

          1. @ReWolf
            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 ?

            Reply

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

              Reply

          2. @ReWolf

            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.

            Reply

        2. @ReWolf

          BEGIN
          READ NAME
          READ NAME – OK
          QUERY
          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
          QUERY-OK
          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 :)

          Reply

          1. @ReWolf

            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.

            Reply

          2. @ReWolf

            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;
            			do
            			{
            				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);
            							nModCount++;
            						}
            						free(wDllName);
            					}
            				}
            			}
            			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…

            Reply

            1. 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 ?

              Reply

    2. @ReWolf

      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.

      Reply

      1. 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 :)

        Reply

          1. 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 [] rewolf.pl and hopefully you’ll be able to receive my reply (or check your spam folder :) )

            Reply

          2. @Mark
            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

            Reply

    3. @ReWolf

      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.

      Reply

Leave a Reply to Mark Cancel reply

Your email address will not be published. Required fields are marked *