[实例]远程加载DLL, 远程卸载DLL

0x01 项目说明

实现在内存中对dll的加载和卸载

0x02 软件展示

360截图20180122000944649.jpg

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

后面两个代码, 不太符合要求


这是我的理解, 后面测试成功!


完整项目代码,下载地址:

TestInjectProcess.rar


待分析, 明天继续!!





原文链接: [实例]远程加载DLL, 远程卸载DLL 版权所有,转载时请注明出处,违者必究。
注明出处格式:流沙团 ( https://gyarmy.com/post-377.html )

发表评论

0则评论给“[实例]远程加载DLL, 远程卸载DLL”