win10 x64实现内存注入DLL

x64实现内存注入DLL

  • 环境
  • 注入代码
  • DLL代码
  • 测试结果如下

环境

1:win10最新版本
2:vs2019 dll配置环境
一:属性–链接器–常规–启用增量链接:否
二:属性–链接器–高级–随机地址:否 固定基址:是
三:属性–c/c+±-代码生成–基本运行时检查:默认值 安全检查:禁用安全检查(G/S)

注入代码

#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
/*
kd > dt _PEB_LDR_DATA
nt!_PEB_LDR_DATA
+ 0x000 Length           : Uint4B
+ 0x004 Initialized : UChar
+ 0x008 SsHandle : Ptr64 Void
+ 0x010 InLoadOrderModuleList : _LIST_ENTRY
+ 0x020 InMemoryOrderModuleList : _LIST_ENTRY
+ 0x030 InInitializationOrderModuleList : _LIST_ENTRY
+ 0x040 EntryInProgress : Ptr64 Void
+ 0x048 ShutdownInProgress : UChar
+ 0x050 ShutdownThreadId : Ptr64 Void
*/

/*
 dt _LDR_DATA_TABLE_ENTRY
nt!_LDR_DATA_TABLE_ENTRY
   +0x000 InLoadOrderLinks : _LIST_ENTRY
   +0x010 InMemoryOrderLinks : _LIST_ENTRY
   +0x020 InInitializationOrderLinks : _LIST_ENTRY
   +0x030 DllBase          : Ptr64 Void
   +0x038 EntryPoint       : Ptr64 Void
   +0x040 SizeOfImage      : Uint4B
   +0x048 FullDllName      : _UNICODE_STRING
   +0x058 BaseDllName      : _UNICODE_STRING
   +0x068 FlagGroup        : [4] UChar
   +0x068 Flags            : Uint4B
   +0x068 PackagedBinary   : Pos 0, 1 Bit
   +0x068 MarkedForRemoval : Pos 1, 1 Bit
   +0x068 ImageDll         : Pos 2, 1 Bit
   +0x068 LoadNotificationsSent : Pos 3, 1 Bit
   +0x068 TelemetryEntryProcessed : Pos 4, 1 Bit
   +0x068 ProcessStaticImport : Pos 5, 1 Bit
   +0x068 InLegacyLists    : Pos 6, 1 Bit
   +0x068 InIndexes        : Pos 7, 1 Bit
   +0x068 ShimDll          : Pos 8, 1 Bit
   +0x068 InExceptionTable : Pos 9, 1 Bit
   +0x068 ReservedFlags1   : Pos 10, 2 Bits
   +0x068 LoadInProgress   : Pos 12, 1 Bit
   +0x068 LoadConfigProcessed : Pos 13, 1 Bit
   +0x068 EntryProcessed   : Pos 14, 1 Bit
   +0x068 ProtectDelayLoad : Pos 15, 1 Bit
   +0x068 ReservedFlags3   : Pos 16, 2 Bits
   +0x068 DontCallForThreads : Pos 18, 1 Bit
   +0x068 ProcessAttachCalled : Pos 19, 1 Bit
   +0x068 ProcessAttachFailed : Pos 20, 1 Bit
   +0x068 CorDeferredValidate : Pos 21, 1 Bit
   +0x068 CorImage         : Pos 22, 1 Bit
   +0x068 DontRelocate     : Pos 23, 1 Bit
   +0x068 CorILOnly        : Pos 24, 1 Bit
   +0x068 ChpeImage        : Pos 25, 1 Bit
   +0x068 ReservedFlags5   : Pos 26, 2 Bits
   +0x068 Redirected       : Pos 28, 1 Bit
   +0x068 ReservedFlags6   : Pos 29, 2 Bits
   +0x068 CompatDatabaseProcessed : Pos 31, 1 Bit
   +0x06c ObsoleteLoadCount : Uint2B
   +0x06e TlsIndex         : Uint2B
   +0x070 HashLinks        : _LIST_ENTRY
   +0x080 TimeDateStamp    : Uint4B
   +0x088 EntryPointActivationContext : Ptr64 _ACTIVATION_CONTEXT
   +0x090 Lock             : Ptr64 Void
   +0x098 DdagNode         : Ptr64 _LDR_DDAG_NODE
   +0x0a0 NodeModuleLink   : _LIST_ENTRY
   +0x0b0 LoadContext      : Ptr64 _LDRP_LOAD_CONTEXT
   +0x0b8 ParentDllBase    : Ptr64 Void
   +0x0c0 SwitchBackContext : Ptr64 Void
   +0x0c8 BaseAddressIndexNode : _RTL_BALANCED_NODE
   +0x0e0 MappingInfoIndexNode : _RTL_BALANCED_NODE
   +0x0f8 OriginalBase     : Uint8B
   +0x100 LoadTime         : _LARGE_INTEGER
   +0x108 BaseNameHashValue : Uint4B
   +0x10c LoadReason       : _LDR_DLL_LOAD_REASON
   +0x110 ImplicitPathOptions : Uint4B
   +0x114 ReferenceCount   : Uint4B
   +0x118 DependentLoadFlags : Uint4B
   +0x11c SigningLevel     : UChar
*/

BOOL EnableDebugPrivilege();
DWORD FileBufferToImageBuffer(char* pFileBuffer, LPVOID* pImageBuffer);
DWORD ReadPEFile(LPWSTR const lpszFile);
DWORD GetFileSize(const char* FileName);
DWORD ReportIatp(LPVOID* ImageBase);
//内存dll注入
char* FileAddress;
DWORD ReLocaTion(LPVOID* ImageBase, LONGLONG ReImageBase);



int main()
{
	EnableDebugPrivilege();
	//1:打开需要注入进程的hProcess
	HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 2732);
	if (NULL == hProcess)
	{
		printf("句柄无效\n");
		return FALSE;
	}
	//2:获取dll路径 并打开  获取dll的拉升后内存大小  申请内存空间
	//DWORD Size = ReadPEFile((LPWSTR)L"C:\\Users\\mirsun\\Desktop\\chuanqi.dll");F:\\360MoveData\\Users\\Administrator\\Desktop\\chuanqi.dll
	DWORD Size = GetFileSize("C:\\Users\\mirsun\\Desktop\\chuanqi.dll");
	//3:拉升dll  为内存状态
	LPVOID PpImageBase;
	DWORD ImageSize = FileBufferToImageBuffer(FileAddress,&PpImageBase);
	delete[] FileAddress;

	//4:获取dll大小 申请注入进程的镜像空间
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)PpImageBase;
	PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((char*)PpImageBase + pDosHeader->e_lfanew);
	LPVOID pImageBase = VirtualAllocEx(hProcess, NULL, pNtHeader->OptionalHeader.SizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
	if (pImageBase == NULL)
	{
		printf("VirtualAllocEx 错误码: 0x%X\n", GetLastError()); // 0x1e7 试图访问无效地址
		return -1;
	}
	//5 修复IAT表  当dll注入后第一件事情就是修复IAT

	//6修复重定位表  如果没有全局变量就不用修复  好像我的dll就没有要修复
	ReLocaTion(&PpImageBase, pNtHeader->OptionalHeader.ImageBase);
	
	//7 文件拉升过的imageFile 写入申请的进程镜像空间中
	if (0 == WriteProcessMemory(hProcess, (LPVOID)pImageBase, PpImageBase, ImageSize, NULL))
	{
		printf("写入源程序内存镜像失败\n");
		TerminateThread(hProcess, 0);
		getchar();
		return -1;
	}
	//8 创建远程线程,执行入口代码  线程入口该dll的:函数地址 - imageBase=该函数的偏移 +新申请的ImageBase
	long long dwProcOffset = (LONGLONG)pImageBase + 0x0000000180001C80 - pNtHeader->OptionalHeader.ImageBase;
	CreateRemoteThread(hProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)dwProcOffset, pImageBase, NULL, NULL);
	::CloseHandle(hProcess);
	::free(PpImageBase);
	std::cout << "chenggong1111" << std::endl;
	system("pause");

	return 0;

}

BOOL EnableDebugPrivilege()
{

    HANDLE TokenHandle = NULL;
    TOKEN_PRIVILEGES TokenPrivilege;
    LUID uID;

    //打开权限令牌
    if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &TokenHandle))
    {
        return FALSE;
    }

    if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &uID))
    {

        CloseHandle(TokenHandle);
        TokenHandle = INVALID_HANDLE_VALUE;
        return FALSE;
    }

    TokenPrivilege.PrivilegeCount = 1;
    TokenPrivilege.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    TokenPrivilege.Privileges[0].Luid = uID;

    //在这里我们进行调整权限
    if (!AdjustTokenPrivileges(TokenHandle, FALSE, &TokenPrivilege, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
    {
        CloseHandle(TokenHandle);
        TokenHandle = INVALID_HANDLE_VALUE;
        return  FALSE;
    }

    CloseHandle(TokenHandle);
    TokenHandle = INVALID_HANDLE_VALUE;
    return TRUE;
}

DWORD FileBufferToImageBuffer(char* pFileBuffer, LPVOID* pImageBuffer)
{
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pFileBuffer;
	PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((char*)pDosHeader + pDosHeader->e_lfanew);
	PIMAGE_FILE_HEADER pPEHeader = (PIMAGE_FILE_HEADER)((char*)pDosHeader + pDosHeader->e_lfanew + 4);
	PIMAGE_OPTIONAL_HEADER pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((char*)pPEHeader + sizeof(IMAGE_FILE_HEADER));
	PIMAGE_SECTION_HEADER pSectionHeader = (PIMAGE_SECTION_HEADER)((char*)pOptionHeader + pPEHeader->SizeOfOptionalHeader);

	std::cout << pOptionHeader->SizeOfImage << std::endl;
	
	*pImageBuffer = malloc(pOptionHeader->SizeOfImage);


	if (*pImageBuffer == NULL)
	{
		printf("分配内存失败\n");
		getchar();
		system("pause");
		return 0;
	}
	memset(*pImageBuffer, 0, pOptionHeader->SizeOfImage);
	// 复制DOS头+PE头+可选PE头+节表+文件对齐
	memcpy(*pImageBuffer, pFileBuffer, pOptionHeader->SizeOfHeaders);
	std::cout <<"*pImageBuffer:" << *pImageBuffer << std::endl;
	// 遍历节表,复制所有节	
	for (int i = 0; i < pPEHeader->NumberOfSections; i++)
	{
		memcpy((LPVOID)((char*)(*pImageBuffer) + pSectionHeader[i].VirtualAddress),
			(LPVOID)(pFileBuffer + pSectionHeader[i].PointerToRawData),
			pSectionHeader[i].SizeOfRawData);
	}
	return pOptionHeader->SizeOfImage;
}


DWORD ReadPEFile(LPWSTR const lpszFile)
{
	FILE* file = _wfopen(lpszFile, L"r+b");
	if (file == NULL)
		return 0;
	int flength;
	fseek(file, 0, SEEK_END);
	flength = ftell(file);
	fseek(file, 0, SEEK_SET);
	FileAddress = new char[flength];
	if (FileAddress == NULL)
		return 0;
	fread(FileAddress, 1, flength, file);
	fclose(file);
	return flength;
}
DWORD GetFileSize(const char* FileName)
{
	FILE* pFileHandle;
	fopen_s(&pFileHandle, FileName, "rb");
	if (pFileHandle == NULL)
	{
		std::cout << "获取文件句柄失败" << std::endl;
		return 0;
	}

	if (fseek(pFileHandle, 0, SEEK_END) != 0)
	{
		std::cout << "移动文件指针到末尾失败" << std::endl;
		fclose(pFileHandle);
		return 0;
	}
	//获取到了大小
	DWORD dwsize = ftell(pFileHandle);
	std::cout << "获取文件成功,文件大小为:" << std::hex << dwsize << std::endl;


	FileAddress = new char[dwsize];

	if (FileAddress == 0)
	{
		std::cout << "申请内存失败" << std::endl;
		fclose(pFileHandle);
		return 0;
	}

	memset(FileAddress, 0, dwsize);//初始化数据都为 0
	// 恢复指针指向起始位置
	if (fseek(pFileHandle, 0, SEEK_SET) != 0)
	{
		std::cout << "设置数据失败2" << std::endl;
		fclose(pFileHandle);
		return FALSE;
	}
	//把文件数据读到 内存空间中
	std::cout << "正常释放资源" << std::endl;
	fread(FileAddress, dwsize, 1, pFileHandle);
	fclose(pFileHandle);
	pFileHandle = NULL;

	return dwsize;
}



DWORD ReportIatp(LPVOID* ImageBase)
{
	PIMAGE_DOS_HEADER pDosHeader = NULL;
	PIMAGE_NT_HEADERS pNTHeader = NULL;
	PIMAGE_FILE_HEADER pPEHeader = NULL;
	PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
	PIMAGE_SECTION_HEADER pSectionHeader = NULL;
	PIMAGE_IMPORT_DESCRIPTOR pIMPORT_DESCRIPTOR = NULL;
	PIMAGE_IMPORT_BY_NAME pImage_IMPORT_BY_NAME = NULL;

	PLONGLONG OriginalFirstThunk = NULL;
	PLONGLONG FirstThunk = NULL;

	PIMAGE_THUNK_DATA pImageThunkData = NULL;

	DWORD Original = 0;

	pDosHeader = (PIMAGE_DOS_HEADER)*ImageBase;
	pNTHeader = (PIMAGE_NT_HEADERS)((char*)*ImageBase + pDosHeader->e_lfanew);
	pPEHeader = (PIMAGE_FILE_HEADER)((char*)pNTHeader + 4);
	pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((char*)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);

	//导入表相关信息占20个字节
	pIMPORT_DESCRIPTOR = (PIMAGE_IMPORT_DESCRIPTOR)((char*)*ImageBase + pOptionHeader->DataDirectory[1].VirtualAddress);

	LONGLONG dwFuncAddr = 0;
	HMODULE hModule;
	TCHAR Buffer[80] = { 0 };
	while (pIMPORT_DESCRIPTOR->FirstThunk && pIMPORT_DESCRIPTOR->OriginalFirstThunk)
	{
		const char* pModuleAddr = (const char*)((char*)*ImageBase + pIMPORT_DESCRIPTOR->Name);
		mbstowcs(Buffer, pModuleAddr, 80);
		hModule = LoadLibrary(Buffer);
		if (hModule == NULL)
		{
			return 0;
		}

		// FirstThunk 指向 IMAGE_THUNK_DATA 结构数组
		
		FirstThunk = (PLONGLONG)((char*)*ImageBase + pIMPORT_DESCRIPTOR->FirstThunk);

		while (*FirstThunk)
		{
		
			printf("*FirstThunk:%I64d\n", *FirstThunk);
		
			FirstThunk++;
		}

		pIMPORT_DESCRIPTOR++;
	}
	return TRUE;
}


void FixRelocation(IN LPVOID Buffer, IN DWORD FixImageBase)
{

	PIMAGE_DOS_HEADER pDos = (PIMAGE_DOS_HEADER)Buffer;

	PIMAGE_FILE_HEADER pFile = (PIMAGE_FILE_HEADER)((DWORD)pDos + pDos->e_lfanew + 4);
	PIMAGE_OPTIONAL_HEADER32 pOptionalFile = (PIMAGE_OPTIONAL_HEADER32)((DWORD)pFile + IMAGE_SIZEOF_FILE_HEADER);

	PIMAGE_BASE_RELOCATION pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)Buffer + pOptionalFile->DataDirectory[5].VirtualAddress);
	//保存原本值 更改ImageBase
	DWORD Imagebase = pOptionalFile->ImageBase;
	pOptionalFile->ImageBase = FixImageBase;

	//修复重定位表
	PWORD pDataAddr = (PWORD)((DWORD)pRelocation + 8);
	DWORD Block = pRelocation->SizeOfBlock;
	DWORD VitualAddr = pRelocation->VirtualAddress;

	PDWORD Replace = NULL;
	DWORD Rva = 0;
	while (Block != 0 && VitualAddr != 0)
	{
		for (DWORD i = 0; i < (Block - 8) / 2; i++)
		{
			// 高四位值为3 代表的是需要修改的数据 
			if ((*(pDataAddr + i) & 0xF000) == 0x3000)
			{
				Rva = (*(pDataAddr + i) & 0x0FFF) + VitualAddr;
				Replace = (PDWORD)((DWORD)Buffer + Rva);
				*Replace = *Replace - Imagebase + FixImageBase;
			}

		}
		pRelocation = (PIMAGE_BASE_RELOCATION)((DWORD)pRelocation + Block);
		Block = pRelocation->SizeOfBlock;
		VitualAddr = pRelocation->VirtualAddress;
		pDataAddr = (PWORD)((DWORD)pRelocation + 8);
	}
}

