通用系统函数

2022-12-28 15:02:46 浏览数 (1)

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

通用系统函数

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

代码语言:javascript复制
.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

最小化指定窗口:

代码语言:javascript复制
.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

显示当前目录等:

代码语言:javascript复制
.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

取系统版本等:

代码语言:javascript复制
.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

取命令行参数:

代码语言:javascript复制
.data
	cmdline dword ?

.code
	main PROC
		
		invoke GetCommandLine                ; 获取命令行参数
		mov cmdline,eax
		
		
		
		invoke ExitProcess,0
	main ENDP
END main

获取环境变量:

代码语言:javascript复制
.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

设置环境变量:

代码语言:javascript复制
.data

	lpVarName DB "PATH",0h
	lpValue   DB "E:RadASMmasm32bin",0h
.code
	main PROC
		invoke SetEnvironmentVariable,addr lpVarName,addr lpValue
		invoke ExitProcess,0
	main ENDP
END main

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

代码语言:javascript复制
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

获取本地时间:

代码语言:javascript复制
.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

获取系统时间:

代码语言:javascript复制
.data
	systime SYSTEMTIME <>

.code
	main PROC
		invoke GetSystemTime,addr systime
		mov ax,systime.wYear
		mov bx,systime.wMonth
		mov cx,systime.wDay
		
		invoke SetSystemTime,addr systime
	main ENDP
END main

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

代码语言:javascript复制
.data
	dwTock DWORD ?

.code
	main PROC
		invoke GetTickCount
		mov dwTock,eax
		invoke GetTickCount
		sub eax,dwTock
	main ENDP
END main

## 内存分配函数

◆标准内存管理◆

获取内存状态: GlobalMemourStatus

代码语言:javascript复制
.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

申请内存:

代码语言:javascript复制
.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

扩大内存空间:

代码语言:javascript复制
.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

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

代码语言:javascript复制
.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

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

代码语言:javascript复制
.data
	lp_Move_Memory DWORD ?
	lp_Disb_Memory DWORD ?
.code
	main PROC
		invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,1024     ; 分配可移动的内存
		.if(eax != NULL)
			mov lp_Move_Memory,eax                  ; 分配成功则保存其内存地址
		.endif
		
		invoke GlobalAlloc,GMEM_DISCARDABLE or GMEM_ZEROINIT,1024  ; 分配可丢弃的内存
		.if(eax != NULL)
			mov lp_Disb_Memory,eax
		.endif
		
		invoke ExitProcess,0
	main ENDP
END main

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

代码语言:javascript复制
.data
	Source DWORD 1,2,3,4,5
	       DWORD 6,7,8,9,0
	
	Dest   DWORD 0,0,0,0,0
	       DWORD 0,0,0,0,0

.code
	main PROC
		lea eax,Source         ; 源地址
		lea ebx,Dest           ; 目标地址
		
		invoke RtlMoveMemory,addr Dest,addr Source,40     ;将源地址复制到目标地址,复制40个字节
		invoke ExitProcess,0
	main ENDP
END main

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

代码语言:javascript复制
.data
	Memory DB 1,2,3,4,5,6,7,8,9,0
	       DB 1,2,3,4,5,6,7,8,9,0
	       DB 1,2,3,4,5,6,7,8,9,0
	Fill   DB "A",0
.code
	main PROC
		lea eax,Memory
		
		; 填充Memory内存,向后填充1024字节,填充为A
		invoke RtlFillMemory,addr Memory,1024,addr Fill
		;填充Memory内存,向后填充1024字节,全部初始化为0
		invoke RtlZeroMemory,addr Memory,1024
		invoke ExitProcess,0
	main ENDP
END main

◆堆管理函数◆

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

代码语言:javascript复制
.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

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

代码语言:javascript复制
.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

在堆中分配内存:

代码语言:javascript复制
.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

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

代码语言:javascript复制
.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

计算堆空间大小:

代码语言:javascript复制
.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

锁定/解锁堆:

代码语言:javascript复制
.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

◆虚拟内存函数◆

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

代码语言:javascript复制
.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

分配地址空间:

代码语言:javascript复制
.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

保护/锁定内存:

代码语言:javascript复制
.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

内存状态测试:

代码语言:javascript复制
.data
	lpMemory DWORD 1024
	lpString BYTE "hello lyshark",0
	lpStatus DWORD ?
