环境
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;
}
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;
}
}
}
}
测试结果如下
文章来源:https://www.toymoban.com/news/detail-532194.html
注入成功后会创建一个线程打印:jinrule字符串
不懂可以私信我或在评论区留言,(手留余香)对您有用请随手点赞。文章来源地址https://www.toymoban.com/news/detail-532194.html
到了这里,关于win10 x64实现内存注入DLL的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!