📄 lion-tutorial29.htm
字号:
.data <br>
AppName db "Win32 Debug Example no.2",0 <br>
ClassName db "SimpleWinClass",0 <br>
SearchFail db "Cannot find the target process",0 <br>
TargetPatched db "Target patched!",0 <br>
buffer dw 9090h<br>
<br>
.data? <br>
DBEvent DEBUG_EVENT <> <br>
ProcessId dd ? <br>
ThreadId dd ? <br>
align dword <br>
context CONTEXT <> <br>
<br>
.code <br>
start: <br>
invoke FindWindow, addr ClassName, NULL <br>
.if eax!=NULL <br>
invoke GetWindowThreadProcessId, eax, addr ProcessId <br>
mov ThreadId, eax <br>
invoke DebugActiveProcess, ProcessId <br>
.while TRUE <br>
invoke WaitForDebugEvent, addr DBEvent,
INFINITE <br>
.break .if DBEvent.dwDebugEventCode==EXIT_PROCESS_DEBUG_EVENT
<br>
.if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT
<br>
mov context.ContextFlags,
CONTEXT_CONTROL <br>
invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread,
addr context <br>
invoke WriteProcessMemory,
DBEvent.u.CreateProcessInfo.hProcess, context.regEip ,addr buffer, 2, NULL<br>
invoke MessageBox, 0,
addr TargetPatched, addr AppName, MB_OK+MB_ICONINFORMATION <br>
.elseif DBEvent.dwDebugEventCode==EXCEPTION_DEBUG_EVENT
<br>
.if DBEvent.u.Exception.pExceptionRecord.ExceptionCode==EXCEPTION_BREAKPOINT
<br>
invoke
ContinueDebugEvent, DBEvent.dwProcessId,DBEvent.dwThreadId, DBG_CONTINUE <br>
.continue
<br>
.endif <br>
.endif <br>
invoke ContinueDebugEvent, DBEvent.dwProcessId,
DBEvent.dwThreadId, DBG_EXCEPTION_NOT_HANDLED <br>
.endw <br>
.else <br>
invoke MessageBox, 0, addr SearchFail, addr AppName,MB_OK+MB_ICONERROR
.endif <br>
invoke ExitProcess, 0 <br>
end start </p>
<p>;--------------------------------------------------------------------<br>
; The partial source code of win.asm, our debuggee. It's actually<br>
; the simple window example in tutorial 2 with an infinite loop inserted<br>
; just before it enters the message loop.<br>
;----------------------------------------------------------------------</p>
<p>......<br>
mov wc.hIconSm,eax <br>
invoke LoadCursor,NULL,IDC_ARROW <br>
mov wc.hCursor,eax <br>
invoke RegisterClassEx, addr wc <br>
INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\ WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\ hInst,NULL <br>
mov hwnd,eax <br>
jmp $ <---- Here's our infinite loop. It assembles to EB FE<br>
invoke ShowWindow, hwnd,SW_SHOWNORMAL <br>
invoke UpdateWindow, hwnd <br>
.while TRUE <br>
invoke GetMessage, ADDR msg,NULL,0,0 <br>
.break .if (!eax) <br>
invoke TranslateMessage, ADDR msg <br>
invoke DispatchMessage, ADDR msg <br>
.endw <br>
mov eax,msg.wParam <br>
ret <br>
WinMain endp </p>
<h3>Analysis:</h3>
<p>invoke FindWindow, addr ClassName, NULL </p>
<p>Our program needs to attach itself to the debuggee with <b>DebugActiveProcess
</b>which requires the process Id of the debuggee. We can obtain the process
Id by calling <b>GetWindowThreadProcessId </b>which in turn needs the window
handle as its parameter. So we need to obtain the window handle first. <br>
With <b>FindWindow</b>, we can specify the name of the window class we need.
It returns the handle to the window created by that window class. If it returns<b>
NULL</b>, no window of that class is present.</p>
<p> .if eax!=NULL <br>
invoke GetWindowThreadProcessId, eax, addr ProcessId <br>
mov ThreadId, eax <br>
invoke DebugActiveProcess, ProcessId </p>
<p>After we obtain the process Id, we can call <b>DebugActiveProcess</b>. Then
we enter the debug loop waiting for the debug events.</p>
<p> .if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT
<br>
mov context.ContextFlags,
CONTEXT_CONTROL <br>
invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread,
addr context </p>
<p>When we get<b> CREATE_PROCESS_DEBUG_INFO</b>, it means the debuggee is suspended,
ready for us to do surgery upon its process. In this example, we will overwrite
the infinite loop instruction in the debuggee (0EBh 0FEh) with NOPs ( 90h 90h).
<br>
First, we need to obtain the address of the instruction. Since the debuggee
is already in the loop by the time our program attached to it, eip will always
point to the instruction. All we need to do is obtain the value of eip. We use
<b>GetThreadContext</b> to achieve that goal. We set the <b>ContextFlags</b>
member to <b>CONTEXT_CONTROL </b>so as to tell <b>GetThreadContext</b> that
we want it to fill the "control" register members of the<b> CONTEXT</b>
structure.</p>
<p> invoke WriteProcessMemory,
DBEvent.u.CreateProcessInfo.hProcess, context.regEip ,addr buffer, 2, NULL</p>
<p>Now that we get the value of eip, we can call <b>WriteProcessMemory</b> to
overwrite the "jmp $" instruction with NOPs, thus effectively help
the debuggee exit the infinite loop. After that we display the message to the
user and then call <b>ContinueDebugEvent</b> to resume the debuggee. Since the
"jmp $" instruction is overwritten by NOPs, the debuggee will be able
to continue with showing its window and enter the message loop. The evidence
is we will see its window on screen.</p>
<p>The other example uses a slightly different approach to break the debuggee
out of the infinite loop.</p>
<p> .......<br>
.......<br>
.if DBEvent.dwDebugEventCode==CREATE_PROCESS_DEBUG_EVENT <br>
mov context.ContextFlags, CONTEXT_CONTROL <br>
invoke GetThreadContext,DBEvent.u.CreateProcessInfo.hThread,
addr context <br>
add context.regEip,2 <br>
invoke SetThreadContext,DBEvent.u.CreateProcessInfo.hThread,
addr context <br>
invoke MessageBox, 0, addr LoopSkipped, addr AppName, MB_OK+MB_ICONINFORMATION
<br>
.......<br>
....... </p>
<p>It still calls <b>GetThreadContext</b> to obtain the current value of eip but
instead of overwriting the "jmp $" instruction, it increments the
value of<b> regEip</b> by 2 to "skip over" the instruction. The result
is that when the debuggee regains control , it resumes execution at the next
instruction after "jmp $". </p>
<p>Now you can see the power of Get/SetThreadContext. You can also modify the
other register images as well and their values will be reflected back to the
debuggee. You can even insert int 3h instruction to put breakpoints in the debuggee
process.<strong> </strong></p>
<hr size="1">
<div align="center"> This article come from Iczelion's asm page, Welcom to <a href="http://asm.yeah.net">http://asm.yeah.net</a></div>
</body>
</html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -