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