SHARE
TWEET

CodeMon copy module bypass

ahcript Apr 15th, 2017 (edited) 57 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /*
  2. CodeMon copy module bypass
  3. Credit to mcrypt. http://mcrypt.hatenablog.com/
  4. */
  5.  
  6. /*=================== File: CodeMonL.hpp ===================*/
  7. #pragma once
  8.  
  9. #include <map>
  10.  
  11. typedef struct _MODULE_CONTEXT
  12. {
  13.     PVOID ImageBase[3];
  14.     PVOID BaseOfCode[3];
  15.     DWORD SizeOfImage;
  16.     PVOID OriginalImage;
  17.     WCHAR ImageName[MAX_PATH];
  18. }MODULE_CONTEXT, far *LPMODULE_CONTEXT, near *PMODULE_CONTEXT, MODULE_CTX, far *LPMODULE_CTX, near *PMODULE_CTX;
  19.  
  20. class CodeMonL
  21. {
  22. public:
  23.     CodeMonL();
  24.     ~CodeMonL();
  25.  
  26. publuc:
  27.     BOOL InitializeModuleContext(__in LPVOID lpBuffer, __in DWORD dwSize);
  28.     BOOL FindModuleContext(__in LPVOID lpBuffer, __out LPVOID* lppvTarget, __out LPVOID* lppvOriginal);
  29.     BOOL JmpToOriginalModule(__in LPVOID lpvTarget, __in LPVOID lpvOriginal);
  30.  
  31.     static CodeMonL *GetInstance()
  32.     {
  33.         static CodeMonL instance;
  34.         return &instance;
  35.     }
  36.  
  37. private:
  38.     BOOL SetModuleContext(__in LPVOID lpvOriginal, __in LPVOID lpvTarget, __in DWORD dwSize, __inout_opt MODULE_CONTEXT *pContext, __in DWORD dwBaseOfCodeOffset = 0x1000);
  39.     MODULE_CONTEXT m_mCTX[9];
  40. };
  41.  
  42. /*=================== File: CodeMonL.cpp ===================*/
  43. #include "stdafx.h"
  44.  
  45. #include "CodeMonL.hpp"
  46. #include "utils.hpp"
  47.  
  48. CodeMonL::CodeMonL()
  49. {
  50. }
  51. CodeMonL::~CodeMonL()
  52. {
  53. }
  54.  
  55. BOOL CodeMonL::SetModuleContext(__in LPVOID lpvOriginal, __in LPVOID lpvTarget, __in DWORD dwSize, __inout_opt MODULE_CONTEXT *pContext, __in DWORD dwBaseOfCode)
  56. {
  57.     int i;
  58.  
  59.     for (i = 0; i < 3; i++)
  60.     {
  61.         if (pContext->ImageBase[i] == NULL) continue;
  62.         break;
  63.     }
  64.  
  65.     pContext->BaseOfCode[i] = (PBYTE)lpvTarget + dwBaseOfCode;
  66.     pContext->ImageBase[i]  = lpvTarget;
  67.     pContext->SizeOfImage   = dwSize;
  68.     pContext->OriginalImage = lpvOriginal;
  69.  
  70.     TCHAR szFilename[MAX_PATH];
  71.     GetModuleFileName((HMODULE)lpvOriginal, szFilename, MAX_PATH);
  72.     StringCchPrintf(pContext->ImageName, _countof(szFilename), _T("%s"), szFilename);
  73.  
  74.     return TRUE;
  75. }
  76.  
  77. BOOL CodeMonL::InitializeModuleContext(__in LPVOID lpBuffer, __in DWORD dwSize)
  78. {
  79.     if (lpBuffer == NULL || dwSize == NULL)
  80.         return FALSE;
  81.  
  82.     switch (dwSize)
  83.     {
  84.         case 0x0017B000: // ntdll
  85.         {
  86.             SetModuleContext(GetModuleHandle(L"NTDLL"), lpBuffer, dwSize, &m_mCTX[0]);
  87.             break;
  88.         }
  89.         case 0x0017E000: // kernelbase
  90.         {
  91.             SetModuleContext(GetModuleHandle(L"KERNELBASE"), lpBuffer, dwSize, &m_mCTX[1]);
  92.             break;
  93.         }
  94.         case 0x0005F000: // ws2_32
  95.         {
  96.             SetModuleContext(GetModuleHandle(L"WS2_32"), lpBuffer, dwSize, &m_mCTX[2]);
  97.             break;
  98.         }
  99.         case 0x000E0000: // kernel32
  100.         {
  101.             SetModuleContext(GetModuleHandle(L"KERNEL32"), lpBuffer, dwSize, &m_mCTX[3], 0x00010000);
  102.             break;
  103.         }
  104.         case 0x00024000: // winmm
  105.         {
  106.             SetModuleContext(GetModuleHandle(L"WINMM"), lpBuffer, dwSize, &m_mCTX[4]);
  107.             break;
  108.         }
  109.         case 0x00147000: // user32
  110.         {
  111.             SetModuleContext(GetModuleHandle(L"USER32"), lpBuffer, dwSize, &m_mCTX[5]);
  112.             break;
  113.         }
  114.         case 0x0014F000: // gdi32
  115.         {
  116.             SetModuleContext(GetModuleHandle(L"GDI32"), lpBuffer, dwSize, &m_mCTX[6]);
  117.             break;
  118.         }
  119.         case 0x001BD000: // combase
  120.         {
  121.             SetModuleContext(GetModuleHandle(L"COMBASE"), lpBuffer, dwSize, &m_mCTX[7]);
  122.             break;
  123.         }
  124.         case 0x00277000: // wininet
  125.         {
  126.             SetModuleContext(GetModuleHandle(L"WININET"), lpBuffer, dwSize, &m_mCTX[8]);
  127.             break;
  128.         }
  129.         default:
  130.         {
  131. #ifdef _DEBUG
  132.             if (dwSize >= 0x00010000)
  133.             {
  134.                 LogOutput(L"[%s] lpBuffer = %p, dwSize = %p \n", __FUNCTIONW__, lpBuffer, dwSize);
  135.             }
  136. #endif
  137.             return FALSE;
  138.         }
  139.     }
  140.  
  141.     return TRUE;
  142. }
  143.  
  144. BOOL CodeMonL::FindModuleContext(__in LPVOID lpBuffer, __out LPVOID* lppvTarget, __out LPVOID* lppvOriginal)
  145. {
  146.     if (!lpBuffer)
  147.         return FALSE;
  148.  
  149.     for (int i = 0; i < 9; i++)
  150.     {
  151.         // 3回コピーされるので 3
  152.         for (int j = 0; j < 3; j++)
  153.         {
  154.             if (lpBuffer != m_mCTX[i].BaseOfCode[j])
  155.                 continue;
  156.  
  157.             if (m_mCTX[i].ImageBase[j] == NULL)
  158.                 continue;
  159.  
  160.             *lppvTarget = m_mCTX[i].ImageBase[j];
  161.             *lppvOriginal = m_mCTX[i].OriginalImage;
  162.  
  163.             return TRUE;
  164.         }
  165.     }
  166.  
  167.     return FALSE;
  168. }
  169.  
  170. BOOL CodeMonL::JmpToOriginalModule(__in LPVOID lpvTarget, __in LPVOID lpvOriginal)
  171. {
  172.     if (!lpvModule || !lpvOriginal)
  173.         return FALSE;
  174.  
  175.     LPDWORD pName, pNameOriginal;
  176.     LPDWORD pFunc, pFuncOriginal;
  177.     LPWORD pOrdinal, pOrdinalOriginal;
  178.  
  179.     // Copy
  180.     IMAGE_NT_HEADERS32 *pNtHeaders = reinterpret_cast<IMAGE_NT_HEADERS32*>(reinterpret_cast<PBYTE>(lpvTarget) + PIMAGE_DOS_HEADER(lpvTarget)->e_lfanew);
  181.     IMAGE_EXPORT_DIRECTORY *pExports = reinterpret_cast<IMAGE_EXPORT_DIRECTORY*>(reinterpret_cast<PBYTE>(lpvTarget) + pNtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
  182.  
  183.     // Original
  184.     IMAGE_NT_HEADERS32 *pNtHeadersOriginal = reinterpret_cast<IMAGE_NT_HEADERS32*>(reinterpret_cast<PBYTE>(lpvOriginal) + PIMAGE_DOS_HEADER(lpvOriginal)->e_lfanew);
  185.     IMAGE_EXPORT_DIRECTORY *pExportsOriginal = reinterpret_cast<IMAGE_EXPORT_DIRECTORY*>(reinterpret_cast<PBYTE>(lpvOriginal) + pNtHeadersOriginal->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
  186.  
  187.     if (pNtHeaders && pExports
  188.         && pNtHeadersOriginal && pExportsOriginal)
  189.     {
  190.         // Copy
  191.         pName = reinterpret_cast<LPDWORD>(reinterpret_cast<PBYTE>(lpvTarget) + pExports->AddressOfNames);
  192.         pFunc = reinterpret_cast<LPDWORD>(reinterpret_cast<PBYTE>(lpvTarget) + pExports->AddressOfFunctions);
  193.         pOrdinal = reinterpret_cast<LPWORD>(reinterpret_cast<PBYTE>(lpvTarget) + pExports->AddressOfNameOrdinals);
  194.  
  195.         // Original
  196.         pNameOriginal = reinterpret_cast<LPDWORD>(reinterpret_cast<PBYTE>(lpvOriginal) + pExportsOriginal->AddressOfNames);
  197.         pFuncOriginal = reinterpret_cast<LPDWORD>(reinterpret_cast<PBYTE>(lpvOriginal) + pExportsOriginal->AddressOfFunctions);
  198.         pOrdinalOriginal = reinterpret_cast<LPWORD>(reinterpret_cast<PBYTE>(lpvOriginal) + pExportsOriginal->AddressOfNameOrdinals);
  199.  
  200.         // コピーされたDLLの各APIをオリジナルのDLLの各APIに飛ばす(jmp)
  201.         for (int i = 0; i < pExports->NumberOfNames; i++)
  202.         {
  203.             WORD w = pOrdinal[i];
  204.             WORD wo = pOrdinalOriginal[i];
  205.             LPVOID lpvFunction = reinterpret_cast<LPVOID>(reinterpret_cast<PBYTE>(lpvTarget) + pFunc[w]);
  206.             LPVOID lpvFuncOriginal = reinterpret_cast<LPVOID>(reinterpret_cast<PBYTE>(lpvOriginal) + pFuncOriginal[wo]);
  207.             LPSTR pszName = reinterpret_cast<LPSTR>(reinterpret_cast<PBYTE>(lpvOriginal) + pNameOriginal[i]);
  208.  
  209.             DetourFunction(TRUE, reinterpret_cast<LPVOID*>(&lpvFunction), lpvFuncOriginal);
  210.         }
  211.  
  212.         return TRUE;
  213.     }
  214.  
  215.     return FALSE;
  216. }
  217.  
  218. /*=================== File: Bypass.cpp ===================*/
  219.  
  220. VOID Detour_o_o()
  221. {
  222.     typedef LPVOID(WINAPI *pfnVirtualAlloc)(
  223.         _In_opt_ LPVOID lpAddress,
  224.         _In_     SIZE_T dwSize,
  225.         _In_     DWORD  flAllocationType,
  226.         _In_     DWORD  flProtect);
  227.  
  228.     typedef BOOL(WINAPI *pfnVirtualProtect)(
  229.         _In_  LPVOID lpAddress,
  230.         _In_  SIZE_T dwSize,
  231.         _In_  DWORD  flNewProtect,
  232.         _Out_ PDWORD lpflOldProtect);
  233.  
  234.     static pfnVirtualAlloc _VirtualAlloc =
  235.         reinterpret_cast<pfnVirtualAlloc>(GetProcAddress(GetModuleHandle(L"KERNELBASE.dll"), "VirtualAlloc"));
  236.     pfnVirtualAlloc VirtualAlloc_Hook = [](
  237.         _In_opt_ LPVOID lpAddress,
  238.         _In_     SIZE_T dwSize,
  239.         _In_     DWORD  flAllocationType,
  240.         _In_     DWORD  flProtect) -> LPVOID
  241.     {
  242.         LPVOID lpBuffer = _VirtualAlloc(lpAddress, dwSize, flAllocationType, flProtect);
  243.         if (lpBuffer)
  244.         {
  245.             CodeMonL::GetInstance()->InitializeModuleContext(lpBuffer, dwSize);
  246.         }
  247.  
  248.         return lpBuffer;
  249.     };
  250.  
  251.     static pfnVirtualProtect _VirtualProtect =
  252.         reinterpret_cast<pfnVirtualProtect>(GetProcAddress(GetModuleHandle(L"KERNELBASE.dll"), "VirtualProtect"));
  253.     pfnVirtualProtect VirtualProtect_Hook = [](
  254.         _In_  LPVOID lpAddress,
  255.         _In_  SIZE_T dwSize,
  256.         _In_  DWORD  flNewProtect,
  257.         _Out_ PDWORD lpflOldProtect) -> BOOL
  258.     {
  259.         CodeMonL *pCodeMonL = CodeMonL::GetInstance();
  260.         LPVOID lpvTarget, lpvOriginal;
  261.  
  262.         if (pCodeMonL->FindModuleContext(lpAddress, &lpvTarget, &lpvOriginal))
  263.             if (lpvTarget && lpvOriginal)
  264.                 pCodeMonL->JmpToOriginalModule(lpvTarget, lpvOriginal);
  265.  
  266.         return _VirtualProtect(lpAddress, dwSize, flNewProtect, lpflOldProtect);
  267.     };
  268.  
  269.     DetourFunction(TRUE, reinterpret_cast<LPVOID*>(&_VirtualAlloc), VirtualAlloc_Hook);
  270.     DetourFunction(TRUE, reinterpret_cast<LPVOID*>(&_VirtualProtect), VirtualProtect_Hook);
  271. }
RAW Paste Data
Top