.code
	main PROC
		mov lpMemory,1024
		lea eax,lpMemory
		
		invoke IsBadCodePtr,lpMemory          ; 内存的第一个字节是否可读
		mov lpStatus,eax                      ; 可读返回0否则返回非0
		
		invoke IsBadReadPtr,lpMemory,1024     ; 测试前1024字节是否可读
		mov lpStatus,eax                      ; 可读返回0否则返回非0
		
		invoke IsBadWritePtr,lpMemory,1024    ; 测试前1024字节是否可写
		mov lpStatus,eax                      ; 可写返回0否则返回非0
		
		invoke IsBadStringPtr,addr lpString,sizeof lpString ; 测试字符串是否可读
		mov lpStatus,eax                      ; 可读返回0否则返回非0
		invoke ExitProcess,0
	main ENDP
END main

## 文件与磁盘函数

◆文件相关函数◆

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

代码语言:javascript复制
.data
	szFileName db "e:lyshark.log",0h    ; 打开的文件名称
	hFile      dd ?                      ; 打开成功后返回的句柄

.code
	main PROC
		invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0, 
		OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0

		.if(eax != INVALID_HANDLE_VALUE)
			mov hFile,eax
		.endif
		
		invoke ExitProcess,0
	main ENDP
END main

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

代码语言:javascript复制
.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

移动文件指针:

代码语言:javascript复制
.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

设置指针到末尾:

代码语言:javascript复制
.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

读取文件内容:

代码语言:javascript复制
.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

写入文件内容:

代码语言:javascript复制
.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

获取文件长度:

代码语言:javascript复制
.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

获取文件日期:

代码语言:javascript复制
.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

修改文件日期:

代码语言:javascript复制
.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

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

代码语言:javascript复制
.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

◆磁盘相关函数◆

显示所有驱动器:

代码语言:javascript复制
.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

获取磁盘类型:

代码语言:javascript复制
.data
	lpDrive DB "c:",0
.code
	main PROC
		invoke GetDriveType,addr lpDrive
		invoke ExitProcess,0
	main ENDP
END main

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

代码语言:javascript复制
.data
	lpRoot DB "c:",0h
	lpBuffer DB 1024 dup(?)
	dwSerial DD ?
	lpType DB 1024 dup(?)
.code
	main PROC
		invoke GetVolumeInformation,addr lpRoot, 
		addr lpBuffer,1024,addr dwSerial,255, 
		FILE_CASE_PRESERVED_NAMES,addr lpType,1024
		
		lea eax,lpRoot
		lea ebx,lpBuffer
		lea ecx,dwSerial
		lea edx,lpType
		invoke ExitProcess,0
	main ENDP
END main

检测逻辑驱动器字节:

代码语言:javascript复制
.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

获取当前目录:

代码语言:javascript复制
.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

创建删除目录:

代码语言:javascript复制
.data
	lpRoot DB "c:windows",0
	szDir  DB "c:lysharkwang",0

.code
	main PROC
		invoke SetCurrentDirectory,addr lpRoot         ; 设置默认路径
		
		invoke CreateDirectory,addr szDir,NULL         ; 创建目录
		invoke RemoveDirectory,addr szDir              ; 删除目录
		invoke ExitProcess,0
	main ENDP
END main

## 进程与线程函数

◆进程相关函数◆

创建进程:

代码语言:javascript复制
.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

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

代码语言:javascript复制
.data
	hSnapShot dd ?
	stProcess PROCESSENTRY32 <?>
.code
	main proc
		invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0   ; 创建快照
		mov hSnapShot,eax                                      ; 保存句柄
		mov stProcess.dwSize,sizeof stProcess                  ; 保存快照大小
		
		invoke Process32First,hSnapShot,addr stProcess         ; 取第一个进程数据
		.while(eax)                                            ; eax!=0则继续循环
			invoke Process32Next,hSnapShot,addr stProcess      ; 取下一个进程数据
		.endw
			invoke CloseHandle,hSnapShot                       ; 关闭进程句柄
		ret
	main endp
end main

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

代码语言:javascript复制
.data
	FindID    DB "Xshell",0h
	ThreadID  DD ?
	ProcessID DD ?          ; 获取到的进程号
	
