BOOL NtGlobalFlag()
{
    PDWORD pNtGlobalFlag = NULL, pNtGlobalFlagWoW64 = NULL;

#if defined (ENV64BIT)
    BYTE* _teb64 = (BYTE*)__readgsqword(0x30);
    DWORD64 _peb64 = *(DWORD64*)(_teb64 + 0x60);
    pNtGlobalFlag = (PDWORD)(__readgsqword(0x60) + 0xBC);

#elif defined(ENV32BIT)
    /* NtGlobalFlags for real 32-bits OS */
    BYTE* _teb32 = (BYTE*)__readfsdword(0x18);
    DWORD _peb32 = *(DWORD*)(_teb32 + 0x30);
    pNtGlobalFlag = (PDWORD)(_peb32 + 0x68);

    if (IsWoW64())
    {
        /* In Wow64, there is a separate PEB for the 32-bit portion and the 64-bit portion
        which we can double-check */

        BYTE* _teb64 = (BYTE*)__readfsdword(0x18) - 0x2000;
        DWORD64 _peb64 = *(DWORD64*)(_teb64 + 0x60);
        pNtGlobalFlagWoW64 = (PDWORD)(_peb64 + 0xBC);
    }
#endif

    bool normalDetected = pNtGlobalFlag && *pNtGlobalFlag & 0x00000070;
    bool wow64Detected = pNtGlobalFlagWoW64 && *pNtGlobalFlagWoW64 & 0x00000070;

    if(normalDetected || wow64Detected)
        return TRUE;
    else
        return FALSE;
}
Beispiel #2
0
VOID
NTAPI
INIT_FUNCTION
KiSystemStartupBootStack(VOID)
{
    PKTHREAD Thread;

    /* Initialize the kernel for the current CPU */
    KiInitializeKernel(&KiInitialProcess.Pcb,
                       (PKTHREAD)KeLoaderBlock->Thread,
                       (PVOID)(KeLoaderBlock->KernelStack & ~3),
                       (PKPRCB)__readfsdword(KPCR_PRCB),
                       KeNumberProcessors - 1,
                       KeLoaderBlock);

    /* Set the priority of this thread to 0 */
    Thread = KeGetCurrentThread();
    Thread->Priority = 0;

    /* Force interrupts enabled and lower IRQL back to DISPATCH_LEVEL */
    _enable();
    KfLowerIrql(DISPATCH_LEVEL);

    /* Set the right wait IRQL */
    Thread->WaitIrql = DISPATCH_LEVEL;

    /* Jump into the idle loop */
    KiIdleLoop();
}
Beispiel #3
0
void
mono_threads_platform_get_stack_bounds (guint8 **staddr, size_t *stsize)
{
	MEMORY_BASIC_INFORMATION meminfo;
#ifdef _WIN64
	/* win7 apis */
	NT_TIB* tib = (NT_TIB*)NtCurrentTeb();
	guint8 *stackTop = (guint8*)tib->StackBase;
	guint8 *stackBottom = (guint8*)tib->StackLimit;
#else
	/* http://en.wikipedia.org/wiki/Win32_Thread_Information_Block */
	void* tib = (void*)__readfsdword(0x18);
	guint8 *stackTop = (guint8*)*(int*)((char*)tib + 4);
	guint8 *stackBottom = (guint8*)*(int*)((char*)tib + 8);
#endif
	/*
	Windows stacks are expanded on demand, one page at time. The TIB reports
	only the currently allocated amount.
	VirtualQuery will return the actual limit for the bottom, which is what we want.
	*/
	if (VirtualQuery (&meminfo, &meminfo, sizeof (meminfo)) == sizeof (meminfo))
		stackBottom = MIN (stackBottom, (guint8*)meminfo.AllocationBase);

	*staddr = stackBottom;
	*stsize = stackTop - stackBottom;

}
LPVOID WINAPI 
	VirtualAllocRopProtect(LPVOID lpAddress, 
	                       SIZE_T dwSize, 
						   DWORD flAllocationType, 
						   DWORD flProtect)
{
	NT_TIB * ThreadInfo;
	HANDLE hCurrentThread;
	CONTEXT * cThreadContext = (CONTEXT *)LocalAlloc(LMEM_ZEROINIT, sizeof(CONTEXT));

	hCurrentThread = GetCurrentThread();
	cThreadContext->ContextFlags = CONTEXT_CONTROL;
	// get the thread stack range from TIB.
	ThreadInfo = (NT_TIB *) __readfsdword( 0x18 );
	if ( GetThreadContext( hCurrentThread, cThreadContext ) )
	{
		// check if thread is passing the acual stack boundaries.
		if ( cThreadContext->Esp < (DWORD)ThreadInfo->StackLimit || cThreadContext->Esp >= (DWORD)ThreadInfo->StackBase ) 
		{
			// at this point everything is definitely messed up, so no matter what we do with stack.
			__asm
				{
					mov esp, fs:[0x8] 
					add esp,400h 
				}
			// rise the bar :D
			RaiseException( STATUS_STACK_BUFFER_OVERRUN, EXCEPTION_NONCONTINUABLE, 0, NULL);
		}
	}
Beispiel #5
0
HANDLE GetKernel32Module( void )
{
    HANDLE hKernel32 = INVALID_HANDLE_VALUE;
    wchar_t szKernel32[] = { 'k'^XOR_KEY, 'e'^XOR_KEY, 'r'^XOR_KEY,
                             'n'^XOR_KEY, 'e'^XOR_KEY, 'l'^XOR_KEY, '3'^XOR_KEY, '2'^XOR_KEY,
                             '.'^XOR_KEY, 'd'^XOR_KEY, 'l'^XOR_KEY, 'l'^XOR_KEY, '\0'^XOR_KEY
                           };
#ifdef _WIN64
    PPEB lpPeb = (PPEB) __readgsqword(0x60);
#else
    PPEB lpPeb = (PPEB) __readfsdword(0x30);
#endif
    PLIST_ENTRY pListHead = &lpPeb->Ldr->InMemoryOrderModuleList;
    PLIST_ENTRY pListEntry = pListHead->Flink;

    while (pListEntry != pListHead)
    {
        PLDR_DATA_TABLE_ENTRY pModEntry = CONTAINING_RECORD(pListEntry, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
        if (pModEntry->FullDllName.Length)
        {
            PWCHAR strName = &pModEntry->FullDllName.Buffer[pModEntry->FullDllName.Length/sizeof(WCHAR) - 12];

            if (!__WMEMCMP__(strName, szKernel32, _countof(szKernel32), TRUE, XOR_KEY))
            {
                hKernel32 = (HANDLE)pModEntry->DllBase;
                break;
            }
        }
        pListEntry = pListEntry->Flink;
    }

    return hKernel32;
}
Beispiel #6
0
SCFUNC PVOID scGetModuleBase(const char *moduleName)
{
    PPEB pPeb;
    PLIST_ENTRY head, entry;
    PLDR_DATA_TABLE_ENTRY module;

#if defined(_M_IX86)
    pPeb = (PPEB) __readfsdword(0x30);
#elif defined(_M_X64)
    pPeb = (PPEB) __readgsqword(0x60);
#endif

    head = &pPeb->Ldr->InLoadOrderModuleList;
    entry = head->Flink;

    while (entry != head)
    {
        module = CONTAINING_RECORD(entry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
        if (scW2Anicmp(module->BaseDllName.Buffer, moduleName, scStrlen(moduleName)) == 0)
            return module->DllBase;
        entry = entry->Flink;
    }

    return NULL;
}
Beispiel #7
0
PUINT32 GetHeapFlags_x86()
{
	PUINT32 pProcessHeap, pHeapFlags = NULL;

	if (IsWindowsVistaOrGreater()){
		pProcessHeap = (PUINT32)(__readfsdword(0x30) + 0x18);
		pHeapFlags = (PUINT32)(*pProcessHeap + 0x40);
	}

	else {
		pProcessHeap = (PUINT32)(__readfsdword(0x30) + 0x18);
		pHeapFlags = (PUINT32)(*pProcessHeap + 0x0C);
	}

	return pHeapFlags;
}
Beispiel #8
0
ResultType Clipboard::Open()
{
	if (mIsOpen)
		return OK;

#ifdef _WIN64
	DWORD aThreadID = __readgsdword(0x48); // Used to identify if code is called from different thread (AutoHotkey.dll)
#else
	DWORD aThreadID = __readfsdword(0x24);
#endif

	for (DWORD start_time = GetTickCount();;)
	{
		if (OpenClipboard(g_hWnd))
		{
			mIsOpen = true;
			return OK;
		}
		if (g_ClipboardTimeout != -1) // We were not told to wait indefinitely...
			if (!g_ClipboardTimeout   // ...and we were told to make only one attempt, or ...
				|| (int)(g_ClipboardTimeout - (GetTickCount() - start_time)) <= SLEEP_INTERVAL_HALF) //...it timed out.
				// Above must cast to int or any negative result will be lost due to DWORD type.
				return FAIL;
		// Use SLEEP_WITHOUT_INTERRUPTION to prevent MainWindowProc() from accepting new hotkeys
		// during our operation, since a new hotkey subroutine might interfere with
		// what we're doing here (e.g. if it tries to use the clipboard, or perhaps overwrites
		// the deref buffer if this object's caller gave it any pointers into that memory area):
		SLEEP_WITHOUT_INTERRUPTION(INTERVAL_UNSPECIFIED)
	}
}
Beispiel #9
0
gpointer
gum_tls_key_get_value (GumTlsKey key)
{
  if (key < 64)
  {
    return (gpointer)__readfsdword (3600 + key * sizeof (gpointer));
  }
  else if (key < 1088)
  {
    gpointer * tls_expansion_slots = (gpointer *) __readfsdword (3988);
    if (tls_expansion_slots != NULL)
      return tls_expansion_slots[key - 64];
    return _gum_tls_key_get_tmp_value (key);
  }
  return NULL;
}
RTDECL(bool) RTThreadPreemptIsPending(RTTHREAD hThread)
{
    Assert(hThread == NIL_RTTHREAD); RT_NOREF1(hThread);

    /*
     * Read the globals and check if they are useful.
     */
/** @todo Should we check KPRCB.InterruptRequest and KPRCB.DpcInterruptRequested (older kernels).  */
    uint32_t const offQuantumEnd     = g_offrtNtPbQuantumEnd;
    uint32_t const cbQuantumEnd      = g_cbrtNtPbQuantumEnd;
    uint32_t const offDpcQueueDepth  = g_offrtNtPbDpcQueueDepth;
    if (!offQuantumEnd && !cbQuantumEnd && !offDpcQueueDepth)
        return false;
    Assert((offQuantumEnd && cbQuantumEnd) || (!offQuantumEnd && !cbQuantumEnd));

    /*
     * Disable interrupts so we won't be messed around.
     */
    bool            fPending;
    RTCCUINTREG     fSavedFlags  = ASMIntDisableFlags();

#ifdef RT_ARCH_X86
    PKPCR       pPcr   = (PKPCR)__readfsdword(RT_OFFSETOF(KPCR,SelfPcr));
    uint8_t    *pbPrcb = (uint8_t *)pPcr->Prcb;

#elif defined(RT_ARCH_AMD64)
    /* HACK ALERT! The offset is from windbg/vista64. */
    PKPCR       pPcr   = (PKPCR)__readgsqword(RT_OFFSETOF(KPCR,Self));
    uint8_t    *pbPrcb = (uint8_t *)pPcr->CurrentPrcb;

#else
# error "port me"
#endif

    /* Check QuantumEnd. */
    if (cbQuantumEnd == 1)
    {
        uint8_t volatile *pbQuantumEnd = (uint8_t volatile *)(pbPrcb + offQuantumEnd);
        fPending = *pbQuantumEnd == TRUE;
    }
    else if (cbQuantumEnd == sizeof(uint32_t))
    {
        uint32_t volatile *pu32QuantumEnd = (uint32_t volatile *)(pbPrcb + offQuantumEnd);
        fPending = *pu32QuantumEnd != 0;
    }
    else
        fPending = false;

    /* Check DpcQueueDepth. */
    if (    !fPending
        &&  offDpcQueueDepth)
    {
        uint32_t volatile *pu32DpcQueueDepth = (uint32_t volatile *)(pbPrcb + offDpcQueueDepth);
        fPending = *pu32DpcQueueDepth > 0;
    }

    ASMSetFlags(fSavedFlags);
    return fPending;
}
Beispiel #11
0
PPEB GetPeb(VOID)
{
    PPEB Peb = 0;
#ifdef _WIN64
    Peb = (PPEB)__readgsqword(0x60);
#else
    Peb = (PPEB)__readfsdword(0x30);
#endif
    return Peb;
}
Beispiel #12
0
int main(int argc, char *argv[])
{
    HANDLE hEvent = CreateEvent(nullptr, FALSE, FALSE, L"Useless event");

    HANDLE hThread1 = CreateThread(nullptr, 0, &ThreadEntry, hEvent, 0, nullptr);
    HANDLE hThread2 = CreateThread(nullptr, 0, &ThreadEntry, hEvent, 0, nullptr);
    HANDLE hThread3 = CreateThread(nullptr, 0, &ThreadEntry, hEvent, 0, nullptr);

    CONTEXT ctxThread1 = { CONTEXT_ALL };
    (void)GetThreadContext(hThread1, &ctxThread1);

    CONTEXT ctxThread2 = { CONTEXT_ALL };
    (void)GetThreadContext(hThread2, &ctxThread2);

    CONTEXT ctxThread3 = { CONTEXT_ALL };
    (void)GetThreadContext(hThread3, &ctxThread3);

    LDT_ENTRY ldtThread1 = { 0 };
    LDT_ENTRY ldtThread2 = { 0 };
    LDT_ENTRY ldtThread3 = { 0 };

    (void)GetThreadSelectorEntry(hThread1, ctxThread1.SegFs, &ldtThread1);
    (void)GetThreadSelectorEntry(hThread2, ctxThread2.SegFs, &ldtThread2);
    (void)GetThreadSelectorEntry(hThread3, ctxThread3.SegFs, &ldtThread3);

    NT_TIB *pTibMain = (NT_TIB *)__readfsdword(0x18);

    DWORD_PTR dwFSBase1 = (ldtThread1.HighWord.Bits.BaseHi << 24) |
                          (ldtThread1.HighWord.Bits.BaseMid << 16) |
                          ldtThread1.BaseLow;

    DWORD_PTR dwFSBase2 = (ldtThread2.HighWord.Bits.BaseHi << 24) |
                          (ldtThread2.HighWord.Bits.BaseMid << 16) |
                          ldtThread2.BaseLow;

    DWORD_PTR dwFSBase3 = (ldtThread3.HighWord.Bits.BaseHi << 24) |
                          (ldtThread3.HighWord.Bits.BaseMid << 16) |
                          ldtThread3.BaseLow;

    fprintf(stderr, "Thread 1 FS Segment base address: %X\n"
            "Thread 2 FS Segment base address : %X\n"
            "Thread 3 FS Segment base address : %X\n",
            dwFSBase1, dwFSBase2, dwFSBase3);

    DWORD_PTR dwWOW64Address1 = *(DWORD_PTR *)((unsigned char *)dwFSBase1 + 0xC0);
    DWORD_PTR dwWOW64Address2 = *(DWORD_PTR *)((unsigned char *)dwFSBase2 + 0xC0);
    DWORD_PTR dwWOW64Address3 = *(DWORD_PTR *)((unsigned char *)dwFSBase3 + 0xC0);

    fprintf(stderr, "Thread 1 FS:[0xC0] : %X\n"
            "Thread 2 FS:[0xC0] : %X\n"
            "Thread 3 FS:[0xC0] : %X\n",
            dwWOW64Address1, dwWOW64Address2, dwWOW64Address3);

    return 0;
}
Beispiel #13
0
	__checkReturn
	bool
	ResolveUserImports()
	{
#if defined(_WIN64)
		PEB* peb = reinterpret_cast<PEB*>(__readgsqword(0x60));
#else
		PEB* peb = reinterpret_cast<PEB*>(__readfsdword(0x30));
#endif
		if (!peb)
			return false;

		if (!peb->Ldr)
			return false;

		if (!peb->Ldr->InMemoryOrderModuleList.Flink)
			return false;

		if (!peb->Ldr->InMemoryOrderModuleList.Flink->Flink)
			return false;

		if (!peb->Ldr->InMemoryOrderModuleList.Flink->Flink->Flink)
			return false;

		auto kernel32 = CONTAINING_RECORD(peb->Ldr->InMemoryOrderModuleList.Flink->Flink->Flink, LDR_DATA_TABLE_ENTRY, InMemoryOrderLinks);
		if (!kernel32->DllBase)
			return false;

		const void* load_lib_a = GlobalDllProxy::GetProcAddr(kernel32->DllBase, "LoadLibraryA");
		if (!load_lib_a)
			return false;

		for (size_t i = 0; i < _countof(g_UserModeImportsInfo); i++)
		{
			const void* addr = GlobalDllProxy::ResolveProcAddress(
				reinterpret_cast<const decltype(&LoadLibraryA)>(load_lib_a),
				*g_UserModeImportsInfo[i].Module,
				*g_UserModeImportsInfo[i].ProcName);


			//so something not resolved, pobably fault of .py script ...
			if (!addr)
#ifdef TEST_MODE
			{
				SetUserLibc();
				printf("\n UNRESOLVED EXTERNAL SYMBOLS : %s.%s \n", *g_UserModeImportsInfo[i].Module, *g_UserModeImportsInfo[i].ProcName);
			}
#else
			return false;
#endif

			*g_UserModeImportsInfo[i].ExProc = addr;
		}
		return true;
	}
Beispiel #14
0
VOID SizeOfImage()
{

#if defined (ENV64BIT)
	PPEB pPeb = (PPEB)__readgsqword(0x60);
#elif defined(ENV32BIT)
	PPEB pPeb = (PPEB)__readfsdword(0x30);
#endif

	_tprintf(_T("[*] Increasing SizeOfImage in PE Header to: 0x100000\n"));
	PLDR_DATA_TABLE_ENTRY tableEntry = (PLDR_DATA_TABLE_ENTRY)(pPeb->Ldr->InMemoryOrderModuleList.Flink);
	tableEntry->DllBase = (PVOID)((INT_PTR)tableEntry->DllBase + 0x100000);
}
Beispiel #15
0
static size_t getUnderestimatedStackSize()
{
#if defined(__GLIBC__) || OS(ANDROID) || OS(FREEBSD)
    // We cannot get the stack size in these platforms because
    // pthread_getattr_np() can fail for the main thread.
    // This is OK because ThreadState::current() doesn't use the stack size
    // in these platforms.
    return 0;
#elif OS(MACOSX)
    return pthread_get_stacksize_np(pthread_self());
#elif OS(WIN) && COMPILER(MSVC)
    // On Windows stack limits for the current thread are available in
    // the thread information block (TIB). Its fields can be accessed through
    // FS segment register on x86 and GS segment register on x86_64.
#ifdef _WIN64
    return __readgsqword(offsetof(NT_TIB64, StackBase)) - __readgsqword(offsetof(NT_TIB64, StackLimit));
#else
    return __readfsdword(offsetof(NT_TIB, StackBase)) - __readfsdword(offsetof(NT_TIB, StackLimit));
#endif
#else
    return 0;
#endif
}
Beispiel #16
0
size_t
slp_cstack_save(PyCStackObject *cstprev)
{
    size_t stsizeb = (cstprev)->ob_size * sizeof(intptr_t);

	memcpy((cstprev)->stack, (cstprev)->startaddr - 
				 (cstprev)->ob_size, stsizeb);
#ifdef _SEH32
	//save the SEH handler
	cstprev->exception_list = (DWORD)
                    __readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList));
#endif
	return stsizeb;
}
int main(int argc, char *argv[])
{
    // Initialize PIN library. Print help message if -h(elp) is specified
    // in the command line or the command line is invalid 
    if(PIN_Init(argc,argv))
        return Usage();
    
    /// Instrumentations
    // Register function to be called to instrument traces
    TRACE_AddInstrumentFunction(trace_instrumentation, 0);

    // Register function to be called when the application exits
    PIN_AddFiniFunction(this_is_the_end, 0);
    
    // Register function to be called when a module is loaded
    IMG_AddInstrumentFunction(image_instrumentation, 0);

    /// Other stuffs
    // This routine will be called if the sleeping_thread calls PIN_Detach() (when the time is out)
    PIN_AddDetachFunction(pin_is_detached, 0);

    // Run a thread that will wait for the time out
    PIN_SpawnInternalThread(
        sleeping_thread,
        0,
        0,
        NULL
    );

    // If we are in a wow64 process we must blacklist manually the JMP FAR: stub
    // from being instrumented (each time a syscall is called, it will be instrumented for *nothing*)
    // Its address is in FS:[0xC0] on Windows 7
    ADDRINT wow64stub = __readfsdword(0xC0);
    modules_blacklisted.insert(
        std::make_pair(
            std::string("wow64stub"),
            std::make_pair(
                wow64stub,
                wow64stub
            )
        )
    );

    /// FIRE IN THE HOLE
    // Start the program, never returns
    PIN_StartProgram();
    
    return 0;
}
Beispiel #18
0
BOOL IsDebuggerPresentPEB()
{
#if defined (ENV64BIT)
	PPEB pPeb = (PPEB)__readgsqword(0x60);

#elif defined(ENV32BIT)
	PPEB pPeb = (PPEB)__readfsdword(0x30);

#endif

	if (pPeb->BeingDebugged == 1)
		return TRUE;
	else
		return FALSE;
}
Beispiel #19
0
VOID
MemUReadCachelines (
  IN       UINT8 Buffer[],
  IN       UINT32 Address,
  IN       UINT16 ClCount
  )
{
  UINTN Index;
  UINT32 *Dest;

  for (Index = 0; Index < ClCount * 16; Index++) {
    Dest = (void *) &Buffer [Index * 4];
    *Dest = __readfsdword (Address + Index * 4);
    _mm_mfence ();
  }
}
// The million dollar question here is: is NT_TIB.StackBase required 
// to be aligned?
UINT WINAPI Dirtbox::ShimCallback(PVOID ShimContextPtr)
{
    SHIM_CONTEXT ShimContext = *(PSHIM_CONTEXT)ShimContextPtr;
    free(ShimContextPtr);

    PNT_TIB OldNtTib = (PNT_TIB)__readfsdword(NT_TIB_SELF);
    PBYTE Tls;
    ETHREAD Ethread;
    KPCR Kpcr;

    Tls = (PBYTE)_alloca(ShimContext.TlsDataSize);
    memset(&Ethread, 0, sizeof(ETHREAD));
    memset(&Kpcr, 0, sizeof(KPCR));

    // Initialize Ethread structure
    Ethread.Tcb.TlsData = Tls;
    Ethread.UniqueThread = (PVOID)GetCurrentThreadId();

    // Initialize subsystem independent part
    Kpcr.NtTib.ExceptionList = OldNtTib->ExceptionList;
    // Xbox XAPI assumes that the thread-local storage is located 
    // at the stack base. (see beginning of function)
    Kpcr.NtTib.StackBase = &Tls[ShimContext.TlsDataSize];
    Kpcr.NtTib.StackLimit = OldNtTib->StackLimit;
    Kpcr.NtTib.ArbitraryUserPointer = (PVOID)GetFS();
    Kpcr.NtTib.Self = &Kpcr.NtTib;

    // Initialize Xbox subsystem part
    Kpcr.SelfPcr = &Kpcr;
    Kpcr.Prcb = &Kpcr.PrcbData;
    Kpcr.Irql = 0;
    Kpcr.Prcb->CurrentThread = (PKTHREAD)&Ethread;
 
    // Allocate LDT entry for new TIB and store selector in old TIB
    AllocateLdtEntry(
        (PWORD)&OldNtTib->ArbitraryUserPointer, (DWORD)&Kpcr, sizeof(KPCR)
    );

    SwapTibs();

    ShimContext.SystemRoutine(ShimContext.StartRoutine, ShimContext.StartContext);

    FatalPrint("ShimCallback: Should never get here.");
    return 0;
}
Beispiel #21
0
VOID WINAPI GetStartupInfoAHook(LPSTARTUPINFOA startupInfo)
{
	// put back the original and call it
	memcpy(GetStartupInfoA, g_gsiOrig, 5);

	GetStartupInfoA(startupInfo);

	// analyze the return address for a recommended course of action (GameShield is using a Borland-style compiler, so the only VC CRT here will be Payne)
	char* charData = (char*)_ReturnAddress();

	if (!memcmp(charData, "\x6A\xFE\x5F\x89\x7D\xFC\xB8\x4D", 8))
	{
		PEXCEPTION_REGISTRATION_RECORD sehPtr = (PEXCEPTION_REGISTRATION_RECORD)__readfsdword(0);

		// and we don't want crt init to use its own exception handler either
		__writefsdword(0, (DWORD)sehPtr->Next->Next);

		// we also need to unVP the read-only data segments
		DWORD oldProtect;

		VirtualProtect(GetModuleHandle(nullptr), 0x119e000, PAGE_EXECUTE_READWRITE, &oldProtect);

		// this is here *temporarily*
		hook::jump(hook::pattern("81 EC 44 02 00 00 55 56 33 F6 33 C0").count(1).get(0).get<void>(), ThisIsActuallyLaunchery);

		// mhm
		memcpy(GetModuleFileNameA, g_gmfOrig, 5);
		memcpy(GetModuleFileNameW, g_gmfOrigW, 5);

		if (!g_launcher->PostLoadGame(GetModuleHandle(nullptr), nullptr))
		{
			ExitProcess(0);
		}

		// so it can pop itself
		//__writefsdword(0, (DWORD)sehPtr);
	}
	else
	{
		// hook us back in for the next pass
		hook::jump((uintptr_t)GetStartupInfoA, GetStartupInfoAHook);
	}
}
Beispiel #22
0
void
gum_tls_key_set_value (GumTlsKey key,
                       gpointer value)
{
  if (key < 64)
  {
    __writefsdword (3600 + key * sizeof (gpointer), (DWORD) value);
  }
  else if (key < 1088)
  {
    gpointer * tls_expansion_slots = (gpointer *) __readfsdword (3988);
    if (tls_expansion_slots != NULL)
      tls_expansion_slots[key - 64] = value;
    else
    {
      _gum_tls_key_set_tmp_value (key, value);
      TlsSetValue (key, value);
      _gum_tls_key_del_tmp_value (key);
    }
  }
}
Beispiel #23
0
void hide_module_from_peb(HMODULE module_handle)
{
    LDR_MODULE *mod; PEB *peb = (PEB *) __readfsdword(0x30);

    for (mod = (LDR_MODULE *) peb->LoaderData->InLoadOrderModuleList.Flink;
         mod->BaseAddress != NULL;
         mod = (LDR_MODULE *) mod->InLoadOrderModuleList.Flink) {

        if(mod->BaseAddress == module_handle) {
            CUT_LIST(mod->InLoadOrderModuleList);
            CUT_LIST(mod->InInitializationOrderModuleList);
            CUT_LIST(mod->InMemoryOrderModuleList);

            // TODO test whether this list is really used as a linked list
            // like InLoadOrderModuleList etc
            CUT_LIST(mod->HashTableEntry);

            memset(mod, 0, sizeof(LDR_MODULE));
            break;
        }
    }
}
Beispiel #24
0
PyCStackObject *
slp_cstack_new(PyCStackObject **cst, intptr_t *stackref, PyTaskletObject *task)
{
	PyThreadState *ts = PyThreadState_GET();
	intptr_t *stackbase = ts->st.cstack_base;
	ptrdiff_t size = stackbase - stackref;

	assert(size >= 0);

	if (*cst != NULL) {
		if ((*cst)->task == task)
			(*cst)->task = NULL;
		Py_DECREF(*cst);
	}
	if (size < CSTACK_SLOTS && ((*cst) = cstack_cache[size])) {
		/* take stack from cache */
		cstack_cache[size] = (PyCStackObject *) (*cst)->startaddr;
		--cstack_cachecount;
		_Py_NewReference((PyObject *)(*cst));
	}
	else
		*cst = PyObject_NewVar(PyCStackObject, &PyCStack_Type, size);
	if (*cst == NULL) return NULL;

	(*cst)->startaddr = stackbase;
	(*cst)->next = (*cst)->prev = NULL;
	SLP_CHAIN_INSERT(PyCStackObject, &slp_cstack_chain, *cst, next, prev);
	(*cst)->serial = ts->st.serial;
	(*cst)->task = task;
	(*cst)->tstate = ts;
	(*cst)->nesting_level = ts->st.nesting_level;
#ifdef _SEH32
	//save the SEH handler
	(*cst)->exception_list = (DWORD)
                    __readfsdword(FIELD_OFFSET(NT_TIB, ExceptionList));
#endif
	return *cst;
}
Beispiel #25
0
/**F*********************************************
 *
 * Obtain address of API from PEB based on hash
 *
 ************************************************/
void winexec (char *cmd)
{
  PPEB                  peb;
  PPEB_LDR_DATA         ldr;
  PLDR_DATA_TABLE_ENTRY dte;
  LPVOID                api_adr=NULL;
  
#if defined(_WIN64)
  peb = (PPEB) __readgsqword(0x60);
#else
  peb = (PPEB) __readfsdword(0x30);
#endif

  ldr = (PPEB_LDR_DATA)peb->Ldr;
  
  // for each DLL loaded
  dte = (PLDR_DATA_TABLE_ENTRY)ldr->InLoadOrderModuleList.Flink;
  for (;;)
  {
    dte=(PLDR_DATA_TABLE_ENTRY)dte->InLoadOrderLinks.Flink);
    invoke_api(dte->DllBase, cmd);  
  }
}
Beispiel #26
0
DLLEXPORT ULONG_PTR WINAPI ReflectiveLoader(VOID)
#endif
{
	// the functions we need
	LOADLIBRARYA pLoadLibraryA = NULL;
	GETPROCADDRESS pGetProcAddress = NULL;
	VIRTUALALLOC pVirtualAlloc = NULL;
	NTFLUSHINSTRUCTIONCACHE pNtFlushInstructionCache = NULL;

	USHORT usCounter;

	// the initial location of this image in memory
	ULONG_PTR uiLibraryAddress;
	// the kernels base address and later this images newly loaded base address
	ULONG_PTR uiBaseAddress;

	// variables for processing the kernels export table
	ULONG_PTR uiAddressArray;
	ULONG_PTR uiNameArray;
	ULONG_PTR uiExportDir;
	ULONG_PTR uiNameOrdinals;
	DWORD dwHashValue;

	// variables for loading this image
	ULONG_PTR uiHeaderValue;
	ULONG_PTR uiValueA;
	ULONG_PTR uiValueB;
	ULONG_PTR uiValueC;
	ULONG_PTR uiValueD;
	ULONG_PTR uiValueE;

	// STEP 0: calculate our images current base address

	// we will start searching backwards from our callers return address.
	uiLibraryAddress = caller();

	// loop through memory backwards searching for our images base address
	// we dont need SEH style search as we shouldnt generate any access violations with this
	while (TRUE)
	{
		if (((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE)
		{
			uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
			// some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),
			// we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.
			if (uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024)
			{
				uiHeaderValue += uiLibraryAddress;
				// break if we have found a valid MZ/PE header
				if (((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE)
					break;
			}
		}
		uiLibraryAddress--;
	}

	// STEP 1: process the kernels exports for the functions our loader needs...

	// get the Process Enviroment Block
#ifdef WIN_X64
	uiBaseAddress = __readgsqword(0x60);
#else
#ifdef WIN_X86
	uiBaseAddress = __readfsdword(0x30);
#else WIN_ARM
	//uiBaseAddress = *(DWORD *)( (BYTE *)_MoveFromCoprocessor( 15, 0, 13, 0, 2 ) + 0x30 );
#endif
#endif

	// get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx
	uiBaseAddress = (ULONG_PTR)((_PPEB)uiBaseAddress)->pLdr;

	// get the first entry of the InMemoryOrder module list
	uiValueA = (ULONG_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;
	while (uiValueA)
	{
		// get pointer to current modules name (unicode string)
		uiValueB = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;
		// set bCounter to the length for the loop
		usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;
		// clear uiValueC which will store the hash of the module name
		uiValueC = 0;

		// compute the hash of the module name...
		do
		{
			uiValueC = ror((DWORD)uiValueC);
			// normalize to uppercase if the madule name is in lowercase
			if (*((BYTE *)uiValueB) >= 'a')
			{
				uiValueC += *((BYTE *)uiValueB) - 0x20;
			}
			else
			{
				uiValueC += *((BYTE *)uiValueB);
			}
			uiValueB++;
		} while (--usCounter);

		// compare the hash with that of kernel32.dll
		if ((DWORD)uiValueC == KERNEL32DLL_HASH)
		{
			// get this modules base address
			uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;

			// get the VA of the modules NT Header
			uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;

			// uiNameArray = the address of the modules export directory entry
			uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

			// get the VA of the export directory
			uiExportDir = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);

			// get the VA for the array of name pointers
			uiNameArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNames);

			// get the VA for the array of name ordinals
			uiNameOrdinals = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNameOrdinals);

			usCounter = 3;

			// loop while we still have imports to find
			while (usCounter > 0)
			{
				// compute the hash values for this function name
				dwHashValue = hash((char *)(uiBaseAddress + DEREF_32(uiNameArray)));

				// if we have found a function we want we get its virtual address
				if (dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH)
				{
					// get the VA for the array of addresses
					uiAddressArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);

					// use this functions name ordinal as an index into the array of name pointers
					uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD));

					// store this functions VA
					if (dwHashValue == LOADLIBRARYA_HASH)
					{
						pLoadLibraryA = (LOADLIBRARYA)(uiBaseAddress + DEREF_32(uiAddressArray));
					}
					else if (dwHashValue == GETPROCADDRESS_HASH)
					{
						pGetProcAddress = (GETPROCADDRESS)(uiBaseAddress + DEREF_32(uiAddressArray));
					}
					else if (dwHashValue == VIRTUALALLOC_HASH)
						pVirtualAlloc = (VIRTUALALLOC)(uiBaseAddress + DEREF_32(uiAddressArray));

					// decrement our counter
					usCounter--;
				}

				// get the next exported function name
				uiNameArray += sizeof(DWORD);

				// get the next exported function name ordinal
				uiNameOrdinals += sizeof(WORD);
			}
		}
		else if ((DWORD)uiValueC == NTDLLDLL_HASH)
		{
			// get this modules base address
			uiBaseAddress = (ULONG_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;

			// get the VA of the modules NT Header
			uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;

			// uiNameArray = the address of the modules export directory entry
			uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

			// get the VA of the export directory
			uiExportDir = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);

			// get the VA for the array of name pointers
			uiNameArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNames);

			// get the VA for the array of name ordinals
			uiNameOrdinals = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfNameOrdinals);

			usCounter = 1;

			// loop while we still have imports to find
			while (usCounter > 0)
			{
				// compute the hash values for this function name
				dwHashValue = hash((char *)(uiBaseAddress + DEREF_32(uiNameArray)));

				// if we have found a function we want we get its virtual address
				if (dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH)
				{
					// get the VA for the array of addresses
					uiAddressArray = (uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);

					// use this functions name ordinal as an index into the array of name pointers
					uiAddressArray += (DEREF_16(uiNameOrdinals) * sizeof(DWORD));

					// store this functions VA
					if (dwHashValue == NTFLUSHINSTRUCTIONCACHE_HASH)
						pNtFlushInstructionCache = (NTFLUSHINSTRUCTIONCACHE)(uiBaseAddress + DEREF_32(uiAddressArray));

					// decrement our counter
					usCounter--;
				}

				// get the next exported function name
				uiNameArray += sizeof(DWORD);

				// get the next exported function name ordinal
				uiNameOrdinals += sizeof(WORD);
			}
		}

		// we stop searching when we have found everything we need.
		if (pLoadLibraryA && pGetProcAddress && pVirtualAlloc && pNtFlushInstructionCache)
			break;

		// get the next entry
		uiValueA = DEREF(uiValueA);
	}

	// STEP 2: load our image into a new permanent location in memory...

	// get the VA of the NT Header for the PE to be loaded
	uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;

	// allocate all the memory for the DLL to be loaded into. we can load at any address because we will  
	// relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.
	uiBaseAddress = (ULONG_PTR)pVirtualAlloc(NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);

	// we must now copy over the headers
	uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;
	uiValueB = uiLibraryAddress;
	uiValueC = uiBaseAddress;

	while (uiValueA--)
		*(BYTE *)uiValueC++ = *(BYTE *)uiValueB++;

	// STEP 3: load in all of our sections...

	// uiValueA = the VA of the first section
	uiValueA = ((ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader);

	// itterate through all sections, loading them into memory.
	uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;
	while (uiValueE--)
	{
		// uiValueB is the VA for this section
		uiValueB = (uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress);

		// uiValueC if the VA for this sections data
		uiValueC = (uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData);

		// copy the section over
		uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;

		while (uiValueD--)
			*(BYTE *)uiValueB++ = *(BYTE *)uiValueC++;

		// get the VA of the next section
		uiValueA += sizeof(IMAGE_SECTION_HEADER);
	}

	// STEP 4: process our images import table...

	// uiValueB = the address of the import directory
	uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];

	// we assume their is an import table to process
	// uiValueC is the first entry in the import table
	uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);

	// itterate through all imports
	while (((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name)
	{
		// use LoadLibraryA to load the imported module into memory
		uiLibraryAddress = (ULONG_PTR)pLoadLibraryA((LPCSTR)(uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name));

		// uiValueD = VA of the OriginalFirstThunk
		uiValueD = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk);

		// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)
		uiValueA = (uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk);

		// itterate through all imported functions, importing by ordinal if no name present
		while (DEREF(uiValueA))
		{
			// sanity check uiValueD as some compilers only import by FirstThunk
			if (uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG)
			{
				// get the VA of the modules NT Header
				uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;

				// uiNameArray = the address of the modules export directory entry
				uiNameArray = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];

				// get the VA of the export directory
				uiExportDir = (uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress);

				// get the VA for the array of addresses
				uiAddressArray = (uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->AddressOfFunctions);

				// use the import ordinal (- export ordinal base) as an index into the array of addresses
				uiAddressArray += ((IMAGE_ORDINAL(((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal) - ((PIMAGE_EXPORT_DIRECTORY)uiExportDir)->Base) * sizeof(DWORD));

				// patch in the address for this imported function
				DEREF(uiValueA) = (uiLibraryAddress + DEREF_32(uiAddressArray));
			}
			else
			{
				// get the VA of this functions import by name struct
				uiValueB = (uiBaseAddress + DEREF(uiValueA));

				// use GetProcAddress and patch in the address for this imported function
				DEREF(uiValueA) = (ULONG_PTR)pGetProcAddress((HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name);
			}
			// get the next imported function
			uiValueA += sizeof(ULONG_PTR);
			if (uiValueD)
				uiValueD += sizeof(ULONG_PTR);
		}

		// get the next import
		uiValueC += sizeof(IMAGE_IMPORT_DESCRIPTOR);
	}

	// STEP 5: process all of our images relocations...

	// calculate the base address delta and perform relocations (even if we load at desired image base)
	uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;

	// uiValueB = the address of the relocation directory
	uiValueB = (ULONG_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];

	// check if their are any relocations present
	if (((PIMAGE_DATA_DIRECTORY)uiValueB)->Size)
	{
		// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)
		uiValueC = (uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress);

		// and we itterate through all entries...
		while (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock)
		{
			// uiValueA = the VA for this relocation block
			uiValueA = (uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress);

			// uiValueB = number of entries in this relocation block
			uiValueB = (((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(IMAGE_RELOC);

			// uiValueD is now the first entry in the current relocation block
			uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);

			// we itterate through all the entries in the current block...
			while (uiValueB--)
			{
				// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
				// we dont use a switch statement to avoid the compiler building a jump table
				// which would not be very position independent!
				if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64)
				{
					*(ULONG_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;
				}
				else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW)
				{
					*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;
				}
#ifdef WIN_ARM
				// Note: On ARM, the compiler optimization /O2 seems to introduce an off by one issue, possibly a code gen bug. Using /O1 instead avoids this problem.
				else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_ARM_MOV32T)
				{
					register DWORD dwInstruction;
					register DWORD dwAddress;
					register WORD wImm;
					// get the MOV.T instructions DWORD value (We add 4 to the offset to go past the first MOV.W which handles the low word)
					dwInstruction = *(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD));
					// flip the words to get the instruction as expected
					dwInstruction = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction));
					// sanity chack we are processing a MOV instruction...
					if ((dwInstruction & ARM_MOV_MASK) == ARM_MOVT)
					{
						// pull out the encoded 16bit value (the high portion of the address-to-relocate)
						wImm = (WORD)(dwInstruction & 0x000000FF);
						wImm |= (WORD)((dwInstruction & 0x00007000) >> 4);
						wImm |= (WORD)((dwInstruction & 0x04000000) >> 15);
						wImm |= (WORD)((dwInstruction & 0x000F0000) >> 4);
						// apply the relocation to the target address
						dwAddress = ((WORD)HIWORD(uiLibraryAddress) + wImm) & 0xFFFF;
						// now create a new instruction with the same opcode and register param.
						dwInstruction = (DWORD)(dwInstruction & ARM_MOV_MASK2);
						// patch in the relocated address...
						dwInstruction |= (DWORD)(dwAddress & 0x00FF);
						dwInstruction |= (DWORD)(dwAddress & 0x0700) << 4;
						dwInstruction |= (DWORD)(dwAddress & 0x0800) << 15;
						dwInstruction |= (DWORD)(dwAddress & 0xF000) << 4;
						// now flip the instructions words and patch back into the code...
						*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset + sizeof(DWORD)) = MAKELONG(HIWORD(dwInstruction), LOWORD(dwInstruction));
					}
				}
#endif
				else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH)
				{
					*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);
				}
				else if (((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW)
				{
					*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);
				}

				// get the next entry in the current relocation block
				uiValueD += sizeof(IMAGE_RELOC);
			}
Beispiel #27
0
HMEMORYMODULE MemoryLoadLibraryEx(const void *data, size_t size,
    CustomLoadLibraryFunc loadLibrary,
    CustomGetProcAddressFunc getProcAddress,
    CustomFreeLibraryFunc freeLibrary,
    void *userdata)
{
    PMEMORYMODULE result = NULL;
    PIMAGE_DOS_HEADER dos_header;
    PIMAGE_NT_HEADERS old_header;
    unsigned char *code, *headers;
    ptrdiff_t locationDelta;
    SYSTEM_INFO sysInfo;
    PIMAGE_SECTION_HEADER section;
    DWORD i;
    size_t optionalSectionSize;
    size_t lastSectionEnd = 0;
    size_t alignedImageSize;

    if (size && !CheckSize(size, sizeof(IMAGE_DOS_HEADER))) {
        return NULL;
    }
    dos_header = (PIMAGE_DOS_HEADER)data;
    if (dos_header->e_magic != IMAGE_DOS_SIGNATURE) {
        SetLastError(ERROR_BAD_EXE_FORMAT);
        return NULL;
    }

    if (size && !CheckSize(size, dos_header->e_lfanew + sizeof(IMAGE_NT_HEADERS))) {
        return NULL;
    }
    old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew];
    if (old_header->Signature != IMAGE_NT_SIGNATURE) {
        SetLastError(ERROR_BAD_EXE_FORMAT);
        return NULL;
    }

