创建远程线程实现DLL注入
2016-04-12 21:56
363 查看
最近在学逆向,学到了DLL注入。DLL注入有三种方式:创建远程线程(该方法不适用于win7及以上的OS),使用注册表(APPInit_DLLs,该方法不适用于xp及以上的OS)。消息勾取(SetWindowsHookEx()API )。下面介绍一下关于创建远程线程的实验。
远程线程技术指的是通过在另一个进程中创建远程线程的方法进入那个进程的内存地址空间。我们知道,在进程中,可以通过CreateThread函数创建线程,被创建的新线程与主线程共享地址空间以及其他的资源。但是很少有人知道,通过CreateRemoteThread也同样可以在另一个进程内创建新线程,被创建的远程线程同样可以共享远程进程(是远程进程耶!)的地址空间,所以,实际上,我们通过一个远程线程,进入了远程进程的内存地址空间,也就拥有了那个远程进程相当的权限。例如在远程进程内部启动一个DLL木马。
下面贴一下实验代码
myhack.cpp: 待注入的dll文件代码(VS2010编译通过,得到myhack.dll)
开xp虚拟机再跑一下:
记事本弹窗,success,这就是注入的dll。
思考:为什么在win8上该程序不能成功注入dll文件?
解答:windows从kernel6(vista,7,8)开始采用全新的会话管理机制,这使得通过creatremotethread()API注入dll的旧方法对某些进程(服务进程)不在适用。
试验中遇到的问题:关于WCHAR * 与char *的转化。http://blog.163.com/tianshi_17th/blog/static/4856418920085209414977/该网站给出了解决方法。
后续:研究在kernel6中如何使用creatRemoteThread实现dll注入。
远程线程技术指的是通过在另一个进程中创建远程线程的方法进入那个进程的内存地址空间。我们知道,在进程中,可以通过CreateThread函数创建线程,被创建的新线程与主线程共享地址空间以及其他的资源。但是很少有人知道,通过CreateRemoteThread也同样可以在另一个进程内创建新线程,被创建的远程线程同样可以共享远程进程(是远程进程耶!)的地址空间,所以,实际上,我们通过一个远程线程,进入了远程进程的内存地址空间,也就拥有了那个远程进程相当的权限。例如在远程进程内部启动一个DLL木马。
下面贴一下实验代码
myhack.cpp: 待注入的dll文件代码(VS2010编译通过,得到myhack.dll)
#include "windows.h" BOOL APIENTRY DllMain(HANDLE hMoudle,DWORD reason,LPVOID lpReserved) { switch(reason) { case DLL_PROCESS_ATTACH: MessageBox(NULL,L"this is a test!",L"Success",MB_OK); break; default: return TRUE; } }inject.cpp:inject.exe将myhack,dll注入到目标进程
#include "windows.h" #include "stdlib.h" #include "stdio.h" #include "tlhelp32.h" DWORD ProcessNameToPID(char Name[20]);//将进程名转化成PID VOID EnableDebugPriv() //提权函数,如果不加此函数,再调用openprocess时会报错,使用getlasterror得知错误号为5(权限不够) { HANDLE hToken; LUID sedebugnameValue; TOKEN_PRIVILEGES tkp; OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue); tkp.PrivilegeCount = 1; tkp.Privileges[0].Luid = sedebugnameValue; tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken, false, &tkp, sizeof tkp, NULL, NULL); CloseHandle(hToken); } int main() { DWORD pdwProcessId; WCHAR pszLibFileName[MAX_PATH]={0}; char lpDllFullPathName[MAX_PATH],ProcessName[20]; HANDLE hRemoteThread,hRemoteProcess; PWSTR pszLibFileRemote=NULL; printf("请输入进程名称:\n"); scanf("%s",ProcessName); printf("请输入dll地址:\n"); scanf("%s",lpDllFullPathName); MultiByteToWideChar(CP_ACP,MB_ERR_INVALID_CHARS,lpDllFullPathName,strlen(lpDllFullPathName),pszLibFileName,MAX_PATH); if((pdwProcessId=ProcessNameToPID(ProcessName))==-1) return 0; EnableDebugPriv(); hRemoteProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,pdwProcessId);//打开被注入进程 if (hRemoteProcess==NULL) { DWORD testerror = GetLastError(); printf("%u\n",testerror); printf("OpenProcess Error\n"); scanf("%s",ProcessName); return 0; } int cb=(1+lstrlenW(pszLibFileName))*sizeof(WCHAR); pszLibFileRemote=(PWSTR)VirtualAllocEx(hRemoteProcess,NULL,cb,MEM_COMMIT,PAGE_EXECUTE_READWRITE);//开辟内存 if (pszLibFileRemote==NULL) { printf("VirtualAllocEx Error\n"); scanf("%s",ProcessName); return 0; } if(!WriteProcessMemory(hRemoteProcess,(PVOID)pszLibFileRemote,(PVOID)pszLibFileName,cb,NULL))//将dll模块名称写入被注入进程作为私有变量可供目标进程使用 { printf("WriteProcessMemory Error %d\n",GetLastError()); scanf("%s",ProcessName); return 0; } PTHREAD_START_ROUTINE pfnStartAddr=(PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle(TEXT("kernel32")),"LoadLibraryW");//获得LoadLibraryW地址 if(pfnStartAddr==NULL) { printf("pfnStartAddr Error\n"); } //创建远程线程,线程回调函数就是LoadLibraryW,pszLibFileRemote中的dll路径作为LoadLibraryW的唯一参数传入 hRemoteThread=CreateRemoteThread(hRemoteProcess,NULL,0,pfnStartAddr,pszLibFileRemote,0,NULL); if (hRemoteThread==NULL) { printf("CreatRemoteThread Error\n"); scanf("%s",ProcessName); return 0; } scanf("%s",ProcessName); return -1; } DWORD ProcessNameToPID(char Name[20]) //进程遍历就不用多说了把,方法多的是 { PROCESSENTRY32 pe32; pe32.dwSize=sizeof(pe32); HANDLE hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0) ; if(hProcessSnap==INVALID_HANDLE_VALUE) { printf("CreateToolhelp32Snapshot fuild!\n"); return -1; } BOOL bMore=Process32First(hProcessSnap,&pe32); while(bMore) { size_t len = wcslen(pe32.szExeFile)+1; size_t converted = 0; char * Cstr; Cstr = (char *)malloc(len*sizeof(char)); wcstombs_s(&converted,Cstr,len,pe32.szExeFile,_TRUNCATE); if (!strcmp(Name,Cstr)) { printf("find it %d\n",pe32.th32ProcessID); return pe32.th32ProcessID; } bMore=Process32Next(hProcessSnap,&pe32); } CloseHandle(hProcessSnap); return -1; }
下面是在win8上跑,不通过。
开xp虚拟机再跑一下:
记事本弹窗,success,这就是注入的dll。
思考:为什么在win8上该程序不能成功注入dll文件?
解答:windows从kernel6(vista,7,8)开始采用全新的会话管理机制,这使得通过creatremotethread()API注入dll的旧方法对某些进程(服务进程)不在适用。
试验中遇到的问题:关于WCHAR * 与char *的转化。http://blog.163.com/tianshi_17th/blog/static/4856418920085209414977/该网站给出了解决方法。
后续:研究在kernel6中如何使用creatRemoteThread实现dll注入。
相关文章推荐
- App更新策略课程-检查更新
- 【bzoj4296】【PA2015】【Mistrzostwa】【bfs+dfs】
- Pycharm及Sublime Text输出中文
- JS实现循环给元素绑定事件的几个常用方法
- ubuntu14.04 64位 jd-gui
- poj 1125 Stockbroker Grapevine
- spring mvc 上传文件
- netfilter入门
- MVC表单
- 【eclipse插件开发】右键菜单获取选中文件以及文件的创建
- ubuntu中source,sh/bash,./的区别
- LightOJ 1245 Harmonic Number (II) 水题
- linux安装nginx
- 系统的平均并发用户数和并发数峰值如何估算
- Python学习笔记(六)
- CCF参赛感悟
- android之对话框<一>
- 关于Markdown编辑器
- CSS块级元素、内联元素概念
- 带武器角色类