.code
	main PROC
		invoke FindWindow,NULL,addr FindID
		.if(FindID != 0)
			mov ThreadID,eax
		.endif
		invoke GetWindowThreadProcessId, ThreadID,offset ProcessID
		mov eax,ProcessID
		ret
	main ENDP
END main

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

代码语言:javascript复制
	.386p
	.model flat,stdcall
	option casemap:none

include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib

.data
	titles  DB "box",0h
	check_ok DB "破解完成.",0h
	check_err DB "破解失败",0h
.code
	main proc
		xor eax,eax
		.if eax
			invoke MessageBox,NULL,addr check_ok,addr titles,MB_OK
		.else
			invoke MessageBox,NULL,addr check_err,addr titles,MB_OK
		.endif
		ret
	main endp
end main

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

代码语言:javascript复制
OEP equ 004198402                            ; 读取的范围
.data
	stStartUp STARTUPINFO <>             ; 初始化
	stProInfo PROCESS_INFORMATION <>     ; 该进程的进程信息
	ExeRun    DB "C:\lyshark.exe",0h    ; 要打开的进程名称
	ReadBuf   DD ?                       ; 读取到的数据内容
.code
	main proc
		invoke GetStartupInfo,addr stStartUp
		invoke CreateProcess,addr ExeRun,NULL,NULL,NULL,NULL,
		NORMAL_PRIORITY_CLASS,0,0,addr stStartUp,addr stProInfo
		
		.if(eax)
		        ; 读取当前进程,读取内存地址为OEP,每次读取8个字节,读取到放入ReadBuf
			invoke ReadProcessMemory,stProInfo.hProcess,OEP,addr ReadBuf,8,NULL
			lea eax,ReadBuf
		.endif
		ret
	main endp
end main

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

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

◆线程相关函数◆

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

代码语言:javascript复制
.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

创建事件:

代码语言:javascript复制
.data
	lpEventName DWORD ?         ; 创建的时间名称
	hEventID    DWORD ?         ; 成功后返回的句柄
.code
	main PROC
	
		invoke CreateEvent,NULL,TRUE,TRUE,addr lpEventName
		.if(eax != NULL)
			mov hEventID,eax
		.endif
		
		invoke WaitForSingleObject,addr hEventID,INFINITE  ; 等待一个事件
		invoke SetEvent,addr hEventID    ; 将事件的状态设置为:"置位"

		invoke ResetEvent,hEventID       ; 将事件的状态设置为:"复位"
		invoke CloseHandle,hEventID      ; 关闭这个句柄
		ret
	main ENDP
END main

## DLL与线程注入

◆创建动态链接库◆

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

代码语言:javascript复制
	.586
	.model flat,stdcall
	option casemap:none

include windows.inc
include kernel32.inc
include user32.inc
includelib kernel32.lib
includelib user32.lib

.data
	lpText db "hello lyshark",0
	lpCapt db "MsgBox",0

.code
	DllEntry PROC _hInstance,_dwReason,_dwReserved
		mov eax,TRUE
		ret
	DllEntry ENDP
	
	_MsgBox PROC                          ; 无参数的信息框
		invoke MessageBox,NULL,addr lpText,addr lpCapt,MB_OK
		ret
	_MsgBox ENDP
	
	_MySum PROC Num_x:DWORD,Num_y:DWORD   ; 一个加法计算的函数
		mov eax,Num_x
		add eax,Num_y
		ret
	_MySum endp
end DllEntry

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

代码语言:javascript复制
EXPORTS _MsgBox
EXPORTS _MySum

创建inc文件: 在当前目录继续创建一个lyshark.inc文件,并写入相应的导入函数.

代码语言:javascript复制
_MsgBox PROTO
_MySum  PROTO Num_X:DWORD,Num_Y:DWORD

生成dll: 生成dll执行如下代码.

代码语言:javascript复制
ml /c /coff lyshark.asm
link /SUBSYSTEM:WINDOWS /RELEASE /DLL /DEF:lyshark.def /OUT:"lyshark.dll" "lyshark.obj"

直接调用dll:

代码语言:javascript复制
include lyshark.inc
includelib lyshark.lib

.code
	main proc
		invoke _MsgBox
		invoke _MySum,100,200
		ret
	main endp
end main

动态装载dll(无参):

代码语言:javascript复制
.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(有参):

代码语言:javascript复制
.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注入◆

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