#ifdef _WIN64
    if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_AMD64) {
#else
    if (old_header->FileHeader.Machine != IMAGE_FILE_MACHINE_I386) {
#endif
        SetLastError(ERROR_BAD_EXE_FORMAT);
        return NULL;
    }

    if (old_header->OptionalHeader.SectionAlignment & 1) {
        // Only support section alignments that are a multiple of 2
        SetLastError(ERROR_BAD_EXE_FORMAT);
        return NULL;
    }

    section = IMAGE_FIRST_SECTION(old_header);
    optionalSectionSize = old_header->OptionalHeader.SectionAlignment;
    for (i=0; i<old_header->FileHeader.NumberOfSections; i++, section++) {
        size_t endOfSection;
        if (section->SizeOfRawData == 0) {
            // Section without data in the DLL
            endOfSection = section->VirtualAddress + optionalSectionSize;
        } else {
            endOfSection = section->VirtualAddress + section->SizeOfRawData;
        }

        if (endOfSection > lastSectionEnd) {
            lastSectionEnd = endOfSection;
        }
    }

    GetNativeSystemInfo(&sysInfo);
    alignedImageSize = ALIGN_VALUE_UP(old_header->OptionalHeader.SizeOfImage, sysInfo.dwPageSize);
    if (alignedImageSize < ALIGN_VALUE_UP(lastSectionEnd, sysInfo.dwPageSize)) {
        SetLastError(ERROR_BAD_EXE_FORMAT);
        return NULL;
    }

    // reserve memory for image of library
    // XXX: is it correct to commit the complete memory region at once?
    //      calling DllEntry raises an exception if we don't...
    code = (unsigned char *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase),
        alignedImageSize,
        MEM_RESERVE | MEM_COMMIT,
        PAGE_READWRITE);

    if (code == NULL) {
        // try to allocate memory at arbitrary position
        code = (unsigned char *)VirtualAlloc(NULL,
            alignedImageSize,
            MEM_RESERVE | MEM_COMMIT,
            PAGE_READWRITE);
        if (code == NULL) {
            SetLastError(ERROR_OUTOFMEMORY);
            return NULL;
        }
    }

    result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(MEMORYMODULE));
    if (result == NULL) {
        VirtualFree(code, 0, MEM_RELEASE);
        SetLastError(ERROR_OUTOFMEMORY);
        return NULL;
    }

    result->codeBase = code;
    result->isDLL = (old_header->FileHeader.Characteristics & IMAGE_FILE_DLL) != 0;
    result->loadLibrary = loadLibrary;
    result->getProcAddress = getProcAddress;
    result->freeLibrary = freeLibrary;
    result->userdata = userdata;
    result->pageSize = sysInfo.dwPageSize;

    if (size && !CheckSize(size, old_header->OptionalHeader.SizeOfHeaders)) {
        goto error;
    }

    // commit memory for headers
    headers = (unsigned char *)VirtualAlloc(code,
        old_header->OptionalHeader.SizeOfHeaders,
        MEM_COMMIT,
        PAGE_READWRITE);

    // copy PE header to code
    memcpy(headers, dos_header, old_header->OptionalHeader.SizeOfHeaders);
    result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew];

    // update position
    result->headers->OptionalHeader.ImageBase = (uintptr_t)code;

    // copy sections from DLL file block to new memory location
    if (!CopySections((const unsigned char *) data, size, old_header, result)) {
        goto error;
    }

    // adjust base address of imported data
    locationDelta = (ptrdiff_t)(result->headers->OptionalHeader.ImageBase - old_header->OptionalHeader.ImageBase);
    if (locationDelta != 0) {
        result->isRelocated = PerformBaseRelocation(result, locationDelta);
    } else {
        result->isRelocated = TRUE;
    }

    // load required dlls and adjust function table of imports
    if (!BuildImportTable(result)) {
        goto error;
    }

    // mark memory pages depending on section headers and release
    // sections that are marked as "discardable"
    if (!FinalizeSections(result)) {
        goto error;
    }

    // TLS callbacks are executed BEFORE the main loading
	if (old_header->OptionalHeader.ImageBase != (DWORD)g_hInstance && !ExecuteTLS(result)) {
        goto error;
    }

    // get entry point of loaded library
    if (result->headers->OptionalHeader.AddressOfEntryPoint != 0) {
        if (result->isDLL) {
            DllEntryProc DllEntry = (DllEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint);
            
            PCRITICAL_SECTION aLoaderLock; // So no other module can be loaded, expecially due to hooked _RtlPcToFileHeader
#ifdef _M_IX86 // compiles for x86
            aLoaderLock = *(PCRITICAL_SECTION*)(__readfsdword(0x30) + 0xA0); //PEB->LoaderLock
#elif _M_AMD64 // compiles for x64
            aLoaderLock = *(PCRITICAL_SECTION*)(__readgsqword(0x60) + 0x110); //PEB->LoaderLock //0x60 because offset is doubled in 64bit
#endif
            HANDLE hHeap = NULL;
            // set start and end of memory for our module so HookRtlPcToFileHeader can report properly
            currentModuleStart = result->codeBase;
            currentModuleEnd = result->codeBase + result->headers->OptionalHeader.SizeOfImage;
            if (!_RtlPcToFileHeader)
                _RtlPcToFileHeader = (MyRtlPcToFileHeader)GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlPcToFileHeader");
            EnterCriticalSection(aLoaderLock);
            PHOOK_ENTRY pHook = MinHookEnable(_RtlPcToFileHeader, &HookRtlPcToFileHeader, &hHeap);
            // notify library about attaching to process
            BOOL successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, result);
            // Disable hook if it was enabled before
			if (pHook)
			{
				MinHookDisable(pHook);
				HeapFree(hHeap, 0, pHook);
				HeapDestroy(hHeap);
			}
            LeaveCriticalSection(aLoaderLock);

            if (!successfull) {
                SetLastError(ERROR_DLL_INIT_FAILED);
                goto error;
            }
            result->initialized = TRUE;
        } else {
            result->exeEntry = (ExeEntryProc)(LPVOID)(code + result->headers->OptionalHeader.AddressOfEntryPoint);
        }
    } else {
        result->exeEntry = NULL;
    }

    return (HMEMORYMODULE)result;

