科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件VC6下编译进Ring0代码的疑惑

VC6下编译进Ring0代码的疑惑

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

VC6下编译进Ring0代码的疑惑,操作系统XPSP2,CPU:AMD3000+。现象,VC6总会优化代码,编译出来的代码不是想要的。

作者:苏晓 来源:CSDN 2008年3月20日

关键字: Ring0 VC6.0 C++ C Linux

  • 评论
  • 分享微博
  • 分享邮件

VC6下编译进Ring0代码的疑惑,操作系统XPSP2,CPU:AMD3000+。现象,VC6总会优化代码,编译出来的代码不是想要的。

代码如下:

// tt.cpp : Defines the entry point for the application. //#include "stdafx.h" #define _X86_ #include <windows.h> #include <stdio.h> #include <aclapi.h> #include <conio.h> #include <windef.h> #include <shellapi.h> typedef long NTSTATUS; typedef unsigned short USHORT; #define NT_SUCCESS(Status) ((NTSTATUS)(Status) >= 0) #define OBJ_INHERIT 0x00000002L #define OBJ_PERMANENT 0x00000010L #define OBJ_EXCLUSIVE 0x00000020L #define OBJ_CASE_INSENSITIVE 0x00000040L #define OBJ_OPENIF 0x00000080L #define OBJ_OPENLINK 0x00000100L #define OBJ_KERNEL_HANDLE 0x00000200L #define OBJ_VALID_ATTRIBUTES 0x000003F2L typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; #ifdef MIDL_PASS [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer; #else // MIDL_PASS PWSTR Buffer; #endif // MIDL_PASS } UNICODE_STRING; typedef UNICODE_STRING *PUNICODE_STRING; typedef const UNICODE_STRING *PCUNICODE_STRING; #define UNICODE_NULL ((WCHAR)0) // winnt typedef struct _OBJECT_ATTRIBUTES { ULONG Length; HANDLE RootDirectory; PUNICODE_STRING ObjectName; ULONG Attributes; PVOID SecurityDescriptor; // Points to type SECURITY_DESCRIPTOR PVOID SecurityQualityOfService; // Points to type SECURITY_QUALITY_OF_SERVICE } OBJECT_ATTRIBUTES; typedef OBJECT_ATTRIBUTES *POBJECT_ATTRIBUTES; #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; \ } extern "C" typedef VOID (*pRtlInitUnicodeString)( PUNICODE_STRING DestinationString,PCWSTR SourceString); extern "C" typedef NTSTATUS (*pZwOpenSection)(OUT PHANDLE SectionHandle,IN ACCESS_MASK DesiredAccess,IN POBJECT_ATTRIBUTES ObjectAttributes); extern "C" typedef NTSTATUS (*pZwClose)(IN HANDLE Handle); static const HINSTANCE NTDLLHANDLE=(HINSTANCE)0x7c920000; //ntdll.dll加载的位置可以用GetModuleHandle获取 #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) // ntsubauth #define STATUS_ACCESS_DENIED ((NTSTATUS)0xC0000022L) //#pragma comment(lib,"C:\\NTDDK\\libfre\\i386\\ntdll.lib") #define ENTERRING0 _asm pushad \ _asm pushf \_asm cli#define LEAVERING0 _asm popf \ _asm popad \_asm retf typedef struct gdtr { unsigned short Limit; unsigned short BaseLow; unsigned short BaseHigh; } Gdtr_t, *PGdtr_t; typedef struct { unsigned short offset_0_15; unsigned short selector; unsigned char param_count : 4; unsigned char some_bits : 4; unsigned char type : 4; unsigned char app_system : 1; unsigned char dpl : 2; unsigned char present : 1; unsigned short offset_16_31; } CALLGATE_DESCRIPTOR; void PrintWin32Error( DWORD ErrorCode ) { LPVOID lpMsgBuf; FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL); printf("%s\n", lpMsgBuf ); LocalFree( lpMsgBuf );} ULONG MiniMmGetPhysicalAddress(ULONG virtualaddress) { if(virtualaddress<0x80000000||virtualaddress>=0xA0000000) return 0; return virtualaddress&0x1FFFF000; } VOID SetPhyscialMemorySectionCanBeWrited(HANDLE hSection) { PACL pDacl=NULL; PACL pNewDacl=NULL; PSECURITY_DESCRIPTOR pSD=NULL; DWORD dwRes; EXPLICIT_ACCESS ea; if(dwRes=GetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION, NULL,NULL,&pDacl,NULL,&pSD) != ERROR_SUCCESS) { printf( "GetSecurityInfo Error %u\n", dwRes ); goto CleanUp; } ZeroMemory(&ea, sizeof(EXPLICIT_ACCESS)); ea.grfAccessPermissions = SECTION_MAP_WRITE; ea.grfAccessMode = GRANT_ACCESS; ea.grfInheritance= NO_INHERITANCE; ea.Trustee.TrusteeForm = TRUSTEE_IS_NAME; ea.Trustee.TrusteeType = TRUSTEE_IS_USER; ea.Trustee.ptstrName = "CURRENT_USER"; if(dwRes=SetEntriesInAcl(1,&ea,pDacl,&pNewDacl)!=ERROR_SUCCESS) { printf( "SetEntriesInAcl %u\n", dwRes ); goto CleanUp; } if(dwRes=SetSecurityInfo(hSection,SE_KERNEL_OBJECT,DACL_SECURITY_INFORMATION,NULL,NULL,pNewDacl,NULL)!=ERROR_SUCCESS) { printf("SetSecurityInfo %u\n",dwRes); goto CleanUp; } CleanUp: if(pSD) LocalFree(pSD); if(pNewDacl) LocalFree(pSD);} #define RING0PROC void __declspec (naked) BOOL ExecRing0Proc(ULONG Entry,ULONG seglen) { Gdtr_t gdt; __asm sgdt gdt; ULONG mapAddr=MiniMmGetPhysicalAddress(gdt.BaseHigh<<16U|gdt.BaseLow); if(!mapAddr) return 0; HANDLE hSection=NULL; NTSTATUS status; OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING objName; CALLGATE_DESCRIPTOR *cg; status = STATUS_SUCCESS; pRtlInitUnicodeString RtlInitUnicodeString; pZwOpenSection ZwOpenSection; pZwClose ZwClose; RtlInitUnicodeString=(pRtlInitUnicodeString)GetProcAddress(NTDLLHANDLE,"RtlInitUnicodeString"); ZwOpenSection=(pZwOpenSection)GetProcAddress(NTDLLHANDLE,"ZwOpenSection"); ZwClose=(pZwClose)GetProcAddress(NTDLLHANDLE,"ZwClose"); RtlInitUnicodeString(&objName,L"\\Device\\PhysicalMemory"); InitializeObjectAttributes(&objectAttributes, &objName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, (PSECURITY_DESCRIPTOR) NULL); status = ZwOpenSection(&hSection,SECTION_MAP_READ|SECTION_MAP_WRITE,&objectAttributes); //if(status == STATUS_ACCESS_DENIED) //这个地方就一直加强改写才行! { status = ZwOpenSection(&hSection,READ_CONTROL|WRITE_DAC,&objectAttributes); SetPhyscialMemorySectionCanBeWrited(hSection); ZwClose(hSection); status = ZwOpenSection(&hSection,SECTION_MAP_READ|SECTION_MAP_WRITE,&objectAttributes); } if(status != STATUS_SUCCESS) { printf("Error Open PhysicalMemory Section Object,Status:%08X\n",status); return 0; } PVOID BaseAddress; BaseAddress=MapViewOfFile(hSection, FILE_MAP_READ|FILE_MAP_WRITE, 0, mapAddr, //low part (gdt.Limit+1)); if(!BaseAddress) { printf("Error MapViewOfFile:"); PrintWin32Error(GetLastError()); return 0; } BOOL setcg=FALSE; for(cg=(CALLGATE_DESCRIPTOR *)((ULONG)BaseAddress+(gdt.Limit&0xFFF8));(ULONG)cg>(ULONG)BaseAddress;cg--) if(cg->type == 0){ cg->offset_0_15 = LOWORD(Entry); cg->selector = 8; cg->param_count = 0; cg->some_bits = 0; cg->type = 0xC; // 386 call gate cg->app_system = 0; // A system descriptor cg->dpl = 3; // Ring 3 code can call cg->present = 1; cg->offset_16_31 = HIWORD(Entry); setcg=TRUE; break; } if(!setcg){ ZwClose(hSection); return 0; } char *msg=new char[1000]; sprintf(msg,"BaseAddress=%x\thSection=%x\tmapAddr=%x",BaseAddress,hSection,mapAddr); MessageBox(NULL,msg,NULL,NULL); delete [] msg; short farcall[3]; farcall[2]=((short)((ULONG)cg-(ULONG)BaseAddress))|3; //Ring 3 callgate; if(!VirtualLock((PVOID)Entry,seglen)) { printf("Error VirtualLock:"); PrintWin32Error(GetLastError()); return 0; } SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_TIME_CRITICAL); Sleep(0); _asm call fword ptr [farcall]; MessageBox(NULL,"com",NULL,NULL); SetThreadPriority(GetCurrentThread(),THREAD_PRIORITY_NORMAL); VirtualUnlock((PVOID)Entry,seglen); //Clear callgate *(ULONG *)cg=0; *((ULONG *)cg+1)=0; ZwClose(hSection); MessageBox(NULL,"com2",NULL,NULL); return TRUE; }struct _RING0DATA { DWORD mcr0,mcr2,mcr3; unsigned short BaseMemory; unsigned short ExtendedMemory; }r0Data; RING0PROC Ring0Proc1(){ ENTERRING0; _asm { mov eax, cr0 mov r0Data.mcr0, eax; mov eax, cr2 mov r0Data.mcr2, eax; mov eax, cr3 mov r0Data.mcr3, eax; } LEAVERING0;} RING0PROC Ring0Proc2(){ ENTERRING0; _outp( 0x70, 0x15 ); _asm { mov ax,0 in al,71h mov r0Data.BaseMemory,ax } _outp( 0x70, 0x16 ); r0Data.BaseMemory += _inp(0x71) << 8; _outp( 0x70, 0x17 ); r0Data.ExtendedMemory = _inp( 0x71 ); _outp( 0x70, 0x18 ); r0Data.ExtendedMemory += _inp(0x71) << 8; LEAVERING0;} int Freq; RING0PROC BeepOn(){ ENTERRING0; BYTE b; if ((Freq >= 20) && (Freq <= 20000)) { Freq = 1193181 / Freq; b = _inp(0x61); if ((b & 3) == 0) { _outp(0x61, (BYTE) (b | 3)); _outp(0x43, 0xb6); } _outp(0x42, (BYTE) Freq); _outp(0x42, (BYTE) (Freq >> 8)); }; LEAVERING0;}; RING0PROC BeepOff(){ ENTERRING0; BYTE b; b= (_inp(0x61) & 0xfc); _outp(0x61, b); LEAVERING0;}; int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { ZeroMemory(&r0Data,sizeof(struct _RING0DATA)); VirtualLock((PVOID)&r0Data,sizeof(struct _RING0DATA)); ExecRing0Proc((ULONG)Ring0Proc1,0x100); ExecRing0Proc((ULONG)Ring0Proc2,0x100); VirtualUnlock((PVOID)&r0Data,sizeof(struct _RING0DATA)); char* msg=new char[100]; sprintf(msg,"CR0 = %x\tCR2 = %x\tCR3 = %x\t", r0Data.mcr0,r0Data.mcr2,r0Data.mcr3); MessageBox(NULL,msg,NULL,NULL); delete [] msg; Freq=5000; ExecRing0Proc((ULONG)BeepOn,0x100); Sleep(1000); Freq=3000; ExecRing0Proc((ULONG)BeepOn,0x100); Sleep(1000); ExecRing0Proc((ULONG)BeepOff,0x100); MessageBox(NULL,"com3",NULL,NULL); return 0; }

