Some "malicious" code is run before main is executed!


 Yes, keep going with the article I mentioned in the previous post, I come up with a new thing: "mainCRTStartup" or other function depending on the switch we choose when start a new project (/SUBSYSTEM:WINDOWS or /SUBSYSTEM:CONSOLE). Let's go >:)

The first guy I met is crtexe.c and the code of that function is here:
  1. #ifdef _WINMAIN_
  2. #ifdef WPRFLAG
  3. int wWinMainCRTStartup(
  4. #else  /* WPRFLAG */
  5. int WinMainCRTStartup(
  6. #endif  /* WPRFLAG */
  7. #else  /* _WINMAIN_ */
  8. #ifdef WPRFLAG
  9. int wmainCRTStartup(
  10. #else  /* WPRFLAG */
  11. int mainCRTStartup(
  12. #endif  /* WPRFLAG */
  13. #endif  /* _WINMAIN_ */
  14.         void
  15.         )
  16. {
  17.         /*
  18.          * The /GS security cookie must be initialized before any exception
  19.          * handling targetting the current image is registered.  No function
  20.          * using exception handling can be called in the current image until
  21.          * after __security_init_cookie has been called.
  22.           */
  23.          __security_init_cookie();
  24.          return __tmainCRTStartup();
  25. }

Let's begin with the __security_init_cookie( ) function. "Cookie", "security", huhm, something relating to web application? Of course not, I have investigated and found some helpful information from here. Thanks Brandon Bray (MSFT) for your useful article.

Now I'll summary everything in my view for easily understanding later.

  • winMain 
Look into __tmainCRTStartup() we see that the first entry point's  argument casted to HINSTANCE is image base. This is the base memory address where the system will load the executable file's image into the process's address space.

The base address where an executable file's image loads is determined by the linker. Different linkers can use different default base addresses. The Visual C++ linker uses a default base address of 0x00400000 because this is the lowest address an executable file image can load to when you run Windows 98. You can change the base address that your application loads to by using the /BASE: address linker switch for Microsoft's linker.

  • Buffer Overflow
Whenever a function is called, a new stack frame is established with the following layout:
Function parameters
Function return address
Frame pointer
Exception Handler frame
Locally declared variables and buffers
Callee save registers
(The Exception Handler frame is optional. It just exists in the case that the function which is called includes try/catch.)

The BO is caused coz the return address is overwriten. And Visual Studio comes up with an option for checking this problem - /GS (Buffer Security Check). So, the new stack layout will become like this with new field - cookie.
Function parameters
Function return address
Frame pointer
Cookie
Exception Handler frame
Locally declared variables and buffers
Callee save registers
In this way, when a function is called, instead that ESP register's value is subtracted with the total size of local variable, it's actually subtracted with more extra 4 bytes. Means that
sub esp 24h 
instead of
sub esp 20h
The reason is coz of cookie. Let's see the detail:
 
sub   esp,24h
mov   eax,dword ptr [___security_cookie (408040h)]
xor   eax,dword ptr [esp+24h]
mov   dword ptr [esp+20h],eax
 
I'll explain more detail about the value at ___security_cookie (408040h) (I call it X) later. Now it's more important to be clear that code. Value at [esp+24h] is the function return address is "xor"ed with the X and then is put right below the return address. Huh, what's for? Keep going with the end code (epilog):
mov   ecx,dword ptr [esp+20h]
xor   ecx,dword ptr [esp+24h]
add   esp,24h
jmp   __security_check_cookie (4010B2h)
Oops! It's not simple as common:
add   esp,20h
ret
ECX now is the "xor"ed value got from the prolog, and one more time is "xor"ed with the return address. So strange, no any ret instruction but jump ... instead :| I think now it's time to take a loot at
__security_check_cookie function. Open seccheck.c in VC/crt/src/intel of visual studio 9 (maybe the filename changes with other version - in this case, just search with the function name :-) )
  1. void __declspec(naked) __fastcall __security_check_cookie(UINT_PTR cookie)
  2. {
  3.     /* x86 version written in asm to preserve all regs */
  4.     __asm {
  5.         cmp ecx, __security_cookie
  6.         jne failure
  7.         rep ret    /* REP to avoid AMD branch prediction penalty */
  8. failure:
  9.         jmp __report_gsfailure
  10.     }
  11. }
It's clear to understand. Just check if the value of ecx differ __security_cookie and carry out the proper action. Not much to talk :-)

Ref: Jeffrey Richter, Programming Applications for Microsoft Windows, Fourth Edition.