📄 pe-tut2.html
字号:
assume edi:ptr IMAGE_NT_HEADERS <br>
.if [edi].Signature==IMAGE_NT_SIGNATURE <br>
mov ValidPE, TRUE <br>
.else <br>
mov ValidPE, FALSE <br>
.endif <br>
.else
<br>
mov ValidPE,FALSE <br>
.endif
<br>
FinalExit: <br>
.if
ValidPE==TRUE <br>
invoke MessageBox, 0, addr FileValidPE, addr AppName, MB_OK+MB_ICONINFORMATION
<br>
.else
<br>
invoke MessageBox, 0, addr FileInValidPE, addr AppName, MB_OK+MB_ICONINFORMATION
<br>
.endif
<br>
push
seh.PrevLink <br>
pop
fs:[0] <br>
invoke
UnmapViewOfFile, pMapping <br>
.else <br>
invoke
MessageBox, 0, addr FileMappingError, addr AppName, MB_OK+MB_ICONERROR <br>
.endif <br>
invoke CloseHandle,hMapping
<br>
.else <br>
invoke MessageBox, 0,
addr FileOpenMappingError, addr AppName, MB_OK+MB_ICONERROR <br>
.endif <br>
invoke CloseHandle, hFile <br>
.else <br>
invoke MessageBox, 0, addr FileOpenError,
addr AppName, MB_OK+MB_ICONERROR <br>
.endif <br>
.endif <br>
invoke ExitProcess, 0 <br>
start endp <br>
<br>
SEHHandler proc uses edx pExcept:DWORD, pFrame:DWORD, pContext:DWORD, pDispatch:DWORD
<br>
mov edx,pFrame <br>
assume edx:ptr SEH <br>
mov eax,pContext <br>
assume eax:ptr CONTEXT <br>
push [edx].SafeOffset <br>
pop [eax].regEip <br>
push [edx].PrevEsp <br>
pop [eax].regEsp <br>
push [edx].PrevEbp <br>
pop [eax].regEbp <br>
mov ValidPE, FALSE <br>
mov eax,ExceptionContinueExecution <br>
ret <br>
SEHHandler endp <br>
end start </font></p>
<h3><font face="Arial, Helvetica, sans-serif">Analysis:</font></h3>
<p><font face="MS Sans Serif" size="-1">The program opens a file and checks if
the DOS header is valid, if it is, it checks the PE header if it's valid. If
it is, then it assumes the file is a valid PE. In this example, I use structured
exception handling (SEH) so that we don't have to check for every possible error:
if a fault occurs, we assume that it's because the file is not a valid PE thus
giving our program wrong information. Windows itself uses SEH heavily in its
parameter validation routines. If you're interested in SEH, read <b><a href="Exceptionhandling.html" style="text-decoration:none">the
article</a></b> by Jeremy Gordon.</font></p>
<p><font face="MS Sans Serif" size="-1">The program displays an open file common
dialog to the user and when the user chooses an executable file, it opens the
file and maps it into memory. Before it goes on with the verification, it sets
up a SEH:</font></p>
<p><font face="Fixedsys"> assume fs:nothing <br>
push fs:[0] <br>
pop seh.PrevLink <br>
mov seh.CurrentHandler,offset SEHHandler <br>
mov seh.SafeOffset,offset FinalExit <br>
lea eax,seh <br>
mov fs:[0], eax <br>
mov seh.PrevEsp,esp <br>
mov seh.PrevEbp,ebp </font></p>
<p><font face="MS Sans Serif" size="-1">We start by assuming the use of fs register
as nothing. This must be done because MASM assumes the use of fs register to
ERROR. Next we store the address of the previous SEH handler in our structure
for use by Windows. We store the address of our SEH handler, the address where
the execution can safely resume if a fault occurs, the current values of esp
and ebp so that our SEH handler can get the state of the stack back to normal
before it resumes the execution of our program.</font></p>
<p><font face="Fixedsys"> mov edi, pMapping <br>
assume edi:ptr IMAGE_DOS_HEADER <br>
.if [edi].e_magic==IMAGE_DOS_SIGNATURE </font></p>
<p><font face="MS Sans Serif" size="-1">After we are done with setting up SEH,
we continue with the verification. We put the address of the first byte of the
target file in edi, which is the first byte of the DOS header. For ease of comparison,
we tell the assembler that it can assume edi as pointing to the<font color="#CCFFCC"><b>
IMAGE_DOS_HEADER</b></font> structure (which is the truth). We then compare
the first word of the DOS header with the string "MZ" which is defined
as a constant in windows.inc named <font color="#CCFFCC"><b>IMAGE_DOS_SIGNATURE</b></font>.
If the comparison is ok, we continue to the PE header. If not, we set the value
in <font color="#FFFFCC"><b>ValidPE</b></font> to FALSE, meaning that the file
is not a valid PE.</font></p>
<p><font face="Fixedsys"> add edi, [edi].e_lfanew
<br>
assume edi:ptr IMAGE_NT_HEADERS <br>
.if [edi].Signature==IMAGE_NT_SIGNATURE
<br>
mov ValidPE, TRUE <br>
.else <br>
mov ValidPE, FALSE <br>
.endif </font></p>
<p><font face="MS Sans Serif" size="-1">To get to the PE header, we need the value
in <font color="#FFFFCC"><b>e_lfanew</b></font> of the DOS header. This field
contains the file offset of the PE header, relative to the file beginning. Thus
we add this value to edi and we get to the first byte of the PE header. It's
this place that a fault may occur. If the file is really not a PE file, the
value in e_lfanew will be incorrect and thus using it amounts to using a wild
pointer. If we don't use SEH, we must check the value of the <font color="#FFFFCC"><b>e_lfanew</b></font>
against the file size which is ugly. If all goes well, we compare the first
dword of the PE header with the string "PE". Again there is a handy
constant named <font color="#CCFFCC"><b>IMAGE_NT_SIGNATURE</b></font> which
we can use. If the result of comparison is true, we assume the file is a valid
PE.<br>
If the value in<font color="#FFFFCC"><b> e_lfanew</b></font> is incorrect, a
fault may occur and our SEH handler will get control. It simply restores the
stack pointer, bsae pointer and resumes the execution at the safe offset which
is at the FinalExit label.</font></p>
<p><font face="Fixedsys">FinalExit: <br>
.if ValidPE==TRUE <br>
invoke MessageBox, 0, addr FileValidPE,
addr AppName, MB_OK+MB_ICONINFORMATION <br>
.else <br>
invoke MessageBox, 0, addr FileInValidPE,
addr AppName, MB_OK+MB_ICONINFORMATION <br>
.endif </font></p>
<p><font face="MS Sans Serif" size="-1">The above code is simplicity itself. It
checks the value in ValidPE and displays a message to the user accordingly.</font></p>
<p><font face="Fixedsys"> push seh.PrevLink <br>
pop fs:[0] </font></p>
<p><font face="MS Sans Serif" size="-1">When the SEH is no longer used, we dissociate
it from the SEH chain.</font></p>
<hr>
<p align="center"><font face="MS Sans Serif" size="-1"><b>[<a href="http://win32asm.cjb.net">Iczelion's
Win32 Assembly Homepage</a>]</b></font></p>
<p> </p>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -