ASM32 6 RadASM的使用
RadASM配置及应用
RadASM配置
参考 https://blog.csdn.net/2301_79113923/article/details/135665466
在路径设置中设置为自己的masm32和Ollydbg的路径
代码测试
1
MyTest.inc
1 | include windows.inc |
代码分析
1 | include windows.inc |
这些行是引入Windows API相关的头文件,其中包含了函数和常量的定义:
windows.inc
包含Windows相关的常量、结构体和函数。kernel32.inc
包含与Windows内核32位系统相关的API函数和常量。user32.inc
包含与Windows用户界面相关的API函数和常量。Comctl32.inc
包含常见控件库(Common Controls)的API函数和常量。shell32.inc
包含与Windows外壳程序相关的API函数和常量。
1 | includelib kernel32.lib |
这些行是引入对应的Windows库文件,这些库文件包含了上面提到的API的实际实现:
kernel32.lib
链接内核库。user32.lib
链接用户界面库。Comctl32.lib
链接常见控件库。shell32.lib
链接外壳程序库。
1 | DlgProc PROTO :HWND,:UINT,:WPARAM,:LPARAM |
这行是声明一个名为 DlgProc
的函数原型,表示这个函数是对话框的处理过程。参数分别是:
:HWND
对话框的句柄。:UINT
消息类型。:WPARAM
和:LPARAM
是消息参数,通常是一些额外信息。
1 | .const |
这是一个常量定义,MY_MSG
是一个包含字符串 "click"
的常量,并且字符串以空字符(0)结尾。
1 | IDD_DIALOG1 equ 101 |
这些是资源ID定义:
IDD_DIALOG1
代表对话框资源的ID号为101。BTN_BUTTON1
代表按钮资源的ID号为1001。
1 | .data? |
这是一个未初始化的数据段,定义了一个名为 hInstance
的双字(dd
),通常用于存储应用程序实例的句柄。
这个代码片段总体上是一个Windows应用程序框架,定义了基本的头文件、库、常量和数据。它还包括一个消息处理函数的声明,用于响应用户界面的事件(如按钮点击)。
MyTest.asm
1 | .386 |
代码分析
1 | .386 |
.386
:指定目标处理器为Intel 80386及以上的CPU。.model flat, stdcall
:定义扁平内存模型,并使用stdcall
调用约定,这种约定用于Windows API,调用者负责清理堆栈。option casemap :none
:使得代码对大小写敏感,变量或指令的名称区分大小写。
1 | include MyTest.inc |
include MyTest.inc
:包含一个名为MyTest.inc
的头文件,假设它里面定义了程序所需的常量、结构或函数。
1 | .code |
.code
:表示接下来是代码段。
1 | start: |
start:
:程序的入口点,所有代码从这里开始执行。
1 | invoke GetModuleHandle,NULL |
invoke GetModuleHandle, NULL
:调用GetModuleHandle
获取当前模块(程序)的句柄,返回值存放在eax
寄存器中。mov hInstance, eax
:将eax
中的模块句柄保存到变量hInstance
中。
1 | invoke InitCommonControls |
invoke InitCommonControls
:初始化通用控件(如按钮、编辑框等),这是使用某些控件前必须调用的函数。
1 | invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL |
invoke DialogBoxParam, hInstance, IDD_DIALOG1, NULL, addr DlgProc, NULL
:调用DialogBoxParam
函数创建并显示模态对话框。hInstance
是模块句柄。IDD_DIALOG1
是对话框的资源ID。NULL
是父窗口句柄(此处没有父窗口)。addr DlgProc
是对话框的回调函数地址。- 最后的
NULL
是传递给对话框的额外参数。
1 | invoke ExitProcess,0 |
invoke ExitProcess, 0
:调用ExitProcess
函数终止程序,返回代码为0
。
1 | MyAdd proc |
MyAdd proc
:定义一个名为MyAdd
的过程(函数),没有参数。
1 | ret |
ret
:返回到调用此过程的地方。
1 | MyAdd endp |
MyAdd endp
:结束MyAdd
过程的定义。
1 | DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM |
DlgProc proc hWin:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
:定义对话框处理过程DlgProc
,它接受4个参数:hWin
:对话框窗口的句柄。uMsg
:消息的类型(例如按钮点击、关闭事件等)。wParam
和lParam
:消息相关的附加信息。
1 | mov eax,uMsg |
mov eax, uMsg
:将传递的消息类型uMsg
复制到eax
寄存器中。.if eax==WM_INITDIALOG
:检查是否为WM_INITDIALOG
消息,即对话框初始化消息,如果是,执行后续代码。
1 | .elseif eax==WM_COMMAND |
.elseif eax==WM_COMMAND
:检查是否为WM_COMMAND
消息,即用户界面控件的命令消息。mov eax, wParam
:将wParam
的值复制到eax
寄存器中。.if ax==BTN_BUTTON1
:检查低位字的值是否等于按钮BTN_BUTTON1
的ID,判断是否为按钮点击事件。invoke MessageBox, NULL, offset MY_MSG, NULL, MB_OK
:如果是按钮点击,调用MessageBox
函数,显示消息框,MY_MSG
是显示的消息,MB_OK
显示一个“确定”按钮。
1 | .elseif eax==WM_CLOSE |
.elseif eax==WM_CLOSE
:检查是否为WM_CLOSE
消息,表示用户点击了关闭按钮。invoke EndDialog, hWin, 0
:调用EndDialog
函数关闭对话框,返回代码为0
。
1 | .else |
.else
:如果消息不是上面处理的那些类型,则执行else
部分。mov eax, FALSE
:将eax
设为FALSE
,表示消息没有被处理。ret
:返回调用点。
mov eax, TRUE
:将eax
设为TRUE
,表示消息已被处理。ret
:返回到调用DlgProc
的地方。
1 | DlgProc endp |
DlgProc endp
:结束DlgProc
过程的定义。
1 | end start |
end start
:程序从start
标签开始执行,表示程序的入口。
运行结果
2
MyTest.inc
1 | include windows.inc |
代码分析
include msvcrt.inc
:包含msvcrt.inc
头文件,定义了与C运行时库(msvcrt.dll
)相关的函数和常量,比如标准输入输出函数。includelib msvcrt.lib
:链接C运行时库msvcrt.lib
,提供标准C库函数(如printf
、malloc
)的实现。MY_WND_NAME db "计算器", 0
:定义一个窗口名的字符串,内容为"计算器"
,0
表示字符串结束符。
MyTest.asm
1 | .386 |
指令集和模型设置
1 | .386 |
.386
:指示程序将使用386及以上的处理器指令集。.model flat, stdcall
:设定扁平内存模型,并使用stdcall
调用约定,符合Windows API的标准。option casemap :none
:指定对大小写敏感。
1 | include MyTest.inc |
- 包含
MyTest.inc
,这是一个头文件,应该包含了程序所需的常量、结构或函数的定义。
代码段
1 | .code |
INJECT_CODE_START
和INJECT_CODE_END
:定义了一个注入的代码段,表示将注入到目标进程中的机器代码。mov eax, 0
:将eax
寄存器清零。mov dword ptr [eax], 0
:尝试将值0
写入内存地址0
,这是一个非法操作,通常会导致崩溃。retn 4
:从函数返回,并从堆栈弹出4个字节(参数)。
注入代码
1 | Inject proc |
- 定义了
Inject
函数,这个函数负责将代码注入到另一个进程中。 LOCAL
声明局部变量:@hWnd
:存储目标窗口的句柄。@dwPid
:存储目标进程的进程ID。@hProcess
:存储目标进程的句柄。@lpBuf
:存储目标进程中分配的内存地址。@dwBytes
:存储写入内存的字节数。
1 | invoke FindWindow,NULL,OFFSET MY_WND_NAME |
invoke FindWindow, NULL, OFFSET MY_WND_NAME
:调用FindWindow
API,根据窗口名称MY_WND_NAME
查找窗口句柄,返回值存入@hWnd
。MOV @hWnd, eax
:将窗口句柄存入局部变量@hWnd
。
1 | invoke GetWindowThreadProcessId,@hWnd,addr @dwPid |
invoke GetWindowThreadProcessId, @hWnd, addr @dwPid
:调用GetWindowThreadProcessId
API,获取与该窗口相关的进程ID,存储在@dwPid
中。
1 | invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,@dwPid |
invoke OpenProcess, PROCESS_ALL_ACCESS, FALSE, @dwPid
:调用OpenProcess
API,打开指定进程,获取其句柄,存入@hProcess
。mov @hProcess, eax
:将进程句柄存储在局部变量@hProcess
中。
1 | ;1.对方进程申请内存 |
invoke VirtualAllocEx, @hProcess, NULL, 1000h, MEM_COMMIT, PAGE_EXECUTE_READWRITE
:在目标进程中分配1KB的内存,具有可执行、可读、可写的权限。返回的内存地址存储在@lpBuf
中。
1 | ;2.写入INJECT_CODE的代码 |
invoke WriteProcessMemory, @hProcess, @lpBuf, offset INJECT_CODE_START, offset INJECT_CODE_END-offset INJECT_CODE_START, addr @dwBytes
:将INJECT_CODE
写入目标进程分配的内存区,INJECT_CODE_START
到INJECT_CODE_END
之间的代码段大小被计算并写入到目标进程。
1 | ;3.创建远程线程 |
invoke CreateRemoteThread, @hProcess, NULL, 0, @lpBuf, NULL, 0, NULL
:在目标进程中创建一个线程,执行写入的代码,@lpBuf
是线程入口地址。
1 | ret |
ret
:返回,结束Inject
过程。
程序入口
1 | start: |
start:
:程序的入口点。invoke GetModuleHandle, NULL
:获取当前模块句柄,存入hInstance
。invoke InitCommonControls
:初始化常用控件(按钮、进度条等)。invoke DialogBoxParam, hInstance, IDD_DIALOG1, NULL, addr DlgProc, NULL
:显示对话框,DlgProc
是对话框的回调函数。invoke ExitProcess, 0
:退出程序。
对话框处理函数
1 | DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM |
DlgProc proc
:定义对话框处理过程DlgProc
,接受4个参数:hWin
:窗口句柄。uMsg
:消息类型。wParam
和lParam
:消息相关信息。
WM_INITDIALOG
:处理对话框初始化消息。WM_COMMAND
:处理命令消息,当点击按钮时会收到此消息。- 如果点击了
BTN_INJECT
,弹出消息框显示"click"
。
- 如果点击了
WM_CLOSE
:处理关闭窗口的消息,调用EndDialog
结束对话框。mov eax, TRUE
:表示消息已处理,返回TRUE
。
1 | end start |
- 程序结束,程序从
start
标签开始执行。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hexo!