元始天尊 发表于 2015-6-15 00:05:41

实现自己的LoadLibrary

决定实现自己的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)
                return FALSE;
        WCHAR tmp;
        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)
                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.VirtualAddress;
                                if(VA == NULL)
                                        return NULL;
                                RelocDataSize = tpnh->OptionalHeader.DataDirectory.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.VirtualAddress;
                                if(VA == NULL)
                                        return NULL;
                                RelocDataSize = tpnh->OptionalHeader.DataDirectory.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;
        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.VirtualAddress;
                        if(VA == NULL)
                                return NULL;
                        ExportDirSize = tpnh->OptionalHeader.DataDirectory.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.VirtualAddress;
                        if(VA == NULL)
                                return NULL;
                        ExportDirSize = tpnh->OptionalHeader.DataDirectory.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);
                        ANSI_STRING FuncNameA;
                        UNICODE_STRING FuncNameW;
                        WCHAR tmp;
                        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;
                                if(Ordinal >=0 && Ordinal < ExportDir->NumberOfFunctions)
                                {
                                        ULONG_PTR Function = (ULONG_PTR)BaseAddress + AddressOfFunctions;
                                        if(!(Function > (ULONG_PTR)ExportDir && Function < (ULONG_PTR)ExportDir + ExportDirSize))
                                        {
                                                ds.FuncMap = (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,PCCHLoaderName,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;
        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 || ProcName == 0)
                return NULL;
        WCHAR tmp1,tmp2;
        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 || ProcName == 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)
                return FALSE;
        WCHAR tmp;
        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)
                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);
                ANSI_STRING FuncNameA;
                UNICODE_STRING FuncNameW;
                WCHAR tmp;
                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;
                        if(Ordinal >=0 && Ordinal < ExportDir->NumberOfFunctions)
                        {
                                ULONG_PTR Function = (ULONG_PTR)ViewBase + AddressOfFunctions;
                                if(!(Function > (ULONG_PTR)ExportDir && Function < (ULONG_PTR)ExportDir + ExportDirSize))
                                {
                                        ds->FuncMap = (FARPROC)Function;
                                }
                        }
                }
        }
}

BOOL WINAPI LoadLibraryTA(LPCSTR DllPath)
{
        ANSI_STRING DllPathA;
        UNICODE_STRING DllPathW;
        NTSTATUS status;
        if(!DllPath || DllPath == 0)
                return FALSE;
        WCHAR tmp;
        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;
                                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.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;
                                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.VirtualAddress;
                        if(VA)
                        {
                                *RelocDataSize = tpnh->OptionalHeader.DataDirectory.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.VirtualAddress;
                        if(VA)
                        {
                                *RelocDataSize = tpnh->OptionalHeader.DataDirectory.Size;
                                *RelocData = (PVOID)((BYTE*)ViewBase + VA);
                        }
                }
        }
}

BOOL WINAPI LoadLibraryTW(LPCWSTR DllPath)
{
        if(!DllPath || DllPath == 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;
        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;
                                        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,PCCHLoaderName,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;
        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 || ProcName == 0)
                return NULL;
        WCHAR tmp1,tmp2;
        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 || ProcName == 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)
                return FALSE;
        WCHAR tmp;
        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)
                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)();
}

Golden Blonde 发表于 2015-6-23 08:52:44

你可以去看看memorymodule
页: [1]
查看完整版本: 实现自己的LoadLibrary