通用系统函数

  • 获取时间差: eax 保存的就是执行代码后的时间差,单位毫秒

    .data
        dwTock DWORD ?
    
    .code
        main PROC
            invoke GetTickCount
            mov dwTock,eax
            invoke GetTickCount
            sub eax,dwTock
        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
    
  • 获取本地时间:

    .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
    
  • 运行系统软件: 下载并运行一个软件.

    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
    
        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
    
  • 获取环境变量:

    .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
        cmdline dword ?
    
    .code
        main PROC
    
            invoke GetCommandLine                ; 获取命令行参数
            mov cmdline,eax
    
            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
    
  • 显示当前目录:

    .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
        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
    
  • 注册热键: 注册全局热键并能激活.

    .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
    
  • 最小化指定窗口:

    .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
    

标准内存管理

  • 填充内存: 将 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
    
  • 复制内存地址: 将源地址复制到目标地址中,总共复制 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
    
  • 可移动/可丢弃内存: 可移动内存允许在不使用时改变其内存地址,可丢弃当内存不足时可将其丢弃。

    .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
    
  • 锁定/解锁内存: 程序需要使用这块内存可以将其锁定,使用完后可以解除锁定.

    .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
        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 ?
    .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
    
  • 获取内存状态: 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
    
  • 填充内存: 将 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
    
  • 复制内存地址: 将源地址复制到目标地址中,总共复制 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
    

堆管理函数

  • 锁定/解锁堆:

    .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
        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 ?
        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 ?
    
    .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 ?
        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
    
  • 创建私有堆: 创建一个 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
        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
    
  • 保护/锁定内存:

    .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
        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_RESERVE,PAGE_NOACCESS  ; 保留内存地址
            mov lpAddr,eax
            invoke VirtualFree,lpAddr,1024,MEM_RELEASE               ; 释放地址空间
    
            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
        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
        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 ?
        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 "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 "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 "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
        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
    
  • 创建文件: 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
    
  • 打开/关闭文件: 打开文件成功返回文件句柄,失败则返回 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
    

磁盘相关函数

  • 创建删除目录:

    .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
        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:\",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
    
  • 获取磁盘详细信息:

    .386
    .model flat,stdcall
    option casemap:none
    
    includelib user32.lib
    includelib kernel32.lib
    
    ExitProcess PROTO :DWORD
    GetDiskFreeSpaceExA PROTO :DWORD, :DWORD, :DWORD, :DWORD
    
    .data
        driveLetter db 'C:',0  ; 要获取信息的磁盘盘符,这里是C盘
        lpFreeBytesAvailable DWORD?  ; 可用字节数
        lpTotalNumberOfBytes DWORD?  ; 总字节数
        lpTotalNumberOfFreeBytes DWORD?  ; 总可用字节数
    .code
    main PROC
        ; 调用GetDiskFreeSpaceEx获取磁盘空间信息
        push offset lpTotalNumberOfFreeBytes
        push offset lpTotalNumberOfBytes
        push offset lpFreeBytesAvailable
        push offset driveLetter
        call GetDiskFreeSpaceExA
    
        push 0
        call ExitProcess
    main ENDP
    END main
    
  • 获取磁盘类型:

    .data
        lpDrive DB "c:\",0
    .code
        main PROC
            invoke GetDriveType,addr lpDrive
            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
    

进程相关函数

  • 写入进程数据: 写入进程数据,将跳转替换为 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
    
  • 读取进程数据: 读取指定的内存地址中的数据,并将其放入 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
    
  • 获取指定进程 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
    
  • 获取所有进程信息: 使用快照函数,一次性遍历出所有的进程列表.

    .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
    
  • 创建进程:

    .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
        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
    
  • 创建线程函数: 默认情况下,线程创建后会被系统挂起,需要执行 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
    

创建动态链接库

  • 创建 dll:lyshark.asm​.

    .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
        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(无参):

    include lyshark.inc
    includelib lyshark.lib
    
    .code
        main proc
            invoke _MsgBox
            invoke _MySum,100,200
            ret
        main endp
    end main
    
  • 直接调用 dll:

    ml /c /coff lyshark.asm
    link /SUBSYSTEM:WINDOWS /RELEASE /DLL /DEF:lyshark.def /OUT:"lyshark.dll" "lyshark.obj"
    
  • 生成 dll:

    _MsgBox PROTO
    _MySum  PROTO Num_X:DWORD,Num_Y:DWORD
    
  • 创建 inc 文件: 在当前目录继续创建一个 lyshark.inc​ 文件,并写入相应的导入函数.

    EXPORTS _MsgBox
    EXPORTS _MySum
    
  • 创建 def: 然后在当前目录下创建一个 lyshark.def​ 文件,用来声明导入库的函数名.

    .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
    

远程线程 DLL 注入

  • 注入 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
    
  • 编写 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
    
  • 动态调用函数: 动态的加载并使用一个函数.

    .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
    

远程线程代码注入

  • 注入器: 新建 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
    
  • 注入代码: 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
    
  • 反转宏: 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
    

