📄 r32r0.cpp
字号:
UNICODE_STRING memString;
WCHAR memName[] = L"\\Device\\PhysicalMemory";
NTSTATUS status;
RtlInitUnicodeString( &memString, memName );
InitializeObjectAttributes( &attributes, &memString,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL, NULL );
status = ZwOpenSection( &mem, DesiredAccess, &attributes );
if ( !NT_SUCCESS( status ) )
{
PrintZwError( "Could not open \\Device\\PhysicalMemory", status );
return( NULL );
}
return( mem );
} /* end of OpenPhysicalMemory */
/*
* 这是一个偏向Unix编程风格的函数。跟VI与EMACS是两种哲学流派一样,我不习惯
* 也不喜欢匈牙利命名法。更深层次的原因是我非Windows程序员,见谅,:-)
*/
static void outputBinary ( FILE *out, const unsigned char *byteArray, const size_t byteArrayLen )
{
size_t offset, k, j, i;
fprintf( out, "byteArray [ %u bytes ] -> \n", byteArrayLen );
if ( byteArrayLen <= 0 )
{
return;
}
i = 0;
offset = 0;
for ( k = byteArrayLen / 16; k > 0; k--, offset += 16 )
{
fprintf( out, "%08X ", offset );
for ( j = 0; j < 16; j++, i++ )
{
if ( j == 8 )
{
fprintf( out, "-%02X", byteArray[i] );
}
else
{
fprintf( out, " %02X", byteArray[i] );
}
}
fprintf( out, " " );
i -= 16;
for ( j = 0; j < 16; j++, i++ )
{
/*
* if ( isprint( (int)byteArray[i] ) )
*/
#if 0
if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] <= 255 )
&& ( byteArray[i] != 0x7f ) )
#endif
if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] < 0x7f ) )
{
fprintf( out, "%c", byteArray[i] );
}
else
{
fprintf( out, "." );
}
}
fprintf( out, "\n" );
} /* end of for */
k = byteArrayLen - i;
if ( k <= 0 )
{
return;
}
fprintf( out, "%08X ", offset );
for ( j = 0 ; j < k; j++, i++ )
{
if ( j == 8 )
{
fprintf( out, "-%02X", byteArray[i] );
}
else
{
fprintf( out, " %02X", byteArray[i] );
}
}
i -= k;
for ( j = 16 - k; j > 0; j-- )
{
fprintf( out, " " );
}
fprintf( out, " " );
for ( j = 0; j < k; j++, i++ )
{
#if 0
if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] <= 255 )
&& ( byteArray[i] != 0x7f ) )
#endif
if ( ( byteArray[i] >= ' ' ) && ( byteArray[i] < 0x7f ) )
{
fprintf( out, "%c", byteArray[i] );
}
else
{
fprintf( out, "." );
}
}
fprintf( out, "\n" );
return;
} /* end of outputBinary */
static void PrintWin32Error ( char *message, DWORD dwMessageId )
{
char *errMsg;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
dwMessageId,
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
( LPTSTR )&errMsg, 0, NULL );
fprintf( stderr, "%s: %s", message, errMsg );
LocalFree( errMsg );
return;
} /* end of PrintWin32Error */
static void PrintZwError ( char *message, NTSTATUS status )
{
char *errMsg;
FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL,
RtlNtStatusToDosError( status ),
MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ),
( LPTSTR )&errMsg, 0, NULL );
fprintf( stderr, "%s: %s", message, errMsg );
LocalFree( errMsg );
return;
} /* end of PrintZwError */
static PVOID PrivateFindModule ( const char *ModuleName )
{
NTSTATUS status;
PSYSTEM_MODULE_INFORMATION module = NULL;
PVOID Base = NULL;
ULONG n = 0;
ULONG i = 0;
void *buf = NULL;
ZwQuerySystemInformation( SystemModuleInformation, &n, 0, &n );
if ( NULL == ( buf = calloc( ( size_t )n, 1 ) ) )
{
fprintf( stderr, "calloc() failed\n" );
goto PrivateFindModule_return;
}
/*
* <<Windows NT/2000 Native API Reference>> by Gary Nebbett所给的例子
* 1.3以及A.2对第二、三形参理解有误,下面才是正确的用法。
*/
status = ZwQuerySystemInformation( SystemModuleInformation, buf, n, NULL );
if ( !NT_SUCCESS( status ) )
{
PrintZwError( "ZwQuerySystemInformation() failed", status );
goto PrivateFindModule_return;
}
module = ( PSYSTEM_MODULE_INFORMATION )( ( PULONG )buf + 1 );
n = *( ( PULONG )buf );
for ( i = 0; i < n; i++ )
{
if ( 0 == _stricmp( module[i].ImageName + module[i].ModuleNameOffset, ModuleName ) )
{
Base = module[i].Base;
}
}
PrivateFindModule_return:
if ( buf != NULL )
{
free( buf );
buf = NULL;
}
return( Base );
} /* end of PrivateFindModule */
/*
* 将某固定范围的线性地址转换成物理地址
*/
static PHYSICAL_ADDRESS PrivateMmGetPhysicalAddress ( IN PVOID LinearAddress )
{
/*
* Header: Declared in Winnt.h; include Windows.h.
*
* typedef union _LARGE_INTEGER
* {
* struct
* {
* DWORD LowPart;
* LONG HighPart;
* };
* LONGLONG QuadPart;
* } LARGE_INTEGER, *PLARGE_INTEGER;
*/
PHYSICAL_ADDRESS physical_address;
physical_address.HighPart = 0;
if ( ( ULONG )LinearAddress >= 0x80000000 &&
( ULONG )LinearAddress < 0xa0000000 )
{
physical_address.LowPart = ( DWORD )LinearAddress & 0x1fffffff;
}
else
{
physical_address.LowPart = 0;
}
return( physical_address );
} /* end of PrivateMmGetPhysicalAddress */
/*
* 这种技术在VC范畴内对我而言太陌生了,好在我可以将之想像成汇编代码。由于
* 通过调用门进入,必须考虑CS被压栈、特权级改变、堆栈切换等一系列问题,其
* 具体细节可以参看MSDN以及Intel卷III。
*
* 这里写成"void Ring0Code ( void )"也可以,形参部分没有意义,也不能使用,
* CS被压栈后形参定位有变。变通的办法就是下面演示的技术,在prolog中用汇编
* 指令将形参取出并赋予局部变量,后续的C代码使用局部变量。其实这里很好理解,
* 只需按平日里用汇编语言写调用门的理解去做就是。
*
* 这段代码搭了一个"可用"的框架,允许以标准C编程技巧向内传递形参,至于这个
* call_arg如何解释,完全依赖于call_type。框架是我的主意,但下面演示的三种
* 具体操作不是我的主意,见其附近的注释。
*/
static __declspec(naked) void Ring0Code ( unsigned int unused_call_type, void *unused_call_arg )
{
unsigned int call_type;
void *call_arg;
/*
* prolog
*/
__asm
{
push ebp
mov ebp,esp
sub esp,__LOCAL_SIZE
pushad
pushfd
mov eax,[ebp+0xc]
mov call_type,eax
mov eax,[ebp+0x10]
mov call_arg,eax
}
/*
* 不要在这里做涉及I/O的操作
*/
switch ( call_type )
{
case 0:
/*
* 获取控制寄存器CRn、调试寄存器DRn的值。cr4未被支持。这是tsu00的
* 主意。
*/
__asm
{
mov ebx,call_arg
mov eax,cr0
mov [ebx]CALL_ARG_0.cr0,eax
mov eax,cr2
mov [ebx]CALL_ARG_0.cr2,eax
mov eax,cr3
mov [ebx]CALL_ARG_0.cr3,eax
mov eax,dr0
mov [ebx]CALL_ARG_0.dr0,eax
mov eax,dr1
mov [ebx]CALL_ARG_0.dr1,eax
mov eax,dr2
mov [ebx]CALL_ARG_0.dr2,eax
mov eax,dr3
mov [ebx]CALL_ARG_0.dr3,eax
mov eax,dr6
mov [ebx]CALL_ARG_0.dr6,eax
mov eax,dr7
mov [ebx]CALL_ARG_0.dr7,eax
}
break;
case 1:
/*
* 调用内核函数MmGetPhysicalAddress。这是crazylord的主意。
*/
__asm
{
mov ebx,call_arg
push [ebx]CALL_ARG_1.LinearAddress
call MmGetPhysicalAddress
mov [ebx]CALL_ARG_1.PhysicalAddress.LowPart,eax
mov [ebx]CALL_ARG_1.PhysicalAddress.HighPart,edx
}
break;
case 2:
/*
* 内存复制。由于在Ring 0,直接访问内核空间线性地址没有任何问题,
* 这是h0ck0r@smth的主意。
*/
__asm
{
mov ebx,call_arg
mov esi,[ebx]CALL_ARG_2.src
mov edi,[ebx]CALL_ARG_2.dst
mov ecx,[ebx]CALL_ARG_2.len
rep movsb
}
break;
default:
break;
} /* end of switch */
/*
* epilog
*/
__asm
{
popfd
popad
mov esp,ebp
pop ebp
retf 8
}
} /* end of Ring0Code */
static BOOLEAN SetPhysicalMemoryDACLs ( HANDLE handle, LPTSTR ptstrName )
{
BOOLEAN boolean_ret = TRUE;
DWORD ret = ERROR_SUCCESS;
PACL OldDACLs = NULL;
PACL NewDACLs = NULL;
PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
EXPLICIT_ACCESS Access;
/*
* Header : Declared in Aclapi.h
* Library: Use Advapi32.lib
*
* DWORD GetSecurityInfo
* (
* HANDLE handle,
* SE_OBJECT_TYPE ObjectType,
* SECURITY_INFORMATION SecurityInfo,
* PSID *ppsidOwner,
* PSID *ppsidGroup,
* PACL *ppDacl,
* PACL *ppSacl,
* PSECURITY_DESCRIPTOR *ppSecurityDescriptor
* );
*/
ret = GetSecurityInfo
(
handle,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -