找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 7571|回复: 2

实现自己的LoadLibrary

[复制链接]
发表于 2015-6-15 00:05:41 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
决定实现自己的loadlibrary,已经实现大部分,然而在模拟执行dllmain时却发生异常,查找发现加载的dll导入表没有初始化。
不明白这段代码在哪里实现的,正在研究中,功亏一篑啊
该代码完全独立于ldr结构,并用map结构一次映射所有函数,不需要getproc一个个进行查找,LoadLibary只需要传入完整dll路径
GetProcAddress只需要dll路径以及函数名即可获得函数地址,这部分功能测试正常,500行代码

而输出表部分,很奇怪,懂得高人指点一下:
#include <windows.h>
#include <winternl.h>
#include <map>
#include <string>
using namespace std;

#if defined(WIN64) || defined(_WIN64)
#pragma comment(lib,"ntdll64.lib")
#else
#pragma comment(lib,"ntdll.lib")
#endif

#if defined(UNICODE) || defined(_UNICODE)
#define GetProcAddressT GetProcAddressTW
#define LoadLibraryT LoadLibraryTW
#define FreeLibraryT FreeLibraryTW
#else
#define GetProcAddressT GetProcAddressTA
#define LoadLibraryT LoadLibraryTA
#define FreeLibraryT FreeLibraryTA
#endif

extern "C"
{
    BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(PCWSTR,PUNICODE_STRING,PCWSTR*,PVOID*);
    NTSTATUS WINAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG,SIZE_T,const LARGE_INTEGER*,SIZE_T*,ULONG,ULONG,ULONG);
    BOOLEAN WINAPI RtlFreeHeap(PVOID,ULONG,PVOID);
    NTSTATUS WINAPI NtCreateSection(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PLARGE_INTEGER,ULONG,ULONG,HANDLE);
    NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID);
    NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE,PVOID,PSIZE_T,ULONG,PULONG);
    NTSTATUS WINAPI NtFlushInstructionCache(HANDLE,PVOID,ULONG);
};

ULONG NTAPI LdrRelocateImageWithBias(PVOID,PIMAGE_NT_HEADERS,LONGLONG ,PCCH,ULONG,ULONG,ULONG);
NTSTATUS NTAPI LdrpSetProtection(PVOID,PIMAGE_NT_HEADERS,BOOLEAN);

#define STATUS_IMAGE_NOT_AT_BASE ((NTSTATUS)0x40000003L)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 
#define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS)0xC0000018L)
#define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS)0xC000007BL)

typedef struct _CLIENT_ID 
{
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
} CLIENT_ID;

typedef struct _MTEB 
{ 
    _NT_TIB NtTib; 
    PVOID EnvironmentPointer; 
    CLIENT_ID ClientId;
    PVOID ActiveRpcHandle;
    PVOID ThreadLocalStoragePointer;
    PPEB Peb;
}MTEB,*PMTEB;

typedef struct _MPEB
{
    DWORD flags;
    PVOID Mutant;
    PVOID ImageBaseAddress;
    PPEB_LDR_DATA Ldr;
    PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
    PVOID SubSystemData;
    PVOID ProcessHeap;
}MPEB,*PMPEB;

struct DllStruct
{
    PVOID EntryPoint;
    PVOID ViewBase;
    SIZE_T ViewSize;
    std::map<std::wstring,FARPROC> FuncMap;//函数映射
};
std::map<std::wstring,DllStruct> DllMap;
CRITICAL_SECTION DllLock;
#define RtlGetProcessHeap() ( (PMPEB)((PMTEB)NtCurrentTeb())->Peb )->ProcessHeap

BOOL WINAPI LoadLibraryTA(LPCSTR DllPath);
BOOL WINAPI LoadLibraryTW(LPCWSTR DllPath);
FARPROC WINAPI GetProcAddressTA(LPCSTR DllPath,LPCSTR ProcName);
FARPROC WINAPI GetProcAddressTW(LPCWSTR DllPath,LPCWSTR ProcName);
BOOL WINAPI FreeLibraryTA(LPCSTR DllPath);
BOOL WINAPI FreeLibraryTW(LPCWSTR DllPath);

BOOL WINAPI LoadLibraryTA(LPCSTR DllPath)
{
    ANSI_STRING DllPathA;
    UNICODE_STRING DllPathW;
    NTSTATUS status;
    if(!DllPath || DllPath[0] == 0)
        return FALSE;
    WCHAR tmp[0x1000];
    memset(tmp,0,sizeof(tmp));
    RtlInitAnsiString(&DllPathA,DllPath);
    DllPathW.Buffer = tmp;
    DllPathW.MaximumLength = 0x1000;
    status = RtlAnsiStringToUnicodeString(&DllPathW,&DllPathA,FALSE);
    if(!NT_SUCCESS(status))
        return FALSE;
    return LoadLibraryTW(DllPathW.Buffer);
}