DWORD ReLocaTion(LPVOID* ImageBase,LONGLONG ReImageBase)
{
	DWORD AddressVir;
	PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)*ImageBase;
	PIMAGE_NT_HEADERS pNTHeader = (PIMAGE_NT_HEADERS)((char*)*ImageBase + pDosHeader->e_lfanew);
	PIMAGE_FILE_HEADER pPEHeader = (PIMAGE_FILE_HEADER)((char*)pNTHeader + 4);
	PIMAGE_OPTIONAL_HEADER pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((char*)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);
	IMAGE_DATA_DIRECTORY DataDir = (IMAGE_DATA_DIRECTORY)(pOptionHeader->DataDirectory[5]);


	//保存原本值 更改ImageBase
	DWORD Imagebase = pOptionHeader->ImageBase;
	pOptionHeader->ImageBase = ReImageBase;

	std::cout << DataDir.Size << std::endl;
	std::cout << DataDir.VirtualAddress << std::endl;
	if (!DataDir.Size && !DataDir.VirtualAddress)
	{
		std::cout << "没有需要重定位的项目" << std::endl;
		return FALSE;
	}
	getchar();

	//保存原本值 更改ImageBase
	//LONGLONG Imagebase = pOptionalFile->ImageBase;
	//pOptionalFile->ImageBase = ReImageBase;
	
	//修复重定位表
	LONGLONG FristAddress = (LONGLONG)((CHAR*)*ImageBase + DataDir.VirtualAddress);
	PIMAGE_BASE_RELOCATION ReLocaTion = PIMAGE_BASE_RELOCATION(FristAddress);
	PLONGLONG Replace = NULL;
	while (ReLocaTion->VirtualAddress != 0 && ReLocaTion->SizeOfBlock != 0)
	{
		WORD* items = (WORD*)(FristAddress + 8);//去掉头部8个字节 就是每一项的值
		int Number2 = (ReLocaTion->SizeOfBlock - 8) / 2;
		printf("VirtualAddress地址:%x \n", ReLocaTion->VirtualAddress);
		printf("SizeOfBlock地址:%x \n", ReLocaTion->SizeOfBlock);
		getchar();
		for (int i = 0; i < Number2; i++)
		{
			std::cout << items[i] << std::endl;
			if (items[i] & 0xF000 == 0x3000)  //有效数据
			{
				AddressVir = (ReLocaTion->VirtualAddress + (items[i] & 0xFFF)); //VirtualAddress + 偏移 只取低12位   高4位是用来判断的
				//std::cout << items[i] << std::endl;
				printf("需要修改重定位RVA地址值:%x \n", AddressVir);
				Replace = (PLONGLONG)((CHAR*)*ImageBase + AddressVir);
				*Replace = ReImageBase + *Replace - (LONGLONG)*ImageBase;
			}
		}

		FristAddress = FristAddress + ReLocaTion->SizeOfBlock;//每次都是加上size 得到下一个块的地址
		ReLocaTion = PIMAGE_BASE_RELOCATION(FristAddress);

	}
	std::cout << "重定位的w完成" << std::endl;
	return TRUE;
}

