// InjectDlg.cpp : 实现文件 // #include "stdafx.h" #include "HandleMemory.h" #include "InjectDlg.h" #include "afxdialogex.h" // CInjectDlg 对话框 IMPLEMENT_DYNAMIC(CInjectDlg, CDialogEx) CInjectDlg::CInjectDlg(CWnd* pParent /*=NULL*/) : CDialogEx(CInjectDlg::IDD, pParent) , m_strProcess(_T("")) , m_strDll(_T("")) { m_dwID = 0; ::lstrcpy(m_szDllPath,""); } CInjectDlg::~CInjectDlg() { } void CInjectDlg::DoDataExchange(CDataExchange* pDX) { CDialogEx::DoDataExchange(pDX); DDX_Text(pDX, IDC_EDIT_PROCESS, m_strProcess); DDX_Text(pDX, IDC_EDIT_DLL, m_strDll); } BEGIN_MESSAGE_MAP(CInjectDlg, CDialogEx) ON_BN_CLICKED(IDC_BUTTON_PROCESS, &CInjectDlg::OnBnClickedButtonProcess) ON_BN_CLICKED(IDC_BUTTON_DLL, &CInjectDlg::OnBnClickedButtonDll) ON_BN_CLICKED(IDC_BUTTON_INJECT, &CInjectDlg::OnBnClickedButtonInject) END_MESSAGE_MAP() // CInjectDlg 消息处理程序 void CInjectDlg::OnBnClickedButtonProcess() { // TODO: 在此添加控件通知处理程序代码 CChooseProcessDlg dlg; DWORD dwID = 0; char szProcessName[MAX_PATH] = {0}; if(IDOK == dlg.DoModal()) { dwID = dlg.GetProcessID(); ::lstrcat(szProcessName, dlg.GetProcessName()); } m_dwID = dwID; m_strProcess.Format("pid:%d exe file:%s", dwID, szProcessName); UpdateData(FALSE); } void CInjectDlg::OnBnClickedButtonDll() { // TODO: 在此添加控件通知处理程序代码 OPENFILENAME stOF; ::RtlZeroMemory(&stOF, sizeof(stOF)); char szFilter[MAX_PATH] = "dll files(*.dll)\0*.dll\0all files(*.*)\0*.*\0\0"; char szFileName[MAX_PATH] = {0}; stOF.lStructSize = sizeof(stOF); stOF.hwndOwner = m_hWnd; stOF.lpstrFilter = szFilter; stOF.lpstrFile = szFileName; stOF.nMaxFile = MAX_PATH; stOF.Flags = OFN_PATHMUSTEXIST; ::GetOpenFileName(&stOF); m_strDll = szFileName; ::lstrcpy(m_szDllPath, szFileName); UpdateData(FALSE); } void CInjectDlg::OnBnClickedButtonInject() { // TODO: 在此添加控件通知处理程序代码 if(0 >= m_dwID) { ::MessageBox(m_hWnd, "Please Choose A Process!", "Warn", MB_OK | MB_ICONWARNING); return ; } if(0 >= ::lstrlen(m_szDllPath)) { ::MessageBox(m_hWnd, "Please Choose A Dll!", "Warn", MB_OK | MB_ICONWARNING); return ; } BOOL bRet = RemoteProcessInject(m_dwID, m_szDllPath); char szMsg[MAX_PATH] = {0}; if(bRet) { ::wsprintf(szMsg, "Inject dll:%s \nto process pid:%d\nDONE!!!",m_szDllPath, m_dwID); ::MessageBox(m_hWnd, szMsg, "DONE", MB_OK | MB_ICONWARNING); } else { ::wsprintf(szMsg, "Inject dll:%s \nto process pid:%d\nFAIL!!!",m_szDllPath, m_dwID); ::MessageBox(m_hWnd, szMsg, "FAIL", MB_OK | MB_ICONWARNING); } } BOOL CInjectDlg::RemoteProcessInject(DWORD dwID, char *lpszDllPath) { // 打开要注入DLL的进程 HANDLE hProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwID); if(NULL == hProcess) { char szErr[MAX_PATH] = {0}; ::wsprintf(szErr, "Open Process Error!\nError Code:%d\n", ::GetLastError()); ::MessageBox(m_hWnd, szErr, "Error", MB_OK | MB_ICONWARNING); return FALSE; } // 判断是32位还是64位 BOOL b32 = FALSE; ::IsWow64Process(hProcess, &b32); // 判断DLL是32位还是64位 BOOL bDll32 = JudgePE32Or64(lpszDllPath); if(b32) { if(!bDll32) { ::MessageBox(m_hWnd, "Process Is 32bits, Dll Is 64bits!\nPlease Choose 32bits Dll to Inject!\n", "Warn", MB_OK | MB_ICONWARNING); return FALSE; } } else { if(bDll32) { ::MessageBox(m_hWnd, "Process Is 64bits, Dll Is 32bits!\nPlease Choose 64bits Dll to Inject!\n", "Warn", MB_OK | MB_ICONWARNING); return FALSE; } } // 申请一块内存 DWORD dwSize = 1 + ::lstrlen(lpszDllPath); LPVOID lpAddr = ::VirtualAllocEx(hProcess, 0, dwSize, MEM_COMMIT, PAGE_READWRITE); if(NULL == lpAddr) { char szErr[MAX_PATH] = {0}; ::wsprintf(szErr, "Alloc Virtual Memory Error!\nError Code:%d\n", ::GetLastError()); ::MessageBox(m_hWnd, szErr, "Error", MB_OK | MB_ICONWARNING); return FALSE; } // 写入内存 if(!::WriteProcessMemory(hProcess, lpAddr, (LPCVOID)lpszDllPath, dwSize, NULL)) { char szErr[MAX_PATH] = {0}; ::wsprintf(szErr, "Write Process Memory Error!\nError Code:%d\n", ::GetLastError()); ::MessageBox(m_hWnd, szErr, "Error", MB_OK | MB_ICONWARNING); return FALSE; } // 获取LoadLibraryA的内存地址 // 获取进程的基址 HMODULE hBaseAddress = NULL; GetProcessBaseAddress(&hBaseAddress, hProcess); DWORD64 dwDllBaseAddress = GetProcessDllBaseAddress(hProcess, hBaseAddress, "kernel32.dll", b32); DWORD64 dwFuncAddress = GetFuncInDll(hProcess, dwDllBaseAddress, "LoadLibraryA", b32); // 创建远程线程 HANDLE hThread = ::CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)dwFuncAddress, lpAddr, 0, NULL); if(NULL == hThread) { char szErr[MAX_PATH] = {0}; ::wsprintf(szErr, "Create Remote Thread Error!\nError Code:%d\n", ::GetLastError()); ::MessageBox(m_hWnd, szErr, "Error", MB_OK | MB_ICONWARNING); return FALSE; } return TRUE; } BOOL CInjectDlg::JudgePE32Or64(char *lpszDllPath) { // 内存映射文件 HANDLE hFile = ::CreateFile(lpszDllPath, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_ARCHIVE, NULL); if(INVALID_HANDLE_VALUE == hFile) { char szErr[MAX_PATH] = {0}; ::wsprintf(szErr, "Create File Error!\nError Code:%d\n", ::GetLastError()); ::MessageBox(m_hWnd, szErr, "Error", MB_OK | MB_ICONWARNING); return FALSE; } HANDLE hFileMap = ::CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); if(!hFileMap) { ::CloseHandle(hFile); char szErr[MAX_PATH] = {0}; ::wsprintf(szErr, "Create File Mapping Error!\nError Code:%d\n", ::GetLastError()); ::MessageBox(m_hWnd, szErr, "Error", MB_OK | MB_ICONWARNING); return FALSE; } LPVOID lpMemory = ::MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0); if(!lpMemory) { ::CloseHandle(hFileMap); ::CloseHandle(hFile); char szErr[MAX_PATH] = {0}; ::wsprintf(szErr, "Map View Of File Error!\nError Code:%d\n", ::GetLastError()); ::MessageBox(m_hWnd, szErr, "Error", MB_OK | MB_ICONWARNING); return FALSE; } // PE结构 PIMAGE_DOS_HEADER pDosHead = (PIMAGE_DOS_HEADER)lpMemory; if(IMAGE_DOS_SIGNATURE == pDosHead->e_magic) { DWORD dwlfanew = pDosHead->e_lfanew; PIMAGE_NT_HEADERS pNtHeaders = (PIMAGE_NT_HEADERS)((DWORD64)pDosHead + dwlfanew); if(IMAGE_NT_SIGNATURE == pNtHeaders->Signature) { if(IMAGE_FILE_MACHINE_AMD64 == pNtHeaders->FileHeader.Machine || IMAGE_FILE_MACHINE_IA64 == pNtHeaders->FileHeader.Machine) { return FALSE; } } } return TRUE; } BOOL CInjectDlg::GetProcessBaseAddress(HMODULE *lpBaseAddress, HANDLE hProcess) { ::EnumProcessModules(hProcess, lpBaseAddress, sizeof(HMODULE), NULL); return TRUE; } DWORD64 CInjectDlg::GetFuncInDll(HANDLE hProcess, DWORD64 dwDllBaseAddress, char *lpszFuncName, BOOL b32) { DWORD dwlfanew = 0; DWORD dwFuncNameLen = ::lstrlen(lpszFuncName) + 1; char szTemp[MAX_PATH] = {0}; ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + 0x003c), &dwlfanew, 4, NULL); DWORD dwExportRVA = 0; // 根据32位和64位的区别,分别读取内存 // 32位 if(b32) { // 从PE头文件目录获取导出表 // 获取导出表的起始偏移 ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + dwlfanew + 4 + 20 + 96), &dwExportRVA, 4, NULL); } // 64位 else { // 从PE头文件目录获取导出表 // 获取导出表的起始偏移 ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + dwlfanew + 4 + 20 + 112), &dwExportRVA, 4, NULL); } // 获取NumberOfNames DWORD dwNumberOfNames = 0; ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + dwExportRVA + 24), &dwNumberOfNames, 4, NULL); // 获取AddressOfNames DWORD dwAddressOfNames = 0; ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + dwExportRVA + 32), &dwAddressOfNames, 4, NULL); // 遍历API函数名称并匹配 DWORD dwNameRVA = 0; for(DWORD i = 0; i < dwNumberOfNames; i++) { // 获取DLL名称的地址并读取 ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + dwAddressOfNames + 4*i), &dwNameRVA, 4, NULL); ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + dwNameRVA), szTemp, dwFuncNameLen, NULL); if(0 == ::lstrcmpi(lpszFuncName, szTemp)) // 不区分大小写 { // AddressOfNameOrdinals DWORD dwAddressOfNameOrdinals = 0; ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + dwExportRVA + 36), &dwAddressOfNameOrdinals, 4, NULL); WORD wHint = 0; ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + dwAddressOfNameOrdinals + 2*i), &wHint, 2, NULL); // AddressOfFunctions DWORD dwAddressOfFunctions = 0; ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + dwExportRVA + 28), &dwAddressOfFunctions, 4, NULL); DWORD dwFuncRVA = 0; ::ReadProcessMemory(hProcess, (LPCVOID)(dwDllBaseAddress + dwAddressOfFunctions + 4*wHint), &dwFuncRVA, 4, NULL); DWORD64 dwRet = dwDllBaseAddress + dwFuncRVA; return dwRet; } } return 0; } DWORD64 CInjectDlg::GetProcessDllBaseAddress(HANDLE hProcess, HMODULE hBaseAddress, char szDllName[MAX_PATH], BOOL b32) { DWORD64 dwBaseAddress = (DWORD64)hBaseAddress; DWORD dwlfanew = 0; ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + 0x003c), &dwlfanew, 4, NULL); // 根据32位和64位的区别,分别读取内存 // 32位 if(b32) { // 从PE头文件目录获取导入表 // 获取导入表的起始偏移和大小 DWORD dwIATRVA = 0; DWORD dwIATSize = 0; ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwlfanew + 4 + 20 + 96 + 8), &dwIATRVA, 4, NULL); ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwlfanew + 4 + 20 + 96 + 8 + 4), &dwIATSize, 4, NULL); // 遍历DLL全称 DWORD dwIndex = (dwIATSize - 1)/20; DWORD dwOffsetDllName = 0; DWORD dwDllNameLen = ::lstrlen(szDllName) + 1; char szTemp[MAX_PATH] = {0}; for(DWORD i = 0; i < dwIndex; i++) { // 获取DLL名称的偏移 ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwIATRVA + i*20 + 12), &dwOffsetDllName, 4, NULL); // 获取DLL名称的地址并读取 ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwOffsetDllName), szTemp, dwDllNameLen, NULL); if(0 == ::lstrcmpi(szDllName, szTemp)) // 不区分大小写 { DWORD dwFunctionAddress = 0; // 读取DLL中的函数地址 // 获取DLL中的函数的偏移地址 ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwIATRVA + i*20 + 16), &dwFunctionAddress, 4, NULL); // 读取DLL中的函数的地址 ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwFunctionAddress), &dwFunctionAddress, 4, NULL); // 根据DLL中的函数地址暴力搜索出DLL的加载基址 // 原理是:文件是对齐64k(0x10000)装载进内存的,DLL是一个PE结构文件 DWORD64 dwRet = GetDllBase(hProcess, dwFunctionAddress, b32); return dwRet; } } } // 64位 else { // 从PE头文件目录获取导入表 // 获取导入表的起始偏移和大小 DWORD dwIATRVA = 0; DWORD dwIATSize = 0; ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwlfanew + 4 + 20 + 112 + 8), &dwIATRVA, 4, NULL); ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwlfanew + 4 + 20 + 112 + 8 + 4), &dwIATSize, 4, NULL); // 遍历DLL全称 DWORD dwIndex = (dwIATSize - 1)/20; DWORD dwOffsetDllName = 0; DWORD dwDllNameLen = ::lstrlen(szDllName) + 1; char szTemp[MAX_PATH] = {0}; for(DWORD i = 0; i < dwIndex; i++) { // 获取DLL名称的偏移 ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwIATRVA + i*20 + 12), &dwOffsetDllName, 4, NULL); // 获取DLL名称的地址并读取 ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwOffsetDllName), szTemp, dwDllNameLen, NULL); if(0 == ::lstrcmpi(szDllName, szTemp)) // 不区分大小写 { DWORD64 dwFunctionAddress = 0; // 读取DLL中的函数地址 // 获取DLL中的函数的偏移地址 ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwIATRVA + i*20 + 16), &dwFunctionAddress, 4, NULL); // 读取DLL中的函数的地址 ::ReadProcessMemory(hProcess, (LPCVOID)(dwBaseAddress + dwFunctionAddress), &dwFunctionAddress, 8, NULL); // 根据DLL中的函数地址暴力搜索出DLL的加载基址 // 原理是:文件是对齐64k(0x10000)装载进内存的,DLL是一个PE结构文件 DWORD64 dwRet = GetDllBase(hProcess, dwFunctionAddress, b32); return dwRet; } } } return 0; } DWORD64 CInjectDlg::GetDllBase(HANDLE hProcess, DWORD64 dwFunctionAddress, BOOL b32) { WORD MZ = 0; DWORD dwlfanew = 0; DWORD PE00 = 0; if(b32) { dwFunctionAddress = dwFunctionAddress & 0xFFFF0000; } else { dwFunctionAddress = dwFunctionAddress & 0xFFFFFFFFFFFF0000; } do { ::ReadProcessMemory(hProcess, (LPCVOID)dwFunctionAddress, &MZ, 2, NULL); if(IMAGE_DOS_SIGNATURE == MZ) { ::ReadProcessMemory(hProcess, (LPCVOID)(dwFunctionAddress + 0x003c), &dwlfanew, 4, NULL); ::ReadProcessMemory(hProcess, (LPCVOID)(dwFunctionAddress + dwlfanew), &PE00, 4, NULL); if(IMAGE_NT_SIGNATURE == PE00) { return dwFunctionAddress; } } dwFunctionAddress = dwFunctionAddress - 0x10000; }while(dwFunctionAddress >= 0x10000000); return 0; }