title: Win32汇编系统函数(5)
date: 2019-04-20 09:57:38
tags:

  • 汇编语言
    categories: 汇编语言
    copyright: true
    ---

汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言.在汇编语言中,用助记符(Mnemonics)代替机器指令的操作码,用地址符号(Symbol)或标号(Label)代替指令或操作数的地址.在不同的设备中,汇编语言对应着不同的机器语言指令集,通过汇编过程转换成机器指令,普遍地说,特定的汇编语言和特定的机器语言指令集是相互对应的,不同平台之间不可直接移植.

熟练掌握Win32 API函数的参数传递,是软件逆向的基础,本章节内容将使用MASM汇编器,逐个编译这些源程序,你可以通过使用一些调试工具,这里推荐OllyDBG来附加编译后的可执行文件,进行逐个分析,观察二进制程序逆向后的一些变化,总结吸收经验,为以后的二进制逆向,漏洞挖掘打基础.

通用系统函数

注册热键: 注册全局热键并能激活.

.datahMsgBox db "你按下了 CTRL + ALT + A",0huMsg MSG <?>
.codemain PROC; 41h = A | 65h=uMsg.wParaminvoke 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,065hinvoke PostQuitMessage,NULL.endif.endwinvoke ExitProcess,0main ENDP
END main

最小化指定窗口:

.dataFindName db "qq",0hhandle   dd ?
.codemain PROCinvoke FindWindow,NULL,addr FindNamemov handle,eax.if(handle != 0)         ; 找到则隐藏窗口invoke ShowWindow,handle,SW_HIDE.else                    ; 没有找到则显示invoke ShowWindow,handle,SW_SHOW.endifinvoke ExitProcess,0main ENDP
END main

显示当前目录等:

.datastStartUp STARTUPINFO <?>.codemain PROCinvoke  GetStartupInfo,addr stStartUpmov eax,stStartUp.lpDesktopmov eax,stStartUp.lpTitle        ; 显示当前软件目录invoke ExitProcess,0main ENDP
END main

取系统版本等:

.dataversion OSVERSIONINFO <?>lpsystem SYSTEM_INFO <?>
.codemain PROCinvoke GetSystemInfo,addr lpsystemmov ax,lpsystem.wProcessorArchitectureinvoke GetVersionEx,addr versionmov eax,version.dwBuildNumberinvoke ExitProcess,0main ENDP
END main

取命令行参数:

.datacmdline dword ?.codemain PROCinvoke GetCommandLine                ; 获取命令行参数mov cmdline,eaxinvoke ExitProcess,0main ENDP
END main

获取环境变量:

.dataszBuffer  DB 200 dup(?)      ; 保存到缓冲区szVarName DB "PATH",0h       ; 获取set PATHlpVar     DD ?.codemain PROCinvoke GetEnvironmentVariable,addr szVarName,addr szBuffer,sizeof szBufferxor eax,eaxinvoke GetEnvironmentStringsmov lpVar,eaxinvoke ExitProcess,0main ENDP
END main

设置环境变量:

.datalpVarName DB "PATH",0hlpValue   DB "E:\RadASM\masm32\bin",0h
.codemain PROCinvoke SetEnvironmentVariable,addr lpVarName,addr lpValueinvoke ExitProcess,0main ENDP
END main

运行系统软件: 下载并运行一个软件.

include urlmon.inc
includelib urlmon.lib.dataszURL DB "https://www.mkdirs.com/lyshark.exe",0hszFileName DB "C:\\lyshark.exe",0hWinRun DB "C:/lyshark.exe",0h
.codemain procinvoke URLDownloadToFile,NULL,addr szURL,addr szFileName,0,NULLinvoke WinExec,offset WinRun,SW_SHOWretmain endp
end main

获取本地时间:

.datasystime SYSTEMTIME <>.codemain PROCinvoke GetLocalTime,addr systime   ; 获取当前时间mov ax,systime.wYearmov bx,systime.wMonthmov cx,systime.wDayinvoke SetLocalTime,addr systime   ; 设置当前时间main ENDP
END main

获取系统时间:

.datasystime SYSTEMTIME <>.codemain PROCinvoke GetSystemTime,addr systimemov ax,systime.wYearmov bx,systime.wMonthmov cx,systime.wDayinvoke SetSystemTime,addr systimemain ENDP
END main

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

.datadwTock DWORD ?.codemain PROCinvoke GetTickCountmov dwTock,eaxinvoke GetTickCountsub eax,dwTockmain ENDP
END main

内存分配函数

◆标准内存管理◆

获取内存状态: GlobalMemourStatus

.dataMem MEMORYSTATUS <>
.codemain PROCinvoke GlobalMemoryStatus,offset Memmov 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,0main ENDP
END main

申请内存:

.datalpMemory DWORD ?
.codemain PROC;GMEM_FIXED=申请内存;GMEM_ZEROINIT申请并初始化为0invoke GlobalAlloc,GMEM_ZEROINIT,1024.if(eax != NULL)mov lpMemory,eax     ; lpMemory 为分配成功后的内存指针.endifinvoke GlobalFree,lpMemory   ; 释放内存空间invoke ExitProcess,0main ENDP
END main

扩大内存空间:

.datalpMemory DWORD ?reMemory DWORD ?
.codemain PROCinvoke GlobalAlloc,GMEM_ZEROINIT,100mov lpMemory,eaxinvoke GlobalReAlloc,lpMemory,1024,GMEM_ZEROINIT or GMEM_MOVEABLE.if(eax != NULL)mov reMemory,eax.endifinvoke GlobalFree,lpMemoryinvoke GlobalFree,reMemoryinvoke ExitProcess,0main ENDP
END main

锁定/解锁内存: 程序需要使用这块内存可以将其锁定,使用完后可以解除锁定.

.datalpMemory DWORD ?Locks    DWORD ?
.codemain PROCinvoke GlobalAlloc,GMEM_ZEROINIT,100mov lpMemory,eaxinvoke GlobalLock,lpMemory     ; 锁定内存空间.if(eax != NULL)mov Locks,eax          ; 锁定成功后,返回原内存地址.endifinvoke GlobalUnlock,lpMemory   ; 解锁内存空间,成功返回非0invoke ExitProcess,0main ENDP
END main

可移动/可丢弃内存: 可移动内存允许在不使用时改变其内存地址,可丢弃当内存不足时可将其丢弃。

.datalp_Move_Memory DWORD ?lp_Disb_Memory DWORD ?
.codemain PROCinvoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,1024     ; 分配可移动的内存.if(eax != NULL)mov lp_Move_Memory,eax                  ; 分配成功则保存其内存地址.endifinvoke GlobalAlloc,GMEM_DISCARDABLE or GMEM_ZEROINIT,1024  ; 分配可丢弃的内存.if(eax != NULL)mov lp_Disb_Memory,eax.endifinvoke ExitProcess,0main ENDP
END main

复制内存地址: 将源地址复制到目标地址中,总共复制40个字节.

.dataSource DWORD 1,2,3,4,5DWORD 6,7,8,9,0Dest   DWORD 0,0,0,0,0DWORD 0,0,0,0,0.codemain PROClea eax,Source         ; 源地址lea ebx,Dest           ; 目标地址invoke RtlMoveMemory,addr Dest,addr Source,40     ;将源地址复制到目标地址,复制40个字节invoke ExitProcess,0main ENDP
END main

填充内存: 将Memory中的字节数据,全部填充替换为A,或填充为0

.dataMemory DB 1,2,3,4,5,6,7,8,9,0DB 1,2,3,4,5,6,7,8,9,0DB 1,2,3,4,5,6,7,8,9,0Fill   DB "A",0
.codemain PROClea eax,Memory; 填充Memory内存,向后填充1024字节,填充为Ainvoke RtlFillMemory,addr Memory,1024,addr Fill;填充Memory内存,向后填充1024字节,全部初始化为0invoke RtlZeroMemory,addr Memory,1024invoke ExitProcess,0main ENDP
END main

◆堆管理函数◆

创建私有堆: 创建一个1024字节的私有堆,并返回内存地址.

.dataHeapMain DWORD ?
.codemain PROCinvoke HeapCreate,HEAP_NO_SERIALIZE,1024,0   ; 保留1024字节物理内存.if(eax != NULL)mov HeapMain,eax                         ; 成功分配则返回内存地址.endifinvoke HeapDestroy,HeapMain                  ; 释放堆空间invoke ExitProcess,0main ENDP
END main

分配内存块: 在创建的堆中分配内存块.

.datalpHeap DWORD ?lpMem  DWORD ?.codemain PROCinvoke HeapCreate,HEAP_NO_SERIALIZE,1024,0   ; 保留1024字节物理内存mov lpHeap,eax                               ; 保存分配的地址invoke HeapAlloc, lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字节空间.if(eax != NULL)mov lpMem,eax                          ; 分配成功,保存内存地址.endifinvoke HeapDestroy,lpHeap                  ; 释放堆空间invoke ExitProcess,0main ENDP
END main

在堆中分配内存:

.datalpHeap   DWORD ?lpMemory DWORD ?.codemain PROCinvoke 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,0main ENDP
END main

增加堆内存空间: 在原本来的内存地址基础上,增加内存空间

.datalpHeap   DWORD ?lpMemory DWORD ?ReMemory DWORD ?.codemain PROCinvoke HeapCreate,HEAP_NO_SERIALIZE,4096,0     ; 创建堆句柄,并保留4096字节mov lpHeap,eax                                 ; 保存分配句柄地址invoke HeapAlloc,lpHeap,HEAP_ZERO_MEMORY,1024  ; 分配1024字节的地址mov lpMemory,eax                               ; 分配并返回内存地址; 重新分配内存空间,在原内存1024上调整到2048invoke HeapReAlloc,lpHeap,HEAP_ZERO_MEMORY,lpMemory,2048mov ReMemory,eax                               ; 保存返回内存地址invoke HeapDestroy,lpHeap                      ; 释放堆空间invoke ExitProcess,0main ENDP
END main

计算堆空间大小:

.datalpHeap   DWORD ?lpMemory DWORD ?Mem_Size DWORD ?.codemain PROCinvoke 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                                  ; 取地址大小,此处为1024invoke HeapDestroy,lpHeap                      ; 释放堆空间invoke ExitProcess,0main ENDP
END main

锁定/解锁堆:

.datalpHeap   DWORD ?lpMemory DWORD ?.codemain PROCinvoke 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,0main ENDP
END main

◆虚拟内存函数◆

保留地址空间: 保留的空间不可以直接使用.

.datalpAddr DWORD ?
.codemain PROCinvoke VirtualAlloc,NULL,1024,MEM_RESERVE,PAGE_NOACCESS  ; 保留内存地址mov lpAddr,eaxinvoke VirtualFree,lpAddr,1024,MEM_RELEASE               ; 释放地址空间invoke ExitProcess,0main ENDP
END main

分配地址空间:

.datalpAddr DWORD ?
.codemain PROCinvoke VirtualAlloc,NULL,1024,MEM_COMMIT,PAGE_READWRITE  ; 分配内存地址.if(eax != NULL)mov lpAddr,eax.endifinvoke VirtualFree,lpAddr,1024,MEM_RELEASE               ; 释放内存地址invoke ExitProcess,0main ENDP
END main

保护/锁定内存:

.datalpAddr DWORD ?
.codemain PROCinvoke VirtualAlloc,NULL,1024,MEM_COMMIT,PAGE_READWRITE  ; 保留内存地址.if(eax != NULL)mov lpAddr,eax.endifinvoke VirtualProtect,lpAddr,1024,PAGE_NOACCESS,NULL     ; 设置内存为只读invoke VirtualLock,lpAddr,1024                           ; 锁定内存地址invoke VirtualUnlock,lpAddr,1024                         ; 解除内存锁定invoke VirtualFree,lpAddr,1024,MEM_RELEASE               ; 释放地址空间invoke ExitProcess,0main ENDP
END main

内存状态测试:

.datalpMemory DWORD 1024lpString BYTE "hello lyshark",0lpStatus DWORD ?
.codemain PROCmov lpMemory,1024lea eax,lpMemoryinvoke IsBadCodePtr,lpMemory          ; 内存的第一个字节是否可读mov lpStatus,eax                      ; 可读返回0否则返回非0invoke IsBadReadPtr,lpMemory,1024     ; 测试前1024字节是否可读mov lpStatus,eax                      ; 可读返回0否则返回非0invoke IsBadWritePtr,lpMemory,1024    ; 测试前1024字节是否可写mov lpStatus,eax                      ; 可写返回0否则返回非0invoke IsBadStringPtr,addr lpString,sizeof lpString ; 测试字符串是否可读mov lpStatus,eax                      ; 可读返回0否则返回非0invoke ExitProcess,0main ENDP
END main

文件与磁盘函数

◆文件相关函数◆

打开/关闭文件: 打开文件成功返回文件句柄,失败则返回error

.dataszFileName db "e:\lyshark.log",0h    ; 打开的文件名称hFile      dd ?                      ; 打开成功后返回的句柄.codemain PROCinvoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0, \OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0.if(eax != INVALID_HANDLE_VALUE)mov hFile,eax.endifinvoke ExitProcess,0main ENDP
END main

创建文件: CREATE_ALWAYS=文件存在则清空内容,CREATE_NEW=文件存在则返回失败

.dataszNewFile db "C:\lyshark.log",0hhFile      dd ?.codemain PROCinvoke CreateFile,addr szNewFile,GENERIC_WRITE,FILE_SHARE_READ,0, \CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0.if(eax != INVALID_HANDLE_VALUE)mov hFile,eax.endifinvoke CloseHandle,hFileinvoke ExitProcess,0main ENDP
END main

移动文件指针:

.dataszFileName DB "c:\lyshark.log",0hhFileHandl DD ?.codemain PROCinvoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0.if(eax != INVALID_HANDLE_VALUE)mov hFileHandl,eax.endifinvoke SetFilePointer,hFileHandl,0,NULL,FILE_CURRENT     ; eax=获取的文件指针位置xor eax,eaxinvoke SetFilePointer,hFileHandl,10,NULL,FILE_BEGIN      ; 将文件指针向后移动10个字节xor eax,eaxinvoke SetFilePointer,hFileHandl,0,NULL,FILE_CURRENT     ; 再次获取指针位置,eax=10invoke ExitProcess,0main ENDP
END main

设置指针到末尾:

.dataszFileName DB "e:\lyshark.log",0hhFileHandl DD ?.codemain PROCinvoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0.if(eax != INVALID_HANDLE_VALUE)mov hFileHandl,eax.endifinvoke SetEndOfFile,hFileHandl                           ; 将文件位置设置到末尾invoke SetFilePointer,hFileHandl,0,NULL,FILE_CURRENT     ; 获取指针位置invoke ExitProcess,0main ENDP
END main

读取文件内容:

.dataszFileName  DB "C:\lyshark.log",0hhFileHandle DD ?szReadBuff  DB ?      ; 每次读取一个字节,放入该变量中ByteRead    DB ?
.codemain PROCinvoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0.if(eax != INVALID_HANDLE_VALUE)mov hFileHandle,eax.endifinvoke SetFilePointer,hFileHandle,1,NULL,FILE_BEGIN   ; 取第一个字符invoke ReadFile,hFileHandle,addr szReadBuff,sizeof szReadBuff,addr ByteRead,0mov al,[szReadBuff]                           ; 将取出来的字符放入al寄存器中invoke ExitProcess,0main ENDP
END main

写入文件内容:

.dataszFileName  DB "C:\lyshark.log",0hhFileHandle DD ?                         ; 获取文件句柄lpBuffer    DB "hello lyshark",0h        ; 要写入的字符串reWrite     DD ?                         ; 返回写入成功字节数.codemain PROCinvoke 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,NULLinvoke FlushFileBuffers,hFileHandle    ; 强制刷新写入invoke ExitProcess,0main ENDP
END main

获取文件长度:

.dataszFileName  DB "E:\lyshark.log",0hhFileHandle DD ?FilesSize   DD ?
.codemain PROCinvoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0mov hFileHandle,eaxinvoke GetFileSize,hFileHandle,NULL      ; 取出文件的长度mov FilesSize,eax                        ; 放入FilesSize里面invoke ExitProcess,0main ENDP
END main

获取文件日期:

.dataszFileName  DB "E:\lyshark.log",0hhFileHandle DD ?create  FILETIME <>            ; 存储创建文件的日期systime SYSTEMTIME <>          ; 存储转换后的文件日期
.codemain PROCinvoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0mov 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,0main ENDP
END main

修改文件日期:

.dataszFileName  DB "E:\lyshark.log",0hhFileHandle DD ?create  FILETIME <>            ; 存储创建文件的日期systime SYSTEMTIME <>          ; 存储转换后的文件日期
.codemain PROCinvoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0mov hFileHandle,eax                                     ; 取出文件句柄mov systime.wYear,19      ; 先填写结构mov systime.wMonth,19invoke SystemTimeToFileTime,addr systime,addr create  ; 转换成filetimeinvoke SetFileTime,hFileHandle,addr create,NULL,NULL  ; 回写invoke ExitProcess,0main ENDP
END main

拷贝/移动/删除/文件:

.datalpSourceFile  DB "C:\lyshark.log",0hlpDestFile    DB "E:\wang.log",0h.codemain PROCinvoke CopyFile,addr lpSourceFile,addr lpDestFile,TRUE   ; 拷贝文件invoke MoveFile,addr lpDestFile,addr lpSourceFile        ; 移动文件invoke DeleteFile,addr lpSourceFileinvoke DeleteFile,addr lpDestFile                        ; 删除文件invoke ExitProcess,0main ENDP
END main

◆磁盘相关函数◆

显示所有驱动器:

.datalpLength  BYTE  ?lpDrives  DWORD 0 dup(1024).codemain PROCinvoke GetLogicalDrives      ; 获取卷标invoke GetLogicalDriveStrings,addr lpLength,addr lpDrives  ; 同上lea esi,[lpDrives]            ; 显示C盘lea esi,[lpDrives+4]          ; 显示D盘invoke ExitProcess,0main ENDP
END main

获取磁盘类型:

.datalpDrive DB "c:\",0
.codemain PROCinvoke GetDriveType,addr lpDriveinvoke ExitProcess,0main ENDP
END main

获取磁盘详细信息:(有问题的)

.datalpRoot DB "c:\",0hlpBuffer DB 1024 dup(?)dwSerial DD ?lpType DB 1024 dup(?)
.codemain PROCinvoke GetVolumeInformation,addr lpRoot, \addr lpBuffer,1024,addr dwSerial,255, \FILE_CASE_PRESERVED_NAMES,addr lpType,1024lea eax,lpRootlea ebx,lpBufferlea ecx,dwSeriallea edx,lpTypeinvoke ExitProcess,0main ENDP
END main

检测逻辑驱动器字节:

.datalpRoot DB "c:\",0hlpSect DD ?lpByte DD ?lpNumb DD ?lpTota DD ?
.codemain PROC; 总容量 = 簇总数 * 每簇扇区数 * 每扇区字节数; 空闲字节数 = 未使用的簇 * 每扇区数 * 每扇区字节数invoke GetDiskFreeSpace,addr lpRoot,addr lpSect,addr lpByte,addr lpNumb,addr lpTotamov eax,lpSect     ; 返回每个簇的扇区数mov eax,lpByte     ; 返回每扇区的字节数mov eax,lpNumb     ; 返回未使用的簇的数量mov eax,lpTota     ; 返回簇的总数invoke ExitProcess,0main ENDP
END main

获取当前目录:

.datalpRoot DB ?.codemain PROCinvoke GetCurrentDirectory,1024,addr lpRoot    ; 获取当前目录lea eax,lpRootinvoke GetTempPath,1024,addr lpRoot            ; 获取临时目录lea eax,lpRootinvoke GetSystemDirectory,addr lpRoot,1024     ; 获取系统目录lea eax,lpRootinvoke ExitProcess,0main ENDP
END main

创建删除目录:

.datalpRoot DB "c:\windows\",0szDir  DB "c:\lyshark\wang",0.codemain PROCinvoke SetCurrentDirectory,addr lpRoot         ; 设置默认路径invoke CreateDirectory,addr szDir,NULL         ; 创建目录invoke RemoveDirectory,addr szDir              ; 删除目录invoke ExitProcess,0main ENDP
END main

进程与线程函数

◆进程相关函数◆

创建进程:

.dataszBuffer   DWORD ?szFileName DWORD ?szCmdLine DWORD ?szBlank DWORD ?stStartUp DWORD ?stProcInfo DWORD ?.codemain PROCinvoke lstrcpy,addr szBuffer,addr szFileName.if(szCmdLine)invoke lstrcat,addr szBuffer,addr szBlankinvoke lstrcat,addr szBuffer,addr szCmdLine.endifinvoke GetStartupInfo,addr stStartUpinvoke CreateProcess,NULL,addr szBuffer,NULL,NULL,NULL, \NORMAL_PRIORITY_CLASS,NULL,NULL,addr stStrartUp,addr stProcInforetmain ENDP
END main

取所有进程信息: 使用快照函数,一次性遍历出所有的进程列表.

.datahSnapShot dd ?stProcess PROCESSENTRY32 <?>
.codemain procinvoke 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      ; 取下一个进程数据.endwinvoke CloseHandle,hSnapShot                       ; 关闭进程句柄retmain endp
end main

取指定进程PID: 获取xshell进程的PID号

.dataFindID    DB "Xshell",0hThreadID  DD ?ProcessID DD ?          ; 获取到的进程号.codemain PROCinvoke FindWindow,NULL,addr FindID.if(FindID != 0)mov ThreadID,eax.endifinvoke GetWindowThreadProcessId, ThreadID,offset ProcessIDmov eax,ProcessIDretmain ENDP
END main

内存示范例子: 请手动编译该例子,并命名为lyshark.exe,接下来的读内存/写内存例子将用它讲解.

    .386p.model flat,stdcalloption casemap:noneinclude windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib.datatitles  DB "box",0hcheck_ok DB "破解完成.",0hcheck_err DB "破解失败",0h
.codemain procxor eax,eax.if eaxinvoke MessageBox,NULL,addr check_ok,addr titles,MB_OK.elseinvoke MessageBox,NULL,addr check_err,addr titles,MB_OK.endifretmain endp
end main

读取进程数据: 读取指定的内存地址中的数据,并将其放入ReadBuf缓冲区中.

OEP equ 004198402                            ; 读取的范围
.datastStartUp STARTUPINFO <>             ; 初始化stProInfo PROCESS_INFORMATION <>     ; 该进程的进程信息ExeRun    DB "C:\\lyshark.exe",0h    ; 要打开的进程名称ReadBuf   DD ?                       ; 读取到的数据内容
.codemain procinvoke GetStartupInfo,addr stStartUpinvoke CreateProcess,addr ExeRun,NULL,NULL,NULL,NULL,\NORMAL_PRIORITY_CLASS,0,0,addr stStartUp,addr stProInfo.if(eax); 读取当前进程,读取内存地址为OEP,每次读取8个字节,读取到放入ReadBufinvoke ReadProcessMemory,stProInfo.hProcess,OEP,addr ReadBuf,8,NULLlea eax,ReadBuf.endifretmain endp
end main

写入进程数据: 写入进程数据,将跳转替换为nop指令的机器码.

OEP equ 004198402                            ; 读取的范围
.datastStartUp STARTUPINFO <>             ; 初始化stProInfo PROCESS_INFORMATION <>     ; 该进程的进程信息ExeRun    DB "C:\\lyshark.exe",0h    ; 要打开的进程名称lpPatch   DB 90h,90h,90h,90h         ; 要替换的汇编指令redPatch  DD ?                       ; 替换完后保存替换结果
.codemain procinvoke GetStartupInfo,addr stStartUpinvoke CreateProcess,addr ExeRun,NULL,NULL,NULL,NULL,\NORMAL_PRIORITY_CLASS,0,0,addr stStartUp,addr stProInfo.if(eax); 写入当前进程,写入内存地址为OEP,替换8个字节,替换成nopinvoke WriteProcessMemory,stProInfo.hProcess,OEP,addr lpPatch,4,NULL.if(eax != 0)            ; 如果不等于0则说明补丁替换完成invoke ReadProcessMemory,stProInfo.hProcess,OEP,addr redPatch,4,NULLlea eax,redPatch ; 将补丁地址取出,并用OD分析,为9090则替换完成..endif .endifretmain endp
end main

◆线程相关函数◆

创建线程函数: 默认情况下,线程创建后会被系统挂起,需要执行ResumeThread函数,将其放入前台.

.dataThreadID DWORD ?              ; 保存返回线程IDhThread  DWORD ?              ; 保存线程句柄
.code_MyThread proc lParam         ; lParam为传递的参数xor eax,eaxret_MyThread endpmain PROCinvoke CreateThread,NULL,0,addr _MyThread,NULL,CREATE_SUSPENDED,addr ThreadID.if(eax)mov hThread,eax             ; 将线程句柄放入hThread.endifinvoke ResumeThread, hThread    ; 运行这个线程retmain ENDP
END main

创建事件:

.datalpEventName DWORD ?         ; 创建的时间名称hEventID    DWORD ?         ; 成功后返回的句柄
.codemain PROCinvoke CreateEvent,NULL,TRUE,TRUE,addr lpEventName.if(eax != NULL)mov hEventID,eax.endifinvoke WaitForSingleObject,addr hEventID,INFINITE  ; 等待一个事件invoke SetEvent,addr hEventID    ; 将事件的状态设置为:"置位"invoke ResetEvent,hEventID       ; 将事件的状态设置为:"复位"invoke CloseHandle,hEventID      ; 关闭这个句柄retmain ENDP
END main

DLL与线程注入

◆创建动态链接库◆

创建dll: 这里我们创建一个lyshark.asm.

    .586.model flat,stdcalloption casemap:noneinclude windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib.datalpText db "hello lyshark",0lpCapt db "MsgBox",0.codeDllEntry PROC _hInstance,_dwReason,_dwReservedmov eax,TRUEretDllEntry ENDP_MsgBox PROC                          ; 无参数的信息框invoke MessageBox,NULL,addr lpText,addr lpCapt,MB_OKret_MsgBox ENDP_MySum PROC Num_x:DWORD,Num_y:DWORD   ; 一个加法计算的函数mov eax,Num_xadd eax,Num_yret_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.codemain procinvoke _MsgBoxinvoke _MySum,100,200retmain endp
end main

动态装载dll(无参):

.dataszMyDll        db "lyshark.dll",0h   ; 装入的动态链接库名称szMsgBox       db "_MsgBox",0h       ; 装入的函数名(无参)hLibMod        dd  ?                 ; dll的句柄lpMsgBox       dd  ?                 ; 函数的地址.codemain procinvoke LoadLibrary,addr szMyDll ; 加载指定的dll.if(eax)mov hLibMod,eaxinvoke GetProcAddress,hLibMod,addr szMsgBoxmov lpMsgBox,eaxcall lpMsgBox         ; 调用MsgBox.endifinvoke FreeLibrary,hLibMod    ; 传递句柄,并释放dllretmain endp
end main

动态装载dll(有参):

.dataszMyDll   db "lyshark.dll",0h   ; 装入的动态链接库名称szMySum   db "_MySum",0h        ; 装入的函数名(无参)hLibMod   dd  ?                 ; dll的句柄lpMySum   dd  ?                 ; 函数的地址Num_X     dd 10                 ; 参数x=10Num_Y     dd 20                 ; 参数y=20.codemain procinvoke LoadLibrary,addr szMyDll ; 加载指定的dll.if(eax)mov hLibMod,eaxinvoke GetProcAddress,hLibMod,addr szMySummov lpMySum,eaxpush Num_Y           ; 压入第二个参数push Num_X           ; 压入第一个参数call lpMySum         ; 调用_MySum 函数.endifinvoke FreeLibrary,hLibMod    ; 传递句柄,并释放dllretmain endp
end main

◆远程线程DLL注入◆

动态调用函数: 动态的加载并使用一个函数.

.dataszDllKernel db "Kernel32.dll",0hszFunction  db "GetVersion",0hCallAddr    dd ?
.codemain procinvoke GetModuleHandle,offset szDllKernel               ; 取出模块句柄.if(eax != 0)invoke GetProcAddress,eax,offset szFunction     ; 取出函数的地址mov CallAddr,eax                                ; 保存函数地址.endifcall CallAddr           ; 直接调用kernel32.GetVersionretmain endp
end main

编写DLL: 首先编写一个dLL用来测试

    .386.model flat,stdcalloption casemap:noneinclude windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib.dataszText DB "welcome to asm",0hszCaption DB "MsgBox",0h
.codeMain PROCinvoke MessageBox,NULL,addr szText,addr szCaption,MB_OKret
Main endpDllEntry PROC _hInstance,_dwReason,_dwReservedcall Mainmov eax,TRUEret
DllEntry ENDP
END DllEntry

注入DLL:

.dataszMyDll        db "\lyshark.dll",0h       ; 要注入的DLLszDllKernel    db "Kernel32.dll",0hszLoadLibrary  db "LoadLibraryA",0hlpFileName     db "Tutorial-i386",0h      ; 指定要注入进程lpDllName      dd ?
.data?szMyDllFull    db MAX_PATH dup (?)lpLoadLibrary  dd ?dwProcessID    dd ?     dwThreadID     dd ?hProcess       dd ?
.codemain PROC
; 准备工作:获取dll的全路径文件名、获取LoadLibrary函数地址等invoke GetCurrentDirectory,MAX_PATH,addr szMyDllFullinvoke lstrcat,addr szMyDllFull,addr szMyDllinvoke GetModuleHandle,addr szDllKernelinvoke GetProcAddress,eax,offset szLoadLibrarymov lpLoadLibrary,eax; 查找文件管理器窗口并获取进程ID,然后打开进程invoke FindWindow,NULL,addr lpFileNameinvoke GetWindowThreadProcessId,eax,offset dwProcessIDmov dwThreadID,eaxinvoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessIDmov hProcess,eax; 在进程中分配空间并将DLL文件名拷贝过去,然后创建一个LoadLibrary线程invoke VirtualAllocEx,hProcess,NULL,MAX_PATH,MEM_COMMIT,PAGE_READWRITEmov lpDllName,eaxinvoke WriteProcessMemory,hProcess,eax,offset szMyDllFull,MAX_PATH,NULLinvoke CreateRemoteThread,hProcess,NULL,0,lpLoadLibrary,lpDllName,0,NULLretmain endp
end main

◆远程线程代码注入◆

注入器: 新建main.asm

.datalpLoadLibrary      dd ?lpGetProcAddress   dd ?lpGetModuleHandle  dd ?dwProcessID        dd ?dwThreadID         dd ?hProcess           dd ?lpRemoteCode       dd ?
.constProcHandle        db "lyshark.exe",0hKernelBase        db "Kernel32.dll",0hszLoadLibrary     db "LoadLibraryA",0hszGetProcAddress  db "GetProcAddress",0hszGetModuleHandle db "GetModuleHandleA",0h
.code
include Macro.inc
include ShellCode.asmmain procinvoke GetModuleHandle,addr KernelBasemov ebx,eaxinvoke GetProcAddress,ebx,offset szLoadLibrarymov lpLoadLibrary,eaxinvoke GetProcAddress,ebx,offset szGetProcAddressmov lpGetProcAddress,eaxinvoke GetProcAddress,ebx,offset szGetModuleHandlemov lpGetModuleHandle,eaxinvoke FindWindow,NULL,addr ProcHandleinvoke GetWindowThreadProcessId,eax,offset dwProcessIDmov dwThreadID,eaxinvoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessIDmov hProcess,eaxinvoke VirtualAllocEx,hProcess,NULL,2048,MEM_COMMIT,PAGE_EXECUTE_READWRITE.if eaxmov lpRemoteCode,eaxinvoke WriteProcessMemory,hProcess,lpRemoteCode,offset REMOTE_CODE_START,1024,NULLinvoke WriteProcessMemory,hProcess,lpRemoteCode,offset lpLoadLibrary,sizeof dword * 3,NULLmov eax,lpRemoteCodeadd eax,offset _RemoteThread - offset REMOTE_CODE_STARTinvoke CreateRemoteThread,hProcess,NULL,0,eax,0,0,NULLinvoke CloseHandle,eax.endifinvoke CloseHandle,hProcess invoke ExitProcess,NULLretmain endp
end main

反转宏: Macro.inc 用来翻转参数,定义_invoke

; --------------------------------------------
; 翻转参数字节序
reverseArgs macro arglist:VARARGLOCAL txt,counttxt TEXTEQU <>count=0for i,<arglist>count = count+1txt TEXTEQU @CatStr(i,<!,>,<%txt>)endmif count GT 0txt SUBSTR txt,1,@SizeStr(%txt)-1endifexitm txt
endm
; --------------------------------------------
; 创建类似于INVOKE的宏代码
_invoke macro _Proc,args:VARARGLOCAL countcount = 0
%   for i,< reverseArgs( args ) >count = count+1push iendmcall 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 ediLOCAL @hModule
; --------------------------------------------
; 计算指令的偏移地址,用ebx作为基址指针call @F@@:pop ebxsub ebx,offset @B
; --------------------------------------------_invoke [ebx + _lpGetModuleHandle],NULL         ; 取当前模块句柄mov [ebx + _hInstance],eaxlea 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,esimov [edi],eax       ; 获取到函数地址后,放入导入函数字符串中add edi,4           ; 每次递增4字节,指向下一个函数,遇到0则停止@@:lodsbor al,aljnz @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:DWORDLOCAL @szKeyState[256]:byteinvoke CallNextHookEx,hHook,nCode,wParam,lParam invoke GetKeyboardState,addr @szKeyStateinvoke GetKeyState,VK_SHIFTmov @szKeyState+VK_SHIFT,almov ecx,lParamshr ecx,16invoke ToAscii,wParam,ecx,addr @szKeyState,addr szAscii,0mov byte ptr szAscii [eax],0invoke MessageBox,NULL,addr wParam,0,MB_OK    ; 弹出信息框ret
CallBack endp
; ------------------------------------------------------------------
; 加载钩子,安装hook的子程序
installhook procinvoke SetWindowsHookEx,WH_KEYBOARD,addr CallBack,hInstdll,NULLmov hHook,eaxret
installhook endp
; ------------------------------------------------------------------
; 卸载钩子,清除hook的子程序
uninstallhook procinvoke UnhookWindowsHookEx,hHookret
uninstallhook endp
; ------------------------------------------------------------------
; DllMain 程序入口函数DllMain proc _hInstance:HINSTANCE,_dwReason:DWORD, _dwResverved:DWORD.if(_dwReason == DLL_PROCESS_ATTACH)push _hInstancepop hInstdll.elseif(_dwReason == DLL_PROCESS_DETACH)call uninstallhook.endifmov eax,TRUEretDllMain 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 <?>
.codemain procinvoke installhookinvoke GetModuleHandle,NULLmov hInstance,eax.while(TRUE)invoke GetMessage,addr uMsg,NULL,0,0invoke TranslateMessage,addr uMsginvoke DispatchMessage,addr uMsg.endwinvoke uninstallhookretmain endp
end main

