一、进制
进制的运算
进制本质是查数
例如八进制运算
0 1 2 3 4 5 6 7
10 11 12 13 14 15 16 17
2+3 = 2后边三个数 所以是5
2*3 = 3+3就是3后边3个数 就是6
4+5 =就是 4后边5个数就是11
那数量大怎么办
十进制有十进制加法表
八进制有八进制加法表

乘法表


计算步骤 3+7 = 12 3+7 +1=13 2+3+1=6 所以是 632



二、二进制简写形式
为什么计算机要用二进制

那为什么用文档打开都是十六进制呢

三、数据宽度



四、无符号数和有符号数
无符号数

数字是啥就是啥
就是0x9A
有符号数

最高位为0 就是正数
为1就是负数
五、原码反码补码
编码规则

例如文本有文本编码规则,视频有视频编码规则
有符号数的编码规则

例如 用Bit距离
1 原码、反码、补码都是 0000 0001
-1 原码是 1000 0001 反码是 1111 1110 补码是 1111 1111

而-1 对应内存中的 FF 所以负数是以补码的形式存储的
-7 原码 1000 0111 反码 1111 1000 补码 1111 1001
总结 :
正数以原码存储 ,负数以补码存储
存储范围 (以bit为例子)

六、计算机运算
位运算
与运算

或运算

异或运算

非运算

左移

右移

运算过程
计算机只能进行位运算。
第一步
先进行异或操作
第二部进行与运算判断是否存在进位

若与运算后为0 则没有进位 不为1则存在进位
若存在进位 则对与运算结果左移一位再继续异或
再重复第二部操作看是否存在进位
若结果为0则此就是正确答案

这是4+5
4-5呢
4-5=4+(-5)

七、汇编
1.寄存器
寄存器是cpu存储数据的地方
2.通用寄存器

实际上寄存器有32位 16位 8位
都是同一个寄存器 六 eax 就是32位 ax就是16位 是32位分出来一般 al就是8位

3.标志寄存器
EFL 32位

3.1 CF位
若算术操作产生的结果在最高有效位发生进位或者错位就会将CF位置为1 反之清零
如:
AL是八位寄存器,FE+2会溢出所以导致进位,CF为变为1

7F-FF会导致借位,CF也会变为1
所以CF位通常用来标识无符号运算是否存在溢出
3.2 PF位
PF位只统计最后一个字节,不管是四字节还是二字节,他只统计最后一个字节中的1的数量,若为偶数则PF位为1,反之为0
PF位一般用于奇偶校验检查
3.3 AF位
只有第三位发生进位或借位才置为1,主要用于BCD运算
也是和PF一样 无论是四字节还是二字节或者是单字节 都只看最后一个字节中的第三位中是否发生进位或错位
3.4 ZF位
若结果为0,则将其置为1,反之清零
3.5 SF位
该标志呗设置位有符号整型的最高有效位
意思就是 0指示结果为正,反之为负
3.6 OF位
溢出标志,反应有符号数运算是否溢出
如果是无符号数运算,是否溢出看CF位
如果是有符号数运算,是否溢出看OF位
3.7 DF位

ELF第十位是DF位 也叫方向位
如果DF位是 0的话 我们使用movs指令后内存地址是加
如果DF位是1的话 我们使用movs指令后内存地址是减
4.指令
4.1 mov
用来移动数据
例如
1 | mov eax,1 |
就是将1存入eax寄存器中
1 | mov edx,eax |
就是将eax中的值存入edx中

4.2 add

加法 例如
add eax,ecx 会把两个寄存器数值相加存在eax中
4.3 sub
减法指令

和加法相似
4.4 and
与运算

4.5 or
或运算
4.6 xor
异或运算
4.7 not
非运算 只有一个操作数

4.8 movs
mov不支持 将数据从内存移动到内存
但是movs可以

而且有简写方式
没执行一次内存地址自动加
例如BYTE就加一个字节 WORD就加两个字节
4.9 stos

运行指令后EDI也会加减 取决于DF
DF位0就是加 1就是减
如果是BYTE 就存AL的值
如果是WORD就存AX的值
如果是DWORD 就存EAX的值
4.10 rep

