Joesmith2002
驱动牛犊
驱动牛犊
  • 注册日期2002-06-14
  • 最后登录2002-06-26
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:876回复:0

扩展SoftICE--5

楼主#
更多 发布于:2002-06-14 11:22
Chapter 6: Moving to ring 3
---------------------------


Part of the Protected Mode Debug API is available also on ring3.In fact , some
functions from WIN32 API like OutputDebugString relays on INT 41h to carry out the job.
This opens more interesting possibilities , since you can write ring3 programs that
interacts with a system debugger , retrieving info from it and instructing it to carry
out various actions.
Note that not entire API is disponible on ring3.Generally, experimenting won\'t
harm as long as you are sure that a system debugger is installed.


     Chapter 7: How Numega\'s Loader works?
     -------------------------------------

Although this chapter is not directly related to extending system debuggers under
Windows95 ive decided to present it inside this document because it treats a very important
problem: Talking to VxD\'s from ring3.The basic problem is the question: How can I call the
code from a VxD and how do I retrieve data from it?Well , there are more than one method
to to this, but I will present only one.This method uses the DEVICE_IO_CONTROL mechanism
to talk to a VxD.It also provides a very convenient way to manipulate complex data structures
between ring3 and ring0.The only downside is that a certain architecture is imposed to the
VxD which will be called using this method.The device driver is required to process the
W32_DeviceIoControl message and to use a table of offsets to dispatch control to desired
procedures.
NuMega\'s loader uses this method to instruct SoftIce VxD to perform various actions.
The mechanism is implemented within nmtrans.dll. The executable is a simple shell for
an easy user interaction.Now let\'s see the API used to communicate in this way with a VxD
and then let\'s look how NuMega\'s loader use them.Three WIN32 API functions are used:
CreateFile , CloseHandle and DeviceIoControl.
I\'m sure that all of you know very well CreateFile & CloseHandle so let\'s see
DeviceIoControl. The DeviceIoControl function sends a control code directly to a specified
device driver, causing the device to perform the specified operation.

BOOL DeviceIoControl(

        HANDLE  hDevice, // handle of the device
     DWORD  dwIoControlCode, // control code of operation to perform
   LPVOID  lpvInBuffer, // address of buffer for input data
   DWORD  cbInBuffer, // size of input buffer
   LPVOID  lpvOutBuffer, // address of output buffer
   DWORD  cbOutBuffer, // size of output buffer
   LPDWORD  lpcbBytesReturned, // address of actual bytes of output
   LPOVERLAPPED  lpoOverlapped // address of overlapped structure
   );


DIOCParams STRUC
Internal1 DD ?
VMHandle DD ?
Internal2 DD ?
dwIoControlCode DD ?
lpvInBuffer DD ?
cbInBuffer DD ?
lpvOutBuffer DD ?
cbOutBuffer DD ?
lpcbBytesReturned DD ?
lpoOverlapped DD ?
hDevice DD ?
tagProcess DD ?
DIOCParams ENDS

Hope the structure is self-explanatory , tired of typing.Anyway it is used to pass and retrieve
data to the called VxD service,as well as passing desired code of operation.
How Numega use this functions? First CreateFile is called with  LPCSTR lpszName parameter
set to \" \\\\\\\\.\\\\SICE\".If Softice VxD is loaded this call will return a handle to the virtual
device driver.After that DeviceIoControl is called with HANDLE  hDevice set to the value
returned by previously called CreateFile and DWORD  dwIoControlCode set to a integer value
which unique identifies what routine we want to be called from VxD.If the function succeeds
the return value is TRUE.
\"\\\\\\\\.\\\\SICE\" passed to CreateFile is the name of the virtual device we want to
open.You can figure out very easy this name , IDA gives it to you for any VxD.
When DeviceIoControl is called the system wraps to called VxD routine through a
standard Windows95 VxD called vwin32.vxd.A DEVICE_IO_CONTROL message is broadcasted to the
target VxD.In this moment esi register points to a DIOCParams type structure.The VxD code
is responsible to annalize the requested service code ( DWORD  dwIoControlCode) and see if
it\'s a valid one. If it\'s valid , control is passed to the service routine witch must
return with carry flag cleared  to indicate success. If the service code does not exist,
or an error occurs (insufficient nr. of parameters ...and so on ) we must return with
carry flag set to indicate an error.Finally , Close Handle is called to destroy the
handle.
Let\'s annalize , for example , how the command history is saved to a file (the first listing
is from nmtrans.dll , the second from winice.exe ver 3.22).
A simple quick view in nmtrans.dll shows some interesting names.Two of them are interesting
in our problem. They are DevIO_ConnectToSoftIce and DevIO_CopyLogInfo.Very suggestive names,
isn\'t it?When we want to save log info control is passed to DevIO_CopyLogInfo.

...............................!!!!SEVERAL LINES STRIPED OUT!!!................................

disasembly listing of nmtrans.dll
DevIO_CopyLogInfo
-------------------

10019999 call DevIO_ConnectToSoftICE        // In fact this calls CreateFile
      // to open a handle to VxD

1001999E mov [ebp+var_1C], eax
100199A1 cmp eax, 0FFFFFFFFh       // If we don\'t have a valid handle
100199A4 jz short loc_100199EA       // jump out of here
100199A6 push 0
100199A8 lea eax, [ebp+var_24]
100199AB push eax
100199AC push 1Ch
100199AE lea eax, [ebp+var_40]
100199B1 push eax
100199B2 push 0
100199B4 push 0
100199B6 push 9C406018h      //Push control code of operation
     //Remember this , it is a critical
     //value.It decides what service
     // will eventualy execute winice.
     // See below!
100199BB mov eax, [ebp+var_1C]
100199BE push eax      //Push the handle to winice VxD on stack
100199BF call ds:DeviceIoControl      //Call DeviceIoControl
     //At this point control will be passed to
     //Soft-Ice VxD.
     //Remember that the OS have to execute
     // several auxiliary operations , you
     // will not land directly in Winice!
100199C5 mov [ebp+var_20], eax
100199C8 lea esi, [ebp+var_40]
100199CB mov edi, ebx
100199CD mov ecx, 7
100199D2 repe movsd
100199D4 jmp short loc_100199EA


So we learned that the dll\'s call into SoftIce VxD through DeviceIoControl Win32 API
function.To figure out exactly what service will be called from target VxD we have to remember
several things about VxD architecture.First of all we must know that every VxD have a
ControlDispatch routine that receives mesages broadcasted by system.This control block identifies
the messages and call coresponding routines.When this proc. is entered eax contain message code.
Ida Pro 3.7 identifies very well this procedure,giving us a very good starting point.


00000096 Control_0 proc near ; DATA XREF: LCOD:0000055Ao
00000096 ; LCOD:0000407Co
00000096 call sub_7C8BB
0000009B cmp eax, 0 // case SYS_CRITICAL_INIT
0000009E jz loc_93E
000000A4 cmp eax, 1 // case DEVICE_INIT
000000A7 jz short loc_D8
000000A9 cmp eax, 2 // case INIT_COMPLETE
000000AC jz loc_BDC
000000B2 cmp eax, 6 // case SYS_CRITICAL_EXIT
000000B5
000000B5 loc_B5: ; DATA XREF: LCOD:000B4640o
000000B5 jz loc_BDE
000000BB cmp eax, 23h ; \'#\' // case W32_DEVICEIOCONTROL
//
// Using DeviceIoControl for talking
// to VxD requires that this message
// is processed!
000000BE jz loc_5FD // than jump to this location

000000C4 cmp eax, 0Fh //  case SET_DEVICE_FOCUS
000000C7 jz loc_15F
000000CD cmp eax, 0Ch // case DESTROY_VM
000000D0 jz loc_19B
000000D6 clc
000000D7 retn

The control is passed to the handler for  W32_DeviceIocontrol message (loc_5FD in this case).

000005FD loc_5FD: ; CODE XREF: Control_0+28
000005FD push ebx //
000005FE push esi //Save those registers
000005FF push edi //

00000600 push 10h // EnterMutex param2
00000602 push ds:dword_40BF // EnterMutex param1
00000608 VMMcall _EnterMutex // Create a mutex to ensure that only
// one thread will acces this code at
// a given time

0000060E add esp, 8 // restore stack as at 5ff
00000611 push esi // save esi
00000612 mov esi, offset dword_40C3    // pointer to an Exception_Handler_Struc
   // in this struct are defined the
   // type of handler and memory range
   // what is guarded

00000617 VMMcall Install_Exception_Handler  // install a ring0 exception handler
   // if something goes wrong we can
   // trap the problem