BOOL WINAPI LoadLibraryTW(LPCWSTR DllPath)
{
    if(!DllPath || DllPath[0] == 0)
        return FALSE;
    BOOL result = FALSE;
    EnterCriticalSection(&DllLock);
    //查找Map,遍历导出表,更新Map
    std::map<std::wstring,DllStruct>::iterator itor = DllMap.find(DllPath);
    if(itor != DllMap.end())
    {
        result = FALSE;
        goto ENDLOAD;
    }

    UNICODE_STRING NtPathDllName;
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE FileHandle = NULL,SectionHandle = NULL;
    IO_STATUS_BLOCK IoStatusBlock;
    NTSTATUS Status;
    if(!RtlDosPathNameToNtPathName_U(DllPath,&NtPathDllName,NULL,NULL))
    {
        result = FALSE;
        goto ENDLOAD;
    }
    InitializeObjectAttributes(&ObjectAttributes,&NtPathDllName,OBJ_CASE_INSENSITIVE,NULL,NULL);
    Status = NtOpenFile(&FileHandle,SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,&ObjectAttributes,&IoStatusBlock,
        FILE_SHARE_READ | FILE_SHARE_DELETE,FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
    if (!NT_SUCCESS(Status))
    {//尝试以只读方式打开
        Status = NtOpenFile(&FileHandle,SYNCHRONIZE | FILE_EXECUTE,&ObjectAttributes,&IoStatusBlock,
            FILE_SHARE_READ | FILE_SHARE_DELETE,FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
    }
    if(!NT_SUCCESS(Status))
    {
        result = FALSE;
        RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
        goto ENDLOAD;
    }
    Status = NtCreateSection(&SectionHandle,SECTION_MAP_READ | SECTION_MAP_EXECUTE |SECTION_MAP_WRITE | SECTION_QUERY,
        NULL,NULL,PAGE_EXECUTE,SEC_IMAGE,FileHandle);
    NtClose(FileHandle);
    if(!NT_SUCCESS(Status))
    {
        result = FALSE;
        RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
        goto ENDLOAD;
    }
    RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);

    PVOID ViewBase = NULL;
    SIZE_T ViewSize = 0;
    PIMAGE_NT_HEADERS NtHeaders = NULL;
    PIMAGE_DOS_HEADER DosHeader = NULL;
    PVOID EntryPoint = NULL;
    Status = NtMapViewOfSection(SectionHandle,(HANDLE)-1/*NtCurrentProcess()*/,&ViewBase,0,0,NULL,&ViewSize,1/*ViewShare*/,0,PAGE_READWRITE);

    if(ViewBase)
    {
        DosHeader = (PIMAGE_DOS_HEADER)ViewBase;
        if(DosHeader->e_magic == IMAGE_DOS_SIGNATURE && DosHeader->e_lfanew  && DosHeader->e_lfanew < ViewSize)
        {
            NtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)DosHeader + DosHeader->e_lfanew);
            if(NtHeaders->Signature != IMAGE_NT_SIGNATURE)
                NtHeaders = NULL;
        }
        if(!NtHeaders || NtHeaders->OptionalHeader.AddressOfEntryPoint == NULL || !(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL))
        {
            result = FALSE;
            goto ENDLOAD;
        }
        EntryPoint = (PVOID)(NtHeaders->OptionalHeader.AddressOfEntryPoint + (BYTE*)ViewBase);
    }

    if(Status == STATUS_IMAGE_NOT_AT_BASE)
    {//重定位
        if(!(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED))
        {
            USHORT Directory = IMAGE_DIRECTORY_ENTRY_BASERELOC;
            ULONG RelocDataSize = 0;
            PVOID RelocData = NULL;
            if(NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
            {
                PIMAGE_NT_HEADERS32 tpnh = (PIMAGE_NT_HEADERS32)NtHeaders;
                if(Directory >= tpnh->OptionalHeader.NumberOfRvaAndSizes)
                    return NULL;
                DWORD VA = tpnh->OptionalHeader.DataDirectory[Directory].VirtualAddress;
                if(VA == NULL)
                    return NULL;
                RelocDataSize = tpnh->OptionalHeader.DataDirectory[Directory].Size;
                RelocData = (PVOID)((BYTE*)ViewBase + VA);
            }
            else
            {
                PIMAGE_NT_HEADERS64 tpnh = (PIMAGE_NT_HEADERS64)NtHeaders;
                if(Directory >= tpnh->OptionalHeader.NumberOfRvaAndSizes)
                    return NULL;
                DWORD VA = tpnh->OptionalHeader.DataDirectory[Directory].VirtualAddress;
                if(VA == NULL)
                    return NULL;
                RelocDataSize = tpnh->OptionalHeader.DataDirectory[Directory].Size;
                RelocData = (PVOID)((BYTE*)ViewBase + VA);
            }
            if(RelocData && RelocDataSize)
            {
                Status = LdrpSetProtection(ViewBase,NtHeaders,FALSE);
                if(NT_SUCCESS(Status))
                {
                    Status = LdrRelocateImageWithBias(ViewBase, NtHeaders, 0LL, NULL, STATUS_SUCCESS,STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
                    LdrpSetProtection(ViewBase,NtHeaders,TRUE);
                    if(NT_SUCCESS(Status))
                    {
                        goto ENDLOAD1;
                    }
                }
            }
        }
        if(!NT_SUCCESS(Status) || ViewBase)
        {
            NtUnmapViewOfSection((HANDLE)-1/*NtCurrentProcess()*/,ViewBase);
            result = FALSE;
        }
    }
    else if(!NT_SUCCESS(Status))
    {
        result = FALSE;
        goto ENDLOAD;
    }
ENDLOAD1:
    NtClose(SectionHandle);
    if(NT_SUCCESS(Status))
        result = TRUE;
    DllStruct& ds = DllMap[DllPath];
    ds.EntryPoint = EntryPoint;
    ds.ViewBase = ViewBase;
    ds.ViewSize = ViewSize;
    {
        typedef BOOLEAN (WINAPI *PDLL_INIT_ROUTINE)( PVOID DllHandle,ULONG Reason,PCONTEXT Context );
//      ((PDLL_INIT_ROUTINE)EntryPoint)(ViewBase,DLL_PROCESS_ATTACH,NULL);
        PVOID BaseAddress = ViewBase;
        USHORT Directory = IMAGE_DIRECTORY_ENTRY_EXPORT;
        PIMAGE_EXPORT_DIRECTORY ExportDir = NULL;
        ULONG ExportDirSize = 0;
        if(NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
        {
            PIMAGE_NT_HEADERS32 tpnh = (PIMAGE_NT_HEADERS32)NtHeaders;
            if(Directory >= tpnh->OptionalHeader.NumberOfRvaAndSizes)
                return NULL;
            DWORD VA = tpnh->OptionalHeader.DataDirectory[Directory].VirtualAddress;
            if(VA == NULL)
                return NULL;
            ExportDirSize = tpnh->OptionalHeader.DataDirectory[Directory].Size;
            ExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)ViewBase + VA);
        }
        else
        {
            PIMAGE_NT_HEADERS64 tpnh = (PIMAGE_NT_HEADERS64)NtHeaders;
            if(Directory >= tpnh->OptionalHeader.NumberOfRvaAndSizes)
                return NULL;
            DWORD VA = tpnh->OptionalHeader.DataDirectory[Directory].VirtualAddress;
            if(VA == NULL)
                return NULL;
            ExportDirSize = tpnh->OptionalHeader.DataDirectory[Directory].Size;
            ExportDir = (PIMAGE_EXPORT_DIRECTORY)((BYTE*)ViewBase + VA);
        }
        PULONG NameTable = (PULONG)((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNames);
        PUSHORT OrdinalTable = (PUSHORT)((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfNameOrdinals);
        PULONG AddressOfFunctions = (PULONG)((ULONG_PTR)BaseAddress + (ULONG_PTR)ExportDir->AddressOfFunctions);
        USHORT Ordinal = -1;
        for(LONG i = 0;i < ExportDir->NumberOfNames;i++)
        {
            PCHAR FuncName = (PCHAR)((ULONG_PTR)BaseAddress + NameTable[i]);
            ANSI_STRING FuncNameA;
            UNICODE_STRING FuncNameW;
            WCHAR tmp[0x1000];
            memset(tmp,0,sizeof(tmp));
            RtlInitAnsiString(&FuncNameA,FuncName);
            FuncNameW.Buffer = tmp;
            FuncNameW.MaximumLength = 0x1000;
            Status = RtlAnsiStringToUnicodeString(&FuncNameW,&FuncNameA,FALSE);
            if(NT_SUCCESS(Status))
            {
                Ordinal = OrdinalTable[i];
                if(Ordinal >=0 && Ordinal < ExportDir->NumberOfFunctions)
                {
                    ULONG_PTR Function = (ULONG_PTR)BaseAddress + AddressOfFunctions[Ordinal];
                    if(!(Function > (ULONG_PTR)ExportDir && Function < (ULONG_PTR)ExportDir + ExportDirSize))
                    {
                        ds.FuncMap[FuncNameW.Buffer] = (FARPROC)Function;
                    }
                }
            }
        }
    }

ENDLOAD:
    LeaveCriticalSection(&DllLock);
    return result;
}

NTSTATUS NTAPI LdrpSetProtection(PVOID ViewBase,PIMAGE_NT_HEADERS NtHeaders,BOOLEAN Restore)
{
    NTSTATUS Status;
    PVOID SectionBase;
    SIZE_T SectionSize;
    ULONG NewProtection, OldProtection, i;
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) ((ULONG_PTR)(ntheader) + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + ((ntheader))->FileHeader.SizeOfOptionalHeader ))
    PIMAGE_SECTION_HEADER Section = IMAGE_FIRST_SECTION(NtHeaders);
    for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++)
    {
        if ((Section->SizeOfRawData) && !(Section->Characteristics & IMAGE_SCN_MEM_WRITE))
        {
            if (Restore)
            {
                if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE)
                {
                    NewProtection = PAGE_EXECUTE;
                }
                else
                {
                    NewProtection = PAGE_READONLY;
                }

                if (Section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
                {
                    NewProtection |= PAGE_NOCACHE;
                }
            }
            else
            {
                NewProtection = PAGE_READWRITE;
            }

            SectionBase = (PVOID)((ULONG_PTR)ViewBase + Section->VirtualAddress);
            SectionSize = Section->SizeOfRawData;
            if (SectionSize)
            {
                Status = NtProtectVirtualMemory((HANDLE)-1,&SectionBase,&SectionSize,NewProtection,&OldProtection);
                if (!NT_SUCCESS(Status)) return Status;
            }
        }
        Section++;
    }
    if (Restore) NtFlushInstructionCache((HANDLE)-1, NULL, 0);
    return STATUS_SUCCESS;
}