代码语言:javascript复制
.data
	szDllKernel db "Kernel32.dll",0h
	szFunction  db "GetVersion",0h
	CallAddr    dd ?
.code
	main proc
		invoke GetModuleHandle,offset szDllKernel               ; 取出模块句柄
		.if(eax != 0)
			invoke GetProcAddress,eax,offset szFunction     ; 取出函数的地址
			mov CallAddr,eax                                ; 保存函数地址
		.endif
		
		call CallAddr           ; 直接调用kernel32.GetVersion
		ret
	main endp
end main

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

代码语言:javascript复制
	.386
	.model flat,stdcall
	option casemap:none

include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib

.data
	szText DB "welcome to asm",0h
	szCaption DB "MsgBox",0h
.code

Main PROC
	invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK
	ret
Main endp

DllEntry PROC _hInstance,_dwReason,_dwReserved
	call Main
	mov	eax,TRUE
	ret
DllEntry ENDP
END DllEntry

注入DLL:

代码语言:javascript复制
.data
	szMyDll        db "lyshark.dll",0h       ; 要注入的DLL
	szDllKernel    db "Kernel32.dll",0h
	szLoadLibrary  db "LoadLibraryA",0h
	lpFileName     db "Tutorial-i386",0h      ; 指定要注入进程
	lpDllName      dd ?
.data?
	szMyDllFull    db MAX_PATH dup (?)
	lpLoadLibrary  dd ?
	dwProcessID    dd ?     
	dwThreadID     dd ?
	hProcess       dd ?
.code
	main PROC
; 准备工作:获取dll的全路径文件名、获取LoadLibrary函数地址等
		invoke GetCurrentDirectory,MAX_PATH,addr szMyDllFull
		invoke lstrcat,addr szMyDllFull,addr szMyDll
		invoke GetModuleHandle,addr szDllKernel
		invoke GetProcAddress,eax,offset szLoadLibrary
		mov lpLoadLibrary,eax

; 查找文件管理器窗口并获取进程ID,然后打开进程
		invoke FindWindow,NULL,addr lpFileName
		invoke GetWindowThreadProcessId,eax,offset dwProcessID
  		mov dwThreadID,eax
  		invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessID
		mov hProcess,eax

; 在进程中分配空间并将DLL文件名拷贝过去,然后创建一个LoadLibrary线程
		invoke VirtualAllocEx,hProcess,NULL,MAX_PATH,MEM_COMMIT,PAGE_READWRITE
		mov lpDllName,eax
		invoke WriteProcessMemory,hProcess,eax,offset szMyDllFull,MAX_PATH,NULL
		invoke CreateRemoteThread,hProcess,NULL,0,lpLoadLibrary,lpDllName,0,NULL
		ret
	main endp
end main

◆远程线程代码注入◆

注入器: 新建main.asm

代码语言:javascript复制
.data
	lpLoadLibrary      dd ?
	lpGetProcAddress   dd ?
	lpGetModuleHandle  dd ?
	dwProcessID        dd ?
	dwThreadID         dd ?
	hProcess           dd ?
	lpRemoteCode       dd ?
.const
	ProcHandle        db "lyshark.exe",0h
	KernelBase        db "Kernel32.dll",0h
	szLoadLibrary     db "LoadLibraryA",0h
	szGetProcAddress  db "GetProcAddress",0h
	szGetModuleHandle db "GetModuleHandleA",0h
.code
include Macro.inc
include ShellCode.asm
	main proc
		invoke GetModuleHandle,addr KernelBase
		mov ebx,eax
		invoke GetProcAddress,ebx,offset szLoadLibrary
		mov lpLoadLibrary,eax
		invoke GetProcAddress,ebx,offset szGetProcAddress
		mov lpGetProcAddress,eax
		invoke GetProcAddress,ebx,offset szGetModuleHandle
		mov lpGetModuleHandle,eax

		invoke FindWindow,NULL,addr ProcHandle
		invoke GetWindowThreadProcessId,eax,offset dwProcessID
		mov dwThreadID,eax
		invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessID
		mov hProcess,eax

		invoke VirtualAllocEx,hProcess,NULL,2048,MEM_COMMIT,PAGE_EXECUTE_READWRITE
			.if eax
				mov lpRemoteCode,eax
				invoke WriteProcessMemory,hProcess,lpRemoteCode,offset REMOTE_CODE_START,1024,NULL
				invoke WriteProcessMemory,hProcess,lpRemoteCode,offset lpLoadLibrary,sizeof dword * 3,NULL
				mov eax,lpRemoteCode
				add eax,offset _RemoteThread - offset REMOTE_CODE_START
				invoke CreateRemoteThread,hProcess,NULL,0,eax,0,0,NULL
				invoke CloseHandle,eax
			.endif
			invoke CloseHandle,hProcess	
	invoke ExitProcess,NULL
	ret
	main endp