0000061D pop esi // restore the esi
// esi contain a pointer to a DIOCparams
// struct (All info you pass to ring3
// DeviceIOControl + some not very
// important things for us
0000061E call sub_4B4F5 // ??? unexplored by me
00000623 mov ds:dword_40B7, 1
0000062D push 1
0000062F call sub_8595C // ??? unexplored by me
00000634 push eax
00000635 mov ds:dword_40BB, esp
0000063B mov dword ptr [esi+20h], 0  // set number of bytes returned
// may be modified by the requested
// service
00000642 mov ecx, [esi+0Ch] //load in eax dwIoControlCode
//from DIOCParams.dwIoControlCode
00000645 mov edx, ecx
00000647 shr edx, 10h
0000064A cmp edx, 9C40h // check for validity and reduction
00000650 jnz short loc_672
00000652 mov edx, ecx
00000654 shr edx, 2
00000657 and edx, 0FFFh
0000065D cmp edx, 800h
00000663 jl loc_8BD
00000669 sub edx, 800h
0000066F inc edx
00000670 mov ecx, edx // end check for validity and reduction
// load basic service code in ecx
       // maximum value for a valid request
// will be 0xB
00000672
00000672 loc_672: ; CODE XREF: LCOD:00000650

00000672 inc ecx // services are 0 based so increment
00000673 cmp ecx, 0Ch // is service available?
00000679 jnb loc_8BD // if no , Get Out of here!
0000067F jmp ds:off_7584[ecx*4]  //else jump to the requested routine
    // it\'s address is stored in a DWORD
    // array begining in this case at
    // off_7584  
   

// The mutex object is removed elsewhere in the code as well as the exception handler
// Not listed here because it\'s unimportant for our problem
   

Remember the control code of operation passed to DeviceIoControl?.This is the moment
then it becomes crucial.As already told , at this moment the ESI register points to
a DIOCParams type structure.This structure contains all info passed to DeviceIoControl.
Now if you watch the code above you will notice that from 0x635 to 0x672 a reduction
of this value to a much smaller one  is performed.In fact , the maximum value contained
in ecx at this step is OxB , which BTW is the number of services that SoftIce expose
through this interface. ( in fact , the maximum number of services is 0xC ,but this
contains the default DIOC_GETVERSION service).
At location 673 the code looks if this service is in range (in SICE are implemented 0x0c
services what can be called using this method).If it determines that it\'s a valid service ,
the code jumps to the start adress of requested service. This adress is stored in a table ,
in our case at ds:off_7584.

00007584 off_7584 dd offset off_686 // if ecx = 0
00007588 dd offset off_68B // if ecx = 1
0000758C dd offset loc_690 // if ecx = 2
00007590 dd offset loc_6E8 // if ecx = 3
00007594 dd offset loc_71C // if ecx = 4
00007598 dd offset loc_7F6 // if ecx = 5
0000759C dd offset loc_825 // if ecx = 6
000075A0 dd offset loc_75C       // if ecx = 7
000075A4 dd offset loc_78B       // if ecx = 8  
000075A8 dd offset loc_7BA       // if ecx = 9
000075AC dd offset loc_8B6       // if ecx = A
000075B0 dd offset loc_85D       // if ecx = B

ECX == 0 coresponds to a default DIOC_GETVERSION service .All others values between 0x1 and 0xb
at VxD services called by one  of the folowing functions:

  DevIO_ConnectToSoftICE  (00019490)
               DevIO_CopyLogInfo  (00019940)
                  DevIO_LoadExports  (00019760)
                           DevIO_LoadNm32SymbolTable  (00019630)
                           DevIO_Nm32QueryTableInfoFirst  (00019C50)
                           DevIO_Nm32QueryTableInfoNext  (00019D60)
                           DevIO_Nm32QueryTables  (00019B40)
                           DevIO_Nm32RemoveSymbolTable  (00019E40)
                           DevIO_Nm32TranslateError  (000194F0)
                           DevIO_Nm32VersionInfo  (00019840)
                           DevIO_SetWLDRBreak  (00019A30)

All this functions exported by nmtrans.dll use the same mechanism.Of course , operation
codes ar different , as well as the data passed and retrieved.
Looking at this table we have a clear picture of the starting adress of the VxD routines
what are called from ring3.Pretty interesting , isn\'t it? And we can call them any time
now , once we figured what code of operation coresponds to it.
Note : al C++ style comments in the listing there are NOT auto generated by IDA.


最新喜欢:

flyfoxflyfox
游客

返回顶部