#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)(); }