![]() |
#2
sll08072009-11-02 01:54
|

只有本站会员才能查看附件,请 登录
只有本站会员才能查看附件,请 登录
;**************************************************************************
;主要是查看导入函数练习
;by:onepc/153785587
;主要参考Iczelion与罗云彬的PE教程
;映射内存文件,把文件映射到内存中与PE加载器加载文件不同,前者的文件排列与在磁盘中是一样的[可以认为是按文件对齐]
;后者是按节对齐的方式排列在内存中,这就是要把RVA转换为对文件偏移的目的
;**************************************************************************
.386
.model flat,stdcall
option casemap:none
;**************************************************************************
include windows.inc
include user32.inc
includelib user32.lib
include kernel32.inc
includelib kernel32.lib
include comdlg32.inc
includelib comdlg32.lib
include comctl32.inc
includelib comctl32.lib
;**************************************************************************
IDD_PEINFO_DIALOG equ 102
IDR_MAINFRAME equ 128
IDD_DIALOG1 equ 129
IDR_MENU1 equ 130
IDD_DIALOG2 equ 131
IDC_BUTTON1 equ 1000
IDC_LIST1 equ 1001
IDC_LIST2 equ 1002
IDC_BUTTON2 equ 1003
IDC_EDIT1 equ 1004
IDC_EDIT2 equ 1005
IDC_EDIT3 equ 1006
IDC_EDIT4 equ 1007
IDC_EDIT5 equ 1008
IDC_EDIT6 equ 1009
IDC_EDIT7 equ 1010
IDC_EDIT8 equ 1011
ID_MENUITEM32771 equ 32771
ID_MENUITEM32772 equ 32772
;**************************************************************************
.data
szMsgTitle db 'ERROR',0
szMsgTxt db 'Open File ERROR',0
szMsgPeTxt db 'Not PE File',0
szCaption db 'PE格式练习程序 - 153785587',0
szFilter db 'Text Files(*.exe)',0,'*.exe',0,'Dll Files(*.dll)',0,'*.dll',0,0
szSetion db 'Section',0
szVadress db 'Vaddress',0
szVsize db 'Vsize',0
szRsize db 'Rsize',0
szRoffset db 'Roffset',0
szCharact db 'Charact',0
szDllName db 'DLLNAME',0
szDllNameAddr db 'DllNameAddr',0
szOriginalFirstThunk db 'OriginalThunk',0
szFirstThunk db 'FirstThunk',0
szHint db 'Hint',0
szFunctionName db 'FunctionName',0
szFmatTxt db '%08X',0
szFmatName db '%s',0
.data?
hInstance dd ? ;模块句柄
hDlgMain dd ? ;主对话框句柄
hMenu dd ? ;菜单句柄
hFile dd ? ;CreateFile
hFileMap dd ? ;CreateFileMapping
lpMemory dd ? ;MapViewOfFile ====>IMAGE_DOS_HEADER
lpNtHeader dd ? ;IMAGE_NT_HEADERS
lpImportFstruct dd ? ;第一个IMAGE_IMPORT_DESCRIPTOR地址
szPathName db MAX_PATH dup (?) ;文件路径缓冲区
szTemBuffer db MAX_PATH dup (?) ;临时缓冲区
szTemBuf db MAX_PATH dup (?) ;
;**************************************************************************
.code
;**************************************************************************
;**************************************************************************
_RvaToOffset proc uses edi _RvaAddr:DWORD
local @dwSetionNum
;注:映射内存文件,把文件映射到内存中与PE加载器加载文件不同,前者的文件排列与在磁盘中是一样的[可以认为是按文件对齐]
; 后者是按节对齐的方式排列在内存中,这就是要把RVA转换为对文件偏移的目的。
mov edi,lpNtHeader ;***********
assume edi:ptr IMAGE_NT_HEADERS
movzx eax,[edi].FileHeader.NumberOfSections
mov @dwSetionNum,eax
add edi,sizeof IMAGE_NT_HEADERS
assume edi:ptr IMAGE_SECTION_HEADER
mov edx,_RvaAddr
.while @dwSetionNum>0
mov eax,[edi].VirtualAddress
add eax,[edi].SizeOfRawData
.if (edx>=[edi].VirtualAddress) && (edx<eax)
mov ebx,[edi].VirtualAddress
sub edx,ebx
mov eax,[edi].PointerToRawData ;节头的文件偏移
add eax,edx ;节头的文件偏移+对节头的偏移 即已把RVA转换成了文件偏移
jmp @F
.endif
dec @dwSetionNum
add edi,sizeof IMAGE_SECTION_HEADER ;指向下一个节头
.endw
@@:assume edi:nothing
ret
_RvaToOffset endp
;**************************************************************************
_CheckPeInfo proc uses esi _lpHeader:DWORD
mov esi,_lpHeader
assume esi:ptr IMAGE_DOS_HEADER
.if [esi].e_magic==IMAGE_DOS_SIGNATURE
add esi,[esi].e_lfanew
assume esi:ptr IMAGE_NT_HEADERS
.if [esi].Signature==IMAGE_NT_SIGNATURE
mov lpNtHeader,esi ;******************
;***************************************************
movzx eax,[esi].FileHeader.NumberOfSections
invoke SetDlgItemInt,hDlgMain,IDC_EDIT6,eax,FALSE
mov eax,[esi].OptionalHeader.ImageBase
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax
invoke SetDlgItemText,hDlgMain,IDC_EDIT1,addr szTemBuffer
mov eax,[esi].OptionalHeader.AddressOfEntryPoint
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax
invoke SetDlgItemText,hDlgMain,IDC_EDIT3,addr szTemBuffer
mov eax,[esi].OptionalHeader.FileAlignment
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax
invoke SetDlgItemText,hDlgMain,IDC_EDIT4,addr szTemBuffer
mov eax,[esi].OptionalHeader.SectionAlignment
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax
invoke SetDlgItemText,hDlgMain,IDC_EDIT2,addr szTemBuffer
mov eax,[esi].OptionalHeader.SizeOfImage
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax
invoke SetDlgItemText,hDlgMain,IDC_EDIT7,addr szTemBuffer
mov eax,[esi].OptionalHeader.BaseOfCode
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax
invoke SetDlgItemText,hDlgMain,IDC_EDIT8,addr szTemBuffer
mov eax,[esi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY].VirtualAddress
;这里的DataDirectory[加一个数据结构的大小]表示落在第二项,即序号*结构大小 [0开始]
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax
invoke SetDlgItemText,hDlgMain,IDC_EDIT5,addr szTemBuffer
;***************************************************
.else
invoke MessageBox,NULL,addr szMsgPeTxt,addr szMsgTitle,MB_OK
.endif
.else
invoke MessageBox,NULL,addr szMsgPeTxt,addr szMsgTitle,MB_OK
.endif
assume esi:nothing
ret
_CheckPeInfo endp
;**************************************************************************
_MapFile proc
invoke CreateFile,addr szPathName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL
.if eax!=INVALID_HANDLE_VALUE
mov hFile,eax
invoke CreateFileMapping,hFile,NULL,PAGE_READONLY,0,0,0
.if eax
mov hFileMap,eax
invoke MapViewOfFile,hFileMap,FILE_MAP_READ,0,0,0
.if eax
mov lpMemory,eax
invoke _CheckPeInfo,lpMemory ;**********
;****************************************
invoke GetDlgItem,hDlgMain,IDC_BUTTON1
invoke EnableWindow,eax,TRUE
invoke GetDlgItem,hDlgMain,IDC_BUTTON2
invoke EnableWindow,eax,TRUE
;****************************************
.else
invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK
invoke CloseHandle,hFileMap
invoke CloseHandle,hFile
.endif
.else
invoke CloseHandle,hFile
invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK
.endif
.else
invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK
.endif
ret
_MapFile endp
;**************************************************************************
_OpenFile proc
local @stFile:OPENFILENAME
invoke RtlZeroMemory,addr @stFile,sizeof @stFile
mov @stFile.lStructSize,sizeof @stFile
push hDlgMain
pop @stFile.hwndOwner
mov @stFile.lpstrFilter,offset szFilter
mov @stFile.lpstrFile,offset szPathName
mov @stFile.nMaxFile,MAX_PATH
mov @stFile.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST
invoke GetOpenFileName,addr @stFile
.if eax ;getopenfilename打开成功的话返回非0值
invoke _MapFile ;*****************************
.endif
ret
_OpenFile endp
;**************************************************************************
;**************************************************************************
_SecDlgProc proc uses esi edi ebx hDlg,uMsg,wParam,lParam
local @stLumm1:LV_COLUMN
local @stLtiem1:LV_ITEM
local @dwSetionNum
.if uMsg==WM_INITDIALOG
mov @stLumm1.imask,LVCF_FMT or LVCF_TEXT or LVCF_WIDTH or LVCF_SUBITEM
mov @stLumm1.fmt,LVCFMT_CENTER
mov @stLumm1.lx,85
mov @stLumm1.iSubItem,0
mov @stLumm1.pszText,offset szSetion
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,0,addr @stLumm1
inc @stLumm1.iSubItem
mov @stLumm1.fmt,LVCFMT_CENTER
mov @stLumm1.pszText,offset szVadress
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,1,addr @stLumm1
inc @stLumm1.iSubItem
mov @stLumm1.fmt,LVCFMT_CENTER
mov @stLumm1.pszText,offset szVsize
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,2,addr @stLumm1
inc @stLumm1.iSubItem
mov @stLumm1.fmt,LVCFMT_CENTER
mov @stLumm1.pszText,offset szRsize
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,3,addr @stLumm1
inc @stLumm1.iSubItem
mov @stLumm1.fmt,LVCFMT_CENTER
mov @stLumm1.pszText,offset szRoffset
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,4,addr @stLumm1
inc @stLumm1.iSubItem
mov @stLumm1.fmt,LVCFMT_CENTER
mov @stLumm1.pszText,offset szCharact
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,5,addr @stLumm1
mov esi,lpNtHeader
assume esi:ptr IMAGE_NT_HEADERS
movzx eax,[esi].FileHeader.NumberOfSections
mov @dwSetionNum,eax
add esi,sizeof IMAGE_NT_HEADERS
assume esi:ptr IMAGE_SECTION_HEADER ;指向节头
mov @stLtiem1.imask,LVIF_TEXT
mov @stLtiem1.iItem,0
.while @dwSetionNum>0
mov @stLtiem1.iSubItem,0
invoke RtlZeroMemory,addr szTemBuffer,sizeof szTemBuffer
invoke lstrcpyn,addr szTemBuffer,addr [esi].Name1,8
mov @stLtiem1.pszText,offset szTemBuffer
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTITEM,0,addr @stLtiem1
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].VirtualAddress
mov @stLtiem1.pszText,offset szTemBuffer
inc @stLtiem1.iSubItem
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem1
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].Misc.VirtualSize
mov @stLtiem1.pszText,offset szTemBuffer
inc @stLtiem1.iSubItem
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem1
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].SizeOfRawData
mov @stLtiem1.pszText,offset szTemBuffer
inc @stLtiem1.iSubItem
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem1
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].PointerToRawData
mov @stLtiem1.pszText,offset szTemBuffer
inc @stLtiem1.iSubItem
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem1
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].Characteristics
mov @stLtiem1.pszText,offset szTemBuffer
inc @stLtiem1.iSubItem
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem1
dec @dwSetionNum
inc @stLtiem1.iItem
add esi, sizeof IMAGE_SECTION_HEADER ;下一个节头
.endw
.elseif uMsg==WM_COMMAND
mov eax,wParam
.elseif uMsg==WM_CLOSE
invoke EndDialog,hDlg,FALSE
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_SecDlgProc endp
;**************************************************************************
;**************************************************************************
_ThrDlgProc proc uses esi edi ebx hDlg,uMsg,wParam,lParam
local @stLumm:LV_COLUMN,@stLumm1:LV_COLUMN
local @stLtiem:LV_ITEM,@stLtiem1:LV_ITEM
.if uMsg==WM_INITDIALOG
;*********************
mov @stLumm.imask,LVCF_FMT or LVCF_TEXT or LVCF_WIDTH or LVCF_SUBITEM
mov @stLumm.fmt,LVCFMT_CENTER
mov @stLumm.lx,115
mov @stLumm.iSubItem,0
mov @stLumm.pszText,offset szDllName
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,0,addr @stLumm
inc @stLumm.iSubItem
mov @stLumm.pszText,offset szDllNameAddr
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,1,addr @stLumm
inc @stLumm.iSubItem
mov @stLumm.pszText,offset szOriginalFirstThunk
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,2,addr @stLumm
inc @stLumm.iSubItem
mov @stLumm.pszText,offset szFirstThunk
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTCOLUMN,3,addr @stLumm
;行
mov @stLtiem.imask,LVIF_TEXT
mov @stLtiem.iItem,0
;******************************************
mov esi,lpNtHeader
assume esi:ptr IMAGE_NT_HEADERS
mov ebx,[esi].OptionalHeader.DataDirectory[sizeof IMAGE_DATA_DIRECTORY].VirtualAddress ;导入表RVA
invoke _RvaToOffset,ebx ;把RVA转为文件偏移,返回的eax的值就是文件偏移
add eax,lpMemory ;eax是导入表的文件偏移,所以加上lpMemory,那么现在eax就是指向导入表
mov esi,eax
mov lpImportFstruct,esi
assume esi:ptr IMAGE_IMPORT_DESCRIPTOR ;IMAGE_IMPORT_DESCRIPTOR最后一个是全0的结构
;***
.while [esi].OriginalFirstThunk || [esi].TimeDateStamp || [esi].ForwarderChain || [esi].FirstThunk || [esi].Name1
invoke _RvaToOffset,[esi].Name1 ;这个是一个RVA指向一个以0结尾的字符串
add eax,lpMemory
invoke wsprintf,addr szTemBuffer,addr szFmatName,eax
;********
mov @stLtiem.iSubItem,0
mov @stLtiem.pszText,offset szTemBuffer
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_INSERTITEM,0,addr @stLtiem
inc @stLtiem.iSubItem
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].Name1
mov @stLtiem.pszText,offset szTemBuffer
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem
inc @stLtiem.iSubItem
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].OriginalFirstThunk
mov @stLtiem.pszText,offset szTemBuffer
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem
inc @stLtiem.iSubItem
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,[esi].FirstThunk
mov @stLtiem.pszText,offset szTemBuffer
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_SETITEM,0,addr @stLtiem
inc @stLtiem.iItem
add esi,sizeof IMAGE_IMPORT_DESCRIPTOR
.endw ;全0时退出
;***
;******************************************
assume esi:nothing
;**********************
mov @stLumm1.imask,LVCF_FMT or LVCF_TEXT or LVCF_WIDTH or LVCF_SUBITEM
mov @stLumm1.fmt,LVCFMT_CENTER
mov @stLumm1.lx,140
mov @stLumm1.iSubItem,0
mov @stLumm1.pszText,offset szFunctionName
invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_INSERTCOLUMN,0,addr @stLumm1
inc @stLumm1.iSubItem
mov @stLumm1.pszText,offset szHint
invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_INSERTCOLUMN,1,addr @stLumm1
;**********************
.elseif uMsg==WM_NOTIFY
mov eax,lParam
assume eax:ptr NMHDR
.if ([eax].idFrom==IDC_LIST1) && ([eax].code==LVN_ITEMCHANGED)
assume eax:nothing
invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_DELETEALLITEMS,0,0 ;清空
invoke SendDlgItemMessage,hDlg,IDC_LIST1,LVM_GETNEXTITEM,-1,LVNI_SELECTED
.if eax!=-1
; invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax ;eax是对应的序号,从0开始
; invoke MessageBox,NULL,addr szTemBuffer,addr szMsgTitle,0
mov ebx,sizeof IMAGE_IMPORT_DESCRIPTOR
imul ebx ;eax*ebx
mov esi,lpImportFstruct ;这个是在内存中指向第一个IMAGE_IMPORT_DESCRIPTOR的值
add esi,eax
assume esi:ptr IMAGE_IMPORT_DESCRIPTOR
.if [esi].OriginalFirstThunk ;这个是指向IMAGE_THUNK_DATA结构数组的偏移地址
mov eax,[esi].OriginalFirstThunk ;因为有可能会把OriginalFirstThunk置0
.else
mov eax,[esi].FirstThunk;所以用这个 eax现在是RVA
.endif
assume esi:nothing
invoke _RvaToOffset,eax ;返回文件偏移
add eax,lpMemory ;内存映射文件之后这个IMAGE_THUNK_DATA结构的起始地址
mov esi,eax
; invoke wsprintf,addr szTemBuffer,addr szFmatTxt,ebx
; invoke MessageBox,NULL,addr szTemBuffer,addr szMsgTitle,0
; assume esi:nothing
; IMAGE_THUNK_DATA ;这个结构是一个双字DWORD型
mov @stLtiem1.imask,LVIF_TEXT
mov @stLtiem1.iItem,0
;**********
.while DWORD ptr [esi]!=0
;invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK
.if DWORD ptr [esi] & 80000000h ;按位相与,若高位为1则是按序号导入[双字低位是序号]
mov eax,DWORD ptr [edx]
and eax,0FFFFh
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,eax
mov @stLtiem1.iSubItem,0
mov @stLtiem1.pszText,offset szTemBuffer
invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_INSERTITEM,0,addr @stLtiem1
.else
; invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK
invoke _RvaToOffset,DWORD ptr [esi] ;高位为0时则是一个RVA
;invoke _RvaToOffset,eax
add eax,lpMemory ;指向IMAGE_IMPORT_BY_NAME结构
assume eax:ptr IMAGE_IMPORT_BY_NAME
movzx ecx,[eax].Hint
;*****
invoke wsprintf,addr szTemBuffer,addr szFmatName,addr [eax].Name1
mov @stLtiem1.iSubItem,0
mov @stLtiem1.pszText,offset szTemBuffer
invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_INSERTITEM,0,addr @stLtiem1
inc @stLtiem1.iSubItem
invoke wsprintf,addr szTemBuffer,addr szFmatTxt,ecx
mov @stLtiem1.pszText,offset szTemBuffer
invoke SendDlgItemMessage,hDlg,IDC_LIST2,LVM_SETITEM,0,addr @stLtiem1
;*****
assume eax:nothing
.endif
inc @stLtiem1.iItem
add esi,sizeof IMAGE_THUNK_DATA
; invoke MessageBox,NULL,addr szMsgTxt,addr szMsgTitle,MB_OK
.endw
;**********
;
; ;**********
.endif
.endif
.elseif uMsg==WM_COMMAND
.elseif uMsg==WM_CLOSE
invoke EndDialog,hDlg,FALSE
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ThrDlgProc endp
;**************************************************************************
;**************************************************************************
_MainDlgProc proc uses esi edi ebx hDlg,uMsg,wParam,lParam
.if uMsg==WM_INITDIALOG
push hDlg
pop hDlgMain
invoke LoadIcon,hInstance,IDR_MAINFRAME
invoke SendMessage,hDlg,WM_SETICON,ICON_BIG,eax
invoke LoadMenu,hInstance,IDR_MENU1
mov hMenu,eax
invoke SetMenu,hDlgMain,hMenu
invoke SendMessage,hDlg,WM_SETTEXT,0,addr szCaption
;
invoke GetDlgItem,hDlg,IDC_BUTTON1
invoke EnableWindow,eax,FALSE
invoke GetDlgItem,hDlg,IDC_BUTTON2
invoke EnableWindow,eax,FALSE
.elseif uMsg==WM_COMMAND
mov eax,wParam
.if ax==IDC_BUTTON1
invoke DialogBoxParam,hInstance,IDD_DIALOG2,hDlgMain,addr _SecDlgProc,NULL
.elseif ax==IDC_BUTTON2
invoke DialogBoxParam,hInstance,IDD_DIALOG1,hDlgMain,addr _ThrDlgProc,NULL
.elseif ax==ID_MENUITEM32771
call _OpenFile ;***********************
.elseif ax==ID_MENUITEM32772
invoke EndDialog,hDlg,FALSE
.endif
.elseif uMsg==WM_CLOSE
invoke CloseHandle,hFile
invoke CloseHandle,hFileMap
invoke UnmapViewOfFile,lpMemory
invoke EndDialog,hDlg,FALSE
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_MainDlgProc endp
;**************************************************************************
;**************************************************************************
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,IDD_PEINFO_DIALOG,NULL,addr _MainDlgProc,NULL
invoke ExitProcess,NULL
end start
;**************************************************************************