ECX相当于计数器
4.11 jmp
jmp 用来修改EIP, EIP中存储下一次CPU执行的地址
使用方式:
jmp 1 相当于将EIP内容修改位1
jmp eax
jmp dword ptr ds:[内存地址] 都行
4.12 call
在调试器中要让代码一行一行执行按F8
但是call指令需要按F7
call指令功能是将值赋给EIP的同时将call指令的下一行地址存入栈中
call 1
call eax
call dword ptr ds:[内存地址] 都行
4.13 ret
ret 指令没有参数 作用是将栈顶存储的数值取出放入EIP
4.14 cmp
也是减法指令 不过和sub不一样的是相减的结果并不会保存到第一个操作数中
八、内存
内存地址

向内存中写入数值

启动 Dword 和word 都是数值大小 例如Dword就是4字节
0018FFFC就是内存地址
内存地址的五种形式
1、形势一:[立即数]

2、形式二:[reg]


3、形式三:[reg+立即数]

4、形式四:[reg+reg*{1,2,4,8}]
5、形式五:[reg+reg*{1,2,4,8}+立即数]
九、存储模式
大端模式
数据高位在低位,数据低位在高位
例如0x1A2C

小端模式
数据低位在低位,数据高位在高位
所以0x1A2C应该是

x86大部分是小段模式
arm 例如手机大部分是大端模式
十、堆栈
1、什么是堆栈

2、栈指针寄存器
ESP 存储了栈指针
3、堆栈的使用
4、Push指令

5、Pop指令

十一、调试
1.单步步入与单步步过
1.1单步步入F7
是指运行该行代码的同时,进入该行代码,查看该代码如何运行,查看详细的运行过程。
1.2单步步过F8
是指运行完该行代码之后运行下一行代码。
区别
由于call有好几个步骤,如果F7的话会一步步进行
如果F8的话会把call所有步骤一次执行
2.调试器实现原理
2.1断点
断点就是让程序执行到断点的地址的时候停下来
可以手动打断点F2,也可以让地址的指令为int 3
实际上F2就是让地址指令为CC 也就是int 3 只是调试器没有显示
十二、反调试
1.Fake F8
这里使用的技术是利用call指令
因为call指令会下个断点在下一行地址,然后call执行代码段后有个ret指令可以跳回断点位置。
而Fake F8 技术就是通过 改变call指令将下一行的地址存入栈中数据
例如:
这个指令会将004183DC存入栈中 然后EIP跳转到0041840D执行 一段语句后会执行ret指令会将栈顶的004183DC存入EIP中达到跳回的目的。而Fake F8技术 就是让0048140D中的语句修改栈顶的数值让ret指令无法精准跳回让破解人员无法调试。
但是这个技术可以通过按F7一步步查看call命令所执行的所有语句来破解。

利用大量废数据让破解人员无法准确调试
十三、汇编眼中的函数
1.函数
函数就是一系列指令的集合,为了完成某种会重复使用的功能
2.调用函数
用jmp和call调用函数
但jmp执行后无法跳回
所以一般使用call调用函数
3.简单函数
例如简单的加法函数
1 | add ecx,edx |
这就是简单的加法函数,要调用的话
1 | mov ecx,1 |
其中1,2就是所谓的参数
而eax通常就是返回值
4.堆栈传参
那寄存器就八个,如果有十个参数该怎么办呢?
利用堆栈传参
比方说五个参数
1 | push 1 |
函数:
1 | mov eax,dword ptr ds:[esp+14] |
那为什么push 5 但是是把esp+4和eax相加呢
因为call指令会将下一行的地址压入栈中
如果esp不加4的话会把call指令压入栈中的地址当作参数相加了也就是不是5
十四、堆栈平衡
1.什么是堆栈平衡
如果要返回父程序,则我们在堆栈中进行操作时,要保证RET执行之前ESP指向的是我们压入栈中的地址
如果用堆栈传递参数后,在函数执行完也应该将压入栈中的垃圾数值释放
2.平栈方式
2.1外平栈
如果有两个参数 直接在函数执行完后让esp+8
2.2内平栈
ret函数后跟 8
意义和add esp,8是一样的
十五、外挂
1.什么是外挂
外挂其实就是在工具中修改该进程的内存,或者通过工具执行他本不该执行的语句
十六、ESP寻址
通过esp+数定位传入的参数
但若是函数很复杂esp+几很难计算
例如:
执行函数前有操作堆栈的操作。
十七、EBP寻址
ESP是栈顶指针
而EBP是栈底指针
EBP寻址和ESP寻址类似 由于ESP会随着入栈出栈而改变不方便定位,EBP相对固定所以用来寻址更加方便。
思路就是重新划分一个堆栈。
1 | 1.保存ebp的值 |
十八、JCC指令