ULONG NTAPI LdrRelocateImageWithBias(PVOID BaseAddress,PIMAGE_NT_HEADERS NtHeaders,LONGLONG AdditionalBias,PCCH  LoaderName,ULONG Success,ULONG Conflict,ULONG Invalid)
{
#define SWAPW(x) (x)
#define SWAPD(x) (x)
#define SWAPQ(x) (x)
    PIMAGE_DATA_DIRECTORY RelocationDDir;
    PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
    ULONG Count;
    ULONG_PTR Address;
    PUSHORT TypeOffset;
    LONGLONG Delta;

    if (SWAPW(NtHeaders->FileHeader.Characteristics) & IMAGE_FILE_RELOCS_STRIPPED)
    {
        return Conflict;
    }
    RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
    if (SWAPD(RelocationDDir->VirtualAddress) == 0 || SWAPD(RelocationDDir->Size) == 0)
    {
        return Success;
    }
    Delta = (ULONG_PTR)BaseAddress - SWAPD(NtHeaders->OptionalHeader.ImageBase) + AdditionalBias;
    RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)BaseAddress + SWAPD(RelocationDDir->VirtualAddress));
    RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + SWAPD(RelocationDDir->Size));
    while (RelocationDir < RelocationEnd && SWAPW(RelocationDir->SizeOfBlock) > 0)
    {
        SHORT Offset;
        USHORT Type;
        ULONG i;
        PUSHORT ShortPtr;
        PULONG LongPtr;
        PULONGLONG LongLongPtr;

        Count = (SWAPW(RelocationDir->SizeOfBlock) - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
        Address = (ULONG_PTR)(RelocationDir->VirtualAddress);
        TypeOffset = (PUSHORT)(RelocationDir + 1);

        for (ULONG i = 0; i < Count; i++)
        {
            Offset = SWAPW(*TypeOffset) & 0xFFF;
            Type = SWAPW(*TypeOffset) >> 12;
            ShortPtr = (PUSHORT)Offset;

            if ((ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationDir || (ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationEnd)
                continue;

            switch (Type)
            {
                /* case IMAGE_REL_BASED_SECTION : */
                /* case IMAGE_REL_BASED_REL32 : */
            case IMAGE_REL_BASED_ABSOLUTE:
                break;
            case IMAGE_REL_BASED_HIGH:
                *ShortPtr = HIWORD(MAKELONG(0, *ShortPtr) + (Delta & 0xFFFFFFFF));
                break;
            case IMAGE_REL_BASED_LOW:
                *ShortPtr = SWAPW(*ShortPtr) + LOWORD(Delta & 0xFFFF);
                break;
            case IMAGE_REL_BASED_HIGHLOW:
                LongPtr = (PULONG)Offset;
                *LongPtr = SWAPD(*LongPtr) + (Delta & 0xFFFFFFFF);
                break;
            case IMAGE_REL_BASED_DIR64:
                LongLongPtr = (PUINT64)Offset;
                *LongLongPtr = SWAPQ(*LongLongPtr) + Delta;
                break;
            case IMAGE_REL_BASED_HIGHADJ:
            case IMAGE_REL_BASED_MIPS_JMPADDR:
            default:
                RelocationDir = (PIMAGE_BASE_RELOCATION)NULL;
            }
            TypeOffset++;
        }
        RelocationDir = (PIMAGE_BASE_RELOCATION)TypeOffset;
        if (RelocationDir == NULL)
        {
            return Invalid;
        }
    }
    return Success;
}

FARPROC WINAPI GetProcAddressTA(LPCSTR DllPath,LPCSTR ProcName)
{
    ANSI_STRING DllPathA,ProcNameA;
    UNICODE_STRING DllPathW,ProcNameW;
    NTSTATUS status;
    if(!DllPath || !ProcName || DllPath[0] == 0 || ProcName[0] == 0)
        return NULL;
    WCHAR tmp1[0x1000],tmp2[0x1000];
    memset(tmp1,0,sizeof(tmp1));
    memset(tmp2,0,sizeof(tmp2));
    RtlInitAnsiString(&DllPathA,DllPath);
    RtlInitAnsiString(&ProcNameA,ProcName);
    DllPathW.Buffer = tmp1;
    DllPathW.MaximumLength = 0x1000;
    ProcNameW.Buffer = tmp2;
    ProcNameW.MaximumLength = 0x1000;
    status = RtlAnsiStringToUnicodeString(&DllPathW,&DllPathA,FALSE);
    if(!NT_SUCCESS(status))
        return FALSE;
    status = RtlAnsiStringToUnicodeString(&ProcNameW,&ProcNameA,FALSE);
    if(!NT_SUCCESS(status))
        return FALSE;
    return GetProcAddressTW(DllPathW.Buffer,ProcNameW.Buffer);
}

FARPROC WINAPI GetProcAddressTW(LPCWSTR DllPath,LPCWSTR ProcName)
{
    if(!DllPath || !ProcName || DllPath[0] == 0 || ProcName[0] == 0)
        return NULL;
    FARPROC result = NULL;
    EnterCriticalSection(&DllLock);
    std::map<std::wstring,DllStruct>::iterator itor1 = DllMap.find(DllPath);
    if(itor1 != DllMap.end())
    {
        std::map<std::wstring,FARPROC>::iterator itor2 = (*itor1).second.FuncMap.find(ProcName);
        if(itor2 != (*itor1).second.FuncMap.end())
        {
            result = (*itor2).second;
        }
    }
    LeaveCriticalSection(&DllLock);
    return result;
}

BOOL WINAPI FreeLibraryTA(LPCSTR DllPath)
{
    ANSI_STRING DllPathA;
    UNICODE_STRING DllPathW;
    NTSTATUS status;
    if(!DllPath || DllPath[0] == 0)
        return FALSE;
    WCHAR tmp[0x1000];
    memset(tmp,0,sizeof(tmp));
    RtlInitAnsiString(&DllPathA,DllPath);
    DllPathW.Buffer = tmp;
    DllPathW.MaximumLength = 0x1000;
    status = RtlAnsiStringToUnicodeString(&DllPathW,&DllPathA,FALSE);
    if(!NT_SUCCESS(status))
        return FALSE;
    return FreeLibraryTW(DllPathW.Buffer);
}

BOOL WINAPI FreeLibraryTW(LPCWSTR DllPath)
{
    BOOL result = FALSE;
    if(!DllPath || DllPath[0] == 0)
        return FALSE;

    EnterCriticalSection(&DllLock);
    std::map<std::wstring,DllStruct>::iterator itor = DllMap.find(DllPath);
    if(itor == DllMap.end())
    {
        result = FALSE;
        goto ENDFREE;
    }

    NTSTATUS Status;
    PVOID BaseAddress = (*itor).second.ViewBase;
    PVOID EntryPoint = (*itor).second.EntryPoint;

    typedef BOOLEAN (WINAPI *PDLL_INIT_ROUTINE)( PVOID DllHandle,ULONG Reason,PCONTEXT Context );
    ((PDLL_INIT_ROUTINE)EntryPoint)(BaseAddress,DLL_PROCESS_ATTACH,NULL);
    Status = NtUnmapViewOfSection((HANDLE)-1, BaseAddress);
    if(NT_SUCCESS(Status))
        result = TRUE;
ENDFREE:
    LeaveCriticalSection(&DllLock);
    return result;
}

void main()
{
    InitializeCriticalSection(&DllLock);
    LoadLibraryTA("d:\\1.dll");
    FARPROC func=GetProcAddressTA("d:\\1.dll","func");
    ((void (__cdecl *)())func)();
}


回复

使用道具 举报

 楼主| 发表于 2015-6-18 23:37:09 | 显示全部楼层
完善后的代码,,可以弹出MessageBox
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0500

#include <windows.h>
#include <winternl.h>
#include <Shlwapi.h>
#include <map>
#include <string>
using namespace std;

#pragma comment(lib,"user32.lib")
#pragma comment(lib,"Shlwapi.lib")

#if defined(WIN64) || defined(_WIN64)
#pragma comment(lib,"ntdll64.lib")
#else
#pragma comment(lib,"ntdll.lib")
#endif

#if defined(UNICODE) || defined(_UNICODE)
#define GetProcAddressT GetProcAddressTW
#define LoadLibraryT LoadLibraryTW
#define FreeLibraryT FreeLibraryTW
#else
#define GetProcAddressT GetProcAddressTA
#define LoadLibraryT LoadLibraryTA
#define FreeLibraryT FreeLibraryTA
#endif

extern "C"
{
    BOOLEAN WINAPI RtlDosPathNameToNtPathName_U(PCWSTR,PUNICODE_STRING,PCWSTR*,PVOID*);
    NTSTATUS WINAPI NtMapViewOfSection(HANDLE,HANDLE,PVOID*,ULONG,SIZE_T,const LARGE_INTEGER*,SIZE_T*,ULONG,ULONG,ULONG);
    BOOLEAN WINAPI RtlFreeHeap(PVOID,ULONG,PVOID);
    NTSTATUS WINAPI NtCreateSection(PHANDLE,ACCESS_MASK,POBJECT_ATTRIBUTES,PLARGE_INTEGER,ULONG,ULONG,HANDLE);
    NTSTATUS WINAPI NtUnmapViewOfSection(HANDLE,PVOID);
    NTSTATUS WINAPI NtProtectVirtualMemory(HANDLE,PVOID,PSIZE_T,ULONG,PULONG);
    NTSTATUS WINAPI NtFlushInstructionCache(HANDLE,PVOID,ULONG);
};

void RtlImageDirectoryEntryToData(PIMAGE_NT_HEADERS,USHORT,ULONG*,PVOID*,PVOID) ;
ULONG NTAPI LdrRelocateImageWithBias(PVOID,PIMAGE_NT_HEADERS,LONGLONG ,PCCH,ULONG,ULONG,ULONG);
NTSTATUS NTAPI LdrpSetProtection(PVOID,PIMAGE_NT_HEADERS,BOOLEAN);

#define OBJ_CASE_INSENSITIVE    0x00000040L
#define STATUS_IMAGE_NOT_AT_BASE ((NTSTATUS)0x40000003L)
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 
#define STATUS_CONFLICTING_ADDRESSES ((NTSTATUS)0xC0000018L)
#define STATUS_INVALID_IMAGE_FORMAT ((NTSTATUS)0xC000007BL)
#define FILE_NON_DIRECTORY_FILE 0x00000040
#define FILE_SYNCHRONOUS_IO_NONALERT 0x00000020

typedef struct _CLIENT_ID 
{
    HANDLE UniqueProcess;
    HANDLE UniqueThread;
} CLIENT_ID;

typedef struct _MTEB 
{ 
    _NT_TIB NtTib; 
    PVOID EnvironmentPointer; 
    CLIENT_ID ClientId;
    PVOID ActiveRpcHandle;
    PVOID ThreadLocalStoragePointer;
    PPEB Peb;
}MTEB,*PMTEB;

typedef struct _MPEB_LDR_DATA
{
    UINT32 Length;
    UCHAR Initialized;
    PVOID SsHandle;
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
}MPEB_LDR_DATA,*PMPEB_LDR_DATA;

typedef struct _LDR_MODULE
{
    LIST_ENTRY InLoadOrderModuleList;
    LIST_ENTRY InMemoryOrderModuleList;
    LIST_ENTRY InInitializationOrderModuleList;
    PVOID BaseAddress;
    PVOID EntryPoint;
    ULONG SizeOfImage;
    UNICODE_STRING FullDllName;
}LDR_MODULE,*PLDR_MODULE;

typedef struct _MPEB
{
    DWORD flags;
    PVOID Mutant;
    PVOID ImageBaseAddress;
    PMPEB_LDR_DATA Ldr;
    PVOID ProcessParameters;
    PVOID SubSystemData;
    PVOID ProcessHeap;
}MPEB,*PMPEB;

struct DllStruct
{
    PVOID EntryPoint;
    PVOID ViewBase;
    SIZE_T ViewSize;
    std::map<std::wstring,FARPROC> FuncMap;//函数映射
};
std::map<std::wstring,DllStruct> DllMap;
CRITICAL_SECTION DllLock;
#define RtlGetProcessHeap() ( (PMPEB)((PMTEB)NtCurrentTeb())->Peb )->ProcessHeap
#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define InitializeObjectAttributes( p, n, a, r, s ) { (p)->Length = sizeof( OBJECT_ATTRIBUTES ); (p)->RootDirectory = r; (p)->Attributes = a; (p)->ObjectName = n; (p)->SecurityDescriptor = s; (p)->SecurityQualityOfService = NULL; }
#define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) ((ULONG_PTR)(ntheader) + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + ((ntheader))->FileHeader.SizeOfOptionalHeader ))

BOOL WINAPI LoadLibraryTA(LPCSTR DllPath);
BOOL WINAPI LoadLibraryTW(LPCWSTR DllPath);
FARPROC WINAPI GetProcAddressTA(LPCSTR DllPath,LPCSTR ProcName);
FARPROC WINAPI GetProcAddressTW(LPCWSTR DllPath,LPCWSTR ProcName);
BOOL WINAPI FreeLibraryTA(LPCSTR DllPath);
BOOL WINAPI FreeLibraryTW(LPCWSTR DllPath);

#define SWAPW(x) (x)
#define SWAPD(x) (x)
#define SWAPQ(x) (x)
#define RVA(m, b) ((PVOID)((ULONG_PTR)(b) + (ULONG_PTR)(m)))

typedef BOOLEAN (WINAPI *PDLL_INIT_ROUTINE)( PVOID DllHandle,ULONG Reason,PCONTEXT Context );

void GetExportFuncs( PIMAGE_NT_HEADERS NtHeaders, PVOID ViewBase, DllStruct* ds)
{
    PIMAGE_EXPORT_DIRECTORY ExportDir = NULL;
    ULONG ExportDirSize = 0;
    if(!NtHeaders && ViewBase)
    {
        PIMAGE_DOS_HEADER DosHeader = (PIMAGE_DOS_HEADER)ViewBase;
        NtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)DosHeader + DosHeader->e_lfanew);
    }
    if(!NtHeaders)
        return;
    RtlImageDirectoryEntryToData(NtHeaders, IMAGE_DIRECTORY_ENTRY_EXPORT, &ExportDirSize, (PVOID*)&ExportDir, ViewBase);
    PULONG NameTable = (PULONG)((ULONG_PTR)ViewBase + (ULONG_PTR)ExportDir->AddressOfNames);
    PUSHORT OrdinalTable = (PUSHORT)((ULONG_PTR)ViewBase + (ULONG_PTR)ExportDir->AddressOfNameOrdinals);
    PULONG AddressOfFunctions = (PULONG)((ULONG_PTR)ViewBase + (ULONG_PTR)ExportDir->AddressOfFunctions);
    USHORT Ordinal = -1;
    for(LONG i = 0;i < ExportDir->NumberOfNames;i++)
    {
        PCHAR FuncName = (PCHAR)((ULONG_PTR)ViewBase + NameTable[i]);
        ANSI_STRING FuncNameA;
        UNICODE_STRING FuncNameW;
        WCHAR tmp[0x1000];
        memset(tmp,0,sizeof(tmp));
        RtlInitAnsiString(&FuncNameA,FuncName);
        FuncNameW.Buffer = tmp;
        FuncNameW.MaximumLength = 0x1000;
        NTSTATUS Status = RtlAnsiStringToUnicodeString(&FuncNameW,&FuncNameA,FALSE);
        if(NT_SUCCESS(Status))
        {
            Ordinal = OrdinalTable[i];
            if(Ordinal >=0 && Ordinal < ExportDir->NumberOfFunctions)
            {
                ULONG_PTR Function = (ULONG_PTR)ViewBase + AddressOfFunctions[Ordinal];
                if(!(Function > (ULONG_PTR)ExportDir && Function < (ULONG_PTR)ExportDir + ExportDirSize))
                {
                    ds->FuncMap[FuncNameW.Buffer] = (FARPROC)Function;
                }
            }
        }
    }
}

