zoukankan      html  css  js  c++  java
  • 注入(5)---导入表注入(HookINT)

    导入表是WindowsPE文件中的一组数据结构,可执行程序(即EXE文件)被加载到地址空间后,每个导入的DLL模块都有一个对应的导入表,PE加载器会根据导入表来加载进程需要的其他DLL模块。
    导入表的数据结构如下:

    typedef struct _IMAGE_IMPORT_DESCRIPTOR {
        union {
            DWORD   Characteristics;            // 0 for terminating null import descriptor
            DWORD   OriginalFirstThunk;         // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
        } DUMMYUNIONNAME;
        DWORD   TimeDateStamp;                  // 0 if not bound,
                                                // -1 if bound, and real date	ime stamp
                                                //     in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
                                                // O.W. date/time stamp of DLL bound to (Old BIND)
    
        DWORD   ForwarderChain;                 // -1 if no forwarders
        DWORD   Name;
        DWORD   FirstThunk;                     // RVA to IAT (if bound this IAT has actual addresses)
    } IMAGE_IMPORT_DESCRIPTOR;


    OriginalFirstThunk/Characteristics:指向导入表(INT)的RVA(相对虚拟地址)。INT是一个IMAGE_THUNK_DATA结构的数组,数组中的每个元素指向一个IMAGE_IMPORT_BY_NAME结构,INT以元素0结束。
    TimeDateStamp:时间戳,可以忽略。
    ForwarderChain:如果没有前向引用(forwarders)的话就是-1.
    Name:被导入DLL的名字指针,是一个RVA。
    FirstThunk:指向导入表(IAT)的RVA。IAT是一个IMAGE_THUNK_DATA结构的数组。

    导入表逻辑结构如下:

    下面贴出源码:


    // INTHook.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include<Windows.h>
    #include <exception>
    #include <iostream>
    using namespace std;
    
    BOOL AddImportTable(const WCHAR * wzPEFilePath, char * szInjectDllName, char *szFunctionName);
    BOOL AddNewImportDescriptor(const WCHAR * wzPEFilePath, char * szInjectDllName, char *szImportFunctionName);
    BOOL AddNewSection(LPCTSTR lpModulePath, DWORD dwNewSectionSize);
    DWORD PEAlign(DWORD dwTarNumber, DWORD dwAlignTo);
    DWORD RVAToOffset(PIMAGE_NT_HEADERS pImageNTHeader, DWORD dwRVA);
    PIMAGE_SECTION_HEADER ImageRVAToSection(PIMAGE_NT_HEADERS pImageNTHeader, DWORD dwRVA);
    int main()
    {
    	WCHAR TargetPath[0x20] = {0};
    	char DllPath[0x20] = "InjectDll.dll";
    
    	printf("Please Input Target Full Path:
    ");
    	//scanf_s(TargetPath, "%s");
    	wcin >> TargetPath;
    	AddImportTable(TargetPath,DllPath, "InjectFunction");
    
        return 0;
    }
    
    BOOL AddImportTable(const WCHAR * wzPEFilePath, char * szInjectDllName, char *szFunctionName)
    {
    	BOOL bOk = FALSE;
    	try
    	{
    		//增加一个叫"WINSUN"的节
    		bOk = AddNewSection(wzPEFilePath, 256);
    		if (!bOk)
    		{
    			MessageBox(NULL, L"Add New Section Fail", L"Error", MB_OK);
    			return bOk;
    		}
    		//增加一个导入表
    		AddNewImportDescriptor(wzPEFilePath, szInjectDllName, szFunctionName);
    	}
    	catch (exception* e)
    	{
    		return bOk;
    	}
    	return bOk;
    }
    
    
    //
    //增加导入表项
    //
    BOOL AddNewSection(LPCTSTR lpModulePath, DWORD dwNewSectionSize)
    {
    	BOOL   bOk = FALSE;
    	LPVOID lpMemoryModule = NULL;
    	LPBYTE lpData = NULL;
    	DWORD  dwNewSectionFileSize, dwNewSectionMemorySize;
    	HANDLE FileHandle = INVALID_HANDLE_VALUE, MappingHandle = INVALID_HANDLE_VALUE;
    	PIMAGE_NT_HEADERS NtHeader = NULL;
    	PIMAGE_SECTION_HEADER NewSection = NULL, LastSection = NULL;
    
    	printf("[!] AddNewSection Enter!
    ");
    
    	//TODO:可能还涉及关闭windows文件保护
    	__try
    	{
    		//pe文件映射到内存
    		FileHandle = CreateFile(
    			lpModulePath,
    			GENERIC_READ | GENERIC_WRITE,
    			FILE_SHARE_READ | FILE_SHARE_WRITE,
    			NULL,
    			OPEN_EXISTING,
    			FILE_ATTRIBUTE_NORMAL,
    			NULL
    		);
    		if (INVALID_HANDLE_VALUE == FileHandle)
    		{
    			printf("[-] AddNewSection CreateFile Fail!
    ");
    			goto _EXIT_;
    		}
    
    		DWORD dwFileLength = GetFileSize(FileHandle, NULL);
    		//映射PE文件
    		MappingHandle = CreateFileMapping(FileHandle, NULL, PAGE_READWRITE/* | SEC_IMAGE*/, 0, dwFileLength,L"WINSUN_MAPPING_FILE");
    		if (NULL == MappingHandle)
    		{
    
    			printf("[-] AddNewSection CreateFileMapping Fail!
    ");
    			goto _EXIT_;
    
    		}
    
    		lpMemoryModule = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, dwFileLength);
    		if (NULL == lpMemoryModule)
    		{
    			printf("[-] AddNewSection MapViewOfFile Fail!
    ");
    			goto _EXIT_;
    		}
    
    		lpData = (LPBYTE)lpMemoryModule;
    		//判断是否是PE文件
    		if (((PIMAGE_DOS_HEADER)lpData)->e_magic != IMAGE_DOS_SIGNATURE)
    		{
    			printf("[-] AddNewSection PE Header MZ error!
    ");
    			goto _EXIT_;
    		}
    
    		NtHeader = (PIMAGE_NT_HEADERS)(lpData + ((PIMAGE_DOS_HEADER)(lpData))->e_lfanew);
    		if (NtHeader->Signature != IMAGE_NT_SIGNATURE)
    		{
    			printf("[-] AddNewSection PE Header PE Error!
    ");
    			goto _EXIT_;
    		}
    
    		//判断是否可以增加一个新节
    		if (((NtHeader->FileHeader.NumberOfSections + 1) * sizeof(IMAGE_SECTION_HEADER)) > (NtHeader->OptionalHeader.SizeOfHeaders))
    		{
    			printf("[-] AddNewSection Cannot Add A New Section!
    ");
    			goto _EXIT_;
    		}
    
    		NewSection = (PIMAGE_SECTION_HEADER)(NtHeader + 1) + NtHeader->FileHeader.NumberOfSections;
    		LastSection = NewSection - 1;
    
    
    		DWORD rSize, vSize, rOffset, vOffset;
    		//对齐偏移和RVA
    		rSize = PEAlign(dwNewSectionSize,
    			NtHeader->OptionalHeader.FileAlignment);
    
    		rOffset = PEAlign(LastSection->PointerToRawData + LastSection->SizeOfRawData,
    			NtHeader->OptionalHeader.FileAlignment);
    
    		vSize = PEAlign(dwNewSectionSize,
    			NtHeader->OptionalHeader.SectionAlignment);
    
    		vOffset = PEAlign(LastSection->VirtualAddress + LastSection->Misc.VirtualSize,
    			NtHeader->OptionalHeader.SectionAlignment);
    
    		//填充新节表
    		memcpy(NewSection->Name, "WINSUN", strlen("WINSUN"));
    		NewSection->VirtualAddress = vOffset;
    		NewSection->PointerToRawData = rOffset;
    		NewSection->Misc.VirtualSize = vSize;
    		NewSection->SizeOfRawData = rSize;
    		NewSection->Characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE;
    
    		//修改IMAGE_NT_HEADERS,增加新节表
    		NtHeader->FileHeader.NumberOfSections++;
    		NtHeader->OptionalHeader.SizeOfImage += vSize;
    		NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
    		NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
    
    		//增加新节到文件尾部
    		DWORD dwWriteBytes;
    		SetFilePointer(FileHandle, 0, 0, FILE_END);
    		PBYTE pbNewSectionContent = new BYTE[rSize];
    		ZeroMemory(pbNewSectionContent, rSize);
    		bOk = WriteFile(FileHandle, pbNewSectionContent, rSize, &dwWriteBytes, NULL);
    		if (!bOk)
    		{
    			MessageBox(NULL, L"新增节失败", L"Error", MB_OK);
    			goto _EXIT_;
    		}
    
    	}
    	__except (EXCEPTION_EXECUTE_HANDLER)
    	{
    		printf("[-] AddImportTableItem  Exception!
    ");
    		return false;
    	}
    	printf("[!] AddNewSection Exit!
    ");
    	bOk = true;
    _EXIT_:
    
    	if (FileHandle)
    	{
    		CloseHandle(FileHandle);
    	}
    
    	if (lpMemoryModule)
    	{
    		UnmapViewOfFile(lpMemoryModule);
    	}
    
    	if (MappingHandle)
    	{
    		CloseHandle(MappingHandle);
    	}
    	return true;
    }
    //内存对齐
    DWORD PEAlign(DWORD dwTarNumber, DWORD dwAlignTo)
    {
    	return(((dwTarNumber + dwAlignTo - 1) / dwAlignTo)*dwAlignTo);
    }
    
    //增加一个导入表
    BOOL AddNewImportDescriptor(const WCHAR * wzPEFilePath, char * szInjectDllName, char *szImportFunctionName)
    {
    	BOOL bOk = FALSE;
    	LPVOID lpMemoryModule = NULL;
    	LPBYTE lpData = NULL;
    	DWORD  dwNewSecFileSize, dwNewSecMemSize;
    	HANDLE FileHandle = INVALID_HANDLE_VALUE, MappingHandle = INVALID_HANDLE_VALUE;
    	PIMAGE_NT_HEADERS NtHeader = NULL;
    	PIMAGE_IMPORT_DESCRIPTOR ImportTable = NULL;
    	PIMAGE_SECTION_HEADER    SectionHeader = NULL;
    	__try
    	{
    		//pe文件映射到内存
    		FileHandle = CreateFile(
    			wzPEFilePath,
    			GENERIC_READ | GENERIC_WRITE,
    			FILE_SHARE_READ | FILE_SHARE_WRITE,
    			NULL,
    			OPEN_EXISTING,
    			FILE_ATTRIBUTE_NORMAL,
    			NULL
    		);
    		if (INVALID_HANDLE_VALUE == FileHandle)
    		{
    			printf("[-] AddNewImportDescriptor CreateFile fail!
    ");
    			goto _EXIT_;
    		}
    
    		DWORD dwFileLength = GetFileSize(FileHandle, NULL);
    		MappingHandle = CreateFileMapping(FileHandle, NULL, PAGE_READWRITE/* | SEC_IMAGE*/, 0, dwFileLength,L"WINSUN_MAPPING_FILE");
    		if (NULL == MappingHandle)
    		{
    
    			printf("[-] AddNewImportDescriptor CreateFileMapping fail!
    ");
    			goto _EXIT_;
    
    		}
    
    		lpMemoryModule = MapViewOfFile(MappingHandle, FILE_MAP_ALL_ACCESS, 0, 0, dwFileLength);
    		if (NULL == lpMemoryModule)
    		{
    			printf("[-] AddNewImportDescriptor MapViewOfFile fail!
    ");
    			goto _EXIT_;
    		}
    
    		lpData = (LPBYTE)lpMemoryModule;
    		//判断是否是PE
    		if (((PIMAGE_DOS_HEADER)lpData)->e_magic != IMAGE_DOS_SIGNATURE)
    		{
    			printf("[-] AddNewImportDescriptor PE Header MZ error!
    ");
    			goto _EXIT_;
    		}
    
    		NtHeader = (PIMAGE_NT_HEADERS)(lpData + ((PIMAGE_DOS_HEADER)(lpData))->e_lfanew);
    		if (NtHeader->Signature != IMAGE_NT_SIGNATURE)
    		{
    			printf("[-] AddNewImportDescriptor PE Header PE error!
    ");
    			goto _EXIT_;
    		}
    		ImportTable = (PIMAGE_IMPORT_DESCRIPTOR)(lpData + RVAToOffset(NtHeader, NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress));
    		BOOL bBoundImport = FALSE;
    		if (ImportTable->Characteristics == 0 && ImportTable->FirstThunk != 0)
    		{
    			bBoundImport = TRUE;
    			NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].Size = 0;
    			NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT].VirtualAddress = 0;
    		}
    
    		SectionHeader = (PIMAGE_SECTION_HEADER)(NtHeader + 1) + NtHeader->FileHeader.NumberOfSections - 1;
    		PBYTE pbNewSection = SectionHeader->PointerToRawData + lpData;
    		int i = 0;
    		while (ImportTable->FirstThunk != 0)
    		{
    			memcpy(pbNewSection, ImportTable, sizeof(IMAGE_IMPORT_DESCRIPTOR));
    			ImportTable++;
    			pbNewSection += sizeof(IMAGE_IMPORT_DESCRIPTOR);
    			i++;
    		}
    		memcpy(pbNewSection, (pbNewSection - sizeof(IMAGE_IMPORT_DESCRIPTOR)), sizeof(IMAGE_IMPORT_DESCRIPTOR));
    
    
    
    		DWORD dwDelt = SectionHeader->VirtualAddress - SectionHeader->PointerToRawData;
    
    		//avoid import not need table
    		PIMAGE_THUNK_DATA pImgThunkData = (PIMAGE_THUNK_DATA)(pbNewSection + sizeof(IMAGE_IMPORT_DESCRIPTOR) * 2);
    
    
    
    		//import dll name
    		PBYTE pszDllNamePosition = (PBYTE)(pImgThunkData + 2);
    		memcpy(pszDllNamePosition, szInjectDllName, strlen(szInjectDllName));
    		pszDllNamePosition[strlen(szInjectDllName)] = 0;
    
    		//确定IMAGE_IMPORT_BY_NAM的位置
    		PIMAGE_IMPORT_BY_NAME pImgImportByName = (PIMAGE_IMPORT_BY_NAME)(pszDllNamePosition + strlen(szInjectDllName) + 1);
    
    
    		//init IMAGE_THUNK_DATA
    		pImgThunkData->u1.Ordinal = dwDelt + (DWORD)pImgImportByName - (DWORD)lpData;
    
    
    		//init IMAGE_IMPORT_BY_NAME
    		pImgImportByName->Hint = 1;
    		memcpy(pImgImportByName->Name, szImportFunctionName, strlen(szImportFunctionName)); //== dwDelt + (DWORD)pszFuncNamePosition - (DWORD)lpData ;
    		pImgImportByName->Name[strlen(szImportFunctionName)] = 0;
    		//init OriginalFirstThunk
    		if (bBoundImport)
    		{
    			((PIMAGE_IMPORT_DESCRIPTOR)pbNewSection)->OriginalFirstThunk = 0;
    		}
    		else
    			((PIMAGE_IMPORT_DESCRIPTOR)pbNewSection)->OriginalFirstThunk = dwDelt + (DWORD)pImgThunkData - (DWORD)lpData;
    		//init FirstThunk
    		((PIMAGE_IMPORT_DESCRIPTOR)pbNewSection)->FirstThunk = dwDelt + (DWORD)pImgThunkData - (DWORD)lpData;
    		//init Name
    		((PIMAGE_IMPORT_DESCRIPTOR)pbNewSection)->Name = dwDelt + (DWORD)pszDllNamePosition - (DWORD)lpData;
    
    		//改变导入表
    		NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = SectionHeader->VirtualAddress;
    		NtHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = (i + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
    
    
    	}
    	__except (EXCEPTION_EXECUTE_HANDLER)
    	{
    		printf("[-] AddNewImportDescriptor  Exception!
    ");
    		return false;
    	}
    
    _EXIT_:
    
    	if (FileHandle)
    	{
    		CloseHandle(FileHandle);
    	}
    
    	if (lpMemoryModule)
    	{
    		UnmapViewOfFile(lpMemoryModule);
    	}
    
    	if (MappingHandle)
    	{
    		CloseHandle(MappingHandle);
    	}
    	return true;
    }
    
    //
    // calulates the Offset from a RVA
    // Base    - base of the MMF
    // dwRVA - the RVA to calculate
    // returns 0 if an error occurred else the calculated Offset will be returned
    DWORD RVAToOffset(PIMAGE_NT_HEADERS pImageNTHeader, DWORD dwRVA)
    {
    	DWORD _offset;
    	PIMAGE_SECTION_HEADER section;
    	section = ImageRVAToSection(pImageNTHeader, dwRVA);//ImageRvaToSection(pimage_nt_headers,Base,dwRVA);
    	if (section == NULL)
    	{
    		return(0);
    	}
    	_offset = dwRVA + section->PointerToRawData - section->VirtualAddress;
    	return(_offset);
    }
    
    PIMAGE_SECTION_HEADER ImageRVAToSection(PIMAGE_NT_HEADERS pImageNTHeader, DWORD dwRVA)
    {
    	int i;
    	PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)(pImageNTHeader + 1);
    	for (i = 0; i<pImageNTHeader->FileHeader.NumberOfSections; i++)
    	{
    		if ((dwRVA >= (pSectionHeader + i)->VirtualAddress) && (dwRVA <= ((pSectionHeader + i)->VirtualAddress + (pSectionHeader + i)->SizeOfRawData)))
    		{
    			return ((PIMAGE_SECTION_HEADER)(pSectionHeader + i));
    		}
    	}
    	return(NULL);
    }



  • 相关阅读:
    struct resbuf 结构就象LISP里面的表(
    CString互转int
    C++中std::sort/std::stable_sort/std::partial_sort的区别及使用
    *ARX对数据的类型和单位进行转换
    c++常见容器操作
    C++中const关键字的使用方法,烦透了一遍一遍的搜,总结一下,加深印象!!!
    ARX 简单程序(不错的例子)
    ARX对象的一些文字说明
    CAD ObjectARX扩展工具的源码(一)
    CAD ObjectARX扩展工具的源码(三)
  • 原文地址:https://www.cnblogs.com/Toring/p/6628280.html
Copyright © 2011-2022 走看看