0x01 项目说明
实现在内存中对dll的加载和卸载
0x02 软件展示
0x03 代码展示
// TestInjectProcess.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "resource.h"
#include <Windows.h>
#include <Tlhelp32.h>
#include <assert.h>
#include <string.h>
#include <tchar.h>
#include <stdlib.h>
#include <stdio.h>
//提升进程权限
BOOL EnableDebugPrivilege(BOOL bEnable)
{
BOOL status=FALSE;
HANDLE hToken;
//打开当前进程的访问令牌
if(OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES,&hToken))
{
LUID uID;
LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&uID);
//调整特权级别
TOKEN_PRIVILEGES tp;
tp.PrivilegeCount =1;
tp.Privileges[0].Luid=uID;
tp.Privileges[0].Attributes=bEnable?SE_PRIVILEGE_ENABLED:0;
AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(tp),NULL,NULL);
status =(GetLastError() ==ERROR_SUCCESS);
CloseHandle(hToken);
}
return status;
}
//获取进程name的ID
DWORD getPid(LPTSTR name)
{
HANDLE hProcSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);//获取进程快照句柄
assert(hProcSnap!=INVALID_HANDLE_VALUE);
PROCESSENTRY32 pe32;
pe32.dwSize=sizeof(PROCESSENTRY32);
BOOL flag=Process32First(hProcSnap,&pe32);//获取列表的第一个进程
while(flag)
{
if(!_tcscmp(pe32.szExeFile,name))
{
CloseHandle(hProcSnap);
return pe32.th32ProcessID;//pid
}
flag=Process32Next(hProcSnap,&pe32);//获取下一个进程
}
CloseHandle(hProcSnap);
return 0;
}
//卸载dll
BOOL ExitDll(DWORD dwID, LPSTR szDllName)
{
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, dwID);
if ( !hProcess ) {
return FALSE;
}
int cByte = (_tcslen(szDllName)+1) * sizeof(TCHAR);
LPVOID pAddr = VirtualAllocEx(hProcess, NULL, cByte, MEM_COMMIT, PAGE_READWRITE);
if ( !pAddr || !WriteProcessMemory(hProcess, pAddr, szDllName, cByte, NULL)) {
return FALSE;
}
#ifdef _UNICODE
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetModuleHandleW;
#else
PTHREAD_START_ROUTINE pfnStartAddr = (PTHREAD_START_ROUTINE)GetModuleHandleA;
#endif
//Kernel32.dll总是被映射到相同的地址
if ( !pfnStartAddr ) {
return FALSE;
}
DWORD dwThreadID = 0,dwFreeId=0,dwHandle;
HANDLE hRemoteThread = CreateRemoteThread(hProcess, NULL, 0, pfnStartAddr, pAddr, 0, &dwThreadID);
if ( !hRemoteThread ) {
return FALSE;
}
WaitForSingleObject(hRemoteThread,INFINITE);
// 获得GetModuleHandle的返回值
GetExitCodeThread(hRemoteThread,&dwHandle);
CloseHandle(hRemoteThread);
// 使目标进程调用FreeLibrary,卸载DLL
#ifdef _UNICODE
PTHREAD_START_ROUTINE pfnFreeAddr = (PTHREAD_START_ROUTINE)FreeLibrary;
#else
PTHREAD_START_ROUTINE pfnFreeAddr = (PTHREAD_START_ROUTINE)FreeLibrary;
#endif
HANDLE hFreeThread = CreateRemoteThread(hProcess, NULL, 0, pfnFreeAddr,(LPVOID)dwHandle,0,&dwFreeId);
if ( !hFreeThread ) {
return FALSE;
}
WaitForSingleObject(hFreeThread,INFINITE);
VirtualFreeEx(hProcess,pAddr,cByte,MEM_COMMIT);
CloseHandle(hFreeThread);
CloseHandle(hProcess);
return TRUE;
}
// 向目标进程地址空间写入DLL名称
BOOL InjectDll(HANDLE hProcess, LPSTR lpszDll)
{
DWORD dwSize, dwWritten;
//HANDLE hProcess = (HANDLE)hTProcess;
dwSize = lstrlenA(lpszDll) + 1;
LPVOID lpBuf = VirtualAllocEx(hProcess, NULL, dwSize, MEM_COMMIT, PAGE_READWRITE );
if (NULL == lpBuf)
{
CloseHandle(hProcess);
return FALSE;
}
if (WriteProcessMemory(hProcess, lpBuf, (LPVOID)lpszDll, dwSize, &dwWritten))
{
if(dwWritten!=dwSize)
{
VirtualFreeEx(hProcess, lpBuf, dwSize,MEM_DECOMMIT);
CloseHandle(hProcess); // 失败处理
return FALSE;
}
}
else
{
CloseHandle(hProcess);
}
// 使目标进程调用LoadLibrary,加载DLL
DWORD dwID;
LPVOID pFunc = LoadLibraryA;
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0,(LPTHREAD_START_ROUTINE)pFunc, lpBuf, 0, &dwID);
if(hThread == NULL)
{
return FALSE;
}
//收尾工具
WaitForSingleObject(hThread,INFINITE);
// 释放目标进程中申请的空间
VirtualFreeEx(hProcess,lpBuf,dwSize,MEM_DECOMMIT);
CloseHandle(hThread);
CloseHandle(hProcess);
// 等待LoadLibrary加载完毕
return TRUE;
}
BOOL CALLBACK InjectDialogProc(
HWND hwndDlg, // handle to dialog box
UINT uMsg, // message
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
TCHAR szStrTemp[256]={0};
DWORD ProcessId=0;
TCHAR szProcess[10]={0};
TCHAR szDllStr[256]={0};
TCHAR szExitDllStr[256]={0};
HANDLE hProcess;
BOOL isInject;
BOOL isExit;
switch(uMsg)
{
case WM_INITDIALOG:
break;
case WM_CLOSE:
EndDialog(hwndDlg,0);
break;
case WM_COMMAND:
{
switch(LOWORD(wParam))
{
case IDC_BUTTON_INJECT:
//MessageBox(0,"inject","注入",0);
GetDlgItemText(hwndDlg,IDC_EDIT_PROCESSNAME,szStrTemp,256);
ProcessId = getPid(szStrTemp);
if(ProcessId == 0)
{
MessageBox(0,"没找到进程","错误1",0);
return FALSE;
}
//打开目标进程
hProcess = OpenProcess( PROCESS_CREATE_THREAD | PROCESS_VM_OPERATION |
PROCESS_VM_WRITE, FALSE, ProcessId);
if(hProcess == NULL)
{
MessageBox(0,"进程打开失败","错误2",0);
return FALSE;
}
//sprintf(szProcess,"%d",ProcessId);
//MessageBox(0,szProcess,"进程ID",MB_OK);
//写入进程的内存中去
GetDlgItemText(hwndDlg,IDC_EDIT_DLLLOCATION,szDllStr,256);
isInject =InjectDll(hProcess,szDllStr);
if(!isInject)
{
MessageBox(0,"注入DLL失败","错误\3",0);
return FALSE;
}
break;
case IDC_BUTTON_EXITDLL:
//EndDialog(hwndDlg,0);
GetDlgItemText(hwndDlg,IDC_EDIT_PROCESSNAME,szStrTemp,256);
ProcessId = getPid(szStrTemp);
if(ProcessId == 0)
{
MessageBox(0,"没找到进程","错误1",0);
return FALSE;
}
/*
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, ProcessId);
if(hProcess == NULL)
{
MessageBox(0,"进程打开失败","错误2",0);
return FALSE;
}
*/
GetDlgItemText(hwndDlg,IDC_EDIT_DLLLOCATION,szExitDllStr,256);
//MessageBox(0,szExitDllStr,"卸载测试",MB_OK);
isExit = ExitDll(ProcessId,szExitDllStr);
if(!isExit)
{
MessageBox(0,"卸载Dll失败","错误5",0);
return FALSE;
}
break;
}
}
}
return FALSE;
}
int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
EnableDebugPrivilege(TRUE);
DialogBox(hInstance,MAKEINTRESOURCE(IDD_DIALOG_MAIN),NULL,InjectDialogProc);
return 0;
}
0x04 分析
因为代码基本参考一些文章编写的
在写卸载dll的时候, 遇到了很多问题, 因为对几个函数还不是太熟悉
写下来,继续分析一下吧!!
错误代码一:
void CDllManageDlg::UnInjectDll(DWORD dwPid, char *szDllName)
{
// 使目标进程调用GetModuleHandle,获得DLL在目标进程中的句柄
DWORD dwHandle;
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid);
LPVOID pFunc = GetModuleHandleA;
char lpBuf[MAXBYTE];
HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)pFunc, lpBuf, 0, &dwPid );
// 等待GetModuleHandle运行完毕
WaitForSingleObject( hThread, INFINITE );
// 获得GetModuleHandle的返回值
GetExitCodeThread( hThread, &dwHandle );
// 释放目标进程中申请的空间
int dwSize = strlen(szDllName) + sizeof(char);
VirtualFreeEx( hProcess, lpBuf, dwSize, MEM_DECOMMIT );
CloseHandle( hThread );
// 使目标进程调用FreeLibrary,卸载DLL
pFunc = FreeLibrary;
hThread = CreateRemoteThread( hProcess, NULL, 0,
(LPTHREAD_START_ROUTINE)pFunc, (LPVOID)dwHandle, 0, &dwPid );
// 等待FreeLibrary卸载完毕
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
CloseHandle( hProcess );
}
错误代码二:
// 使目标进程调用GetModuleHandle,获得DLL在目标进程中的句柄
DWORD dwHandle, dwID;
LPVOID pFunc = GetModuleHandleA;
HANDLE hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, lpBuf, 0, &dwID );
// 等待GetModuleHandle运行完毕
WaitForSingleObject( hThread, INFINITE );
// 获得GetModuleHandle的返回值
GetExitCodeThread( hThread, &dwHandle );
// 释放目标进程中申请的空间
VirtualFreeEx( hProcess, lpBuf, dwSize, MEM_DECOMMIT );
CloseHandle( hThread );
// 使目标进程调用FreeLibrary,卸载DLL
pFunc = FreeLibrary;
hThread = CreateRemoteThread( hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)pFunc, (LPVOID)dwHandle, 0, &dwID );
// 等待FreeLibrary卸载完毕
WaitForSingleObject( hThread, INFINITE );
CloseHandle( hThread );
CloseHandle( hProcess );
这两端代码, 继续分析一下
睡觉, 明天早起, 继续分析,, LP在催了,,,
标注:20180123:
已经分析完毕, 第一段代码的
lpBuf 没有指定模块名字(没有进行任何模块的分配)
lpBuf 没有指定
流程的话
VirtualAllocEx
WriteProcessMemory
CreateRemoteThread
获取返回值:dwHandle
CreateRemoteThread - FreeLibrary
VirtualFreeEx
后面两个代码, 不太符合要求
这是我的理解, 后面测试成功!
完整项目代码,下载地址:
待分析, 明天继续!!