Killing threads outside the code segment

Joined
Apr 4, 2009
Messages
898
Reaction score
157
An idea I had that would inevitably kill current methods of DLL injection would be to kill all threads found to have a start address outside the code segment.

To battle against such an idea, you would have to either:

a) Spoof the TIB.
b) Launch a thread from within the code segment, which would involve modification of the code segment (Wouldn't work if checks on the code segment were done during runtime).

A very poorly formatted program I've been working on that makes use of the PEB's BeingDebugged bit and an anti-debug technique involving a software interrupt with Microsoft's proprietary __try/__except extensions:

Code:
#include <windows.h>
#include <strsafe.h>
#include <tlhelp32.h>

#define WIN32_LEAN_AND_MEAN
#define VC_EXTRALEAN

#define CODEBEGIN	0x00401000
#define CODEEND		0x00401A5E

char BeingDebugged( )
{
  char BeingDebuggedBit;
  __asm {
    MOV EAX,DWORD PTR FS:[0x30]
	XOR EAX, 0x2
	SUB EBX, EBX
	XOR BL, [EAX]
    MOV BeingDebuggedBit, BL
  };
  return( BeingDebuggedBit );
}

DWORD WINAPI GetThreadStartAddress( HANDLE hThread )
{
    NTSTATUS ntStatus;
    HANDLE hDupHandle;
    DWORD dwStartAddress;
    typedef NTSTATUS ( WINAPI *NQIT )( HANDLE, LONG, PVOID, ULONG, PULONG );
    NQIT NtQueryInformationThread = ( NQIT )GetProcAddress( GetModuleHandle( "ntdll.dll" ), "NtQueryInformationThread" );

    HANDLE hCurrentProcess = GetCurrentProcess( );

    if( !DuplicateHandle( hCurrentProcess, hThread, hCurrentProcess, &hDupHandle, THREAD_QUERY_INFORMATION, FALSE, 0 ) ) {
        return( ERROR_ACCESS_DENIED );
    }

    ntStatus = NtQueryInformationThread( hDupHandle, 9, &dwStartAddress, sizeof( DWORD ), NULL );

    CloseHandle( hDupHandle ); 

    return( dwStartAddress );
}

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd )
{
  bool noDebugger = FALSE;
  __try {
	__asm INT 0x2D
  } __except( true ) {
	  noDebugger = TRUE;
  }
  if( noDebugger == FALSE )
	  return( EXIT_FAILURE );

  if( ( int ) BeingDebugged( ) == TRUE )
	  return( EXIT_FAILURE );


  HANDLE h = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
  if( h != INVALID_HANDLE_VALUE ) {
    THREADENTRY32 te;
    te.dwSize = sizeof(te);
    if( Thread32First( h, &te ) ) {
      do {
       if ( te.dwSize >= FIELD_OFFSET(THREADENTRY*** th32OwnerProcessID) +
                      sizeof(te.th32OwnerProcessID) &&
					  GetCurrentProcessId( ) == te.th32OwnerProcessID ) {
			DWORD dwStartAddress;
			HANDLE lclThread = OpenThread( THREAD_GET_CONTEXT, FALSE, te.th32ThreadID );
			dwStartAddress = GetThreadStartAddress( lclThread );
			if( dwStartAddress < CODEBEGIN || dwStartAddress > CODEEND )
				TerminateThread( lclThread, EXIT_SUCCESS );

			CloseHandle( lclThread );
	  }
      te.dwSize = sizeof( te );
    } while( Thread32Next( h, &te ) );
   }
  }
  CloseHandle( h );
 

  MessageBox( 0, "Debugger not found.", "Success?", MB_OK );

  return( EXIT_SUCCESS );
}

Credits to:
- Enumerating threads of all active processes

- Getting the start address of a thread via accessing the TIB using NtQuerySystemInformation.


Thoughts?
 
wow thanks.

I was actually thinking that same idea before but never had enough coding experience to do any of it.

xD Amazing

Integrity checks of sorts are something I'm surprised you don't see more if in custom anti-cheat engines; this technique I consider a bit more passive if you were to incorporate it to into an anti-cheat, as some third-party libraries do launch threads in new processes, obviously with a start address outside the code segment (e.g. AVI Helper software).
 
Good Idea ! But will it block Detours 2.1 DetourCreateProcessWithDll ?
Remarks
DetourCreateProcessWithDll creates a new process with the specified DLL inserted into it.

The process is created in a suspended state with the CREATE_SUSPENDED flag to CreateProcess. Detours then modifies the image of the application binary in the new process to include the specified DLL as its first import. Execution in the process is then resumed. When execution resumes, the Windows process loader will first load the target DLL and then any other DLLs in the application's import table, before calling the application entry point.

DetourCreateProcessWithDll modifies the in-memory import table of the target PE binary program in the new process it creates. The updated import table will contain a reference to function ordinal #1 exported from the target DLL.
 
Wow, good idea actually. The thing about what PaulBub said is, if I understood correctly, that the process is modified to add the dll to the executable as if it was in the import list. So, unless the DLL made a thread for some other issue, how would you tell the difference between a DLL that should be there(fmod.dll) and another one(haxorifixasdoqjwoije.dll)?
 
Wow, good idea actually. The thing about what PaulBub said is, if I understood correctly, that the process is modified to add the dll to the executable as if it was in the import list. So, unless the DLL made a thread for some other issue, how would you tell the difference between a DLL that should be there(fmod.dll) and another one(haxorifixasdoqjwoije.dll)?

The idea is you would use this with integrity checks and obfuscation/virtualization; I mean, if you're going to modify the import list, why not just hook TerminateThread() and have it return on call?
 
Back