免杀笔记 ----->汇编基础

免杀的第一件事,当然是学汇编啦,小编也是从0开始呢!!!一起来看看吧!

免责声明,本人所有教学内容仅供参考,无任何不良引导,内容资料来自网络,如有侵权请联系删除!!!!

**1.**数据宽度

学计算机的大家一定不会陌生,比如经常听什么一个字节等于8个比特 ....这种之类的。

其实可以分为以下这些单位

  • 比特 比如像我们平时所看见的那些 0101101001010这样子,一位就是一个bit
  • 字节 也可以叫做Byte,就好像我们上面说的,一个字节就是8个比特
  • 字 是计算机进行数据存储和数据处理的运算的单位。而一个字又是两个字节

这里就要说一下,如果你往一个32位寄存器里面存很大的数,肯定是不行的,超过了数据宽度

2.进制

我们在生活中用的最多的就是十进制了 ,但是计算机可不是用的十进制 而是二进制01010这些

其中我们在免杀中需要熟悉的,就是2进制和十进制吧,8进制的话少一点

就比如 0x08 = 8 = 0100 , 0x10 = 16 = 10000 0xC = 12 = 1100

这种简单的计算还是要会

3.通用寄存器

我们一开始先是去研究32位下的寄存器

  • EAX
  • ECX
  • EDX
  • EBX
  • ESP
  • EBP

我们去OD看一下mimikatz的就知道了 ,这个OD只能打开32位的哦,你别拿64位的mimikatz 那当然是打不开的

我们看见最右边那个就是对应的通用的寄存器

4.OD的使用

虽然在这里插入感觉有的点突兀,但是既然提到了OD,那还是要给大家去讲一下怎么使用的

  • F8 单步步过

当我们想要从0075ECF7走到0075ECFA的时候只需要F8 一下就好了!!!

  • F7 单步步入

就拿我们的c++来举例子

当我们输出完1之后我们就要进入函数,如果f8的话就直接略过函数,f7则是单步进入

那这个举例子,如果我们继续f8的话,就会直接执行这个函数的结果,然后走到0075ED0E

如果我们F7的话,就会进入到栈(可以看见前面的地址都不一样了)

  • F2 打断点

假如我现在有一个程序在 0075EF12这个位置我想让他跑去 0075EF27这个位置

我们只需要在 0075EF27 这个位置点一下,然后直接F2

他变红了,但是此时我们程序还是运行到了0075EF27这个位置而已

  • F4 运行到指定位置

继续上面,我们只要F4一下,就能让他跑到0075EF27这个位置

5.汇编指令

1.mov

其实就是move,我来操作一遍你就懂了

这个指令就是将334的值移动到eax这个寄存器里面

看,瞬间就变红了 其中eax就是寄存器,然后0x334我们称之为立即数

当然了,除了我们直接这样子赋值,也可以直接这么写

意思就是把Dword(32位数据类型)ptr 在 0x00BF5F9D4这个地址的值给拿出来,丢到EAX里面

不出什么以外的话,EAX应该是变成了00B5F9E8

当然,也是可以直接把寄存器当作一个地址来用的,但这时候寄存器的值就变成了一个地址,而不是寄存器的值 我们后买你lea会讲到

2.add sub

这个看起来都很明白了吧,我就直接用一个示例来演示一下得了

这个意思就是EAX=EAX+0x11 有没有编成里面的+=的意思捏,嘻嘻嘻

不出意外就是 00CFFC55

那么同理 SUB也是一样的!!! 我就不过多演示了

3.and or xor

这个可能对于学过离散数学的会比较好理解,我们还是来举一个例子

4 and 7 也就是离散数学上的 4 和取7 (二进制)

  • 4:0100
  • 7:0111 这两个合取结果应该是 0100 也就是4

结果也是如此

然后就是我们的XOR 也就是异或 为我们还是拿上面的来举例子

  • 4:0100
  • 7:0111 这两个异或结果应该是 0011 (异或就是只有01同时存在才为1)

那么答案不出意外的话,应该就是 3

4.lea

这个用的多,最简单的就是这样

将0x446这个地址(不是这个地址的数)直接给到EAX,所以EAX应该会变成446

但是一般没人会这么用,我们更多的是直接用的寄存器

至于为什么要这样子用,我们讲到堆栈的时候你就懂了

最常用的更是我们的立即数配和寄存器

至于为什么,我们后面再说

5.push pop

这两个都是涉及到了堆栈,我们下面再讲

6.cmp

这个我们也放在下面讲

5.内存寻址

这个其实我们在上面的add的时候就已经提到了一些了

其实也就是通过内存地址来获取或者得到一些值,这个内存地址,你可以直接写地址,或者直接写寄存器。

不过还是要说一下,我们刚才的那个 dword ptr ds:[0x2121312]这个例子

我们里面提到的ds ,在用户层只是起寻址的作用,在内核层涉及到段,页有别的作用
cs :代码段
ds :数据段
ss :堆栈段
es :附加段

6.代码是怎么执行的

我们一定用过VS或者devcpp等其他编译器写过代码,那么他的底层逻辑是什么呢???

因为我们的CPU只能看的懂0 1 ,所以一般是这样的一个过程

c/cpp代码 ---> 汇编代码 ------> 硬编码 ------> CPU

我们去VS看一下,就像这段最简单的hello world

我们右键转到反汇编

就能看见我们的汇编代码

然后我们再把他转换成硬编码

然后就是到了CPU那里了,我们的 "Hello World!" 就是这么被执行的

7.标志寄存器

我们再OD里面除了能看见我们的通用寄存器,我们还能看见这个标志寄存器

对于32位下,我们的标志寄存器叫做EFlag ,也就是我们看见上面的EFL

在64位下,我们的标志寄存器就叫做RFlag

其中EFlag寄存器各个位置有各个位置的不同作用,特别是ZF这个位置,也就是上面我们看见的Z这个位置,我们来举个栗子

我们用CMP这个汇编指令的时候,我们总不能把返回结果存储在eax中吧,这时候就要用到标志寄存器中的ZF这一个位置

我们能看见Z这个位置变成了1 就是说明了结果相同,这个到后面的JCC语句会用

同样的还有CF

CF:进位标志CF(Carry Flag),如果运算结果的最高位产生了一个进位或借位,其值为1,否则为0

OF

如果运算结果超过当前运算位数所能表示的范围,则称为溢出,OF的值被置为1,否则,OF的值被清为0。

8.堆栈

栈Stack,堆Heap这两个对于程序员来说更是经典

:用于存储函数的局部变量和函数调用的上下文信息。栈上的数据在函数执行结束时自动释放。

这个其实很好理解,就像这个代码,我们的两个a都是开在了栈上面

:用于动态分配的内存,由程序员手动分配和释放。在C语言中,使用 malloc()calloc() 等函数分配的内存位于堆上。

这个也很好理解,像下图,就是在堆区上开辟了一个长度为三的整数数组,并且用p指向了首地址

而规定了,进出函数的前后堆栈的地址不能改变

Jmp

这个其实就是Jump的缩写,就是直接跳转到其他地址

我们之际JMP一下,就能直接跳到我们对应的地方了

但是JMP不会堆堆栈的位置进行改变,怎么看是否改变呢??? 还记得我们之前的通用寄存器码

  • ESP 指向栈顶
  • EBP 指向栈底

我们可以去尝试,堆栈在JMP下是不会发生改变的

Call Ret

这两个一般都是搭配使用的

  • Call 跳转到指定地址并返回到当前指令的下一行,当我们调用这个的时候,他会先将esp提升四个字节,并将返回地址压入堆栈 (提栈)
  • ret 返回到指定地址,当我们调用这个指令的时候,会将esp降低四个字节,并且从堆栈中取出返回地址,传递给EIP(运行的地址)