end main

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

代码语言:javascript复制
; --------------------------------------------
; 翻转参数字节序
reverseArgs macro arglist:VARARG
	LOCAL txt,count
	txt TEXTEQU <>
	count=0
	for i,<arglist>
		count = count 1
		txt TEXTEQU @CatStr(i,<!,>,<%txt>)
	endm
	if count GT 0
		txt SUBSTR txt,1,@SizeStr(%txt)-1
	endif
	exitm txt
endm
; --------------------------------------------
; 创建类似于INVOKE的宏代码
_invoke macro _Proc,args:VARARG
	LOCAL count
	count = 0
%	for i,< reverseArgs( args ) >
		count = count 1
		push i
	endm
	call dword ptr _Proc    
endm

注入代码: shellcode.asm

代码语言:javascript复制
REMOTE_CODE_START equ this byte
_lpLoadLibrary      dd ?
_lpGetProcAddress   dd ?
_lpGetModuleHandle  dd ?

; --------------------------------------------
; 存放静态资源,比如常量,字符串等.
_hInstance          dd ?
_szShowTitle        db "hello lyshark",0h

; --------------------------------------------
; 存放获取到的指针
_lpDllUser          dd ?
_lpMessageBox       dd ?
; --------------------------------------------
; 放入导入函数的字符串
_szDllUser		db	"user32.dll",0h
_szMessageBox           db      "MessageBoxA",0h,0
; --------------------------------------------
_RemoteThread proc uses ebx esi edi
		LOCAL @hModule
; --------------------------------------------
; 计算指令的偏移地址,用ebx作为基址指针
		call @F
		@@:
		pop ebx
		sub ebx,offset @B
; --------------------------------------------
		_invoke [ebx   _lpGetModuleHandle],NULL         ; 取当前模块句柄
		mov [ebx   _hInstance],eax
		lea eax,[ebx   offset _szDllUser]           
		_invoke [ebx   _lpGetModuleHandle],eax          ; 取user32.dll模块句柄
		mov @hModule,eax
; --------------------------------------------
; 循环获取每个导入函数的地址,并放入指针变量保存
		lea esi,[ebx   offset _szMessageBox]            ; 循环获取,从该函数起始地址处
		lea edi,[ebx   offset _lpMessageBox]
		.while TRUE
			_invoke	[ebx   _lpGetProcAddress],@hModule,esi
			mov [edi],eax       ; 获取到函数地址后,放入导入函数字符串中
			add edi,4           ; 每次递增4字节,指向下一个函数,遇到0则停止
			@@:
			lodsb
			or al,al
			jnz @B
			.break .if !byte ptr [esi]
		.endw
; --------------------------------------------
		;lea esi,[ebx  offset _szMessageBox]            ; 取msgbox模块地址
		;_invoke [ebx _lpGetProcAddress],@hModule,esi   ; 获取地址
		;mov [ebx _lpMessageBox],eax                    ; 存入变量中
		lea esi,[ebx   offset _szShowTitle]             ; 获取弹窗资源
		_invoke [ebx   _lpMessageBox],0,esi,eax,0       ; 调用信息框
		ret
_RemoteThread endp

◆创建Windows钩子◆

创建DLL文件: hookdll.dll

代码语言:javascript复制
	.386 
	.model flat,stdcall 
	option casemap:none 

include windows.inc
include user32.inc
include kernel32.inc
includelib user32.lib
includelib kernel32.lib

.data?
	hInstdll dd ?          ; dll句柄
	hHook    dd ?          ; 钩子句柄
	szAscii  db 5 dup (?)
