大理寺少卿 发表于 2024-12-27 21:28:56

Win32汇编学习笔记07.筛选器异常

### 钢琴

od调试老师给的多媒体钢琴

!(./notesimg/1634224633130-ca6325fa-d08b-4761-8798-1f713c4252a5.png)

运行找到Piano的过程函数里去

!(./notesimg/1634224670232-98f7f15a-32b0-468a-bb41-5347e6759a69.png)

找到处理WM_KEYDOWN消息的那

!(./notesimg/1634224725844-2efdc8ac-6538-4837-9e48-e5b9602ce263.png)

下个断点,然后按键断下来在这

!(./notesimg/1634224775277-15054e01-dfea-408e-8eca-5c50343694e5.png)

- 分析上图汇编代码:mov eax,dword ptr 拿wParma
- lea ecx,dword ptr ,41的ASSCII为A,这里应该是判断是哪个按键做准备
- cmp ecx,19    19h->25,0~25为26个数,对应26个字母
- ja imm      大于则不是字母按键,跳出
- 发出声音功能的函数应该是下面的call <jnp.&oiano_dll.fun_lpayOneSound>
- 然后我们观察该函数,分析其为C调用约定,传入一个参数,push eax
- !(./notesimg/1634226084685-6e29529d-78f3-4382-9bd5-d60c189cbca0.png)
- 该函数参数eax的来源是上面的wParma

我们去写一个win32程序去测试一下

RasAsm创建工程MyPiano

!(./notesimg/1634227785976-f935c56c-de5e-4c7f-ae22-4b17f8bac8a8.png)

相应地方:;=============包起来的是后加入的代码

```
586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   
   includelib user32.lib
   includelib kernel32.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD


.data
   ClassName db "MainWinClass",0
   AppNamedb "Main Window",0
   g_szPianoDll db "piano_dll",0
   g_szPlayOneSound db "fun_playOneSound",0
   g_pfnPlayOneSound dd 0
   g_hPianoDll dd 0

.data?
   hInstance HINSTANCE ?
   CommandLine LPSTR ?

.code


; ---------------------------------------------------------------------------


start:
        ;=============
        invoke LoadLibrary,offset g_szPianoDll
        mov g_hPianoDll,eax
        invoke GetProcAddress,g_hPianoDll,offset g_szPlayOneSound
        mov g_pfnPlayOneSound,eax
        ;=============

        invoke GetModuleHandle, NULL
        mov    hInstance,eax

        invoke GetCommandLine
        mov    CommandLine,eax

        invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
        invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
        LOCAL wc:WNDCLASSEX
        LOCAL msg:MSG
        LOCAL hwnd:HWND

        mov   wc.cbSize,SIZEOF WNDCLASSEX
        mov   wc.style, CS_HREDRAW or CS_VREDRAW
        mov   wc.lpfnWndProc, OFFSET WndProc
        mov   wc.cbClsExtra,NULL
        mov   wc.cbWndExtra,NULL
        pushhInstance
        pop   wc.hInstance
        mov   wc.hbrBackground,COLOR_BTNFACE+1
        mov   wc.lpszMenuName,NULL
        mov   wc.lpszClassName,OFFSET ClassName

        invoke LoadIcon,NULL,IDI_APPLICATION
        mov   wc.hIcon,eax
        mov   wc.hIconSm,eax

        invoke LoadCursor,NULL,IDC_ARROW
        mov   wc.hCursor,eax

        invoke RegisterClassEx, addr wc
        INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
         WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
         CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
         hInst,NULL
        mov   hwnd,eax

        invoke ShowWindow, hwnd,SW_SHOWNORMAL
        invoke UpdateWindow, hwnd

        .WHILE TRUE
                invoke GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                invoke TranslateMessage, ADDR msg
                invoke DispatchMessage, ADDR msg
        .ENDW

        mov   eax,msg.wParam
        ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

        .IF uMsg==WM_DESTROY
                invoke PostQuitMessage,NULL
        .ELSEIF uMsg==WM_CREATE
.elseif uMsg==WM_KEYDOWN
                ;=============
                push wParam
                call g_pfnPlayOneSound
                add esp,4
                ;=============
        .ELSE
                invoke DefWindowProc,hWnd,uMsg,wParam,lParam       
                ret
        .ENDIF

        xor eax,eax
        ret
WndProc endp


end start
```

