.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
.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
.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
.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
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
.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就可以了。
.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
.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的字节文件,让那个表指向代码段的数据。详情可见本人线程本地存储记录。
.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
.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