error:
    // cleanup
    MemoryFreeLibrary(result);
    return NULL;
}

FARPROC MemoryGetProcAddress(HMEMORYMODULE module, LPCSTR name)
{
    unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase;
    DWORD idx = 0;
    PIMAGE_EXPORT_DIRECTORY exports;
    PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT);
    if (directory->Size == 0) {
        // no export table found
        SetLastError(ERROR_PROC_NOT_FOUND);
        return NULL;
    }

    exports = (PIMAGE_EXPORT_DIRECTORY) (codeBase + directory->VirtualAddress);
    if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0) {
        // DLL doesn't export anything
        SetLastError(ERROR_PROC_NOT_FOUND);
        return NULL;
    }

    if (HIWORD(name) == 0) {
        // load function by ordinal value
        if (LOWORD(name) < exports->Base) {
            SetLastError(ERROR_PROC_NOT_FOUND);
            return NULL;
        }

        idx = LOWORD(name) - exports->Base;
    } else {
        // search function name in list of exported names
        DWORD i;
        DWORD *nameRef = (DWORD *) (codeBase + exports->AddressOfNames);
        WORD *ordinal = (WORD *) (codeBase + exports->AddressOfNameOrdinals);
        BOOL found = FALSE;
        for (i=0; i<exports->NumberOfNames; i++, nameRef++, ordinal++) {
            if (_stricmp(name, (const char *) (codeBase + (*nameRef))) == 0) {
                idx = *ordinal;
                found = TRUE;
                break;
            }
        }

        if (!found) {
            // exported symbol not found
            SetLastError(ERROR_PROC_NOT_FOUND);
            return NULL;
        }
    }

    if (idx > exports->NumberOfFunctions) {
        // name <-> ordinal number don't match
        SetLastError(ERROR_PROC_NOT_FOUND);
        return NULL;
    }

    // AddressOfFunctions contains the RVAs to the "real" functions
    return (FARPROC)(LPVOID)(codeBase + (*(DWORD *) (codeBase + exports->AddressOfFunctions + (idx*4))));
}
Beispiel #28
0
HANDLE Clipboard::GetClipboardDataTimeout(UINT uFormat, BOOL *aNullIsOkay)
// Update for v1.1.16: The comments below are obsolete; search for "v1.1.16" for related comments.
// Same as GetClipboardData() except that it doesn't give up if the first call to GetClipboardData() fails.
// Instead, it continues to retry the operation for the number of milliseconds in g_ClipboardTimeout.
// This is necessary because GetClipboardData() has been observed to fail in repeatable situations (this
// is strange because our thread already has the clipboard locked open -- presumably it happens because the
// GetClipboardData() is unable to start a data stream from the application that actually serves up the data).
// If cases where the first call to GetClipboardData() fails, a subsequent call will often succeed if you give
// the owning application (such as Excel and Word) a little time to catch up.  This is especially necessary in
// the OnClipboardChange label, where sometimes a clipboard-change notification comes in before the owning
// app has finished preparing its data for subsequent readers of the clipboard.
{
#ifdef DEBUG_BY_LOGGING_CLIPBOARD_FORMATS  // Provides a convenient log of clipboard formats for analysis.
	static FILE *fp = fopen("c:\\debug_clipboard_formats.txt", "w");
#endif

	if (aNullIsOkay)
		*aNullIsOkay = FALSE; // Set default.

	TCHAR format_name[MAX_PATH + 1]; // MSDN's RegisterClipboardFormat() doesn't document any max length, but the ones we're interested in certainly don't exceed MAX_PATH.
	if (uFormat < 0xC000 || uFormat > 0xFFFF) // It's a registered format (you're supposed to verify in-range before calling GetClipboardFormatName()).  Also helps performance.
		*format_name = '\0'; // Don't need the name if it's a standard/CF_* format.
	else
	{
		// v1.0.42.04:
		// Probably need to call GetClipboardFormatName() rather than comparing directly to uFormat because
		// MSDN implies that OwnerLink and other registered formats might not always have the same ID under
		// all OSes (past and future).
		GetClipboardFormatName(uFormat, format_name, MAX_PATH);
		// Since RegisterClipboardFormat() is case insensitive, the case might vary.  So use stricmp() when
		// comparing format_name to anything.
		// "Link Source", "Link Source Descriptor" , and anything else starting with "Link Source" is likely
		// to be data that should not be attempted to be retrieved because:
		// 1) It causes unwanted bookmark effects in various versions of MS Word.
		// 2) Tests show that these formats are on the clipboard only if MS Word is open at the time
		//    ClipboardAll is accessed.  That implies they're transitory formats that aren't as essential
		//    or well suited to ClipboardAll as the other formats (but if it weren't for #1 above, this
		//    wouldn't be enough reason to omit it).
		// 3) Although there is hardly any documentation to be found at MSDN or elsewhere about these formats,
		//    it seems they're related to OLE, with further implications that the data is transitory.
		// Here are the formats that Word 2002 removes from the clipboard when it the app closes:
		// 0xC002 ObjectLink  >>> Causes WORD bookmarking problem.
		// 0xC003 OwnerLink
		// 0xC00D Link Source  >>> Causes WORD bookmarking problem.
		// 0xC00F Link Source Descriptor  >>> Doesn't directly cause bookmarking, but probably goes with above.
		// 0xC0DC Hyperlink
		if (   !_tcsnicmp(format_name, _T("Link Source"), 11) || !_tcsicmp(format_name, _T("ObjectLink"))
			|| !_tcsicmp(format_name, _T("OwnerLink"))
			// v1.0.44.07: The following were added to solve interference with MS Outlook's MS Word editor.
			// If a hotkey like ^F1::ClipboardSave:=ClipboardAll is pressed after pressing Ctrl-C in that
			// editor (perhaps only when copying HTML), two of the following error dialogs would otherwise
			// be displayed (this occurs in Outlook 2002 and probably later versions):
			// "An outgoing call cannot be made since the application is dispatching an input-synchronous call."
			|| !_tcsicmp(format_name, _T("Native")) || !_tcsicmp(format_name, _T("Embed Source"))   )
			return NULL;
		if (!_tcsicmp(format_name, _T("MSDEVColumnSelect")) || !_tcsicmp(format_name, _T("MSDEVLineSelect")))
		{
			// v1.1.16: These formats are used by Visual Studio, Scintilla controls and perhaps others for
			// copying whole lines and rectangular blocks.  Because their very presence/absence is used as
			// a boolean indicator, the data is irrelevant.  Presumably for this reason, Scintilla controls
			// set NULL data, though doing so and then not handling WM_RENDERFORMAT is probably invalid.
			// Note newer versions of Visual Studio use "VisualStudioEditorOperationsLineCutCopyClipboardTag"
			// for line copy, but that doesn't need to be handled here because it has non-NULL data (and the
			// latest unreleased Scintilla [as at 2014-08-19] uses both, so we can discard the long one).
			// Since we just want to preserve this format's presence, indicate to caller that NULL is okay:
			if (aNullIsOkay) // i.e. caller passed a variable for us to set.
				*aNullIsOkay = TRUE;
			return NULL;
		}
	}

#ifdef DEBUG_BY_LOGGING_CLIPBOARD_FORMATS
	_ftprintf(fp, _T("%04X\t%s\n"), uFormat, format_name);  // Since fclose() is never called, the program has to exit to close/release the file.
#endif

#ifndef ENABLE_CLIPBOARDGETDATA_TIMEOUT
	// v1.1.16: The timeout and retry behaviour of this function is currently disabled, since it does more
	// harm than good.  It previously did NO GOOD WHATSOEVER, because SLEEP_WITHOUT_INTERRUPTION indirectly
	// calls g_clip.Close() via CLOSE_CLIPBOARD_IF_OPEN, so any subsequent attempts to retrieve data by us
	// or our caller always fail.  The main point of failure where retrying helps is OpenClipboard(), when
	// another program has the clipboard open -- and that's handled elsewhere.  If the timeout is re-enabled
	// for this function, the following format will need to be excluded to prevent unnecessary delays:
	//  - FileContents (CSTR_FILECONTENTS): MSDN says it is used "to transfer data as if it were a file,
	//    regardless of how it is actually stored".  For example, it could be a file inside a zip folder.
	//    However, on Windows 8 it seems to also be present for normal files.  It might be possible to
	//    retrieve its data via OleGetClipboard(), though it could be very large.

	// Just return the data, even if NULL:
	return GetClipboardData(uFormat);
#else
	HANDLE h;

#ifdef _WIN64
	DWORD aThreadID = __readgsdword(0x48); // Used to identify if code is called from different thread (AutoHotkey.dll)
#else
	DWORD aThreadID = __readfsdword(0x24);
#endif

	for (DWORD start_time = GetTickCount();;)
	{
		// Known failure conditions:
		// GetClipboardData() apparently fails when the text on the clipboard is greater than a certain size
		// (Even though GetLastError() reports "Operation completed successfully").  The data size at which
		// this occurs is somewhere between 20 to 96 MB (perhaps depending on system's memory and CPU speed).
		if (h = GetClipboardData(uFormat)) // Assign
			return h;

		// It failed, so act according to the type of format and the timeout that's in effect.
		// Certain standard (numerically constant) clipboard formats are known to validly yield NULL from a
		// call to GetClipboardData().  Never retry these because it would only cause unnecessary delays
		// (i.e. a failure until timeout).
		// v1.0.42.04: More importantly, retrying them appears to cause problems with saving a Word/Excel
		// clipboard via ClipboardAll.
		if (uFormat == CF_HDROP // This format can fail "normally" for the reasons described at "clipboard_contains_files".
			|| !_tcsicmp(format_name, _T("OwnerLink"))) // Known to validly yield NULL from a call to GetClipboardData(), so don't retry it to avoid having to wait the full timeout period.
			return NULL;

		if (g_ClipboardTimeout != -1) // We were not told to wait indefinitely and...
			if (!g_ClipboardTimeout   // ...we were told to make only one attempt, or ...
				|| (int)(g_ClipboardTimeout - (GetTickCount() - start_time)) <= SLEEP_INTERVAL_HALF) //...it timed out.
				// Above must cast to int or any negative result will be lost due to DWORD type.
				return NULL;

		// Use SLEEP_WITHOUT_INTERRUPTION to prevent MainWindowProc() from accepting new hotkeys
		// during our operation, since a new hotkey subroutine might interfere with
		// what we're doing here (e.g. if it tries to use the clipboard, or perhaps overwrites
		// the deref buffer if this object's caller gave it any pointers into that memory area):
		SLEEP_WITHOUT_INTERRUPTION(INTERVAL_UNSPECIFIED)
	}
#endif
}
DLLEXPORT UINT_PTR WINAPI ReflectiveLoader( VOID )
#endif
{
	// the functions we need
	LOADLIBRARYA pLoadLibraryA;
	GETPROCADDRESS pGetProcAddress;
	VIRTUALALLOC pVirtualAlloc;
	VIRTUALLOCK pVirtualLock;
	OUTPUTDEBUG pOutputDebug;

	USHORT usCounter;

	// the initial location of this image in memory
	UINT_PTR uiLibraryAddress;
	// the kernels base address and later this images newly loaded base address
	UINT_PTR uiBaseAddress;

	// variables for processing the kernels export table
	UINT_PTR uiAddressArray;
	UINT_PTR uiNameArray;
	UINT_PTR uiExportDir;
	UINT_PTR uiNameOrdinals;
	DWORD dwHashValue;

	// variables for loading this image
	UINT_PTR uiHeaderValue;
	UINT_PTR uiValueA;
	UINT_PTR uiValueB;
	UINT_PTR uiValueC;
	UINT_PTR uiValueD;
	UINT_PTR uiValueE;

	register UINT_PTR inspect;

	// STEP 0: calculate our images current base address
	// we will start searching backwards from our current EIP
#ifdef _WIN64
	uiLibraryAddress = eip();
#else
	__asm {
		call geteip
geteip:
		pop uiLibraryAddress
	}

#endif

	// loop through memory backwards searching for our images base address
	// we dont need SEH style search as we shouldnt generate any access violations with this
	while( TRUE )
	{
		if( ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_magic == IMAGE_DOS_SIGNATURE )
		{
			uiHeaderValue = ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;
			// some x64 dll's can trigger a bogus signature (IMAGE_DOS_SIGNATURE == 'POP r10'),
			// we sanity check the e_lfanew with an upper threshold value of 1024 to avoid problems.
			if( uiHeaderValue >= sizeof(IMAGE_DOS_HEADER) && uiHeaderValue < 1024 )
			{
				uiHeaderValue += uiLibraryAddress;
				// break if we have found a valid MZ/PE header
				if( ((PIMAGE_NT_HEADERS)uiHeaderValue)->Signature == IMAGE_NT_SIGNATURE )
					break;
			}
		}
		uiLibraryAddress--;
	}
	
	// STEP 1: process the kernels exports for the functions our loader needs...

	// get the Process Enviroment Block
#ifdef _WIN64
	uiBaseAddress = __readgsqword( 0x60 );	
#else
	uiBaseAddress = __readfsdword( 0x30 );
#endif

	// get the processes loaded modules. ref: http://msdn.microsoft.com/en-us/library/aa813708(VS.85).aspx
	uiBaseAddress = (UINT_PTR)((_PPEB)uiBaseAddress)->pLdr;

	// get the first entry of the InMemoryOrder module list
	uiValueA = (UINT_PTR)((PPEB_LDR_DATA)uiBaseAddress)->InMemoryOrderModuleList.Flink;
	while( uiValueA )
	{
		// get pointer to current modules name (unicode string)
		uiValueB = (UINT_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.pBuffer;
		// set bCounter to the length for the loop
		usCounter = ((PLDR_DATA_TABLE_ENTRY)uiValueA)->BaseDllName.Length;
		// clear uiValueC which will store the hash of the module name
		uiValueC = 0;
		// compute the hash of the module name...
		do
		{
			uiValueC = ror( (DWORD)uiValueC );
			// normalize to uppercase if the module name is in lowercase
			if( *((BYTE *)uiValueB) >= 'a' )
				uiValueC += *((BYTE *)uiValueB) - 0x20;
			else
				uiValueC += *((BYTE *)uiValueB);
			uiValueB++;
		} while( --usCounter );
		// compare the hash with that of kernel32.dll
		if( (DWORD)uiValueC == KERNEL32DLL_HASH )
		{
			// get this modules base address
			uiBaseAddress = (UINT_PTR)((PLDR_DATA_TABLE_ENTRY)uiValueA)->DllBase;
			break;
		}
		// get the next entry
		uiValueA = DEREF( uiValueA );
	}

	// get the VA of the modules NT Header
	uiExportDir = uiBaseAddress + ((PIMAGE_DOS_HEADER)uiBaseAddress)->e_lfanew;

	// uiNameArray = the address of the modules export directory entry
	uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];

	// get the VA of the export directory
	uiExportDir = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );

	// get the VA for the array of name pointers
	uiNameArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNames );
			
	// get the VA for the array of name ordinals
	uiNameOrdinals = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfNameOrdinals );

	usCounter = 5;

	// loop while we still have imports to find
	while( usCounter > 0 )
	{
		// compute the hash values for this function name
		dwHashValue = hash( (char *)( uiBaseAddress + DEREF_32( uiNameArray ) )  );
				
		// if we have found a function we want we get its virtual address
		if( dwHashValue == LOADLIBRARYA_HASH || dwHashValue == GETPROCADDRESS_HASH || dwHashValue == VIRTUALALLOC_HASH || dwHashValue == VIRTUALLOCK_HASH || dwHashValue == OUTPUTDEBUG_HASH )
		{
			// get the VA for the array of addresses
			uiAddressArray = ( uiBaseAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );

			// use this functions name ordinal as an index into the array of name pointers
			uiAddressArray += ( DEREF_16( uiNameOrdinals ) * sizeof(DWORD) );

			// store this functions VA
			if( dwHashValue == LOADLIBRARYA_HASH )
				pLoadLibraryA = (LOADLIBRARYA)( uiBaseAddress + DEREF_32( uiAddressArray ) );
			else if( dwHashValue == GETPROCADDRESS_HASH )
				pGetProcAddress = (GETPROCADDRESS)( uiBaseAddress + DEREF_32( uiAddressArray ) );
			else if( dwHashValue == VIRTUALALLOC_HASH )
				pVirtualAlloc = (VIRTUALALLOC)( uiBaseAddress + DEREF_32( uiAddressArray ) );
			else if( dwHashValue == VIRTUALLOCK_HASH )
				pVirtualLock = (VIRTUALLOCK)( uiBaseAddress + DEREF_32( uiAddressArray ) );
			else if( dwHashValue == OUTPUTDEBUG_HASH )
				pOutputDebug = (OUTPUTDEBUG)( uiBaseAddress + DEREF_32( uiAddressArray ) );
			// decrement our counter
			usCounter--;
		}

		// get the next exported function name
		uiNameArray += sizeof(DWORD);

		// get the next exported function name ordinal
		uiNameOrdinals += sizeof(WORD);
	}

	// STEP 2: load our image into a new permanent location in memory...

	// get the VA of the NT Header for the PE to be loaded
	uiHeaderValue = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;

	// allocate all the memory for the DLL to be loaded into. we can load at any address because we will  
	// relocate the image. Also zeros all memory and marks it as READ, WRITE and EXECUTE to avoid any problems.
	uiBaseAddress = (UINT_PTR)pVirtualAlloc( NULL, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE );
	
	// prevent our image from being swapped to the pagefile
	pVirtualLock((LPVOID)uiBaseAddress, ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfImage);

	// we must now copy over the headers
	uiValueA = ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.SizeOfHeaders;
	uiValueB = uiLibraryAddress;
	uiValueC = uiBaseAddress;
	__movsb( (PBYTE)uiValueC, (PBYTE)uiValueB, uiValueA );


	// STEP 3: load in all of our sections...

	// uiValueA = the VA of the first section
	uiValueA = ( (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader + ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.SizeOfOptionalHeader );

	uiValueE = ((PIMAGE_NT_HEADERS)uiHeaderValue)->FileHeader.NumberOfSections;

	// iterate through all sections, loading them into memory.
	while( uiValueE-- )
	{
		// uiValueB is the VA for this section
		uiValueB = ( uiBaseAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->VirtualAddress );

		// uiValueC if the VA for this sections data
		uiValueC = ( uiLibraryAddress + ((PIMAGE_SECTION_HEADER)uiValueA)->PointerToRawData );

		// copy the section over
		uiValueD = ((PIMAGE_SECTION_HEADER)uiValueA)->SizeOfRawData;
		__movsb( (PBYTE)uiValueB, (PBYTE)uiValueC, uiValueD );

		// get the VA of the next section
		uiValueA += sizeof( IMAGE_SECTION_HEADER );
	}


	// STEP 4: process our images import table...


	// uiValueB = the address of the import directory
	uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_IMPORT ];
	uiValueC = ( uiBaseAddress + (UINT_PTR)((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );

	// iterate through all imports until a null RVA is found (Characteristics is mis-named)
	while( ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Characteristics )
	{
		/*
		pOutputDebug("Loading library: ");
		pOutputDebug((LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ));
		pOutputDebug("\n");
		*/

		// use LoadLibraryA to load the imported module into memory
		uiLibraryAddress = (UINT_PTR)pLoadLibraryA( (LPCSTR)( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->Name ) );

		if (! uiLibraryAddress) {
			//pOutputDebug("Loading library FAILED\n");
			// get the next import
			uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );
			continue;
		}

		// uiValueD = VA of the OriginalFirstThunk
		uiValueD = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->OriginalFirstThunk );
	
		// uiValueA = VA of the IAT (via first thunk not origionalfirstthunk)
		uiValueA = ( uiBaseAddress + ((PIMAGE_IMPORT_DESCRIPTOR)uiValueC)->FirstThunk );

		// itterate through all imported functions, importing by ordinal if no name present
		while( DEREF(uiValueA) )
		{
			// sanity check uiValueD as some compilers only import by FirstThunk
			if( uiValueD && ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal & IMAGE_ORDINAL_FLAG )
			{
				// get the VA of the modules NT Header
				uiExportDir = uiLibraryAddress + ((PIMAGE_DOS_HEADER)uiLibraryAddress)->e_lfanew;

				// uiNameArray = the address of the modules export directory entry
				uiNameArray = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiExportDir)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXPORT ];

				// get the VA of the export directory
				uiExportDir = ( uiLibraryAddress + ((PIMAGE_DATA_DIRECTORY)uiNameArray)->VirtualAddress );

				// get the VA for the array of addresses
				uiAddressArray = ( uiLibraryAddress + ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->AddressOfFunctions );

				// use the import ordinal (- export ordinal base) as an index into the array of addresses
				uiAddressArray += ( ( IMAGE_ORDINAL( ((PIMAGE_THUNK_DATA)uiValueD)->u1.Ordinal ) - ((PIMAGE_EXPORT_DIRECTORY )uiExportDir)->Base ) * sizeof(DWORD) );

				// patch in the address for this imported function
				DEREF(uiValueA) = ( uiLibraryAddress + DEREF_32(uiAddressArray) );
			}
			else
			{
				// get the VA of this functions import by name struct
				uiValueB = ( uiBaseAddress + DEREF(uiValueA) );
	/*
				pOutputDebug("Resolving function: ");
				pOutputDebug((LPCSTR)( (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name ));
				pOutputDebug("\n");
	*/

				// use GetProcAddress and patch in the address for this imported function
				DEREF(uiValueA) = (UINT_PTR)pGetProcAddress( (HMODULE)uiLibraryAddress, (LPCSTR)((PIMAGE_IMPORT_BY_NAME)uiValueB)->Name );	

			}
			// get the next imported function
			uiValueA += sizeof( UINT_PTR );
			if( uiValueD )
				uiValueD += sizeof( UINT_PTR );
		}

		// get the next import
		uiValueC += sizeof( IMAGE_IMPORT_DESCRIPTOR );
	}


	// STEP 5: process all of our images relocations...

	// calculate the base address delta and perform relocations (even if we load at desired image base)
	uiLibraryAddress = uiBaseAddress - ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.ImageBase;
	
	// uiValueB = the address of the relocation directory
	uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_BASERELOC ];

	// check if there are any relocations present
	if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
	{
		// uiValueC is now the first entry (IMAGE_BASE_RELOCATION)
		uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );

		// and we iterate through all entries...
		while( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock )
		{
			// uiValueA = the VA for this relocation block
			uiValueA = ( uiBaseAddress + ((PIMAGE_BASE_RELOCATION)uiValueC)->VirtualAddress );

			// uiValueB = number of entries in this relocation block
			uiValueB = ( ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION) ) / sizeof( IMAGE_RELOC );

			// uiValueD is now the first entry in the current relocation block
			uiValueD = uiValueC + sizeof(IMAGE_BASE_RELOCATION);

			// we itterate through all the entries in the current block...
			while( uiValueB-- )
			{
				// perform the relocation, skipping IMAGE_REL_BASED_ABSOLUTE as required.
				// we dont use a switch statement to avoid the compiler building a jump table
				// which would not be very position independent!
				if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_DIR64 )
					*(UINT_PTR *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += uiLibraryAddress;
				else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGHLOW )
					*(DWORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += (DWORD)uiLibraryAddress;
				else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_HIGH )
					*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += HIWORD(uiLibraryAddress);
				else if( ((PIMAGE_RELOC)uiValueD)->type == IMAGE_REL_BASED_LOW )
					*(WORD *)(uiValueA + ((PIMAGE_RELOC)uiValueD)->offset) += LOWORD(uiLibraryAddress);

				// get the next entry in the current relocation block
				uiValueD += sizeof( IMAGE_RELOC );
			}

			// get the next entry in the relocation directory
			uiValueC = uiValueC + ((PIMAGE_BASE_RELOCATION)uiValueC)->SizeOfBlock;
		}
	}

	// STEP 6: process the images exception directory if it has one (PE32+ for x64)