但是我们发现无论是注入asm和刚刚的这个,都无法让钢琴发出声音,我们在换成WM_KEYUP和 WM_KEYCHAR 结果跟 WM_KEYDOWN 一样 因此我们打开dll看看其导出函数(之前分析那个函数的所在dll)

!(./notesimg/1634229049115-00a4b1be-08cc-40bd-8639-17c10ba4cc9e.png)

猜想可能有所谓的播放环境,可能需要调用其它函数相辅相成

比如需要先调用fun_Create,可能调用时机比较早,我们直接用od调式去对应dll查看名称找该函数。

!(./notesimg/1634229373089-f24dfa1b-2e34-469e-9981-c1f00024a8ec.png)

查看参考

!(./notesimg/1634229472993-ac5e060a-732f-43e9-8576-a2fa9612c3e9.png)

发现只有一个地方式函数调用,我们直接去看看

!(./notesimg/1634229563342-f84463d9-9f94-431f-8a03-0983eebb630e.png)

发现WM_CREATE就调用了,果然如此

因此回到我们的MyPiano的工程中加入对应的,注意要将对应dll及其它可能用到文件都拷贝到工程目录下

值得注意的是fun_Create有一个参数,在上图看出来参数来自esi,可追溯其来源

然后修改为:

```
.586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   
   includelib user32.lib
   includelib kernel32.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD


.data
   ClassName db "MainWinClass",0
   AppNamedb "Main Window",0
   g_szPianoDll db "piano_dll",0
   g_szPlayOneSound db "fun_playOneSound",0
   g_szfun_Create db "fun_Create",0
   g_pfnPlayOneSound dd 0
   g_pnfun_Create dd 0
   g_hPianoDll dd 0

.data?
   hInstance HINSTANCE ?
   CommandLine LPSTR ?

.code


; ---------------------------------------------------------------------------


start:
        ;=============
        invoke LoadLibrary,offset g_szPianoDll
        mov g_hPianoDll,eax
        invoke GetProcAddress,g_hPianoDll,offset g_szPlayOneSound
        mov g_pfnPlayOneSound,eax
        invoke GetProcAddress,g_hPianoDll,offset g_szfun_Create
        mov g_pnfun_Create,eax
        ;=============

        invoke GetModuleHandle, NULL
        mov    hInstance,eax

        invoke GetCommandLine
        mov    CommandLine,eax

        invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
        invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
        LOCAL wc:WNDCLASSEX
        LOCAL msg:MSG
        LOCAL hwnd:HWND

        mov   wc.cbSize,SIZEOF WNDCLASSEX
        mov   wc.style, CS_HREDRAW or CS_VREDRAW
        mov   wc.lpfnWndProc, OFFSET WndProc
        mov   wc.cbClsExtra,NULL
        mov   wc.cbWndExtra,NULL
        pushhInstance
        pop   wc.hInstance
        mov   wc.hbrBackground,COLOR_BTNFACE+1
        mov   wc.lpszMenuName,NULL
        mov   wc.lpszClassName,OFFSET ClassName

        invoke LoadIcon,NULL,IDI_APPLICATION
        mov   wc.hIcon,eax
        mov   wc.hIconSm,eax

        invoke LoadCursor,NULL,IDC_ARROW
        mov   wc.hCursor,eax

        invoke RegisterClassEx, addr wc
        INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
         WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
         CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
         hInst,NULL
        mov   hwnd,eax

        invoke ShowWindow, hwnd,SW_SHOWNORMAL
        invoke UpdateWindow, hwnd

        .WHILE TRUE
                invoke GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                invoke TranslateMessage, ADDR msg
                invoke DispatchMessage, ADDR msg
        .ENDW

        mov   eax,msg.wParam
        ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

        .IF uMsg==WM_DESTROY
                invoke PostQuitMessage,NULL
        .ELSEIF uMsg==WM_CREATE
                push hWnd
                call g_pnfun_Create
                add esp,4
        .elseif uMsg==WM_KEYDOWN
                ;=============
                push wParam
                call g_pfnPlayOneSound
                add esp,4
                ;=============
        .ELSE
                invoke DefWindowProc,hWnd,uMsg,wParam,lParam       
                ret
        .ENDIF

        xor eax,eax
        ret
WndProc endp


end start

```

