0x00
开设日常学习和笔记分享的篇章,帮助大家来学习汇编语言。为什么要学习汇编语言呢?是由于在红蓝对抗中,常常因为一些AV/EDR的存在导致我们的工具被查杀。所以才需要我们来对抗AV也就是免杀技术。所以要学习免杀技术就要从基础开始。后续可能还会分享一些C++、PE文件结构等等笔记。另外也可能会推出逆向相关的知识。
0x01
三、第一个程序
源程序从写出到执行的过程
一个汇编语言程序从写出到执行的过程:
- 编写汇编源程序
- 对程序进行编译链接,生成可执行文件
- 执行可执行文件中的程序
可执行文件包含两部分内容:
- 程序(从源程序中的汇编指令翻译过来的机器码)和数据(源程序中定义的数据)
- 相关的描述信息(比如程序有多大,要多少内存空间)
源程序
assume cs:codesg ;assume:含义为“假设”,然后cs声明为代码段,还有db声明数据端 ss声明为栈段
;冒号后面的内容可以自行其名称,但需要于下面对应
codesg segment ;声明代码段的开始
mov ax,0123h
mov bx,0456h
add ax,bx
add ax,ad ;这段位汇编代码
mov ax,4c00h ;这里表示程序结束,固定写法,程序必须有返回
int 21h
codesg ends ;声明代码段的结束
end;程序结束
- segment和ends是一对成对使用的伪指令,这是在写可呗编译器编译的汇编程序时,必须要用到的一对伪指令。segment说明一个段的开始;ends说明一个段结束
- 一个汇编程序是由多个段组成的,这些段被用来存放代码、数据或当作栈空间使用
- 一个有意义的汇编程序中至少要有一个段,这恶鬼段用来存放代码
- end是一个汇编程序的结束标记,编译器在编译汇编程序的过程中,如果碰到了伪指令end,就结束对源程序的编译。
- 如果程序写完了,要在结尾处加上伪指令end,否则,编译器在编译程序时,无法知道程序在何处结束
- assume:含义为“假设”它假设某一段寄存器和程序中的某一个用segment...ends定义的段相联
- 通过assume说明这种管理,在需要的情况下,编译程序可以将段寄存器和某一个具体的段相联系
- 编号:一个标号指代表一个地址;codesg:放在segment的前面,作为一个段的名称,这个段的名称最终将被编译、连接程序处理为一个段的段地址
- 程序返回:应该在程序的末尾添加返回的程序段。
- mov ax,4c00h
- int 21h(中断机制)
- 这两条指令所实现的功能就是程序返回
编译源程序
可以用任意的文本编辑器来编辑源程序,也可以使用dos下的edit
- 进入DOS方式,在C:>后输入edit
- 在edit中编辑程序
- 将程序保存为C:1.asm后退出edit
编译
我们使用微软的masm汇编编译器
- 进入DOS方式,进入masm目录,运行masm.exe,C:masm>masm
运行masm会显示一些版本细腻些,然后输入要被编译的源程序文件的名称,[.asm]提示我们默认文件扩展名是asm,比如要编译的程序文件名是p1.asm,只需要输入p1即可,如果程序不是以asm为扩展名的话,就要输入全名,在输入源程序文件名是,一定要指明路径,如果文件就在当前路径下,秩序输入文件名就可以,如果文件在其他目录中,则需要输入路径
连接
编译源程序后得到目标文件后,需要对目标文件进行连接得到可执行文件,比如1.asm编译得到1.obj,在连接为1.exe
使用Overlay Linker连接器
- 进入DOS方式,进入masm文件夹,运行link.exe,首先会显示一些版本细腻些,然后提示输入要被连接的文件名称,规则同编译
- 输入要连接的文件名,按Enter,程序提示输入生产的文件名称
- 确定名称之后程序显示List File [NUL.MAP]: ,为连接的中间过程,可以Enter跳过忽略映像文件的生成
- 屏幕显示Libraries [.LIB]提升输入库文件名称,如果调用某个库中的子程序需要在这里连接,一般忽略之间Enter
- 屏幕显示 LINK:warning L4021:no stack segment,没有栈段,不理会这个错误,得到1.exe
连接的作用
- 源程序很大时分为多个源程序来编译,分别编译后进行连接生成一个可执行文件
- 程序调用某个库中子程序,需要将库文件和程序生成的目标文件里那句,生成一个可执行文件
- 源程序编译后得到存有机器码的目标文件,有些还不能直接生成可执行文件,连接程序处理为最终的可执行信息
简化的编译和连接
简化的方法是忽略中间文件,首先 masm 1.asm; 编译1.asm,然后 link 1.obj;最后得到1.exe
程序执行可能只是计算,不向屏幕输出信息,程序执行文成后屏幕会出现操作系统提示符
谁将可执行文件中的程序加载入内存并使它运行
操作系统的外壳
DOS中有一个程序command.com,被称为命令解释器,就是DOS的shell,DOS启动时先完成其他重要的初始化工作,然后运行command.com,之后屏幕出现命令提示符
用户输入命令入cd dir等这些命令有command执行,如果用户执行某个可执行文件,command将可执行文件中的程序加载入内存,设置cs:ip指向程序的入口,之后command粘贴,cpu运行程序,运行结束后返回command中,再次显示命令提示符。
程序执行的过程跟踪
可以用debug将程序加载入内存,跟踪程序的运行程序,debug将程序载入内存,设置CS:IP指向程序入口,但是不放弃对CPU控制
在提示符输入debug 1.exe后,使用r命令查看各个寄存器的设置情况
cx中存放的是程序的长度,实例程序有15个机子,则加载后cx为000FH
程序加载后,ds中存放所在内存区的段地址,偏移地址为0,则程序所在内存区ds:0
这个内存区钱256租户额存放psp,dos用来和程序进行通信,256字节后存放的是程序
现在我们可以开始跟踪了,用T命令单步执行程序中的每一条指令,并观察每条指令的执行结果,到了 int 21h 我么能使用p命令执行,执行后显示 Program terminated normally,表示程序正常结束
使用q退出debug,将返回到command中,因为程序追踪过程是command加载的不过,debug加载1.exe
实验:编写一个程序,并进行编译,连接以及追踪
要求:编写一个程序求出2的平方等于多少,并存入内存的1000h:0处。
0x02
往期笔记:
往期实战:
红队视角下的域森林突破:一场由Shiro反序列化引发的跨域控攻防对抗
域控接管后的“核爆效应”:基于DCSync与黄金票据的1600台主机权限收割
原文始发于微信公众号(伍六七安全):汇编语言Day03
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论