BOOL WINAPI LoadLibraryTA(LPCSTR DllPath)
{
    ANSI_STRING DllPathA;
    UNICODE_STRING DllPathW;
    NTSTATUS status;
    if(!DllPath || DllPath[0] == 0)
        return FALSE;
    WCHAR tmp[0x1000];
    memset(tmp,0,sizeof(tmp));
    RtlInitAnsiString(&DllPathA,DllPath);
    DllPathW.Buffer = tmp;
    DllPathW.MaximumLength = 0x1000;
    status = RtlAnsiStringToUnicodeString(&DllPathW,&DllPathA,FALSE);
    if(!NT_SUCCESS(status))
        return FALSE;
    return LoadLibraryTW(DllPathW.Buffer);
}

BOOL LdrpLoadImportModule(LPSTR ImportName, PVOID BaseAddress, LPWSTR pDllPath) 
{
    PVOID Address = (PVOID)LoadLibraryA(ImportName);
    Address = (PVOID)((ULONG_PTR)Address&~3);
    //遍历Ldr找到全路径
    PLIST_ENTRY ListHead = &((PMPEB)((PMTEB)NtCurrentTeb())->Peb)->Ldr->InLoadOrderModuleList;
    PLIST_ENTRY Next = ListHead->Flink;
    while(Next != ListHead)
    {
        PLDR_MODULE Cur = (PLDR_MODULE)Next;
        if(Cur->BaseAddress == Address)
        {
            memset(pDllPath,0,0x1000);
            wcsncpy(pDllPath,Cur->FullDllName.Buffer,Cur->FullDllName.Length);
            std::map<std::wstring,DllStruct>::iterator itor = DllMap.find(pDllPath);
            if(itor == DllMap.end())
            {
                DllStruct& ds= DllMap[pDllPath];
                ds.EntryPoint = Cur->EntryPoint;
                ds.ViewBase = Cur->BaseAddress;
                ds.ViewSize = Cur->SizeOfImage;
                GetExportFuncs(NULL,Address,&ds);
            }
            return TRUE;
        }
        Next = Next->Flink;
    }
    return FALSE;
}

void LdrpSnapThunk( PVOID ExportBase, PVOID ImportBase, PIMAGE_THUNK_DATA OriginalThunk, PIMAGE_THUNK_DATA Thunk, PIMAGE_EXPORT_DIRECTORY ExportEntry, ULONG ExportSize )
{
    PIMAGE_IMPORT_BY_NAME AddressOfData = (PIMAGE_IMPORT_BY_NAME)((ULONG_PTR)ImportBase + ((ULONG_PTR)OriginalThunk->u1.AddressOfData & 0xFFFFFFFF));
    LPSTR ImportName = (LPSTR)AddressOfData->Name;
    PULONG NameTable = (PULONG)((ULONG_PTR)ExportBase + (ULONG_PTR)ExportEntry->AddressOfNames);
    PUSHORT OridinalTable = (PUSHORT)((ULONG_PTR)ExportBase + (ULONG_PTR)ExportEntry->AddressOfNameOrdinals);
    USHORT Hint = AddressOfData->Hint;

}

void LdrpSnapIAT(PIMAGE_NT_HEADERS NtHeaders, PIMAGE_IMPORT_DESCRIPTOR IatData, PVOID ViewBase,LPCWSTR DllPathW) 
{
    NTSTATUS Status;
    PVOID Iat = NULL;
    SIZE_T ImportSize = 0;
    ULONG IatSize = 0, ExportSize = 0;
    ULONG OldProtect = 0;
    RtlImageDirectoryEntryToData(NtHeaders, IMAGE_DIRECTORY_ENTRY_IAT, &IatSize, &Iat, ViewBase);
    if(!Iat || !IatSize)
    {
        PIMAGE_SECTION_HEADER SectionHeader = (PIMAGE_SECTION_HEADER)((ULONG_PTR)(NtHeaders) + FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + NtHeaders->FileHeader.SizeOfOptionalHeader );
        ULONG Rva = NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
        if(Rva)
        {
            for(ULONG i = 0;i < NtHeaders->FileHeader.NumberOfSections;i++)
            {
                if((Rva >= SectionHeader->VirtualAddress) && Rva < (SectionHeader->VirtualAddress + SectionHeader->SizeOfRawData))
                {
                    Iat = (PVOID)((ULONG_PTR)(ViewBase) + SectionHeader->VirtualAddress);
                    IatSize = SectionHeader->Misc.VirtualSize;
                    if(!IatSize)
                        IatSize = SectionHeader->SizeOfRawData;
                    break;
                }
                SectionHeader++;
            }
        }
        else
            return;
    }
    ImportSize = IatSize;

    Status = NtProtectVirtualMemory(((HANDLE)(LONG_PTR) -1), &Iat, &ImportSize, PAGE_READWRITE, &OldProtect);
    if(!NT_SUCCESS(Status))
        return;
    if(IatData->FirstThunk)
    {
        PIMAGE_THUNK_DATA OriginalThunk = NULL;
        PIMAGE_THUNK_DATA FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)ViewBase + IatData->FirstThunk);
        if((IatData->Characteristics < NtHeaders->OptionalHeader.SizeOfHeaders) || (IatData->Characteristics >= NtHeaders->OptionalHeader.SizeOfImage))
        {
            OriginalThunk = FirstThunk;
        }
        else
        {
            OriginalThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)ViewBase + IatData->OriginalFirstThunk);
        }
        LPSTR ImportName = (LPSTR)((ULONG_PTR)ViewBase + IatData->Name);
        while(OriginalThunk->u1.AddressOfData)
        {
            __try
            {
                PIMAGE_IMPORT_BY_NAME AddressOfData = (PIMAGE_IMPORT_BY_NAME)((ULONG_PTR)ViewBase + (ULONG_PTR)OriginalThunk->u1.AddressOfData & 0xFFFFFFFF);
                ImportName = (LPSTR)AddressOfData->Name;
                ANSI_STRING FuncNameA;
                WCHAR FuncName[0x1000];
                UNICODE_STRING FuncNameW;
                memset(FuncName,0,sizeof(FuncName));
                RtlInitAnsiString(&FuncNameA,ImportName);
                FuncNameW.Buffer = FuncName;
                FuncNameW.MaximumLength = sizeof(FuncName);
                RtlAnsiStringToUnicodeString(&FuncNameW,&FuncNameA,FALSE);
                FirstThunk->u1.Function = (DWORD)GetProcAddressTW(DllPathW,FuncNameW.Buffer);
                OriginalThunk++;
                FirstThunk++;
            }
            __except(1)
            {

            }
        }
    }
    NtProtectVirtualMemory(((HANDLE)(LONG_PTR) -1),&Iat,&ImportSize,OldProtect,&OldProtect);
    NtFlushInstructionCache(((HANDLE)(LONG_PTR) -1),Iat,IatSize);
}

