当前位置:   article > 正文

win10 x64实现内存注入DLL

内存注入

环境

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

注入代码

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <windows.h>
/*
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;
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437

DLL代码

#define _CRT_SECURE_NO_WARNINGS
#include "pch.h"
#include <iostream>
#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;
            }
        }

    }

}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210

测试结果如下

在这里插入图片描述

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

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号