The content of the article
If you ask the first programmer you come up with what function the Windows program starts with, most likely we will hear the answer “with
WinMain". And that will be a mistake. Actually, the first control gets the start code, which is hidden by the compiler. Having completed the necessary initialization procedures, at some point he calls
WinMain, and after its completion, it regains control and performs capital de-initialization.
Fundamentals of Hacking
Fifteen years ago, Chris Kaspersky's epic work, Fundamental Fundamentals of Hacking, was the handbook of every aspiring computer security researcher. However, time goes by and the knowledge published by Chris is no longer relevant. The Hacker editors tried to update this voluminous work and migrate it from the time of Windows 2000 and Visual Studio 6.0 to the time of Windows 10 and Visual Studio 2017.
Identification of start functions
In the vast majority of cases, the start code is not of any interest, and the first task in the analysis is to search for a function
WinMain. If the compiler is among the IDA’s “acquaintances,” it will recognize
WinMain automatically, otherwise you have to look for a function with your hands and head.
Typically, the compiler’s standard delivery includes the source code of its libraries, including the procedures for the start code. For example, for Microsoft Visual C ++, the start code is located in the file
VCcrtsrcvcruntimemcrtexe.cpp. It contains code for initializing ASCII versions of console (main) applications. In the same folder are several more files:
mwcrtexe.cpp– the code from this file is used when starting console applications with Unicode characters;
mcrtexew.cpp– Called when Windows applications (WinMain) with ASCII support are launched;
mwcrtexew.cpp– Used to run Windows applications with Unicode.
After executing a very small block of code, control from the last three files is transferred to the first. For Embarcadero C ++ Builder 10.3 (nee Borland C ++), all startup code files are stored in a separate directory of the same name. In particular, the files containing the startup code for Windows applications are located in the folder
sourcecpprtlSourcestartup. Its contents are somewhat similar to
vcruntime the fact that there is a main file for launching Win32 applications –
c0nt.asm. The code from this file is called by other files containing initializations for subsystems on Win32: DLL, VCL, FMX (FireMonkey application, cross-platform graphics subsystem). If you look at the source, understanding a disassembled listing will be a lot easier!
But what if we used an unknown or inaccessible compiler to compile the program under study? Before starting the tedious manual analysis, let's recall what a prototype the WinMain function has:
int APIENTRY wWinMain( _In_ HINSTANCE hInstance, // Handle to current instance _In_opt_ HINSTANCE hPrevInstance, // Handle to previous instance _In_ LPWSTR lpCmdLine, // Pointer to command line _In_ int nCmdShow) // Show state of window
WINAPI. Firstly, four arguments are quite a lot, and in most cases
WinMain It turns out to be the most "rich" in the arguments function of the start code. Secondly, the last argument pushed onto the stack is
hInstance – most often calculated on the fly by calling a function
GetModuleHandleW. That is, if you meet a type construct
CALL GetModuleHandleW, we can state with a high degree of certainty that the following function is
WinMain. Finally call
WinMain usually located almost at the very end of the start function code. Behind it there are no more than two or three "closing" functions, for example
Compiled, compiled and we will compile!
Until now, we have compiled our examples from the command line:
cl.exe <имя файла>.cpp /EHcs
As a result, we got a strict machine code cleared of tinsel, after disassembling which in the assembler listing there were no any comments or clear names of functions. Now we will build our applications directly from the development environment (this is still Visual Studio 2017), so that when analyzing the code, we will use the tools provided by the compiler itself. We have already practiced quite a lot and we can determine the basic constructions of a high-level language with our eyes closed: to the touch and smell!
Continuation is available only to participants
Materials from the latest issues become available separately only two months after publication. To continue reading, you must become a member of the Xakep.ru community.
Join the Xakep.ru Community!
Membership in the community during the specified period will open you access to ALL Hacker materials, increase your personal cumulative discount and allow you to accumulate a professional Xakep Score!
I am already a member of Xakep.ru