彙編語言(assembly language)是一種用於電子計算機、微處理器、微控制器或其餘可編程器件的低級語言,亦稱爲符號語言.在彙編語言中,用助記符(Mnemonics)代替機器指令的操做碼,用地址符號(Symbol)或標號(Label)代替指令或操做數的地址.在不一樣的設備中,彙編語言對應着不一樣的機器語言指令集,經過彙編過程轉換成機器指令,廣泛地說,特定的彙編語言和特定的機器語言指令集是相互對應的,不一樣平臺之間不可直接移植.python
熟練掌握Win32 API函數的參數傳遞,是軟件逆向的基礎,本章節內容將使用MASM彙編器,逐個編譯這些源程序,你能夠經過使用一些調試工具,這裏推薦OllyDBG來附加編譯後的可執行文件,進行逐個分析,觀察二進制程序逆向後的一些變化,總結吸取經驗,爲之後的二進制逆向,漏洞挖掘打基礎.shell
註冊熱鍵: 註冊全局熱鍵並能激活.編程
.data hMsgBox db "你按下了 CTRL + ALT + A",0h uMsg MSG <?> .code main PROC ; 41h = A | 65h=uMsg.wParam invoke RegisterHotKey,NULL,065h,MOD_CONTROL or MOD_ALT,041h .while(TRUE) invoke GetMessage,addr uMsg,NULL,0,0 .if(uMsg.message == WM_HOTKEY) ; 按下按鍵提示 invoke MessageBox,NULL,addr hMsgBox,addr uMsg.wParam,MB_OK .elseif(uMsg.message == WM_DESTROY) ; 程序結束後關閉熱鍵 invoke UnregisterHotKey,NULL,065h invoke PostQuitMessage,NULL .endif .endw invoke ExitProcess,0 main ENDP END main
最小化指定窗口:windows
.data FindName db "qq",0h handle dd ? .code main PROC invoke FindWindow,NULL,addr FindName mov handle,eax .if(handle != 0) ; 找到則隱藏窗口 invoke ShowWindow,handle,SW_HIDE .else ; 沒有找到則顯示 invoke ShowWindow,handle,SW_SHOW .endif invoke ExitProcess,0 main ENDP END main
顯示當前目錄等:api
.data stStartUp STARTUPINFO <?> .code main PROC invoke GetStartupInfo,addr stStartUp mov eax,stStartUp.lpDesktop mov eax,stStartUp.lpTitle ; 顯示當前軟件目錄 invoke ExitProcess,0 main ENDP END main
取系統版本等:網絡
.data version OSVERSIONINFO <?> lpsystem SYSTEM_INFO <?> .code main PROC invoke GetSystemInfo,addr lpsystem mov ax,lpsystem.wProcessorArchitecture invoke GetVersionEx,addr version mov eax,version.dwBuildNumber invoke ExitProcess,0 main ENDP END main
取命令行參數:app
.data cmdline dword ? .code main PROC invoke GetCommandLine ; 獲取命令行參數 mov cmdline,eax invoke ExitProcess,0 main ENDP END main
獲取環境變量:socket
.data szBuffer DB 200 dup(?) ; 保存到緩衝區 szVarName DB "PATH",0h ; 獲取set PATH lpVar DD ? .code main PROC invoke GetEnvironmentVariable,addr szVarName,addr szBuffer,sizeof szBuffer xor eax,eax invoke GetEnvironmentStrings mov lpVar,eax invoke ExitProcess,0 main ENDP END main
設置環境變量:函數
.data lpVarName DB "PATH",0h lpValue DB "E:\RadASM\masm32\bin",0h .code main PROC invoke SetEnvironmentVariable,addr lpVarName,addr lpValue invoke ExitProcess,0 main ENDP END main
運行系統軟件: 下載並運行一個軟件.工具
include urlmon.inc includelib urlmon.lib .data szURL DB "https://www.mkdirs.com/lyshark.exe",0h szFileName DB "C:\\lyshark.exe",0h WinRun DB "C:/lyshark.exe",0h .code main proc invoke URLDownloadToFile,NULL,addr szURL,addr szFileName,0,NULL invoke WinExec,offset WinRun,SW_SHOW ret main endp end main
獲取本地時間:
.data systime SYSTEMTIME <> .code main PROC invoke GetLocalTime,addr systime ; 獲取當前時間 mov ax,systime.wYear mov bx,systime.wMonth mov cx,systime.wDay invoke SetLocalTime,addr systime ; 設置當前時間 main ENDP END main
獲取系統時間:
.data systime SYSTEMTIME <> .code main PROC invoke GetSystemTime,addr systime mov ax,systime.wYear mov bx,systime.wMonth mov cx,systime.wDay invoke SetSystemTime,addr systime main ENDP END main
獲取時間差: eax保存的就是執行代碼後的時間差,單位毫秒
.data dwTock DWORD ? .code main PROC invoke GetTickCount mov dwTock,eax invoke GetTickCount sub eax,dwTock main ENDP END main
獲取內存狀態: GlobalMemourStatus
.data Mem MEMORYSTATUS <> .code main PROC invoke GlobalMemoryStatus,offset Mem mov eax,Mem.dwLength ; 獲取結構長度 mov eax,Mem.dwMemoryLoad ; 已用內存百分比 mov eax,Mem.dwTotalPhys ; 物理內存總數 mov eax,Mem.dwAvailPhys ; 可用物理內存 mov eax,Mem.dwTotalPageFile ; 交換文件的總大小 mov eax,Mem.dwAvailPageFile ; 交換文件可用大小 mov eax,Mem.dwTotalVirtual ; 用戶可用的地址空間 mov eax,Mem.dwAvailVirtual ; 用戶空閒地址空間 invoke ExitProcess,0 main ENDP END main
申請內存:
.data lpMemory DWORD ? .code main PROC ;GMEM_FIXED=申請內存;GMEM_ZEROINIT申請並初始化爲0 invoke GlobalAlloc,GMEM_ZEROINIT,1024 .if(eax != NULL) mov lpMemory,eax ; lpMemory 爲分配成功後的內存指針 .endif invoke GlobalFree,lpMemory ; 釋放內存空間 invoke ExitProcess,0 main ENDP END main
擴大內存空間:
.data lpMemory DWORD ? reMemory DWORD ? .code main PROC invoke GlobalAlloc,GMEM_ZEROINIT,100 mov lpMemory,eax invoke GlobalReAlloc,lpMemory,1024,GMEM_ZEROINIT or GMEM_MOVEABLE .if(eax != NULL) mov reMemory,eax .endif invoke GlobalFree,lpMemory invoke GlobalFree,reMemory invoke ExitProcess,0 main ENDP END main
鎖定/解鎖內存: 程序須要使用這塊內存能夠將其鎖定,使用完後能夠解除鎖定.
.data lpMemory DWORD ? Locks DWORD ? .code main PROC invoke GlobalAlloc,GMEM_ZEROINIT,100 mov lpMemory,eax invoke GlobalLock,lpMemory ; 鎖定內存空間 .if(eax != NULL) mov Locks,eax ; 鎖定成功後,返回原內存地址 .endif invoke GlobalUnlock,lpMemory ; 解鎖內存空間,成功返回非0 invoke ExitProcess,0 main ENDP END main
可移動/可丟棄內存: 可移動內存容許在不使用時改變其內存地址,可丟棄當內存不足時可將其丟棄。
.data lp_Move_Memory DWORD ? lp_Disb_Memory DWORD ? .code main PROC invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,1024 ; 分配可移動的內存 .if(eax != NULL) mov lp_Move_Memory,eax ; 分配成功則保存其內存地址 .endif invoke GlobalAlloc,GMEM_DISCARDABLE or GMEM_ZEROINIT,1024 ; 分配可丟棄的內存 .if(eax != NULL) mov lp_Disb_Memory,eax .endif invoke ExitProcess,0 main ENDP END main
複製內存地址: 將源地址複製到目標地址中,總共複製40個字節.
.data Source DWORD 1,2,3,4,5 DWORD 6,7,8,9,0 Dest DWORD 0,0,0,0,0 DWORD 0,0,0,0,0 .code main PROC lea eax,Source ; 源地址 lea ebx,Dest ; 目標地址 invoke RtlMoveMemory,addr Dest,addr Source,40 ;將源地址複製到目標地址,複製40個字節 invoke ExitProcess,0 main ENDP END main
填充內存: 將Memory中的字節數據,所有填充替換爲A,或填充爲0
.data Memory DB 1,2,3,4,5,6,7,8,9,0 DB 1,2,3,4,5,6,7,8,9,0 DB 1,2,3,4,5,6,7,8,9,0 Fill DB "A",0 .code main PROC lea eax,Memory ; 填充Memory內存,向後填充1024字節,填充爲A invoke RtlFillMemory,addr Memory,1024,addr Fill ;填充Memory內存,向後填充1024字節,所有初始化爲0 invoke RtlZeroMemory,addr Memory,1024 invoke ExitProcess,0 main ENDP END main
建立私有堆: 建立一個1024字節的私有堆,並返回內存地址.
.data HeapMain DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,1024,0 ; 保留1024字節物理內存 .if(eax != NULL) mov HeapMain,eax ; 成功分配則返回內存地址 .endif invoke HeapDestroy,HeapMain ; 釋放堆空間 invoke ExitProcess,0 main ENDP END main
分配內存塊: 在建立的堆中分配內存塊.
.data lpHeap DWORD ? lpMem DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,1024,0 ; 保留1024字節物理內存 mov lpHeap,eax ; 保存分配的地址 invoke HeapAlloc, lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字節空間 .if(eax != NULL) mov lpMem,eax ; 分配成功,保存內存地址 .endif invoke HeapDestroy,lpHeap ; 釋放堆空間 invoke ExitProcess,0 main ENDP END main
在堆中分配內存:
.data lpHeap DWORD ? lpMemory DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,1024,0 ; 建立堆句柄,並保留1024字節 mov lpHeap,eax ; 保存分配句柄地址 invoke HeapAlloc,lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字節的地址 mov lpMemory,eax ; 分配並返回內存地址 invoke HeapDestroy,lpHeap ; 釋放堆空間 invoke ExitProcess,0 main ENDP END main
增長堆內存空間: 在本來來的內存地址基礎上,增長內存空間
.data lpHeap DWORD ? lpMemory DWORD ? ReMemory DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,4096,0 ; 建立堆句柄,並保留4096字節 mov lpHeap,eax ; 保存分配句柄地址 invoke HeapAlloc,lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字節的地址 mov lpMemory,eax ; 分配並返回內存地址 ; 從新分配內存空間,在原內存1024上調整到2048 invoke HeapReAlloc,lpHeap,HEAP_ZERO_MEMORY,lpMemory,2048 mov ReMemory,eax ; 保存返回內存地址 invoke HeapDestroy,lpHeap ; 釋放堆空間 invoke ExitProcess,0 main ENDP END main
計算堆空間大小:
.data lpHeap DWORD ? lpMemory DWORD ? Mem_Size DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,4096,0 ; 建立堆句柄,並保留4096字節 mov lpHeap,eax ; 保存分配句柄地址 invoke HeapAlloc,lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字節的地址 mov lpMemory,eax ; 分配並返回內存地址 invoke HeapSize,lpHeap,HEAP_NO_SERIALIZE,lpMemory ; 計算堆空間的大小 mov Mem_Size,eax ; 取地址大小,此處爲1024 invoke HeapDestroy,lpHeap ; 釋放堆空間 invoke ExitProcess,0 main ENDP END main
鎖定/解鎖堆:
.data lpHeap DWORD ? lpMemory DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,4096,0 ; 建立堆句柄,並保留4096字節 mov lpHeap,eax ; 保存分配句柄地址 invoke HeapAlloc,lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字節的地址 mov lpMemory,eax ; 分配並返回內存地址 invoke HeapLock,lpHeap ; 鎖定內存堆 invoke HeapUnlock,lpHeap ; 解鎖內存堆 invoke HeapDestroy,lpHeap ; 釋放堆空間 invoke ExitProcess,0 main ENDP END main
保留地址空間: 保留的空間不能夠直接使用.
.data lpAddr DWORD ? .code main PROC invoke VirtualAlloc,NULL,1024,MEM_RESERVE,PAGE_NOACCESS ; 保留內存地址 mov lpAddr,eax invoke VirtualFree,lpAddr,1024,MEM_RELEASE ; 釋放地址空間 invoke ExitProcess,0 main ENDP END main
分配地址空間:
.data lpAddr DWORD ? .code main PROC invoke VirtualAlloc,NULL,1024,MEM_COMMIT,PAGE_READWRITE ; 分配內存地址 .if(eax != NULL) mov lpAddr,eax .endif invoke VirtualFree,lpAddr,1024,MEM_RELEASE ; 釋放內存地址 invoke ExitProcess,0 main ENDP END main
保護/鎖定內存:
.data lpAddr DWORD ? .code main PROC invoke VirtualAlloc,NULL,1024,MEM_COMMIT,PAGE_READWRITE ; 保留內存地址 .if(eax != NULL) mov lpAddr,eax .endif invoke VirtualProtect,lpAddr,1024,PAGE_NOACCESS,NULL ; 設置內存爲只讀 invoke VirtualLock,lpAddr,1024 ; 鎖定內存地址 invoke VirtualUnlock,lpAddr,1024 ; 解除內存鎖定 invoke VirtualFree,lpAddr,1024,MEM_RELEASE ; 釋放地址空間 invoke ExitProcess,0 main ENDP END main
內存狀態測試:
.data lpMemory DWORD 1024 lpString BYTE "hello lyshark",0 lpStatus DWORD ? .code main PROC mov lpMemory,1024 lea eax,lpMemory invoke IsBadCodePtr,lpMemory ; 內存的第一個字節是否可讀 mov lpStatus,eax ; 可讀返回0不然返回非0 invoke IsBadReadPtr,lpMemory,1024 ; 測試前1024字節是否可讀 mov lpStatus,eax ; 可讀返回0不然返回非0 invoke IsBadWritePtr,lpMemory,1024 ; 測試前1024字節是否可寫 mov lpStatus,eax ; 可寫返回0不然返回非0 invoke IsBadStringPtr,addr lpString,sizeof lpString ; 測試字符串是否可讀 mov lpStatus,eax ; 可讀返回0不然返回非0 invoke ExitProcess,0 main ENDP END main
打開/關閉文件: 打開文件成功返回文件句柄,失敗則返回error
.data szFileName db "e:\lyshark.log",0h ; 打開的文件名稱 hFile dd ? ; 打開成功後返回的句柄 .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0, \ OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFile,eax .endif invoke ExitProcess,0 main ENDP END main
建立文件: CREATE_ALWAYS=文件存在則清空內容,CREATE_NEW=文件存在則返回失敗
.data szNewFile db "C:\lyshark.log",0h hFile dd ? .code main PROC invoke CreateFile,addr szNewFile,GENERIC_WRITE,FILE_SHARE_READ,0, \ CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFile,eax .endif invoke CloseHandle,hFile invoke ExitProcess,0 main ENDP END main
移動文件指針:
.data szFileName DB "c:\lyshark.log",0h hFileHandl DD ? .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFileHandl,eax .endif invoke SetFilePointer,hFileHandl,0,NULL,FILE_CURRENT ; eax=獲取的文件指針位置 xor eax,eax invoke SetFilePointer,hFileHandl,10,NULL,FILE_BEGIN ; 將文件指針向後移動10個字節 xor eax,eax invoke SetFilePointer,hFileHandl,0,NULL,FILE_CURRENT ; 再次獲取指針位置,eax=10 invoke ExitProcess,0 main ENDP END main
設置指針到末尾:
.data szFileName DB "e:\lyshark.log",0h hFileHandl DD ? .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFileHandl,eax .endif invoke SetEndOfFile,hFileHandl ; 將文件位置設置到末尾 invoke SetFilePointer,hFileHandl,0,NULL,FILE_CURRENT ; 獲取指針位置 invoke ExitProcess,0 main ENDP END main
讀取文件內容:
.data szFileName DB "C:\lyshark.log",0h hFileHandle DD ? szReadBuff DB ? ; 每次讀取一個字節,放入該變量中 ByteRead DB ? .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFileHandle,eax .endif invoke SetFilePointer,hFileHandle,1,NULL,FILE_BEGIN ; 取第一個字符 invoke ReadFile,hFileHandle,addr szReadBuff,sizeof szReadBuff,addr ByteRead,0 mov al,[szReadBuff] ; 將取出來的字符放入al寄存器中 invoke ExitProcess,0 main ENDP END main
寫入文件內容:
.data szFileName DB "C:\lyshark.log",0h hFileHandle DD ? ; 獲取文件句柄 lpBuffer DB "hello lyshark",0h ; 要寫入的字符串 reWrite DD ? ; 返回寫入成功字節數 .code main PROC invoke CreateFile,addr szFileName,GENERIC_WRITE,FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFileHandle,eax .endif ; 將lpBuffer中的數據寫入到文件,寫入大小爲sizeof獲取的大小. invoke WriteFile,hFileHandle,addr lpBuffer,sizeof lpBuffer,addr reWrite,NULL invoke FlushFileBuffers,hFileHandle ; 強制刷新寫入 invoke ExitProcess,0 main ENDP END main
獲取文件長度:
.data szFileName DB "E:\lyshark.log",0h hFileHandle DD ? FilesSize DD ? .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 mov hFileHandle,eax invoke GetFileSize,hFileHandle,NULL ; 取出文件的長度 mov FilesSize,eax ; 放入FilesSize裏面 invoke ExitProcess,0 main ENDP END main
獲取文件日期:
.data szFileName DB "E:\lyshark.log",0h hFileHandle DD ? create FILETIME <> ; 存儲建立文件的日期 systime SYSTEMTIME <> ; 存儲轉換後的文件日期 .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 mov hFileHandle,eax ; 取出文件句柄 invoke GetFileTime,hFileHandle,addr create,NULL,NULL ; 只取出建立日期,其餘的用NULL填充 invoke FileTimeToSystemTime,addr create,addr systime ; 轉換成經常使用格式 mov ax,systime.wYear ; 取出年份 mov bx,systime.wMonth ; 取出月份 mov cx,systime.wDay ; 取出天數 invoke ExitProcess,0 main ENDP END main
修改文件日期:
.data szFileName DB "E:\lyshark.log",0h hFileHandle DD ? create FILETIME <> ; 存儲建立文件的日期 systime SYSTEMTIME <> ; 存儲轉換後的文件日期 .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 mov hFileHandle,eax ; 取出文件句柄 mov systime.wYear,19 ; 先填寫結構 mov systime.wMonth,19 invoke SystemTimeToFileTime,addr systime,addr create ; 轉換成filetime invoke SetFileTime,hFileHandle,addr create,NULL,NULL ; 回寫 invoke ExitProcess,0 main ENDP END main
拷貝/移動/刪除/文件:
.data lpSourceFile DB "C:\lyshark.log",0h lpDestFile DB "E:\wang.log",0h .code main PROC invoke CopyFile,addr lpSourceFile,addr lpDestFile,TRUE ; 拷貝文件 invoke MoveFile,addr lpDestFile,addr lpSourceFile ; 移動文件 invoke DeleteFile,addr lpSourceFile invoke DeleteFile,addr lpDestFile ; 刪除文件 invoke ExitProcess,0 main ENDP END main
顯示全部驅動器:
.data lpLength BYTE ? lpDrives DWORD 0 dup(1024) .code main PROC invoke GetLogicalDrives ; 獲取卷標 invoke GetLogicalDriveStrings,addr lpLength,addr lpDrives ; 同上 lea esi,[lpDrives] ; 顯示C盤 lea esi,[lpDrives+4] ; 顯示D盤 invoke ExitProcess,0 main ENDP END main
獲取磁盤類型:
.data lpDrive DB "c:\",0 .code main PROC invoke GetDriveType,addr lpDrive invoke ExitProcess,0 main ENDP END main
獲取磁盤詳細信息:(有問題的)
.data lpRoot DB "c:\",0h lpBuffer DB 1024 dup(?) dwSerial DD ? lpType DB 1024 dup(?) .code main PROC invoke GetVolumeInformation,addr lpRoot, \ addr lpBuffer,1024,addr dwSerial,255, \ FILE_CASE_PRESERVED_NAMES,addr lpType,1024 lea eax,lpRoot lea ebx,lpBuffer lea ecx,dwSerial lea edx,lpType invoke ExitProcess,0 main ENDP END main
檢測邏輯驅動器字節:
.data lpRoot DB "c:\",0h lpSect DD ? lpByte DD ? lpNumb DD ? lpTota DD ? .code main PROC ; 總容量 = 簇總數 * 每簇扇區數 * 每扇區字節數 ; 空閒字節數 = 未使用的簇 * 每扇區數 * 每扇區字節數 invoke GetDiskFreeSpace,addr lpRoot,addr lpSect,addr lpByte,addr lpNumb,addr lpTota mov eax,lpSect ; 返回每一個簇的扇區數 mov eax,lpByte ; 返回每扇區的字節數 mov eax,lpNumb ; 返回未使用的簇的數量 mov eax,lpTota ; 返回簇的總數 invoke ExitProcess,0 main ENDP END main
獲取當前目錄:
.data lpRoot DB ? .code main PROC invoke GetCurrentDirectory,1024,addr lpRoot ; 獲取當前目錄 lea eax,lpRoot invoke GetTempPath,1024,addr lpRoot ; 獲取臨時目錄 lea eax,lpRoot invoke GetSystemDirectory,addr lpRoot,1024 ; 獲取系統目錄 lea eax,lpRoot invoke ExitProcess,0 main ENDP END main
建立刪除目錄:
.data lpRoot DB "c:\windows\",0 szDir DB "c:\lyshark\wang",0 .code main PROC invoke SetCurrentDirectory,addr lpRoot ; 設置默認路徑 invoke CreateDirectory,addr szDir,NULL ; 建立目錄 invoke RemoveDirectory,addr szDir ; 刪除目錄 invoke ExitProcess,0 main ENDP END main
建立進程:
.data szBuffer DWORD ? szFileName DWORD ? szCmdLine DWORD ? szBlank DWORD ? stStartUp DWORD ? stProcInfo DWORD ? .code main PROC invoke lstrcpy,addr szBuffer,addr szFileName .if(szCmdLine) invoke lstrcat,addr szBuffer,addr szBlank invoke lstrcat,addr szBuffer,addr szCmdLine .endif invoke GetStartupInfo,addr stStartUp invoke CreateProcess,NULL,addr szBuffer,NULL,NULL,NULL, \ NORMAL_PRIORITY_CLASS,NULL,NULL,addr stStrartUp,addr stProcInfo ret main ENDP END main
取全部進程信息: 使用快照函數,一次性遍歷出全部的進程列表.
.data hSnapShot dd ? stProcess PROCESSENTRY32 <?> .code main proc invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0 ; 建立快照 mov hSnapShot,eax ; 保存句柄 mov stProcess.dwSize,sizeof stProcess ; 保存快照大小 invoke Process32First,hSnapShot,addr stProcess ; 取第一個進程數據 .while(eax) ; eax!=0則繼續循環 invoke Process32Next,hSnapShot,addr stProcess ; 取下一個進程數據 .endw invoke CloseHandle,hSnapShot ; 關閉進程句柄 ret main endp end main
取指定進程PID: 獲取xshell進程的PID號
.data FindID DB "Xshell",0h ThreadID DD ? ProcessID DD ? ; 獲取到的進程號 .code main PROC invoke FindWindow,NULL,addr FindID .if(FindID != 0) mov ThreadID,eax .endif invoke GetWindowThreadProcessId, ThreadID,offset ProcessID mov eax,ProcessID ret main ENDP END main
內存示範例子: 請手動編譯該例子,並命名爲lyshark.exe
,接下來的讀內存/寫內存
例子將用它講解.
.386p .model flat,stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib .data titles DB "box",0h check_ok DB "破解完成.",0h check_err DB "破解失敗",0h .code main proc xor eax,eax .if eax invoke MessageBox,NULL,addr check_ok,addr titles,MB_OK .else invoke MessageBox,NULL,addr check_err,addr titles,MB_OK .endif ret main endp end main
讀取進程數據: 讀取指定的內存地址中的數據,並將其放入ReadBuf緩衝區中.
OEP equ 004198402 ; 讀取的範圍 .data stStartUp STARTUPINFO <> ; 初始化 stProInfo PROCESS_INFORMATION <> ; 該進程的進程信息 ExeRun DB "C:\\lyshark.exe",0h ; 要打開的進程名稱 ReadBuf DD ? ; 讀取到的數據內容 .code main proc invoke GetStartupInfo,addr stStartUp invoke CreateProcess,addr ExeRun,NULL,NULL,NULL,NULL,\ NORMAL_PRIORITY_CLASS,0,0,addr stStartUp,addr stProInfo .if(eax) ; 讀取當前進程,讀取內存地址爲OEP,每次讀取8個字節,讀取到放入ReadBuf invoke ReadProcessMemory,stProInfo.hProcess,OEP,addr ReadBuf,8,NULL lea eax,ReadBuf .endif ret main endp end main
寫入進程數據: 寫入進程數據,將跳轉替換爲nop指令的機器碼.
OEP equ 004198402 ; 讀取的範圍 .data stStartUp STARTUPINFO <> ; 初始化 stProInfo PROCESS_INFORMATION <> ; 該進程的進程信息 ExeRun DB "C:\\lyshark.exe",0h ; 要打開的進程名稱 lpPatch DB 90h,90h,90h,90h ; 要替換的彙編指令 redPatch DD ? ; 替換完後保存替換結果 .code main proc invoke GetStartupInfo,addr stStartUp invoke CreateProcess,addr ExeRun,NULL,NULL,NULL,NULL,\ NORMAL_PRIORITY_CLASS,0,0,addr stStartUp,addr stProInfo .if(eax) ; 寫入當前進程,寫入內存地址爲OEP,替換8個字節,替換成nop invoke WriteProcessMemory,stProInfo.hProcess,OEP,addr lpPatch,4,NULL .if(eax != 0) ; 若是不等於0則說明補丁替換完成 invoke ReadProcessMemory,stProInfo.hProcess,OEP,addr redPatch,4,NULL lea eax,redPatch ; 將補丁地址取出,並用OD分析,爲9090則替換完成. .endif .endif ret main endp end main
建立線程函數: 默認狀況下,線程建立後會被系統掛起,須要執行ResumeThread函數,將其放入前臺.
.data ThreadID DWORD ? ; 保存返回線程ID hThread DWORD ? ; 保存線程句柄 .code _MyThread proc lParam ; lParam爲傳遞的參數 xor eax,eax ret _MyThread endp main PROC invoke CreateThread,NULL,0,addr _MyThread,NULL,CREATE_SUSPENDED,addr ThreadID .if(eax) mov hThread,eax ; 將線程句柄放入hThread .endif invoke ResumeThread, hThread ; 運行這個線程 ret main ENDP END main
建立事件:
.data lpEventName DWORD ? ; 建立的時間名稱 hEventID DWORD ? ; 成功後返回的句柄 .code main PROC invoke CreateEvent,NULL,TRUE,TRUE,addr lpEventName .if(eax != NULL) mov hEventID,eax .endif invoke WaitForSingleObject,addr hEventID,INFINITE ; 等待一個事件 invoke SetEvent,addr hEventID ; 將事件的狀態設置爲:"置位" invoke ResetEvent,hEventID ; 將事件的狀態設置爲:"復位" invoke CloseHandle,hEventID ; 關閉這個句柄 ret main ENDP END main
建立dll: 這裏咱們建立一個lyshark.asm
.
.586 .model flat,stdcall option casemap:none include windows.inc include kernel32.inc include user32.inc includelib kernel32.lib includelib user32.lib .data lpText db "hello lyshark",0 lpCapt db "MsgBox",0 .code DllEntry PROC _hInstance,_dwReason,_dwReserved mov eax,TRUE ret DllEntry ENDP _MsgBox PROC ; 無參數的信息框 invoke MessageBox,NULL,addr lpText,addr lpCapt,MB_OK ret _MsgBox ENDP _MySum PROC Num_x:DWORD,Num_y:DWORD ; 一個加法計算的函數 mov eax,Num_x add eax,Num_y ret _MySum endp end DllEntry
建立def: 而後在當前目錄下建立一個lyshark.def
文件,用來聲明導入庫的函數名.
EXPORTS _MsgBox EXPORTS _MySum
建立inc文件: 在當前目錄繼續建立一個lyshark.inc
文件,並寫入相應的導入函數.
_MsgBox PROTO _MySum PROTO Num_X:DWORD,Num_Y:DWORD
生成dll: 生成dll執行以下代碼.
ml /c /coff lyshark.asm link /SUBSYSTEM:WINDOWS /RELEASE /DLL /DEF:lyshark.def /OUT:"lyshark.dll" "lyshark.obj"
直接調用dll:
include lyshark.inc includelib lyshark.lib .code main proc invoke _MsgBox invoke _MySum,100,200 ret main endp end main
動態裝載dll(無參):
.data szMyDll db "lyshark.dll",0h ; 裝入的動態連接庫名稱 szMsgBox db "_MsgBox",0h ; 裝入的函數名(無參) hLibMod dd ? ; dll的句柄 lpMsgBox dd ? ; 函數的地址 .code main proc invoke LoadLibrary,addr szMyDll ; 加載指定的dll .if(eax) mov hLibMod,eax invoke GetProcAddress,hLibMod,addr szMsgBox mov lpMsgBox,eax call lpMsgBox ; 調用MsgBox .endif invoke FreeLibrary,hLibMod ; 傳遞句柄,並釋放dll ret main endp end main
動態裝載dll(有參):
.data szMyDll db "lyshark.dll",0h ; 裝入的動態連接庫名稱 szMySum db "_MySum",0h ; 裝入的函數名(無參) hLibMod dd ? ; dll的句柄 lpMySum dd ? ; 函數的地址 Num_X dd 10 ; 參數x=10 Num_Y dd 20 ; 參數y=20 .code main proc invoke LoadLibrary,addr szMyDll ; 加載指定的dll .if(eax) mov hLibMod,eax invoke GetProcAddress,hLibMod,addr szMySum mov lpMySum,eax push Num_Y ; 壓入第二個參數 push Num_X ; 壓入第一個參數 call lpMySum ; 調用_MySum 函數 .endif invoke FreeLibrary,hLibMod ; 傳遞句柄,並釋放dll ret main endp end main
動態調用函數: 動態的加載並使用一個函數.
.data szDllKernel db "Kernel32.dll",0h szFunction db "GetVersion",0h CallAddr dd ? .code main proc invoke GetModuleHandle,offset szDllKernel ; 取出模塊句柄 .if(eax != 0) invoke GetProcAddress,eax,offset szFunction ; 取出函數的地址 mov CallAddr,eax ; 保存函數地址 .endif call CallAddr ; 直接調用kernel32.GetVersion ret main endp end main
編寫DLL: 首先編寫一個dLL用來測試
.386 .model flat,stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib .data szText DB "welcome to asm",0h szCaption DB "MsgBox",0h .code Main PROC invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK ret Main endp DllEntry PROC _hInstance,_dwReason,_dwReserved call Main mov eax,TRUE ret DllEntry ENDP END DllEntry
注入DLL:
.data szMyDll db "\lyshark.dll",0h ; 要注入的DLL szDllKernel db "Kernel32.dll",0h szLoadLibrary db "LoadLibraryA",0h lpFileName db "Tutorial-i386",0h ; 指定要注入進程 lpDllName dd ? .data? szMyDllFull db MAX_PATH dup (?) lpLoadLibrary dd ? dwProcessID dd ? dwThreadID dd ? hProcess dd ? .code main PROC ; 準備工做:獲取dll的全路徑文件名、獲取LoadLibrary函數地址等 invoke GetCurrentDirectory,MAX_PATH,addr szMyDllFull invoke lstrcat,addr szMyDllFull,addr szMyDll invoke GetModuleHandle,addr szDllKernel invoke GetProcAddress,eax,offset szLoadLibrary mov lpLoadLibrary,eax ; 查找文件管理器窗口並獲取進程ID,而後打開進程 invoke FindWindow,NULL,addr lpFileName invoke GetWindowThreadProcessId,eax,offset dwProcessID mov dwThreadID,eax invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessID mov hProcess,eax ; 在進程中分配空間並將DLL文件名拷貝過去,而後建立一個LoadLibrary線程 invoke VirtualAllocEx,hProcess,NULL,MAX_PATH,MEM_COMMIT,PAGE_READWRITE mov lpDllName,eax invoke WriteProcessMemory,hProcess,eax,offset szMyDllFull,MAX_PATH,NULL invoke CreateRemoteThread,hProcess,NULL,0,lpLoadLibrary,lpDllName,0,NULL ret main endp end main
注入器: 新建main.asm
.data lpLoadLibrary dd ? lpGetProcAddress dd ? lpGetModuleHandle dd ? dwProcessID dd ? dwThreadID dd ? hProcess dd ? lpRemoteCode dd ? .const ProcHandle db "lyshark.exe",0h KernelBase db "Kernel32.dll",0h szLoadLibrary db "LoadLibraryA",0h szGetProcAddress db "GetProcAddress",0h szGetModuleHandle db "GetModuleHandleA",0h .code include Macro.inc include ShellCode.asm main proc invoke GetModuleHandle,addr KernelBase mov ebx,eax invoke GetProcAddress,ebx,offset szLoadLibrary mov lpLoadLibrary,eax invoke GetProcAddress,ebx,offset szGetProcAddress mov lpGetProcAddress,eax invoke GetProcAddress,ebx,offset szGetModuleHandle mov lpGetModuleHandle,eax invoke FindWindow,NULL,addr ProcHandle invoke GetWindowThreadProcessId,eax,offset dwProcessID mov dwThreadID,eax invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessID mov hProcess,eax invoke VirtualAllocEx,hProcess,NULL,2048,MEM_COMMIT,PAGE_EXECUTE_READWRITE .if eax mov lpRemoteCode,eax invoke WriteProcessMemory,hProcess,lpRemoteCode,offset REMOTE_CODE_START,1024,NULL invoke WriteProcessMemory,hProcess,lpRemoteCode,offset lpLoadLibrary,sizeof dword * 3,NULL mov eax,lpRemoteCode add eax,offset _RemoteThread - offset REMOTE_CODE_START invoke CreateRemoteThread,hProcess,NULL,0,eax,0,0,NULL invoke CloseHandle,eax .endif invoke CloseHandle,hProcess invoke ExitProcess,NULL ret main endp end main
反轉宏: Macro.inc 用來翻轉參數,定義_invoke
; -------------------------------------------- ; 翻轉參數字節序 reverseArgs macro arglist:VARARG LOCAL txt,count txt TEXTEQU <> count=0 for i,<arglist> count = count+1 txt TEXTEQU @CatStr(i,<!,>,<%txt>) endm if count GT 0 txt SUBSTR txt,1,@SizeStr(%txt)-1 endif exitm txt endm ; -------------------------------------------- ; 建立相似於INVOKE的宏代碼 _invoke macro _Proc,args:VARARG LOCAL count count = 0 % for i,< reverseArgs( args ) > count = count+1 push i endm call dword ptr _Proc endm
注入代碼: shellcode.asm
REMOTE_CODE_START equ this byte _lpLoadLibrary dd ? _lpGetProcAddress dd ? _lpGetModuleHandle dd ? ; -------------------------------------------- ; 存放靜態資源,好比常量,字符串等. _hInstance dd ? _szShowTitle db "hello lyshark",0h ; -------------------------------------------- ; 存放獲取到的指針 _lpDllUser dd ? _lpMessageBox dd ? ; -------------------------------------------- ; 放入導入函數的字符串 _szDllUser db "user32.dll",0h _szMessageBox db "MessageBoxA",0h,0 ; -------------------------------------------- _RemoteThread proc uses ebx esi edi LOCAL @hModule ; -------------------------------------------- ; 計算指令的偏移地址,用ebx做爲基址指針 call @F @@: pop ebx sub ebx,offset @B ; -------------------------------------------- _invoke [ebx + _lpGetModuleHandle],NULL ; 取當前模塊句柄 mov [ebx + _hInstance],eax lea eax,[ebx + offset _szDllUser] _invoke [ebx + _lpGetModuleHandle],eax ; 取user32.dll模塊句柄 mov @hModule,eax ; -------------------------------------------- ; 循環獲取每一個導入函數的地址,並放入指針變量保存 lea esi,[ebx + offset _szMessageBox] ; 循環獲取,從該函數起始地址處 lea edi,[ebx + offset _lpMessageBox] .while TRUE _invoke [ebx + _lpGetProcAddress],@hModule,esi mov [edi],eax ; 獲取到函數地址後,放入導入函數字符串中 add edi,4 ; 每次遞增4字節,指向下一個函數,遇到0則中止 @@: lodsb or al,al jnz @B .break .if !byte ptr [esi] .endw ; -------------------------------------------- ;lea esi,[ebx+ offset _szMessageBox] ; 取msgbox模塊地址 ;_invoke [ebx+_lpGetProcAddress],@hModule,esi ; 獲取地址 ;mov [ebx+_lpMessageBox],eax ; 存入變量中 lea esi,[ebx + offset _szShowTitle] ; 獲取彈窗資源 _invoke [ebx + _lpMessageBox],0,esi,eax,0 ; 調用信息框 ret _RemoteThread endp
建立DLL文件: hookdll.dll
.386 .model flat,stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib .data? hInstdll dd ? ; dll句柄 hHook dd ? ; 鉤子句柄 szAscii db 5 dup (?) .code ; ------------------------------------------------------------------ ; 鉤子回調函數,這裏按鍵後,彈出信息框提示 CallBack proc nCode:DWORD,wParam:DWORD,lParam:DWORD LOCAL @szKeyState[256]:byte invoke CallNextHookEx,hHook,nCode,wParam,lParam invoke GetKeyboardState,addr @szKeyState invoke GetKeyState,VK_SHIFT mov @szKeyState+VK_SHIFT,al mov ecx,lParam shr ecx,16 invoke ToAscii,wParam,ecx,addr @szKeyState,addr szAscii,0 mov byte ptr szAscii [eax],0 invoke MessageBox,NULL,addr wParam,0,MB_OK ; 彈出信息框 ret CallBack endp ; ------------------------------------------------------------------ ; 加載鉤子,安裝hook的子程序 installhook proc invoke SetWindowsHookEx,WH_KEYBOARD,addr CallBack,hInstdll,NULL mov hHook,eax ret installhook endp ; ------------------------------------------------------------------ ; 卸載鉤子,清除hook的子程序 uninstallhook proc invoke UnhookWindowsHookEx,hHook ret uninstallhook endp ; ------------------------------------------------------------------ ; DllMain 程序入口函數 DllMain proc _hInstance:HINSTANCE,_dwReason:DWORD, _dwResverved:DWORD .if(_dwReason == DLL_PROCESS_ATTACH) push _hInstance pop hInstdll .elseif(_dwReason == DLL_PROCESS_DETACH) call uninstallhook .endif mov eax,TRUE ret DllMain endp end DllMain
建立inc文件: hookdll.inc
installhook proto uninstallhook proto
建立def: hookdll.def,並將目錄下的hook.dll,hook.inc,hook.lib 拷貝出來.
LIBRARY hookdll EXPORTS installhook EXPORTS uninstallhook
建立主程序: 建立main.asm文件,並將hookdll.dll,hookdll.inc,hookdll.lib拷貝到目錄下.
include hookdll.inc includelib hookdll.lib .data? hInstance dd ? uMsg MSG <?> .code main proc invoke installhook invoke GetModuleHandle,NULL mov hInstance,eax .while(TRUE) invoke GetMessage,addr uMsg,NULL,0,0 invoke TranslateMessage,addr uMsg invoke DispatchMessage,addr uMsg .endw invoke uninstallhook ret main endp end main
遍歷子鍵: HKEY_LOCAL_MACHINE中的子鍵
include msvcrt.inc includelib msvcrt.lib include advapi32.inc includelib advapi32.lib .data dwIndex dd ? dwSize dd ? szBuffer db 256 dup(?) PrintText db "%s",0ah .code main proc mov dwIndex,0 .while(TRUE) mov dwSize,offset szBuffer invoke RegEnumKeyEx,HKEY_LOCAL_MACHINE,dwIndex,addr szBuffer,addr dwSize, \ NULL,NULL,NULL,NULL .break .if eax == ERROR_NO_MORE_ITEMS invoke crt_printf,addr PrintText,addr szBuffer inc dwIndex .endw ret main endp end main
建立鍵值:
include advapi32.inc includelib advapi32.lib .data szKeyPATH db "Software\\Microsoft\\Windows\\CurrentVersion\\Run",0h szValueName db "AutoRun Shell",0h szFileName db MAX_PATH dup(?) .code _RegSetValue proc _lpszKey,_lpszValueName,_lpszValue,_dwValueType,_dwSize LOCAL @hKey invoke RegCreateKey,HKEY_LOCAL_MACHINE,_lpszKey,addr @hKey .if (eax == ERROR_SUCCESS) invoke RegSetValueEx,@hKey,_lpszValueName,NULL,\ _dwValueType,_lpszValue,_dwSize invoke RegCloseKey,@hKey .endif ret _RegSetValue endp main proc invoke GetModuleFileName,NULL,addr szFileName,MAX_PATH ; 獲取文件全路徑 inc eax invoke _RegSetValue,addr szKeyPATH,addr szValueName,addr szFileName,REG_SZ,eax ret main endp end main
刪除鍵值:
include advapi32.inc includelib advapi32.lib .data szKeyPATH db "Software\\Microsoft\\Windows\\CurrentVersion\\Run",0h szValueName db "AutoRun Shell",0h .code _RegDelValue proc _lpszKey,_lpszValueName LOCAL @hKey invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,KEY_WRITE,addr @hKey .if(eax == ERROR_SUCCESS) invoke RegDeleteValue,@hKey,_lpszValueName invoke RegCloseKey,@hKey .endif ret _RegDelValue endp main proc invoke _RegDelValue,addr szKeyPATH,addr szValueName ret main endp end main
建立子鍵
include advapi32.inc includelib advapi32.lib .data lpszKey db "Software\Microsoft\\Windows\\CurrentVersion\\Run\\",0h lpszSubKey db "MySub",0h .code _RegCreateKey proc _lpszKey,_lpszSubKeyName LOCAL @hKey,@hSubkey,@dwDisp invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,KEY_CREATE_SUB_KEY,addr @hKey .if eax == ERROR_SUCCESS invoke RegCreateKeyEx,@hKey,_lpszSubKeyName,NULL,NULL,\ NULL,NULL,NULL,addr @hSubkey,addr @dwDisp invoke RegCloseKey,@hKey invoke RegCloseKey,@hSubkey .endif ret _RegCreateKey endp main proc invoke _RegCreateKey,addr lpszKey,addr lpszSubKey ret main endp end main
刪除子鍵:
include advapi32.inc includelib advapi32.lib .data lpszKey db "Software\Microsoft\\Windows\\CurrentVersion\\Run\\",0h lpszSubKey db "MySub",0h .code _RegDelSubKey proc _lpszKey,_lpszSubKeyName LOCAL @hKey invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,KEY_WRITE,addr @hKey .if eax == ERROR_SUCCESS invoke RegDeleteKey,@hKey,_lpszSubKeyName invoke RegCloseKey,@hKey .endif ret _RegDelSubKey endp main proc invoke _RegDelSubKey,addr lpszKey,addr lpszSubKey ret main endp end main
讀取鍵值:
include advapi32.inc includelib advapi32.lib .data lpDwSize dd 1024 lpValue db 1024 dup(?) szKeyPATH db "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\",0h szValueName db "IgfxTray",0h .code _RegQueryValue proc _lpszKey,_lpszValueName,_lpszValue,_lpdwSize,_lpdwType LOCAL @hKey,@dwReturn mov @dwReturn,-1 invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,\ KEY_QUERY_VALUE,addr @hKey .if eax == ERROR_SUCCESS invoke RegQueryValueEx,@hKey,_lpszValueName,NULL,_lpdwType,\ _lpszValue,_lpdwSize mov @dwReturn,eax invoke RegCloseKey,@hKey .endif mov eax,@dwReturn ret _RegQueryValue endp main proc invoke _RegQueryValue,addr szKeyPATH,addr szValueName,addr lpValue,addr lpDwSize,0 lea eax,lpValue ret main endp end main
設置開機自啓動:
include advapi32.inc includelib advapi32.lib .data szhKey dd ? szFileName db MAX_PATH dup(?) ; 獲取當前路徑 szKeyAutoRun db "Software\\Microsoft\\Windows\\CurrentVersion\\Run",0h ; 寫入子鍵 szValueAutoRun db "AutoRun Shell",0h ; 寫入的名稱 .code main proc invoke GetModuleFileName,NULL,addr szFileName,MAX_PATH ; 獲取文件全路徑 invoke RegCreateKey,HKEY_LOCAL_MACHINE,addr szKeyAutoRun,addr szhKey .if(eax == ERROR_SUCCESS) invoke RegSetValueEx,szhKey,addr szValueAutoRun,NULL,REG_SZ, \ addr szFileName,sizeof szFileName .endif ret main endp end main
建立INI: Option.ini
[lyshark] ; 字段1 X=1024 Y=2048 Z=4096 [IniDemo] ; 字段2 StringKey=hello,lyshark! IntKey=123123 ToString=lyshark
遍歷Section列表:
include msvcrt.inc includelib msvcrt.lib .data szStrlen dd ? szBuffer1 db 20480 dup(?) szININame db ".\Option.ini",0h szFmtSection db "[%s]",0h PrintText db "%s ",0ah .code main proc LOCAL @szBuffer[256]:byte invoke GetPrivateProfileSectionNames,addr szBuffer1,sizeof szBuffer1,addr szININame mov esi,offset szBuffer1 .while byte ptr [esi] invoke wsprintf,addr @szBuffer,addr szFmtSection,esi invoke crt_printf,addr PrintText,esi ; 打印鍵值 invoke lstrlen,esi add esi,eax inc esi .endw ret main endp end main
遍歷鍵值對
include msvcrt.inc includelib msvcrt.lib .data szStrlen dd ? szBuffer db 2048 dup(?) szININame db ".\Option.ini",0h ; 指定要遍歷的文件 szPrintKey db "lyshark",0h ; 指定要遍歷的key szFmtSection db "[%s]",0h PrintText db "%s ",0ah .code main proc invoke GetPrivateProfileSection,addr szPrintKey,addr szBuffer,sizeof szBuffer,addr szININame mov edi,offset szBuffer .while byte ptr [edi] invoke crt_printf,addr PrintText,edi ; 打印key invoke lstrlen,edi add edi,eax inc edi .endw invoke lstrlen,esi add esi,eax inc esi ret main endp end main
拼接並打印字符串:
include masm32.inc includelib masm32.lib .data szBuffer db 2048 dup(?) ; 保存當前路徑 szININame db "\Option.ini",0h ; 配置文件路徑 .code main proc invoke GetCurrentDirectory,MAX_PATH,addr szBuffer mov esi,offset szBuffer invoke lstrlen,esi mov ecx,offset szININame .if byte ptr [esi+eax-1] == '\' inc ecx .endif invoke lstrcat,esi,ecx invoke StdOut, eax ; 打印拼接後的字符串 ret main endp end main
讀取:
.data szININame db ".\Option.ini",0h ; 指定要遍歷的文件 szSecPos db "IniDemo",0h ; 指定要遍歷的key szKeyInt db "IntKey",0h ; 要讀取的整數字段值 szKeyStr db "StringKey",0h ; 要讀取的字符串字段 szBuffer db 2048 dup(?) .code main proc invoke GetPrivateProfileInt,addr szSecPos,addr szKeyInt,50,addr szININame ; 讀取整數 invoke GetPrivateProfileString,addr szSecPos,addr szKeyStr,0, \ addr szBuffer,sizeof szBuffer,addr szININame ; 讀取字符串 lea eax,szBuffer ret main endp end main
添加/刪除鍵值:
include masm32.inc includelib masm32.lib .data szBuffer db 2048 dup(?) ; 保存當前路徑 szININame db ".\Option.ini",0h ; 配置文件路徑 szAppName db "IniDemo",0h ; 字段爲IniDemo lpAppKey db "Temp",0h ; 鍵值對爲Temp lpAppStr db "app temp",0h ; 鍵值對值 lpAppNew db "hello temp",0h ; 新的鍵值對 .code main proc ; 在IniDemo中添加 Temp=apptemp invoke WritePrivateProfileString,addr szAppName,addr lpAppKey,addr lpAppStr,addr szININame ; 將IniDemo中的Temp=app temp修改成Temp=hello temp invoke WritePrivateProfileString,addr szAppName,addr lpAppKey,addr lpAppNew,addr szININame ; 刪除IniDemo中的Temp鍵值對 invoke WritePrivateProfileString,addr szAppName,addr lpAppKey,NULL,addr szININame ; 清空IniDemo底下的全部鍵值對 invoke WritePrivateProfileString,addr szAppName,NULL,NULL,addr szININame ret main endp end main
設置頁面對話框:
include Comdlg32.inc includelib Comdlg32.lib .code main proc LOCAL @stPS:PAGESETUPDLG invoke RtlZeroMemory,addr @stPS,sizeof @stPS mov @stPS.lStructSize,sizeof @stPS mov @stPS.hwndOwner,0 invoke PageSetupDlg,addr @stPS .if eax && @stPS.hDevMode mov eax,@stPS.hDevMode mov eax,[eax] invoke MessageBox,0,eax,0,MB_OK .endif ret main endp end main
打開對話框:
include Comdlg32.inc includelib Comdlg32.lib .data szFilter db 'Text Files(*.txt)',0,'*.txt',0,'All Files(*.*)',0,'*.*',0,0 szFileName db MAX_PATH dup (?) .code main proc LOCAL @stOF:OPENFILENAME invoke RtlZeroMemory,addr @stOF,sizeof @stOF mov @stOF.lStructSize,sizeof @stOF mov @stOF.hwndOwner,eax mov @stOF.lpstrFilter,offset szFilter mov @stOF.lpstrFile,offset szFileName mov @stOF.nMaxFile,MAX_PATH mov @stOF.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST invoke GetOpenFileName,addr @stOF .if eax invoke MessageBox,NULL,addr szFileName,0,MB_OK .endif ret main endp end main
保存對話框:
include Comdlg32.inc includelib Comdlg32.lib .data szFilter db 'Text Files(*.txt)',0,'*.txt',0,'All Files(*.*)',0,'*.*',0,0 szFileName db MAX_PATH dup (?) szDefExt db 'txt',0 szSaveCaption db '請輸入保存的文件名',0 .code main proc LOCAL @stOF:OPENFILENAME invoke RtlZeroMemory,addr @stOF,sizeof @stOF mov @stOF.lStructSize,sizeof @stOF mov @stOF.hwndOwner,0 mov @stOF.lpstrFilter,offset szFilter mov @stOF.lpstrFile,offset szFileName mov @stOF.nMaxFile,MAX_PATH mov @stOF.Flags,OFN_PATHMUSTEXIST mov @stOF.lpstrDefExt,offset szDefExt mov @stOF.lpstrTitle,offset szSaveCaption invoke GetSaveFileName,addr @stOF .if eax invoke MessageBox,NULL,addr szFileName,0,MB_OK .endif ret main endp end main
選擇顏色:
include Comdlg32.inc includelib Comdlg32.lib .data dwBackColor dd ? dwCustColors dd 16 dup (?) szBuffer db 1024 dup (?) szFormatColor db "您選擇的顏色值:%08x",0 .code main proc LOCAL @stCC:CHOOSECOLOR invoke RtlZeroMemory,addr @stCC,sizeof @stCC mov @stCC.lStructSize,sizeof @stCC mov @stCC.hwndOwner,0 push dwBackColor pop @stCC.rgbResult mov @stCC.Flags,CC_RGBINIT or CC_FULLOPEN mov @stCC.lpCustColors,offset dwCustColors invoke ChooseColor,addr @stCC .if eax push @stCC.rgbResult pop dwBackColor invoke wsprintf,addr szBuffer,addr szFormatColor,dwBackColor invoke MessageBox,NULL,addr szBuffer,0,MB_OK .endif ret main endp end main
選擇字體:
include Comdlg32.inc includelib Comdlg32.lib .data stLogFont LOGFONT <?> dwFontColor dd ? szBuffer db 1024 dup (?) szFormatFont db '字體名稱:%s',0dh,0ah .code main proc LOCAL @stCF:CHOOSEFONT invoke RtlZeroMemory,addr @stCF,sizeof @stCF mov @stCF.lStructSize,sizeof @stCF mov @stCF.hwndOwner,0 mov @stCF.lpLogFont,offset stLogFont push dwFontColor pop @stCF.rgbColors mov @stCF.Flags,CF_SCREENFONTS or CF_INITTOLOGFONTSTRUCT or CF_EFFECTS invoke ChooseFont,addr @stCF .if eax push @stCF.rgbColors pop dwFontColor invoke wsprintf,addr szBuffer,addr szFormatFont,addr stLogFont.lfFaceName,\ dwFontColor,@stCF.iPointSize invoke MessageBox,NULL,addr szBuffer,0,MB_OK .endif ret main endp end main
服務端:
import socket ip_addr=("127.0.0.1",6666) server = socket.socket() server.bind(ip_addr) server.listen(5) while True: conn,addr=server.accept() print(addr) send_data = input("input:") conn.send(bytes(send_data,encoding="ascii")) recv_data = conn.recv(1024) print(str(recv_data, encoding="utf-8"))
客戶端:
.386 .model flat,stdcall option casemap:none include windows.inc include user32.inc include ws2_32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib includelib ws2_32.lib TCP_PORT equ 6666 .data WSAData WSADATA <> stSin sockaddr_in <> szServer byte "127.0.0.1",0h sock dd ? Buff BYTE 256 dup (?) ; 接收數據的緩衝區 Send BYTE "hello",0h ; 發送數據緩衝區 .code main proc invoke WSAStartup,0202h,addr WSAData invoke socket,AF_INET, SOCK_STREAM, 0 .if(eax != INVALID_SOCKET) mov sock,eax .endif mov stSin.sin_family,AF_INET invoke htons,TCP_PORT mov stSin.sin_port,ax invoke inet_addr,addr szServer mov stSin.sin_addr,eax invoke connect,sock,addr stSin,sizeof stSin ; 鏈接套接字 invoke recv,sock,addr Buff,sizeof Buff,0 ; 接收內容 lea eax,Buff invoke send,sock,addr Send,sizeof Send,0 ; 發送數據 invoke closesocket,sock invoke WSACleanup ret main endp end main
改進版
服務端:
import socket ip_addr=("127.0.0.1",6666) server = socket.socket() server.bind(ip_addr) server.listen(5) conn, addr = server.accept() print(addr) while True: send_data = input("input:") conn.send(bytes(send_data,encoding="ascii")) recv_data = conn.recv(1024) print(str(recv_data, encoding="ascii"))
客戶端:
.386 .model flat,stdcall option casemap:none include windows.inc include user32.inc include ws2_32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib includelib ws2_32.lib TCP_PORT equ 6666 .data WSAData WSADATA <> stSin sockaddr_in <> szServer byte "127.0.0.1",0h sock dd ? Buff BYTE 256 dup (?) ; 接收數據的緩衝區 Send BYTE "ls",0h ; 發送數據緩衝區 Send1 BYTE "down",0h cmdls BYTE "ls",0h cmddown BYTE "down",0h .code main proc invoke WSAStartup,0202h,addr WSAData invoke socket,AF_INET, SOCK_STREAM, 0 .if(eax != INVALID_SOCKET) mov sock,eax .endif invoke RtlZeroMemory,addr stSin,sizeof stSin mov stSin.sin_family,AF_INET invoke htons,TCP_PORT mov stSin.sin_port,ax invoke inet_addr,addr szServer mov stSin.sin_addr,eax invoke connect,sock,addr stSin,sizeof stSin ; 鏈接套接字 .while(1) invoke RtlZeroMemory,addr Buff,sizeof Buff invoke recv,sock,addr Buff,sizeof Buff,0 invoke lstrcmp,addr cmdls,addr Buff ; 對比字符串是不是ls .if(eax==0) invoke send,sock,addr Send,sizeof Send,0 .continue .endif invoke lstrcmp,addr Buff,addr cmddown ; 對比是否是down .if(eax==0) invoke send,sock,addr Send1,sizeof Send1,0 .continue .endif .endw invoke closesocket,sock invoke WSACleanup ret main endp end main
參考文獻:《Intel 彙編語言程序設計》,《琢石成器-Win32彙編語言程序設計》,《彙編語言-王爽》