注册表和INI文件

◆注册表相关◆

遍历子键: HKEY_LOCAL_MACHINE中的子键

include msvcrt.inc
includelib msvcrt.lib
include advapi32.inc
includelib advapi32.lib.datadwIndex   dd ?dwSize    dd ?szBuffer  db 256 dup(?)PrintText db "%s",0ah
.codemain procmov dwIndex,0.while(TRUE)mov dwSize,offset szBufferinvoke RegEnumKeyEx,HKEY_LOCAL_MACHINE,dwIndex,addr szBuffer,addr dwSize, \NULL,NULL,NULL,NULL.break .if eax == ERROR_NO_MORE_ITEMSinvoke crt_printf,addr PrintText,addr szBufferinc dwIndex.endwretmain endp
end main

创建键值:

include advapi32.inc
includelib advapi32.lib.dataszKeyPATH    db "Software\\Microsoft\\Windows\\CurrentVersion\\Run",0hszValueName  db "AutoRun Shell",0hszFileName   db MAX_PATH dup(?)
.code
_RegSetValue proc _lpszKey,_lpszValueName,_lpszValue,_dwValueType,_dwSizeLOCAL @hKeyinvoke RegCreateKey,HKEY_LOCAL_MACHINE,_lpszKey,addr @hKey.if (eax == ERROR_SUCCESS)invoke  RegSetValueEx,@hKey,_lpszValueName,NULL,\_dwValueType,_lpszValue,_dwSizeinvoke RegCloseKey,@hKey.endifret
_RegSetValue    endpmain procinvoke GetModuleFileName,NULL,addr szFileName,MAX_PATH  ; 获取文件全路径inc eaxinvoke _RegSetValue,addr szKeyPATH,addr szValueName,addr szFileName,REG_SZ,eaxretmain endp
end main

删除键值:

include advapi32.inc
includelib advapi32.lib.dataszKeyPATH   db "Software\\Microsoft\\Windows\\CurrentVersion\\Run",0hszValueName db "AutoRun Shell",0h
.code
_RegDelValue proc _lpszKey,_lpszValueNameLOCAL @hKeyinvoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,KEY_WRITE,addr @hKey.if(eax == ERROR_SUCCESS)invoke RegDeleteValue,@hKey,_lpszValueNameinvoke RegCloseKey,@hKey.endifret
_RegDelValue endpmain procinvoke _RegDelValue,addr szKeyPATH,addr szValueNameretmain endp
end main

创建子键

include advapi32.inc
includelib advapi32.lib.datalpszKey    db "Software\Microsoft\\Windows\\CurrentVersion\\Run\\",0hlpszSubKey db "MySub",0h
.code
_RegCreateKey proc _lpszKey,_lpszSubKeyNameLOCAL @hKey,@hSubkey,@dwDispinvoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,KEY_CREATE_SUB_KEY,addr @hKey.if eax == ERROR_SUCCESSinvoke RegCreateKeyEx,@hKey,_lpszSubKeyName,NULL,NULL,\NULL,NULL,NULL,addr @hSubkey,addr @dwDispinvoke RegCloseKey,@hKeyinvoke RegCloseKey,@hSubkey.endifret
_RegCreateKey endpmain procinvoke _RegCreateKey,addr lpszKey,addr lpszSubKeyretmain endp
end main

删除子键:

include advapi32.inc
includelib advapi32.lib.datalpszKey    db "Software\Microsoft\\Windows\\CurrentVersion\\Run\\",0hlpszSubKey db "MySub",0h
.code
_RegDelSubKey proc _lpszKey,_lpszSubKeyNameLOCAL @hKeyinvoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,KEY_WRITE,addr @hKey.if eax == ERROR_SUCCESSinvoke RegDeleteKey,@hKey,_lpszSubKeyNameinvoke RegCloseKey,@hKey.endifret
_RegDelSubKey endpmain procinvoke _RegDelSubKey,addr lpszKey,addr lpszSubKeyretmain endp
end main

读取键值:

include advapi32.inc
includelib advapi32.lib.datalpDwSize  dd 1024lpValue   db 1024 dup(?)szKeyPATH   db "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\",0hszValueName db "IgfxTray",0h
.code
_RegQueryValue proc _lpszKey,_lpszValueName,_lpszValue,_lpdwSize,_lpdwTypeLOCAL @hKey,@dwReturnmov @dwReturn,-1invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,\KEY_QUERY_VALUE,addr @hKey.if eax == ERROR_SUCCESSinvoke RegQueryValueEx,@hKey,_lpszValueName,NULL,_lpdwType,\_lpszValue,_lpdwSizemov @dwReturn,eaxinvoke RegCloseKey,@hKey.endifmov eax,@dwReturnret
_RegQueryValue endpmain procinvoke _RegQueryValue,addr szKeyPATH,addr szValueName,addr lpValue,addr lpDwSize,0lea eax,lpValueretmain endp
end main

设置开机自启动:

include advapi32.inc
includelib advapi32.lib.dataszhKey         dd ?szFileName     db MAX_PATH dup(?)                                        ; 获取当前路径szKeyAutoRun   db "Software\\Microsoft\\Windows\\CurrentVersion\\Run",0h ; 写入子键szValueAutoRun db "AutoRun Shell",0h                                     ; 写入的名称
.codemain procinvoke 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.endifretmain 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
.dataszStrlen     dd ?szBuffer1    db 20480 dup(?)szININame    db ".\Option.ini",0hszFmtSection db "[%s]",0hPrintText    db "%s ",0ah.codemain procLOCAL @szBuffer[256]:byteinvoke GetPrivateProfileSectionNames,addr szBuffer1,sizeof szBuffer1,addr szININamemov esi,offset szBuffer1.while byte ptr [esi]invoke wsprintf,addr @szBuffer,addr szFmtSection,esiinvoke crt_printf,addr PrintText,esi          ; 打印键值invoke lstrlen,esiadd esi,eaxinc esi.endwretmain endp
end main

遍历键值对