DLL代码

#define _CRT_SECURE_NO_WARNINGS
#include "pch.h"
#include 
#include "windows.h"
extern "C" LONGLONG __stdcall FindKer();
typedef HMODULE(WINAPI* MyLoadlibary)(LPCWSTR);
typedef FARPROC(WINAPI* MyGetProc)(HMODULE, LPCSTR);
typedef size_t(WINAPI* Mymbstowcs)(wchar_t*, const char* src, std::size_t len);
VOID FindFunAdress(LONGLONG** GetPro, LONGLONG** Loadlib);
BOOL ReportIat(LPVOID* ImageBase);
//线程rukou 0000000180001C80
void DbgPrint(const char* format, ...)
{
    char buf[4096], * p = buf;
    va_list args;
    va_start(args, format);
    p += _vsnprintf(p, sizeof buf - 1, format, args);
    va_end(args);
    OutputDebugStringA(buf);
}
HANDLE hThread;

DWORD WINAPI ThreadProc(LPVOID ImageBasee)
{

    LPVOID ImageBase = ImageBasee;

   BOOL TorF =  ReportIat(&ImageBase);//修复IAT表
   if (!TorF)
   {
       return 0;
   };
   
    //00000001800010A0  新的入口地址 0000000180001C80
    char zifu[] = "jinrule";
    for (;;)
    {
        Sleep(6000);
        std::cout<< zifu<<std::endl;
    }
  
    return TRUE;
}

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:

        //MessageBoxW(0,L"加载dll", L"加载dll",0);
        // 启动一个线程
        //DWORD dwThread;
      hThread = ::CreateThread(NULL , NULL, ThreadProc, NULL, 0,0);

        break;
    }
    return TRUE;
}

