RadASM配置及应用

RadASM配置

参考 https://blog.csdn.net/2301_79113923/article/details/135665466

在路径设置中设置为自己的masm32和Ollydbg的路径

image-20240913215557741

代码测试

1

image-20240912171212811

MyTest.inc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc

includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib

DlgProc PROTO :HWND,:UINT,:WPARAM,:LPARAM

.const
MY_MSG db "click",0

IDD_DIALOG1 equ 101
BTN_BUTTON1 equ 1001

;#########################################################################

.data?

hInstance dd ?

;#########################################################################

代码分析

1
2
3
4
5
include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.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
2
3
4
includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib

这些行是引入对应的Windows库文件,这些库文件包含了上面提到的API的实际实现:

  • kernel32.lib 链接内核库。
  • user32.lib 链接用户界面库。
  • Comctl32.lib 链接常见控件库。
  • shell32.lib 链接外壳程序库。
1
DlgProc			PROTO	:HWND,:UINT,:WPARAM,:LPARAM

这行是声明一个名为 DlgProc 的函数原型,表示这个函数是对话框的处理过程。参数分别是:

  • :HWND 对话框的句柄。
  • :UINT 消息类型。
  • :WPARAM:LPARAM 是消息参数,通常是一些额外信息。
1
2
.const
MY_MSG db "click",0

这是一个常量定义,MY_MSG 是一个包含字符串 "click" 的常量,并且字符串以空字符(0)结尾。

1
2
IDD_DIALOG1			equ 101
BTN_BUTTON1 equ 1001

这些是资源ID定义:

  • IDD_DIALOG1 代表对话框资源的ID号为101。
  • BTN_BUTTON1 代表按钮资源的ID号为1001。
1
2
3
.data?

hInstance dd ?

这是一个未初始化的数据段,定义了一个名为 hInstance 的双字(dd),通常用于存储应用程序实例的句柄。

这个代码片段总体上是一个Windows应用程序框架,定义了基本的头文件、库、常量和数据。它还包括一个消息处理函数的声明,用于响应用户界面的事件(如按钮点击)。

MyTest.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive

include MyTest.inc

.code

start:

invoke GetModuleHandle,NULL
mov hInstance,eax

invoke InitCommonControls
invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
invoke ExitProcess,0

;########################################################################
MyAdd proc


ret

MyAdd endp
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

mov eax,uMsg
.if eax==WM_INITDIALOG

.elseif eax==WM_COMMAND
mov eax,wParam
.if ax==BTN_BUTTON1
invoke MessageBox,NULL,offset MY_MSG,NULL,MB_OK
.endif
.elseif eax==WM_CLOSE
invoke EndDialog,hWin,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret

DlgProc endp

end start

代码分析

1
2
3
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
  • .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
2
invoke GetModuleHandle,NULL
mov hInstance,eax
  • 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:消息的类型(例如按钮点击、关闭事件等)。
    • wParamlParam:消息相关的附加信息。
1
2
mov		eax,uMsg
.if eax==WM_INITDIALOG
  • mov eax, uMsg:将传递的消息类型 uMsg 复制到 eax 寄存器中。
  • .if eax==WM_INITDIALOG:检查是否为 WM_INITDIALOG 消息,即对话框初始化消息,如果是,执行后续代码。
1
2
3
4
5
.elseif eax==WM_COMMAND
mov eax,wParam
.if ax==BTN_BUTTON1
invoke MessageBox,NULL,offset MY_MSG,NULL,MB_OK
.endif
  • .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
2
.elseif eax==WM_CLOSE
invoke EndDialog,hWin,0
  • .elseif eax==WM_CLOSE:检查是否为 WM_CLOSE 消息,表示用户点击了关闭按钮。
    • invoke EndDialog, hWin, 0:调用 EndDialog 函数关闭对话框,返回代码为 0
1
2
3
4
5
6
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
  • .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 标签开始执行,表示程序的入口。

运行结果

image-20240912171921876

2

image-20240912233754241

image-20240913153116009

image-20240913153153315

image-20240913153220594

MyTest.inc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
include windows.inc
include kernel32.inc
include user32.inc
include Comctl32.inc
include shell32.inc
include msvcrt.inc

includelib kernel32.lib
includelib user32.lib
includelib Comctl32.lib
includelib shell32.lib
includelib msvcrt.lib

DlgProc PROTO :HWND,:UINT,:WPARAM,:LPARAM

