Login Register






Thread Rating:
  • 0 Vote(s) - 0 Average


Tutorial Reverse Engineering VirtualAlloc filter_list
Author
Message
Reverse Engineering VirtualAlloc #1
Didn't find any sections for reverse engineering, I hope here is ok.
The tools you are gonna need is a text editor and debugger or disassembler. I'm gonna use WINDBG.
First we need to find out where is VirtualAllocal

Code:
0:000> x kernel32!VirtualAlloc
0:000> x kernelbase!VirtualAlloc
76277060          KERNELBASE!VirtualAlloc (void)
Code:
KERNELBASE!VirtualAlloc:
76277060 8bff            mov     edi,edi
76277062 55              push    ebp
76277063 8bec            mov     ebp,esp
76277065 51              push    ecx
76277066 51              push    ecx
76277067 8b450c          mov     eax,dword ptr [ebp+0Ch]
7627706a 8945f8          mov     dword ptr [ebp-8],eax
7627706d 8b4508          mov     eax,dword ptr [ebp+8]
76277070 8945fc          mov     dword ptr [ebp-4],eax
76277073 56              push    esi
76277074 85c0            test    eax,eax
76277076 740c            je      KERNELBASE!VirtualAlloc+0x24 (76277084)
76277078 3b05b8573276    cmp     eax,dword ptr [KERNELBASE!SysInfo+0x18 (763257b8)]
7627707e 0f829aa00200    jb      KERNELBASE!VirtualAlloc+0x2a0be (762a111e)
76277084 ff7514          push    dword ptr [ebp+14h]
76277087 8b4510          mov     eax,dword ptr [ebp+10h]
7627708a 33f6            xor     esi,esi
7627708c 83e0c0          and     eax,0FFFFFFC0h
7627708f 50              push    eax
76277090 8d45f8          lea     eax,[ebp-8]
76277093 50              push    eax
76277094 56              push    esi
76277095 8d45fc          lea     eax,[ebp-4]
76277098 50              push    eax
76277099 6aff            push    0FFFFFFFFh
7627709b ff153c873276    call    dword ptr [KERNELBASE!_imp__NtAllocateVirtualMemory (7632873c)]
762770a1 85c0            test    eax,eax
762770a3 780c            js      KERNELBASE!VirtualAlloc+0x51 (762770b1)
762770a5 8b75fc          mov     esi,dword ptr [ebp-4]
762770a8 8bc6            mov     eax,esi
762770aa 5e              pop     esi
762770ab 8be5            mov     esp,ebp
762770ad 5d              pop     ebp
762770ae c21000          ret     10h
762770b1 8bc8            mov     ecx,eax
762770b3 e86854ffff      call    KERNELBASE!BaseSetLastNTError (7626c520)
762770b8 ebee            jmp     KERNELBASE!VirtualAlloc+0x48 (762770a8)
762770ba cc              int     3
762770bb cc              int     3
762770bc cc              int     3
762770bd cc              int     3
762770be cc              int     3
762770bf cc              int     3

KERNELBASE!VirtualAlloc+0x2a0be:
762a111e 6a57            push    57h
762a1120 ff15c8803276    call    dword ptr [KERNELBASE!_imp__RtlSetLastWin32Error (763280c8)]
762a1126 33f6            xor     esi,esi
762a1128 e97b5ffdff      jmp     KERNELBASE!VirtualAlloc+0x48 (762770a8)  Branch

Default conversation for WIN32 is STDCALL defined as WINAPI, STDCALL arguments are pushed from right to left, witch means the they are stored backwards
We see one function (_imp__NtAllocateVirtualMemory) from the Nt* family, The functions from Nt* and Zw* are NTAPI witch on x86 are STDCALL and on x64 are FASTCALL, we are wokring on x86 so we are gonna ignore FASTCALL.

VirtualAlloc takes 4 arguments, after the call this is how the stack should look
   ESP +  0  RETURN ADDRESS
   ESP +  4  lpAddress
   ESP +  8  dwSize
   EPP +  C  flAllocationType
   ESP + 10  flProtect

The first instructions we see are the stack frame setting up, witch will move our arguments by 4 bytes
Code:
76277062 55              push    ebp
76277063 8bec            mov     ebp,esp
This is our new arguments offsets
   EBP +  4  RETURN ADDRESS
   EBP +  8  lpAddress
   EBP +  C  dwSize
   EBP + 10  flAllocationType
   EBP + 14  flProtect

After this we see
Code:
76277065 51              push    ecx
76277066 51              push    ecx
Might be to align the stack, not sure. ignore it
Lets just look the code and see what is happending, I recommend disassembling sections of the code by splitting them by JMP. If that makes sence.
Code:
76277067 8b450c          mov     eax,dword ptr [ebp+0Ch]      // eax = parameter dwSize
7627706a 8945f8          mov     dword ptr [ebp-8],eax        // store dwSize in local
7627706d 8b4508          mov     eax,dword ptr [ebp+8]        // eax = parameter lpAddress
76277070 8945fc          mov     dword ptr [ebp-4],eax        // store lpAddress in local
76277073 56              push    esi                          // saves ESI so it cannot be destroyed                    
76277074 85c0            test    eax,eax                      // eax (lpAddress) == NULL
76277076 740c            je      lpAddress_geq_0010000_or_eq_0
KERNELBASE!SysInfo is unknown, but looking up KERNELBASE!SysInfo+0x18 we see 0x0010000, this has to be the minimal address that can be allocated
Code:
lpAddress_neq_null
76277078 3b05b8573276    cmp     eax,dword ptr [KERNELBASE!SysInfo+0x18 (763257b8)]  // Minimal base address
7627707e 0f829aa00200    jb      lpAddress_IS_null_error                             // lpAddress < 0x10000