void RtlImageDirectoryEntryToData(PIMAGE_NT_HEADERS NtHeaders, USHORT Directory, ULONG* RelocDataSize, PVOID* RelocData, PVOID ViewBase) 
{
    if(NtHeaders->OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC)
    {
        PIMAGE_NT_HEADERS32 tpnh = (PIMAGE_NT_HEADERS32)NtHeaders;
        if(Directory < tpnh->OptionalHeader.NumberOfRvaAndSizes)
        {
            DWORD VA = tpnh->OptionalHeader.DataDirectory[Directory].VirtualAddress;
            if(VA)
            {
                *RelocDataSize = tpnh->OptionalHeader.DataDirectory[Directory].Size;
                *RelocData = (PVOID)((ULONG_PTR)ViewBase + VA);
            }
        }
    }
    else
    {
        PIMAGE_NT_HEADERS64 tpnh = (PIMAGE_NT_HEADERS64)NtHeaders;
        if(Directory < tpnh->OptionalHeader.NumberOfRvaAndSizes)
        {
            DWORD VA = tpnh->OptionalHeader.DataDirectory[Directory].VirtualAddress;
            if(VA)
            {
                *RelocDataSize = tpnh->OptionalHeader.DataDirectory[Directory].Size;
                *RelocData = (PVOID)((BYTE*)ViewBase + VA);
            }
        }
    }
}