.const
MY_MSG db "click",0
MY_WND_NAME db "计算器",0
IDD_DIALOG1 equ 101
BTN_INJECT equ 1001

;#########################################################################

.data?

hInstance dd ?

;#########################################################################

代码分析

  • include msvcrt.inc:包含 msvcrt.inc 头文件,定义了与C运行时库(msvcrt.dll)相关的函数和常量,比如标准输入输出函数。
  • includelib msvcrt.lib:链接C运行时库 msvcrt.lib,提供标准C库函数(如 printfmalloc)的实现。
  • MY_WND_NAME db "计算器", 0:定义一个窗口名的字符串,内容为 "计算器"0 表示字符串结束符。

MyTest.asm

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive

include MyTest.inc

.code
INJECT_CODE_START:
;invoke MessageBox,NULL,NULL,NULL,MB_OK
;push 0
;push 0
;push 0
;push 0
;call MessageBoxA
mov eax,0
mov dword ptr [eax],0
retn 4
INJECT_CODE_END:

Inject proc
LOCAL @hWnd:HWND
LOCAL @dwPid:DWORD
LOCAL @hProcess:HANDLE
LOCAL @lpBuf:LPVOID
LOCAL @dwBytes:dword

invoke FindWindow,NULL,OFFSET MY_WND_NAME
MOV @hWnd,eax
;check

invoke GetWindowThreadProcessId,@hWnd,addr @dwPid
;check

invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,@dwPid
mov @hProcess,eax
;check

;1.对方进程申请内存
invoke VirtualAllocEx,@hProcess,NULL,1000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
mov @lpBuf,eax
;check

;2.写入INJECT_CODE的代码
invoke WriteProcessMemory,@hProcess,@lpBuf,offset INJECT_CODE_START,offset INJECT_CODE_END-offset INJECT_CODE_START,addr @dwBytes
;check;

;3.创建远程线程
invoke CreateRemoteThread,@hProcess,NULL,0,@lpBuf,NULL,0,NULL
;check

ret

Inject endp

start:
;invoke crt_strcpy,NULL,NULL

invoke GetModuleHandle,NULL
mov hInstance,eax

invoke InitCommonControls
invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
invoke ExitProcess,0

;########################################################################
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM

mov eax,uMsg
.if eax==WM_INITDIALOG

.elseif eax==WM_COMMAND
mov eax,wParam
.if ax==BTN_INJECT
invoke MessageBox,NULL,offset MY_MSG,NULL,MB_OK
.endif
.elseif eax==WM_CLOSE
invoke EndDialog,hWin,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret

DlgProc endp

end start
指令集和模型设置
1
2
3
.386
.model flat, stdcall ;32 bit memory model
option casemap :none ;case sensitive
  • .386:指示程序将使用386及以上的处理器指令集。
  • .model flat, stdcall:设定扁平内存模型,并使用 stdcall 调用约定,符合Windows API的标准。
  • option casemap :none:指定对大小写敏感。
1
include MyTest.inc
  • 包含 MyTest.inc,这是一个头文件,应该包含了程序所需的常量、结构或函数的定义。
代码段
1
2
3
4
5
6
7
8
9
10
11
12
.code
INJECT_CODE_START:
;invoke MessageBox,NULL,NULL,NULL,MB_OK
;push 0
;push 0
;push 0
;push 0
;call MessageBoxA
mov eax,0
mov dword ptr [eax],0
retn 4
INJECT_CODE_END:
  • INJECT_CODE_STARTINJECT_CODE_END:定义了一个注入的代码段,表示将注入到目标进程中的机器代码。
    • mov eax, 0:将 eax 寄存器清零。
    • mov dword ptr [eax], 0:尝试将值 0 写入内存地址 0,这是一个非法操作,通常会导致崩溃。
    • retn 4:从函数返回,并从堆栈弹出4个字节(参数)。
注入代码
1
2
3
4
5
6
Inject proc
LOCAL @hWnd:HWND
LOCAL @dwPid:DWORD
LOCAL @hProcess:HANDLE
LOCAL @lpBuf:LPVOID
LOCAL @dwBytes:dword
  • 定义了 Inject 函数,这个函数负责将代码注入到另一个进程中。
  • LOCAL 声明局部变量:
    • @hWnd:存储目标窗口的句柄。
    • @dwPid:存储目标进程的进程ID。
    • @hProcess:存储目标进程的句柄。
    • @lpBuf:存储目标进程中分配的内存地址。
    • @dwBytes:存储写入内存的字节数。
