汇编语言(assembly language)是一种用于电子计算机、微处理器、微控制器或其余可编程器件的低级语言,亦称为符号语言.在汇编语言中,用助记符(Mnemonics)代替机器指令的操做码,用地址符号(Symbol)或标号(Label)代替指令或操做数的地址.在不一样的设备中,汇编语言对应着不一样的机器语言指令集,经过汇编过程转换成机器指令,广泛地说,特定的汇编语言和特定的机器语言指令集是相互对应的,不一样平台之间不可直接移植.python
熟练掌握Win32 API函数的参数传递,是软件逆向的基础,本章节内容将使用MASM汇编器,逐个编译这些源程序,你能够经过使用一些调试工具,这里推荐OllyDBG来附加编译后的可执行文件,进行逐个分析,观察二进制程序逆向后的一些变化,总结吸取经验,为之后的二进制逆向,漏洞挖掘打基础.shell
注册热键: 注册全局热键并能激活.编程
.data hMsgBox db "你按下了 CTRL + ALT + A",0h uMsg MSG <?> .code main PROC ; 41h = A | 65h=uMsg.wParam invoke RegisterHotKey,NULL,065h,MOD_CONTROL or MOD_ALT,041h .while(TRUE) invoke GetMessage,addr uMsg,NULL,0,0 .if(uMsg.message == WM_HOTKEY) ; 按下按键提示 invoke MessageBox,NULL,addr hMsgBox,addr uMsg.wParam,MB_OK .elseif(uMsg.message == WM_DESTROY) ; 程序结束后关闭热键 invoke UnregisterHotKey,NULL,065h invoke PostQuitMessage,NULL .endif .endw invoke ExitProcess,0 main ENDP END main
最小化指定窗口:windows
.data FindName db "qq",0h handle dd ? .code main PROC invoke FindWindow,NULL,addr FindName mov handle,eax .if(handle != 0) ; 找到则隐藏窗口 invoke ShowWindow,handle,SW_HIDE .else ; 没有找到则显示 invoke ShowWindow,handle,SW_SHOW .endif invoke ExitProcess,0 main ENDP END main
显示当前目录等:api
.data stStartUp STARTUPINFO <?> .code main PROC invoke GetStartupInfo,addr stStartUp mov eax,stStartUp.lpDesktop mov eax,stStartUp.lpTitle ; 显示当前软件目录 invoke ExitProcess,0 main ENDP END main
取系统版本等:网络
.data version OSVERSIONINFO <?> lpsystem SYSTEM_INFO <?> .code main PROC invoke GetSystemInfo,addr lpsystem mov ax,lpsystem.wProcessorArchitecture invoke GetVersionEx,addr version mov eax,version.dwBuildNumber invoke ExitProcess,0 main ENDP END main
取命令行参数:app
.data cmdline dword ? .code main PROC invoke GetCommandLine ; 获取命令行参数 mov cmdline,eax invoke ExitProcess,0 main ENDP END main
获取环境变量:socket
.data szBuffer DB 200 dup(?) ; 保存到缓冲区 szVarName DB "PATH",0h ; 获取set PATH lpVar DD ? .code main PROC invoke GetEnvironmentVariable,addr szVarName,addr szBuffer,sizeof szBuffer xor eax,eax invoke GetEnvironmentStrings mov lpVar,eax invoke ExitProcess,0 main ENDP END main
设置环境变量:函数
.data lpVarName DB "PATH",0h lpValue DB "E:\RadASM\masm32\bin",0h .code main PROC invoke SetEnvironmentVariable,addr lpVarName,addr lpValue invoke ExitProcess,0 main ENDP END main
运行系统软件: 下载并运行一个软件.工具
include urlmon.inc includelib urlmon.lib .data szURL DB "https://www.mkdirs.com/lyshark.exe",0h szFileName DB "C:\\lyshark.exe",0h WinRun DB "C:/lyshark.exe",0h .code main proc invoke URLDownloadToFile,NULL,addr szURL,addr szFileName,0,NULL invoke WinExec,offset WinRun,SW_SHOW ret main endp end main
获取本地时间:
.data systime SYSTEMTIME <> .code main PROC invoke GetLocalTime,addr systime ; 获取当前时间 mov ax,systime.wYear mov bx,systime.wMonth mov cx,systime.wDay invoke SetLocalTime,addr systime ; 设置当前时间 main ENDP END main
获取系统时间:
.data systime SYSTEMTIME <> .code main PROC invoke GetSystemTime,addr systime mov ax,systime.wYear mov bx,systime.wMonth mov cx,systime.wDay invoke SetSystemTime,addr systime main ENDP END main
获取时间差: eax保存的就是执行代码后的时间差,单位毫秒
.data dwTock DWORD ? .code main PROC invoke GetTickCount mov dwTock,eax invoke GetTickCount sub eax,dwTock main ENDP END main
获取内存状态: GlobalMemourStatus
.data Mem MEMORYSTATUS <> .code main PROC invoke GlobalMemoryStatus,offset Mem mov eax,Mem.dwLength ; 获取结构长度 mov eax,Mem.dwMemoryLoad ; 已用内存百分比 mov eax,Mem.dwTotalPhys ; 物理内存总数 mov eax,Mem.dwAvailPhys ; 可用物理内存 mov eax,Mem.dwTotalPageFile ; 交换文件的总大小 mov eax,Mem.dwAvailPageFile ; 交换文件可用大小 mov eax,Mem.dwTotalVirtual ; 用户可用的地址空间 mov eax,Mem.dwAvailVirtual ; 用户空闲地址空间 invoke ExitProcess,0 main ENDP END main
申请内存:
.data lpMemory DWORD ? .code main PROC ;GMEM_FIXED=申请内存;GMEM_ZEROINIT申请并初始化为0 invoke GlobalAlloc,GMEM_ZEROINIT,1024 .if(eax != NULL) mov lpMemory,eax ; lpMemory 为分配成功后的内存指针 .endif invoke GlobalFree,lpMemory ; 释放内存空间 invoke ExitProcess,0 main ENDP END main
扩大内存空间:
.data lpMemory DWORD ? reMemory DWORD ? .code main PROC invoke GlobalAlloc,GMEM_ZEROINIT,100 mov lpMemory,eax invoke GlobalReAlloc,lpMemory,1024,GMEM_ZEROINIT or GMEM_MOVEABLE .if(eax != NULL) mov reMemory,eax .endif invoke GlobalFree,lpMemory invoke GlobalFree,reMemory invoke ExitProcess,0 main ENDP END main
锁定/解锁内存: 程序须要使用这块内存能够将其锁定,使用完后能够解除锁定.
.data lpMemory DWORD ? Locks DWORD ? .code main PROC invoke GlobalAlloc,GMEM_ZEROINIT,100 mov lpMemory,eax invoke GlobalLock,lpMemory ; 锁定内存空间 .if(eax != NULL) mov Locks,eax ; 锁定成功后,返回原内存地址 .endif invoke GlobalUnlock,lpMemory ; 解锁内存空间,成功返回非0 invoke ExitProcess,0 main ENDP END main
可移动/可丢弃内存: 可移动内存容许在不使用时改变其内存地址,可丢弃当内存不足时可将其丢弃。
.data lp_Move_Memory DWORD ? lp_Disb_Memory DWORD ? .code main PROC invoke GlobalAlloc,GMEM_MOVEABLE or GMEM_ZEROINIT,1024 ; 分配可移动的内存 .if(eax != NULL) mov lp_Move_Memory,eax ; 分配成功则保存其内存地址 .endif invoke GlobalAlloc,GMEM_DISCARDABLE or GMEM_ZEROINIT,1024 ; 分配可丢弃的内存 .if(eax != NULL) mov lp_Disb_Memory,eax .endif invoke ExitProcess,0 main ENDP END main
复制内存地址: 将源地址复制到目标地址中,总共复制40个字节.
.data Source DWORD 1,2,3,4,5 DWORD 6,7,8,9,0 Dest DWORD 0,0,0,0,0 DWORD 0,0,0,0,0 .code main PROC lea eax,Source ; 源地址 lea ebx,Dest ; 目标地址 invoke RtlMoveMemory,addr Dest,addr Source,40 ;将源地址复制到目标地址,复制40个字节 invoke ExitProcess,0 main ENDP END main
填充内存: 将Memory中的字节数据,所有填充替换为A,或填充为0
.data Memory DB 1,2,3,4,5,6,7,8,9,0 DB 1,2,3,4,5,6,7,8,9,0 DB 1,2,3,4,5,6,7,8,9,0 Fill DB "A",0 .code main PROC lea eax,Memory ; 填充Memory内存,向后填充1024字节,填充为A invoke RtlFillMemory,addr Memory,1024,addr Fill ;填充Memory内存,向后填充1024字节,所有初始化为0 invoke RtlZeroMemory,addr Memory,1024 invoke ExitProcess,0 main ENDP END main
建立私有堆: 建立一个1024字节的私有堆,并返回内存地址.
.data HeapMain DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,1024,0 ; 保留1024字节物理内存 .if(eax != NULL) mov HeapMain,eax ; 成功分配则返回内存地址 .endif invoke HeapDestroy,HeapMain ; 释放堆空间 invoke ExitProcess,0 main ENDP END main
分配内存块: 在建立的堆中分配内存块.
.data lpHeap DWORD ? lpMem DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,1024,0 ; 保留1024字节物理内存 mov lpHeap,eax ; 保存分配的地址 invoke HeapAlloc, lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字节空间 .if(eax != NULL) mov lpMem,eax ; 分配成功,保存内存地址 .endif invoke HeapDestroy,lpHeap ; 释放堆空间 invoke ExitProcess,0 main ENDP END main
在堆中分配内存:
.data lpHeap DWORD ? lpMemory DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,1024,0 ; 建立堆句柄,并保留1024字节 mov lpHeap,eax ; 保存分配句柄地址 invoke HeapAlloc,lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字节的地址 mov lpMemory,eax ; 分配并返回内存地址 invoke HeapDestroy,lpHeap ; 释放堆空间 invoke ExitProcess,0 main ENDP END main
增长堆内存空间: 在本来来的内存地址基础上,增长内存空间
.data lpHeap DWORD ? lpMemory DWORD ? ReMemory DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,4096,0 ; 建立堆句柄,并保留4096字节 mov lpHeap,eax ; 保存分配句柄地址 invoke HeapAlloc,lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字节的地址 mov lpMemory,eax ; 分配并返回内存地址 ; 从新分配内存空间,在原内存1024上调整到2048 invoke HeapReAlloc,lpHeap,HEAP_ZERO_MEMORY,lpMemory,2048 mov ReMemory,eax ; 保存返回内存地址 invoke HeapDestroy,lpHeap ; 释放堆空间 invoke ExitProcess,0 main ENDP END main
计算堆空间大小:
.data lpHeap DWORD ? lpMemory DWORD ? Mem_Size DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,4096,0 ; 建立堆句柄,并保留4096字节 mov lpHeap,eax ; 保存分配句柄地址 invoke HeapAlloc,lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字节的地址 mov lpMemory,eax ; 分配并返回内存地址 invoke HeapSize,lpHeap,HEAP_NO_SERIALIZE,lpMemory ; 计算堆空间的大小 mov Mem_Size,eax ; 取地址大小,此处为1024 invoke HeapDestroy,lpHeap ; 释放堆空间 invoke ExitProcess,0 main ENDP END main
锁定/解锁堆:
.data lpHeap DWORD ? lpMemory DWORD ? .code main PROC invoke HeapCreate,HEAP_NO_SERIALIZE,4096,0 ; 建立堆句柄,并保留4096字节 mov lpHeap,eax ; 保存分配句柄地址 invoke HeapAlloc,lpHeap,HEAP_ZERO_MEMORY,1024 ; 分配1024字节的地址 mov lpMemory,eax ; 分配并返回内存地址 invoke HeapLock,lpHeap ; 锁定内存堆 invoke HeapUnlock,lpHeap ; 解锁内存堆 invoke HeapDestroy,lpHeap ; 释放堆空间 invoke ExitProcess,0 main ENDP END main
保留地址空间: 保留的空间不能够直接使用.
.data lpAddr DWORD ? .code main PROC invoke VirtualAlloc,NULL,1024,MEM_RESERVE,PAGE_NOACCESS ; 保留内存地址 mov lpAddr,eax invoke VirtualFree,lpAddr,1024,MEM_RELEASE ; 释放地址空间 invoke ExitProcess,0 main ENDP END main
分配地址空间:
.data lpAddr DWORD ? .code main PROC invoke VirtualAlloc,NULL,1024,MEM_COMMIT,PAGE_READWRITE ; 分配内存地址 .if(eax != NULL) mov lpAddr,eax .endif invoke VirtualFree,lpAddr,1024,MEM_RELEASE ; 释放内存地址 invoke ExitProcess,0 main ENDP END main
保护/锁定内存:
.data lpAddr DWORD ? .code main PROC invoke VirtualAlloc,NULL,1024,MEM_COMMIT,PAGE_READWRITE ; 保留内存地址 .if(eax != NULL) mov lpAddr,eax .endif invoke VirtualProtect,lpAddr,1024,PAGE_NOACCESS,NULL ; 设置内存为只读 invoke VirtualLock,lpAddr,1024 ; 锁定内存地址 invoke VirtualUnlock,lpAddr,1024 ; 解除内存锁定 invoke VirtualFree,lpAddr,1024,MEM_RELEASE ; 释放地址空间 invoke ExitProcess,0 main ENDP END main
内存状态测试:
.data lpMemory DWORD 1024 lpString BYTE "hello lyshark",0 lpStatus DWORD ? .code main PROC mov lpMemory,1024 lea eax,lpMemory invoke IsBadCodePtr,lpMemory ; 内存的第一个字节是否可读 mov lpStatus,eax ; 可读返回0不然返回非0 invoke IsBadReadPtr,lpMemory,1024 ; 测试前1024字节是否可读 mov lpStatus,eax ; 可读返回0不然返回非0 invoke IsBadWritePtr,lpMemory,1024 ; 测试前1024字节是否可写 mov lpStatus,eax ; 可写返回0不然返回非0 invoke IsBadStringPtr,addr lpString,sizeof lpString ; 测试字符串是否可读 mov lpStatus,eax ; 可读返回0不然返回非0 invoke ExitProcess,0 main ENDP END main
打开/关闭文件: 打开文件成功返回文件句柄,失败则返回error
.data szFileName db "e:\lyshark.log",0h ; 打开的文件名称 hFile dd ? ; 打开成功后返回的句柄 .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0, \ OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFile,eax .endif invoke ExitProcess,0 main ENDP END main
建立文件: CREATE_ALWAYS=文件存在则清空内容,CREATE_NEW=文件存在则返回失败
.data szNewFile db "C:\lyshark.log",0h hFile dd ? .code main PROC invoke CreateFile,addr szNewFile,GENERIC_WRITE,FILE_SHARE_READ,0, \ CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFile,eax .endif invoke CloseHandle,hFile invoke ExitProcess,0 main ENDP END main
移动文件指针:
.data szFileName DB "c:\lyshark.log",0h hFileHandl DD ? .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFileHandl,eax .endif invoke SetFilePointer,hFileHandl,0,NULL,FILE_CURRENT ; eax=获取的文件指针位置 xor eax,eax invoke SetFilePointer,hFileHandl,10,NULL,FILE_BEGIN ; 将文件指针向后移动10个字节 xor eax,eax invoke SetFilePointer,hFileHandl,0,NULL,FILE_CURRENT ; 再次获取指针位置,eax=10 invoke ExitProcess,0 main ENDP END main
设置指针到末尾:
.data szFileName DB "e:\lyshark.log",0h hFileHandl DD ? .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFileHandl,eax .endif invoke SetEndOfFile,hFileHandl ; 将文件位置设置到末尾 invoke SetFilePointer,hFileHandl,0,NULL,FILE_CURRENT ; 获取指针位置 invoke ExitProcess,0 main ENDP END main
读取文件内容:
.data szFileName DB "C:\lyshark.log",0h hFileHandle DD ? szReadBuff DB ? ; 每次读取一个字节,放入该变量中 ByteRead DB ? .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFileHandle,eax .endif invoke SetFilePointer,hFileHandle,1,NULL,FILE_BEGIN ; 取第一个字符 invoke ReadFile,hFileHandle,addr szReadBuff,sizeof szReadBuff,addr ByteRead,0 mov al,[szReadBuff] ; 将取出来的字符放入al寄存器中 invoke ExitProcess,0 main ENDP END main
写入文件内容:
.data szFileName DB "C:\lyshark.log",0h hFileHandle DD ? ; 获取文件句柄 lpBuffer DB "hello lyshark",0h ; 要写入的字符串 reWrite DD ? ; 返回写入成功字节数 .code main PROC invoke CreateFile,addr szFileName,GENERIC_WRITE,FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 .if(eax != INVALID_HANDLE_VALUE) mov hFileHandle,eax .endif ; 将lpBuffer中的数据写入到文件,写入大小为sizeof获取的大小. invoke WriteFile,hFileHandle,addr lpBuffer,sizeof lpBuffer,addr reWrite,NULL invoke FlushFileBuffers,hFileHandle ; 强制刷新写入 invoke ExitProcess,0 main ENDP END main
获取文件长度:
.data szFileName DB "E:\lyshark.log",0h hFileHandle DD ? FilesSize DD ? .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 mov hFileHandle,eax invoke GetFileSize,hFileHandle,NULL ; 取出文件的长度 mov FilesSize,eax ; 放入FilesSize里面 invoke ExitProcess,0 main ENDP END main
获取文件日期:
.data szFileName DB "E:\lyshark.log",0h hFileHandle DD ? create FILETIME <> ; 存储建立文件的日期 systime SYSTEMTIME <> ; 存储转换后的文件日期 .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 mov hFileHandle,eax ; 取出文件句柄 invoke GetFileTime,hFileHandle,addr create,NULL,NULL ; 只取出建立日期,其余的用NULL填充 invoke FileTimeToSystemTime,addr create,addr systime ; 转换成经常使用格式 mov ax,systime.wYear ; 取出年份 mov bx,systime.wMonth ; 取出月份 mov cx,systime.wDay ; 取出天数 invoke ExitProcess,0 main ENDP END main
修改文件日期:
.data szFileName DB "E:\lyshark.log",0h hFileHandle DD ? create FILETIME <> ; 存储建立文件的日期 systime SYSTEMTIME <> ; 存储转换后的文件日期 .code main PROC invoke CreateFile,addr szFileName,GENERIC_READ,FILE_SHARE_READ,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0 mov hFileHandle,eax ; 取出文件句柄 mov systime.wYear,19 ; 先填写结构 mov systime.wMonth,19 invoke SystemTimeToFileTime,addr systime,addr create ; 转换成filetime invoke SetFileTime,hFileHandle,addr create,NULL,NULL ; 回写 invoke ExitProcess,0 main ENDP END main
拷贝/移动/删除/文件:
.data lpSourceFile DB "C:\lyshark.log",0h lpDestFile DB "E:\wang.log",0h .code main PROC invoke CopyFile,addr lpSourceFile,addr lpDestFile,TRUE ; 拷贝文件 invoke MoveFile,addr lpDestFile,addr lpSourceFile ; 移动文件 invoke DeleteFile,addr lpSourceFile invoke DeleteFile,addr lpDestFile ; 删除文件 invoke ExitProcess,0 main ENDP END main
显示全部驱动器:
.data lpLength BYTE ? lpDrives DWORD 0 dup(1024) .code main PROC invoke GetLogicalDrives ; 获取卷标 invoke GetLogicalDriveStrings,addr lpLength,addr lpDrives ; 同上 lea esi,[lpDrives] ; 显示C盘 lea esi,[lpDrives+4] ; 显示D盘 invoke ExitProcess,0 main ENDP END main
获取磁盘类型:
.data lpDrive DB "c:\",0 .code main PROC invoke GetDriveType,addr lpDrive invoke ExitProcess,0 main ENDP END main
获取磁盘详细信息:(有问题的)
.data lpRoot DB "c:\",0h lpBuffer DB 1024 dup(?) dwSerial DD ? lpType DB 1024 dup(?) .code main PROC invoke GetVolumeInformation,addr lpRoot, \ addr lpBuffer,1024,addr dwSerial,255, \ FILE_CASE_PRESERVED_NAMES,addr lpType,1024 lea eax,lpRoot lea ebx,lpBuffer lea ecx,dwSerial lea edx,lpType invoke ExitProcess,0 main ENDP END main
检测逻辑驱动器字节:
.data lpRoot DB "c:\",0h lpSect DD ? lpByte DD ? lpNumb DD ? lpTota DD ? .code main PROC ; 总容量 = 簇总数 * 每簇扇区数 * 每扇区字节数 ; 空闲字节数 = 未使用的簇 * 每扇区数 * 每扇区字节数 invoke GetDiskFreeSpace,addr lpRoot,addr lpSect,addr lpByte,addr lpNumb,addr lpTota mov eax,lpSect ; 返回每一个簇的扇区数 mov eax,lpByte ; 返回每扇区的字节数 mov eax,lpNumb ; 返回未使用的簇的数量 mov eax,lpTota ; 返回簇的总数 invoke ExitProcess,0 main ENDP END main
获取当前目录:
.data lpRoot DB ? .code main PROC invoke GetCurrentDirectory,1024,addr lpRoot ; 获取当前目录 lea eax,lpRoot invoke GetTempPath,1024,addr lpRoot ; 获取临时目录 lea eax,lpRoot invoke GetSystemDirectory,addr lpRoot,1024 ; 获取系统目录 lea eax,lpRoot invoke ExitProcess,0 main ENDP END main
建立删除目录:
.data lpRoot DB "c:\windows\",0 szDir DB "c:\lyshark\wang",0 .code main PROC invoke SetCurrentDirectory,addr lpRoot ; 设置默认路径 invoke CreateDirectory,addr szDir,NULL ; 建立目录 invoke RemoveDirectory,addr szDir ; 删除目录 invoke ExitProcess,0 main ENDP END main
建立进程:
.data szBuffer DWORD ? szFileName DWORD ? szCmdLine DWORD ? szBlank DWORD ? stStartUp DWORD ? stProcInfo DWORD ? .code main PROC invoke lstrcpy,addr szBuffer,addr szFileName .if(szCmdLine) invoke lstrcat,addr szBuffer,addr szBlank invoke lstrcat,addr szBuffer,addr szCmdLine .endif invoke GetStartupInfo,addr stStartUp invoke CreateProcess,NULL,addr szBuffer,NULL,NULL,NULL, \ NORMAL_PRIORITY_CLASS,NULL,NULL,addr stStrartUp,addr stProcInfo ret main ENDP END main
取全部进程信息: 使用快照函数,一次性遍历出全部的进程列表.
.data hSnapShot dd ? stProcess PROCESSENTRY32 <?> .code main proc invoke CreateToolhelp32Snapshot,TH32CS_SNAPPROCESS,0 ; 建立快照 mov hSnapShot,eax ; 保存句柄 mov stProcess.dwSize,sizeof stProcess ; 保存快照大小 invoke Process32First,hSnapShot,addr stProcess ; 取第一个进程数据 .while(eax) ; eax!=0则继续循环 invoke Process32Next,hSnapShot,addr stProcess ; 取下一个进程数据 .endw invoke CloseHandle,hSnapShot ; 关闭进程句柄 ret main endp end main
取指定进程PID: 获取xshell进程的PID号
.data FindID DB "Xshell",0h ThreadID DD ? ProcessID DD ? ; 获取到的进程号 .code main PROC invoke FindWindow,NULL,addr FindID .if(FindID != 0) mov ThreadID,eax .endif invoke GetWindowThreadProcessId, ThreadID,offset ProcessID mov eax,ProcessID ret main ENDP END main
内存示范例子: 请手动编译该例子,并命名为lyshark.exe
,接下来的读内存/写内存
例子将用它讲解.
.386p .model flat,stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib .data titles DB "box",0h check_ok DB "破解完成.",0h check_err DB "破解失败",0h .code main proc xor eax,eax .if eax invoke MessageBox,NULL,addr check_ok,addr titles,MB_OK .else invoke MessageBox,NULL,addr check_err,addr titles,MB_OK .endif ret main endp end main
读取进程数据: 读取指定的内存地址中的数据,并将其放入ReadBuf缓冲区中.
OEP equ 004198402 ; 读取的范围 .data stStartUp STARTUPINFO <> ; 初始化 stProInfo PROCESS_INFORMATION <> ; 该进程的进程信息 ExeRun DB "C:\\lyshark.exe",0h ; 要打开的进程名称 ReadBuf DD ? ; 读取到的数据内容 .code main proc invoke GetStartupInfo,addr stStartUp invoke CreateProcess,addr ExeRun,NULL,NULL,NULL,NULL,\ NORMAL_PRIORITY_CLASS,0,0,addr stStartUp,addr stProInfo .if(eax) ; 读取当前进程,读取内存地址为OEP,每次读取8个字节,读取到放入ReadBuf invoke ReadProcessMemory,stProInfo.hProcess,OEP,addr ReadBuf,8,NULL lea eax,ReadBuf .endif ret main endp end main
写入进程数据: 写入进程数据,将跳转替换为nop指令的机器码.
OEP equ 004198402 ; 读取的范围 .data stStartUp STARTUPINFO <> ; 初始化 stProInfo PROCESS_INFORMATION <> ; 该进程的进程信息 ExeRun DB "C:\\lyshark.exe",0h ; 要打开的进程名称 lpPatch DB 90h,90h,90h,90h ; 要替换的汇编指令 redPatch DD ? ; 替换完后保存替换结果 .code main proc invoke GetStartupInfo,addr stStartUp invoke CreateProcess,addr ExeRun,NULL,NULL,NULL,NULL,\ NORMAL_PRIORITY_CLASS,0,0,addr stStartUp,addr stProInfo .if(eax) ; 写入当前进程,写入内存地址为OEP,替换8个字节,替换成nop invoke WriteProcessMemory,stProInfo.hProcess,OEP,addr lpPatch,4,NULL .if(eax != 0) ; 若是不等于0则说明补丁替换完成 invoke ReadProcessMemory,stProInfo.hProcess,OEP,addr redPatch,4,NULL lea eax,redPatch ; 将补丁地址取出,并用OD分析,为9090则替换完成. .endif .endif ret main endp end main
建立线程函数: 默认状况下,线程建立后会被系统挂起,须要执行ResumeThread函数,将其放入前台.
.data ThreadID DWORD ? ; 保存返回线程ID hThread DWORD ? ; 保存线程句柄 .code _MyThread proc lParam ; lParam为传递的参数 xor eax,eax ret _MyThread endp main PROC invoke CreateThread,NULL,0,addr _MyThread,NULL,CREATE_SUSPENDED,addr ThreadID .if(eax) mov hThread,eax ; 将线程句柄放入hThread .endif invoke ResumeThread, hThread ; 运行这个线程 ret main ENDP END main
建立事件:
.data lpEventName DWORD ? ; 建立的时间名称 hEventID DWORD ? ; 成功后返回的句柄 .code main PROC invoke CreateEvent,NULL,TRUE,TRUE,addr lpEventName .if(eax != NULL) mov hEventID,eax .endif invoke WaitForSingleObject,addr hEventID,INFINITE ; 等待一个事件 invoke SetEvent,addr hEventID ; 将事件的状态设置为:"置位" invoke ResetEvent,hEventID ; 将事件的状态设置为:"复位" invoke CloseHandle,hEventID ; 关闭这个句柄 ret main ENDP END main
建立dll: 这里咱们建立一个lyshark.asm
.
.586 .model flat,stdcall option casemap:none include windows.inc include kernel32.inc include user32.inc includelib kernel32.lib includelib user32.lib .data lpText db "hello lyshark",0 lpCapt db "MsgBox",0 .code DllEntry PROC _hInstance,_dwReason,_dwReserved mov eax,TRUE ret DllEntry ENDP _MsgBox PROC ; 无参数的信息框 invoke MessageBox,NULL,addr lpText,addr lpCapt,MB_OK ret _MsgBox ENDP _MySum PROC Num_x:DWORD,Num_y:DWORD ; 一个加法计算的函数 mov eax,Num_x add eax,Num_y ret _MySum endp end DllEntry
建立def: 而后在当前目录下建立一个lyshark.def
文件,用来声明导入库的函数名.
EXPORTS _MsgBox EXPORTS _MySum
建立inc文件: 在当前目录继续建立一个lyshark.inc
文件,并写入相应的导入函数.
_MsgBox PROTO _MySum PROTO Num_X:DWORD,Num_Y:DWORD
生成dll: 生成dll执行以下代码.
ml /c /coff lyshark.asm link /SUBSYSTEM:WINDOWS /RELEASE /DLL /DEF:lyshark.def /OUT:"lyshark.dll" "lyshark.obj"
直接调用dll:
include lyshark.inc includelib lyshark.lib .code main proc invoke _MsgBox invoke _MySum,100,200 ret main endp end main
动态装载dll(无参):
.data szMyDll db "lyshark.dll",0h ; 装入的动态连接库名称 szMsgBox db "_MsgBox",0h ; 装入的函数名(无参) hLibMod dd ? ; dll的句柄 lpMsgBox dd ? ; 函数的地址 .code main proc invoke LoadLibrary,addr szMyDll ; 加载指定的dll .if(eax) mov hLibMod,eax invoke GetProcAddress,hLibMod,addr szMsgBox mov lpMsgBox,eax call lpMsgBox ; 调用MsgBox .endif invoke FreeLibrary,hLibMod ; 传递句柄,并释放dll ret main endp end main
动态装载dll(有参):
.data szMyDll db "lyshark.dll",0h ; 装入的动态连接库名称 szMySum db "_MySum",0h ; 装入的函数名(无参) hLibMod dd ? ; dll的句柄 lpMySum dd ? ; 函数的地址 Num_X dd 10 ; 参数x=10 Num_Y dd 20 ; 参数y=20 .code main proc invoke LoadLibrary,addr szMyDll ; 加载指定的dll .if(eax) mov hLibMod,eax invoke GetProcAddress,hLibMod,addr szMySum mov lpMySum,eax push Num_Y ; 压入第二个参数 push Num_X ; 压入第一个参数 call lpMySum ; 调用_MySum 函数 .endif invoke FreeLibrary,hLibMod ; 传递句柄,并释放dll ret main endp end main
动态调用函数: 动态的加载并使用一个函数.
.data szDllKernel db "Kernel32.dll",0h szFunction db "GetVersion",0h CallAddr dd ? .code main proc invoke GetModuleHandle,offset szDllKernel ; 取出模块句柄 .if(eax != 0) invoke GetProcAddress,eax,offset szFunction ; 取出函数的地址 mov CallAddr,eax ; 保存函数地址 .endif call CallAddr ; 直接调用kernel32.GetVersion ret main endp end main
编写DLL: 首先编写一个dLL用来测试
.386 .model flat,stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib .data szText DB "welcome to asm",0h szCaption DB "MsgBox",0h .code Main PROC invoke MessageBox,NULL,addr szText,addr szCaption,MB_OK ret Main endp DllEntry PROC _hInstance,_dwReason,_dwReserved call Main mov eax,TRUE ret DllEntry ENDP END DllEntry
注入DLL:
.data szMyDll db "\lyshark.dll",0h ; 要注入的DLL szDllKernel db "Kernel32.dll",0h szLoadLibrary db "LoadLibraryA",0h lpFileName db "Tutorial-i386",0h ; 指定要注入进程 lpDllName dd ? .data? szMyDllFull db MAX_PATH dup (?) lpLoadLibrary dd ? dwProcessID dd ? dwThreadID dd ? hProcess dd ? .code main PROC ; 准备工做:获取dll的全路径文件名、获取LoadLibrary函数地址等 invoke GetCurrentDirectory,MAX_PATH,addr szMyDllFull invoke lstrcat,addr szMyDllFull,addr szMyDll invoke GetModuleHandle,addr szDllKernel invoke GetProcAddress,eax,offset szLoadLibrary mov lpLoadLibrary,eax ; 查找文件管理器窗口并获取进程ID,而后打开进程 invoke FindWindow,NULL,addr lpFileName invoke GetWindowThreadProcessId,eax,offset dwProcessID mov dwThreadID,eax invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessID mov hProcess,eax ; 在进程中分配空间并将DLL文件名拷贝过去,而后建立一个LoadLibrary线程 invoke VirtualAllocEx,hProcess,NULL,MAX_PATH,MEM_COMMIT,PAGE_READWRITE mov lpDllName,eax invoke WriteProcessMemory,hProcess,eax,offset szMyDllFull,MAX_PATH,NULL invoke CreateRemoteThread,hProcess,NULL,0,lpLoadLibrary,lpDllName,0,NULL ret main endp end main
注入器: 新建main.asm
.data lpLoadLibrary dd ? lpGetProcAddress dd ? lpGetModuleHandle dd ? dwProcessID dd ? dwThreadID dd ? hProcess dd ? lpRemoteCode dd ? .const ProcHandle db "lyshark.exe",0h KernelBase db "Kernel32.dll",0h szLoadLibrary db "LoadLibraryA",0h szGetProcAddress db "GetProcAddress",0h szGetModuleHandle db "GetModuleHandleA",0h .code include Macro.inc include ShellCode.asm main proc invoke GetModuleHandle,addr KernelBase mov ebx,eax invoke GetProcAddress,ebx,offset szLoadLibrary mov lpLoadLibrary,eax invoke GetProcAddress,ebx,offset szGetProcAddress mov lpGetProcAddress,eax invoke GetProcAddress,ebx,offset szGetModuleHandle mov lpGetModuleHandle,eax invoke FindWindow,NULL,addr ProcHandle invoke GetWindowThreadProcessId,eax,offset dwProcessID mov dwThreadID,eax invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,dwProcessID mov hProcess,eax invoke VirtualAllocEx,hProcess,NULL,2048,MEM_COMMIT,PAGE_EXECUTE_READWRITE .if eax mov lpRemoteCode,eax invoke WriteProcessMemory,hProcess,lpRemoteCode,offset REMOTE_CODE_START,1024,NULL invoke WriteProcessMemory,hProcess,lpRemoteCode,offset lpLoadLibrary,sizeof dword * 3,NULL mov eax,lpRemoteCode add eax,offset _RemoteThread - offset REMOTE_CODE_START invoke CreateRemoteThread,hProcess,NULL,0,eax,0,0,NULL invoke CloseHandle,eax .endif invoke CloseHandle,hProcess invoke ExitProcess,NULL ret main endp end main
反转宏: Macro.inc 用来翻转参数,定义_invoke
; -------------------------------------------- ; 翻转参数字节序 reverseArgs macro arglist:VARARG LOCAL txt,count txt TEXTEQU <> count=0 for i,<arglist> count = count+1 txt TEXTEQU @CatStr(i,<!,>,<%txt>) endm if count GT 0 txt SUBSTR txt,1,@SizeStr(%txt)-1 endif exitm txt endm ; -------------------------------------------- ; 建立相似于INVOKE的宏代码 _invoke macro _Proc,args:VARARG LOCAL count count = 0 % for i,< reverseArgs( args ) > count = count+1 push i endm call dword ptr _Proc endm
注入代码: shellcode.asm
REMOTE_CODE_START equ this byte _lpLoadLibrary dd ? _lpGetProcAddress dd ? _lpGetModuleHandle dd ? ; -------------------------------------------- ; 存放静态资源,好比常量,字符串等. _hInstance dd ? _szShowTitle db "hello lyshark",0h ; -------------------------------------------- ; 存放获取到的指针 _lpDllUser dd ? _lpMessageBox dd ? ; -------------------------------------------- ; 放入导入函数的字符串 _szDllUser db "user32.dll",0h _szMessageBox db "MessageBoxA",0h,0 ; -------------------------------------------- _RemoteThread proc uses ebx esi edi LOCAL @hModule ; -------------------------------------------- ; 计算指令的偏移地址,用ebx做为基址指针 call @F @@: pop ebx sub ebx,offset @B ; -------------------------------------------- _invoke [ebx + _lpGetModuleHandle],NULL ; 取当前模块句柄 mov [ebx + _hInstance],eax lea eax,[ebx + offset _szDllUser] _invoke [ebx + _lpGetModuleHandle],eax ; 取user32.dll模块句柄 mov @hModule,eax ; -------------------------------------------- ; 循环获取每一个导入函数的地址,并放入指针变量保存 lea esi,[ebx + offset _szMessageBox] ; 循环获取,从该函数起始地址处 lea edi,[ebx + offset _lpMessageBox] .while TRUE _invoke [ebx + _lpGetProcAddress],@hModule,esi mov [edi],eax ; 获取到函数地址后,放入导入函数字符串中 add edi,4 ; 每次递增4字节,指向下一个函数,遇到0则中止 @@: lodsb or al,al jnz @B .break .if !byte ptr [esi] .endw ; -------------------------------------------- ;lea esi,[ebx+ offset _szMessageBox] ; 取msgbox模块地址 ;_invoke [ebx+_lpGetProcAddress],@hModule,esi ; 获取地址 ;mov [ebx+_lpMessageBox],eax ; 存入变量中 lea esi,[ebx + offset _szShowTitle] ; 获取弹窗资源 _invoke [ebx + _lpMessageBox],0,esi,eax,0 ; 调用信息框 ret _RemoteThread endp
建立DLL文件: hookdll.dll
.386 .model flat,stdcall option casemap:none include windows.inc include user32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib .data? hInstdll dd ? ; dll句柄 hHook dd ? ; 钩子句柄 szAscii db 5 dup (?) .code ; ------------------------------------------------------------------ ; 钩子回调函数,这里按键后,弹出信息框提示 CallBack proc nCode:DWORD,wParam:DWORD,lParam:DWORD LOCAL @szKeyState[256]:byte invoke CallNextHookEx,hHook,nCode,wParam,lParam invoke GetKeyboardState,addr @szKeyState invoke GetKeyState,VK_SHIFT mov @szKeyState+VK_SHIFT,al mov ecx,lParam shr ecx,16 invoke ToAscii,wParam,ecx,addr @szKeyState,addr szAscii,0 mov byte ptr szAscii [eax],0 invoke MessageBox,NULL,addr wParam,0,MB_OK ; 弹出信息框 ret CallBack endp ; ------------------------------------------------------------------ ; 加载钩子,安装hook的子程序 installhook proc invoke SetWindowsHookEx,WH_KEYBOARD,addr CallBack,hInstdll,NULL mov hHook,eax ret installhook endp ; ------------------------------------------------------------------ ; 卸载钩子,清除hook的子程序 uninstallhook proc invoke UnhookWindowsHookEx,hHook ret uninstallhook endp ; ------------------------------------------------------------------ ; DllMain 程序入口函数 DllMain proc _hInstance:HINSTANCE,_dwReason:DWORD, _dwResverved:DWORD .if(_dwReason == DLL_PROCESS_ATTACH) push _hInstance pop hInstdll .elseif(_dwReason == DLL_PROCESS_DETACH) call uninstallhook .endif mov eax,TRUE ret DllMain endp end DllMain
建立inc文件: hookdll.inc
installhook proto uninstallhook proto
建立def: hookdll.def,并将目录下的hook.dll,hook.inc,hook.lib 拷贝出来.
LIBRARY hookdll EXPORTS installhook EXPORTS uninstallhook
建立主程序: 建立main.asm文件,并将hookdll.dll,hookdll.inc,hookdll.lib拷贝到目录下.
include hookdll.inc includelib hookdll.lib .data? hInstance dd ? uMsg MSG <?> .code main proc invoke installhook invoke GetModuleHandle,NULL mov hInstance,eax .while(TRUE) invoke GetMessage,addr uMsg,NULL,0,0 invoke TranslateMessage,addr uMsg invoke DispatchMessage,addr uMsg .endw invoke uninstallhook ret main endp end main
遍历子键: HKEY_LOCAL_MACHINE中的子键
include msvcrt.inc includelib msvcrt.lib include advapi32.inc includelib advapi32.lib .data dwIndex dd ? dwSize dd ? szBuffer db 256 dup(?) PrintText db "%s",0ah .code main proc mov dwIndex,0 .while(TRUE) mov dwSize,offset szBuffer invoke RegEnumKeyEx,HKEY_LOCAL_MACHINE,dwIndex,addr szBuffer,addr dwSize, \ NULL,NULL,NULL,NULL .break .if eax == ERROR_NO_MORE_ITEMS invoke crt_printf,addr PrintText,addr szBuffer inc dwIndex .endw ret main endp end main
建立键值:
include advapi32.inc includelib advapi32.lib .data szKeyPATH db "Software\\Microsoft\\Windows\\CurrentVersion\\Run",0h szValueName db "AutoRun Shell",0h szFileName db MAX_PATH dup(?) .code _RegSetValue proc _lpszKey,_lpszValueName,_lpszValue,_dwValueType,_dwSize LOCAL @hKey invoke RegCreateKey,HKEY_LOCAL_MACHINE,_lpszKey,addr @hKey .if (eax == ERROR_SUCCESS) invoke RegSetValueEx,@hKey,_lpszValueName,NULL,\ _dwValueType,_lpszValue,_dwSize invoke RegCloseKey,@hKey .endif ret _RegSetValue endp main proc invoke GetModuleFileName,NULL,addr szFileName,MAX_PATH ; 获取文件全路径 inc eax invoke _RegSetValue,addr szKeyPATH,addr szValueName,addr szFileName,REG_SZ,eax ret main endp end main
删除键值:
include advapi32.inc includelib advapi32.lib .data szKeyPATH db "Software\\Microsoft\\Windows\\CurrentVersion\\Run",0h szValueName db "AutoRun Shell",0h .code _RegDelValue proc _lpszKey,_lpszValueName LOCAL @hKey invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,KEY_WRITE,addr @hKey .if(eax == ERROR_SUCCESS) invoke RegDeleteValue,@hKey,_lpszValueName invoke RegCloseKey,@hKey .endif ret _RegDelValue endp main proc invoke _RegDelValue,addr szKeyPATH,addr szValueName ret main endp end main
建立子键
include advapi32.inc includelib advapi32.lib .data lpszKey db "Software\Microsoft\\Windows\\CurrentVersion\\Run\\",0h lpszSubKey db "MySub",0h .code _RegCreateKey proc _lpszKey,_lpszSubKeyName LOCAL @hKey,@hSubkey,@dwDisp invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,KEY_CREATE_SUB_KEY,addr @hKey .if eax == ERROR_SUCCESS invoke RegCreateKeyEx,@hKey,_lpszSubKeyName,NULL,NULL,\ NULL,NULL,NULL,addr @hSubkey,addr @dwDisp invoke RegCloseKey,@hKey invoke RegCloseKey,@hSubkey .endif ret _RegCreateKey endp main proc invoke _RegCreateKey,addr lpszKey,addr lpszSubKey ret main endp end main
删除子键:
include advapi32.inc includelib advapi32.lib .data lpszKey db "Software\Microsoft\\Windows\\CurrentVersion\\Run\\",0h lpszSubKey db "MySub",0h .code _RegDelSubKey proc _lpszKey,_lpszSubKeyName LOCAL @hKey invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,KEY_WRITE,addr @hKey .if eax == ERROR_SUCCESS invoke RegDeleteKey,@hKey,_lpszSubKeyName invoke RegCloseKey,@hKey .endif ret _RegDelSubKey endp main proc invoke _RegDelSubKey,addr lpszKey,addr lpszSubKey ret main endp end main
读取键值:
include advapi32.inc includelib advapi32.lib .data lpDwSize dd 1024 lpValue db 1024 dup(?) szKeyPATH db "Software\\Microsoft\\Windows\\CurrentVersion\\Run\\",0h szValueName db "IgfxTray",0h .code _RegQueryValue proc _lpszKey,_lpszValueName,_lpszValue,_lpdwSize,_lpdwType LOCAL @hKey,@dwReturn mov @dwReturn,-1 invoke RegOpenKeyEx,HKEY_LOCAL_MACHINE,_lpszKey,NULL,\ KEY_QUERY_VALUE,addr @hKey .if eax == ERROR_SUCCESS invoke RegQueryValueEx,@hKey,_lpszValueName,NULL,_lpdwType,\ _lpszValue,_lpdwSize mov @dwReturn,eax invoke RegCloseKey,@hKey .endif mov eax,@dwReturn ret _RegQueryValue endp main proc invoke _RegQueryValue,addr szKeyPATH,addr szValueName,addr lpValue,addr lpDwSize,0 lea eax,lpValue ret main endp end main
设置开机自启动:
include advapi32.inc includelib advapi32.lib .data szhKey dd ? szFileName db MAX_PATH dup(?) ; 获取当前路径 szKeyAutoRun db "Software\\Microsoft\\Windows\\CurrentVersion\\Run",0h ; 写入子键 szValueAutoRun db "AutoRun Shell",0h ; 写入的名称 .code main proc invoke GetModuleFileName,NULL,addr szFileName,MAX_PATH ; 获取文件全路径 invoke RegCreateKey,HKEY_LOCAL_MACHINE,addr szKeyAutoRun,addr szhKey .if(eax == ERROR_SUCCESS) invoke RegSetValueEx,szhKey,addr szValueAutoRun,NULL,REG_SZ, \ addr szFileName,sizeof szFileName .endif ret main endp end main
建立INI: Option.ini
[lyshark] ; 字段1 X=1024 Y=2048 Z=4096 [IniDemo] ; 字段2 StringKey=hello,lyshark! IntKey=123123 ToString=lyshark
遍历Section列表:
include msvcrt.inc includelib msvcrt.lib .data szStrlen dd ? szBuffer1 db 20480 dup(?) szININame db ".\Option.ini",0h szFmtSection db "[%s]",0h PrintText db "%s ",0ah .code main proc LOCAL @szBuffer[256]:byte invoke GetPrivateProfileSectionNames,addr szBuffer1,sizeof szBuffer1,addr szININame mov esi,offset szBuffer1 .while byte ptr [esi] invoke wsprintf,addr @szBuffer,addr szFmtSection,esi invoke crt_printf,addr PrintText,esi ; 打印键值 invoke lstrlen,esi add esi,eax inc esi .endw ret main endp end main
遍历键值对
include msvcrt.inc includelib msvcrt.lib .data szStrlen dd ? szBuffer db 2048 dup(?) szININame db ".\Option.ini",0h ; 指定要遍历的文件 szPrintKey db "lyshark",0h ; 指定要遍历的key szFmtSection db "[%s]",0h PrintText db "%s ",0ah .code main proc invoke GetPrivateProfileSection,addr szPrintKey,addr szBuffer,sizeof szBuffer,addr szININame mov edi,offset szBuffer .while byte ptr [edi] invoke crt_printf,addr PrintText,edi ; 打印key invoke lstrlen,edi add edi,eax inc edi .endw invoke lstrlen,esi add esi,eax inc esi ret main endp end main
拼接并打印字符串:
include masm32.inc includelib masm32.lib .data szBuffer db 2048 dup(?) ; 保存当前路径 szININame db "\Option.ini",0h ; 配置文件路径 .code main proc invoke GetCurrentDirectory,MAX_PATH,addr szBuffer mov esi,offset szBuffer invoke lstrlen,esi mov ecx,offset szININame .if byte ptr [esi+eax-1] == '\' inc ecx .endif invoke lstrcat,esi,ecx invoke StdOut, eax ; 打印拼接后的字符串 ret main endp end main
读取:
.data szININame db ".\Option.ini",0h ; 指定要遍历的文件 szSecPos db "IniDemo",0h ; 指定要遍历的key szKeyInt db "IntKey",0h ; 要读取的整数字段值 szKeyStr db "StringKey",0h ; 要读取的字符串字段 szBuffer db 2048 dup(?) .code main proc invoke GetPrivateProfileInt,addr szSecPos,addr szKeyInt,50,addr szININame ; 读取整数 invoke GetPrivateProfileString,addr szSecPos,addr szKeyStr,0, \ addr szBuffer,sizeof szBuffer,addr szININame ; 读取字符串 lea eax,szBuffer ret main endp end main
添加/删除键值:
include masm32.inc includelib masm32.lib .data szBuffer db 2048 dup(?) ; 保存当前路径 szININame db ".\Option.ini",0h ; 配置文件路径 szAppName db "IniDemo",0h ; 字段为IniDemo lpAppKey db "Temp",0h ; 键值对为Temp lpAppStr db "app temp",0h ; 键值对值 lpAppNew db "hello temp",0h ; 新的键值对 .code main proc ; 在IniDemo中添加 Temp=apptemp invoke WritePrivateProfileString,addr szAppName,addr lpAppKey,addr lpAppStr,addr szININame ; 将IniDemo中的Temp=app temp修改成Temp=hello temp invoke WritePrivateProfileString,addr szAppName,addr lpAppKey,addr lpAppNew,addr szININame ; 删除IniDemo中的Temp键值对 invoke WritePrivateProfileString,addr szAppName,addr lpAppKey,NULL,addr szININame ; 清空IniDemo底下的全部键值对 invoke WritePrivateProfileString,addr szAppName,NULL,NULL,addr szININame ret main endp end main
设置页面对话框:
include Comdlg32.inc includelib Comdlg32.lib .code main proc LOCAL @stPS:PAGESETUPDLG invoke RtlZeroMemory,addr @stPS,sizeof @stPS mov @stPS.lStructSize,sizeof @stPS mov @stPS.hwndOwner,0 invoke PageSetupDlg,addr @stPS .if eax && @stPS.hDevMode mov eax,@stPS.hDevMode mov eax,[eax] invoke MessageBox,0,eax,0,MB_OK .endif ret main endp end main
打开对话框:
include Comdlg32.inc includelib Comdlg32.lib .data szFilter db 'Text Files(*.txt)',0,'*.txt',0,'All Files(*.*)',0,'*.*',0,0 szFileName db MAX_PATH dup (?) .code main proc LOCAL @stOF:OPENFILENAME invoke RtlZeroMemory,addr @stOF,sizeof @stOF mov @stOF.lStructSize,sizeof @stOF mov @stOF.hwndOwner,eax mov @stOF.lpstrFilter,offset szFilter mov @stOF.lpstrFile,offset szFileName mov @stOF.nMaxFile,MAX_PATH mov @stOF.Flags,OFN_FILEMUSTEXIST or OFN_PATHMUSTEXIST invoke GetOpenFileName,addr @stOF .if eax invoke MessageBox,NULL,addr szFileName,0,MB_OK .endif ret main endp end main
保存对话框:
include Comdlg32.inc includelib Comdlg32.lib .data szFilter db 'Text Files(*.txt)',0,'*.txt',0,'All Files(*.*)',0,'*.*',0,0 szFileName db MAX_PATH dup (?) szDefExt db 'txt',0 szSaveCaption db '请输入保存的文件名',0 .code main proc LOCAL @stOF:OPENFILENAME invoke RtlZeroMemory,addr @stOF,sizeof @stOF mov @stOF.lStructSize,sizeof @stOF mov @stOF.hwndOwner,0 mov @stOF.lpstrFilter,offset szFilter mov @stOF.lpstrFile,offset szFileName mov @stOF.nMaxFile,MAX_PATH mov @stOF.Flags,OFN_PATHMUSTEXIST mov @stOF.lpstrDefExt,offset szDefExt mov @stOF.lpstrTitle,offset szSaveCaption invoke GetSaveFileName,addr @stOF .if eax invoke MessageBox,NULL,addr szFileName,0,MB_OK .endif ret main endp end main
选择颜色:
include Comdlg32.inc includelib Comdlg32.lib .data dwBackColor dd ? dwCustColors dd 16 dup (?) szBuffer db 1024 dup (?) szFormatColor db "您选择的颜色值:%08x",0 .code main proc LOCAL @stCC:CHOOSECOLOR invoke RtlZeroMemory,addr @stCC,sizeof @stCC mov @stCC.lStructSize,sizeof @stCC mov @stCC.hwndOwner,0 push dwBackColor pop @stCC.rgbResult mov @stCC.Flags,CC_RGBINIT or CC_FULLOPEN mov @stCC.lpCustColors,offset dwCustColors invoke ChooseColor,addr @stCC .if eax push @stCC.rgbResult pop dwBackColor invoke wsprintf,addr szBuffer,addr szFormatColor,dwBackColor invoke MessageBox,NULL,addr szBuffer,0,MB_OK .endif ret main endp end main
选择字体:
include Comdlg32.inc includelib Comdlg32.lib .data stLogFont LOGFONT <?> dwFontColor dd ? szBuffer db 1024 dup (?) szFormatFont db '字体名称:%s',0dh,0ah .code main proc LOCAL @stCF:CHOOSEFONT invoke RtlZeroMemory,addr @stCF,sizeof @stCF mov @stCF.lStructSize,sizeof @stCF mov @stCF.hwndOwner,0 mov @stCF.lpLogFont,offset stLogFont push dwFontColor pop @stCF.rgbColors mov @stCF.Flags,CF_SCREENFONTS or CF_INITTOLOGFONTSTRUCT or CF_EFFECTS invoke ChooseFont,addr @stCF .if eax push @stCF.rgbColors pop dwFontColor invoke wsprintf,addr szBuffer,addr szFormatFont,addr stLogFont.lfFaceName,\ dwFontColor,@stCF.iPointSize invoke MessageBox,NULL,addr szBuffer,0,MB_OK .endif ret main endp end main
服务端:
import socket ip_addr=("127.0.0.1",6666) server = socket.socket() server.bind(ip_addr) server.listen(5) while True: conn,addr=server.accept() print(addr) send_data = input("input:") conn.send(bytes(send_data,encoding="ascii")) recv_data = conn.recv(1024) print(str(recv_data, encoding="utf-8"))
客户端:
.386 .model flat,stdcall option casemap:none include windows.inc include user32.inc include ws2_32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib includelib ws2_32.lib TCP_PORT equ 6666 .data WSAData WSADATA <> stSin sockaddr_in <> szServer byte "127.0.0.1",0h sock dd ? Buff BYTE 256 dup (?) ; 接收数据的缓冲区 Send BYTE "hello",0h ; 发送数据缓冲区 .code main proc invoke WSAStartup,0202h,addr WSAData invoke socket,AF_INET, SOCK_STREAM, 0 .if(eax != INVALID_SOCKET) mov sock,eax .endif mov stSin.sin_family,AF_INET invoke htons,TCP_PORT mov stSin.sin_port,ax invoke inet_addr,addr szServer mov stSin.sin_addr,eax invoke connect,sock,addr stSin,sizeof stSin ; 链接套接字 invoke recv,sock,addr Buff,sizeof Buff,0 ; 接收内容 lea eax,Buff invoke send,sock,addr Send,sizeof Send,0 ; 发送数据 invoke closesocket,sock invoke WSACleanup ret main endp end main
改进版
服务端:
import socket ip_addr=("127.0.0.1",6666) server = socket.socket() server.bind(ip_addr) server.listen(5) conn, addr = server.accept() print(addr) while True: send_data = input("input:") conn.send(bytes(send_data,encoding="ascii")) recv_data = conn.recv(1024) print(str(recv_data, encoding="ascii"))
客户端:
.386 .model flat,stdcall option casemap:none include windows.inc include user32.inc include ws2_32.inc include kernel32.inc includelib user32.lib includelib kernel32.lib includelib ws2_32.lib TCP_PORT equ 6666 .data WSAData WSADATA <> stSin sockaddr_in <> szServer byte "127.0.0.1",0h sock dd ? Buff BYTE 256 dup (?) ; 接收数据的缓冲区 Send BYTE "ls",0h ; 发送数据缓冲区 Send1 BYTE "down",0h cmdls BYTE "ls",0h cmddown BYTE "down",0h .code main proc invoke WSAStartup,0202h,addr WSAData invoke socket,AF_INET, SOCK_STREAM, 0 .if(eax != INVALID_SOCKET) mov sock,eax .endif invoke RtlZeroMemory,addr stSin,sizeof stSin mov stSin.sin_family,AF_INET invoke htons,TCP_PORT mov stSin.sin_port,ax invoke inet_addr,addr szServer mov stSin.sin_addr,eax invoke connect,sock,addr stSin,sizeof stSin ; 链接套接字 .while(1) invoke RtlZeroMemory,addr Buff,sizeof Buff invoke recv,sock,addr Buff,sizeof Buff,0 invoke lstrcmp,addr cmdls,addr Buff ; 对比字符串是不是ls .if(eax==0) invoke send,sock,addr Send,sizeof Send,0 .continue .endif invoke lstrcmp,addr Buff,addr cmddown ; 对比是否是down .if(eax==0) invoke send,sock,addr Send1,sizeof Send1,0 .continue .endif .endw invoke closesocket,sock invoke WSACleanup ret main endp end main
参考文献:《Intel 汇编语言程序设计》,《琢石成器-Win32汇编语言程序设计》,《汇编语言-王爽》