broadviewbj 发表于 2011-12-22 08:53

编写安全的驱动程序之输入输出检查

<SPAN style="FONT-FAMILY: 宋体"><FONT size=5>编写安全的驱动程序之输入输出检查<SPAN lang=EN-US></SPAN></FONT></SPAN>
<P style="TEXT-INDENT: 20pt; MARGIN: 0cm 0cm 0pt" class=MsoNormal><SPAN style="FONT-FAMILY: 宋体"><FONT size=2>输入输出检查是指对不可信的输入输出地址及数据长度进行合法性检查的过程。这种方法在<SPAN lang=EN-US>Windows</SPAN>内核<SPAN lang=EN-US>API</SPAN>中应用的十分广泛。<SPAN lang=EN-US></SPAN></FONT></SPAN></P>
<P style="TEXT-INDENT: 20pt; MARGIN: 0cm 0cm 7.8pt" class=a0><SPAN style="FONT-FAMILY: 宋体"><FONT size=2>例如,在<SPAN lang=EN-US>NtReadFile</SPAN>函数中,如果<SPAN lang=EN-US>PreviousMode</SPAN>不是<SPAN lang=EN-US>KernelMode</SPAN>,即<SPAN lang=EN-US>NtReadFile</SPAN>函数是从用户态被调用的,可以使用<SPAN lang=EN-US>ProbeForWrite</SPAN>函数检测输入输出缓冲区是否可写,参见<SPAN lang=EN-US>ReactOS</SPAN>中的代码如下:<SPAN lang=EN-US></SPAN></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9">NTSTATUS NTAPI NtReadFile(IN HANDLE FileHandle,</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>IN HANDLE Event OPTIONAL,</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>IN PIO_APC_ROUTINE ApcRoutine OPTIONAL,</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>IN PVOID ApcContext OPTIONAL,</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>OUT PIO_STATUS_BLOCK IoStatusBlock,</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>OUT PVOID Buffer,</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>IN ULONG Length,</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>IN PLARGE_INTEGER ByteOffset OPTIONAL,</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>IN PULONG Key OPTIONAL)</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9">{ </FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp; </FONT></SPAN>KPROCESSOR_MODE PreviousMode = KeGetPreviousMode();</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT style=""><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp; </FONT></SPAN>//</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体">省略部分代码<SPAN lang=EN-US>...... </SPAN></SPAN></FONT></FONT></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp; </FONT></SPAN>/* Validate User-Mode Buffers */</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp; </FONT></SPAN>if (PreviousMode != KernelMode)</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp; </FONT></SPAN>{</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>_SEH2_TRY</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>{</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>/* Probe the status block */</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>ProbeForWriteIoStatusBlock(IoStatusBlock); </FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>/* Probe the read buffer */</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT></SPAN>ProbeForWrite(Buffer, Length, 1);</FONT></FONT></SPAN></P>
<P style="MARGIN: 0cm 0cm 0pt" class=a><FONT size=2><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT style="BACKGROUND-COLOR: #d9d9d9"><SPAN style="mso-spacerun: yes"><FONT style="">&nbsp;&nbsp;&nbsp; </FONT></SPAN>//</FONT></SPAN><SPAN style="FONT-FAMILY: 宋体"><FONT style="BACKGROUND-COLOR: #d9d9d9">省略部分代码<SPAN lang=EN-US>......</SPAN></FONT></SPAN></FONT></P>
<P style="TEXT-INDENT: 20pt; MARGIN: 7.8pt 0cm 0pt" class=a1><SPAN style="FONT-FAMILY: 宋体"><FONT size=2>类似地,在<SPAN lang=EN-US>NtWriteFile</SPAN>函数中当发现<SPAN lang=EN-US>PreviousMode</SPAN>不是<SPAN lang=EN-US>KernelMode</SPAN>时,即从用户态调用过来的,可以使用<SPAN lang=EN-US>ProbeForRead</SPAN>函数进行检测。<SPAN lang=EN-US></SPAN></FONT></SPAN></P>
<P style="TEXT-INDENT: 20pt; MARGIN: 0cm 0cm 0pt" class=MsoNormal><SPAN style="FONT-FAMILY: 宋体"><FONT size=2>此外,在<SPAN lang=EN-US>IoControl</SPAN>中如果<SPAN lang=EN-US>IoControlCode</SPAN>指定的<SPAN lang=EN-US>Mthod</SPAN>为<SPAN lang=EN-US>METHOD_NEITHER</SPAN>时,也应当对输入和输出地址使用<SPAN lang=EN-US>ProbeForRead</SPAN>和<SPAN lang=EN-US>ProbeForWrite</SPAN>函数进行检验。<SPAN lang=EN-US></SPAN></FONT></SPAN></P>
<P style="TEXT-INDENT: 20pt; MARGIN: 0cm 0cm 0pt" class=MsoNormal><SPAN style="FONT-FAMILY: 宋体" lang=EN-US><FONT size=2>&nbsp;<a href="http://blog.chinaunix.nethttp://blog.chinaunix.net/attachment/201107/11/13164110_13103839327aaA.jpg" target="_blank"><IMG .load="imgResize(this, 650);" border=0 src="http://blog.chinaunix.nethttp://blog.chinaunix.net/attachment/201107/11/13164110_13103839327aaA.jpg" ;></A></FONT></SPAN></P>
<P style="TEXT-INDENT: 20pt; MARGIN: 0cm 0cm 0pt; LAYOUT-GRID-MODE: char; mso-layout-grid-align: none" class=MsoNormal><SPAN style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt"><FONT size=2>本文节选自《<SPAN lang=EN-US>0day</SPAN>安全:软件漏洞分析技术(第<SPAN lang=EN-US>2</SPAN>版)》一书。<SPAN lang=EN-US></SPAN></FONT></SPAN></P>
<P style="TEXT-INDENT: 20pt; MARGIN: 0cm 0cm 0pt; LAYOUT-GRID-MODE: char; mso-layout-grid-align: none" class=MsoNormal><SPAN style="FONT-FAMILY: 宋体; mso-bidi-font-size: 10.5pt"><FONT size=2>图书详细信息<SPAN lang=EN-US>:http://blog.chinaunix.net/space.php?uid=13164110&amp;do=blog&amp;id=1645730</SPAN></FONT></SPAN></P>
页: [1]
查看完整版本: 编写安全的驱动程序之输入输出检查