1
2
3
invoke FindWindow,NULL,OFFSET MY_WND_NAME
MOV @hWnd,eax
;check
  • invoke FindWindow, NULL, OFFSET MY_WND_NAME:调用 FindWindow API,根据窗口名称 MY_WND_NAME 查找窗口句柄,返回值存入 @hWnd
    • MOV @hWnd, eax:将窗口句柄存入局部变量 @hWnd
1
2
invoke GetWindowThreadProcessId,@hWnd,addr @dwPid
;check
  • invoke GetWindowThreadProcessId, @hWnd, addr @dwPid:调用 GetWindowThreadProcessId API,获取与该窗口相关的进程ID,存储在 @dwPid 中。
1
2
3
invoke OpenProcess,PROCESS_ALL_ACCESS,FALSE,@dwPid
mov @hProcess,eax
;check
  • invoke OpenProcess, PROCESS_ALL_ACCESS, FALSE, @dwPid:调用 OpenProcess API,打开指定进程,获取其句柄,存入 @hProcess
  • mov @hProcess, eax:将进程句柄存储在局部变量 @hProcess 中。
1
2
3
4
;1.对方进程申请内存
invoke VirtualAllocEx,@hProcess,NULL,1000h,MEM_COMMIT,PAGE_EXECUTE_READWRITE
mov @lpBuf,eax
;check
  • invoke VirtualAllocEx, @hProcess, NULL, 1000h, MEM_COMMIT, PAGE_EXECUTE_READWRITE:在目标进程中分配1KB的内存,具有可执行、可读、可写的权限。返回的内存地址存储在 @lpBuf 中。
1
2
3
;2.写入INJECT_CODE的代码
invoke WriteProcessMemory,@hProcess,@lpBuf,offset INJECT_CODE_START,offset INJECT_CODE_END-offset INJECT_CODE_START,addr @dwBytes
;check;
  • invoke WriteProcessMemory, @hProcess, @lpBuf, offset INJECT_CODE_START, offset INJECT_CODE_END-offset INJECT_CODE_START, addr @dwBytes:将 INJECT_CODE 写入目标进程分配的内存区,INJECT_CODE_STARTINJECT_CODE_END 之间的代码段大小被计算并写入到目标进程。
1
2
3
;3.创建远程线程
invoke CreateRemoteThread,@hProcess,NULL,0,@lpBuf,NULL,0,NULL
;check
  • invoke CreateRemoteThread, @hProcess, NULL, 0, @lpBuf, NULL, 0, NULL:在目标进程中创建一个线程,执行写入的代码,@lpBuf 是线程入口地址。
1
2
	ret
Inject endp
  • ret:返回,结束 Inject 过程。
程序入口
1
2
3
4
5
6
7
start:
;invoke crt_strcpy,NULL,NULL
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke InitCommonControls
invoke DialogBoxParam,hInstance,IDD_DIALOG1,NULL,addr DlgProc,NULL
invoke ExitProcess,0
  • start::程序的入口点。
  • invoke GetModuleHandle, NULL:获取当前模块句柄,存入 hInstance
  • invoke InitCommonControls:初始化常用控件(按钮、进度条等)。
  • invoke DialogBoxParam, hInstance, IDD_DIALOG1, NULL, addr DlgProc, NULL:显示对话框,DlgProc 是对话框的回调函数。
  • invoke ExitProcess, 0:退出程序。
对话框处理函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_INITDIALOG
.elseif eax==WM_COMMAND
mov eax,wParam
.if ax==BTN_INJECT
invoke MessageBox,NULL,offset MY_MSG,NULL,MB_OK
.endif
.elseif eax==WM_CLOSE
invoke EndDialog,hWin,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
  • DlgProc proc:定义对话框处理过程 DlgProc,接受4个参数:
    • hWin:窗口句柄。
    • uMsg:消息类型。
    • wParamlParam:消息相关信息。
  • WM_INITDIALOG:处理对话框初始化消息。
  • WM_COMMAND:处理命令消息,当点击按钮时会收到此消息。
    • 如果点击了 BTN_INJECT,弹出消息框显示 "click"
  • WM_CLOSE:处理关闭窗口的消息,调用 EndDialog 结束对话框。
  • mov eax, TRUE:表示消息已处理,返回 TRUE
1
end start
  • 程序结束,程序从 start 标签开始执行。