BOOL WINAPI LoadLibraryTW(LPCWSTR DllPath)
{
    if(!DllPath || DllPath[0] == 0)
        return FALSE;
    BOOL result = FALSE;

    EnterCriticalSection(&DllLock);
    //查找Map,遍历导出表,更新Map
    std::map<std::wstring,DllStruct>::iterator itor = DllMap.find(DllPath);
    if(itor != DllMap.end())
    {
        result = FALSE;
        goto ENDLOAD;
    }

    UNICODE_STRING NtPathDllName;
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE FileHandle = NULL,SectionHandle = NULL;
    IO_STATUS_BLOCK IoStatusBlock;
    NTSTATUS Status;
    if(!RtlDosPathNameToNtPathName_U(DllPath,&NtPathDllName,NULL,NULL))
    {
        result = FALSE;
        goto ENDLOAD;
    }
    InitializeObjectAttributes(&ObjectAttributes,&NtPathDllName,OBJ_CASE_INSENSITIVE,NULL,NULL);
    Status = NtOpenFile(&FileHandle,SYNCHRONIZE | FILE_EXECUTE | FILE_READ_DATA,&ObjectAttributes,&IoStatusBlock,
        FILE_SHARE_READ | FILE_SHARE_DELETE,FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
    if (!NT_SUCCESS(Status))
    {//尝试以只读方式打开
        Status = NtOpenFile(&FileHandle,SYNCHRONIZE | FILE_EXECUTE,&ObjectAttributes,&IoStatusBlock,
            FILE_SHARE_READ | FILE_SHARE_DELETE,FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT);
    }
    if(!NT_SUCCESS(Status))
    {
        result = FALSE;
        RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
        goto ENDLOAD;
    }
    Status = NtCreateSection(&SectionHandle,SECTION_MAP_READ | SECTION_MAP_EXECUTE |SECTION_MAP_WRITE | SECTION_QUERY,
        NULL,NULL,PAGE_EXECUTE,SEC_IMAGE,FileHandle);
    NtClose(FileHandle);
    if(!NT_SUCCESS(Status))
    {
        result = FALSE;
        RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);
        goto ENDLOAD;
    }
    RtlFreeHeap(RtlGetProcessHeap(), 0, NtPathDllName.Buffer);

    PVOID ViewBase = NULL;
    SIZE_T ViewSize = 0;
    PIMAGE_NT_HEADERS NtHeaders = NULL;
    PIMAGE_DOS_HEADER DosHeader = NULL;
    PVOID EntryPoint = NULL;
    Status = NtMapViewOfSection(SectionHandle,((HANDLE)(LONG_PTR) -1)/*NtCurrentProcess()*/,&ViewBase,0,0,NULL,&ViewSize,1/*ViewShare*/,0,PAGE_READWRITE);

    if(ViewBase)
    {
        DosHeader = (PIMAGE_DOS_HEADER)ViewBase;
        if(DosHeader->e_magic == IMAGE_DOS_SIGNATURE && DosHeader->e_lfanew  && DosHeader->e_lfanew < ViewSize)
        {
            NtHeaders = (PIMAGE_NT_HEADERS)((BYTE*)DosHeader + DosHeader->e_lfanew);
            if(NtHeaders->Signature != IMAGE_NT_SIGNATURE)
                NtHeaders = NULL;
        }
        if(!NtHeaders || !(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_DLL))
        {
            result = FALSE;
            goto ENDLOAD;
        }
        if(NtHeaders->OptionalHeader.AddressOfEntryPoint)
            EntryPoint = (PVOID)(NtHeaders->OptionalHeader.AddressOfEntryPoint + (BYTE*)ViewBase);
    }

    if(Status == STATUS_IMAGE_NOT_AT_BASE)
    {//重定位
        if(!(NtHeaders->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED))
        {
            ULONG RelocDataSize = 0;
            PVOID RelocData = NULL;
            RtlImageDirectoryEntryToData(NtHeaders, IMAGE_DIRECTORY_ENTRY_BASERELOC, &RelocDataSize, &RelocData, ViewBase);
            if(RelocData && RelocDataSize)
            {
                Status = LdrpSetProtection(ViewBase,NtHeaders,FALSE);
                if(NT_SUCCESS(Status))
                {
                    Status = LdrRelocateImageWithBias(ViewBase, NtHeaders, 0LL, NULL, STATUS_SUCCESS,STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT);
                    LdrpSetProtection(ViewBase,NtHeaders,TRUE);
                    if(NT_SUCCESS(Status))
                    {
                        goto ENDLOAD1;
                    }
                }
            }
        }
        if(!NT_SUCCESS(Status) || ViewBase)
        {
            NtUnmapViewOfSection(((HANDLE)(LONG_PTR) -1)/*NtCurrentProcess()*/,ViewBase);
            result = FALSE;
        }
    }
    else if(!NT_SUCCESS(Status))
    {
        result = FALSE;
        goto ENDLOAD;
    }
ENDLOAD1:
    NtClose(SectionHandle);
    if(NT_SUCCESS(Status))
        result = TRUE;
    DllStruct& ds = DllMap[DllPath];
    ds.EntryPoint = EntryPoint;
    ds.ViewBase = ViewBase;
    ds.ViewSize = ViewSize;
    {
        //处理导入表
        ULONG IatDataSize = 0;
        IMAGE_IMPORT_DESCRIPTOR* IatData = NULL;
        RtlImageDirectoryEntryToData(NtHeaders, IMAGE_DIRECTORY_ENTRY_IMPORT, &IatDataSize, (PVOID *)&IatData, ViewBase);
        PVOID BaseAddress = ViewBase;
        if(IatData && IatDataSize)
        {
            while(IatData->Name && IatData->FirstThunk)
            {
                LPSTR ImportName = (LPSTR)((ULONG_PTR)BaseAddress + IatData->Name);
                PIMAGE_THUNK_DATA FirstThunk = (PIMAGE_THUNK_DATA)((ULONG_PTR)BaseAddress + IatData->FirstThunk);
                if(FirstThunk->u1.Function)
                {
                    WCHAR FuncName[0x1000];
                    if(LdrpLoadImportModule(ImportName,BaseAddress,FuncName))//否则应该报错
                        LdrpSnapIAT(NtHeaders, IatData, ViewBase, FuncName);
                    else
                    {
                        MessageBoxA(NULL,ImportName,ImportName,MB_OK);
//                      LeaveCriticalSection(&DllLock);
//                      return FALSE;
                    }
                }
                IatData++;
            }
        }

//      if(EntryPoint)
//          ((PDLL_INIT_ROUTINE)EntryPoint)(ViewBase,DLL_PROCESS_ATTACH,NULL);
        GetExportFuncs(NtHeaders, ViewBase, &ds);
    }

ENDLOAD:
    LeaveCriticalSection(&DllLock);
    return result;
}

NTSTATUS NTAPI LdrpSetProtection(PVOID ViewBase,PIMAGE_NT_HEADERS NtHeaders,BOOLEAN Restore)
{
    NTSTATUS Status;
    PVOID SectionBase;
    SIZE_T SectionSize;
    ULONG NewProtection, OldProtection, i;
    PIMAGE_SECTION_HEADER Section = IMAGE_FIRST_SECTION(NtHeaders);
    for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++)
    {
        if ((Section->SizeOfRawData) && !(Section->Characteristics & IMAGE_SCN_MEM_WRITE))
        {
            if (Restore)
            {
                if (Section->Characteristics & IMAGE_SCN_MEM_EXECUTE)
                {
                    NewProtection = PAGE_EXECUTE;
                }
                else
                {
                    NewProtection = PAGE_READONLY;
                }

                if (Section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
                {
                    NewProtection |= PAGE_NOCACHE;
                }
            }
            else
            {
                NewProtection = PAGE_READWRITE;
            }

            SectionBase = (PVOID)((ULONG_PTR)ViewBase + Section->VirtualAddress);
            SectionSize = Section->SizeOfRawData;
            if (SectionSize)
            {
                Status = NtProtectVirtualMemory(((HANDLE)(LONG_PTR) -1)/*NtCurrentProcess*/,&SectionBase,&SectionSize,NewProtection,&OldProtection);
                if (!NT_SUCCESS(Status)) return Status;
            }
        }
        Section++;
    }
    if (Restore) NtFlushInstructionCache(((HANDLE)(LONG_PTR) -1)/*NtCurrentProcess*/, NULL, 0);
    return STATUS_SUCCESS;
}

