1.所有网上那些代码都不靠谱,别抄了,抄了都是白费~
2.支持GetModuleHandle等离奇API不是很容易
我的思路是直接使用Windows自带的加载模型
首先来看一下Pe加载过程(这里不谈论EXE)
LoadLibrary后回去LdrLoadDll,然后去LdrpLoadDLL,然后会一层层走到ZwOpenFile(这里必须有文件——随便你怎么想了),然后ZwCreateSection做个MapFile,以后的所有处理都是在MapViewOfSection的基础上进行的,于是不需要关心Pe结构的问题,只需要提供合理的MapView,那么M$会替我们搞定各种问题,so 有了如下一个思路:
hook ZwMapViewOfSection对MapView进行直接返回~
首先来一份代码
#include "stdafx.h"
//////////////////////////////////////////////////////////////////////////
//LoadLibrary-->LdrLoadDll-->ZwOpenFile //这里只是获取Handle
// -->ZwQuerySection //这里没关系,COR的DLL会查询Image信息
// -->ZwCreateSection //这里没关系 获得handle
// -->ZwMapViewOfSection //这里有关系!,问题是这是什么情况,什么情况呢?
// oo!
//myloader
//Save EmptyPeDLL 为LoadDLLName
//hook ZwCreateSection ZwQuerySection
//ZwCreateSection 创建一个有名字的Section SEC_COMMIT模式,将CopySection ok的代码扔进去
//Set FiltSection=TRUE
//LoadLibrary LoadDLLName
//Set FiltSection=FALSE
#include <winternl.h>
#include "inlinehook.h"
#ifndef __GNUC__
// disable warnings about pointer <-> DWORD conversions
#pragma warning( disable : 4311 4312 4390 4996)
#endif
#ifdef _WIN64
#define POINTER_TYPE ULONGLONG
#else
#define POINTER_TYPE DWORD
#endif
#define RVATOVA( base, offset )(((DWORD)(base) + (DWORD)(offset)))
#define LDRP_RELOCATION_FINAL 0x2
typedef enum _SECTION_INHERIT {
ViewShare = 1,
ViewUnmap = 2
} SECTION_INHERIT;
typedef enum _SECTION_INFORMATION_CLASS
{
SectionBasicInformation,
SectionImageInformation
} SECTION_INFORMATION_CLASS, *PSECTION_INFORMATION_CLASS;
#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; \
}
typedef NTSTATUS (__stdcall *T_NtUnmapViewOfSection)(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress
);
typedef NTSTATUS (__stdcall *T_NtOpenSection)(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
typedef NTSTATUS (__stdcall *T_NtOpenDirectoryObject)(
OUT PHANDLE DirectoryHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes
);
typedef NTSTATUS (__stdcall *T_NtMapViewOfSection)(
IN HANDLE SectionHandle,
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN ULONG CommitSize,
IN OUT PLARGE_INTEGER SectionOffset, // optional
IN OUT PULONG ViewSize,
IN SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType,
IN ULONG Protect
);
typedef VOID (__stdcall *T_RtlInitUnicodeString)(
IN OUT PUNICODE_STRING DestinationString,
IN PCWSTR SourceString
);
typedef ULONG (__stdcall *T_RtlNtStatusToDosError) (
IN NTSTATUS Status
);
typedef VOID (__stdcall *T_NtClose)(
IN HANDLE Object
);
typedef NTSTATUS (__stdcall *T_NtCreateFile)(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN PLARGE_INTEGER AllocationSize OPTIONAL,
IN ULONG FileAttributes,
IN ULONG ShareAccess,
IN ULONG CreateDisposition,
IN ULONG CreateOptions,
IN PVOID EaBuffer OPTIONAL,
IN ULONG EaLength
);
typedef NTSTATUS (__stdcall *T_NtOpenFile)(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG ShareAccess,
IN ULONG OpenOptions
);
typedef NTSTATUS (__stdcall *T_NtCreateSection)(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes, // Optional
IN PLARGE_INTEGER MaximumSize, // Optional
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle // Optional
);
typedef NTSTATUS (__stdcall *T_NtQuerySection)(
IN HANDLE SectionHandle,
IN SECTION_INFORMATION_CLASS SectionInformationClass,
OUT PVOID SectionInformation,
IN ULONG SectionInformationLength,
OUT PULONG ResultLength OPTIONAL
);
typedef NTSTATUS (__stdcall *T_NtProtectVirtualMemory)(
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN OUT PULONG ProtectSize,
IN ULONG NewProtect,
OUT PULONG OldProtect
);
typedef NTSTATUS (NTAPI *T_LdrLoadDll)(IN PWCHAR PathToFile OPTIONAL,
IN PULONG Flags OPTIONAL,
IN PUNICODE_STRING ModuleFileName,
OUT PHANDLE ModuleHandle );
T_RtlInitUnicodeString pRtlInitUnicodeString;
T_NtUnmapViewOfSection pNtUnmapViewOfSection;
T_NtOpenFile pNtOpenFile;
T_NtOpenDirectoryObject pNtOpenDirectoryObject;
T_NtOpenSection pNtOpenSection;
T_NtMapViewOfSection pNtMapViewOfSection;
T_RtlNtStatusToDosError pRtlNtStatusToDosError;
T_NtClose pNtClose;
T_NtCreateFile pNtCreateFile;
T_NtCreateSection pNtCreateSection;
T_NtQuerySection pNtQuerySection;
T_LdrLoadDll pLdrLoadDll;
T_NtUnmapViewOfSection OldNtUnmapViewOfSection=NULL;
T_NtOpenFile OldNtOpenFile=NULL;
T_NtCreateSection OldNtCreateSection=NULL;
T_NtQuerySection OldNtQuerySection=NULL;
T_NtMapViewOfSection OldNtMapViewOfSection=NULL;
//////////////////////////////////////////////////////////////////////////
//重要数据
//////////////////////////////////////////////////////////////////////////
WCHAR szDllName[MAX_PATH]={0};
BOOL m_bSetFilter=FALSE;
HANDLE m_hFileHandle=0;
HANDLE m_hSectionHandle = 0;
PVOID m_PeImageMem = NULL;
ULONG m_PeImageSize =0;
UINT m_ImageCount=0;
//////////////////////////////////////////////////////////////////////////
//定义
//////////////////////////////////////////////////////////////////////////
NTSTATUS __stdcall OnNtOpenFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG ShareAccess,
IN ULONG OpenOptions
);
NTSTATUS __stdcall OnNtCreateSection(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes, // Optional
IN PLARGE_INTEGER MaximumSize, // Optional
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle // Optional
);
NTSTATUS __stdcall OnNtQuerySection(
IN HANDLE SectionHandle,
IN SECTION_INFORMATION_CLASS SectionInformationClass,
OUT PVOID SectionInformation,
IN ULONG SectionInformationLength,
OUT PULONG ResultLength OPTIONAL
);
NTSTATUS __stdcall OnNtMapViewOfSection(
IN HANDLE SectionHandle,
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN ULONG CommitSize,
IN OUT PLARGE_INTEGER SectionOffset, // optional
IN OUT PULONG ViewSize,
IN SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType,
IN ULONG Protect
);
NTSTATUS __stdcall OnNtUnmapViewOfSection(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress
);
UINT GetImageSize(PVOID lpImage);
//////////////////////////////////////////////////////////////////////////
//初始化
//////////////////////////////////////////////////////////////////////////
BOOL m_bLoadSection=FALSE;
BOOL initLoad4()
{
if (m_bLoadSection)
{
return m_bLoadSection;
}
if( !(pRtlInitUnicodeString = (T_RtlInitUnicodeString)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")),"RtlInitUnicodeString" ))) return FALSE;
if( !(pNtUnmapViewOfSection = (T_NtUnmapViewOfSection) GetProcAddress( GetModuleHandle(TEXT("ntdll.dll")),"NtUnmapViewOfSection" ))) return FALSE;
if( !(pNtOpenFile = (T_NtOpenFile)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")),"NtOpenFile" ))) return FALSE;
if( !(pNtOpenDirectoryObject = (T_NtOpenDirectoryObject)GetProcAddress( GetModuleHandle(TEXT("ntdll.dll")),"NtOpenDirectoryObject" )) ) return FALSE;
if( !(pNtOpenSection = (T_NtOpenSection)GetProcAddress( GetModuleHandle(TEXT("ntdll.dll")),"NtOpenSection" )) ) return FALSE;
if( !(pNtMapViewOfSection = (T_NtMapViewOfSection) GetProcAddress( GetModuleHandle(TEXT("ntdll.dll")),"NtMapViewOfSection" )) ) return FALSE;
if( !(pRtlNtStatusToDosError = (T_RtlNtStatusToDosError)GetProcAddress( GetModuleHandle(TEXT("ntdll.dll")),"RtlNtStatusToDosError" )) ) return FALSE;
if( !(pNtClose = (T_NtClose) GetProcAddress( GetModuleHandle(TEXT("ntdll.dll")),"NtClose" )) ) return FALSE;
if( !(pNtCreateFile = (T_NtCreateFile)GetProcAddress( GetModuleHandle(TEXT("ntdll.dll")),"NtCreateFile" )) ) return FALSE;
if( !(pNtCreateSection = (T_NtCreateSection)GetProcAddress( GetModuleHandle(TEXT("ntdll.dll")),"NtCreateSection" )) ) return FALSE;
if (!(pNtQuerySection = (T_NtQuerySection)GetProcAddress(GetModuleHandle(TEXT("ntdll.dll")),"NtQuerySection" ))) return FALSE;
if (!(pLdrLoadDll=(T_LdrLoadDll)GetProcAddress( GetModuleHandle(TEXT("ntdll.dll")),"LdrLoadDll" ))) return FALSE;
InlineHook((void *)pNtOpenFile,(void *)OnNtOpenFile,(void **)&OldNtOpenFile);
InlineHook((void *)pNtCreateSection,(void *)OnNtCreateSection,(void **)&OldNtCreateSection);
InlineHook((void *)pNtQuerySection,(void *)OnNtQuerySection,(void **)&OldNtQuerySection);
InlineHook((void *)pNtMapViewOfSection,(void *)OnNtMapViewOfSection,(void **)&OldNtMapViewOfSection);
InlineHook((void *)pNtUnmapViewOfSection,(void *)OnNtUnmapViewOfSection,(void **)&OldNtUnmapViewOfSection);
m_bLoadSection = TRUE;
return TRUE;
}
BOOL LdrpLoadDll(LPCWSTR lpszDllName,PVOID pDllMem,UINT DllSize,HMODULE *pOutMod)
{
UNICODE_STRING DllNameString;
NTSTATUS ns;
m_bSetFilter = FALSE;
if (initLoad4())
{
wcsncpy(szDllName,lpszDllName,MAX_PATH);
pRtlInitUnicodeString(&DllNameString,lpszDllName);
m_PeImageMem = pDllMem;
m_PeImageSize = DllSize;
m_ImageCount =0;
m_hSectionHandle = 0;
m_hFileHandle = 0;
m_bSetFilter = TRUE;
if (pOutMod)
{
//*pOutMod = LoadLibraryW(lpszDllName);
ULONG Flags=0;
ns = pLdrLoadDll(NULL,NULL,&DllNameString,(PHANDLE)pOutMod);
if (NT_SUCCESS(ns))
{
m_bSetFilter = FALSE;
return TRUE;
}
else
{
CString mfx;
mfx.Format(TEXT("2 %08x"),ns);
AfxMessageBox(mfx);
}
}
m_bSetFilter = FALSE;
return FALSE;
}
return FALSE;
}
BOOL LdrLoadDllFive(LPCWSTR lpszDllName,PVOID pDllMem,UINT DllSize,HMODULE *pOutMod)
{
//BOOL successfull;
CopyFile(TEXT("EmptyDLL.dll"),lpszDllName,FALSE);
//if(ImageFile((BYTE *)pDllMem,(BYTE **)&code,&Size))
{
return LdrpLoadDll(lpszDllName,pDllMem,DllSize,pOutMod);
}
return FALSE;
}
HANDLE OpenFile(LPCWSTR lpszDllName)
{
HANDLE hFile;
NTSTATUS stat;
IO_STATUS_BLOCK iosb;
UNICODE_STRING fileString;
OBJECT_ATTRIBUTES fileattributes;
pRtlInitUnicodeString( &fileString, lpszDllName);
InitializeObjectAttributes( &fileattributes, &fileString,
OBJ_CASE_INSENSITIVE, NULL, NULL);
stat=pNtCreateFile( &hFile,
FILE_GENERIC_READ|FILE_GENERIC_WRITE|FILE_GENERIC_EXECUTE,
&fileattributes,
&iosb,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ|FILE_SHARE_WRITE,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE | FILE_SYNCHRONOUS_IO_NONALERT,
NULL,
0 );
if(!NT_SUCCESS(stat)) {
return 0;
}
return hFile;
}
PVOID MapImageFile(HANDLE hFile,LPCWSTR lpszSectionName,HANDLE *hSection,UINT *lpnImageSize)
{
PVOID MemAddress=NULL;
ULONG MemLength=0;
NTSTATUS ns;
HANDLE hTemp;
*hSection = 0;
ns= pNtCreateSection(hSection,
SECTION_ALL_ACCESS,
NULL,
NULL,
PAGE_EXECUTE,
SEC_IMAGE,
hFile);
if(!NT_SUCCESS(ns))
{
return NULL;
}
hTemp = *hSection;
ns = pNtMapViewOfSection(hTemp,
(HANDLE) -1,
&MemAddress,
0L,
0L,
NULL,
&MemLength,
ViewShare,
0,
PAGE_READWRITE);
if (NT_SUCCESS(ns))
{
*lpnImageSize = MemLength;
return MemAddress;
}
return NULL;
}
BOOL GetDLLMapMem(LPCWSTR lpszFileFullPath,PVOID *pDllMem,UINT *ImageSize)
{
PVOID TempMem=NULL;
PVOID pMem = NULL;
HANDLE hFile =0;
WCHAR szFileName[MAX_PATH];
WCHAR szSectionName[MAX_PATH];
HANDLE hSection;
BOOL bRet= FALSE;
UINT MemSize=0;
UINT mImageSize=0;
UINT allocSize=0;
if (initLoad4())
{
swprintf(szSectionName,L"\\DLL_%08x",GetTickCount());
swprintf(szFileName,L"\\??\\%ws",lpszFileFullPath);
hFile = OpenFile(szFileName);
if (hFile)
{
pMem = MapImageFile(hFile,szSectionName,&hSection,&MemSize);
if (pMem)
{
//计算ImageSize,创建pe 并复制
//
mImageSize = GetImageSize(pMem);
allocSize = MemSize;
if (mImageSize>MemSize)
{
allocSize = mImageSize;
}
TempMem = VirtualAlloc(NULL,allocSize,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
if (TempMem)
{
RtlCopyMemory(TempMem,pMem,allocSize);
*pDllMem = TempMem;
*ImageSize = allocSize;
bRet =TRUE;
}
//pNtClose(hSection);
}
if (hSection)
{
pNtClose(hSection);
}
pNtClose(hFile);
}
}
return bRet;
}
UINT GetImageSize(PVOID lpImage)
{
PIMAGE_DOS_HEADER ImageDosHeader;
PIMAGE_NT_HEADERS ImageNtHeaders;
ULONG FileAlignment,SectionAlignment,NumberOfSections,SizeOfImage,SizeOfHeaders;
ImageDosHeader=(PIMAGE_DOS_HEADER)lpImage;
if (ImageDosHeader->e_magic!=IMAGE_DOS_SIGNATURE)
{
return 0;
}
ImageNtHeaders=(PIMAGE_NT_HEADERS)((char *)lpImage+ImageDosHeader->e_lfanew);
if (ImageNtHeaders->Signature!=IMAGE_NT_SIGNATURE)
{
return 0;
}
FileAlignment=ImageNtHeaders->OptionalHeader.FileAlignment;
SectionAlignment=ImageNtHeaders->OptionalHeader.SectionAlignment;
NumberOfSections=ImageNtHeaders->FileHeader.NumberOfSections;
SizeOfImage=ImageNtHeaders->OptionalHeader.SizeOfImage;
SizeOfHeaders=ImageNtHeaders->OptionalHeader.SizeOfHeaders;
// SizeOfImage=AlignSize(SizeOfImage,SectionAlignment);
return SizeOfImage;
}
NTSTATUS __stdcall OnNtOpenFile(
OUT PHANDLE FileHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes,
OUT PIO_STATUS_BLOCK IoStatusBlock,
IN ULONG ShareAccess,
IN ULONG OpenOptions
)
{
NTSTATUS ns;
ns = OldNtOpenFile(FileHandle,DesiredAccess,ObjectAttributes,IoStatusBlock,ShareAccess,OpenOptions);
if (m_bSetFilter&&NT_SUCCESS(ns))
{
if (ObjectAttributes)
{
if (ObjectAttributes->ObjectName)
{
if (ObjectAttributes->ObjectName->Buffer)
{
if (wcsstr(ObjectAttributes->ObjectName->Buffer,szDllName))
{
//////////////////////////////////////////////////////////////////////////
//记录一下
//////////////////////////////////////////////////////////////////////////
if(!m_hFileHandle)
m_hFileHandle = *FileHandle;
}
}
}
}
}
return ns;
}
NTSTATUS __stdcall OnNtCreateSection(
OUT PHANDLE SectionHandle,
IN ACCESS_MASK DesiredAccess,
IN POBJECT_ATTRIBUTES ObjectAttributes, // Optional
IN PLARGE_INTEGER MaximumSize, // Optional
IN ULONG SectionPageProtection,
IN ULONG AllocationAttributes,
IN HANDLE FileHandle // Optional
)
{
NTSTATUS ns;
ns = OldNtCreateSection(SectionHandle,DesiredAccess,ObjectAttributes,MaximumSize,SectionPageProtection,AllocationAttributes,FileHandle);
if (m_bSetFilter&&NT_SUCCESS(ns))
{
if (FileHandle==m_hFileHandle)
{
if(!m_hSectionHandle)
m_hSectionHandle = *SectionHandle;
//*SectionHandle = m_hRealImageSection;
}
}
return ns;
}
NTSTATUS __stdcall OnNtQuerySection(
IN HANDLE SectionHandle,
IN SECTION_INFORMATION_CLASS SectionInformationClass,
OUT PVOID SectionInformation,
IN ULONG SectionInformationLength,
OUT PULONG ResultLength OPTIONAL
)
{
NTSTATUS ns;
if (m_bSetFilter)
{
if (m_hSectionHandle==SectionHandle)
{
//问题很严峻
if (SectionInformationClass==SectionImageInformation)
{
OutputDebugStringA("SectionImageInformation");
}
if (SectionInformationClass==SectionBasicInformation)
{
OutputDebugStringA("SectionBasicInformation");
}
}
}
ns = OldNtQuerySection(SectionHandle,SectionInformationClass,SectionInformation,SectionInformationLength,ResultLength);
return ns;
}
NTSTATUS __stdcall OnNtMapViewOfSection(
IN HANDLE SectionHandle,
IN HANDLE ProcessHandle,
IN OUT PVOID *BaseAddress,
IN ULONG ZeroBits,
IN ULONG CommitSize,
IN OUT PLARGE_INTEGER SectionOffset, // optional
IN OUT PULONG ViewSize,
IN SECTION_INHERIT InheritDisposition,
IN ULONG AllocationType,
IN ULONG Protect
)
{
BOOL bFilterd=FALSE;
NTSTATUS ns;
if (m_bSetFilter)
{
if (SectionHandle==m_hSectionHandle&&SectionOffset==NULL)
{
//问题出在unmap上,第二次之后的无效了
m_ImageCount++;
bFilterd = TRUE;
Protect = PAGE_EXECUTE;
}
}
ns = OldNtMapViewOfSection(SectionHandle,ProcessHandle,BaseAddress,ZeroBits,CommitSize,SectionOffset,ViewSize,InheritDisposition,AllocationType,Protect);
if (NT_SUCCESS(ns))
{
if (bFilterd)
{
//最大的问题是无法解释的问题
OutputDebugStringA("filter");
*BaseAddress = m_PeImageMem;
if (ViewSize)
{
*ViewSize = m_PeImageSize;
}
}
}
return ns;
}
NTSTATUS __stdcall OnNtUnmapViewOfSection(
IN HANDLE ProcessHandle,
IN PVOID BaseAddress
)
{
if (m_bSetFilter)
{
if (BaseAddress==m_PeImageMem)
{
return 0;
}
}
return OldNtUnmapViewOfSection(ProcessHandle,BaseAddress);
}
void TestLoad(LPCWSTR lpszFileFullPath)
{
PVOID m_FileData=NULL;
int m_FileSize=0;
TCHAR szFileName[MAX_PATH];
if (GetDLLMapMem(lpszFileFullPath,&m_FileData,(UINT *)&m_FileSize))
{
_stprintf(szFileName,TEXT("%d.dll"),m_FileSize);
HMODULE hmod;
if(LdrLoadDllFive(szFileName,m_FileData,m_FileSize,&hmod))
{
OutputDebugStringA("Test ok");
}
}
}
但是测试结果是始终报错:STATUS_INVALID_IMAGE_FORMAT
于是我彻底费解了~求论坛里搞PE文件方面的大牛来解答~
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课