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);
    }



  • 相关阅读:
    ORACLE 查看进程数,已执行任务数, 剩余任务数,删除指定任务
    ORACLE 收集统计整个用户数据
    解决Hystrix dashboard Turbine 一直 Loading…… 及其他坑
    利用 Maven 构造 Spring Cloud 微服务架构 模块使用 spring Boot构建
    AES加解密
    JAVA POI XSSFWorkbook导出扩展名为xlsx的Excel,附带weblogic 项目导出Excel文件错误的解决方案
    JAVA 文件的上传下载
    shell启停服务脚本模板
    JAVA 设计模式之 原型模式详解
    JAVA 设计模式之 工厂模式详解
  • 原文地址:https://www.cnblogs.com/Toring/p/6628280.html
Copyright © 2011-2022 走看看