SamuZai
oalabs
oalabs

patreon


Why Is The PE Entry Point Not The Same As Main Understanding __security_init_cookie and __scrt_common_main_seh

In this tutorial we discuss the __security_init_cookie and __scrt_common_main_seh functions and why the PE Entry Point on an MSVC binary does not point to Main. 

This is an important concept to understand when first learning how to reverse engineer windows binaries, especially when using a debugger. Often it can be confusing when the debugger breaks on the PE Entry Point only to find some code that is not related to the main functionality of the binary. This code is often called "boilerplate" code and is inserted automatically by the MSVC compiler. As a reverse engineer it is useful to be able to identify and navigate this code.

MSVC Console Application Entry Point

The Entry Point on an MSVC console application servers two purposes, it calls the __security_init_cookie function then it jumps to the __scrt_common_main_seh thunk. The __scrt_common_main_seh thunk then performs some setup for the binary including some structured exception handler (SEH) setup and then calls main. 


__security_init_cookie

The __security_init_cookie function is not too interesting to us from a reverse engineering perspective but it's important to be able to recognize it as a pattern as it can be used to "localize" ourselves if we are looking at PE file in memory. The purpose of this cookie is best described by MSDN: Initializes the global security cookie.

__scrt_common_main_seh

The __scrt_common_main_seh thunk is used to setup some SEH stuff for the binary and then call into main. When analyzing malware that has been compile with MSVC this code cn Abe ignored and quickly scanned to identify where it calls main. Main is where the actual developed code begins.

 Looking at this code without labels (for example in x64dbg) it can be confusing to identify where main is. Luckily MSVC console applications all have the same main function prototype.

main(int argc, const char **argv, const char **envp)

This function prototype can be used to identify the call to main in __scrt_common_main_seh, simply by looking for the three arguments that are passed to main: argc, argv, envp. In 64-bit binaries these arguments are compiled into a series of three mov instructions moving the arguments into the registers RCX, RDX, R8.

In 32-bit binaries these arguments are compiled into a series of three push instructions pushing the arguments onto the stack.

These patterns can be relied on to identify main. 

Self Study Examples

Attached to this post are the 64-bit sample we used in the tutorial and it's 32-bit counterpart. As a self-study exercise, unzip these files and copy them onto your FLARE-VM virtual machine. 

** The samples are dynamically linked so if you are not using the FLARE-VM with Windows 10, you will need to have VCRUNTIME140.dll installed. 

Once you have the file copied over to your VM attempt the following.

Now try the same steps with the 32-bit binary.


Why Is The PE Entry Point Not The Same As Main Understanding __security_init_cookie and __scrt_common_main_seh

Comments

It would be very helpful if you could make a tutorial on how to find main in Delphi and other than MSVC compiled binaries, please! Also, an example walk through a binary which has been compiled with all of the compiler optimisations and without any symbols available would be very helpful. Malware authors choose the more obscure ways most at times. Thank you in advance!

puffinRE


More Creators