毕设做了一个相关的东西,一个关于注册表和文件监控的东西,主要的思路是hook 文件和注册表相关的api,然后改变api执行流程,加入自己的处理代码。时间过去了快一年了,在研究生课上有个作业要用到这些,于是就写回忆了一下,发现还不能写出来,所以,写个博客,复习一下吧。
其中借鉴了一下网上其他人的代码,具体是谁的,也忘了,如果谁能认出来,可以告诉我,我在标识出来。而且具体的方法和讲解在《Windows核心编程》里面有具体的讲解。
以前觉得dll注入是个很高大上的东西,自己研究过后,发现也是一件很简单的事情,但是理解起来,则会需要非常全面的知识。大概流程是这样的:
- 使得进程获取权限,不然在注入的时候会有不成功的时候
- 使用OpenProcess获取要注入的进程的句柄
- 在要注入的进程空间内申请一段内存
- 在申请的内存中写入要注入的dll的绝对路径
- 获取loadLibrary的地址
- CreateRemoteThread创建远程线程,函数为loadLibrary,参数为dll的路径
- 等待线程创建完毕,然后释放内存,关闭线程句柄
卸载dll的逻辑也是十分简单:
- 获取注入的dll模块的句柄,发现了有两种方法
1.1 通过创建进程快照的方式,遍历获取
1.2 通过创建远程线程,直接在进程空间里面获取- 打开被注入的进程,获取句柄,然后把dll的path写入到该进程空间中,然后饭后创建远程线程,并且执行函数FreeLibrary
下面是注入的代码
inject(DWORD dwRemoteProcessId)
{
//如果输入“”表示向自身进程注入
if (dwRemoteProcessId == 0)
dwRemoteProcessId = GetCurrentProcessId();
//获得调试权限
if (EnableDebugPriv(SE_DEBUG_NAME))
{
printf("Add Privilege error\n");
return -1;
}
//调用OpenProcess()获得句柄
HANDLE hRemoteProcess;
if ((hRemoteProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwRemoteProcessId)) == NULL)
{
printf("OpenProcess error\n");
printf("Error Code:%d\n",GetLastError());
system("pause");
return -2;
}
//在远程进程中分配内存,准备拷入DLL路径字符串
//取得当前DLL路径
char DllPath[260]; //Windows路径最大为
GetCurrentDirectoryA(260, DllPath); //获取当前进程执行目录
printf("Proces***e Directory is %s\n", DllPath);
strcat(DllPath, "xxx.dll"); //链接到DLL路径
LPVOID pRemoteDllPath = VirtualAllocEx(hRemoteProcess, NULL, strlen(DllPath) + 1, MEM_COMMIT, PAGE_READWRITE);
if (pRemoteDllPath == NULL)
{
printf("VirtualAllocEx error\n");
return -3;
}
//向远程进程空间中写入DLL路径字符串
printf("DllPath is %s\n", DllPath);
DWORD Size;
if (WriteProcessMemory(hRemoteProcess, pRemoteDllPath, DllPath, strlen(DllPath) +1, &Size) == NULL)
{
printf("WriteProcessMemory error\n");
return -4;
}
printf("WriteRrmoyrProcess Size is %d\n\n", Size);
//获得远程进程中LoadLibrary()的地址
LPTHREAD_START_ROUTINE pLoadLibrary = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "LoadLibraryA");
if (pLoadLibrary == NULL)
{
printf("GetProcAddress error\n");
return -5;
}
else
{
printf("LoadLibrary's Address is 0x%x\n\n", pLoadLibrary);
}
//启动远程线程
DWORD dwThreadId;
HANDLE hThread;
if ((hThread = CreateRemoteThread(hRemoteProcess, NULL, 0, pLoadLibrary, pRemoteDllPath, 0, &dwThreadId)) == NULL)
{
printf("CreateRemoteThread error\n");
return -6;
}
else
{
WaitForSingleObject(hThread, INFINITE);
printf("dwThreadId is %d\n\n", dwThreadId);
printf("Inject is done\n");
}
//释放分配内存
if (VirtualFreeEx(hRemoteProcess, pRemoteDllPath, 0, MEM_RELEASE) == 0)
{
printf("VitualFreeEx error\n");
return -8;
}
//释放句柄
if (hThread != NULL) CloseHandle(hThread);
if (hRemoteProcess != NULL) CloseHandle(hRemoteProcess);
}
int EnableDebugPriv(char *name)
{
HANDLE hToken; //进程令牌句柄
TOKEN_PRIVILEGES tp; //TOKEN_PRIVILEGES结构体,其中包含一个【类型+操作】的权限数组
LUID luid; //上述结构体中的类型值
//打开进程令牌环
//GetCurrentProcess()获取当前进程的伪句柄,只会指向当前进程或者线程句柄,随时变化
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY, &hToken))
{
printf("OpenProcessToken error\n");
return -8;
}
//获得本地进程name所代表的权限类型的局部唯一ID
if (!LookupPrivilegeValue(NULL, name, &luid))
{
printf("LookupPrivilegeValue error\n");
}
tp.PrivilegeCount = 1; //权限数组中只有一个“元素”
tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; //权限操作
tp.Privileges[0].Luid = luid; //权限类型
//调整进程权限
if (!AdjustTokenPrivileges(hToken, 0, &tp, sizeof(TOKEN_PRIVILEGES), NULL, NULL))
{
printf("AdjustTokenPrivileges error!\n");
return -9;
}
return 0;
}
卸载代码其一,这是通过创建远程线程获取的dll的句柄:
int uninject(DWORD dwRemoteProcessId, char *DllPath)
{
DWORD ProcessPID=dwRemoteProcessId;
//打开进程
HANDLE hProcess;
hProcess=OpenProcess(
PROCESS_CREATE_THREAD |
PROCESS_VM_OPERATION |
PROCESS_VM_WRITE ,
FALSE,ProcessPID);
if(!hProcess)
{
printf("打开目标进程失败\n");
CloseHandle(hProcess);
return 3;
}
int allocSize=(strlen(DllPath)+1)*sizeof(char);
//申请内存存放以DLL文件路径名
char *pLibFileName=(char*)VirtualAllocEx(hProcess,NULL,allocSize,MEM_COMMIT,PAGE_READWRITE);
//写DLL文件路径名到远程进程
if(!pLibFileName)
{
printf("申请目标进程内存失败");
CloseHandle(hProcess);
return 4;
}
if(!WriteProcessMemory(hProcess,pLibFileName,(PVOID)DllPath, allocSize, NULL))
{
printf("写目标进程内存失败");
VirtualFreeEx(hProcess,pLibFileName,allocSize,MEM_RELEASE);
CloseHandle(hProcess);
return 5;
}
while(1)
{
//创建远程线程,GetModuleHandle获取刚刚注入的DLL的句柄
HANDLE hThread=CreateRemoteThread(hProcess,NULL,0,(PTHREAD_START_ROUTINE)GetModuleHandle,pLibFileName,0,NULL);
if(!hThread)
{
printf("创建目标线程运行GetModuleHandle失败");
VirtualFreeEx(hProcess,pLibFileName,allocSize,MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return 6;
}
WaitForSingleObject(hThread,INFINITE);
DWORD hDll;
GetExitCodeThread(hThread,&hDll);
if(!hDll)
{
printf("卸载DLL成功");//卸载结束!!
VirtualFreeEx(hProcess,pLibFileName,allocSize,MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return 7;
}
CloseHandle(hThread);
hThread=NULL;
//创建远程线程,卸载远程DLL
hThread=CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)FreeLibrary,(LPVOID)hDll,0,NULL);
if(!hThread)
{
printf("创建远程线程运行FreeLibrary失败");
VirtualFreeEx(hProcess,pLibFileName,allocSize,MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return 8;
}
WaitForSingleObject(hThread,INFINITE);
DWORD FreeLibInfo;
GetExitCodeThread(hThread,&FreeLibInfo);
if(!FreeLibInfo)
{
printf("FreeLibrary失败");
VirtualFreeEx(hProcess,pLibFileName,allocSize,MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
return 9;
}
}
return 0;
}
卸载代码其二,这是通过进程快照获取的:
void UnInjectDll(char *szDllName, DWORD dwPid)
{
if(dwPid==0 || strlen(szDllName)==0)
{
AfxMessageBox("输入信息不全");
return;
}
//创建进程快照
HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,dwPid);
MODULEENTRY32 ME32 = {0};
ME32.dwSize = sizeof(MODULEENTRY32);
BOOL isNext = Module32First(hSnap,&ME32);
BOOL flag = FALSE;
while(isNext)
{
if(strcmp(ME32.szModule,szDllName)==0)
{
flag = TRUE;
break;
}
isNext = Module32Next(hSnap,&ME32);
}
if(flag == FALSE)
{
AfxMessageBox("找不到目标模块");
return;
}
CloseHandle(hSnap);
HANDLE hPro = OpenProcess(PROCESS_ALL_ACCESS,FALSE,dwPid);
FARPROC pFun = GetProcAddress(GetModuleHandle("kernel32.dll"),"FreeLibrary");
HANDLE hThread = CreateRemoteThread(hPro,NULL,0,(LPTHREAD_START_ROUTINE)pFun,ME32.szModule,0,NULL);
if(!hThread)
{
AfxMessageBox("创建远程线程失败");
return ;
}
AfxMessageBox("卸载成功");
WaitForSingleObject(hThread,INFINITE);
CloseHandle(hThread);
CloseHandle(hPro);
}