infinite delay routine, trap stub when trying to find main

When trying to find the main routine of AfkBot code I came across this piece of code which is used to prevent debugging or similar purposes.


/* WARNING: Removing unreachable block (ram,0x0040110f) */

undefined4 FUN_00401090(void)

{
  HMODULE pHVar1;
  undefined4 *puVar2;
  char *pcVar3;
  undefined4 local_1c;
  undefined4 local_18;
  undefined1 local_14 [4];
  FARPROC local_10;
  FARPROC local_c;
  undefined4 local_8;
 
  pcVar3 = "ZwSetTimerResolution";
  pHVar1 = GetModuleHandleW(L"ntdll.dll");
  local_c = GetProcAddress(pHVar1,pcVar3);
  pcVar3 = "NtDelayExecution";
  pHVar1 = GetModuleHandleW(L"ntdll.dll");
  local_10 = GetProcAddress(pHVar1,pcVar3);
  (*local_c)(1,1,local_14);
  puVar2 = FUN_00401000();
  stdext::threads::_Mtx_delete(puVar2);
  do {
    local_8 = 0;
    local_1c = 0xfff0bdc0;
    local_18 = 0xffffffff;
    (*local_10)(0,&local_1c);
  } while( true );
}





Okay — this function FUN_00401090() is not your main() or WinMain() after all. It's a decoy or alternate entry point that puts your process into an infinite sleep loop using NtDelayExecution. Let's break this one down in detail.


🧠 Dissecting FUN_00401090()

undefined4 FUN_00401090(void)  

This function does not return. It enters an infinite loop after setting a timer resolution, deleting a mutex, and calling low-level Windows NT APIs from ntdll.dll.


🔍 Step-by-Step Breakdown

1. Load NTDLL and resolve functions

pHVar1 = GetModuleHandleW(L"ntdll.dll");  local_c = GetProcAddress(pHVar1, "ZwSetTimerResolution");    pHVar1 = GetModuleHandleW(L"ntdll.dll");  local_10 = GetProcAddress(pHVar1, "NtDelayExecution");  
  • ZwSetTimerResolution — sets system clock resolution (higher precision = more CPU).

  • NtDelayExecution — native version of Sleep(), allows sub-ms sleep.

2. Call ZwSetTimerResolution(1, 1, ...)

(*local_c)(1,1,local_14);  
  • Enables high-resolution timer. Possibly for timing precision, anti-debugging, or avoiding system-wide throttling.

3. Call some internal cleanup

puVar2 = FUN_00401000();  stdext::threads::_Mtx_delete(puVar2);  
  • Might be deleting a mutex or cleaning up thread-related resources.

  • Could also be part of obfuscation or unused junk code.

4. Infinite Sleep Loop

do {    local_8 = 0;    local_1c = 0xfff0bdc0;        // a large negative value (relative time)    local_18 = 0xffffffff;    (*local_10)(0, &local_1c);     // NtDelayExecution  } while( true );  
  • Calls NtDelayExecution(0, &local_1c);

  • This puts the thread (or process) into a permanent suspended state (huge sleep).

  • The delay is a large negative 64-bit value → relative time, ~forever.


🛑 Important Takeaway

This is a trap stub, placeholder, or infinite delay routine. It's often used for:

💡 Possible Purposes

Purpose Why it's done
Anti-debugging Native APIs + infinite sleep confuse debuggers
Stub/placeholder Dummy function to prevent actual execution
Malware tactic Keeps the process alive without doing anything
Unreachable logic May be discarded or unused by the program

And you even got this hint:

/* WARNING: Removing unreachable block (ram,0x0040110f) */  

Meaning the decompiler knew this code isn't even reachable under normal execution.


✅ So… where is main() or WinMain()?

You're still not in the right place. FUN_00401090() is a dead-end. Your real main() or WinMain() is either:

  • Another function called somewhere else in __scrt_common_main_seh(), not FUN_00401090(), or

  • This FUN_00401090() was intentionally inserted as a fake or decoy entry (common in packers, malware, or obfuscated builds).


🔎 Next Step?

If you want to find the real main() or entry logic:

  1. Search for functions calling WinMain, main, or _mainCRTStartup.

  2. Look inside __scrt_common_main_seh() for other FUN_XXXXXX() style functions being called.

  3. Trace through the PE entry point in your disassembler.

  4. Use runtime tracing (like x64dbg) to set a breakpoint on ExitProcess, and walk the call stack back to main().


Need help finding it? If you can give me a list of functions in the binary (or the next few FUN_00401XXX routines), I can help pinpoint the real entry logic.


Comments

Popular posts from this blog

Avoiding detection when injecting a DLL into a game process

Some global variable set, mystery function

FULL REFLECTIVE INJECTION PACK