include msvcrt.inc
includelib msvcrt.lib
.dataszStrlen     dd ?szBuffer     db 2048 dup(?)szININame    db ".\Option.ini",0h    ; 指定要遍历的文件szPrintKey   db "lyshark",0h         ; 指定要遍历的keyszFmtSection db "[%s]",0hPrintText    db "%s ",0ah
.codemain procinvoke GetPrivateProfileSection,addr szPrintKey,addr szBuffer,sizeof szBuffer,addr szININamemov edi,offset szBuffer.while byte ptr [edi]invoke crt_printf,addr PrintText,edi   ; 打印keyinvoke lstrlen,ediadd edi,eaxinc edi.endwinvoke lstrlen,esiadd esi,eaxinc esiretmain endp
end main

拼接并打印字符串:

include masm32.inc
includelib masm32.lib.dataszBuffer  db 2048 dup(?)       ; 保存当前路径szININame db "\Option.ini",0h  ; 配置文件路径
.codemain procinvoke GetCurrentDirectory,MAX_PATH,addr szBuffermov esi,offset szBufferinvoke lstrlen,esimov ecx,offset szININame.if byte ptr [esi+eax-1] == '\'inc ecx.endifinvoke lstrcat,esi,ecxinvoke StdOut, eax      ; 打印拼接后的字符串retmain endp
end main

读取:

.dataszININame   db ".\Option.ini",0h       ; 指定要遍历的文件szSecPos    db "IniDemo",0h            ; 指定要遍历的keyszKeyInt    db "IntKey",0h             ; 要读取的整数字段值szKeyStr    db "StringKey",0h          ; 要读取的字符串字段szBuffer    db 2048 dup(?)
.codemain procinvoke GetPrivateProfileInt,addr szSecPos,addr szKeyInt,50,addr szININame  ; 读取整数invoke GetPrivateProfileString,addr szSecPos,addr szKeyStr,0, \addr szBuffer,sizeof szBuffer,addr szININame                               ; 读取字符串lea eax,szBufferretmain endp
end main

添加/删除键值:

include masm32.inc
includelib masm32.lib.dataszBuffer  db 2048 dup(?)       ; 保存当前路径szININame db ".\Option.ini",0h  ; 配置文件路径szAppName db "IniDemo",0h       ; 字段为IniDemolpAppKey  db "Temp",0h          ; 键值对为TemplpAppStr  db "app temp",0h      ; 键值对值lpAppNew  db "hello temp",0h    ; 新的键值对
.codemain proc; 在IniDemo中添加 Temp=apptempinvoke WritePrivateProfileString,addr szAppName,addr lpAppKey,addr lpAppStr,addr szININame; 将IniDemo中的Temp=app temp修改为Temp=hello tempinvoke 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 szININameretmain endp
end main

通用对话框

设置页面对话框:

include Comdlg32.inc
includelib Comdlg32.lib.codemain procLOCAL @stPS:PAGESETUPDLGinvoke RtlZeroMemory,addr @stPS,sizeof @stPSmov @stPS.lStructSize,sizeof @stPSmov @stPS.hwndOwner,0invoke PageSetupDlg,addr @stPS.if eax && @stPS.hDevModemov eax,@stPS.hDevModemov eax,[eax]invoke MessageBox,0,eax,0,MB_OK.endifretmain endp
end main

打开对话框:

include Comdlg32.inc
includelib Comdlg32.lib.dataszFilter   db 'Text Files(*.txt)',0,'*.txt',0,'All Files(*.*)',0,'*.*',0,0szFileName db MAX_PATH dup (?)
.codemain procLOCAL @stOF:OPENFILENAMEinvoke RtlZeroMemory,addr @stOF,sizeof @stOFmov @stOF.lStructSize,sizeof @stOFmov @stOF.hwndOwner,eaxmov @stOF.lpstrFilter,offset szFiltermov @stOF.lpstrFile,offset szFileNamemov @stOF.nMaxFile,MAX_PATHmov @stOF.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXISTinvoke GetOpenFileName,addr @stOF.if eaxinvoke MessageBox,NULL,addr szFileName,0,MB_OK.endifretmain endp
end main

保存对话框:

include Comdlg32.inc
includelib Comdlg32.lib.dataszFilter      db 'Text Files(*.txt)',0,'*.txt',0,'All Files(*.*)',0,'*.*',0,0szFileName    db MAX_PATH dup (?)szDefExt      db 'txt',0szSaveCaption db '请输入保存的文件名',0
.codemain procLOCAL @stOF:OPENFILENAMEinvoke RtlZeroMemory,addr @stOF,sizeof @stOFmov @stOF.lStructSize,sizeof @stOFmov @stOF.hwndOwner,0mov @stOF.lpstrFilter,offset szFiltermov @stOF.lpstrFile,offset szFileNamemov @stOF.nMaxFile,MAX_PATHmov @stOF.Flags,OFN_PATHMUSTEXISTmov @stOF.lpstrDefExt,offset szDefExtmov @stOF.lpstrTitle,offset szSaveCaptioninvoke GetSaveFileName,addr @stOF.if eaxinvoke MessageBox,NULL,addr szFileName,0,MB_OK.endifretmain endp
end main

选择颜色:

include Comdlg32.inc
includelib Comdlg32.lib.datadwBackColor     dd ?dwCustColors    dd 16 dup (?)szBuffer        db 1024 dup (?)szFormatColor   db "您选择的颜色值:%08x",0
.codemain procLOCAL @stCC:CHOOSECOLORinvoke RtlZeroMemory,addr @stCC,sizeof @stCCmov @stCC.lStructSize,sizeof @stCCmov @stCC.hwndOwner,0push dwBackColorpop @stCC.rgbResultmov @stCC.Flags,CC_RGBINIT or CC_FULLOPENmov @stCC.lpCustColors,offset dwCustColorsinvoke  ChooseColor,addr @stCC.if eaxpush @stCC.rgbResultpop dwBackColorinvoke wsprintf,addr szBuffer,addr szFormatColor,dwBackColorinvoke MessageBox,NULL,addr szBuffer,0,MB_OK.endifretmain endp
end main

选择字体:

include Comdlg32.inc
includelib Comdlg32.lib.datastLogFont      LOGFONT <?>dwFontColor    dd ?szBuffer       db 1024 dup (?)szFormatFont   db '字体名称:%s',0dh,0ah
.codemain procLOCAL @stCF:CHOOSEFONTinvoke RtlZeroMemory,addr @stCF,sizeof @stCFmov @stCF.lStructSize,sizeof @stCFmov @stCF.hwndOwner,0mov @stCF.lpLogFont,offset stLogFontpush dwFontColorpop @stCF.rgbColorsmov @stCF.Flags,CF_SCREENFONTS or CF_INITTOLOGFONTSTRUCT or CF_EFFECTSinvoke ChooseFont,addr @stCF.if eaxpush @stCF.rgbColorspop dwFontColorinvoke wsprintf,addr szBuffer,addr szFormatFont,addr stLogFont.lfFaceName,\dwFontColor,@stCF.iPointSizeinvoke MessageBox,NULL,addr szBuffer,0,MB_OK.endifretmain endp
end main

