裸函数实现加法运算1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253// Test.cpp : Defines the entry point for the console application.//#include "stdafx.h"int __declspec(naked) add(int x,int y,int z){ __asm { //保存栈底 push ebp //提升堆栈 mov ebp,esp sub esp,0x40 //保存现场 push ebx push esi push edi //缓冲区数据填充 mov eax,0xCCCCCCCC mov ecx,0x10 lea edi,dword ptr ds:[ebp-0x40] rep stosd //函数实际操作 mov dword ptr ds:[ebp-0x4],1 mo ...
裸函数编译器不做任何分配,配合钩子执行自己想要的效果
普通的C程序可以正常执行,但是如下裸函数不允许直接调用
1234void __declspec(naked) Add(){ }
修改裸函数为普通C程序的运行模式
12345678910111213141516171819202122232425262728293031323334353637383940414243// Test.cpp : Defines the entry point for the console application.//#include "stdafx.h"int __declspec(naked) Add(int x,int y){ __asm { push ebp mov ebp,esp sub esp,40 push ebx push esi push edi mov eax,0xcccccccc mov ecx,0x10 lea edi,dword ptr ds:[ebp-0x40] rep stosd mov eax,d ...
安装VisuaI C++根据自己学习的视频和老师使用的编辑器同步即可
C++兼容C语言,可以在这个文件里写c也可以写c++
1https://www.runoob.com/cplusplus/cpp-environment-setup.html
快速创建项目1、file–>new
2、为项目取名并且放到一个合适的目录中
3、选择Hello world程序
4、打开源文件
项目描述12345678910// Test.cpp : Defines the entry point for the console application.//#include "stdafx.h"//程序运行需要依赖该行代码,后面会具体解释int main(int argc, char* argv[])//程序的入口{ printf("Hello World!\n");//打印一句话Hello World! return 0;}
F7编译当前项目为.exe文件放到项目目录的Debug目录下
C:\Project\Test\Debug
...
指令扩展JMPjmp 0040193F= mov eip,0040193F,只不过寄存器不允许直接mov的写法,意思一样
无条件修改寄存器EIP的数值,cpu会根据eip的值跳转,不影响堆栈的值
jmp 0040193F
jmp只影响eip
CALL与retn配合使用
call会把当前cpu汇编指令的下一行地址压入栈里,执行完当前call指令以后跳转回去继续执行,压入的地址被称为返回地址,call指令会通过当前指令有多少字节的数据计算返回地址
RETN相当于pop eip,但是寄存器不允许直接写pop eip
CMP相当于sub指令
eax=0x400
ecx=0x400
与sub指令区别就在于cmp指令只影响标志寄存器,不会修改eax,ebx两个寄存器的数值,cmp指令常常用于判断两个数值是否相等,根据zf位判断
TEST两个数值进行与操作,结果同样不保存,但是会改变相应标志寄存器
该指令尝尝用于判断某个寄存器的值是否为0
JCCJCC指令是x86汇编语言中的条件跳转指令,根据不同的条件码(CF、ZF、SF、OF等)来决定是否跳转,jcc ...
push后面跟立即数就是以四个字节为单位
push后面跟寄存器与内存的时候根据宽度计算栈顶地址,八位的寄存器和八位的内存除外
标志寄存器
进位标志CF运算结果最高位产生了进位或者借位,那么值为1,这里的最高位就不说是以字节为单位了,单纯的指最高位的那个数字,需要注意的是判断进位首先要明确数据宽度
奇偶标志PF用于反应运算结果(二进制结果)中1的个数,1为偶数个时,pf位置1,否则置0,注意该位置只看低位一个字节内的1和0
辅助进位标志AF发生如下情况时,辅助进位标志的值被置1,否则为0
1、对dword操作时,低字向高字进位或借位时
2、对word操作时,低字节向高字节进位或借位时
3、在byte操作时,发生低4位,向高四位进位或借位时
零标志ZF反应运算结果是否为0,结果为0时,置1,否则为0,运算结果指的是操作数进行某种运算所得到的结果,例如加法、减法、乘法、位运算等。mov这种指令不属于运算结果的范畴
符号标志SF运算结果的最高位是什么,SF就是什么
溢出标志OF有符号数前提下,符号位(最高位)与最高有效位(符号位紧跟的一位)
符号位有进位,1,无 ...
堆栈用于临时存放数据的一种【数据项按序排列的数据结构】,堆栈本质上就是一块内存,由于寄存器可存储的大小有限,无法满足程序在运行的时候对临时数据的运算,所以我们需要在内存里开辟一块特殊的空间
1、用于操作临时数据
2、它需要记得自己存了多大的数据
3、对自己所管辖的数据要具有快速查找的功能
设计原理借用两个三十二位寄存器来存储两个内存地址,这两个内存地址中间的区域就是堆栈的数据 base–>top
两个内存地址相减的值就是存储数据的大小
windows机器堆栈存储数据通常是从大的地址单位向小的地址单位存储数据
两个内存地址任选一个加上偏移量就能找到我们想要的数据
模拟堆栈堆栈最早存入数据的内存地址编号称为栈底 EBP
堆栈最后存入数据的内存地址编号称为栈顶 ESP
假设ebx寄存器存放的我们栈底的地址
假设edx寄存器存放的我们栈顶的地址
入栈也就是向堆栈里写入数据
存数据的时候栈底一直不变,也就是ebx不变
接下来存入四个字节的数据,可以先写入数据再改变栈顶的值
也可以先改变栈顶的值再写入数据
出栈也就是把堆栈里面的数据拿出来
同理,先改变栈顶指针的值,再弹出 ...
od窗口简单认知
在反汇编窗口和寄存器窗口数据都是高位在前低位在后,所以0x12345678这个数据的最高位是0x12,为什么不说最高位是0x1呢,因为数据窗口最小单位是以字节为准,一个字节代表八位二进制数,也就是两个16进制数,所以0x12刚好组成一个字节
123db [内存地址] 以字节单位查看数据dd [内存地址] 以双字单位产看数据
一个内存地址能存储一个字节的数据,堆栈窗口的数据是从后网前排序,数据窗口是从头往后排序
内存地址表示方式在逆向过程中看到的汇编指令都是计算机反汇编出来的,内存地址不会很直白的写着0x12345678这种形势,常见形式是需要经过计算
如果地址宽度超过了ffffffff只取ffffffff,多的丢弃,而且反汇编回来的代码不会超过最大范围
123lea指令,获取内存编号 lea ecx,dword ptr ds:[0x22F9C8] //将内存编号存入ecx寄存器,mov指令会把内存编号对应的值存入寄存器
立即数1mov eax,dword ptr ds:[0x22F9C8]
reg(寄存器)12mov ecx,0x22F9B0// ...
汇编指令MOV(移动)12mov eax,0x1mov eax,edx//将edx的数值拿到eax里
ADD(加法)1add eax,5//将5与eax里面的数值相加放到eax里
SUB(减法)1sub eax,5//将5与eax里面的数值相减放到eax里
AND(与运算)1234567mov eax,2and eax,3//计算2&3的值,结果为2 0010 0011 ---- 0010
OR(或运算)1234567mov eax,2or eax,3//计算2|3的值,结果为1 0010 0011 ---- 0011
XOR(异或运算)1234567mov eax,2xor eax,3//计算2^3的值,结果为1 0010 0011 ---- 0001
NOT(非运算)123456mov eax,2not eax//FFFFFFFD 00000002 -------- FFFFFFFD
计算机的位数代表着计算机的寻址宽度,例如32位计算机寻址宽度为4G,每一个内存编号代表一个字节
操作内存 ...
寄存器就是CPU内存区域,与内存里面的存储介质没有区别,但是CPU极其昂贵,运算速度非常快
三十二位通用寄存器寄存器的用途不是固定的,就好像代码编写时候的命名规范一样,不按规范代码也是可以正常运行,但是约定俗成的规矩最好还是遵循相关规定,那样可以提高工作效率
12345678EAX 0 累加器ECX 1 计数EDX 2 I/O指针EBX 3 DS段指针ESP 4 堆栈指针EBP 5 SS段指针ESI 6 源指针EDI 7 目标指针
利用OD打开一个exe程序
EIP也是一个寄存器,代表当前程序运行到哪个位置,我们用od打开exe程序的时候会停在某个位置,点击F8会向下一步执行
注意填入的数据不要超出32位,否则会丢弃高位数据
寄存器分类1234567891011121314151617181916位寄存器AX 0CX 1DX 2BX 3SP 4BP 5SI 6DI 7 8位寄存器ALCLDLBLAHCHDHBH
注意,16位寄存器是32位寄存器的一部分,两者是包含关系
猜一下al的数值改变eax的值会有什么变化
注 ...