VC6下编译进Ring0代码的疑惑(7)
进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 CR2 = %x CR3 = %x ", 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.00400000004014A2 |. 56 PUSH ESI004014A3 |. A3 287A4000 MOV DWORD PTR DS:[407A28],EAX004014A8 |. 57 PUSH EDI004014A9 |. A3 2C7A4000 MOV DWORD PTR DS:[407A2C],EAX004014AE |. 6A 10 PUSH 10004014B0 |. A3 307A4000 MOV DWORD PTR DS:[407A30],EAX004014B5 |. 68 287A4000 PUSH tt.00407A28004014BA |. A3 347A4000 MOV DWORD PTR DS:[407A34],EAX004014BF |. FF15 18604000 CALL DWORD PTR DS:[<&KERNEL32.VirtualLoc>; kernel32.VirtualLock004014C5 |. 68 00010000 PUSH 100004014CA |. 68 D0134000 PUSH tt.004013D0004014CF |. E8 7CFCFFFF CALL tt.00401150004014D4 |. 68 00010000 PUSH 100004014D9 |. 68 F0134000 PUSH tt.004013F0004014DE |. E8 6DFCFFFF CALL tt.00401150004014E3 |. 83C4 10 ADD ESP,10004014E6 |. 6A 10 PUSH 10 ; /Size = 10 (16.)004014E8 |. 68 287A4000 PUSH tt.00407A28 ; |Address = tt.00407A28004014ED |. FF15 30604000 CALL DWORD PTR DS:[<&KERNEL32.VirtualUnl>; VirtualUnlock004014F3 |. 6A 64 PUSH 64004014F5 |. E8 56010000 CALL tt.00401650004014FA |. 8B0D 307A4000 MOV ECX,DWORD PTR DS:[407A30]00401500 |. 8B15 2C7A4000 MOV EDX,DWORD PTR DS:[407A2C]00401506 |. 8BF0 MOV ESI,EAX00401508 |. A1 287A4000 MOV EAX,DWORD PTR DS:[407A28]0040150D |. 51 PUSH ECX0040150E |. 52 PUSH EDX0040150F |. 50 PUSH EAX00401510 |. 68 88714000 PUSH tt.00407188 ; ASCII "CR0 = %x CR2 = %x CR3 = %x "00401515 |. 56 PUSH ESI00401516 |. E8 E3000000 CALL tt.004015FE0040151B |. 8B3D D8604000 MOV EDI,DWORD PTR DS:[<&USER32.MessageBo>; USER32.MessageBoxA00401521 |. 83C4 18 ADD ESP,1800401524 |. 6A 00 PUSH 0 ; /Style = MB_OK|MB_APPLMODAL00401526 |. 6A 00 PUSH 0 ; |Title = NULL00401528 |. 56 PUSH ESI ; |Text00401529 |. 6A 00 PUSH 0 ; |hOwner = NULL0040152B |. FFD7 CALL EDI ; MessageBoxA0040152D |. 56 PUSH ESI0040152E |. E8 C0000000 CALL tt.004015F300401533 |. 68 00010000 PUSH 10000401538 |. 68 40144000 PUSH tt.004014400040153D |. C705 207A4000>MOV DWORD PTR DS:[407A20],138800401547 |. E8 04FCFFFF CALL tt.004011500040154C |. 8B35 20604000 MOV ESI,DWORD PTR DS:[<&KERNEL32.Sleep>] ; kernel32.Sleep00401552 |. 83C4 0C ADD ESP,0C00401555 |. 68 E8030000 PUSH 3E8 ; /Timeout = 1000. ms0040155A |. FFD6 CALL ESI ; Sleep0040155C |. 68 00010000 PUSH 10000401561 |. 68 40144000 PUSH tt.0040144000401566 |. C705 207A4000>MOV DWORD PTR DS:[407A20],0BB800401570 |. E8 DBFBFFFF CALL tt.0040115000401575 |. 83C4 08 ADD ESP,800401578 |. 68 E8030000 PUSH 3E80040157D |. FFD6 CALL ESI ;!!!这是调用Sleep,错误!0040157F |. 68 00010000 PUSH 10000401584 |. 68 90144000 PUSH tt.0040149000401589 |. E8 C2FBFFFF CALL tt.004011500040158E |. 83C4 08 ADD ESP,800401591 |. 6A 00 PUSH 000401593 |. 6A 00 PUSH 000401595 |. 68 80714000 PUSH tt.00407180 ; ASCII "com3"0040159A |. 6A 00 PUSH 00040159C |. FFD7 CALL EDI ;!!!这是调用MessageBox,错误!0040159E |. 5F POP EDI0040159F |. 33C0 XOR EAX,EAX004015A1 |. 5E POP ESI004015A2 . C2 1000 RETN 10每当Call完 401150,返回后,与只用用户态函数调用不同,寄存器的值都会改变!!!而VC6的编译,无论是优化速度,优化大小,禁止优化,都不能避免类似错误。
有什么办法解决这个问题呢?
我想可以用函数指针,通过指针来调用,不会出错,但是这样也太繁了。
哪位大侠有更好的解决办法啊?