BOOL ReportIat(LPVOID* ImageBase)
{
    HMODULE hModule;
    //mbstowcs ---00007FF98195FFF0
    LONGLONG* GetPro = 0;
    LONGLONG* Loadlib = 0;
    FindFunAdress(&GetPro,&Loadlib);

    MyGetProc  MyGetProcAddr = (MyGetProc)GetPro;
    MyLoadlibary  MyLoadlib = (MyLoadlibary)Loadlib;
    //获取mbstowcs地址
    TCHAR Hntdll[] = { 'n','t','d','l','l',0 };
    char Nmbstowcs[] = { 'm','b','s','t','o','w','c','s',0 };
    hModule = MyLoadlib(Hntdll);
    Mymbstowcs wMymbstowcs = (Mymbstowcs)MyGetProcAddr(hModule, Nmbstowcs);

    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pPEHeader = NULL;
    PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    PIMAGE_IMPORT_DESCRIPTOR pIMPORT_DESCRIPTOR = NULL;
    PIMAGE_IMPORT_BY_NAME pImage_IMPORT_BY_NAME = NULL;

    PLONGLONG OriginalFirstThunk = NULL;
    PLONGLONG FirstThunk = NULL;

    PIMAGE_THUNK_DATA pImageThunkData = NULL;

    DWORD Original = 0;

    pDosHeader = (PIMAGE_DOS_HEADER)*ImageBase;
    pNTHeader = (PIMAGE_NT_HEADERS)((char*)*ImageBase + pDosHeader->e_lfanew);
    pPEHeader = (PIMAGE_FILE_HEADER)((char*)pNTHeader + 4);
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((char*)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);

    //导入表相关信息占20个字节
    pIMPORT_DESCRIPTOR = (PIMAGE_IMPORT_DESCRIPTOR)((char*)*ImageBase + pOptionHeader->DataDirectory[1].VirtualAddress);

    LONGLONG dwFuncAddr = 0;
   
    TCHAR Buffer[100] = { 0 };
    while (pIMPORT_DESCRIPTOR->FirstThunk && pIMPORT_DESCRIPTOR->OriginalFirstThunk)
    {
        //char* pModuleAddr = (char*)((char*)*ImageBase + pIMPORT_DESCRIPTOR->Name);
        wMymbstowcs(Buffer, (char*)*ImageBase + pIMPORT_DESCRIPTOR->Name, 0x50);
        hModule = MyLoadlib(Buffer);
        if (hModule == NULL)
        {
            return FALSE;
        }

        // FirstThunk 指向 IMAGE_THUNK_DATA 结构数组
        OriginalFirstThunk = (PLONGLONG)((char*)*ImageBase + pIMPORT_DESCRIPTOR->OriginalFirstThunk);
        FirstThunk = (PLONGLONG)((char*)*ImageBase + pIMPORT_DESCRIPTOR->FirstThunk);

        while (*OriginalFirstThunk)
        {
            if (*OriginalFirstThunk >> 63 != 0)
            {
                //高位为1 则 除去最高位的值就是函数的导出序号

                //去除最高标志位
                Original = *OriginalFirstThunk & 0xffff;
                dwFuncAddr = (LONGLONG)MyGetProcAddr(hModule, (PCHAR)Original);
            }
            else
            {
                //高位不为1 则指向IMAGE_IMPORT_BY_NAME;
                pImage_IMPORT_BY_NAME = (PIMAGE_IMPORT_BY_NAME)((CHAR*)*ImageBase + *OriginalFirstThunk);
                dwFuncAddr = (LONGLONG)MyGetProcAddr(hModule, (PCHAR)pImage_IMPORT_BY_NAME->Name);
            }
            *FirstThunk = dwFuncAddr;
            OriginalFirstThunk++;
            FirstThunk++;
        }

        pIMPORT_DESCRIPTOR++;
    }
    return TRUE;
}

VOID FindFunAdress(LONGLONG** GetPro,LONGLONG** Loadlib)
{
//FindKer(); 取Kerner32模块地址,一般在peb的第二个
    LONGLONG* HandKerner = (LONGLONG*)FindKer();
    //2:取函数api地址Loadlibraryw  GetProcAddress
    char LoadName[] = { 'L','o','a', 'd','L','i','b','r','a','r','y', 'W',0 };
    char GetProName[] = { 'G','e','t', 'P','r','o','c','A','d','d','r', 'e','s','s',0 };

    PIMAGE_DOS_HEADER pDosHeader = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PIMAGE_FILE_HEADER pPEHeader = NULL;
    PIMAGE_OPTIONAL_HEADER pOptionHeader = NULL;
    PIMAGE_SECTION_HEADER pSectionHeader = NULL;
    PIMAGE_IMPORT_DESCRIPTOR pIMPORT_DESCRIPTOR = NULL;
    pDosHeader = (PIMAGE_DOS_HEADER)HandKerner;
    pNTHeader = (PIMAGE_NT_HEADERS)((char*)HandKerner + pDosHeader->e_lfanew);
    pPEHeader = (PIMAGE_FILE_HEADER)((char*)pNTHeader + 4);
    pOptionHeader = (PIMAGE_OPTIONAL_HEADER)((char*)pPEHeader + IMAGE_SIZEOF_FILE_HEADER);

    //导出表相关信息
    PIMAGE_EXPORT_DIRECTORY m_Export = (PIMAGE_EXPORT_DIRECTORY)((char*)HandKerner + pOptionHeader->DataDirectory[0].VirtualAddress);
    DWORD* PAddressOfNames = (DWORD*)((char*)HandKerner + m_Export->AddressOfNames);
    WORD* PAddressOfNamesOrdinals = (WORD*)((char*)HandKerner + m_Export->AddressOfNameOrdinals);//指向函数名称序列号
    DWORD* PAddressOfFunctions = (DWORD*)((char*)HandKerner + m_Export->AddressOfFunctions);//导出地址表RVA(是一个偏移)。
    DWORD cx = 0;
    //找出Loadlibrary 和GetProAddress
    for (DWORD i = 0; i < m_Export->NumberOfFunctions; i++)
    {
        char* LoadNamePtr = NULL;
        char* MyFuntionName = (char*)HandKerner + *(PAddressOfNames + i);
        char* FuntionName = MyFuntionName;
        if (cx == 0)
        {
            LoadNamePtr = GetProName;//不能写在for外面,因为判断第一个字符相等就会移动一格,要复原
        }
        else
        {
            LoadNamePtr = LoadName;
        }
        while (*LoadNamePtr && *FuntionName == *LoadNamePtr)
            LoadNamePtr++, FuntionName++;
        if (*FuntionName == *LoadNamePtr)
        {
            cx++;
            //1 i 为(AddressOfNames)函数名的序列号 
            //2 AddressOfNameOrdinals--->i 取里面的值为函数地址的索引号 
            DWORD TMP = *(PAddressOfNamesOrdinals + i);
            //3 AddressOfFunctions--->取索引号里面的值为函数的rva偏移地址
            //4  kernel32.dll 首地址加上函数RVA地址 为函数地址
            //std::cout << MyFuntionName << std::endl;
            //LONGLONG* GetPro, LONGLONG* Loadlib
            if (cx == 1)
            {
                *GetPro = (LONGLONG*)((char*)HandKerner + (DWORD) * (PAddressOfFunctions + TMP));
            }
            else
            {
                *Loadlib = (LONGLONG*)((char*)HandKerner + (DWORD) * (PAddressOfFunctions + TMP));
                break;
            }
        }

    }

}

测试结果如下

win10 x64实现内存注入DLL_第1张图片

注入成功后会创建一个线程打印:jinrule字符串
不懂可以私信我或在评论区留言,(手留余香)对您有用请随手点赞。

你可能感兴趣的:(c++,java,microsoft)