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

2022/4/3 7:19:34

本文主要是介绍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



这篇关于WindowsPE权威指南学习过程中的代码片段的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程