源碼解析一種無模組注入進程方法

來源:互聯網
上載者:User

標籤:pe 無模組 注入 dll

    對windows安全比較熟悉的同學對模組注入應該都比較瞭解,很多病毒、木馬、外掛都會用到,無模組注入應用得則比較少。

     無模組注入的好處是DLL注入進去後,確實已經不以模組的形式存在了,用任何進程模組查看工具,都找不到注入進去的DLL。因為它已經變為一塊純堆記憶體,跟EXE主模組裡申請的堆沒有任何差別。

     這裡講的一種無模組注入的方法,能夠讓DLL自身實現這樣的功能,無需外部注入工具協助處理。當然如果進程內自行載入這樣的DLL後,也是以無模組DLL形式存在。

     注入完成後,進程內找不到注入的模組存在,用Dbgview每5秒可以看到"No Module Thread"訊息列印出來,表示無模組DLL內進程的活動

     之前這個方法有在看雪發表過,不過沒有詳細講,有的同學不是很明白,這裡把源碼貼出來,加上注釋,應該會比較清楚了。

        LoadPE.CPP

"No Module Thread"//coded by 燕十二#include "stdafx.h"#include <stdio.h>//將DLL檔案讀到記憶體BOOL LoadDll2Mem(PVOID &pAllocMem,DWORD &dwMemSize,char* strFileName)  {  HANDLE hFile = CreateFileA(strFileName, GENERIC_READ,  FILE_SHARE_READ, NULL,  OPEN_EXISTING,  FILE_ATTRIBUTE_NORMAL, NULL);  if (INVALID_HANDLE_VALUE == hFile) {  return FALSE;  }  PVOID pFileBuff = NULL;int nFileSize = GetFileSize(hFile, NULL);  if (nFileSize == 0){return FALSE;}else{pFileBuff = VirtualAlloc(NULL,nFileSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);}DWORD dwReadSize = 0;if (!ReadFile(hFile, pFileBuff, nFileSize, &dwReadSize, NULL)) {  return FALSE; }PVOID pBase = pFileBuff;//判斷是否是PEPIMAGE_DOS_HEADER pIDH = (PIMAGE_DOS_HEADER)pFileBuff;if (IMAGE_DOS_SIGNATURE != pIDH->e_magic) {  return FALSE;  }  PIMAGE_NT_HEADERS pINH = (PIMAGE_NT_HEADERS)((ULONG)pFileBuff + pIDH->e_lfanew);if (IMAGE_NT_SIGNATURE != pINH->Signature) {  return FALSE;  }  dwMemSize = nFileSize;pAllocMem = pFileBuff;      return TRUE;  }  //將DLL檔案按section資訊構建記憶體,重新對齊填充各section,並自行計算填充匯入表BOOL PELoader(char *lpStaticPEBuff, PVOID& pExecuMem){  long lPESignOffset = *(long *)(lpStaticPEBuff + 0x3c);  IMAGE_NT_HEADERS *pINH = (IMAGE_NT_HEADERS *)(lpStaticPEBuff + lPESignOffset);  long lImageSize = pINH->OptionalHeader.SizeOfImage;  char *lpDynPEBuff = (char *)VirtualAlloc(NULL,lImageSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);  if(lpDynPEBuff == NULL)  {    return FALSE;  }  memset(lpDynPEBuff, 0, lImageSize);  long lSectionNum = pINH->FileHeader.NumberOfSections;  IMAGE_SECTION_HEADER *pISH = (IMAGE_SECTION_HEADER *)((char *)pINH + sizeof(IMAGE_NT_HEADERS));    memcpy(lpDynPEBuff, lpStaticPEBuff, pISH->VirtualAddress);  long lFileAlignMask = pINH->OptionalHeader.FileAlignment - 1;          long lSectionAlignMask = pINH->OptionalHeader.SectionAlignment - 1;      for(int nIndex = 0; nIndex < lSectionNum; nIndex++, pISH++)  {    memcpy(lpDynPEBuff + pISH->VirtualAddress, lpStaticPEBuff + pISH->PointerToRawData, pISH->SizeOfRawData);  }  if(pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size > 0)  {    IMAGE_IMPORT_DESCRIPTOR *pIID = (IMAGE_IMPORT_DESCRIPTOR *)(lpDynPEBuff +       pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);    for(; pIID->Name != NULL; pIID++)    {      IMAGE_THUNK_DATA *pITD = (IMAGE_THUNK_DATA *)(lpDynPEBuff + pIID->FirstThunk);  char* pLoadName = lpDynPEBuff + pIID->Name;      HINSTANCE hInstance = LoadLibrary(pLoadName);      if(hInstance == NULL)      {VirtualFree(lpDynPEBuff,lImageSize,MEM_DECOMMIT);        return FALSE;      }      for(; pITD->u1.Ordinal != 0; pITD++)      {        FARPROC fpFun;        if(pITD->u1.Ordinal & IMAGE_ORDINAL_FLAG32)        {          fpFun = GetProcAddress(hInstance, (LPCSTR)(pITD->u1.Ordinal & 0x0000ffff));        }        else        {          IMAGE_IMPORT_BY_NAME * pIIBN = (IMAGE_IMPORT_BY_NAME *)(lpDynPEBuff + pITD->u1.Ordinal);          fpFun = GetProcAddress(hInstance, (LPCSTR)pIIBN->Name);        }        if(fpFun == NULL)        {          delete lpDynPEBuff;          return false;        }        pITD->u1.Ordinal = (long)fpFun;      }    }  }  if(pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size > 0)  {    IMAGE_BASE_RELOCATION *pIBR = (IMAGE_BASE_RELOCATION *)(lpDynPEBuff +       pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);    long lDifference = (long)lpDynPEBuff - pINH->OptionalHeader.ImageBase;    for(; pIBR->VirtualAddress != 0; )    {      char *lpMemPage = lpDynPEBuff + pIBR->VirtualAddress;      long lCount = (pIBR->SizeOfBlock - sizeof(IMAGE_BASE_RELOCATION)) >> 1;      short int *pRelocationItem = (short int *)((char *)pIBR + sizeof(IMAGE_BASE_RELOCATION));      for(int nIndex = 0; nIndex < lCount; nIndex++)      {        int nOffset = pRelocationItem[nIndex] & 0x0fff;        int nType = pRelocationItem[nIndex] >> 12;        if(nType == 3)        {          *(long *)(lpMemPage + nOffset) += lDifference;        }        else if(nType == 0)        {        }      }      pIBR = (IMAGE_BASE_RELOCATION *)(pRelocationItem + lCount);    }  }  pExecuMem = lpDynPEBuff;  return true;} typedef BOOL  (WINAPI *DLL_MAIN)( HMODULE hModule,DWORD  ul_reason_for_call,LPVOID lpReserved);//通過PE資訊擷取EP作為入口函數,並運行,這裡把dwReaseon設定為NO_MODULE_MARK,保留參數設定為模組的路徑//相當於再次以(hModule,NO_MODULE_MARK,pModuleName)為參數,調用一次原始的DllMain函數bool CallDllMain(PVOID pExecMem,DWORD dwReaseon,char* pModuleName){PIMAGE_NT_HEADERS pINH = (PIMAGE_NT_HEADERS)((ULONG)pExecMem + ((PIMAGE_DOS_HEADER)pExecMem)->e_lfanew);DWORD dwEP = pINH->OptionalHeader.AddressOfEntryPoint;DLL_MAIN lpDllMain = (DLL_MAIN)((DWORD)pExecMem + dwEP);lpDllMain((HMODULE)pExecMem,dwReaseon,pModuleName);return TRUE;}BOOL LaunchDll(char *strName,DWORD dwReason){PVOID pRelocMem = NULL;PVOID pExecuMem = NULL;DWORD dwMemSize = 0;if (LoadDll2Mem(pRelocMem,dwMemSize,strName)){PELoader((char *)pRelocMem,pExecuMem);CallDllMain(pExecuMem,dwReason,strName);ZeroMemory(pRelocMem,dwMemSize);VirtualFree(pRelocMem,dwMemSize,MEM_DECOMMIT);}return TRUE;}