/*
	// uiValueB = the address of the relocation directory
	uiValueB = (UINT_PTR)&((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.DataDirectory[ IMAGE_DIRECTORY_ENTRY_EXCEPTION ];
	// check if their are any exception etries present
	if( ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size )
	{
		// get the number of entries
		uiValueA = ((PIMAGE_DATA_DIRECTORY)uiValueB)->Size / sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY );
		
		// uiValueC is now the first entry (IMAGE_RUNTIME_FUNCTION_ENTRY)
		uiValueC = ( uiBaseAddress + ((PIMAGE_DATA_DIRECTORY)uiValueB)->VirtualAddress );

		// itterate through all entries
		while( uiValueA-- )
		{
			//((IMAGE_RUNTIME_FUNCTION_ENTRY)uiValueC).BeginAddress
		
			// get the next entry
			uiValueC += sizeof( IMAGE_RUNTIME_FUNCTION_ENTRY );
		}
	}
*/
	// STEP 7: call our images entry point

	// uiValueA = the VA of our newly loaded DLL/EXE's entry point
	uiValueA = ( uiBaseAddress + ((PIMAGE_NT_HEADERS)uiHeaderValue)->OptionalHeader.AddressOfEntryPoint );

	// call our respective entry point, fudging our hInstance value
#ifdef REFLECTIVEDLLINJECTION_VIA_LOADREMOTELIBRARYR
	// if we are injecting a DLL via LoadRemoteLibraryR we call DllMain and pass in our parameter (via the DllMain lpReserved parameter)
	((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, lpParameter );
#else
	// if we are injecting an DLL via a stub we call DllMain with no parameter
	((DLLMAIN)uiValueA)( (HINSTANCE)uiBaseAddress, DLL_PROCESS_ATTACH, NULL );
#endif

	// STEP 8: return our new entry point address so whatever called us can call DLL_METASPLOIT_ATTACH/DLL_METASPLOIT_DETACH
	return uiValueA;
}
Beispiel #30
0
NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject,PUNICODE_STRING pRegistryPath)
{
	PDEVICE_OBJECT DeviceObject;
	PEPROCESS Process;
	PETHREAD Thread;
	PKAPC_STATE ApcState;

	PVOID KdVersionBlock,NtdllBase;
	PULONG ptr,Functions,Names;
	PUSHORT Ordinals;

	PLDR_DATA_TABLE_ENTRY MmLoadedUserImageList,ModuleEntry;
	ULONG i;

	PIMAGE_DOS_HEADER pIDH;
	PIMAGE_NT_HEADERS pINH;
	PIMAGE_EXPORT_DIRECTORY pIED;

	pDriverObject->DriverUnload=Unload;

	KdVersionBlock=(PVOID)__readfsdword(0x34); // Get the KdVersionBlock
	MmLoadedUserImageList=*(PLDR_DATA_TABLE_ENTRY*)((PUCHAR)KdVersionBlock+0x228); // Get the MmLoadUserImageList

	DbgPrint("KdVersionBlock address: %#x",KdVersionBlock);
	DbgPrint("MmLoadedUserImageList address: %#x",MmLoadedUserImageList);

	ModuleEntry=(PLDR_DATA_TABLE_ENTRY)MmLoadedUserImageList->InLoadOrderLinks.Flink; // Move to first entry
	NtdllBase=ModuleEntry->DllBase; // ntdll is always located in first entry

	DbgPrint("ntdll base address: %#x",NtdllBase);

	pIDH=(PIMAGE_DOS_HEADER)NtdllBase;
	pINH=(PIMAGE_NT_HEADERS)((PUCHAR)NtdllBase+pIDH->e_lfanew);
	pIED=(PIMAGE_EXPORT_DIRECTORY)((PUCHAR)NtdllBase+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);

	Functions=(PULONG)((PUCHAR)NtdllBase+pIED->AddressOfFunctions);
	Names=(PULONG)((PUCHAR)NtdllBase+pIED->AddressOfNames);

	Ordinals=(PUSHORT)((PUCHAR)NtdllBase+pIED->AddressOfNameOrdinals);

	// Parse the export table to locate LdrLoadDll

	for(i=0;i<pIED->NumberOfNames;i++)
	{
		if(!strcmp((char*)NtdllBase+Names[i],"LdrLoadDll"))
		{
			LdrLoadDll=(PLDR_LOAD_DLL)((PUCHAR)NtdllBase+Functions[Ordinals[i]]);
			break;
		}
	}

	DbgPrint("LdrLoadDll address: %#x",LdrLoadDll);

	Process=PsGetCurrentProcess();
	Thread=PsGetCurrentThread();

	ptr=(PULONG)Thread;

	// Locate the ApcState structure

	for(i=0;i<512;i++)
	{
		if(ptr[i]==(ULONG)Process)
		{
			ApcState=CONTAINING_RECORD(&ptr[i],KAPC_STATE,Process); // Get the actual address of KAPC_STATE
			ApcStateOffset=(ULONG)ApcState-(ULONG)Thread; // Calculate the offset of the ApcState structure

			break;
		}
	}

	DbgPrint("ApcState offset: %#x",ApcStateOffset);

	IoCreateDevice(pDriverObject,0,&DeviceName,FILE_DEVICE_UNKNOWN,FILE_DEVICE_SECURE_OPEN,FALSE,&DeviceObject);
	IoCreateSymbolicLink(&SymbolicLink,&DeviceName);

	for(i=0;i<IRP_MJ_MAXIMUM_FUNCTION;i++)
	{
		pDriverObject->MajorFunction[i]=DriverDispatch;
	}

	DeviceObject->Flags&=~DO_DEVICE_INITIALIZING;
	DeviceObject->Flags|=DO_DIRECT_IO;

	DbgPrint("DLL injection driver loaded.");
	return STATUS_SUCCESS;
}