赞
踩
不同位数的寄存器的名称:
eax:累加寄存器。通常用于算数运算,将结果保留在eax当中,当然也可以用于其他用途,比如一般把返回值通过eax传递出去。
ebx:基址寄存器 。有点类似于ebp,代表基础地址,加上偏移量可以得到新的地址
ecx:计数寄存器。用来存储循环的次数,同时也常用于保存this指针。每循环一次,ecx-1
edx:数据寄存器。通常配合eax来使用。例如上面的mov ebx,10 ;div ebx ;由于除数ebx是32位,所以被除数是64位的(高32:edx,低32:eax)
将数据从原地址转移到目的地址
使用REPE MOVSB(move string byte)实现字符串复制:
- MOV ESI, source_address ; 将源字符串的起始地址加载到ESI
- MOV EDI, destination_address ; 将目标字符串的起始地址加载到EDI
- MOV ECX, length ; 将字符串的长度加载到ECX
-
- REPE MOVSB ; 从源字符串复制数据到目标字符串,重复ECX次
使用REPE STOSB(store string byte)实现固定字符串填充:
- MOV EDI, destination_address ; 将目标字符串的起始地址加载到EDI
- MOV AL, value ; 将要填充的值加载到AL寄存器
- MOV ECX, length ; 将字符串的长度加载到ECX
-
- REPE STOSB ; 将值填充到目标字符串,重复ECX次
ebp与esp结合使用
因为esp经常变化,所以把esp保存在ebp这里
eip就是下一次要执行的指令的地址
其中最重要的就是ZF
直接寻址:读写变量
- int x = 10;
- 00BF1836 mov dword ptr [x],0Ah
寄存器寻址:指针解引用
- int* p = &x;
- 00EC1836 lea eax,[x]
- 00EC1839 mov dword ptr [p],eax
寄存器相对寻址:访问数组和结构体
访问数组:
- int arr[4] = { 1,2,3,4 };
- 005C1825 mov dword ptr [ebp-20h],1
- 005C182C mov dword ptr [ebp-1Ch],2
- 005C1833 mov dword ptr [ebp-18h],3
- 005C183A mov dword ptr [ebp-14h],4
访问结构体:
- Student st;
- st.age = 10;
- 001C48E5 mov dword ptr [ebp-0Ch],0Ah
- st.agender = 1;
- 001C48EC mov byte ptr [ebp-8],1
- st.score = 100;
- 001C48F0 mov eax,64h
- 001C48F5 mov word ptr [ebp-6],ax
Linux常用AT&T ,Windows使用intel格式
lea取地址指令
比如:lea dword ptr ds:[0xAAAAAAAA]
mov eax,10+3 (×) mov eax,13 (√)
TEST将A和B做逻辑与,和AND的区别:TEST 不改变A的值
比如:AND eax,ebx ->会把eax与ebx做与运算,并把结果赋值给eax
而TEST eax,ebx则不会赋值给eax,而只是会影响标志位
test eax,eax 》会影响ZF标志位
JZ 0x123
CMP eax,0 (eax-0也是只影响ZF标志位)
JZ 0x123
条件跳转:JNZ JA等等
无条件跳转:JMP
NEG:0-操作数
NOT:逻辑取反(真->反)
1)movzx和movsx指令介绍
凡是带mov的指令都是用于数据传输:
mov在使用的过程当中,他的两边的操作数的位数应该是一样的
而movzx/movsx要求右边宽度必须小于左边
要求:操作数1是寄存器,op2是寄存器或者内存,不能是立即数
movzx eax,byte ptr [0x123] 》
高位没有使用的部分全部用0填充
这就非常类似数据类型之间的转换,比如char -> int类型
在od里面双击寄存器可以直接修改它的值
movsx eax,cx当中eax的高位全部使用符号位(0/1)来填充,比如:
mov ecx,0x00000088
movsx eax,cx
》结果就是eax=0xffffff88
总结一下:movzx直接不管九九八十一,最高位全部填0,而movsx则根据cx的最高位,把eax的高位全部填上符号位(0/1)
2)Test指令介绍
1.Test用来测试一个位,例如寄存器:
test eax,100b;b后缀意为二进制
jnz 0x1234;如果eax右数第三个位为1,jnz将会跳转
我是这样想的,jnz跳转的条件是ZF=0,ZF=0意味着ZF(零标志)没被置位,即逻辑与结果为1。
2.Test的一个非常普遍的用法是用来测试一方寄存器是否为空:
test ecx, ecx
jz somewhere
如果ecx为零,设置ZF零标志为1,jz跳转。
int argc(argument count) ,char*argv[](argument varable)
函数调用栈:kernel32 -> mainCRTStartup -> main
CRT:C Run Time:C运行库
获取操作系统版本,在控制台程序是在命令行运行的
netstat -ano 可以加上一个命令行参数
环境变量,有变量名和值
为什么输入cmd可以进入shell执行程序呢?
》因为环境变量,执行程序会在当前环境变量当中去找/系统路径去找,如果找到了就会执行
环境变量%temp%就会打开他的值所指示的路径
把获取到的参数的数量保存在argc,把每一个参数的首地址保存在argv这个数组里面
setenvp把环境变量的地址分别保存
cinit初始化全局变量,静态变量,就比如类的构造函数执行之前他的静态成员就已经存在了
main实际push了三个参数,其中环境变量这个参数是不需要程序员来进行操作的,所以由运行库来给他填充进来就可以了
一个函数的返回值是放在eax当中的
最终main的底层是调用exit函数来进行退出的
如何使用反汇编工具识别main函数?
将exe拖入od,main在cinit后面
od如何安装插件?
ida使用:
debug版本有调试的信息,release发行版不包含调试信息,所以无法在VS里面调试,即使打了断点也直接就运行完了
start才是程序执行的入口
不用连接服务器获取调试信息
保存数据库就保存了一个MAIN.idb的数据库文件,如果我们自己修改了程序的内容,他就会保存在这个文件里面,下次直接打开这个就好,而不会破坏源文件,当然也可以直接保存到原文件
赞
踩
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。