DemonMemory/源代码/InjectDlg.cpp

410 lines
13 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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