iczelion Vxd tut7

vxd 专栏收录该内容
17 篇文章 0 订阅

 

Application Time and Shell Functions

Some Theory

Application time is usually called "appy time". It simply means the time when the system VM is stable enough to allow interaction between VxDs and the ring-3 applications, especially 16-bit ones. For example, at appy time, VxDs can load and call functions in 16-bit DLLs. This appy time is not available under Windows 3.1x. Under Windows 3.1, a VxD can obtain the address of any function in a 16-bit DLL and simulate a far call to that address. However, this will interrupt whatever task the ring-3 program is doing resulting in VMM reentrancy. So the only APIs which VxDs can call are those that are interrupt-safe, i.e. PostMessage. Under Windows 95, a VxD can call almost any function in any 16-bit DLL with the help of appy time.
Simply put, if your VxD is notified that now is the appy time, it can load 16-bit DLLs and call functions in them. So how does a VxD know that the appy time is arrived?  It must register an appy time event with the Shell VxD. When the system VM is in a stable state, the Shell VxD will call the callback function that the VxD specified when it registered for an appy time event. Shell VxD will call your callback function only once for each registration for appy time event. It's like applying for a job. You go to a recruiting agency, register your name/telephone number with them. Then you go home. When a job is available, the agency phones you about the good news. When you acknowledge that news, they will never call you again.
It may take some time before an appy time event is available. Appy time events are not available under these circumstances:
  • during system startup and shutdown
  • when system VM is in a critical section or waiting for a semaphore

Managing an appy time event

You can register for an appy time event by calling on _SHELL_CallAtAppyTime which has the following definition:
VxDCall _SHELL_CallAtAppyTime, <<OFFSET32 pfnCallback>,  dwRefData, dwFlags, dwTimeout>
pfnCallBackThe flat address of the callback function you want the Shell VxD to call when an appy time event occurs. The function will receive two parameters, dwRefData and dwFlags which are exactly identical to the two parameters you passed to _SHELL_CallAtAppyTime. Note that Shell VxD will call your callback function with C Calling sequence. In short, you have to define your callback function like this:

BeginProc OnAppyTime, CCALL, PUBLIC
ArgVar dwRefData,DWORD   ; declare argument name and type
ArgVar dwFlags, DWORD
EnterProc

<Your code here>

LeaveProc
Return
EndProc OnAppyTime

dwRefDataReference data you want Shell VxD to pass to your callback function. It can be anything you want.
dwFlagsEvent flags. Can be one of the following values:
CAAFL_RING0  Ring zero event.
CAAFL_TIMEOUT  Time out the event after the duration specified by dwTimeout. 
 Simply put, if you want to wait for the appy time event for some period only, use CAAFL_TIMEOUT flag. If you want to wait indefinitely for the appy time event, use NULL. I don't know what CAAFL_RING0 actually does.
dwTimeoutThe period of time the VxD wants to wait for the appy time event to occur. I can't find any info about the time unit used with this argument. 

This service is asynchronous, meaning that it returns immediately after registering your callback function for the appy time event.
If this service call is successful, it returns the application time event handle in eax. If it fails, eax contains 0.
You can cancel the appy time registration by calling on _SHELL_CancelAppyTimeEvent which takes only one parameter, the appy time event handle returned by _SHELL_CallAtAppyTime.
To be on the safe side, prior to calling _SHELL_CallAtAppyTime, you should check the system if appy time event will be available. For example, what if you register for appy time event while the system is shutting down? Your VxD's callback will never be called! You can query the system wheter appy time event will be available by calling _SHELL_QueryAppyTimeAvailable. This service takes no parameter. It returns 0 in eax if appy time will not be available, i.e. the system is closing down or the message server got GP faults. This service doesn't tell you that now is the appy time: it only tells you that there may be appy time events. In short, if you want to play safe, call _SHELL_QueryAppyTimeAvailable first and if it returns a nonzero value in eax, you can proceed to call _SHELL_CallAtAppyTime.

Application-time Shell Services

When appy time is reached, there are several Shell services you can call:
  • _SHELL_CallDll
  • _SHELL_FreeLibrary
  • _SHELL_GetProcAddress
  • _SHELL_LoadLibrary
  • _SHELL_LocalAllocEx
  • _SHELL_LocalFree
Those six services are provided so VxDs can call 16-bit functions in 16-bit DLLs/ExE, such as WinHelp. However, since we are moving on to the 32-bit world (and 64-bit, in the future), I will not go into detail about them. If you're interested, you can read about them in Windows 95/98 DDK documentation.
There are other application-time-only SHELL services which I think are more useful:_SHELL_ShellExecute and _SHELL_BroadcastSystemMessage. With _SHELL_BroadcastSystemMessage, you can send a message to all top-level windows and all VxDs in one call! If the appy time is available, you can send messages to both windows and VxDs. If the appy time is not available, you can send messages only to VxDs.
_SHELL_ShellExecute is the ring-0 counterpart of ShellExecute function in ring-3. Actually it calls ring-3 ShellExecute to do the job. With this Shell service, you can execute/open/print any file. _SHELL_ShellExecute has the following definition:
VxDCall _SHELL_ShellExecute, <OFFSET32 ShexPacket>
It takes only one parameter, the flat address of a SHEXPACKET structure. It returns the value from ShellExecute in eax. Let's examine SHEXPACKET structure in detail next.
 
shex_dwTotalSizeThe size in bytes of SHEXPACKET structure plus the optional parameter, rgchBaggage, which immediately follows this structure. I'll describe what rgchBaggage shortly.
shex_dwSizeThe size in bytes of SHEXPACKET structure, not counting rgchBaggage. Combined with shex_dwTotalSize above, the SHELL VxD can calculate the size of rgchBaggage which is of arbitrary length.
shex_ibOpThe operation you want to perform. If you specify 0, it means you want to open the file. If the file is an executable one, it executes it. If you want to perform other operation, you must specify the name of the operation somewhere in rgchBaggage and this field must contain the distance in bytes from the start of this SHEXPACKET structure to the first character of the ASCIIZ string that specifies the name of the operation you want to perform. The size of SHEXPACKET is 32 bytes. If the operation string immediately follows the SHEXPACKET structure, the value in shex_ibOp MUST be 32. As to the list of the operations you can perform, check ShellExecute. There are three operations defined, "open", "print" and "explore".
shex_ibFileThe relative distance from the start of this structure to the ASCIIZ string that is the name of the file you want to send to ShellExecute, just like shex_ibOp.
shex_ibParamsThe optional parameters you want to pass to the file specified in shex_ibFile. If the file is a document or you don't want to pass any parameter to it, use 0. If you want to pass some parameters to the file, put the parameter string somewhere after this structure and put the relative distance from the start of this structure to the string in this field. In short, just like shex_ibOp and shex_ibFile.
shex_ibDirThe working directory. Specify 0 if you want to use the Windows directory else you can specify your preferred directory string somewhere after this structure and put the relative distance between the start of this structure and the directory string in this field.
shex_dwReservedAs the name implied, it's reserved. Don't mess with it.
shex_nCmdShowHow the application window should be shown. It's one of the value you normally pass to ShowWindow, ie. the SW_XXXX value. Look up those values in windows.inc.

All members are DWORDs in size. Now where is that rgchBaggage member I promised I would describe? It's a little difficult to explain. rgchBaggage is a member of SHEXPACKET structure but it cannot be included into the structure definition because its size is arbitrary. Check shell.inc, you'd see that rgchBaggage is not defined in SHEXPACKET yet the Windows 9x DDK documentation asserts that it's a member of SHEXPACKET.
What's rgchBaggage? It's simply an array of ASCIIZ strings that follows SHEXPACKET structure. Within this array, you can put the name of the operation you want to perform on the file, the name of the file, the parameters you want to pass to the file and the working directory. SHELL VxD obtains the offset of the string in rgchBaggage by adding the relative distance between the SHEXPACKET structure to the first byte of the string to the flat offset of the SHEXPACKET. For example, if the SHEXPACKET structure begins at 60000h, and the string immediately follows the structure, the distance between the structure and the string is the size of the structure itself, 32 bytes (20h). So Shell VxD knows that the string is located at address 60020h.

The Example

This will be a very simple example just to show you how to register for an appy time event and use _SHELL_ShellExecute. The VxD will be a dynamic one which is loaded by a simple win32 application. When the user presses the "run Calculator" button, the win32 app calls DeviceIoControl to ask the VxD to register for an appy time event and run calc.exe which is located in the Windows directory.
 
;---------------------------------------------------------------------------------
;                                   VxD Source Code
;---------------------------------------------------------------------------------
.386p
include /masm/include/vmm.inc
include /masm/include/vwin32.inc
include /masm/include/shell.inc

VxDName TEXTEQU <VXDEXEC>
ControlName TEXTEQU <VXDEXEC_Control>
VxDMajorVersion TEXTEQU <1>
VxDMinorVersion TEXTEQU <0>

VxD_STATIC_DATA_SEG
VxD_STATIC_DATA_ENDS

VXD_LOCKED_CODE_SEG
;----------------------------------------------------------------------------
; Remember: The name of the vxd MUST be uppercase else it won't work/unload
;----------------------------------------------------------------------------
DECLARE_VIRTUAL_DEVICE %VxDName,%VxDMajorVersion,%VxDMinorVersion, %ControlName,UNDEFINED_DEVICE_ID,UNDEFINED_INIT_ORDER

Begin_control_dispatch %VxDName
        Control_Dispatch W32_DEVICEIOCONTROL, OnDeviceIoControl
End_control_dispatch %VxDName
 

BeginProc OnDeviceIoControl
 assume esi:ptr DIOCParams
 .if [esi].dwIoControlCode==1
      VxDCall _SHELL_CallAtAppyTime,<<OFFSET32 OnAppyTime>,0,0,0>
 .endif
 xor eax,eax
 ret
EndProc OnDeviceIoControl
VXD_LOCKED_CODE_ENDS

VXD_PAGEABLE_CODE_SEG
BeginProc OnAppyTime, CCALL
 ArgVar RefData,DWORD
 ArgVar TheFlag,DWORD
 EnterProc
 mov File.shex_dwTotalSize,sizeof SHEXPACKET
 add File.shex_dwTotalSize,sizeof EXEName
 mov File.shex_dwSize,sizeof SHEXPACKET
 mov File.shex_ibOp,0
 mov File.shex_ibFile,sizeof SHEXPACKET
 mov File.shex_ibParams,0
 mov File.shex_ibDir,0
 mov File.shex_dwReserved,0
 mov File.shex_nCmdShow,1
 VxDCall _SHELL_ShellExecute, <OFFSET32 File>
 LeaveProc
 Return
EndProc OnAppyTime
VXD_PAGEABLE_CODE_ENDS

VXD_PAGEABLE_DATA_SEG
 File SHEXPACKET <>
 EXEName db "calc.exe",0
VXD_PAGEABLE_DATA_ENDS

end

Analysis

The VxD waits for DeviceIoControl messages, service no.1. When it receives such message, it registers for an application time event.
VxDCall _SHELL_CallAtAppyTime,<<OFFSET32 OnAppyTime>,0,0,0>
It passes the flat address of OnAppyTime function to _SHELL_CallAtAppyTime so that Shell VxD will call it when an appy time event occurs. We don't use any reference data and have no need for timeout so all three parameters following the flat address of OnAppyTime are zeroes.
When an appy time event occurs, the Shell VxD calls OnAppyTime function.
BeginProc OnAppyTime, CCALL
We declare a function with BeginProc. Since the Shell VxD will call OnAppyTime with C calling sequence, we need to specify CCALL attribute.
ArgVar RefData,DWORD
ArgVar TheFlag,DWORD
EnterProc
...
LeaveProc
Return
Since the Shell VxD will call OnAppyTime with two parameters, we must setup the stack frame accordingly. ArgVar macro is for adjusting the stack frame for each of the argument passed to the function. Its syntax is as follows:
ArgVar  varname, size, used
varname is the name of the parameter. You can use any name you like. size is, of course, the size of the parameter in bytes. You can use BYTE, WORD, DWORD or 1,2,4. used is usually omitted.
Immediately following the ArgVar macros, we need to use EnterProc and LeaveProc macros to mark the beginning and the end of the instructions in the procedure so that the local variables and parameters can be accessed correctly. Use Return macro to return to the caller.
 mov File.shex_dwTotalSize,sizeof SHEXPACKET
 add File.shex_dwTotalSize,sizeof EXEName
 mov File.shex_dwSize,sizeof SHEXPACKET
 mov File.shex_ibOp,0
 mov File.shex_ibFile,sizeof SHEXPACKET
 mov File.shex_ibParams,0
 mov File.shex_ibDir,0
 mov File.shex_dwReserved,0
 mov File.shex_nCmdShow,1
 VxDCall _SHELL_ShellExecute, <OFFSET32 File>
The instructions inside the procedure is simple: initialize the SHEXPACKET structure and call _SHELL_ShellExecute service. Note that shex_dwTotalSize contains the combined size of the SHEXPACKET structure itself and the size of the string that follows it. This is the simple case. If the string doesn't immediately follow the structure, you must calculate the distance between the first byte of the structure and the last byte of the string yourself. shex_ibFile contains the size of the structure itself because the name of the program immediately follows the structure. shex_ibDir is zero meaning that we want to use the Windows directory as the working directory. Note that this doesn't mean the program must be in the windows directory. The program can be anywhere so long as Windows can find it. shex_nCmdShow is 1 which is the value SW_SHOWNORMAL.
File SHEXPACKET <>
EXEName db "calc.exe",0
We define a SHEXPACKET structure followed immediately by the name of the program that we want to execute.

[Iczelion's Win32 Assembly Homepage]
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

相关推荐
<p> <span style="font-size:14px;color:#337FE5;">【为什么学爬虫?】</span> </p> <p> <span style="font-size:14px;">       1、爬虫入手容易,但是深入较难,如何写出高效率的爬虫,如何写出灵活性高可扩展的爬虫都是一项技术活。另外在爬虫过程中,经常容易遇到被反爬虫,比如字体反爬、IP识别、验证码等,如何层层攻克难点拿到想要的数据,这门课程,你都能学到!</span> </p> <p> <span style="font-size:14px;">       2、如果是作为一个其他行业的开发者,比如app开发,web开发,学习爬虫能让你加强对技术的认知,能够开发出更加安全的软件和网站</span> </p> <p> <br /> </p> <span style="font-size:14px;color:#337FE5;">【课程设计】</span> <p class="ql-long-10663260"> <span> </span> </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 一个完整的爬虫程序,无论大小,总体来说可以分成三个步骤,分别是: </p> <ol> <li class="" style="font-size:11pt;color:#494949;"> 网络请求:模拟浏览器的行为从网上抓取数据。 </li> <li class="" style="font-size:11pt;color:#494949;"> 数据解析:将请求下来的数据进行过滤,提取我们想要的数据。 </li> <li class="" style="font-size:11pt;color:#494949;"> 数据存储:将提取到的数据存储到硬盘或者内存中。比如用mysql数据库或者redis等。 </li> </ol> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 那么本课程也是按照这几个步骤循序渐进的进行讲解,带领学生完整的掌握每个步骤的技术。另外,因为爬虫的多样性,在爬取的过程中可能会发生被反爬、效率低下等。因此我们又增加了两个章节用来提高爬虫程序的灵活性,分别是: </p> <ol> <li class="" style="font-size:11pt;color:#494949;"> 爬虫进阶:包括IP代理,多线程爬虫,图形验证码识别、JS加密解密、动态网页爬虫、字体反爬识别等。 </li> <li class="" style="font-size:11pt;color:#494949;"> Scrapy和分布式爬虫:Scrapy框架、Scrapy-redis组件、分布式爬虫等。 </li> </ol> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 通过爬虫进阶的知识点我们能应付大量的反爬网站,而Scrapy框架作为一个专业的爬虫框架,使用他可以快速提高我们编写爬虫程序的效率和速度。另外如果一台机器不能满足你的需求,我们可以用分布式爬虫让多台机器帮助你快速爬取数据。 </p> <p style="font-size:11pt;color:#494949;">   </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> 从基础爬虫到商业化应用爬虫,本套课程满足您的所有需求! </p> <p class="ql-long-26664262" style="font-size:11pt;color:#494949;"> <br /> </p> <p> <br /> </p> <p> <span style="font-size:14px;background-color:#FFFFFF;color:#337FE5;">【课程服务】</span> </p> <p> <span style="font-size:14px;">专属付费社群+定期答疑</span> </p> <p> <br /> </p> <p class="ql-long-24357476"> <span style="font-size:16px;"><br /> </span> </p> <p> <br /> </p> <p class="ql-long-24357476"> <span style="font-size:16px;"></span> </p>
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值