- 接下来探究这个钢琴如何触发使用曲子,即那些文本文件所记录的曲子

去od找读文件相关操作

右键反汇编窗口,选择字符串查找,该软件需要用unicode查找才可

!(./notesimg/1634231302465-21b446a6-c74a-4964-9df6-8530122ab866.png)

下面这个玩意非常可疑

!(./notesimg/1634231665694-01d716d4-f7cf-459d-b229-db3280af1fdd.png)

选中回车到对应位置

!(./notesimg/1634231696899-a7204587-edb1-4ee2-a177-8d1643693214.png)

##### 插入od功介绍:选中 call 一行右击转到

可以看到调用这个函数的地方

!(./notesimg/1634232079732-1f8485ec-4a48-4e35-b1dd-9831e2233215.png)

- !(./notesimg/1634232037585-e37521f2-82c6-4e59-ab4e-e57658729e81.png)

**思路回到打开文件对应函数上**

!(./notesimg/1634232188884-614e5243-dfe2-4a0f-bbfa-39b713dc643a.png)

点击其中一个转到对应调用处

!(./notesimg/1634232251487-6bd0cfb6-90e9-49af-ba7f-592e499031f4.png)

再起上面那个push再来转到

!(./notesimg/1634232415629-d0f47d3f-f7c8-4b70-a20d-dbcf27773f97.png)

转到的是下面这个jmp,然后再看sub又是哪里跳过来的呢?

!(./notesimg/1634232502244-58609845-d74d-4f54-bc74-915131cdd2fd.png)转到下面所示的jg 另外一个mov ecx,dword ptr 是commad消息!!!!(./notesimg/1634232685558-48c27e6d-dc3a-47a9-9762-93ff38447a72.png)

我们猜测这里应该有拿资源id的操作

利用vs:文件->打开->文件

!(./notesimg/1634233045775-58c5b844-e84c-47db-bc60-38e092904c83.png)

选择该exe

!(./notesimg/1653712576278-c4ba7620-094b-4a6f-ac7c-eea9180a8652.png)

情况如下

!(./notesimg/1634233205966-7acf574f-5705-460c-b3b8-27a12311503e.png)

点开快捷键查看

!(./notesimg/1634233241602-cfda41a3-a462-4812-8e65-1fa1cd6c47c1.png)

32772->对应上面我们怀疑是拿资源id那个立即数的8004h,十分巧合?

再去回想之前的转到那

!(./notesimg/1634233429944-e9cc7607-b541-4263-be89-b1f2e8741d4b.png)

去8004h对应要走的地方去下断点,ctrl+K测试

!(./notesimg/1634233615052-ee7e7986-b313-4b25-b7ac-23d429430d60.png)

断点果然下来了

但是并没有播放音乐,我们通过断点处往下走观察发现仅仅只是读了数据而已。

我们可以看它把读的东西放到哪里去了。

再去看文件读写那

!(./notesimg/1634234198435-95520e3f-bceb-42cc-912b-c3ad55c21f88.png)

有用到了全局变量,往它那些如东西,如果别的地方要用到,肯定也要访问全局变量。

##### 如何看那些地方用到了对应的全局变量?选中,右键->查找参考->地址参考

!(./notesimg/1634234430734-f37e32ab-2cbe-4df6-aa38-22ad9a00c56c.png)

那么只要用到了该全局变量的地方都列举出来了

!(./notesimg/1634234463139-2288fd52-f1f4-4884-8e85-0303a587ab31.png)

我们一个个找对应的读操作里面的情况,找到此处有循环,值得注意一下了!!!

!(./notesimg/1634234546076-ccf6bdc0-4308-41b3-bcae-4988d303fce3.png)

看看它从哪里来的

!(./notesimg/1634234636827-c4f1075f-e6e7-47cb-90ac-ab0210048d21.png)

!(./notesimg/1634234646521-ba8d09a6-3e87-42fb-aa75-eedcfba70880.png)

!(./notesimg/1634234670403-e5f28bc5-7cf9-4029-b07c-4181ffc4be11.png)

转到这个jnz,发现还是KeyDown消息触发。又有一个全局变量,去看看它

!(./notesimg/1634235211888-4368c848-238e-4924-930f-1acb0f931871.png)

!(./notesimg/1634234862075-678840fa-be98-472a-8c7f-8c29f864d907.png)

只有一个1,那么就进去看看

!(./notesimg/1634235341375-fa8aee14-5d0d-405c-a21c-46a53e50d727.png)

来自于8003,32771h ctrl+j

总结:

- crtl+num读文件
- ctrl+j   开启         在右上角画一个点
- ctrl+k   关闭         取消右上角画的点
- 按任意键即可播放文件曲子

```
.586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   
   includelib user32.lib
   includelib kernel32.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD


.data
   ClassName   db "MainWinClass",0
   AppName       db "Main Window",0
   g_szDll       db "piano_dll.dll",0      ;要加载的 dll
   g_szPlay      db "fun_playOneSound",0   ;要加在的dll中函数(播放音乐)
   g_szCreate    db "fun_Create", 0          ;要加在的dll中函数(初始化)
   g_pfnCreate   dd 0                        ;函数地址
   g_pfnPlay   dd 0                        ;函数地址

.data?
   hInstance HINSTANCE ?                     ;
   CommandLine LPSTR   ?                     ;

.code


; ---------------------------------------------------------------------------


start:
        invoke GetModuleHandle, NULL
        mov    hInstance,eax

        invoke GetCommandLine
        mov    CommandLine,eax

        invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
        invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
        LOCAL wc:WNDCLASSEX
        LOCAL msg:MSG
        LOCAL hwnd:HWND
        LOCAL hDll:HANDLE         ;dll句柄

        invoke LoadLibrary, offset g_szDll   ;动态加载dll
        mov hDll, eax                        ;保存dll句柄

        invoke GetProcAddress,eax, offset g_szPlay      ;获取函数地址
        mov g_pfnPlay, eax                              ;保存函数地址
        invoke GetProcAddress, hDll, offset g_szCreate;获取函数地址
        mov g_pfnCreate, eax                            ;保存函数地址

        mov   wc.cbSize,SIZEOF WNDCLASSEX
        mov   wc.style, CS_HREDRAW or CS_VREDRAW
        mov   wc.lpfnWndProc, OFFSET WndProc
        mov   wc.cbClsExtra,NULL
        mov   wc.cbWndExtra,NULL
        pushhInstance
        pop   wc.hInstance
        mov   wc.hbrBackground,COLOR_BTNFACE+1
        mov   wc.lpszMenuName,NULL
        mov   wc.lpszClassName,OFFSET ClassName

        invoke LoadIcon,NULL,IDI_APPLICATION
        mov   wc.hIcon,eax
        mov   wc.hIconSm,eax

        invoke LoadCursor,NULL,IDC_ARROW
        mov   wc.hCursor,eax

        invoke RegisterClassEx, addr wc
        INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
         WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
         CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
         hInst,NULL
        mov   hwnd,eax

        invoke ShowWindow, hwnd,SW_SHOWNORMAL
        invoke UpdateWindow, hwnd

        .WHILE TRUE
                invoke GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                invoke TranslateMessage, ADDR msg
                invoke DispatchMessage, ADDR msg
        .ENDW

        mov   eax,msg.wParam
        ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

        .IF uMsg==WM_DESTROY
                invoke PostQuitMessage,NULL
        .ELSEIF uMsg==WM_CREATE
          push hWnd          ;窗口句柄入栈
          call g_pfnCreate   ;调用播放初始化函数 (c调用约定)
          add esp, 4         ;自己平栈
    .elseif uMsg == WM_KEYDOWN
      push wParam      ;按下的字符入栈
      call g_pfnPlay   ;调用播放音乐函数 (c调用约定)
      add esp, 4         ;自己平栈
        .ELSE
                invoke DefWindowProc,hWnd,uMsg,wParam,lParam       
                ret
        .ENDIF

        xor eax,eax
        ret
WndProc endp


end start

```

筛选器异常

操作系统有个机制,他会把异常通告给我们应用程序,让我们应用程序来处理,异常机制windows 系统提供了3种,筛选器异常,SEH 结构化异常,veh 向量异常

筛选器异常是一种最终的异常处理方式,当异常发生时,我们可以在程序启动时,我们可以给程序注册一个异常回调函数当异常发生时,系统就会调这个异常函数,让我们有一次处理的机会.

如果我们要处理筛选器异常哦们需要自己写一个处理的函数,然后把这个函数注册到给操作系统,这样操作系统就知道你要处理筛选器,如果没有注册,那么系统默认不处理筛选器异常

异常派发流程

处于调试状态的派发流程

```
异常出现时,系统首先给 调试器,调试器不处理的话给 应用程序,,应用程序给 SEH, SEH不处理,会再给调试器,调试器不处理优惠给应用程序,应用程序此时会给筛选器,筛选器也不处理就直接给操作系统了,操作系统此时必须处理,操作系统处理方式就是关闭程序 ,
```


处于非调试状态的派发流程

```
异常出现时,系统首先给SEH, SEH不处理,就会给筛选器,筛选器也不处理就直接给操作系统了,操作系统此时必须处理,操作系统处理方式就是关闭程序
```


筛选器是最后一次应用程序处理异常的机会,因此被称为最终异常

注册筛选器    SetUnhandledExceptionFilter

LPTOP LEVEL EXCEPTION FILTER SETUNHANDLEDEXCEPTIONFILTER(

LPTOPLEVELEXCEPTIONFILTER

LPTOP LEVEL EXCEPTION FILTER

!(./notesimg/1653667530196-f13436e9-c5f0-4c4e-ba39-2ea5d6a9ad0d.png)

参数 :   函数指针: 自己注册的函数函数指针          返回值   函数指针: 之前注册的函数指针

声明

LONGSetUnhandledExceptionFilter(   STRUCT _EXCEPTION_POINTERS *ExceptionInfo);

结构体 EXCEPTION_POINTERS

!(./notesimg/1653669614333-deda749c-6ebf-4997-b703-0843c3d0fb80.png)

第一个成员:      异常记录 (异常信息)

第二个成员:      环境记录(寄存器环境)

异常记录: EXCEPTION_RECORD

!(https://cdn.nlark.com/yuque/0/2022/png/27242010/1653669870032-24535da5-e400-4b61-89d0-b20041127b85.png)

成员:      异常码 (异常种类)

```
标志(不用管)
```


```
异常嵌套 (处理异常过程中出现了异常)
```


```
异常产生的地址 (EIP)
```


```
产生异常的: 参数数量
```


```
异常发生时的操作, 0 是 读1是写 ,第二个是访问异常的地址(意思是你读或写哪个地址时发生了异常)
```


```
.586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   
   includelib user32.lib
   includelib kernel32.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD


.data
   g_szTitle db "提示",0
   g_szTextdb "异常来了",0

.data?
   hInstance HINSTANCE ?
   CommandLine LPSTR ?

.code


;异常回调函数   参数:结构体指针
MyUnhandledExceptionFilter proc pExceptPointer:ptr EXCEPTION_POINTERS

    invoke MessageBox, NULL, offset g_szText, offset g_szTitle, MB_OK


    ;--------搭配EXCEPTION_CONTINUE_EXECUTION,不然无法退出程序---------------
    ;---继续执行,即从56行继续执行,又报异常继续回到56行异常处,导致死循环,因此需要跳过56行代码   
   
    mov esi, pExceptPointer            ;获取出现异常的地址
    assume esi:ptr EXCEPTION_POINTERS    ;地址类型类型强转
    mov esi, .ContextRecord;获取出现异常环境记录
    assume esi:ptr CONTEXT      ;地址类型类型强转
    add .regEip, 2         ;跳过出现异常的代码,异常代码地址+2
    assume esi:nothing            ;还原类型
    ;-----------------------------

    ;mov eax, EXCEPTION_EXECUTE_HANDLER;    - 异常已处理,结束进程

    ;mov eax, EXCEPTION_CONTINUE_EXECUTION; -异常已经处理,可以继续执行代码

    mov eax, EXCEPTION_CONTINUE_SEARCH;   - 异常我不处理,交给系统处理,跟第一种区别不大
   
   ret
MyUnhandledExceptionFilter endp

start:
    ;注册异常回调函数
    invoke SetUnhandledExceptionFilter,offset MyUnhandledExceptionFilter

    mov eax, 1212h
    mov , eax    ;因为1212属于不可访问地址,因此会出现异常

    invoke MessageBox, NULL, offset g_szText, offset g_szTitle, MB_OK
        invoke ExitProcess,0
end start
```

!(./notesimg/1653712536319-4b2103c7-eb0e-4b44-af28-e30dd67a549d.jpeg)

### 作业

##### 1. 带作弊功能的钢琴

大键盘1是开启

大键盘2是关闭

大键盘3是读取文件

先读取文件然后再开启。

```
.586
.model flat,stdcall
option casemap:none

include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
include msvcrt.inc
include shlwapi.inc

includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib
includelib msvcrt.lib
includelib shlwapi.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD


.data
   ClassName db "MainWinClass",0
   AppNamedb "Main Window",0
   g_szDll db "piano_dll.dll",0
   g_szPlay db "fun_playOneSound",0
   g_szCreate db "fun_Create", 0
   g_pfnCreate dd 0
   g_pfnPlay dd 0
   g_TestCut dd 0
   g_TestOpenWindb "打开成功", 0
   g_TestCloseWindb "关闭成功", 0
   
   g_TestFmt db"1.txt",0
   g_wFileCode      dd0
   g_szFileMode       db"r", 0
   g_FileTest         db 255 dup(0),0
   g_TestChar db 0
   
   g_TestBufdb 0
   g_TestFlagdb 0
   
.data?
   hInstance HINSTANCE ?
   CommandLine LPSTR ?

.code



start:
        invoke GetModuleHandle, NULL
        mov    hInstance,eax

        invoke GetCommandLine
        mov    CommandLine,eax

        invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
        invoke ExitProcess,eax

WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:DWORD
        LOCAL wc:WNDCLASSEX
        LOCAL msg:MSG
        LOCAL hwnd:HWND
        LOCAL hDll:HANDLE

        invoke LoadLibrary, offset g_szDll
        mov hDll, eax

        invoke GetProcAddress,eax, offset g_szPlay
        mov g_pfnPlay, eax
        invoke GetProcAddress, hDll, offset g_szCreate
        mov g_pfnCreate, eax

        mov   wc.cbSize,SIZEOF WNDCLASSEX
        mov   wc.style, CS_HREDRAW or CS_VREDRAW
        mov   wc.lpfnWndProc, OFFSET WndProc
        mov   wc.cbClsExtra,NULL
        mov   wc.cbWndExtra,NULL
        pushhInstance
        pop   wc.hInstance
        mov   wc.hbrBackground,COLOR_BTNFACE+1
        mov   wc.lpszMenuName,NULL
        mov   wc.lpszClassName,OFFSET ClassName

        invoke LoadIcon,NULL,IDI_APPLICATION
        mov   wc.hIcon,eax
        mov   wc.hIconSm,eax

        invoke LoadCursor,NULL,IDC_ARROW
        mov   wc.hCursor,eax

        invoke RegisterClassEx, addr wc
        INVOKE CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
         WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
         CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
         hInst,NULL
        mov   hwnd,eax

        invoke ShowWindow, hwnd,SW_SHOWNORMAL
        invoke UpdateWindow, hwnd

        .WHILE TRUE
                invoke GetMessage, ADDR msg,NULL,0,0
                .BREAK .IF (!eax)
                invoke TranslateMessage, ADDR msg
                invoke DispatchMessage, ADDR msg
        .ENDW

        mov   eax,msg.wParam
        ret
WinMain endp

WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM

        .IF uMsg==WM_DESTROY
                invoke PostQuitMessage,NULL
       
        .ELSEIF uMsg==WM_CREATE

          push hWnd
          call g_pfnCreate
          add esp, 4
      .elseif uMsg == WM_KEYDOWN
                        
                lea eax,g_TestFlag
            
                .if word ptr == 0
                        .if wParam =="1"
                     
                           invoke MessageBox,NULL,NULL,offset g_TestOpenWin,MB_OK
                           lea eax,g_TestFlag
                           mov word ptr,1
      
                        .elseif wParam == "2"
                     
                           invoke MessageBox,NULL,NULL,offset g_TestCloseWin,MB_OK
                           
                           
                           lea eax,g_TestFlag
                           mov word ptr,0
                           .elseif wParam == "3"
                     
                           ;载入文件
                           
                           ;打开文件
                           invoke crt_fopen,offset g_TestFmt,offset g_szFileMode
                           mov g_wFileCode,eax
                           ;读文件
                           invoke crt_fgets,offset g_FileTest,255, g_wFileCode
                           
                        .else   
                        
                     
                        
                              push wParam
                              call g_pfnPlay
                              add esp, 4
                        
                        
                           .endif
                        
                .else
                     
                     .if wParam != "2"
                      lea ebx,g_FileTest
                      mov wParam, ebx

                  
                  
                      push wParam
                      call g_pfnPlay
                      add esp, 4
                  
                      .else
                           invoke MessageBox,NULL,NULL,offset g_TestCloseWin,MB_OK
                           lea eax,g_TestFlag
                           mov word ptr,0
                           
                      .endif
                  
                .endif

                  
                  
                  
                     
                           
            
        .ELSE
                invoke DefWindowProc,hWnd,uMsg,wParam,lParam       
                ret
        .ENDIF

        xor eax,eax
        ret
WndProc endp


end start
```

2. 在筛选器异常处理中dump程序MiniDumpWriteDump

```
.586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   
   include minidump.inc
   
   includelib user32.lib
   includelib kernel32.lib

   includelib dbghelp_x86.lib

WinMain proto :DWORD,:DWORD,:DWORD,:DWORD


.data
   g_szTitle db "提示",0
   g_szTextdb "异常来了",0
   
   g_szFiledb "info.dump",0

.data?
   hInstance HINSTANCE ?
   CommandLine LPSTR ?

.code



MyUnhandledExceptionFilter proc pExceptPointer:ptr EXCEPTION_POINTERS
    local @hFile:DWORD
    local @hProcess:DWORD
    local @dwProcessId:DWORD


    ;local @bClientPointers:DWORD
    local @pExceptionPointers:DWORD
    local @dwThreadId:DWORD
    mov eax,pExceptPointer
    mov @pExceptionPointers, eax
    ;mov @bClientPointers, 0
    ; 创建文件

    invokeCreateFile,offset g_szFile,GENERIC_READ or GENERIC_WRITE,FILE_SHARE_READ,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL
   
    mov @hFile, eax

    invoke GetCurrentProcess
    mov @hProcess, eax
    invoke GetCurrentProcessId
    mov @dwProcessId, eax
    invoke GetCurrentThreadId
    mov @dwThreadId, eax

    invoke MiniDumpWriteDump, @hProcess, @dwProcessId, @hFile, 0, addr @dwThreadId, NULL, NULL
      
    ;--------搭配EXCEPTION_CONTINUE_EXECUTION,不然无法退出程序---------------
    ;---继续执行,即从56行继续执行,又报异常继续回到56行异常处,导致死循环,因此需要跳过56行代码   
   
    ;mov esi, pExceptPointer            ;获取出现异常的地址
    ;assume esi:ptr EXCEPTION_POINTERS    ;地址类型类型强转
    ;mov esi, .ContextRecord;获取出现异常环境记录
    ;assume esi:ptr CONTEXT      ;地址类型类型强转
    ;add .regEip, 2         ;跳过出现异常的代码,异常代码地址+2
    ;assume esi:nothing            ;还原类型
    ;-----------------------------

    mov eax, EXCEPTION_EXECUTE_HANDLER;    - 异常已处理,结束进程

    ;mov eax, EXCEPTION_CONTINUE_EXECUTION; -异常已经处理,可以继续执行代码
    ;mov eax, EXCEPTION_CONTINUE_SEARCH;   - 异常我不处理,交给系统处理,跟第一种区别不大

    ret
MyUnhandledExceptionFilter endp

start:
    ;注册异常回调函数
    invoke SetUnhandledExceptionFilter,offset MyUnhandledExceptionFilter

    mov eax, 1212h
    mov , eax

    invoke MessageBox, NULL, offset g_szText, offset g_szTitle, MB_OK
    invoke ExitProcess,0
end start
```

```
.586
.model flat,stdcall
option casemap:none

   include windows.inc
   include user32.inc
   include kernel32.inc
   include msvcrt.inc
   
   includelib user32.lib
   includelib kernel32.lib
   includelib msvcrt.lib


WinMain proto :DWORD,:DWORD,:DWORD,:DWORD


.data
   g_szTitle db "提示",0
   g_szTextdb "异常来了",0
   g_szExe db "TestUnh.exe", 0
   g_szDmp db "TestUnh.dmp", 0
   
   g_szDll db "Dbghelp.dll",0
   g_szDump db "MiniDumpWriteDump",0
   g_pfnDump dd 0
   
.data?
   hInstance HINSTANCE ?
   CommandLine LPSTR ?

.code



MyUnhandledExceptionFilter proc pExceptPointer:ptr EXCEPTION_POINTERS
    LOCAL hsnap:HANDLE
    LOCAL pe32:PROCESSENTRY32
    LOCAL pid:DWORD
    LOCAL TestHandle:HANDLE
    LOCAL outFile:HANDLE

    invoke CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS, 0
    mov hsnap, eax
    mov pe32.dwSize, size pe32
    invoke Process32First, hsnap, addr pe32
    invoke crt_strcmp, addr pe32.szExeFile, offset g_szExe
    .while eax != 0
      invoke Process32Next, hsnap, addr pe32
      mov eax, pe32.th32ProcessID
      mov pid, eax
      invoke crt_strcmp, addr pe32.szExeFile, offset g_szExe
    .endw

    invoke OpenProcess, PROCESS_ALL_ACCESS, 0, pid
    mov TestHandle, eax
    invoke CreateFile, offset g_szDmp, GENERIC_ALL, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL
    mov outFile, eax
    xor ebx, ebx
    mov ebx, 2

    push NULL
    push NULL
    push NULL
    push ebx
    push outFile
    push pid
    push TestHandle
    call g_pfnDump

    mov eax, EXCEPTION_EXECUTE_HANDLER; - 异常已处理,结束进程
    ;mov eax, EXCEPTION_CONTINUE_EXECUTION;-异常已经处理,可以继续执行代码
    ;mov eax, EXCEPTION_CONTINUE_SEARCH; - 异常我不处理,交给系统处理
    ret
MyUnhandledExceptionFilter endp

start:
    ;注册异常回调函数
    invoke SetUnhandledExceptionFilter,offset MyUnhandledExceptionFilter

    ;获取dump函数地址
    invoke LoadLibrary, offset g_szDll

        invoke GetProcAddress,eax, offset g_szDump
        mov g_pfnDump, eax


    mov eax, 1212h
    mov , eax

    invoke MessageBox, NULL, offset g_szText, offset g_szTitle, MB_OK
        invoke ExitProcess,0
end start

```
页: [1]
查看完整版本: Win32汇编学习笔记07.筛选器异常