创建 Windows 钩子

  • 创建 DLL 文件: hookdll.dll

    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
    
  • 创建主程序: 创建 main.asm 文件,并将 hookdll.dll,hookdll.inc,hookdll.lib 拷贝到目录下.

    LIBRARY hookdll
    EXPORTS installhook
    EXPORTS uninstallhook
    
  • 创建 def: hookdll.def,并将目录下的 hook.dll,hook.inc,hook.lib 拷贝出来.

    installhook proto
    uninstallhook proto
    
  • 创建 inc 文件: hookdll.inc

    .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
    

注册表相关

  • 设置开机自启动:

    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
        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
        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
        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
        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 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
    
  • 遍历子键: HKEY_LOCAL_MACHINE 中的子键

    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
    

简单算法

  • 将大端顺序转换为小端顺序
    .386
    .model flat,stdcall
    .stack 4096
    ExitProcess PROTO,dwExitCode:DWORD
    
    .data
    bigEndian BYTE 12h,34h,56h,78h
    littleEndian DWORD ?
    
    .code
    main PROC
    	mov eax,0
    	mov al,bigEndian
    	mov ah,[bigEndian+1]
    	mov dl,[bigEndian+2]
    	mov dh,[bigEndian+3]
    
    	xchg dh,dl
    	xchg ah,al
    
    	mov word ptr littleEndian,ax
    	mov word ptr [littleEndian+2],dx
    
    	INVOKE ExitProcess,0
    main ENDP
    END main
    
  • 交换数组元素对
    .386
    .model flat,stdcall
    .stack 4096
    ExitProcess PROTO,dwExitCode:DWORD
    
    .data
    arrayB	BYTE	1,2,3,4,5,6,7,8
    
    .code
    main PROC
    	mov esi,0
    	mov ecx,(LENGTHOF arrayB)/2
    Li:
    	mov al,arrayB[esi]
    	xchg al,arrayB[esi+1]
    	xchg al,arrayB[esi]
    
    	add esi,2
    	loop Li
    
    	INVOKE ExitProcess,0
    main ENDP
    END main
    
  • 数组元素间隔之和
    .386
    .model flat,stdcall
    .stack 4096
    ExitProcess PROTO,dwExitCode:DWORD
    
    .data
    arrayD	DWORD	0,2,5,9,10
    
    .code
    main PROC
    	mov esi,0
    	mov eax,0
    	mov ebx,0
    	mov ecx,(LENGTHOF arrayD) - 1
    Li:
    	mov bl,BYTE PTR arrayD[esi+TYPE arrayD]
    	sub bl,BYTE PTR arrayD[esi]
    	add eax,ebx
    	add esi,TYPE arrayD
    	loop Li
    
    	INVOKE ExitProcess,0
    main ENDP
    END main
    
  • 将字数组复制到双字数组
    .386
    .model flat,stdcall
    .stack 4096
    ExitProcess PROTO,dwExitCode:DWORD
    
    .data
    arrayW WORD 1111h,2222h,3333h,4444h
    arrayD DWORD LENGTHOF arrayW DUP(0)
    .code
    main PROC
    	mov esi,0
    	mov eax,0
    	mov ecx,LENGTHOF arrayD
    Li:
    	movsx eax,arrayW[esi]
    	xchg eax,arrayD[esi*TYPE WORD]
    	add esi,TYPE arrayW
    	loop Li
    
    	INVOKE ExitProcess,0
    main ENDP
    END main
    
  • 数组反向
    .386
    .model flat,stdcall
    .stack 4096
    ExitProcess PROTO,dwExitCode:DWORD
    
    .data
    arrayB BYTE 1,2,3,4,5,6,7,8
    
    .code
    main PROC
    	mov esi,0
    	mov eax,0
    	mov ecx,(LENGTHOF arrayB)/2
    	mov ebx,SIZEOF arrayB
    Li:
    	mov al,arrayB[esi]
    	sub ebx,TYPE arrayB
    	xchg al,arrayB[ebx]
    	xchg al,arrayB[esi]
    	add esi,TYPE arrayB
    	loop Li
    
    	INVOKE ExitProcess,0
    main ENDP
    END main
    
  • 将字符串复制为相反顺序
    .386
    .model flat,stdcall
    .stack 4096
    ExitProcess PROTO,dwExitCode:DWORD
    
    .data
    source BYTE "This is the source string",0
    target BYTE SIZEOF source DUP("#")
    
    .code
    main PROC
    	mov esi,0
    	mov eax,0
    	mov ecx,LENGTHOF source
    Li:
    	mov al,source[ecx-1]
    	xchg al,target[esi]
    	inc esi
    	loop Li
    
    	INVOKE ExitProcess,0
    main ENDP
    END main
    
  • 数组元素位移
    .386
    .model flat,stdcall
    .stack 4096
    ExitProcess PROTO,dwExitCode:DWORD
    
    .data
    arrayD DWORD 10h,20h,30h,40h
    
    .code
    main PROC
    	mov esi,0
    	mov eax,0
    	mov ecx,LENGTHOF arrayD - 1
    	mov ebx,arrayD[SIZEOF arrayD - TYPE DWORD]
    	mov eax,arrayD[esi]
    Li:
    	xchg eax,arrayD[esi+4]
    	add esi,4
    	loop Li
    
    	xchg ebx,arrayD
    	INVOKE ExitProcess,0
    main ENDP
    END main