win32 masm32 汇编学习 及 远程线程实例
生活随笔
收集整理的這篇文章主要介紹了
win32 masm32 汇编学习 及 远程线程实例
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
"門“ 指向某個優(yōu)先級高的程序所規(guī)定的入口點,所有優(yōu)先級低的程序調(diào)用優(yōu)先級高的程序只能通過門重定向
門:中斷門,自陷門,任務(wù)門。
masm32.zip
copy D:\Program Files\Microsoft Visual Studio\VC98\Bin\nmake.exe to ?***\masm32\bin
相應(yīng)cmd設(shè)置臨時環(huán)境變量
@echo off
set include=f:\masm32\Include;D:\Program Files\Microsoft Visual Studio\VC98\Include;D:\Program Files\Microsoft Visual Studio\VC98\MFC\Include
set lib=f:\masm32\lib
set path=f:\masm32\bin;%path%
@echo on
\**\nmake
.model flat ? MASM自動為各段寄存器做了如下定義:
ASSUME cs:FLAT,ds:FLAT,ss:flat,es:flat,fs:error,gs:error
全部段源程序結(jié)構(gòu):
.386
.model flat,stdcall
option casemap:none
< Include 文件定義>
.stack [堆棧段大小]
.data
<一些初始化過的變量定義>
.data? ;不會占用EXE文件空間
<一些沒初始化過的變量定義>
.const
<一些常量定義>
.code
<代碼>
<開始標(biāo)號>
<其他語句>
end 開始標(biāo)號
invoke 不是80x86的偽指令,它只是MASM編譯器的偽指令,實現(xiàn)push參數(shù)和call函數(shù)名而已。
對匯編而言,所有參數(shù)和返回值 只有一個dword類型,所以要么是簡單類型,要么是指針。
返回值放在eax中
函數(shù)名 proto [距離] [語言] [參數(shù)1]:數(shù)據(jù)類型,[參數(shù)2]:數(shù)據(jù)類型,....
proto:函數(shù)聲明偽指令
距離:NEAR,FAR...(WIN32只有只有一個平坦的段,無所謂距離,所以忽略)
語言:.model定義的默認值
對于WIN32它只關(guān)注參數(shù)個數(shù),參數(shù)名為是提高可讀性
MessageBox Proto hWnd:dword,lpText:dword,lpCaption:dword,uType:dword
MessageBox Proto ?:dword,:dword,:dword,:dword ?
其實這兩定義是一樣的
只有windows NT才完全支持Unicode,
if UNICODE
MessageBox equ <MessageBoxW>
else
MessageBox equ <MessageBoxA>
endif
//@@做標(biāo)號
@F本指令后第一個@@標(biāo)號,@B本指令前的第一個@@標(biāo)號
如果要定義兩個字符串"hello,world!",和"hello agin",則每個字符串后跟回車和換行符,最后以一個0字符結(jié)尾,
szText db 'hello,world!',0dh,0ah,'hello agin',0dh,0ah,0
.data? 后面的默認是0,不是隨機的 ?//與這全局變量不同,local后的局部變量起始值是隨機的
MASM用local偽指令來定義局部變量,local偽指令必須proc偽指令后,其他指令開始前。因為變量數(shù)量要早確定下來
結(jié)構(gòu)構(gòu)成員引用:
1: mov eax,strutname.lpfn
2: mov esi,offset strutname
mov eas,[esi+STRUTNAME.lpfn]
3: mov esi,offset strutname
assume esi:ptr STRUTNAME
mov eax,[esi].lpfn
...
assume esi:nothing
.data
bTest1 db 12h
wTest2 dw 1234h
mov ax,bTest1 ;ax = 3412h
movzx ax,bText1 ;ax = 0012h movsx:帶符號擴展
sizeof/lengthof偽指令
如果hello world分兩行定義:
szHello db 'hello',odh,oah
db 'world',0
sizeof szHello為7,原因masm中變量只認一行,db 'world',0 實際上是沒有名稱的數(shù)據(jù)定義。
獲取變量地址:
全局變量:mov 寄存器,offset 變量名 ;編譯時
局部變量:lea ? ?寄存器,[ebp-4] ;運行時
參數(shù)局部變量:addr 參數(shù)變量
對局部變量取地址的時候,addr偽操作只能用在invoke的參數(shù)中,addr實際是先取地址到eax,再代替到參數(shù)里
invoke Test,eax,addr szHello ;錯誤
翻譯如下:
lea eax,addr szHello
push eax
push eax ;已經(jīng)被上面覆蓋
call Test
invoke Test,addr szHello,eax ;正確
子程序的定義:
子程序名 ?proc [...][...][VARARG]
local 局部變量列表
指令
子程序名 endp
proc后的參數(shù)列表中參數(shù)不能和全局變量及子程序中局部變量重名,VARARG指些子程序是可變參數(shù);proto為聲明,如上
調(diào)用約定有:C, SysCall,StdCall,BASIC,FORTRAN,PASCAL具體找度娘
條件測試語句:==, != , >,>=,<,<=,&,!,&&,||
限制:左邊只能是變量或者寄存器,不能是常量;
表達式兩邊不能同時為變量,但可以同時為寄存器。
分支語句:.if/.elseif/.else/.endif,如果不加點,則變成條件匯編偽操作
循環(huán)語句:
.while ?條件測試表達式
指令
[.break [.if 退出條件]]
[.continue]
.endw
或者
.repeat
指令
[.break [.if 退出條件]]
[.continue]
.until 條件測試表達式 (或.untilcxz [條件測試表達式])
上面的相當(dāng)while循環(huán),下面的相當(dāng)do...while循環(huán)
代碼規(guī)范:
參數(shù)用_開頭,局部變量用@開頭,內(nèi)部子程序用_開頭
盡量不要用宏定義,以免影響可讀性
子程序規(guī)模不要太大,注釋寫好,指針安全檢查,做好子程序庫以備未來編寫大程序。
第四章:第一個窗口程序
模塊句柄在數(shù)值上等于程序在內(nèi)存中裝入的起始地址,GetMododuleHandle,模 塊句柄便于訪問程度中的各種資源。
postmessage/sendmessage:
當(dāng)消息中用到指針時,postmessage函數(shù)來發(fā)送的消息都不會成功。
10.1.4
windows的“堆”分為默認堆和私有堆兩種。默認堆是在程序初始化時由OS自動創(chuàng)建的,所有的標(biāo)準(zhǔn)的內(nèi)存管理函數(shù)都是在默認堆中申請內(nèi)存的;而私有堆相當(dāng)于是在默認堆中保留了一大塊內(nèi)存,
默認堆只有一個私有堆可以有多個,默認堆可以直接使用,而私有堆必須先創(chuàng)建。
如果多個模塊在默認堆中使用內(nèi)存會交叉排序,一個模塊越界可以很難找到問題,如果多個模塊在各自的私有堆,越界更容易定位。
私有堆創(chuàng)建函數(shù)heapcreate/heapdestory
私有堆中分配和釋放內(nèi)存塊heapalloc/heaplock/....
在程序運行的時候,進程中每個地址都可以牌下列3種狀態(tài)的1種中:
占用狀態(tài):線程地址已映射物理內(nèi)存,也稱已提交狀態(tài)
自由狀態(tài):沒有映射到物理內(nèi)存,線程地址沒有被使用 //進程剛開始的起始狀態(tài)
保留狀態(tài):雖然沒有映射到物理內(nèi)存,但它不會被使用,直到希望使用他為止
當(dāng)使用上面的標(biāo)準(zhǔn)內(nèi)存管理函數(shù)時,用戶無法指定內(nèi)存位于哪個線程地址,使用virtual開頭的虛擬內(nèi)存管理函數(shù)可以做到這一點。如virtualalloc
VirtualAllocEx/CreateRemoteThread相比 Virtualalloc/createthread多了個hprocess,針對相應(yīng)進程操作
virtualallocex需要對相應(yīng)進程有process_vm_operation權(quán)限
?
遠程線程存在:重定位和函數(shù)的導(dǎo)入問題
對高級語言不可能解決重定位問題,因為沒辦法在機器碼級別上操作,c語言也沒有辦法,通過注入dll繞過去,因為裝載DLL會自動重定位
dwVar dd ?
call @F
@@:
pop ebx
sub ebx,offset @B
mov eax,[ebx+offset dwVar]
:00401000 00000000 BYTE 4 DUP(0)
:00401004 EB00000000 call 00401009
:00401009 5B pop ebx
:0040100A 81EB09104000 sub ebx,00401009
:00401010 8B8300104000 mov eax, dword ptr [ebx+00401000]
當(dāng)這段代碼移動00401000的位置時如下:
:00801000 00000000 BYTE 4 DUP(0)
:00801004 EB00000000 call 00801009
:00801009 5B pop ebx //此時ebx為:00801009
:0080100A 81EB09104000 sub ebx,00401009
:00801010 8B8300104000 mov eax, dword ptr [ebx+00401000]
遠程代碼用的win32 api,api又存在于是dll中,同時dll裝載基地不同,api函數(shù)地址也不同,所以手動完成:
1. loadlibary 使用的dll
2. getprocaddress api函數(shù)
其中1,2用到dll名字和api函數(shù)名都要采用上面重定位的方法保存好
遠程線程創(chuàng)建步驟:
1.VirtualAllocEx申請目標(biāo)進程的一塊內(nèi)存, 要有hProcess有 PROCESS_VM_OPERATION, 內(nèi)存塊應(yīng)該有PAGE_EXECUTE_READWRITE屬性
2.writeProcessMemory寫入代碼及數(shù)據(jù)
3.CreateRemoteThread ? 要hProcess有PROCESS_CREATE_THREAD權(quán)限 //remotethread code and data ; RemoteCode.asm ; 一段自定位的代碼,可以用來創(chuàng)建一個窗口 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> REMOTE_CODE_START equ this byte_lpLoadLibrary dd ? ;導(dǎo)入函數(shù)地址表 _lpGetProcAddress dd ? _lpGetModuleHandle dd ?_lpDestroyWindow dd ? _lpPostQuitMessage dd ? _lpDefWindowProc dd ? _lpLoadCursor dd ? _lpRegisterClassEx dd ? _lpCreateWindowEx dd ? _lpShowWindow dd ? _lpUpdateWindow dd ? _lpGetMessage dd ? _lpTranslateMessage dd ? _lpDispatchMessage dd ?_hInstance dd ? _hWinMain dd ? _szClassName db 'RemoteClass',0 _szCaptionMain db 'RemoteWindow',0 _szDllUser db 'User32.dll',0 _szDestroyWindow db 'DestroyWindow',0 _szPostQuitMessage db 'PostQuitMessage',0 _szDefWindowProc db 'DefWindowProcA',0 _szLoadCursor db 'LoadCursorA',0 _szRegisterClassEx db 'RegisterClassExA',0 _szCreateWindowEx db 'CreateWindowExA',0 _szShowWindow db 'ShowWindow',0 _szUpdateWindow db 'UpdateWindow',0 _szGetMessage db 'GetMessageA',0 _szTranslateMessage db 'TranslateMessage',0 _szDispatchMessage db 'DispatchMessageA',0,0 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _RemoteThread proc uses ebx edi esi lParamlocal @hModulecall @F@@:pop ebxsub ebx,offset @B ;********************************************************************_invoke [ebx + _lpGetModuleHandle],NULLmov [ebx + _hInstance],eaxlea eax,[ebx + offset _szDllUser]_invoke [ebx + _lpGetModuleHandle],eaxmov @hModule,eaxlea esi,[ebx + offset _szDestroyWindow]lea edi,[ebx + offset _lpDestroyWindow].while TRUE_invoke [ebx + _lpGetProcAddress],@hModule,esimov [edi],eaxadd edi,4@@:lodsbor al,aljnz @B.break .if ! byte ptr [esi].endw ;********************************************************************call _WinMainret_RemoteThread endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _ProcWinMain proc uses ebx edi esi,hWnd,uMsg,wParam,lParamcall @F@@:pop ebxsub ebx,offset @B ;********************************************************************mov eax,uMsg.if eax == WM_CLOSE_invoke [ebx + _lpDestroyWindow],hWnd_invoke [ebx + _lpPostQuitMessage],NULL ;********************************************************************.else_invoke [ebx + _lpDefWindowProc],hWnd,uMsg,wParam,lParamret.endif ;********************************************************************xor eax,eaxret_ProcWinMain endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _ZeroMemory proc _lpDest,_dwSizepush edimov edi,_lpDestmov ecx,_dwSizexor eax,eaxcldrep stosbpop ediret_ZeroMemory endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _WinMain proc uses ebx esi edi _lParamlocal @stWndClass:WNDCLASSEXlocal @stMsg:MSGcall @F@@:pop ebxsub ebx,offset @B ;********************************************************************invoke _ZeroMemory,addr @stWndClass,sizeof @stWndClass_invoke [ebx + _lpLoadCursor],0,IDC_ARROWmov @stWndClass.hCursor,eaxpush [ebx + _hInstance]pop @stWndClass.hInstancemov @stWndClass.cbSize,sizeof WNDCLASSEXmov @stWndClass.style,CS_HREDRAW or CS_VREDRAWlea eax,[ebx + offset _ProcWinMain]mov @stWndClass.lpfnWndProc,eaxmov @stWndClass.hbrBackground,COLOR_WINDOW + 1lea eax,[ebx + offset _szClassName]mov @stWndClass.lpszClassName,eaxlea eax,@stWndClass_invoke [ebx + _lpRegisterClassEx],eax ;******************************************************************** ; 建立并顯示窗口 ;********************************************************************lea eax,[ebx + offset _szClassName]lea ecx,[ebx + offset _szCaptionMain]_invoke [ebx + _lpCreateWindowEx],WS_EX_CLIENTEDGE,eax,ecx,\WS_OVERLAPPEDWINDOW,\100,100,600,400,\NULL,NULL,[ebx + _hInstance],NULLmov [ebx + _hWinMain],eax_invoke [ebx + _lpShowWindow],[ebx + _hWinMain],SW_SHOWNORMAL_invoke [ebx + _lpUpdateWindow],[ebx + _hWinMain] ;******************************************************************** ; 消息循環(huán) ;********************************************************************.while TRUElea eax,@stMsg_invoke [ebx + _lpGetMessage],eax,NULL,0,0.break .if eax == 0lea eax,@stMsg_invoke [ebx + _lpTranslateMessage],eaxlea eax,@stMsg_invoke [ebx + _lpDispatchMessage],eax.endwret_WinMain endp REMOTE_CODE_END equ this byte REMOTE_CODE_LENGTH equ offset REMOTE_CODE_END - offset REMOTE_CODE_START ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //createremotethread code ; RemoteThread.asm ; 向 Explorer.exe 進程中嵌入一段遠程執(zhí)行的代碼 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 使用 nmake 或下列命令進行編譯和鏈接: ; ml /c /coff RemoteThread.asm ; rc RemoteThread.rc ; Link /subsystem:windows RemoteThread.obj RemoteThread.res ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.386.model flat, stdcalloption casemap :none ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Include 文件定義 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib include Macro.inc ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 數(shù)據(jù)段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.data? lpLoadLibrary dd ? lpGetProcAddress dd ? lpGetModuleHandle dd ? dwProcessID dd ? dwThreadID dd ? hProcess dd ? lpRemoteCode dd ?.const szErrOpen db '無法打開遠程線程!',0 szDesktopClass db 'Progman',0 szDesktopWindow db 'Program Manager',0 szDllKernel db 'Kernel32.dll',0 szLoadLibrary db 'LoadLibraryA',0 szGetProcAddress db 'GetProcAddress',0 szGetModuleHandle db 'GetModuleHandleA',0 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.code ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>include RemoteCode.asmstart:invoke GetModuleHandle,addr szDllKernelmov ebx,eaxinvoke GetProcAddress,ebx,offset szLoadLibrarymov lpLoadLibrary,eaxinvoke GetProcAddress,ebx,offset szGetProcAddressmov lpGetProcAddress,eaxinvoke GetProcAddress,ebx,offset szGetModuleHandlemov lpGetModuleHandle,eax ;******************************************************************** ; 查找文件管理器窗口并獲取進程ID,然后打開進程 ;********************************************************************invoke FindWindow,addr szDesktopClass,addr szDesktopWindowinvoke GetWindowThreadProcessId,eax,offset dwProcessIDmov dwThreadID,eaxinvoke OpenProcess,PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or \PROCESS_VM_WRITE,FALSE,dwProcessID.if eaxmov hProcess,eax ;******************************************************************** ; 在進程中分配空間并將執(zhí)行代碼拷貝過去,然后創(chuàng)建一個遠程線程 ;********************************************************************invoke VirtualAllocEx,hProcess,NULL,REMOTE_CODE_LENGTH,MEM_COMMIT,PAGE_EXECUTE_READWRITE.if eaxmov lpRemoteCode,eaxinvoke WriteProcessMemory,hProcess,lpRemoteCode,\offset REMOTE_CODE_START,REMOTE_CODE_LENGTH,NULLinvoke WriteProcessMemory,hProcess,lpRemoteCode,\ ;遠程代碼及數(shù)據(jù)放在當(dāng)前進程的代碼段,不能修改本地的代碼段offset lpLoadLibrary,sizeof dword * 3,NULL ;應(yīng)該去遍歷目標(biāo)進程這三個函數(shù)。mov eax,lpRemoteCodeadd eax,offset _RemoteThread - offset REMOTE_CODE_STARTinvoke CreateRemoteThread,hProcess,NULL,0,eax,0,0,NULLinvoke CloseHandle,eax.endifinvoke CloseHandle,hProcess.elseinvoke MessageBox,NULL,addr szErrOpen,NULL,MB_OK or MB_ICONWARNING.endifinvoke ExitProcess,NULL ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>end start
門:中斷門,自陷門,任務(wù)門。
masm32.zip
copy D:\Program Files\Microsoft Visual Studio\VC98\Bin\nmake.exe to ?***\masm32\bin
相應(yīng)cmd設(shè)置臨時環(huán)境變量
@echo off
set include=f:\masm32\Include;D:\Program Files\Microsoft Visual Studio\VC98\Include;D:\Program Files\Microsoft Visual Studio\VC98\MFC\Include
set lib=f:\masm32\lib
set path=f:\masm32\bin;%path%
@echo on
\**\nmake
.model flat ? MASM自動為各段寄存器做了如下定義:
ASSUME cs:FLAT,ds:FLAT,ss:flat,es:flat,fs:error,gs:error
全部段源程序結(jié)構(gòu):
.386
.model flat,stdcall
option casemap:none
< Include 文件定義>
.stack [堆棧段大小]
.data
<一些初始化過的變量定義>
.data? ;不會占用EXE文件空間
<一些沒初始化過的變量定義>
.const
<一些常量定義>
.code
<代碼>
<開始標(biāo)號>
<其他語句>
end 開始標(biāo)號
invoke 不是80x86的偽指令,它只是MASM編譯器的偽指令,實現(xiàn)push參數(shù)和call函數(shù)名而已。
對匯編而言,所有參數(shù)和返回值 只有一個dword類型,所以要么是簡單類型,要么是指針。
返回值放在eax中
函數(shù)名 proto [距離] [語言] [參數(shù)1]:數(shù)據(jù)類型,[參數(shù)2]:數(shù)據(jù)類型,....
proto:函數(shù)聲明偽指令
距離:NEAR,FAR...(WIN32只有只有一個平坦的段,無所謂距離,所以忽略)
語言:.model定義的默認值
對于WIN32它只關(guān)注參數(shù)個數(shù),參數(shù)名為是提高可讀性
MessageBox Proto hWnd:dword,lpText:dword,lpCaption:dword,uType:dword
MessageBox Proto ?:dword,:dword,:dword,:dword ?
其實這兩定義是一樣的
只有windows NT才完全支持Unicode,
if UNICODE
MessageBox equ <MessageBoxW>
else
MessageBox equ <MessageBoxA>
endif
//@@做標(biāo)號
@F本指令后第一個@@標(biāo)號,@B本指令前的第一個@@標(biāo)號
如果要定義兩個字符串"hello,world!",和"hello agin",則每個字符串后跟回車和換行符,最后以一個0字符結(jié)尾,
szText db 'hello,world!',0dh,0ah,'hello agin',0dh,0ah,0
.data? 后面的默認是0,不是隨機的 ?//與這全局變量不同,local后的局部變量起始值是隨機的
MASM用local偽指令來定義局部變量,local偽指令必須proc偽指令后,其他指令開始前。因為變量數(shù)量要早確定下來
結(jié)構(gòu)構(gòu)成員引用:
1: mov eax,strutname.lpfn
2: mov esi,offset strutname
mov eas,[esi+STRUTNAME.lpfn]
3: mov esi,offset strutname
assume esi:ptr STRUTNAME
mov eax,[esi].lpfn
...
assume esi:nothing
.data
bTest1 db 12h
wTest2 dw 1234h
mov ax,bTest1 ;ax = 3412h
movzx ax,bText1 ;ax = 0012h movsx:帶符號擴展
sizeof/lengthof偽指令
如果hello world分兩行定義:
szHello db 'hello',odh,oah
db 'world',0
sizeof szHello為7,原因masm中變量只認一行,db 'world',0 實際上是沒有名稱的數(shù)據(jù)定義。
獲取變量地址:
全局變量:mov 寄存器,offset 變量名 ;編譯時
局部變量:lea ? ?寄存器,[ebp-4] ;運行時
參數(shù)局部變量:addr 參數(shù)變量
對局部變量取地址的時候,addr偽操作只能用在invoke的參數(shù)中,addr實際是先取地址到eax,再代替到參數(shù)里
invoke Test,eax,addr szHello ;錯誤
翻譯如下:
lea eax,addr szHello
push eax
push eax ;已經(jīng)被上面覆蓋
call Test
invoke Test,addr szHello,eax ;正確
子程序的定義:
子程序名 ?proc [...][...][VARARG]
local 局部變量列表
指令
子程序名 endp
proc后的參數(shù)列表中參數(shù)不能和全局變量及子程序中局部變量重名,VARARG指些子程序是可變參數(shù);proto為聲明,如上
調(diào)用約定有:C, SysCall,StdCall,BASIC,FORTRAN,PASCAL具體找度娘
條件測試語句:==, != , >,>=,<,<=,&,!,&&,||
限制:左邊只能是變量或者寄存器,不能是常量;
表達式兩邊不能同時為變量,但可以同時為寄存器。
分支語句:.if/.elseif/.else/.endif,如果不加點,則變成條件匯編偽操作
循環(huán)語句:
.while ?條件測試表達式
指令
[.break [.if 退出條件]]
[.continue]
.endw
或者
.repeat
指令
[.break [.if 退出條件]]
[.continue]
.until 條件測試表達式 (或.untilcxz [條件測試表達式])
上面的相當(dāng)while循環(huán),下面的相當(dāng)do...while循環(huán)
代碼規(guī)范:
參數(shù)用_開頭,局部變量用@開頭,內(nèi)部子程序用_開頭
盡量不要用宏定義,以免影響可讀性
子程序規(guī)模不要太大,注釋寫好,指針安全檢查,做好子程序庫以備未來編寫大程序。
第四章:第一個窗口程序
模塊句柄在數(shù)值上等于程序在內(nèi)存中裝入的起始地址,GetMododuleHandle,模 塊句柄便于訪問程度中的各種資源。
postmessage/sendmessage:
當(dāng)消息中用到指針時,postmessage函數(shù)來發(fā)送的消息都不會成功。
10.1.4
windows的“堆”分為默認堆和私有堆兩種。默認堆是在程序初始化時由OS自動創(chuàng)建的,所有的標(biāo)準(zhǔn)的內(nèi)存管理函數(shù)都是在默認堆中申請內(nèi)存的;而私有堆相當(dāng)于是在默認堆中保留了一大塊內(nèi)存,
默認堆只有一個私有堆可以有多個,默認堆可以直接使用,而私有堆必須先創(chuàng)建。
如果多個模塊在默認堆中使用內(nèi)存會交叉排序,一個模塊越界可以很難找到問題,如果多個模塊在各自的私有堆,越界更容易定位。
私有堆創(chuàng)建函數(shù)heapcreate/heapdestory
私有堆中分配和釋放內(nèi)存塊heapalloc/heaplock/....
在程序運行的時候,進程中每個地址都可以牌下列3種狀態(tài)的1種中:
占用狀態(tài):線程地址已映射物理內(nèi)存,也稱已提交狀態(tài)
自由狀態(tài):沒有映射到物理內(nèi)存,線程地址沒有被使用 //進程剛開始的起始狀態(tài)
保留狀態(tài):雖然沒有映射到物理內(nèi)存,但它不會被使用,直到希望使用他為止
當(dāng)使用上面的標(biāo)準(zhǔn)內(nèi)存管理函數(shù)時,用戶無法指定內(nèi)存位于哪個線程地址,使用virtual開頭的虛擬內(nèi)存管理函數(shù)可以做到這一點。如virtualalloc
VirtualAllocEx/CreateRemoteThread相比 Virtualalloc/createthread多了個hprocess,針對相應(yīng)進程操作
virtualallocex需要對相應(yīng)進程有process_vm_operation權(quán)限
?
遠程線程存在:重定位和函數(shù)的導(dǎo)入問題
對高級語言不可能解決重定位問題,因為沒辦法在機器碼級別上操作,c語言也沒有辦法,通過注入dll繞過去,因為裝載DLL會自動重定位
dwVar dd ?
call @F
@@:
pop ebx
sub ebx,offset @B
mov eax,[ebx+offset dwVar]
:00401000 00000000 BYTE 4 DUP(0)
:00401004 EB00000000 call 00401009
:00401009 5B pop ebx
:0040100A 81EB09104000 sub ebx,00401009
:00401010 8B8300104000 mov eax, dword ptr [ebx+00401000]
當(dāng)這段代碼移動00401000的位置時如下:
:00801000 00000000 BYTE 4 DUP(0)
:00801004 EB00000000 call 00801009
:00801009 5B pop ebx //此時ebx為:00801009
:0080100A 81EB09104000 sub ebx,00401009
:00801010 8B8300104000 mov eax, dword ptr [ebx+00401000]
遠程代碼用的win32 api,api又存在于是dll中,同時dll裝載基地不同,api函數(shù)地址也不同,所以手動完成:
1. loadlibary 使用的dll
2. getprocaddress api函數(shù)
其中1,2用到dll名字和api函數(shù)名都要采用上面重定位的方法保存好
遠程線程創(chuàng)建步驟:
1.VirtualAllocEx申請目標(biāo)進程的一塊內(nèi)存, 要有hProcess有 PROCESS_VM_OPERATION, 內(nèi)存塊應(yīng)該有PAGE_EXECUTE_READWRITE屬性
2.writeProcessMemory寫入代碼及數(shù)據(jù)
3.CreateRemoteThread ? 要hProcess有PROCESS_CREATE_THREAD權(quán)限 //remotethread code and data ; RemoteCode.asm ; 一段自定位的代碼,可以用來創(chuàng)建一個窗口 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> REMOTE_CODE_START equ this byte_lpLoadLibrary dd ? ;導(dǎo)入函數(shù)地址表 _lpGetProcAddress dd ? _lpGetModuleHandle dd ?_lpDestroyWindow dd ? _lpPostQuitMessage dd ? _lpDefWindowProc dd ? _lpLoadCursor dd ? _lpRegisterClassEx dd ? _lpCreateWindowEx dd ? _lpShowWindow dd ? _lpUpdateWindow dd ? _lpGetMessage dd ? _lpTranslateMessage dd ? _lpDispatchMessage dd ?_hInstance dd ? _hWinMain dd ? _szClassName db 'RemoteClass',0 _szCaptionMain db 'RemoteWindow',0 _szDllUser db 'User32.dll',0 _szDestroyWindow db 'DestroyWindow',0 _szPostQuitMessage db 'PostQuitMessage',0 _szDefWindowProc db 'DefWindowProcA',0 _szLoadCursor db 'LoadCursorA',0 _szRegisterClassEx db 'RegisterClassExA',0 _szCreateWindowEx db 'CreateWindowExA',0 _szShowWindow db 'ShowWindow',0 _szUpdateWindow db 'UpdateWindow',0 _szGetMessage db 'GetMessageA',0 _szTranslateMessage db 'TranslateMessage',0 _szDispatchMessage db 'DispatchMessageA',0,0 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _RemoteThread proc uses ebx edi esi lParamlocal @hModulecall @F@@:pop ebxsub ebx,offset @B ;********************************************************************_invoke [ebx + _lpGetModuleHandle],NULLmov [ebx + _hInstance],eaxlea eax,[ebx + offset _szDllUser]_invoke [ebx + _lpGetModuleHandle],eaxmov @hModule,eaxlea esi,[ebx + offset _szDestroyWindow]lea edi,[ebx + offset _lpDestroyWindow].while TRUE_invoke [ebx + _lpGetProcAddress],@hModule,esimov [edi],eaxadd edi,4@@:lodsbor al,aljnz @B.break .if ! byte ptr [esi].endw ;********************************************************************call _WinMainret_RemoteThread endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _ProcWinMain proc uses ebx edi esi,hWnd,uMsg,wParam,lParamcall @F@@:pop ebxsub ebx,offset @B ;********************************************************************mov eax,uMsg.if eax == WM_CLOSE_invoke [ebx + _lpDestroyWindow],hWnd_invoke [ebx + _lpPostQuitMessage],NULL ;********************************************************************.else_invoke [ebx + _lpDefWindowProc],hWnd,uMsg,wParam,lParamret.endif ;********************************************************************xor eax,eaxret_ProcWinMain endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _ZeroMemory proc _lpDest,_dwSizepush edimov edi,_lpDestmov ecx,_dwSizexor eax,eaxcldrep stosbpop ediret_ZeroMemory endp ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> _WinMain proc uses ebx esi edi _lParamlocal @stWndClass:WNDCLASSEXlocal @stMsg:MSGcall @F@@:pop ebxsub ebx,offset @B ;********************************************************************invoke _ZeroMemory,addr @stWndClass,sizeof @stWndClass_invoke [ebx + _lpLoadCursor],0,IDC_ARROWmov @stWndClass.hCursor,eaxpush [ebx + _hInstance]pop @stWndClass.hInstancemov @stWndClass.cbSize,sizeof WNDCLASSEXmov @stWndClass.style,CS_HREDRAW or CS_VREDRAWlea eax,[ebx + offset _ProcWinMain]mov @stWndClass.lpfnWndProc,eaxmov @stWndClass.hbrBackground,COLOR_WINDOW + 1lea eax,[ebx + offset _szClassName]mov @stWndClass.lpszClassName,eaxlea eax,@stWndClass_invoke [ebx + _lpRegisterClassEx],eax ;******************************************************************** ; 建立并顯示窗口 ;********************************************************************lea eax,[ebx + offset _szClassName]lea ecx,[ebx + offset _szCaptionMain]_invoke [ebx + _lpCreateWindowEx],WS_EX_CLIENTEDGE,eax,ecx,\WS_OVERLAPPEDWINDOW,\100,100,600,400,\NULL,NULL,[ebx + _hInstance],NULLmov [ebx + _hWinMain],eax_invoke [ebx + _lpShowWindow],[ebx + _hWinMain],SW_SHOWNORMAL_invoke [ebx + _lpUpdateWindow],[ebx + _hWinMain] ;******************************************************************** ; 消息循環(huán) ;********************************************************************.while TRUElea eax,@stMsg_invoke [ebx + _lpGetMessage],eax,NULL,0,0.break .if eax == 0lea eax,@stMsg_invoke [ebx + _lpTranslateMessage],eaxlea eax,@stMsg_invoke [ebx + _lpDispatchMessage],eax.endwret_WinMain endp REMOTE_CODE_END equ this byte REMOTE_CODE_LENGTH equ offset REMOTE_CODE_END - offset REMOTE_CODE_START ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> //createremotethread code ; RemoteThread.asm ; 向 Explorer.exe 進程中嵌入一段遠程執(zhí)行的代碼 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 使用 nmake 或下列命令進行編譯和鏈接: ; ml /c /coff RemoteThread.asm ; rc RemoteThread.rc ; Link /subsystem:windows RemoteThread.obj RemoteThread.res ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.386.model flat, stdcalloption casemap :none ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; Include 文件定義 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> include windows.inc include user32.inc includelib user32.lib include kernel32.inc includelib kernel32.lib include Macro.inc ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> ; 數(shù)據(jù)段 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.data? lpLoadLibrary dd ? lpGetProcAddress dd ? lpGetModuleHandle dd ? dwProcessID dd ? dwThreadID dd ? hProcess dd ? lpRemoteCode dd ?.const szErrOpen db '無法打開遠程線程!',0 szDesktopClass db 'Progman',0 szDesktopWindow db 'Program Manager',0 szDllKernel db 'Kernel32.dll',0 szLoadLibrary db 'LoadLibraryA',0 szGetProcAddress db 'GetProcAddress',0 szGetModuleHandle db 'GetModuleHandleA',0 ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>.code ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>include RemoteCode.asmstart:invoke GetModuleHandle,addr szDllKernelmov ebx,eaxinvoke GetProcAddress,ebx,offset szLoadLibrarymov lpLoadLibrary,eaxinvoke GetProcAddress,ebx,offset szGetProcAddressmov lpGetProcAddress,eaxinvoke GetProcAddress,ebx,offset szGetModuleHandlemov lpGetModuleHandle,eax ;******************************************************************** ; 查找文件管理器窗口并獲取進程ID,然后打開進程 ;********************************************************************invoke FindWindow,addr szDesktopClass,addr szDesktopWindowinvoke GetWindowThreadProcessId,eax,offset dwProcessIDmov dwThreadID,eaxinvoke OpenProcess,PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or \PROCESS_VM_WRITE,FALSE,dwProcessID.if eaxmov hProcess,eax ;******************************************************************** ; 在進程中分配空間并將執(zhí)行代碼拷貝過去,然后創(chuàng)建一個遠程線程 ;********************************************************************invoke VirtualAllocEx,hProcess,NULL,REMOTE_CODE_LENGTH,MEM_COMMIT,PAGE_EXECUTE_READWRITE.if eaxmov lpRemoteCode,eaxinvoke WriteProcessMemory,hProcess,lpRemoteCode,\offset REMOTE_CODE_START,REMOTE_CODE_LENGTH,NULLinvoke WriteProcessMemory,hProcess,lpRemoteCode,\ ;遠程代碼及數(shù)據(jù)放在當(dāng)前進程的代碼段,不能修改本地的代碼段offset lpLoadLibrary,sizeof dword * 3,NULL ;應(yīng)該去遍歷目標(biāo)進程這三個函數(shù)。mov eax,lpRemoteCodeadd eax,offset _RemoteThread - offset REMOTE_CODE_STARTinvoke CreateRemoteThread,hProcess,NULL,0,eax,0,0,NULLinvoke CloseHandle,eax.endifinvoke CloseHandle,hProcess.elseinvoke MessageBox,NULL,addr szErrOpen,NULL,MB_OK or MB_ICONWARNING.endifinvoke ExitProcess,NULL ;>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>end start
總結(jié)
以上是生活随笔為你收集整理的win32 masm32 汇编学习 及 远程线程实例的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: PE学习(四)第四章:导入表
- 下一篇: PE学习(五)导出表,编写DLL及查看D