Win32彙編經常使用系統函數

彙編語言(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與線程注入

◆建立動態連接庫◆

建立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

◆遠程線程DLL注入◆

動態調用函數: 動態的加載並使用一個函數.

.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

◆建立Windows鉤子◆

建立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


註冊表和INI文件

◆註冊表相關◆

遍歷子鍵: 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文件相關◆

建立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彙編語言程序設計》,《彙編語言-王爽》

相關文章
相關標籤/搜索