看了《加密与解密》第19章觉得手痒所以做了这个。废话少说,直奔主题。
这里采用的是增加接口的方法,一共分为3步:
1.编写DLL
2.添加导入函数
3.修改和添加代码
1.编写DLL
实现全屏的代码如下:
代码:
.386 .model flat, stdcall option casemap:none include windows.inc include user32.inc include gdi32.inc include kernel32.inc includelib user32.lib includelib gdi32.lib includelib kernel32.lib .data szErrlWinMode db "set window window mode faild", 0 szErrlFullScr db "set window full screen mode faild", 0 szCaption db "Info",0 bIsFullMode dword FALSE stOriginPos WINDOWPLACEMENT <0> ESC_HOTKEY equ 1 F11_HOTKEY equ 2 .code DllEntry proc _hInstance, _dwReason, _dwReserved mov eax, TRUE ret DllEntry endp SetFullScr proc _hWnd local @hDC local @dwHorzres local @dwVertres invoke GetWindowPlacement, _hWnd, addr stOriginPos invoke GetWindowLong, _hWnd, GWL_STYLE xor eax, WS_CAPTION invoke SetWindowLong, _hWnd, GWL_STYLE, eax ;去掉标题栏 invoke GetDC, _hWnd mov @hDC, eax invoke GetDeviceCaps, @hDC, HORZRES mov @dwHorzres, eax invoke GetDeviceCaps, @hDC, VERTRES mov @dwVertres, eax xor eax, eax invoke SetWindowPos, _hWnd, HWND_TOPMOST, eax, eax, @dwHorzres, @dwVertres, SWP_SHOWWINDOW ;全屏显示 ret SetFullScr endp SetWinMode proc _hWnd xor eax, eax invoke SetWindowPos, _hWnd, HWND_NOTOPMOST, eax, eax, eax, eax, SWP_NOSIZE ;添加此两行,修正bug invoke GetWindowLong, _hWnd, GWL_STYLE or eax, WS_CAPTION invoke SetWindowLong, _hWnd, GWL_STYLE, eax ;恢复标题栏 invoke ShowWindow, _hWnd, SW_HIDE invoke SetWindowPlacement, _hWnd, addr stOriginPos ret SetWinMode ENDP SwitchMode proc _hWnd .if bIsFullMode == TRUE invoke SetWinMode, _hWnd .IF eax==0 invoke MessageBox, _hWnd, addr szErrlWinMode, addr szCaption, MB_ICONERROR ret .ENDIF mov bIsFullMode, FALSE .else invoke SetFullScr, _hWnd .IF eax==0 invoke MessageBox, _hWnd, addr szErrlFullScr, addr szCaption, MB_ICONERROR ret .ENDIF mov bIsFullMode, TRUE .endif ret SwitchMode endp WndProc proc C dwReserved, hWnd, uMsg, wParam, lParam mov eax, uMsg .if eax == WM_HOTKEY .if wParam == ESC_HOTKEY && bIsFullMode == TRUE invoke SwitchMode, hWnd .elseif wParam == F11_HOTKEY && bIsFullMode == FALSE invoke SwitchMode, hWnd .endif .elseif eax == WM_CREATE invoke RegisterHotKey, hWnd, F11_HOTKEY, 0, VK_F11 invoke RegisterHotKey, hWnd, ESC_HOTKEY, 0, VK_ESCAPE .elseif eax == WM_DESTROY invoke UnregisterHotKey, hWnd, F11_HOTKEY invoke UnregisterHotKey, hWnd, ESC_HOTKEY .endif ret WndProc endp end DllEntry
编写的DLL只导出了一个函数WndProc,需要特别注意的是
WndProc proc C dwReserved, hWnd, uMsg, wParam, lParam,对了就是指定函数的调用类型为C,Tnnd当初我就是栽在这儿了
2.添加导入函数
用LordPE打开OllyICE,点击“Directories”->在弹出的DirectoryTable窗口中的import项后面的“...”按钮上单击->在弹出的ImportTable窗口中单击右键->“add import”->在弹出的AddImport窗口中输入上面创建的DLL文件名(这里是od.dll)->API对应的文本框填写此DLL到处的函数(这里是WndProc)->单击“+”按钮,再单击OK搞定。
这样我们就添加好了输入函数。我们需要记住的唯一一个数据是ThunkRVA(这里是1AA00D),在400000(基址)+ 1AA00D = 5AA00D该处,程序加载完成时这里的双字就是DLL中的WndProc函数地址。
最好是将DLL文件Copy至OllyICE所在目录,否则LordPE会有“API not found!”的提示。
3.修改和添加代码
我们应当首先找到主窗体的窗口过程。我这里是对在注册窗口类时断下,这样就可以通过窗口类得到窗口过程了。按CTRL + N,在弹出的函数名窗口中找到user32的导出函数RegisterClassA,在该行单击回车就到了RegisterClassA的函数参考窗口,可以看到一共是有7条记录,按F2全部设断。回到CPU窗口,按F9执行就断在
代码:
00435CDE . E8 69980700 call <jmp.&USER32.RegisterClassA> ; \RegisterClassA
代码:
00435C6A . C785 94F6FFFF>mov dword ptr [ebp-96C], OI.004323D4 ; 入口地址
代码:
004323D4 /$ 55 push ebp 004323D5 |. 8BEC mov ebp, esp 004323D7 |. 81C4 04F0FFFF add esp, -0FFC
代码:
004323D4 /E9 E2D30700 jmp OllyICE.004AF7BB 004323D9 |90 nop 004323DA |90 nop 004323DB |90 nop 004323DC |90 nop
代码:
004AF7BB 00 db 00 004AF7BC 00 db 00 004AF7BD 00 db 00 004AF7BE 00 db 00 004AF7BF 00 db 00 004AF7C0 00 db 00
代码:
004AF7BB FF15 0DA05A00 call dword ptr [<&od.WndProc>] ; od.WndProc 004AF7C1 55 push ebp 004AF7C2 8BEC mov ebp, esp 004AF7C4 81C4 04F0FFFF add esp, -0FFC 004AF7CA ^ E9 0E2CF8FF jmp OllyICE.004323DD
这样,我们就可以按F11键实现全屏,而按Esc键退出全屏。哈哈,Pediy够简单的吧。

附件里是修改好的OllyICE和od.asm,od.def.od.dll,请注意你的OllyICE版本是否和我的一样。