• WindowsPE权威指南学习过程中的代码片段


    第一个基础的HelloWorld

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    
    	.data
    szText db 'HelloWorld',0
    
    	.code
    start:
    	invoke MessageBox,NULL,offset szText,NULL,MB_OK
    	invoke ExitProcess,NULL
    end start
    

    调试观察栈的变化

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    
    	.code
    _add proc a:word,b:word
    	local @bl1:dword
    	ret
    _add endp
    start:
    	push 1
    	push 2
    	call _add
    	add eax,1
    end start
    

    第二章的几个小工具

    太长太长了,而且书中代码有一些过时的部分,所以也就跟着敲了一部分。

    pe.rc

    #include <resource.h>
    
    #define ICO_MAIN 1000
    #define DLG_MAIN 1000
    #define IDC_INFO 1001
    #define IDM_MAIN 2000
    #define IDM_OPEN 2001
    #define IDM_EXIT 2002
    
    #define IDM_1 4000
    #define IDM_2 4001
    #define IDM_3 4002
    #define IDM_4 4003
    
    ICO_MAIN ICON "saz.ico"
    
    ICO_MAIN DIALOG 50,50,544,399
    STYLE DS_MODALFRAME | WS_POPUP |WS_VISIBLE |WS_CAPTION| WS_SYSMENU
    CAPTION "JIBEN XINXI"
    MENU IDM_MAIN
    FONT 9,"宋体"
    BEGIN
    	CONTROL "",IDC_INFO,"RichEdit20A",196|ES_WANTRETURN|WS_CHILD
    		|WS_VISIBLE|WS_BORDER |WS_VSCROLL|WS_TABSTOP,0,0,540,396
    END
    
    IDM_MAIN menu discardable
    BEGIN
    	POPUP "file(&F)"
    		BEGIN
    			menuitem "openFile(&O)",IDM_OPEN
    			menuitem separator
    			menuitem "quit(&X)",IDM_EXIT
    		END
    	POPUP "LOOK"
    		BEGIN
    			menuitem "oriFile",IDM_1
    			menuitem "touming",IDM_2
    			menuitem separator
    			menuitem "size",IDM_3
    			menuitem "width",IDM_4
    		END
    END
    

    pe.asm

    	.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
    
    ICO_MAIN EQU 1000
    DLG_MAIN EQU 1000
    IDC_INFO EQU 1001
    IDM_MAIN EQU 2000
    IDM_OPEN EQU 2001
    IDM_EXIT EQU 2002
    IDM_1 EQU 4000
    IDM_2 EQU 4001
    IDM_3 EQU 4002
    
    	.data
    hInstance dd ?
    hRichEdit dd ?
    hWinMain dd ?
    hWinEdit dd ?
    szFileName db MAX_PATH dup(?)
    
    	.const
    szDllEdit db 'RichEd20.dll',0
    szClassEdit db 'RichEdit20A',0
    szFont db '宋体',0
    
    	.code
    _init proc
    	local @stCf:CHARFORMAT
    	invoke GetDlgItem,hWinMain,IDC_INFO
    	mov hWinEdit,eax
    
    	invoke LoadIcon,hInstance,ICO_MAIN
    	invoke SendMessage,hWinMain,WM_SETICON,ICON_BIG,eax
    
    	invoke SendMessage,hWinEdit,EM_SETTEXTMODE,TM_PLAINTEXT,0
    	invoke RtlZeroMemory,addr @stCf,sizeof @stCf
    	mov @stCf.cbSize,sizeof @stCf
    	mov @stCf.yHeight,9*20
    	mov @stCf.dwMask,CFM_FACE or CFM_SIZE or CFM_BOLD
    	invoke lstrcpy,addr @stCf.szFaceName,addr szFont
    	invoke SendMessage,hWinEdit,EM_SETCHARFORMAT,0,addr @stCf
    	invoke SendMessage,hWinEdit,EM_EXLIMITTEXT,0,-1
    	ret
    _init endp
    
    _ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam
    	mov eax,wMsg
    	.if eax==WM_CLOSE
    		invoke EndDialog,hWnd,NULL
    	.elseif eax==WM_INITDIALOG
    		push hWnd
    		pop hWinMain
    		call _init
    	.elseif eax == WM_COMMAND
    		mov eax,wParam
    		.if eax==IDM_EXIT
    			invoke EndDialog,hWnd,NULL
    		.elseif eax==IDM_OPEN
    		.elseif eax==IDM_1
    		.elseif eax==IDM_2
    		.elseif eax==IDM_3
    		.endif
    	.else
    		mov eax,FALSE
    		ret
    	.endif
    	mov eax,TRUE
    	ret
    _ProcDlgMain endp
    
    start:
    	invoke LoadLibrary,offset szDllEdit
    	mov hRichEdit,eax
    	invoke GetModuleHandle,NULL
    	mov hInstance,eax
    	invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
    	invoke FreeLibrary,hRichEdit
    	invoke ExitProcess,NULL
    	end start
    

    导入表值导入多个user32的函数,稍微修改了一下,按照原文禁止窗口就不好玩了。

    	.386
    	.model flat,stdcall
    	option casemap:none
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    	.data
    sz1	db	'Shell_TrayWnd',0
    hTray	dd	?
    	.code
    start:
    	invoke FindWindow,addr sz1,0
    	mov hTray,eax
    	invoke ShowWindow,hTray,SW_SHOW
    	invoke EnableWindow,hTray,TRUE
    
    	invoke ExitProcess,NULL
    end start
    

    汇编写第一个窗口,可以作为模板使用。

    	.386
    	.model flat,stdcall
    	option casemap:none
    include windows.inc
    include gdi32.inc
    includelib	gdi32.lib
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    	.data?
    hInstance	dd	?
    hWinMain	dd	?
    	.const
    szClassName	db	'MyClass',0
    szCaptionMain	db	'My First Window!',0
    szText	db	'Win32 Assembly,Simple and powerful!',0
    	.code
    _ProcWinMain proc uses ebx edi esi,hWnd,uMsg,wParam,lParam
    	local	@stPs:PAINTSTRUCT
    	local	@stRect:RECT
    	local	@hDc
    
    	mov eax,uMsg
    	.if	eax == WM_PAINT
    		invoke BeginPaint,hWnd,addr @stPs
    		mov	@hDc,eax
    
    		invoke	GetClientRect,hWnd,addr @stRect
    		invoke DrawText,@hDc,addr szText,-1,addr @stRect,\
    		DT_SINGLELINE or DT_CENTER or DT_VCENTER
    
    		invoke EndPaint,hWnd,addr @stPs
    
    	.elseif eax == WM_CLOSE
    		invoke DestroyWindow,hWinMain
    		invoke PostQuitMessage,NULL
    	.else
    		invoke DefWindowProc,hWnd,uMsg,wParam,lParam
    		ret
    	.endif
    	xor eax,eax
    	ret
    _ProcWinMain	endp
    
    _WinMain proc
    	local @stWndClass:WNDCLASSEX
    	local @stMsg:MSG
    
    	invoke GetModuleHandle,NULL
    	mov hInstance,eax
    	invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
    
    	invoke LoadCursor,0,IDC_ARROW
    	mov @stWndClass.hCursor,eax
    	push hInstance
    	pop @stWndClass.hInstance
    	mov @stWndClass.cbSize,sizeof WNDCLASSEX
    	mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW
    	mov @stWndClass.lpfnWndProc,offset _ProcWinMain
    	mov @stWndClass.hbrBackground,COLOR_WINDOW + 1
    	mov @stWndClass.lpszClassName,offset szClassName
    	invoke RegisterClassEx,addr @stWndClass
    
    	invoke CreateWindowEx,WS_EX_CLIENTEDGE,\
    	offset szClassName,offset szCaptionMain,\
    	WS_OVERLAPPEDWINDOW,\
    	100,100,600,400,\
    	NULL,NULL,hInstance,NULL
    
    	mov hWinMain,eax
    	invoke ShowWindow,hWinMain,SW_SHOWNORMAL
    	invoke UpdateWindow,hWinMain
    
    	.while TRUE
    		invoke GetMessage,addr @stMsg,NULL,0,0
    		.break	.if eax == 0
    		invoke TranslateMessage,addr @stMsg
    		invoke DispatchMessage,addr @stMsg
    	.endw
    	ret
    _WinMain endp
    
    start:	
    	call _WinMain
    	invoke ExitProcess,NULL
    end start
    

    第6章无导入表的helloworld

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    
    _QLGetProcAddress typedef proto :dword,:dword
    
    _ApiGetProcAddress typedef ptr _QLGetProcAddress
    
    _QLLoadLib typedef proto :dword
    _ApiLoadLib typedef ptr _QLLoadLib
    
    _QLMessageBoxA typedef proto :dword,:dword,:dword,:dword
    _ApiMessageBoxA typedef ptr _QLMessageBoxA
    
    	.code
    szText db 'HelloWorldPE',0
    szGetProcAddr db 'GetProcAddress',0
    szLoadLib db 'LoadLibraryA',0
    szMessageBox db 'MessageBoxA',0
    
    user32_DLL db 'user32.dll',0,0
    
    _getProcAddress _ApiGetProcAddress ?
    _loadLibrary _ApiLoadLib ?
    _messageBox _ApiMessageBoxA ?
    
    hKernel32Base dd ?
    hUser32Base dd ?
    lpGetProcAddr dd ?
    lpLoadLib dd ?
    
    _getKernelBase proc _dwKernelRetAddress
    	local @dwRet
    
    	pushad
    	mov @dwRet,0
    	mov edi,_dwKernelRetAddress
    
    	and edi,0ffff0000h
    
    	.repeat
    		.if word ptr [edi] == IMAGE_DOS_SIGNATURE
    			mov esi,edi
    			add esi,[esi+003ch]
    			.if word ptr [esi] == IMAGE_NT_SIGNATURE
    				mov @dwRet,edi
    				.break
    			.endif
    		.endif
    		sub edi,010000h
    		.break .if edi<070000000h
    	.until FALSE
    	popad
    	mov eax,@dwRet
    	ret
    _getKernelBase endp
    
    _getApi proc _hModule,_lpApi
    	local @ret
    	local @dwLen
    
    	pushad
    	mov @ret,0
    	mov edi,_lpApi
    	mov ecx,-1
    	xor al,al
    	cld
    	repnz scasb
    	mov ecx,edi
    	sub ecx,_lpApi
    	mov @dwLen,ecx
    
    	mov esi,_hModule
    	add esi,[esi+3ch]
    	assume esi:ptr IMAGE_NT_HEADERS
    	mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
    	add esi,_hModule
    	assume esi:ptr IMAGE_EXPORT_DIRECTORY
    
    	mov ebx,[esi].AddressOfNames
    	add ebx,_hModule
    	xor edx,edx
    	.repeat
    		push esi
    		mov edi,[ebx]
    		add edi,_hModule
    		mov esi,_lpApi
    		mov ecx,@dwLen
    		repz cmpsb
    		.if ZERO?
    			pop esi
    			jmp @F
    		.endif
    		pop esi
    		add ebx,4
    		inc edx
    	.until	edx>=[esi].NumberOfNames
    	jmp _ret
    @@:
    	sub ebx,[esi].AddressOfNames
    	sub ebx,_hModule
    	shr ebx,1
    	add ebx,[esi].AddressOfNameOrdinals
    	add ebx,_hModule
    	movzx eax,word ptr [ebx]
    	shl eax,2
    	add eax,[esi].AddressOfFunctions
    	add eax,_hModule
    	mov eax,[eax]
    	add eax,_hModule
    	mov @ret,eax
    _ret:
    	assume esi:nothing
    	popad
    	mov eax,@ret
    	ret
    _getApi endp
    
    start:
    	mov eax,dword ptr [esp]
    	invoke _getKernelBase,eax
    	mov hKernel32Base,eax
    
    	invoke _getApi,hKernel32Base,addr szGetProcAddr
    	mov lpGetProcAddr,eax
    	mov _getProcAddress,eax
    	invoke _getProcAddress,hKernel32Base,addr szLoadLib
    	mov _loadLibrary,eax
    	invoke _loadLibrary ,addr user32_DLL
    	mov hUser32Base,eax
    	invoke _getProcAddress,hUser32Base,addr szMessageBox
    	mov _messageBox,eax
    	invoke _messageBox,NULL,offset szText,NULL,MB_OK
    	ret
    end start
    
    

    自己修改,使用重定位的HelloWorld

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    
    _QLGetProcAddress typedef proto :dword,:dword
    
    _ApiGetProcAddress typedef ptr _QLGetProcAddress
    
    _QLLoadLib typedef proto :dword
    _ApiLoadLib typedef ptr _QLLoadLib
    
    _QLMessageBoxA typedef proto :dword,:dword,:dword,:dword
    _ApiMessageBoxA typedef ptr _QLMessageBoxA
    
    	.code
    szText db 'HelloWorldPE',0
    szGetProcAddr db 'GetProcAddress',0
    szLoadLib db 'LoadLibraryA',0
    szMessageBox db 'MessageBoxA',0
    szExitProcess db 'ExitProcess',0
    
    user32_DLL db 'user32.dll',0,0
    
    _getProcAddress _ApiGetProcAddress ?
    _loadLibrary _ApiLoadLib ?
    _messageBox _ApiMessageBoxA ?
    
    hKernel32Base dd ?
    hUser32Base dd ?
    lpGetProcAddr dd ?
    lpLoadLib dd ?
    
    _getKernelBase proc _dwKernelRetAddress
    	local @dwRet
    
    	pushad
    	mov @dwRet,0
    	mov edi,_dwKernelRetAddress
    
    	and edi,0ffff0000h
    
    	.repeat
    		.if word ptr [edi] == IMAGE_DOS_SIGNATURE
    			mov esi,edi
    			add esi,[esi+003ch]
    			.if word ptr [esi] == IMAGE_NT_SIGNATURE
    				mov @dwRet,edi
    				.break
    			.endif
    		.endif
    		sub edi,010000h
    		.break .if edi<070000000h
    	.until FALSE
    	popad
    	mov eax,@dwRet
    	ret
    _getKernelBase endp
    
    _getApi proc _hModule,_lpApi
    	local @ret
    	local @dwLen
    
    	pushad
    	mov @ret,0
    	mov edi,_lpApi
    	mov ecx,-1
    	xor al,al
    	cld
    	repnz scasb
    	mov ecx,edi
    	sub ecx,_lpApi
    	mov @dwLen,ecx
    
    	mov esi,_hModule
    	add esi,[esi+3ch]
    	assume esi:ptr IMAGE_NT_HEADERS
    	mov esi,[esi].OptionalHeader.DataDirectory.VirtualAddress
    	add esi,_hModule
    	assume esi:ptr IMAGE_EXPORT_DIRECTORY
    
    	mov ebx,[esi].AddressOfNames
    	add ebx,_hModule
    	xor edx,edx
    	.repeat
    		push esi
    		mov edi,[ebx]
    		add edi,_hModule
    		mov esi,_lpApi
    		mov ecx,@dwLen
    		repz cmpsb
    		.if ZERO?
    			pop esi
    			jmp @F
    		.endif
    		pop esi
    		add ebx,4
    		inc edx
    	.until	edx>=[esi].NumberOfNames
    	jmp _ret
    @@:
    	sub ebx,[esi].AddressOfNames
    	sub ebx,_hModule
    	shr ebx,1
    	add ebx,[esi].AddressOfNameOrdinals
    	add ebx,_hModule
    	movzx eax,word ptr [ebx]
    	shl eax,2
    	add eax,[esi].AddressOfFunctions
    	add eax,_hModule
    	mov eax,[eax]
    	add eax,_hModule
    	mov @ret,eax
    _ret:
    	assume esi:nothing
    	popad
    	mov eax,@ret
    	ret
    _getApi endp
    
    start:
    	mov eax,dword ptr [esp]
    	push eax
    	call @F
    @@:
    	pop ebx
    	sub ebx,offset @B
    	pop eax
    
    	;获取kernel32.dll的基址
    	invoke _getKernelBase,eax
    	
    	mov [ebx + offset hKernel32Base],eax
    
    
    	;获取ProcAddress的函数地址
    	mov edx,ebx
    	add edx,offset szGetProcAddr
    	invoke _getApi,eax,edx
    
    	mov [ebx + offset _getProcAddress],eax
    	
    	;获取LoadLibrary的函数地址
    	mov edx,ebx
    	add edx,offset szLoadLib
    	push edx
    	push [ebx + offset hKernel32Base]
    	call eax
    
    
    	;下面这一段和上面等效,其实自己写的_getApi和系统库的GetProcAddress一个效果
    	;mov edx,ebx
    	;add edx,offset szLoadLib
    	;invoke _getApi,[ebx + offset hKernel32Base],edx
    
    
    	mov [ebx+offset _loadLibrary],eax
    
    	;加载user32.dll
    	mov edx,ebx
    	add edx,offset user32_DLL
    	push edx
    	call eax
    
    	mov [ebx + offset hUser32Base],eax  
    
    	;找到MessageBox的函数地址
    	mov edx,ebx
    	add edx,offset szMessageBox
    	invoke _getApi,eax,edx
    	
    	;下面这一段和上面等效
    	;mov ecx,ebx
    	;add ecx,offset szMessageBox
    	;push ecx
    	;push eax
    	;call [ebx + offset _getProcAddress]
    
    	mov ecx,ebx
    	add ecx,offset szText
    
    	push MB_OK
    	push NULL
    	push ecx
    	push NULL
    	call eax
    
    	;不加上ExitProcess的话,关闭信息框后进程还挂在后台
    	mov edx,ebx
    	add edx,offset szExitProcess
    	invoke _getApi,[ebx + offset hKernel32Base],edx
    
    	push NULL
    	call eax
    end start
    

    栈溢出,配合OD调试观看栈的变化。

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    	
    	.data
    szText db 'HelloWorldPE',0
    szText2 db 'Touch Me!',0
    szShellCode dd 0fffffffh,0dddddddh,0040103ah,0
    
    	.code
    _memCopy proc _lpSrc
    	local @buf[4]:byte
    	pushad
    	mov al,1
    	mov esi,_lpSrc
    	lea edi,@buf
    	.while al!=0
    		mov al,byte ptr [esi]
    		mov byte ptr [edi],al
    
    		inc esi
    		inc edi
    	.endw
    	popad
    	ret
    _memCopy endp
    
    start:
    	invoke _memCopy,addr szShellCode
    	invoke MessageBox,NULL,offset szText,NULL,MB_OK
    	invoke MessageBox,NULL,offset szText2,NULL,MB_OK
    	invoke ExitProcess,NULL
    end start
    
    
    

    编写dll的源代码以及过程

    1.asm

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    
    MAX_XYSTEPS equ 50
    DELAY_VALUE equ 50
    X_STEP_SIZE equ 10
    Y_STEP_SIZE equ 9
    X_START_SIZE equ 20
    Y_START_SIZE equ 10
    
    LMA_ALPHA 	equ 2
    LMA_COLORKEY equ 1
    WS_EX_LAYERED equ 80000h
    
    	.data
    dwCount dd ?
    Value dd ?
    Xsize dd ?
    Ysize dd ?
    sWth dd ?
    sHth dd ?
    Xplace dd ?
    Yplace dd ?
    counts dd ?
    pSLWA dd ?
    User32 db 'user32.dll',0
    SLWA db 'SetLayeredWindowAttributes',0
    
    	.code
    DllEntry proc _hInstance,_dwReason,_dwReserved
    	mov eax,TRUE
    	ret
    DllEntry endp
    
    TopXY proc wDim:DWORD,sDim:DWORD
    	shr sDim,1
    	shr wDim,1
    	mov eax,wDim
    	sub sDim,eax
    	mov eax,sDim
    	ret
    TopXY endp
    
    AnimateOpen proc hWin:DWORD
    	
    	LOCAL Rct:RECT
    
    	invoke GetWindowRect,hWin,ADDR Rct
    	mov Xsize,X_START_SIZE
    	mov Ysize,Y_START_SIZE
    	invoke GetSystemMetrics,SM_CXSCREEN
    	mov sWth,eax
    	invoke TopXY,Xsize,eax
    	mov Xplace,eax
    	invoke GetSystemMetrics,SM_CYSCREEN
    	mov sHth,eax
    	invoke TopXY,Ysize,eax
    	mov Yplace,eax
    	mov counts,MAX_XYSTEPS
    
    aniloop:
    	invoke MoveWindow,hWin,Xplace,Yplace,Xsize,Ysize,FALSE
    	invoke ShowWindow,hWin,SW_SHOWNA
    	invoke Sleep,DELAY_VALUE
    	invoke ShowWindow,hWin,SW_HIDE
    	add Xsize,X_STEP_SIZE
    	add Ysize,Y_STEP_SIZE
    	invoke TopXY,Xsize,sWth
    	mov Xplace,eax
    	invoke TopXY,Ysize,sHth
    	mov Yplace,eax
    	dec counts
    	jnz aniloop
    	mov eax,Rct.left
    	mov ecx,Rct.right
    	sub ecx,eax
    	mov Xsize,ecx
    	mov eax,Rct.top
    	mov ecx,Rct.bottom
    	sub ecx,eax
    	mov Ysize,ecx
    	invoke TopXY,Xsize,sWth
    	mov Xplace,eax
    	invoke TopXY,Ysize,sHth
    	mov Yplace,eax
    	invoke MoveWindow,hWin,Xplace,Yplace,Xsize,Ysize,TRUE
    	invoke ShowWindow,hWin,SW_SHOW
    	ret
    AnimateOpen endp
    
    AnimateClose proc hWin:DWORD
    	
    	LOCAL Rct:RECT
    
    	invoke ShowWindow,hWin,SW_HIDE
    	invoke GetWindowRect,hWin,ADDR Rct
    	mov eax,Rct.left
    	mov ecx,Rct.right
    	sub ecx,eax
    	mov Xsize,ecx
    	mov eax,Rct.top
    	mov ecx,Rct.bottom
    	sub ecx,eax
    	mov Ysize,ecx
    	invoke GetSystemMetrics,SM_CXSCREEN
    	mov sWth,eax
    	invoke TopXY,Xsize,eax
    	mov Xplace,eax
    	invoke GetSystemMetrics,SM_CYSCREEN
    	mov sHth,eax
    	invoke TopXY,Ysize,eax
    	mov Yplace,eax
    	mov counts,MAX_XYSTEPS
    
    aniloop:
    	invoke MoveWindow,hWin,Xplace,Yplace,Xsize,Ysize,FALSE
    	invoke ShowWindow,hWin,SW_SHOWNA
    	invoke Sleep,DELAY_VALUE
    	invoke ShowWindow,hWin,SW_HIDE
    	sub Xsize,X_STEP_SIZE
    	sub Ysize,Y_STEP_SIZE
    	invoke TopXY,Xsize,sWth
    	mov Xplace,eax
    	invoke TopXY,Ysize,sHth
    	mov Yplace,eax
    	dec counts
    	jnz aniloop
    	ret
    AnimateClose endp
    
    FadeInOpen proc hWin:DWORD
    	invoke GetWindowLongA,hWin,GWL_EXSTYLE
    	or eax,WS_EX_LAYERED
    	invoke SetWindowLongA,hWin,GWL_EXSTYLE,eax
    	invoke GetModuleHandleA,ADDR User32
    	invoke GetProcAddress,eax,ADDR SLWA
    	mov pSLWA,eax
    	push LMA_ALPHA
    	push 0
    	push 0
    	push hWin
    	call pSLWA
    	mov Value,90
    	invoke ShowWindow,hWin,SW_SHOWNA
    doloop:
    	push LMA_COLORKEY + LMA_ALPHA
    	push Value
    	push Value
    	push pSLWA
    	invoke Sleep,DELAY_VALUE
    	add Value,15
    	cmp Value,255
    	jne doloop
    	push LMA_ALPHA
    	push 255
    	push 0
    	push hWin
    	call pSLWA
    	ret
    FadeInOpen endp
    
    FadeOutClose proc hWin:DWORD
    	invoke GetWindowLongA,hWin,GWL_EXSTYLE
    	or eax,WS_EX_LAYERED
    	invoke SetWindowLongA,hWin,GWL_EXSTYLE,eax
    	invoke GetModuleHandleA,ADDR User32
    	invoke GetProcAddress,eax,ADDR SLWA
    	mov pSLWA,eax
    	push LMA_ALPHA
    	push 255
    	push 0
    	push hWin
    	call pSLWA
    	mov Value,255
    doloop:
    	push LMA_COLORKEY + LMA_ALPHA
    	push Value
    	push Value
    	push hWin
    	call pSLWA
    	invoke Sleep,DELAY_VALUE
    	sub Value,15
    	cmp Value,0
    	jne doloop
    	ret
    FadeOutClose endp
    
    End DllEntry
    
    

    1.def

    EXPORTS AnimateOpen
    		AnimateClose
    		FadeInOpen
    		FadeOutClose
    

    编译链接:

    ml -c -coff 1.asm
    link -subsystem:windows -DLL -def:1.def 1.obj
    

    但是要在其他程序中使用这个dll,还需要编写inc文件

    1.inc

    AnimateOpen proto :dword
    AnimateClose proto :dword
    FadeInOpen proto :dword
    FadeOutClose proto :dword
    

    后面的例子,使用上一个dll

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include gdi32.inc
    includelib gdi32.lib
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    include 1.inc
    includelib 1.lib
    	
    	.data?
    hInstance dd ?
    hWinMain dd ?
    
    	.const
    szClassName db 'MyClass',0
    szCaptionMain db '窗口特效演示',0
    szText db '你好,认识我吗?^-^',0
    
    	.code
    _ProcWinMain proc uses ebx edi esi,hWnd,uMsg,wParam,lParam
    	local @stPs:PAINTSTRUCT
    	local @stRect:RECT
    	local @hDc
    
    	mov eax,uMsg
    
    	.if eax==WM_PAINT
    		invoke BeginPaint,hWnd,addr @stPs
    		invoke DrawText,@hDc,addr szText,-1,\
    			addr @stRect,\
    			DT_SINGLELINE or DT_CENTER or DT_VCENTER
    		invoke EndPaint,hWnd,addr @stPs
    	.elseif eax==WM_CLOSE
    		invoke FadeOutClose,hWinMain
    		invoke DestroyWindow,hWinMain
    		invoke PostQuitMessage,NULL
    	.else
    		invoke DefWindowProc,hWnd,uMsg,wParam,lParam
    		ret
    	.endif
    	xor eax,eax
    	ret
    _ProcWinMain endp
    
    _WinMain proc
    	local @stWndClass:WNDCLASSEX
    	local @stMsg:MSG
    
    	invoke GetModuleHandle,NULL
    	mov hInstance,eax
    	invoke RtlZeroMemory,addr @stWndClass,sizeof @stWndClass
    
    	invoke LoadCursor,0,IDC_ARROW
    	mov @stWndClass.hCursor,eax
    	push hInstance
    	pop @stWndClass.hInstance
    	mov @stWndClass.cbSize,sizeof WNDCLASSEX
    	mov @stWndClass.style,CS_HREDRAW or CS_VREDRAW
    	mov @stWndClass.lpfnWndProc,offset _ProcWinMain
    	mov @stWndClass.hbrBackground,COLOR_WINDOW + 1
    	mov @stWndClass.lpszClassName,offset szClassName
    	invoke RegisterClassEx,addr @stWndClass
    
    	invoke CreateWindowEx,WS_EX_CLIENTEDGE,\
    	offset szClassName,offset szCaptionMain,\
    	WS_OVERLAPPEDWINDOW,\
    	100,100,600,400,\
    	NULL,NULL,hInstance,NULL
    
    	mov hWinMain,eax
    	invoke FadeInOpen,hWinMain
    	;invoke ShowWindow,hWinMain,SW_SHOWNORMAL
    	invoke UpdateWindow,hWinMain
    
    	.while TRUE
    		invoke GetMessage,addr @stMsg,NULL,0,0
    		.break	.if eax == 0
    		invoke TranslateMessage,addr @stMsg
    		invoke DispatchMessage,addr @stMsg
    	.endw
    	ret
    _WinMain endp
    
    start:
    	call _WinMain
    	invoke ExitProcess,NULL
    	end start
    

    延迟导入:

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    include 7.inc
    includelib 7.lib
    include delayimp.inc
    includelib delayimp.lib
    	.data
    dwFlag dd 1
    szText db 'HelloWorldPE',0
    	.code
    	start:
    	mov eax,dwFlag
    	.if eax==0
    		invoke AnimateOpen,NULL
    	.endif
    	invoke MessageBox,NULL,offset szText,NULL,MB_OK
    	invoke ExitProcess,NULL
    	end start
    
    

    代码没问题,但是win10下的masm32链接就报错,所以想学习这个延迟导入,直接VS写个代码,然后配置里面添加延迟导入的dll就可以了。

    第9章的使用TLS多线程的例子。

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    
    MAX_THREAD_COUNT equ 4
    
    	.data
    hTlsIndex dd ?
    dwThreadID dd ?
    hThreadID dd MAX_THREAD_COUNT dup(0)
    dwCount dd ?
    szBuffer db 500 dup(0)
    szOut1 db 'xc%dstop use:%dms',0
    szErr1 db 'read TLS errorr!',0
    szErr2 db 'write TLS error!',0
    
    	.code
    _initTime proc
    	local @dwStart
    	pushad
    
    	invoke GetTickCount
    	mov @dwStart,eax
    	invoke TlsSetValue,hTlsIndex,@dwStart
    	.if eax==0
    		invoke MessageBox,NULL,addr szErr2,NULL,MB_OK
    	.endif
    	popad
    	ret
    _initTime endp
    
    _getLostTime proc
    	local @dwTemp
    	pushad
    
    	invoke GetTickCount
    	mov @dwTemp,eax
    	invoke TlsGetValue,hTlsIndex
    	.if eax==0
    		invoke MessageBox,NULL,addr szErr2,NULL,MB_OK
    	.endif
    	sub @dwTemp,eax
    	popad
    	mov eax,@dwTemp
    	ret
    _getLostTime endp
    
    _tFun proc uses ebx ecx edx esi edi,lParam
    	local @dwCount
    	local @tID
    	pushad
    	invoke _initTime
    
    	mov @dwCount,1000*10000
    	mov ecx,@dwCount
    	.while ecx>0
    		dec @dwCount
    		dec ecx
    	.endw
    
    	invoke GetCurrentThreadId
    	mov @tID,eax
    	invoke _getLostTime
    	invoke wsprintf,addr szBuffer,addr szOut1,@tID,eax
    	invoke MessageBox,NULL,addr szBuffer,NULL,MB_OK
    	popad
    	ret
    _tFun endp
    
    start:
    	invoke TlsAlloc
    	mov hTlsIndex,eax
    	mov dwCount,MAX_THREAD_COUNT
    	mov edi,offset hThreadID
    	.while dwCount>0
    		invoke CreateThread,NULL,0,offset _tFun,NULL,NULL,addr dwThreadID
    		mov dword ptr [edi],eax
    		add edi,4
    		dec dwCount
    	.endw
    
    	mov dwCount,MAX_THREAD_COUNT
    	mov edi,offset hThreadID
    	.while dwCount>0
    		mov eax,dword ptr [edi]
    		mov dwThreadID,eax
    		push edi
    		invoke WaitForSingleObject,eax,INFINITE
    		invoke CloseHandle,dwThreadID
    		pop edi
    		add edi,4
    		dec dwCount
    	.endw
    	invoke TlsFree,hTlsIndex
    	invoke ExitProcess,NULL
    	end start
    
    

    不带TLS的多线程例子

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    
    MAX_THREAD_COUNT equ 4
    
    	.data
    hTlsIndex dd ?
    dwThreadID dd ?
    hThreadID dd MAX_THREAD_COUNT dup(0)
    
    dwCount dd ?
    
    szBuffer db 500 dup(0)
    szOut1 db 'xc %d terminated,use %d ms.',0
    
    	.code
    _tFun proc uses ebx ecx edx esi edi,lParam
    	local @dwCount
    	local @dwStart
    	local @dwEnd
    	local @tID
    	pushad
    
    	invoke GetTickCount
    	mov @dwStart,eax
    
    	mov @dwCount,1000*10000
    	mov ecx,@dwCount
    	.while ecx>0
    		dec @dwCount
    		dec ecx
    	.endw
    
    	invoke GetCurrentThreadId
    	mov @tID,eax
    
    	invoke GetTickCount
    	mov @dwEnd,eax
    	mov eax,@dwStart
    	sub @dwEnd,eax
    	invoke wsprintf,addr szBuffer,addr szOut1,@tID,@dwEnd
    	invoke MessageBox,NULL,addr szBuffer,NULL,MB_OK
    
    	popad
    	ret
    _tFun endp
    
    start:
    	mov dwCount,MAX_THREAD_COUNT
    	mov edi,offset hThreadID
    	.while dwCount>0
    		invoke CreateThread,NULL,0,offset _tFun,NULL,NULL,addr dwThreadID
    		mov dword ptr [edi],eax
    		add edi,4
    		dec dwCount
    	.endw
    
    	mov dwCount,MAX_THREAD_COUNT
    	mov edi,offset hThreadID
    	.while dwCount>0
    		mov eax,dword ptr [edi]
    		mov dwThreadID,eax
    		push edi
    		invoke WaitForSingleObject,dwThreadID,INFINITE
    		invoke CloseHandle,dwThreadID
    		pop edi
    		add edi,4
    		dec dwCount
    	.endw
    	invoke ExitProcess,NULL
    	end start
    
    

    TLS回调函数的例子

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    
    	.data
    szText db 'HelloWorldPE',0,0,0,0
    
    TLS_DIRR dd offset Tls1
    		 dd offset Tls2
    		 dd offset Tls3
    		 dd offset TlsCallBack
    		 dd 0
    		 dd 0
    Tls1     dd 0
    Tls2 	 dd 0
    Tls3 	 dd 0
    TlsCallBack dd	offset TLS
    			dd 0
    			dd 0
    	.data?
    TLSCalled db ?
    	.code
    start:
    	invoke ExitProcess,NULL
    	RET
    TLS:
    cmp byte ptr [TLSCalled],1
    je @exit
    mov byte ptr [TLSCalled],1
    invoke MessageBox,NULL,addr szText,NULL,MB_OK
    
    @exit:
    RET
    	end start
    

    需要注意的是,这里构造了数据目录表里面线程本地存储表的数据,需要自己修改exe的字节文件,让那个表指向代码段的数据。详情可见本人线程本地存储记录。

    第11章,获取kernel32.dll地址(一)

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    
    	.data
    szText db 'kernel32.dll的基地址为%08x',0
    szOut db '%08x',0dh,0ah,0
    szBuffer db 256 dup(0)
    
    	.code
    start:
    	call loc0
    	db 'GetProcAddress',0
    
    loc0:
    	pop edx
    	push edx
    	mov ebx,7ffe0000h
    	;mov ebx,75950000h
    
    loc1:
    	cmp dword ptr [ebx],905A4Dh
    	JE loc2
    
    loc5:
    	sub ebx,00010000h
    
    	pushad
    	invoke IsBadReadPtr,ebx,2
    	.if eax
    		popad
    		jmp loc5
    	.endif
    	popad
    
    	jmp loc1
    
    loc2:
    	mov esi,dword ptr [ebx+3ch]
    	add esi,ebx
    	mov esi,dword ptr [esi+78h]
    	nop
    
    	.if esi==0
    		jmp loc5
    	.endif
    	add esi,ebx
    	mov edi,dword ptr [esi+20h]
    	add edi,ebx
    	mov ecx,dword ptr [esi+18h]
    	push esi
    
    	xor eax,eax
    
    loc3:
    	push edi
    	push ecx
    	mov edi,dword ptr [edi]
    	add edi,ebx
    	mov esi,edx
    	xor ecx,ecx
    	mov cl,0eh
    	repe cmpsb
    	pop ecx
    	pop edi
    	je loc4
    	add edi,4
    	inc eax
    	loop loc3
    
    	jmp loc5
    loc4:
    	invoke wsprintf,addr szBuffer,addr szText,ebx
    	invoke MessageBox,NULL,addr szBuffer,NULL,MB_OK
    	ret
    
    	end start
    

    这里有坑,它写的地址太高了,不属于此进程,使用isbadreadptr就会抛出异常。个人认为,还不如直接查看栈顶地址,然后以10000H向下取整。。。因为执行到main的时候,是从kernel32.dll跳过来的。

    image

    (二)
        .386
        .model flat,stdcall
        option casemap:none
    
    include windows.inc
    include kernel32.inc
    includelib kernel32.lib
    include user32.inc
    includelib user32.lib
    
        .data
    szText db 'ksernel32.dll %08x',0
    szOut db '%08x',0dh,0ah,0
    szBuffer db 256 dup(0)
        
        .code
    
    start:
        assume fs:nothing
        mov eax,fs:[0]
        inc eax
    loc1:
        dec eax
        mov esi,eax
        mov eax,[eax]
        inc eax
        jne loc1
        lodsd
        lodsd
        xor ax,ax
        jmp loc3
    loc2:
        sub eax,10000h
    loc3:
        cmp dword ptr [eax],905A4Dh
        jne loc2
    
        invoke wsprintf,addr szBuffer,addr szText,eax
        invoke MessageBox,NULL,addr szBuffer,NULL,MB_OK
    
        invoke ExitProcess,NULL
        ret
    end start
    
    

    本人对此也不太熟悉,不过能确定的是,在win10上,运行结果是错的,不是kernel32.dll的地址。建议合并一和二。把一里面那个太高的地址改成二获得的地址就好了。

    (三)

        .386
        .model flat,stdcall
        option casemap:none
    
    include windows.inc
    include kernel32.inc
    includelib kernel32.lib
    include user32.inc
    includelib user32.lib
    
        .data
    szText db 'ksernel32.dll %08x',0
    szOut db '%08x',0dh,0ah,0
    szBuffer db 256 dup(0)
        
        .code
    
    start:
        assume fs:nothing
        mov eax,fs:[30h]
        mov eax,[eax+0ch]
        mov esi,[eax+1ch]
        lodsd
        mov eax,[eax];这一句是win7/win10需要添加的,原文没有,运行结果不是对的
        mov eax,[eax+8]
    
        invoke wsprintf,addr szBuffer,addr szText,eax
        invoke MessageBox,NULL,addr szBuffer,NULL,MB_OK
    
        invoke ExitProcess,NULL
        ret
    end start
    
    

    第10章SEH处理框架

    代码:

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    
    	.data
    szText db 'HelloWorldPE',0
    szErr  db 'SEH Error',0
    	.code
    _handler proc _lpException,_lpSEH,\
    	_lpContext,_lpSidpatcherContext
    
    	nop
    	pushad
    	mov esi,_lpException
    	mov edi,_lpContext
    
    	assume edi:ptr CONTEXT
    
    	invoke MessageBox,NULL,addr szErr,NULL,MB_OK
    
    	mov [edi].regEip,offset _safePlace
    	assume edi:nothing
    
    	popad 
    
    	mov eax,ExceptionContinueExecution
    	;mov eax,ExceptionContinueSearch
    
    	ret
    _handler endp
    
    start:
    	assume fs:nothing
    	push offset _handler
    	push fs:[0]
    	mov fs:[0],esp
    
    	xor eax,eax
    	mov dword ptr [eax],eax
    
    _safePlace:
    	pop fs:[0]
    	pop eax
    
    	invoke MessageBox,NULL,addr szText,NULL,MB_OK
    	invoke ExitProcess,NULL
    	end start
    

    刚开始还不明白xor eax,eax之前的语句,后来才发现,这是构造了一个ExceptionList结构。

    ExceptionList指向一个EXCEPTION_REGISTRATION结构。

    定义:

    EXCEPTION_REGISTRATION STRUCT
    Prev dd ?
    Handler dd ?
    EXCEPTION_REGISTRATION ENDS
    

    8个字节,前4个字节对应链接的其他结构,后4个字节对应此结构的异常处理函数地址。

    配置表

    代码:

    	.386
    	.model flat,stdcall
    	option casemap:none
    
    include windows.inc
    include user32.inc
    includelib user32.lib
    include kernel32.inc
    includelib kernel32.lib
    
    	.data
    szText1 db 'safeHandler!',0
    szText2 db 'nosafeHandler!',0
    szText db 'HelloWorldPE',0
    
    	.code
    ;IMAGE_LOAD_CONFIG_STRUCT STRUCT
    	Characteristic dd 00000048h
    	TimeDateStamp dd 0
    	MajorVersion dw 0
    	MinorVersion dw 0
    	GlobalFlagsClear dd 0
    	GlobalFlagsSet dd 0
    	CriticalSectionDefaultTimeout dd 0
    	DeCommitFreeeBlockThreshold dd 0
    	DeCommitTotalFreeThreshold dd 0
    	LockPrefixTable dd 0
    	MaximumAllocationSize dd 0
    	VirtualMemoryThreshold dd 0
    	ProcessHeapFlags dd 0
    	ProcessAffinityMask dd 0
    	CSDVersion dw 0
    	Reserved1 dw 0
    	EditList dd 0
    	SecurityCookie dd 00000000h
    	SEHandlerTable dd offset safeHandler
    	SEHandlerCount dd 00000001h
    ;IMAGE_LOAD_CONFIG_STRUCT ENDS
    
    safeHandler dd offset _handler1-00400000h
    			dd 0
    
    _handler1 proc _lpException,lpSEH,_lpContext,_lpDispatcherContext
    	nop
    	pushad
    	mov esi,_lpException
    	mov edi,_lpContext
    
    	assume edi:ptr CONTEXT
    
    	invoke MessageBox,NULL,addr szText1,NULL,MB_OK
    	mov [edi].regEip,offset _safePlace
    	assume edi:nothing
    
    	popad
    	mov eax,ExceptionContinueExecution
    	ret
    _handler1 endp
    
    _handler2 proc _lpException,_lpSEH,_lpContext,_lpDispatcherContext
    	nop
    	pushad
    	mov esi,_lpException
    	mov edi,_lpContext
    	assume edi:ptr CONTEXT
    	invoke MessageBox,NULL,addr szText2,NULL,MB_OK
    	mov [edi].regEip,offset _safePlace
    	assume edi:nothing
    
    	popad
    	mov eax,ExceptionContinueExecution
    	ret
    _handler2 endp
    
    start:
    	assume fs:nothing
    	push offset _handler1
    	push fs:[0]
    	mov fs:[0],esp
    	xor eax,eax
    	mov dword ptr [eax],eax
    
    _safePlace:
    	pop fs:[0]
    	pop eax
    	invoke MessageBox,NULL,addr szText,NULL,MB_OK
    	invoke ExitProcess,NULL
    	end start
    
    
    

    这个也是把配置表写在代码段里面进行构造,需要修改exe文件的配置属性表。

  • 相关阅读:
    pip 8 安装
    zabbix server配置文件
    双代号网络图、双代号时标网络图
    logrotate
    tsql 执行存储过程
    dos 加用户
    Visual Studio (VS IDE) 你必须知道的功能和技巧
    格式化数字字符串 与C#变量
    .NET中的字符串你了解多少?
    新手如何有效地学习.NET
  • 原文地址:https://www.cnblogs.com/dayq/p/16094798.html
Copyright © 2020-2023  润新知