lpAddress_neq_null_error:
762a111e 6a57            push    57h                          // ERROR_INVALID_PARAMETER
762a1120 ff15c8803276    call    dword ptr [KERNELBASE!_imp__RtlSetLastWin32Error (763280c8)]
762a1126 33f6            xor     esi,esi                      // return value
762a1128 e97b5ffdff      jmp     return_from_function
If lpAddress is 0 or is greater or equal to 0x0010000
Code:
lpAddress_geq_0010000_or_eq_0:
76277084 ff7514          push    dword ptr [ebp+14h]          // passing argument flProtect
76277087 8b4510          mov     eax,dword ptr [ebp+10h]      // flAllocationType
7627708a 33f6            xor     esi,esi                      // esi = 0
7627708c 83e0c0          and     eax,0FFFFFFC0h
7627708f 50              push    eax                          // passing argument flAllocationType & 0xFFFFFFC0
76277090 8d45f8          lea     eax,[ebp-8]
76277093 50              push    eax                          // passing argument the address of our local dwSize
76277094 56              push    esi                          // passing argument 0
76277095 8d45fc          lea     eax,[ebp-4]
76277098 50              push    eax                          // passing argument the address of our local lpAddress
76277099 6aff            push    0FFFFFFFFh                   // passing argument -1 is NtCurrentProcess()
7627709b ff153c873276    call    dword ptr [KERNELBASE!_imp__NtAllocateVirtualMemory (7632873c)]
This is what we got
Code:
NtAllocateVirtualMemory(
   NtCurrentProcess(),
   &lpAddressLocal,
   0,
   &dwSizeLocal,
   flAllocationType & 0xFFFFFFC0,
   flProtect
)
Code:
7627709b ff153c873276    call    dword ptr [KERNELBASE!_imp__NtAllocateVirtualMemory (7632873c)]
762770a1 85c0            test    eax,eax
762770a3 780c            js      NtAllocateVirtualMemory_failed // is bit 31 set, !NT_SUCCESS(X)

NtAllocateVirtualMemory_success:
762770a5 8b75fc          mov     esi,dword ptr [ebp-4]       // lpAddress in local // return value

return_from_function:
762770a8 8bc6            mov     eax,esi
762770aa 5e              pop     esi
762770ab 8be5            mov     esp,ebp
762770ad 5d              pop     ebp
762770ae c21000          ret     10h                         // arguments size
Since the error code is passed to ECX, we can see that KERNELBASE!BaseSetLastNTError is FASTCALL, arguments are passed this way: ECX, EDX and the rest are pushed to the stack from right to left
Code:
NtAllocateVirtualMemory_failed:
762770b1 8bc8            mov     ecx,eax                     // ecx = error code
762770b3 e86854ffff      call    KERNELBASE!BaseSetLastNTError (7626c520)
762770b8 ebee            jmp     return_from_function
Ok! We are done! Now we can create a prototype
Code:
PVOID
WINPAI
VirtualAlloc(
     LPVOID lpAddress,
     SIZE_T dwSize,
     DWORD  flAllocationType,
     DWORD  flProtect
   )
{
   dwSizeLocal    = dwSize;
   lpAddressLocal = lpAddress;

   if (lpAddressLocal) {
       if (lpAddressLocal < SysInfo.MinimalAlloAddress) {
           RtlSetLastWin32Error(ERROR_INVALID_PARAMETER);

           return NULL;
       }
   }

   dwErrorCode = NtAllocateVirtualMemory(
       NtCurrentProcess(),
       &lpAddressLocal,
       0,
       &dwSizeLocal,
       flAllocationType & 0xFFFFFFC0,
       flpProtect
   );

   if (!NT_SUCCESS(dwErrorCode)) {
       BaseSetLastNTError(dwErrorCode);

       return NULL;
   }

   return lpAddressLocal
}

If there are some errors or question ask
(This post was last modified: 04-19-2019, 11:31 AM by IsBadWritePtr.)

Reply

RE: Reverse Engineering VirtualAlloc #2
The good old WinDbg- an extremely effective tool.

This thread has enticed me to pull out OllyDbg, ImportREC , PEiD, W32Dasm and a few others.
Excellent guide Indeed.
[Image: AD83g1A.png]

Reply

RE: Reverse Engineering VirtualAlloc #3
nice well-written tutorial. thank you for making step by step.
My IT skills that I know perfect is SQL, HTML ,css ,wordpress, PHP.
coding skills that I know is Java, JavaScript and C#

Reply







Users browsing this thread: 1 Guest(s)