📄 r32r0.cpp
字号:
unsigned short int selector,
unsigned int call_type,
void *call_arg )
{
unsigned short int farcall[3];
HANDLE Thread;
if ( 0 == VirtualLock( Ring0Code, Ring0CodeLength ) )
{
PrintWin32Error( "VirtualLock() failed", GetLastError() );
}
else
{
farcall[2] = selector;
Thread = GetCurrentThread();
SetThreadPriority( Thread, THREAD_PRIORITY_TIME_CRITICAL );
Sleep( 0 );
printf( "ExecuteRing0Code() begin\n" );
/*
* 实际上这种情形下的SEH(结构化异常处理)没有意义,一旦在Ring 0代码
* 中引发异常,控制不会再回到Ring 3代码中来。也可能我对SEH的理解太
* 浅,还有别的办法让控制返回Ring 3代码。
*/
__try
{
/*
* 形参从右至左压栈,这是C调用风格,主要便于处理形参个数不定的
* 情况。虽然我这里只有两个形参,还是用了C调用风格,谁叫咱是标
* 准C程序员。
*
* 堆栈由Ring0Code中的"retf 8"负责平衡,这是最快的办法。
*/
__asm
{
push call_arg
push call_type
call fword ptr [farcall]
}
}
__except ( EXCEPTION_EXECUTE_HANDLER )
{
fprintf( stderr, "ExecuteRing0Code() failed\n" );
}
printf( "ExecuteRing0Code() end\n" );
SetThreadPriority( Thread, THREAD_PRIORITY_NORMAL );
VirtualUnlock( Ring0Code, Ring0CodeLength );
}
return;
} /* end of ExecuteRing0Code */
/*
* 在DDK的ntdef.h中InitializeObjectAttributes()是一个宏
*/
static VOID InitializeObjectAttributes ( OUT POBJECT_ATTRIBUTES InitializedAttributes,
IN PUNICODE_STRING ObjectName,
IN ULONG Attributes,
IN HANDLE RootDirectory,
IN PSECURITY_DESCRIPTOR SecurityDescriptor
)
{
InitializedAttributes->Length = sizeof( OBJECT_ATTRIBUTES );
InitializedAttributes->RootDirectory = RootDirectory;
InitializedAttributes->Attributes = Attributes;
InitializedAttributes->ObjectName = ObjectName;
InitializedAttributes->SecurityDescriptor = SecurityDescriptor;
InitializedAttributes->SecurityQualityOfService = NULL;
return;
} /* end of InitializeObjectAttributes */
static GATEDESCRIPTOR * InstallCallgate ( ULONG Gdtrbase, ULONG Gdtrlimit, DWORD CodeOffset,
GATEDESCRIPTOR *orig_callgate )
{
/*
* callgate指向GDT中最后一个描述符
*/
GATEDESCRIPTOR *callgate = ( GATEDESCRIPTOR * )( Gdtrbase + ( Gdtrlimit & 0xfffffff8 ) );
/*
* 搜索空闲描述符
*/
for ( ; ( ULONG )callgate > Gdtrbase; callgate-- )
{
/*
* GDT中不一定都是门描述符,但所有类型的描述符P位在同一位域,并且
* 意义接近。
*/
if ( 0 == callgate->p )
{
/*
* 备份即将被征用的"空闲"描述符
*/
memcpy( orig_callgate, callgate, sizeof( GATEDESCRIPTOR ) );
/*
* 设置成DPL等于3的调用门
*/
callgate->offset_low = ( WORD )( CodeOffset & 0x0000ffff );
callgate->selector = RING0_CODE_SELECTOR;
callgate->parameter_count = 2;
callgate->reserved = 0;
callgate->type = 12;
callgate->s = 0;
callgate->dpl = 3;
callgate->p = 1;
callgate->offset_high = ( WORD )( CodeOffset >> 16 );
return( callgate );
}
}
return( NULL );
} /* end of InstallCallgate */
/*
* ntdll.dll输出了所有的Native API
*/
static BOOLEAN LocateNtdllEntry ( void )
{
BOOLEAN boolean_ret = FALSE;
char NTDLL_DLL[] = "ntdll.dll";
HMODULE ntdll_dll = NULL;
/*
* returns a handle to a mapped module without incrementing its
* reference count
*/
if ( ( ntdll_dll = GetModuleHandle( NTDLL_DLL ) ) == NULL )
{
PrintWin32Error( "GetModuleHandle() failed", GetLastError() );
return( FALSE );
}
if ( !( RtlInitUnicodeString = ( RTLINITUNICODESTRING )GetProcAddress( ntdll_dll,
"RtlInitUnicodeString" ) ) )
{
goto LocateNtdllEntry_return;
}
if ( !( ZwOpenSection = ( ZWOPENSECTION )GetProcAddress( ntdll_dll,
"ZwOpenSection" ) ) )
{
goto LocateNtdllEntry_return;
}
if ( !( ZwClose = ( ZWCLOSE )GetProcAddress( ntdll_dll,
"ZwClose" ) ) )
{
goto LocateNtdllEntry_return;
}
if ( !( ZwMapViewOfSection = ( ZWMAPVIEWOFSECTION )GetProcAddress( ntdll_dll,
"ZwMapViewOfSection" ) ) )
{
goto LocateNtdllEntry_return;
}
if ( !( ZwUnmapViewOfSection = ( ZWUNMAPVIEWOFSECTION )GetProcAddress( ntdll_dll,
"ZwUnmapViewOfSection" ) ) )
{
goto LocateNtdllEntry_return;
}
if ( !( ZwQuerySystemInformation = ( ZWQUERYSYSTEMINFORMATION )GetProcAddress( ntdll_dll,
"ZwQuerySystemInformation" ) ) )
{
goto LocateNtdllEntry_return;
}
if ( !( RtlNtStatusToDosError = ( RTLNTSTATUSTODOSERROR )GetProcAddress( ntdll_dll,
"RtlNtStatusToDosError" ) ) )
{
goto LocateNtdllEntry_return;
}
boolean_ret = TRUE;
LocateNtdllEntry_return:
if ( FALSE == boolean_ret )
{
PrintWin32Error( "GetProcAddress() failed", GetLastError() );
}
ntdll_dll = NULL;
return( boolean_ret );
} /* end of LocateNtdllEntry */
/*
* ntoskrnl.exe输出Kernel API
*/
static BOOLEAN LocateNtoskrnlEntry ( void )
{
BOOLEAN boolean_ret = TRUE;
char NTOSKRNL_EXE[] = "ntoskrnl.exe";
HMODULE ntoskrnl_exe = NULL;
unsigned char *Base = NULL;
Base = ( unsigned char * )PrivateFindModule( ( const char * )NTOSKRNL_EXE );
if ( NULL == Base )
{
fprintf( stderr, "PrivateFindModule() failed\n" );
boolean_ret = FALSE;
goto LocateNtoskrnlEntry_return;
}
/*
* Header : Declared in Winbase.h; include Windows.h
* Library: Use Kernel32.lib
*
* HMODULE LoadLibrary
* (
* LPCTSTR lpFileName
* );
*/
if ( NULL == ( ntoskrnl_exe = LoadLibrary( NTOSKRNL_EXE ) ) )
{
PrintWin32Error( "LoadLibrary() failed", GetLastError() );
boolean_ret = FALSE;
goto LocateNtoskrnlEntry_return;
}
if ( !( MmGetPhysicalAddress = ( MMGETPHYSICALADDRESS )GetProcAddress( ntoskrnl_exe,
"MmGetPhysicalAddress" ) ) )
{
boolean_ret = FALSE;
goto LocateNtoskrnlEntry_return;
}
MmGetPhysicalAddress = ( MMGETPHYSICALADDRESS )
( Base + ( unsigned int )
( ( unsigned char * )MmGetPhysicalAddress -
( unsigned char * )ntoskrnl_exe
)
);
printf( "ntoskrnl.exe base = 0x%08X\n"
"MmGetPhysicalAddress = 0x%08X\n", Base, MmGetPhysicalAddress );
LocateNtoskrnlEntry_return:
if ( ntoskrnl_exe != NULL )
{
FreeLibrary( ntoskrnl_exe );
ntoskrnl_exe = NULL;
}
return( boolean_ret );
} /* end of LocateNtoskrnlEntry */
static BOOLEAN MapPhysicalMemory ( IN HANDLE SectionHandle,
IN OUT PVOID *LinearAddress,
IN OUT PULONG MapSize,
IN OUT PLARGE_INTEGER PhysicalAddress,
IN ULONG Protect
)
{
NTSTATUS status;
char error_msg[256];
ULONG mapsize = *MapSize;
DWORD LowPart = PhysicalAddress->LowPart;
*LinearAddress = NULL;
#if 0
/*
* 假设GDTR的物理基址在0x0003F000,而虚拟内存分配粒度是64KB,向下舍入
* 后得到0x00030000,ZwMapViewOfSection()会报告"试图访问无效的地址"。
*/
LowPart %= system_info.dwAllocationGranularity;
if ( LowPart != 0 )
{
/*
* 向下舍入到dwAllocationGranularity(内存分配粒度)的边界
*/
PhysicalAddress->LowPart -= LowPart;
mapsize += LowPart;
*MapSize = mapsize;
}
#endif
/*
* 按照DDK文档的意思,物理地址要向下舍入到内存分配粒度的边界。按我的理
* 解,这里的(物理)内存分配粒度应该是一页,而GetSystemInfo()返回的是虚
* 拟内存分配粒度(64KB)。可能这个理解有问题,暂时先搁置一下。
*/
LowPart %= system_info.dwPageSize;
if ( LowPart != 0 )
{
/*
* 向下舍入到dwPageSize(页大小)的边界(4096)
*/
PhysicalAddress->LowPart -= LowPart;
mapsize += LowPart;
*MapSize = mapsize;
}
mapsize %= system_info.dwPageSize;
if ( mapsize != 0 )
{
/*
* 向上舍入到dwPageSize(页大小)的边界
*/
*MapSize += system_info.dwPageSize - mapsize;
}
/*
* DDK文档里有详细介绍。
*
* ZwMapViewOfSection
* (
* IN HANDLE SectionHandle,
* IN HANDLE ProcessHandle,
* IN OUT PVOID *BaseAddress,
* IN ULONG ZeroBits,
* IN ULONG CommitSize,
* IN OUT PLARGE_INTEGER SectionOffset,
* IN OUT PULONG ViewSize,
* IN SECTION_INHERIT InheritDisposition,
* IN ULONG AllocationType,
* IN ULONG Protect
* );
*
* BaseAddress
*
* 目标映射到进程空间后的线性基址,初始化成NULL则由操作系统任意安
* 排映射后的线性基址。Unix程序员可与mmap()的第一形参做个比较。
*
* CommitSize
*
* 以字节为单位,向上舍入到dwPageSize(页大小)的边界。
*
* SectionOffset
*
* 对我们这个程序来说,就是物理地址,向下舍入到
* dwAllocationGranularity(内存分配粒度)的边界。
*
* ViewSize
*
* 可以简单等同于CommitSize,向上舍入到dwPageSize(页大小)的边界。
*
* InheritDisposition
*
* 指明子进程如何继承该映射。
*
* Protect
*
* 指明访问权限,比如PAGE_READONLY、PAGE_READWRITE。
*/
status = ZwMapViewOfSection
(
SectionHandle,
( HANDLE )-1,
LinearAddress,
0,
*MapSize,
PhysicalAddress,
MapSize,
ViewShare,
0,
Protect
);
if ( !NT_SUCCESS( status ) )
{
sprintf( error_msg, "Could not map 0x%08X bytes PhysicalMemory from 0x%08X",
*MapSize, PhysicalAddress->LowPart );
PrintZwError( error_msg, status );
return( FALSE );
}
return( TRUE );
} /* end of MapPhysicalMemory */
static HANDLE OpenPhysicalMemory ( ACCESS_MASK DesiredAccess )
{
OBJECT_ATTRIBUTES attributes;
HANDLE mem;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -