FINDING MAIN()/ENTRY POINT W/O DEBUG SYMBOLS
after using ghidra, try using gdb...
PROCESS
when identifying main(), use the reverse method
identify where "return" is, then double-click the first function encountered above the "return" keyword or the __scrt_common_main_seh()
#step 1:
ghidra > File > Open > 15_function_args_no_debug.exe
filter: main
* since there is no debug symbols when the executable was compiled, main won't be found
#step 2:
ghidra > Symbol Tree > Functions > entry
void entry(void)
{
__security_init_cookie();
__scrt_common_main_seh();
return;
}
* this will drop you to where ghidra thinks the main function is
#step 3:
ghidra > Symbol Tree > Functions > entry
* click on "entry" to automatically decompile it
- entry is NOT main(), but it leads to it.
ghidra > decompile ...
void entry(void)
{
__security_init_cookie();
__scrt_common_main_seh();
return;
}
* click __scrt_common_main_seh()
- This function is responsible for setting up exception handling and eventually calling main().
- Goal: Find __scrt_common_main();
* __scrt_common_main_seh(); is a function commonly found in Windows executables
compiled with Microsoft's C runtime (CRT). It is part of the Microsoft Startup Code
and is involved in setting up exception handling for the main program.
- this function is responsible for several things including...
- Calling main() or WinMain(): Once the initialization is complete, it calls the
user-defined main() (for console apps) or WinMain() (for GUI apps).
- __scrt_common_main_seh(); is just a wrapper around main() or WinMain()
* the __security_init_cookie(); is a function that initializes a global security
cookie used to detect stack buffer overflows at runtime. It is part of /GS
(Buffer Security Check), a compiler flag that adds stack canary protection to
functions that may be vulnerable to buffer overflows.
step 4: continue w/ the backwards method until the real main function is identified
...
iVar1 = __cinit(1);
if (iVar1 != 0){
__amsg_exit(iVar1);
}
_DAT_0040cf34 = DAT_0040cf30;
iVar1 = FUN_00401010();
_exit(iVar1);
__cexit();
return iVar1;
* if you see __{arbitraryString}...it means that its coming from imports
- Symbol Tree > Imports > KERNEL32.DLL
step 5: the first function encountered when working backwards that is NOT start w/ __ is the real main function
iVar1 = FUN_00401010();
_exit(iVar1);
__cexit();
return iVar1;
* double click the FUN_00401010() in iVar1 = FUN_00401010(); to get to its memory location
undefined4 FUN_00401010(void)
{
int iVar1;
iVar1 = FUN_00401000(1, 2, 3);
_printf(&DAT_0040c000,iVar1);
return 0;
}
step 6: rename to make it clear to ghidra that you found the main()
***********************
* FUNCTION *
***********************
undefined4 __stdcall FUN_00401010(void) //hit the "l" key on the keyboard or right-click it to rename
- rename FUN.. to main
#C CODE SNIPPET
//these global declarations are stored in memory
int x = 1;
int y = 2;
void main()
{
//local variables
int a = 1;
int b = 2;
printf("this printf is inside the main function");
printf("global variable being used here %d", x);
}
PS C:\> cl /MD /Od /FA noDebugSymbolsTraining.c
Last updated