到底日更变成拖更变成月更了,水一篇吧,实在太忙了,或者你们想看的话我更新高等数学也行
借鉴来源:
# ASM 源码:
section .data
msg db "Welcome_to_CTFshow_PWN", 0
section .text
global _start
_start:
; 立即寻址方式
mov eax, 11 ; 将11赋值给eax
add eax, 114504 ; eax加上114504
sub eax, 1 ; eax减去1
; 寄存器寻址方式
mov ebx, 0x36d ; 将0x36d赋值给ebx
mov edx, ebx ; 将ebx的值赋值给edx
; 直接寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
; 寄存器间接寻址方式
mov esi, msg ; 将msg的地址赋值给esi
mov eax, [esi] ; 将esi所指向的地址的值赋值给eax
; 寄存器相对寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
add ecx, 4 ; 将ecx加上4
mov eax, [ecx] ; 将ecx所指向的地址的值赋值给eax
; 基址变址寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
mov edx, 2 ; 将2赋值给edx
mov eax, [ecx + edx*2] ; 将ecx+edx*2所指向的地址的值赋值给eax
; 相对基址变址寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
mov edx, 1 ; 将1赋值给edx
add ecx, 8 ; 将ecx加上8
mov eax, [ecx + edx*2 - 6] ; 将ecx+edx*2-6所指向的地址的值赋值给eax
; 输出字符串
mov eax, 4 ; 系统调用号4代表输出字符串
mov ebx, 1 ; 文件描述符1代表标准输出
mov ecx, msg ; 要输出的字符串的地址
mov edx, 22 ; 要输出的字符串的长度
int 0x80 ; 调用系统调用
; 退出程序
mov eax, 1 ; 系统调用号1代表退出程序
xor ebx, ebx ; 返回值为0
int 0x80 ; 调用系统调用
# 详解:
# 1. .data 段
section .data
msg db "Welcome_to_CTFshow_PWN", 0
解释:
-
.data
段:用来存放程序中的已初始化数据,这些数据在程序运行时会被加载到内存中。 -
msg db
:声明一个字符串"Welcome_to_CTFshow_PWN"
,以字节(db
= Define Byte)存储,并以0
结尾,表示字符串结束符(类似 C 语言的\0
)。 - 地址:
msg
是一个标签,代表该字符串的内存地址,供后续使用。
# 2. .text 段
section .text
global _start
_start:
解释:
-
.text
段:存放程序的代码(指令)。 -
_start
:程序的入口,系统从这里开始执行程序(对应 Linux 的 ELF 文件格式的起点)。
# 3. 立即寻址方式
mov eax, 11 ; 将11赋值给eax
add eax, 114504 ; eax加上114504
sub eax, 1 ; eax减去1
解释:
-
立即寻址方式:操作数是一个立即数,直接嵌入在指令中。例如
11
和114504
。 -
过程
:
mov eax, 11
:将立即数11
加载到寄存器eax
中。add eax, 114504
:将立即数114504
加到eax
的当前值上。sub eax, 1
:将eax
的值减去立即数1
。
-
硬件实现:立即数直接写入指令的操作数字段,CPU 解码指令后直接将值加载到指定寄存器中。
# 4. 寄存器寻址方式
mov ebx, 0x36d ; 将0x36d赋值给ebx
mov edx, ebx ; 将ebx的值赋值给edx
解释:
-
寄存器寻址方式:操作数在寄存器中,CPU 直接对寄存器进行操作。
-
过程
:
mov ebx, 0x36d
:将立即数0x36d
加载到寄存器ebx
。mov edx, ebx
:将寄存器ebx
的值复制到寄存器edx
。
-
硬件实现:寄存器之间的数据传递不需要访问内存,速度非常快。
# 5. 直接寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
解释:
-
直接寻址方式:操作数的地址直接给出,即指令中明确指出操作数所在的内存地址。
-
过程
:
mov ecx, msg
:将标签msg
所指向的内存地址加载到寄存器ecx
。
-
硬件实现:CPU 将指令中的地址字段直接解析为内存地址,然后取出对应地址的内容。
# 6. 寄存器间接寻址方式
mov esi, msg ; 将msg的地址赋值给esi
mov eax, [esi] ; 将esi所指向的地址的值赋值给eax
解释:
-
寄存器间接寻址方式:寄存器中存储的是操作数的内存地址,操作数存储在该地址中。
-
过程
:
mov esi, msg
:将msg
的地址加载到寄存器esi
。mov eax, [esi]
:从esi
指向的内存地址中读取数据,并存储到寄存器eax
。
-
硬件实现
:
- CPU 读取寄存器
esi
的值(作为内存地址)。 - 然后去内存中访问该地址,取出存储的值加载到寄存器
eax
。
- CPU 读取寄存器
# 7. 寄存器相对寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
add ecx, 4 ; 将ecx加上4
mov eax, [ecx] ; 将ecx所指向的地址的值赋值给eax
解释:
-
寄存器相对寻址方式:寄存器中存储基地址,操作数的地址是基地址加上一个偏移量。
-
过程
:
mov ecx, msg
:将msg
的地址加载到寄存器ecx
。add ecx, 4
:将ecx
加上偏移量4
。mov eax, [ecx]
:从ecx
指向的地址读取数据到寄存器eax
。
-
硬件实现
:
- 计算内存地址:
ecx + 4
。 - 访问该地址并读取数据。
- 计算内存地址:
# 8. 基址变址寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
mov edx, 2 ; 将2赋值给edx
mov eax, [ecx + edx*2] ; 将ecx+edx*2所指向的地址的值赋值给eax
解释:
-
基址变址寻址方式:地址是基地址加上索引值(
edx
),并根据一个比例因子(如*2
)计算得到。 -
过程
:
mov ecx, msg
:加载基地址到寄存器ecx
。mov edx, 2
:加载索引值2
到寄存器edx
。mov eax, [ecx + edx*2]
:计算地址为ecx + edx*2
,然后读取该地址的数据到eax
。
-
硬件实现
:
- 地址计算:
ecx + edx*2
。 - 访问该内存地址并读取数据。
- 地址计算:
# 9. 相对基址变址寻址方式
mov ecx, msg ; 将msg的地址赋值给ecx
mov edx, 1 ; 将1赋值给edx
add ecx, 8 ; 将ecx加上8
mov eax, [ecx + edx*2 - 6] ; 将ecx+edx*2-6所指向的地址的值赋值给eax
解释:
-
相对基址变址寻址方式:地址是基地址加索引值乘比例因子再加偏移量。
-
过程
:
mov ecx, msg
:加载基地址到ecx
。mov edx, 1
:加载索引值1
到edx
。add ecx, 8
:将偏移量8
加到ecx
。mov eax, [ecx + edx*2 - 6]
:计算地址为ecx + edx*2 - 6
,然后读取数据到eax
。
-
硬件实现
:
- 地址计算:
ecx + edx*2 - 6
。 - 访问该地址并读取数据。
- 地址计算:
# 10. 系统调用(输出字符串)
mov eax, 4 ; 系统调用号4代表输出字符串
mov ebx, 1 ; 文件描述符1代表标准输出
mov ecx, msg ; 要输出的字符串的地址
mov edx, 22 ; 要输出的字符串的长度
int 0x80 ; 调用系统调用
解释:
-
过程
:
mov eax, 4
:设置系统调用号为4
(sys_write
)。mov ebx, 1
:文件描述符为1
(标准输出)。mov ecx, msg
:输出字符串的地址。mov edx, 22
:字符串的长度。int 0x80
:触发软中断,调用 Linux 内核的系统调用。
-
硬件实现
:
- 将参数放入寄存器(
eax
,ebx
,ecx
,edx
)。 - 调用
int 0x80
,切换到内核模式执行sys_write
。
- 将参数放入寄存器(
# 11. 退出程序
mov eax, 1 ; 系统调用号1代表退出程序
xor ebx, ebx ; 返回值为0
int 0x80 ; 调用系统调用
解释:
-
过程
:
mov eax, 1
:设置系统调用号为1
(sys_exit
)。xor ebx, ebx
:返回值为0
。int 0x80
:触发软中断,调用内核终止程序。
# 总结
-
寻址方式:
- 立即寻址:直接在指令中给出操作数。
- 寄存器寻址:操作数在寄存器中。
- 直接寻址:操作数的地址直接给出。
- 间接寻址:通过寄存器指向的地址访问数据。
- 相对寻址:基址 + 偏移量。
- 基址变址寻址:基址 + 索引 * 比例因子。
- 相对基址变址寻址:基址 + 索引 * 比例因子 + 偏移量。
-
系统调用:
- 使用
int 0x80
切换到内核模式执行特定操作。
这个 int 0x80 有点小关键的,有时候打 shellcode 会用
- 使用