TestDll.cpp

// TestDll.cpp : Defines the entry point for the DLL application.//Coded by  燕十二#include "stdafx.h"#include "LoadPE.h"//防止無模組DLL多次注入BOOL IsMutexExist(char* pstrMutex){BOOL bRet = FALSE;HANDLE hMutex = NULL; hMutex = CreateMutexA(NULL, TRUE, pstrMutex);if ( hMutex ){if ( GetLastError() == ERROR_ALREADY_EXISTS )bRet = TRUE;ReleaseMutex(hMutex);CloseHandle(hMutex);}else{bRet = TRUE;}return bRet;}//調用LoadPE.cpp裡的函數,自行處理PE載入,把DLL在新申請的記憶體載入起來,並執行入口函數void LaunchNoModule(){LaunchDll(dllModuleName,NO_MODULE_MARK);}unsigned int  __stdcall NoModuleThread(void* lpParameter){while (TRUE){Sleep(5000);OutputDebugString("No Module Thread");}return TRUE;}//開啟一個線程,調用實際的DLL功能代碼void NoModuleEntryCall(HMODULE hModule, DWORD ul_reason_for_call, char* pstrModuleName){char szMutexName[MAX_PATH];wsprintf(szMutexName,"yanshier2013nomoduleinject%d",GetCurrentProcessId());g_hMutex = CreateMutex(NULL, TRUE, szMutexName);char szLog[MAX_PATH] = {0};wsprintf(szLog,"NoModuleEntryCall Module Start:%p",hModule);OutputDebugString(szLog);//下面為正常Dll功能代碼CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)NoModuleThread,NULL,NULL,NULL);}BOOL ChooseSub(HMODULE hModule, DWORD ul_reason_for_call, char* pstrModuleName){BOOL bRet = FALSE;GetModuleFileNameA(NULL, exeModuleName, MAX_PATH);if ( ul_reason_for_call == NO_MODULE_MARK )strcpy(dllModuleName, pstrModuleName);elseGetModuleFileName(hModule, dllModuleName, MAX_PATH);if ( ul_reason_for_call == NO_MODULE_MARK ){NoModuleEntryCall(hModule, DLL_PROCESS_ATTACH, 0);bRet = TRUE;}else{LaunchNoModule();bRet = FALSE;}return bRet;}//ul_reason_for_call等於NO_MODULE_MARK時,DllMain已經是在新申請的記憶體中運行//DllMain傳回值是個很關鍵的地方,可能平常寫DLLMain的時候不會注意到,都是直接返回TRUE,沒有去關注FALSE的情況//ul_reason_for_call等於DLL_PROCESS_ATTACH時,DllMain返回FALSE會使DLL自行卸載//利用這一點再結合PE自行載入,就可以實現無模組注入了//當然,這樣的DLL,如果由程式內部載入,也是以無模組的形式存在的BOOL APIENTRY DllMain( HMODULE hModule,                       DWORD  ul_reason_for_call,                       LPVOID lpReserved ){BOOL  bRet = FALSE;if ( ul_reason_for_call == DLL_PROCESS_ATTACH || ul_reason_for_call == NO_MODULE_MARK ){char szMutexName[MAX_PATH];wsprintf(szMutexName,"yanshier2013nomoduleinject%d",GetCurrentProcessId());if ( IsMutexExist(szMutexName))return FALSE;bRet = ChooseSub(hModule, ul_reason_for_call, (char *)lpReserved);}else{if ( ul_reason_for_call ==  DLL_PROCESS_DETACH){ReleaseMutex(g_hMutex);CloseHandle(g_hMutex);bRet = TRUE;}}return bRet;}

 源碼下載見附件

本文出自 “燕十二” 部落格,請務必保留此出處http://chenjava.blog.51cto.com/374566/1574442

源碼解析一種無模組注入進程方法

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.