ULONG NTAPI LdrRelocateImageWithBias(PVOID BaseAddress,PIMAGE_NT_HEADERS NtHeaders,LONGLONG AdditionalBias,PCCH  LoaderName,ULONG Success,ULONG Conflict,ULONG Invalid)
{

    PIMAGE_DATA_DIRECTORY RelocationDDir;
    PIMAGE_BASE_RELOCATION RelocationDir, RelocationEnd;
    ULONG Count;
    ULONG_PTR Address;
    PUSHORT TypeOffset;
    LONGLONG Delta;

    if (SWAPW(NtHeaders->FileHeader.Characteristics) & IMAGE_FILE_RELOCS_STRIPPED)
    {
        return Conflict;
    }
    RelocationDDir = &NtHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
    if (SWAPD(RelocationDDir->VirtualAddress) == 0 || SWAPD(RelocationDDir->Size) == 0)
    {
        return Success;
    }
    Delta = (ULONG_PTR)BaseAddress - SWAPD(NtHeaders->OptionalHeader.ImageBase) + AdditionalBias;
    RelocationDir = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)BaseAddress + SWAPD(RelocationDDir->VirtualAddress));
    RelocationEnd = (PIMAGE_BASE_RELOCATION)((ULONG_PTR)RelocationDir + SWAPD(RelocationDDir->Size));
    while (RelocationDir < RelocationEnd && SWAPW(RelocationDir->SizeOfBlock) > 0)
    {
        SHORT Offset;
        USHORT Type;
        ULONG i;
        PUSHORT ShortPtr;
        PULONG LongPtr;
        PULONGLONG LongLongPtr;
        Count = (SWAPW(RelocationDir->SizeOfBlock) - sizeof(IMAGE_BASE_RELOCATION)) / sizeof(USHORT);
        Address = (ULONG_PTR)RVA(BaseAddress,SWAPD(RelocationDir->VirtualAddress));
        TypeOffset = (PUSHORT)(RelocationDir + 1);
        for (ULONG i = 0; i < Count; i++)
        {
            Offset = SWAPW(*TypeOffset) & 0xFFF;
            Type = SWAPW(*TypeOffset) >> 12;
            ShortPtr = (PUSHORT)RVA(Address,Offset);
            if((ULONG_PTR)ShortPtr >= (ULONG_PTR)RelocationDir && (ULONG_PTR)ShortPtr < (ULONG_PTR)RelocationEnd)
                continue;
            switch (Type)
            {
            case IMAGE_REL_BASED_ABSOLUTE:
                break;
            case IMAGE_REL_BASED_HIGH:
                *ShortPtr = HIWORD(MAKELONG(0, *ShortPtr) + (Delta & 0xFFFFFFFF));
                break;
            case IMAGE_REL_BASED_LOW:
                *ShortPtr = SWAPW(*ShortPtr) + LOWORD(Delta & 0xFFFF);
                break;
            case IMAGE_REL_BASED_HIGHLOW:
                LongPtr = (PULONG)RVA(Address,Offset);
                *LongPtr = SWAPD(*LongPtr) + (Delta & 0xFFFFFFFF);
                break;
            case IMAGE_REL_BASED_DIR64:
                LongLongPtr = (PUINT64)RVA(Address,Offset);
                *LongLongPtr = SWAPQ(*LongLongPtr) + Delta;
                break;
            case IMAGE_REL_BASED_HIGHADJ:
            case IMAGE_REL_BASED_MIPS_JMPADDR:
            default:
                RelocationDir = (PIMAGE_BASE_RELOCATION)NULL;
            }
            TypeOffset++;
        }
        RelocationDir = (PIMAGE_BASE_RELOCATION)TypeOffset;
        if (RelocationDir == NULL)
        {
            return Invalid;
        }
    }
    return Success;
}

FARPROC WINAPI GetProcAddressTA(LPCSTR DllPath,LPCSTR ProcName)
{
    ANSI_STRING DllPathA,ProcNameA;
    UNICODE_STRING DllPathW,ProcNameW;
    NTSTATUS status;
    if(!DllPath || !ProcName || DllPath[0] == 0 || ProcName[0] == 0)
        return NULL;
    WCHAR tmp1[0x1000],tmp2[0x1000];
    memset(tmp1,0,sizeof(tmp1));
    memset(tmp2,0,sizeof(tmp2));
    RtlInitAnsiString(&DllPathA,DllPath);
    RtlInitAnsiString(&ProcNameA,ProcName);
    DllPathW.Buffer = tmp1;
    DllPathW.MaximumLength = 0x1000;
    ProcNameW.Buffer = tmp2;
    ProcNameW.MaximumLength = 0x1000;
    status = RtlAnsiStringToUnicodeString(&DllPathW,&DllPathA,FALSE);
    if(!NT_SUCCESS(status))
        return FALSE;
    status = RtlAnsiStringToUnicodeString(&ProcNameW,&ProcNameA,FALSE);
    if(!NT_SUCCESS(status))
        return FALSE;
    return GetProcAddressTW(DllPathW.Buffer,ProcNameW.Buffer);
}

FARPROC WINAPI GetProcAddressTW(LPCWSTR DllPath,LPCWSTR ProcName)
{
    if(!DllPath || !ProcName || DllPath[0] == 0 || ProcName[0] == 0)
        return NULL;
    FARPROC result = NULL;
    EnterCriticalSection(&DllLock);
    std::map<std::wstring,DllStruct>::iterator itor1 = DllMap.find(DllPath);
    if(itor1 != DllMap.end())
    {
        std::map<std::wstring,FARPROC>::iterator itor2 = (*itor1).second.FuncMap.find(ProcName);
        if(itor2 != (*itor1).second.FuncMap.end())
        {
            result = (*itor2).second;
        }
    }
    LeaveCriticalSection(&DllLock);
    return result;
}

BOOL WINAPI FreeLibraryTA(LPCSTR DllPath)
{
    ANSI_STRING DllPathA;
    UNICODE_STRING DllPathW;
    NTSTATUS status;
    if(!DllPath || DllPath[0] == 0)
        return FALSE;
    WCHAR tmp[0x1000];
    memset(tmp,0,sizeof(tmp));
    RtlInitAnsiString(&DllPathA,DllPath);
    DllPathW.Buffer = tmp;
    DllPathW.MaximumLength = 0x1000;
    status = RtlAnsiStringToUnicodeString(&DllPathW,&DllPathA,FALSE);
    if(!NT_SUCCESS(status))
        return FALSE;
    return FreeLibraryTW(DllPathW.Buffer);
}

BOOL WINAPI FreeLibraryTW(LPCWSTR DllPath)
{
    BOOL result = FALSE;
    if(!DllPath || DllPath[0] == 0)
        return FALSE;

    EnterCriticalSection(&DllLock);
    std::map<std::wstring,DllStruct>::iterator itor = DllMap.find(DllPath);
    if(itor == DllMap.end())
    {
        result = FALSE;
        goto ENDFREE;
    }

    NTSTATUS Status;
    PVOID BaseAddress = (*itor).second.ViewBase;
    PVOID EntryPoint = (*itor).second.EntryPoint;

    ((PDLL_INIT_ROUTINE)EntryPoint)(BaseAddress,DLL_PROCESS_ATTACH,NULL);
    Status = NtUnmapViewOfSection(((HANDLE)(LONG_PTR) -1)/*NtCurrentProcess*/, BaseAddress);
    if(NT_SUCCESS(Status))
        result = TRUE;
    DllMap.erase(itor);
ENDFREE:
    LeaveCriticalSection(&DllLock);
    return result;
}

void main()
{
    InitializeCriticalSection(&DllLock);
    LoadLibraryTA("d:\\1.dll");
    FARPROC func=GetProcAddressTA("d:\\1.dll","func");
    ((void (__cdecl *)())func)();
}
回复 赞! 靠!

使用道具 举报

发表于 2015-6-23 08:52:44 | 显示全部楼层
你可以去看看memorymodule
回复 赞! 靠!

使用道具 举报

本版积分规则

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2026-8-9 04:05 , Processed in 0.018187 second(s), 7 queries , Gzip On, Redis On.

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表