进Ring0的功能是正确的,问题出现在VC6汇编Sleep,MessageBox这样的函数时,把Sleep,MessageBox调用
地址写在ESI,EDI寄存器内。如主过程:

ZeroMemory(&r0Data,sizeof(struct _RING0DATA)); VirtualLock((PVOID)&r0Data,sizeof(struct _RING0DATA)); ExecRing0Proc((ULONG)Ring0Proc1,0x100); ExecRing0Proc((ULONG)Ring0Proc2,0x100); VirtualUnlock((PVOID)&r0Data,sizeof(struct _RING0DATA)); char* msg=new char[100]; sprintf(msg,"CR0 = %x\tCR2 = %x\tCR3 = %x\t", r0Data.mcr0,r0Data.mcr2,r0Data.mcr3); MessageBox(NULL,msg,NULL,NULL); delete [] msg; Freq=5000; ExecRing0Proc((ULONG)BeepOn,0x100); Sleep(1000); Freq=3000; ExecRing0Proc((ULONG)BeepOn,0x100); Sleep(1000); ExecRing0Proc((ULONG)BeepOff,0x100); MessageBox(NULL,"com3",NULL,NULL); return 0;

汇编后成为:
004014A0  /___FCKpd___2nbsp; 33C0          XOR EAX,EAX                              ;  tt.00400000
004014A2  |.  56            PUSH ESI
004014A3  |.  A3 287A4000   MOV DWORD PTR DS:[407A28],EAX
004014A8  |.  57            PUSH EDI
004014A9  |.  A3 2C7A4000   MOV DWORD PTR DS:[407A2C],EAX
004014AE  |.  6A 10         PUSH 10
004014B0  |.  A3 307A4000   MOV DWORD PTR DS:[407A30],EAX
004014B5  |.  68 287A4000   PUSH tt.00407A28
004014BA  |.  A3 347A4000   MOV DWORD PTR DS:[407A34],EAX
004014BF  |.  FF15 18604000 CALL DWORD PTR DS:[<&KERNEL32.VirtualLoc>;  kernel32.VirtualLock
004014C5  |.  68 00010000   PUSH 100
004014CA  |.  68 D0134000   PUSH tt.004013D0
004014CF  |.  E8 7CFCFFFF   CALL tt.00401150
004014D4  |.  68 00010000   PUSH 100
004014D9  |.  68 F0134000   PUSH tt.004013F0
004014DE  |.  E8 6DFCFFFF   CALL tt.00401150
004014E3  |.  83C4 10       ADD ESP,10
004014E6  |.  6A 10         PUSH 10                                  ; /Size = 10 (16.)
004014E8  |.  68 287A4000   PUSH tt.00407A28                         ; |Address = tt.00407A28
004014ED  |.  FF15 30604000 CALL DWORD PTR DS:[<&KERNEL32.VirtualUnl>; \VirtualUnlock
004014F3  |.  6A 64         PUSH 64
004014F5  |.  E8 56010000   CALL tt.00401650
004014FA  |.  8B0D 307A4000 MOV ECX,DWORD PTR DS:[407A30]
00401500  |.  8B15 2C7A4000 MOV EDX,DWORD PTR DS:[407A2C]
00401506  |.  8BF0          MOV ESI,EAX
00401508  |.  A1 287A4000   MOV EAX,DWORD PTR DS:[407A28]
0040150D  |.  51            PUSH ECX
0040150E  |.  52            PUSH EDX
0040150F  |.  50            PUSH EAX
00401510  |.  68 88714000   PUSH tt.00407188                         ;  ASCII "CR0 = %x CR2 = %x CR3 = %x "
00401515  |.  56            PUSH ESI
00401516  |.  E8 E3000000   CALL tt.004015FE
0040151B  |.  8B3D D8604000 MOV EDI,DWORD PTR DS:[<&USER32.MessageBo>;  USER32.MessageBoxA
00401521  |.  83C4 18       ADD ESP,18
00401524  |.  6A 00         PUSH 0                                   ; /Style = MB_OK|MB_APPLMODAL
00401526  |.  6A 00         PUSH 0                                   ; |Title = NULL
00401528  |.  56            PUSH ESI                                 ; |Text
00401529  |.  6A 00         PUSH 0                                   ; |hOwner = NULL
0040152B  |.  FFD7          CALL EDI                                 ; \MessageBoxA
0040152D  |.  56            PUSH ESI
0040152E  |.  E8 C0000000   CALL tt.004015F3
00401533  |.  68 00010000   PUSH 100
00401538  |.  68 40144000   PUSH tt.00401440
0040153D  |.  C705 207A4000>MOV DWORD PTR DS:[407A20],1388
00401547  |.  E8 04FCFFFF   CALL tt.00401150
0040154C  |.  8B35 20604000 MOV ESI,DWORD PTR DS:[<&KERNEL32.Sleep>] ;  kernel32.Sleep
00401552  |.  83C4 0C       ADD ESP,0C
00401555  |.  68 E8030000   PUSH 3E8                                 ; /Timeout = 1000. ms
0040155A  |.  FFD6          CALL ESI                                 ; \Sleep
0040155C  |.  68 00010000   PUSH 100
00401561  |.  68 40144000   PUSH tt.00401440
00401566  |.  C705 207A4000>MOV DWORD PTR DS:[407A20],0BB8
00401570  |.  E8 DBFBFFFF   CALL tt.00401150
00401575  |.  83C4 08       ADD ESP,8
00401578  |.  68 E8030000   PUSH 3E8
0040157D  |.  FFD6          CALL ESI ;!!!这是调用Sleep,错误!
0040157F  |.  68 00010000   PUSH 100
00401584  |.  68 90144000   PUSH tt.00401490
00401589  |.  E8 C2FBFFFF   CALL tt.00401150
0040158E  |.  83C4 08       ADD ESP,8
00401591  |.  6A 00         PUSH 0
00401593  |.  6A 00         PUSH 0
00401595  |.  68 80714000   PUSH tt.00407180                         ;  ASCII "com3"
0040159A  |.  6A 00         PUSH 0
0040159C  |.  FFD7          CALL EDI ;!!!这是调用MessageBox,错误!
0040159E  |.  5F            POP EDI
0040159F  |.  33C0          XOR EAX,EAX
004015A1  |.  5E            POP ESI
004015A2  \.  C2 1000       RETN 10

每当Call完 401150,返回后,与只用用户态函数调用不同,寄存器的值都会改变!!!而VC6的编译,无论是优化速度,优化大小,禁止优化,都不能避免类似错误。

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章