めいくりぷとのブログ

技術的なことやゲームのことやら・・・

PEBを用いたモジュール隠蔽 + α

PEBを理解するために適当に書いたコードです。

///////////////////////////////////////////////////////////
// peb.hpp
///////////////////////////////////////////////////////////
#pragma once
 
#ifndef Padding
#define Padding(x) struct { unsigned char __padding##x[(x)]; };
#endif
 
typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
 
typedef struct _PEB_LDR_DATA
{
    Padding(0x0C);
    LIST_ENTRY InLoadOrderModuleList; // 0x0c
    LIST_ENTRY InMemoryOrderModuleList; // 0x14
    LIST_ENTRY InInitializationOrderModuleList; // 0x1c
}PEB_LDR_DATA, PPEB_LDR_DATA;
 
typedef struct _PEB
{
#ifdef _WIN64
    Padding(0x18);
#else
    Padding(0x0C);
#endif
    PEB_LDR_DATA* Ldr;
}PEB, *PPEB;
 
typedef struct _LDR_DATA_TABLE_ENTRY
{
    LIST_ENTRY            InLoadOrderModuleList;
    LIST_ENTRY            InMemoryOrderModuleList;
    LIST_ENTRY            InInitializationOrderModuleList;
    PVOID                 BaseAddress;
    PVOID                 EntryPoint;
    ULONG                 SizeOfImage;
    UNICODE_STRING        FullDllName;
    UNICODE_STRING        BaseDllName;
    ULONG                 Flags;
    USHORT                LoadCount;
    USHORT                TlsIndex;
    LIST_ENTRY            HashTableEntry;
    union
    {
        LIST_ENTRY HashLinks;
        struct
        {
            PVOID SectionPointer;
            ULONG CheckSum;
        };
    };
    union
    {
        ULONG TimeDateStamp;
        PVOID LoadedImports;
    };
    _ACTIVATION_CONTEXT *   EntryPointActivationContext;
    PVOID                   PatchInformation;
    LIST_ENTRY              ForwarderLinks;
    LIST_ENTRY              ServiceTagLinks;
    LIST_ENTRY              StaticLinks;
    PVOID                   ContextInformation;
    DWORD                   OriginalBase;
    LARGE_INTEGER           LoadTime;
} LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY;
///////////////////////////////////////////////////////////
// dllmain.cpp
///////////////////////////////////////////////////////////
 
#include "stdafx.h"
 
#include "peb.hpp"
#include <algorithm>
 
#define UNLINK(x)                   \
    (x).Flink->Blink = (x).Blink;   \
    (x).Blink->Flink = (x).Flink;
 
// hide module
VOID WINAPI HideModule(__in HMODULE hModule)
{
#ifdef _WIN64
    PEB *pPEB = reinterpret_cast<PEB*>(__readfsqword(0x60));
#else
    PEB *pPEB = reinterpret_cast<PEB*>(__readfsdword(0x30));
#endif
 
    PLDR_DATA_TABLE_ENTRY pData;
    PLIST_ENTRY           pEntry;
 
    pEntry = pPEB->Ldr->InLoadOrderModuleList.Flink;
 
    while (pEntry != &pPEB->Ldr->InLoadOrderModuleList &&
        pEntry != NULL)
    {
        pData = CONTAINING_RECORD(pEntry, LDR_DATA_TABLE_ENTRY, InLoadOrderModuleList);
 
        if (pData->BaseAddress == hModule)
        {
#ifdef _DEBUG
            _tprintf(TEXT("\nDll name: %s \nBase: %08X \nEntryPoint: %08X \n"),
                pData->BaseDllName.Buffer, pData->BaseAddress, pData->EntryPoint);
#endif
 
            UNLINK(pData->InLoadOrderModuleList);
            UNLINK(pData->InInitializationOrderModuleList);
            UNLINK(pData->InMemoryOrderModuleList);
        }
 
        pEntry = pEntry->Flink;
    }
}
 
// remove pe header
VOID WINAPI EraseHeaders(__in HMODULE hModule)
{
    DWORD i, size, protect;
 
    IMAGE_DOS_HEADER *pDosHeader = PIMAGE_DOS_HEADER(hModule);
    IMAGE_NT_HEADERS *pNtHeaders = reinterpret_cast<IMAGE_NT_HEADERS*>(reinterpret_cast<PBYTE>(hModule) + pDosHeader->e_lfanew);
 
    size = sizeof(IMAGE_DOS_HEADER);
 
    if (VirtualProtect(pDosHeader, size, PAGE_READWRITE, &protect))
    {
        for (i = 0; i < size; i++)
            *(BYTE*)((BYTE*)pDosHeader + i) = 0x00;
    }
 
    size = sizeof(IMAGE_NT_HEADERS);
 
    if (pNtHeaders && VirtualProtect(pNtHeaders, size, PAGE_READWRITE, &protect))
    {
        for (i = 0; i < size; i++)
            *(BYTE*)((BYTE*)pNtHeaders + i) = 0x00;
    }
}

終わり。