这么说似乎有点抽象,我们来举个栗子就懂了

首先我们遇到了一个call,然后有以下的信息

  • 当前的地址是 EF12 下一步的地址是 EF17
  • 当前的EBP是 FB34 ESP的地址是FB28

然后我们单步F7进入一下

然后又能收集到以下的信息

  • 我们的ESP减少了4(提栈)ESP变成了FB24
  • 并且我们的返回地址EF17被压栈,压入了FB24

然后我们直接跑到retn那里

可以看见函数跑了一通之后我们的ESP还是FB24里面还是EF17,然后我们F8走一下

还是能收集到以下的信息

  • retn成功的返回了我们的地址
  • ESP是FB28 EBP是FB34 和函数一开始调用时候的栈地址是一样的!!!!!

Push Pop

这两个其实和Call 和Ret有点像的,但是也有差异

在介绍这两个命令之前,还得讲一下栈的数据存储,是从高到低的,比如我上一个是94,那么我压栈存数据之后就应该存在90这个地址!

Push 压栈,将ESP减少4,然后将数据压入。

有点类似call的功能,只是将返回的地址更换成了数据

Pop 出栈 将ESP加4,并且将原来ESP的数值取出放到指定的地址或者寄存器

有了上面的Push的基础,我们就不难理解我们的pop了,直接举例子吧

像这样,就是直接把ESP的值取出来,mov到EAX,然后将ESP的值加上4

9.JCC语句

JCC不知道能不能被翻译为Jump Condition Code

其实就是和标志寄存器实现了一个联动,一般格式如下

bash 复制代码
JCC target_address

JZ/JE jump if zero;jump if equal 其实就是检查ZF这个位是不是为1,是则跳转
举个栗子,首先我们构造一个Z标志位为1的一种情况

然后我们直接构造一个JCC语句

因为我们的Z位置是1,所以他是会直接跳到我们对应的位置的

JNZ/JNE jump if not zero;jump if not equal 如果ZF为0则跳转
这个其实和上面的那个差不多,我就不给大家演示了。

10.堆栈图

这个算是有点难吧,不过也是理解就好了,其实你把上面的指令都理解清除的话,就不会有问题。

我们之前说的栈平衡其实有点问题,就是并不是说call回来之后esp一定会与原来相同,有些则是通过 add esp,0x...... 这样来实现ESP不变 ------->这样我们也叫他是栈平衡(看他是在函数外平衡堆栈还是在函数内平衡堆栈)


具体堆栈图就不演示了,因为会非常麻烦,而且混乱(除非视频讲解),但是原理还是一样

相关推荐
猫猫的小茶馆16 小时前
【Linux 驱动开发】一. 搭建开发环境
linux·汇编·arm开发·驱动开发·stm32·嵌入式硬件·mcu
猫猫的小茶馆17 小时前
【Linux 驱动开发】二. linux内核模块
linux·汇编·arm开发·驱动开发·stm32·嵌入式硬件·架构
切糕师学AI1 天前
ARM 中的 SVC 监管调用(Supervisor Call)
linux·c语言·汇编·arm开发
ベadvance courageouslyミ2 天前
硬件基础中断
汇编·硬件·中断
你爱写程序吗(新H)2 天前
基于单片机的洗衣机控制系统设计 单片机洗衣机控制(设计+文档)
c语言·汇编·单片机·嵌入式硬件·matlab
VekiSon2 天前
ARM架构——用汇编语言点亮 LED
汇编·arm开发·嵌入式硬件
JJCar3 天前
汇编文字池(literal pool)
汇编·文字池·literal pool
乾复道4 天前
巧用终端,每天节省2小时
汇编·经验分享·vim
2501_927773074 天前
嵌入式——汇编语言1
汇编
山峰哥4 天前
数据库工程核心:SQL调优让查询效率飙升的实战密码
网络·汇编·数据库·sql·编辑器