.code
; ------------------------------------------------------------------
; 钩子回调函数,这里按键后,弹出信息框提示
CallBack proc nCode:DWORD,wParam:DWORD,lParam:DWORD
	LOCAL @szKeyState[256]:byte
	invoke CallNextHookEx,hHook,nCode,wParam,lParam 
	invoke GetKeyboardState,addr @szKeyState
	invoke GetKeyState,VK_SHIFT
	mov @szKeyState VK_SHIFT,al
	mov ecx,lParam
	shr ecx,16
	invoke ToAscii,wParam,ecx,addr @szKeyState,addr szAscii,0
	mov byte ptr szAscii [eax],0
	invoke MessageBox,NULL,addr wParam,0,MB_OK    ; 弹出信息框
	ret
CallBack endp
; ------------------------------------------------------------------
; 加载钩子,安装hook的子程序
installhook proc
	invoke SetWindowsHookEx,WH_KEYBOARD,addr CallBack,hInstdll,NULL
	mov hHook,eax
	ret
installhook endp
; ------------------------------------------------------------------
; 卸载钩子,清除hook的子程序
uninstallhook proc
	invoke UnhookWindowsHookEx,hHook
	ret
uninstallhook endp
; ------------------------------------------------------------------
; DllMain 程序入口函数
	DllMain proc _hInstance:HINSTANCE,_dwReason:DWORD, _dwResverved:DWORD
		.if(_dwReason == DLL_PROCESS_ATTACH)
			push _hInstance
			pop hInstdll
		.elseif(_dwReason == DLL_PROCESS_DETACH)
			call uninstallhook
		.endif
			mov eax,TRUE
			ret
	DllMain endp
end DllMain

创建inc文件: hookdll.inc

代码语言:javascript复制
installhook proto
uninstallhook proto

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

代码语言:javascript复制
LIBRARY hookdll
EXPORTS installhook
EXPORTS uninstallhook

创建主程序: 创建main.asm文件,并将hookdll.dll,hookdll.inc,hookdll.lib拷贝到目录下.

代码语言:javascript复制
include hookdll.inc
includelib hookdll.lib

.data?
	hInstance dd ?
	uMsg MSG <?>
.code
	main proc
		invoke installhook
		invoke GetModuleHandle,NULL
		mov hInstance,eax
		.while(TRUE)
			invoke GetMessage,addr uMsg,NULL,0,0
			invoke TranslateMessage,addr uMsg
			invoke DispatchMessage,addr uMsg
		.endw
		invoke uninstallhook
		ret
	main endp
end main

## 注册表和INI文件

◆注册表相关◆

遍历子键: HKEY_LOCAL_MACHINE中的子键

代码语言:javascript复制
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

创建键值:

代码语言:javascript复制
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

删除键值:

代码语言:javascript复制
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

创建子键

代码语言:javascript复制
include advapi32.inc
includelib advapi32.lib

.data
	lpszKey    db "SoftwareMicrosoft\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

删除子键:

代码语言:javascript复制
include advapi32.inc
includelib advapi32.lib

.data
	lpszKey    db "SoftwareMicrosoft\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

读取键值:

代码语言:javascript复制
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

设置开机自启动:

代码语言:javascript复制
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

代码语言:javascript复制
[lyshark]         ; 字段1
X=1024
Y=2048
Z=4096
[IniDemo]         ; 字段2
StringKey=hello,lyshark!
IntKey=123123
ToString=lyshark

遍历Section列表:

代码语言:javascript复制
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

遍历键值对

代码语言:javascript复制
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

拼接并打印字符串:

代码语言:javascript复制
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

读取:

代码语言:javascript复制
.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

添加/删除键值:

代码语言:javascript复制
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

## 通用对话框

设置页面对话框:

代码语言:javascript复制
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

打开对话框:

代码语言:javascript复制
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

保存对话框:

代码语言:javascript复制
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

选择颜色:

代码语言:javascript复制
include Comdlg32.inc
includelib Comdlg32.lib

.data
	dwBackColor     dd ?
	dwCustColors    dd 16 dup (?)
	szBuffer        db 1024 dup (?)
	szFormatColor   db "您选择的颜色值:x",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

选择字体:

代码语言:javascript复制
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

## 网络相关函数

服务端:

代码语言:javascript复制
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"))

客户端:

代码语言:javascript复制
	.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

改进版

服务端:

代码语言:javascript复制
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"))

客户端:

代码语言:javascript复制
	.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

0 人点赞