0x00
开设日常学习和笔记分享的篇章,帮助大家来学习汇编语言。为什么要学习汇编语言呢?是由于在红蓝对抗中,常常因为一些AV/EDR的存在导致我们的工具被查杀。所以才需要我们来对抗AV也就是免杀技术。所以要学习免杀技术就要从基础开始。后续可能还会分享一些C++、PE文件结构等等笔记。另外也可能会推出逆向相关的知识。
0x01
一、寄存器CPU互作原理
寄存器概述
1.8086CPU有14个寄存器,它们的名称为AX、BX、CX、DX、SI、DI、SP、BP、IP、CS、SS、DS、ES、PSW,其中AX、BX、CX、DX用来存放一般性数据称为通用寄存器。
2.8086CPU所有的寄存器都是16位的,可以存放两个字节即1个字,最大存储数据的值为2的16次方减一。
3.通用寄存器逻辑结构:
4.一个16位寄存器可以存储一个16位的数据
数据:2000
寄存器AX中的存储:
5.8086上一代CPU中的寄存器都是8位的;为保证兼容性,这四个通用寄存器都可以分为两个独立的8位寄存器使用
AX可以分为AH和AL 其中 AH位高位 AL位低位
AH和AL寄存器都是可以独立使用的8位寄存器
字在寄存器中的存储
出于兼容性考虑,8086CPU可以一次性处理以下两种尺寸的数据
- 字节,1byte=8bit,可以存在8位寄存器中
- 字,一个字有两个字节,分别位高位字节和低位字节
一个字可以存在16位寄存器中,这个字的高位字节和低位字节自然存在这个寄存器的高8位和低8位寄存器中。 1word=2byte=16bit
几条汇编指令
汇编指令控制CPU完成的操作 用高级语言的语法描述
mov ax,8 将18送入AX AX=18
mov ah,20 将20送入AH AH=20
add ax,8将寄存器AX中的数值加8 AX=AX+8
mov ax,bx将寄存器BX中的数据送入寄存器AX中 AX=BX
add ax,bx将AX,BX中的内容相加结果存入AX中 AX=AX+BX
注意:
1.汇编语言不区分大小写!
2.进行数据传送或运算时,需要保障两个操作对象位数相同!
物理地址
1.CPU访问内存单元时,要给出内存单元的地址。所有的内存单元构成的存储空间时一个一维的线性空间。
2.概括的讲,16位结构描述一个CPU具有以下几个方面特征:
1)运算器一次最多可以处理16位的数据;
2)寄存器的最大宽度为16位;
3)寄存器和运算器之间的通路时16位
3.8086有20位地址总线,可传送20位地址,寻址能力为1M;8086内部为16位结构,它只能传送16位的地址,表现储的寻址能力却只有64K.
4.地址加法器合成物理地址的方法:物理地址=段地址*16+偏移地址!!!
8086CPU给出物理地址的方法
1.CPU中的相关部件提供两个16位的地址,一个称为段地址,另一个偏移地址;
2.段地址和偏移地址通过内部总线送入一个称为地址加法器的部件;
3.地址加法器将两个16位地址合并成一个20位的地址
段的概念
1.错误的认识;内存被划分成一个一个的段,每一个段有一个段地址。❌❌❌❌
2.其实:内存并没有分段,段的划分来自于CPU,由于8086CPU用“(段地址*16)+偏移地址=物理地址”的方式给出内存单元的物理地址,使得我们看一看用分段的方式来管理内存。‘
3.再变成时可以根据需要,将若干地址连续的内存单元看作一个段,用段地址*16未段的其实地址(基础地址),用偏移地址定位段中的内存单元。
4.数据在21F60H内存单元中,对于8086PC机的两种描述:
1)数据存在内存2000:1F60单元中;
2)数据存在内存的2000段中的1F60单元中
需要注意的两点:
1.段地址*16必然时16 的倍数,所以一个段的起始地址也一定时16的倍数;
2.偏移地址为16位。16位地址的寻址能力为64KB,所以一个段的长度最大为64KB
内存单元地址
1.CPU访问内存单元时,必须向内存提供内存单元的物理地址;
2.8086CPU在内部用段地址和偏移地址以为相加的方法形成最终的物理地址。
思考两个问题?
1.观察下面的地址,读者有什么发现?
结论:CPU可以用不同的段地址和偏移地址形成同一个物理地址。
2.如果给定一个段地址,仅通过变化偏移地址来进行寻址,最多可以定位多少内存单元?
结论:偏移地址16位,变化范围位0~FFFFH,仅用偏移地址来寻址最多可寻64K个内存单元。
比如:给定段地址1000H,用偏移地址寻址,CPU的寻址范围为1000H~1FFFFH
段寄存器
1.段寄存器就是提供段地址的,8086CPU有4个段寄存器:CS(代码段寄存器),DS(数据段寄存器),SS(堆栈段寄存器),ES(附加段寄存器)
2.当8086CPU要访问内存时,由于这4个段寄存器提供内存单元的段地址
3.CS和IP是8086CPU中最关键的寄存器,他们指示了CPU 当前要读取指令的地址。
CS为代码段寄存器,IP 为指令段寄存器(通常存放的是偏移地址)
4.mov指令不能用于设置CS、IP的值,8086CPU没有提供这样的功能
CS和IP
CS和IP 是最关键的寄存器,指示了CPU 当前要读取指令的地址,CS为代码寄存器,IP为指针寄存器
8086CPU工作的过程简要描述如下
- 从CS:IP指向的内存单元读取指令,读取的指令进入指令缓冲器
- IP=IP+读取的指令长度,从而指向下一条指令
- 执行指令,转到步骤1,重复这个过程
8086CPU加电或复位后,CS=FFFFH,IP=0000H,CPU从FFFF0H开始执行
下面介绍一下完整的工作流程:
CS指向的内容相当段地址
IP指向的内容相当于偏移地址
CPU将CS:IP指向的内容当作指令来指向
CPU读取部件指令并指向的流程如下:
CPU从CS:IP获取段地址和偏移地址,通过地址加法器得到内存单元的地址,然后通过输入输出控制电路在经过20位地址总线从内存中读取指令又通过数据总线进入到指令缓冲器,最后执行指令。
执行第一条指令后,变化,及开始执行第二指令流程:
IP会随指令的变化而变化
所有指令执行完成后 段寄存器与指令指针寄存器变化
修改CS和IP
在CPU 中程序员能用指令读写的只有寄存器,但是mov指令不能用于设置CS、IP的值,需要使用转移指令 (jmp)
若想同时修改CS、IP的内容,可用形如jmp 段地址:偏移地址,比如
jmp 2AE3:3执行后CS=2AE3H,IP=0003H 从2AE33H处读取指令
jmp 3:0B16执行后CS=0003H,IP=0B16H 从00B46H处读取指令
若仅修改IP中的内容,可用jmp 某一合法寄存器代表用寄存器中的内容修改IP
jmp ax 执行前 ax=1000h cs=2000h ip=0003h
执行后 ax=1000h cs=2000h ip=1000h
8086PC互作过程的简要描述
1.在8086CPU加点启动或复位后(即CPU刚开始互作是)CS和IP被设置位CS=FFFFH,IP=0000H
2.即在8086PC机刚启动时,CPU从内存FFFF0H单元中读取指令执行
3.FFFF0H单元中的指令时8086PC开机后执行的第一条指令
实验:使用Debug命令查看你的主板ROM的生产日期
提示:ROM的生产日期在内存FFFF0H~FFFFFH的某几个单元中
Debug使用
Debug是DOS、Windows都提供的实模式(8086方式)的调试工具,使用它可以查看CPU各种寄存器中的内容,内存的情况和机器码及跟踪程序的运行。
使用到的Debug功能
- R命令查看、改变CPU寄存器的内容
- D命令查看内存中的内容
- E命令改写内存中的内容
- U命令将内存中的机器指令翻译成汇编指令
- T命令执行一条机器指令
- A命令以汇编指令格式在内存中写入一条机器指令
R命令
首先debug后,输入r查看全部寄存器内容
修改寄存器中的内容,比如修改ax的值为200
r ax
200
D命令
D命令查看内存内容,d 用段地址:偏移地址 查看
d 1000:0 查看1000:0处的内容
d 1000:0 9 查看1000:0~1000:9的内容
使用D命令将输出三部分内容:
中间是从指定地址开始的128个内存单元的内容,用16 禁止的格式输出,每行的输出 从16的证书倍的地址开始,最多输出16个单元的内容,每行的中间有个 - 便于查看
左边是每行的起始位置
右边是每个内存单元中数据对应可显示的ASCII码字符,没有对应的字符就用 . 表示
E命令
使用E命令能改写内存中的内容,比如将1000:0~1000:9的内容该为0~9可以使用 e 1000:0 0 1 2 3 4 5 6 7 8 9 来进行
也可以使用提问的方法从某一地址逐一修改,步骤如下:
- 输入 e 1000:10,按Enter
- debug显示1000:0010单元的原始内容
- 输入数据改写当前的内存单元,或者不输入数据,按空格不改写
- 当前单元完成后,按空格结束修改,自动进入下一个单元
- 所有改写完毕后按Enter结束
可以使用E命令写入字符,比如 e 1000:0 1 'a' 2 'b' 分别写入1,a,2,b的ASCII值
也可以写入字符传,比如 e 1000:0 1 "a+b" 2 "c++" 分别写入1,a+b,2,c++的ASCII值
也可以写入机器码,用U查看内存中机器码的含义,用T命令执行内存中的机器码,比如写入这三条
机器码对应的汇编指令
b80100mov ax,0001
b90200mov cx,0002
01c8add ax,cx
可以使用 e 1000:0 b8 01 00 b9 02 00 01 c8 来完成
U命令
用U命令可以查看内存中机器码对应的汇编指令,比如 u 1000:0 查看
U 命令的显示输出分为三部分:
- 每一条机器指令的地址
- 机器指令
- 机器指令对应的汇编指令
T命令
使用T命令可以执行一条或多条指令,简单的使用T命令,可以执行CS:IP指向的指令
- 首先用E命令向目标内存单元写入机器码
- 用R命令查看CPU 中寄存器的状态,修改CS:IP指向目标地址
- T命令执行写入的指令,debug显示执行后寄存器的状态
A命令
以汇编指令的形式写入机器指令,在给出的起始地址后直接按Enter表示操作结束
a 1000:0
1000:0000 mov ax,1
1000:0003 mov bx,2
1000:0005 mov cx,3
Debug安装
debug安装教程:https://www.cnblogs.com/zhaijiahui/p/10148698.html
ASMT00ls:https://www.yuque.com/desktop/auth?url=https%3A%2F%2Fwww.yuque.com%2Fattachments%2Fyuque%2F0%2F2025%2Frar%2F46595978%2F1750241004893-8fdee8b4-4083-46df-8686-f099c4123c37.rar%3Ffrom%3Dhttps%253A%252F%252Fwww.yuque.com%252Fyizhiyiyudebuoumao%252Fysr4tp%252Figgn8qdeqy6uva82&token=encrypted%7CsN7SGO0v2US-KGseTh0jmbaSJcNPvME0PlAAwRnmkzVp4VWiKtkHcF6KwSoCcloW0VQg4zr7lhUV26fc9hQx1mxpC9GdJGTzeQYZDmATPKfFvuwk9MIZq5253NilWxZqpbC2we4c-kt6DQIwTNeZ631iDSEPerjQetlq7x0Nf9QtYyjgwX_cpD30rMRZaQnpdmeHxmoxQGeXUdkBf_MhXzvHH8UBVjtbpbxYvx-mMraHwazElOi6yS1n040dA9SFKKPIFfPIslzGICAy33L7uR2WXQL-pMhhBEP-895BGZU%3D
或者使用windows 2003虚拟机 在cmd下直接输入debug即可
ASMTools:
📎AsmTools.rar
0x02
往前笔记:
往期精彩实战:
红队视角下的域森林突破:一场由Shiro反序列化引发的跨域控攻防对抗
域控接管后的“核爆效应”:基于DCSync与黄金票据的1600台主机权限收割
0x03
粉丝福利:
原文始发于微信公众号(伍六七安全):汇编语言Day01
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论