比如说user32.dll会在什么时候被解除映射?
我所写的dll好像是被loadlibrary调用完,就被freelibrary了.
这是我的dll的代码
// dllmain.cpp : 定义 DLL 应用程序的入口点。
#include "stdafx.h"
#include <stdio.h>
#include <ImageHlp.h> //for ImageDirectoryEntryToData
#include <TlHelp32.h> //for Module32First,MODULEENTRY32 and CreateToolhelp32Snapshot
#pragma comment(lib,"ImageHlp") //for ImageDirectoryEntryToData
//替换了的MessageBoxA.注意函数原型要和原来的一致,包括WIAPI
//它显示一个消息框指明MessageBoxA已被截获
int WINAPI MyMessageBoxA(HWND hwnd, LPCSTR lpszContent, LPCSTR lpszCaption, UINT uType) {
return MessageBoxW(hwnd, TEXT("Call to MessageBoxW is interceptedZZZZZZZZZZ!"), TEXT("Hook"), MB_OK);
}
//修改输入表
VOID ModifyIAT(HMODULE hmodCaller, LPCSTR szDllName, PROC pfnCurent, PROC pfnNew) {
ULONG ulSize;
PIMAGE_IMPORT_DESCRIPTOR pid = (PIMAGE_IMPORT_DESCRIPTOR)
ImageDirectoryEntryToData(
hmodCaller,
TRUE,
IMAGE_DIRECTORY_ENTRY_IMPORT,
&ulSize);
// if this image has no import section, just simply return and do nothing
if (pid == NULL)
return;
// find the corresponding item
while (pid->Name)
{
// pid->Name contains the RVA addr of the module name string
PSTR pszModName = (PSTR)((PBYTE)hmodCaller + pid->Name);
if (lstrcmpiA(szDllName, pszModName) == 0)
{
// found
break;
}
pid++;
}
if (pid->Name == 0)
{
// not found, just return
return;
}
// get caller's import address table(IAT) for the callee's functions
PIMAGE_THUNK_DATA pThunk = (PIMAGE_THUNK_DATA)((PBYTE)hmodCaller + pid->FirstThunk);
while (pThunk->u1.Function)
{
PROC *ppfn = (PROC*) &(pThunk->u1.Function);
if (*ppfn == pfnCurent)
{
SIZE_T sBytesWritten;
BOOL bProtectResult = FALSE;
DWORD dwOldProtect = 0;
MEMORY_BASIC_INFORMATION memInfo;
if (VirtualQuery(pfnCurent, &memInfo, sizeof(memInfo)) > 0)
{
// change the pages to read/write
bProtectResult = VirtualProtect(
memInfo.BaseAddress,
memInfo.RegionSize,
PAGE_READWRITE,
&dwOldProtect);
printf("ok\n");
WriteProcessMemory(GetCurrentProcess(),
ppfn,
&pfnNew,
sizeof(pfnNew),
&sBytesWritten);
bProtectResult = VirtualProtect(
memInfo.BaseAddress,
memInfo.RegionSize,
PAGE_READONLY,
&dwOldProtect);
}
return;
}
pThunk++;
}
}
//dll的入口函数.每当这个dll被映射到一个进程的地址空间中,我们就挂接MessageBoxW
//在dll从进程的地址空间中缷载时,我们将原来的MessageboxW的地址写回进程中
//要取得这个进程的基地址,要用到MODULEENTRY32和CreateToolhelp32Snapshot
//MODULEENTRY32的hModule成员就是进程的基地址
BOOL APIENTRY DllMain(HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved)
{
HMODULE hCurrentProcess;
MODULEENTRY32 me32;
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, GetCurrentProcessId());
me32.dwSize = sizeof(MODULEENTRY32);
Module32First(hSnapshot, &me32);
hCurrentProcess = me32.hModule;
switch (ul_reason_for_call) {
case DLL_PROCESS_ATTACH:
printf("Process attach. \n");
ModifyIAT(
hCurrentProcess,
"USER32.DLL",
GetProcAddress(GetModuleHandle(TEXT("USER32.DLL")), "MessageBoxA"),
(PROC)MyMessageBoxA
);
break;
case DLL_THREAD_ATTACH:
printf("Thread attach. \n");
case DLL_THREAD_DETACH:
printf("Thread detach. \n");
case DLL_PROCESS_DETACH:
printf("Process detach. \n");
break;
}
return TRUE;
}
这是我编写的测试程序代码
#include "stdafx.h"
#include<Windows.h>
#include<iostream>
using namespace std;
int main()
{
int a;
cin >> a;
MessageBoxA(NULL, "666", "666", MB_OK);
system("pause");
return 0;
}
这是我创建远程线程注入dll的程序
// injectdll.cpp: 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <Windows.h>
#include <TlHelp32.h>
int main()
{
HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);//获得进程快照
if (hProcessSnap == FALSE)
{
printf("CreateToolhelp32Snapshot error");
return -1;
}
PROCESSENTRY32 pe32;
pe32.dwSize = sizeof(PROCESSENTRY32);
TCHAR m_processToFind[128] = TEXT("ConsoleApplication1.exe");//所要注入的进程名
BOOL bRet = Process32First(hProcessSnap, &pe32);
while (bRet)
{
printf("[process name]:%ws\n", pe32.szExeFile);
printf("[PID]:%d\n\n", pe32.th32ProcessID);
if (lstrcmp(pe32.szExeFile, m_processToFind) == 0)
{
printf("进程:%ws找到,它的进程ID为:%d\n", m_processToFind, pe32.th32ProcessID);
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pe32.th32ProcessID);//获得所要注入进程的句柄
//执行openprocess之前可能需要开启特权
PVOID addr = VirtualAllocEx(hProcess, NULL, 50, MEM_COMMIT, PAGE_READWRITE);//在所注入进程开辟一段空间
if (addr == NULL)
{
int ret = GetLastError();
printf("在远程进程申请空间失败!错误码为:%d\n", ret);
}
else
{
printf("远程进程地址空间中申请空间成功!\n");
}
char path[50] = "F:\\injertdll.dll";//自己编写的注入dll
int retval = WriteProcessMemory(hProcess, addr, (LPVOID)path, sizeof(path), NULL);//将自己dll写入到所找进程空间
if (retval)
{
printf("写入成功!\n");
}
else
printf("写入失败!\n");
PTHREAD_START_ROUTINE pfnThread = (PTHREAD_START_ROUTINE)
GetProcAddress(GetModuleHandle(TEXT("kernel32.DLL")), "LoadLibraryA");//用loadlibrary注入自己的dll
HANDLE hRemoteThread = CreateRemoteThread(
hProcess,//目标进程的句柄
NULL,//指向线程的安全描述结构体的指针,一般设置为NULL,表示使用默认的安全级别
0, //线程堆栈大小,一般设置为0
pfnThread,//线程函数的地址(loadlibrary)
addr,//线程参数(传入loadlibrary的dll)
0,//线程的创建方式
NULL); //输出参数,记录创建的远程线程的ID
if (hRemoteThread == INVALID_HANDLE_VALUE)
{
printf("远程线程创建失败!\n");
}
else
{
printf("远程线程创建成功!\n");
}
break;
}
bRet = Process32Next(hProcessSnap, &pe32);
}
system("pause");
CloseHandle(hProcessSnap); // 经常忘记这句
return 0;
}
在测试程序执行messageboxA时会报错,是不是因为注入的DLL已经被解除映射了