网络相关函数

服务端:

import socketip_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,stdcalloption casemap:noneinclude windows.inc
include user32.inc
include ws2_32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
includelib ws2_32.libTCP_PORT equ 6666.dataWSAData  WSADATA <>stSin sockaddr_in <>szServer byte "127.0.0.1",0hsock dd ?Buff BYTE 256 dup (?)                ; 接收数据的缓冲区Send BYTE "hello",0h                 ; 发送数据缓冲区.codemain procinvoke WSAStartup,0202h,addr WSADatainvoke socket,AF_INET, SOCK_STREAM, 0.if(eax != INVALID_SOCKET)mov sock,eax.endifmov stSin.sin_family,AF_INETinvoke htons,TCP_PORTmov stSin.sin_port,axinvoke inet_addr,addr szServermov stSin.sin_addr,eaxinvoke connect,sock,addr stSin,sizeof stSin    ; 连接套接字invoke recv,sock,addr Buff,sizeof Buff,0       ; 接收内容lea eax,Buffinvoke send,sock,addr Send,sizeof Send,0       ; 发送数据invoke closesocket,sockinvoke WSACleanupretmain endp
end main

改进版

服务端:

import socketip_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,stdcalloption casemap:noneinclude windows.inc
include user32.inc
include ws2_32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib
includelib ws2_32.libTCP_PORT equ 6666.dataWSAData  WSADATA <>stSin sockaddr_in <>szServer byte "127.0.0.1",0hsock dd ?Buff BYTE 256 dup (?)                ; 接收数据的缓冲区Send BYTE "ls",0h                 ; 发送数据缓冲区Send1 BYTE "down",0hcmdls BYTE "ls",0hcmddown BYTE "down",0h
.codemain procinvoke WSAStartup,0202h,addr WSADatainvoke socket,AF_INET, SOCK_STREAM, 0.if(eax != INVALID_SOCKET)mov sock,eax.endifinvoke RtlZeroMemory,addr stSin,sizeof stSinmov stSin.sin_family,AF_INETinvoke htons,TCP_PORTmov stSin.sin_port,axinvoke inet_addr,addr szServermov stSin.sin_addr,eaxinvoke connect,sock,addr stSin,sizeof stSin    ; 连接套接字.while(1)invoke RtlZeroMemory,addr Buff,sizeof Buffinvoke recv,sock,addr Buff,sizeof Buff,0invoke lstrcmp,addr cmdls,addr Buff                    ; 对比字符串是否是ls.if(eax==0)invoke send,sock,addr Send,sizeof Send,0.continue.endifinvoke lstrcmp,addr Buff,addr cmddown                  ; 对比是不是down.if(eax==0)invoke send,sock,addr Send1,sizeof Send1,0.continue.endif.endwinvoke closesocket,sockinvoke WSACleanupretmain endp
end main

转载于:https://www.cnblogs.com/LyShark/p/11136335.html

Win32汇编系统函数(5)相关推荐

  1. win32汇编系统函数简单小示例图解

    1 打开 计算器 窗口,最小化 计算器 窗口 从 Console Build All 菜单构建: 代码: .386 .model flat, stdcall option casemap :nonei ...

  2. c#调用win32 API函数修改系统时间

    一般来说,系统时间的修改可以通过win32 API函数库中的SetLocalTime函数进行设置.对于C#语言来说,虽然win32 API大部分函数都已经封装在了.NET Framework类库中,但 ...

  3. win32异常处理函数

    Win32程序在出现未处理异常时,会调用这个函数,我们就在这里处理程序挂掉后的所有事,包括重启. 原型:LONG WINAPI FreeEIM_UnhandledExceptionFilter(LPE ...

  4. win32 API函数大全

    [1]. API之网络函数  WNetAddConnection :创建同一个网络资源的永久性连接  WNetAddConnection2 :创建同一个网络资源的连接  WNetAddConnecti ...

  5. Win32 API 函数列表

    ID编号 函数名 函数说明 详细说明 Win16支持 Win9x支持 WinNT支持 1 AbortDoc 终止一项打印作业  Yes Yes Yes 2 AbortPath 终止或取消DC中的一切路 ...

  6. Win32 API 函数列表1(格式有点乱)

    西安邮电学院 徐兆元 ID编号 函数名 函数说明 详细说明 Win16支持 Win9x支持 WinNT支持 1 AbortDoc 终止一项打印作业  Yes Yes Yes 2 AbortPath 终 ...

  7. Win32 Api函数

    1. API之网络函数 WNetAddConnection 创建同一个网络资源的永久性连接  WNetAddConnection2 创建同一个网络资源的连接  WNetAddConnection3 创 ...

  8. 管理输入光标的 WIN32 API 函数

    下面的 API 函数是用来管理输入光标的 API 函数,下面是在使用C#时声明的这些函数: /**//// <summary> /// 参数说明: ///        hwnd   :  ...

  9. win32 断言函数和转换到COFF期间失败错误

    断言(assert)的用法 assert,是个宏:     其作用可描述为: if(假设成立) {      程序正常运行: } else {       报错&&终止程序!(避免由程 ...

最新文章

  1. 军工企业敏捷项目管理
  2. logrotate机制和原理
  3. 简约之美Jodd-http--应用一箩筐
  4. deeplab ssd识别
  5. 【算法学习笔记】19.算法设计初步 最大子列和问题的几种方法
  6. JavaScript学习笔记之BOM篇,认识几种常见的浏览器对象
  7. python书籍推荐:Head First Python(中文版)
  8. 存放哪些内容 项目中vuex_房屋安全鉴定中房屋抗震检测内容有哪些
  9. spring mvc实例
  10. build openposewith opencv-2.4.13,cuda9(9.0 - 9.2)
  11. C++ multimap 用法总结 例子
  12. 算法:匹配有效的括号20. Valid Parentheses
  13. MAC地址生成器(可带跳数)
  14. 关于一些桌面、移动应用开发的平台
  15. 【jmeter教程——从入门到熟练】
  16. unity2D游戏案例-躲避怪云
  17. element表格动态合并多列
  18. python做一个大鱼吃小鱼_Python精灵模块制作的大鱼吃小鱼游戏
  19. courant数_CFD中常用的参数介绍 | 坐倚北风
  20. Spring 青鸟云题库

热门文章

  1. miui系统里的android文件夹,小米手机的文件夹都装着些什么,你知道吗?
  2. 第三课:购买您的第一个树莓派
  3. 淘宝api app版淘宝店铺商品
  4. 因果模型四:实现因果模型的python工具——pycasual
  5. 湖北理工学院计算机二级成绩查询,湖北理工学院教务管理系统入口http://jwc.hbpu.edu.cn/...
  6. JS 阻止冒泡 阻止默认
  7. 【运维能力提升计划-1】:JAVA基础
  8. 一文详解PHP用流方式实现下载文件(附代码示例)
  9. Word、WPS中表格的第一行和第二行中间间距,如何去掉,使得跟其他行间距相同
  10. BOS初级开发培训认证