一起学习 代码审计、安全开发、web攻防、逆向等。。。
私信联系
EIP是一个寄存器,用来存储CPU要读取指令的地址。
CPU通过EIP寄存器读取即将要执行的指令。
每次CPU执行完相应的汇编指令之后,EIP寄存器的值就会增加
windows 逆向 软件保护
IDA扩展
正向开发
C# 逆向
1.1.1目前计算机的常见指令集
● x86/x64
● ARM/ARM64(AArch64)
● 其他相对小众的架构(如MIPS)
汇编指令<-----C语言代码(简洁的运算符) 拆开写
CPU的运行方式:
取出下一条要执行的指令+执行当前的指令+输出结果
Intel AMD
常用汇编指令
运算指令:
加减乘除 与或非 异或
数据转移指令:
读取/写入不同长度的内存
写入寄存器
跳转指令:
无条件跳转/条件跳转
JMP 无条件跳转
jmp 入口点
栈操作指令:
入栈、出栈
push 0
把立即数 0 和 -1 压入堆栈。
汇编指令: JO、JNO、JB、JNB、JE、JNE、JBE、JA、JS、JNS、JP、JNP、JL、JNL、JNG、JG、JCXZ、JECXZ、JMP、JMPE
名称 功能 操作数 操作码 模数 寄存器1 寄存器2 或内存 位移量 立即数 符号方向 芯片型号 16位 32位JO 溢出跳转 短 $70 无 无 无 无 10 无 无 8086 无 无
JNO 不溢出跳转 短 $71 无 无 无 无 10 无 无 8086 无 无
JB 低于跳转 短 $72 无 无 无 无 10 无 无 8086 无 无
JNB 不低于跳转 短 $73 无 无 无 无 10 无 无 8086 无 无
JE 相等跳转 短 $74 无 无 无 无 10 无 无 8086 无 无
JNE 不等跳转 短 $75 无 无 无 无 10 无 无 8086 无 无
JBE 不高于跳转 短 $76 无 无 无 无 10 无 无 8086 无 无
JA 高于跳转 短 $77 无 无 无 无 10 无 无 8086 无 无
JS 负号跳转 短 $78 无 无 无 无 10 无 无 8086 无 无
JNS 非负跳转 短 $79 无 无 无 无 10 无 无 8086 无 无
JP 奇偶跳转 短 $7A 无 无 无 无 10 无 无 8086 无 无
JNP 非奇偶跳转 短 $7B 无 无 无 无 10 无 无 8086 无 无
JL 小于跳转 短 $7C 无 无 无 无 10 无 无 8086 无 无
JNL 不小于跳转 短 $7D 无 无 无 无 10 无 无 8086 无 无
JNG 不大于跳转 短 $7E 无 无 无 无 10 无 无 8086 无 无
JG 大于跳转 短 $7F 无 无 无 无 10 无 无 8086 无 无
JO 溢出跳转 近 $0F80 无 无 无 无 10 无 无 386 无 $66
JNO 不溢出跳转 近 $0F81 无 无 无 无 10 无 无 386 无 $66
JB 低于跳转 近 $0F82 无 无 无 无 10 无 无 386 无 $66
JNB 不低于跳转 近 $0F83 无 无 无 无 10 无 无 386 无 $66
JE 相等跳转 近 $0F84 无 无 无 无 10 无 无 386 无 $66
JNE 不等跳转 近 $0F85 无 无 无 无 10 无 无 386 无 $66
JBE 不高于跳转 近 $0F86 无 无 无 无 10 无 无 386 无 $66
JA 高于跳转 近 $0F87 无 无 无 无 10 无 无 386 无 $66
JS 负号跳转 近 $0F88 无 无 无 无 10 无 无 386 无 $66
JNS 非负跳转 近 $0F89 无 无 无 无 10 无 无 386 无 $66
JP 奇偶跳转 近 $0F8A 无 无 无 无 10 无 无 386 无 $66
JNP 非奇偶跳转 近 $0F8B 无 无 无 无 10 无 无 386 无 $66
JL 小于跳转 近 $0F8C 无 无 无 无 10 无 无 386 无 $66
JNL 不小于跳转 近 $0F8D 无 无 无 无 10 无 无 386 无 $66
JNG 不大于跳转 近 $0F8E 无 无 无 无 10 无 无 386 无 $66
JG 大于跳转 近 $0F8F 无 无 无 无 10 无 无 386 无 $66
JO 溢出跳转 近 $0F80 无 无 无 无 10 无 无 386 $66 无
JNO 不溢出跳转 近 $0F81 无 无 无 无 10 无 无 386 $66 无
JB 低于跳转 近 $0F82 无 无 无 无 10 无 无 386 $66 无
JNB 不低于跳转 近 $0F83 无 无 无 无 10 无 无 386 $66 无
JE 相等跳转 近 $0F84 无 无 无 无 10 无 无 386 $66 无
JNE 不等跳转 近 $0F85 无 无 无 无 10 无 无 386 $66 无
JBE 不高于跳转 近 $0F86 无 无 无 无 10 无 无 386 $66 无
JA 高于跳转 近 $0F87 无 无 无 无 10 无 无 386 $66 无
JS 负号跳转 近 $0F88 无 无 无 无 10 无 无 386 $66 无
JNS 非负跳转 近 $0F89 无 无 无 无 10 无 无 386 $66 无
JP 奇偶跳转 近 $0F8A 无 无 无 无 10 无 无 386 $66 无
JNP 非奇偶跳转 近 $0F8B 无 无 无 无 10 无 无 386 $66 无
JL 小于跳转 近 $0F8C 无 无 无 无 10 无 无 386 $66 无
JNL 不小于跳转 近 $0F8D 无 无 无 无 10 无 无 386 $66 无
JNG 不大于跳转 近 $0F8E 无 无 无 无 10 无 无 386 $66 无
JG 大于跳转 近 $0F8F 无 无 无 无 10 无 无 386 $66 无
JCXZ 计数一六零跳转 位移8 $E3 无 无 无 无 10 无 无 8086 无 $67
JECXZ 计数三二零跳转 位移8 $E3 无 无 无 无 10 无 无 386 $67 无
JMP 跳转 寄16 $FF 11 100 3 无 无 无 无 8086 无 $66
JMP 跳转 寄32 $FF 11 100 3 无 无 无 无 386 $66 无
JMP 跳转 16[寄16] $FF 00 100 5 无 无 无 无 8086 无 $6766
JMP 跳转 32[寄16] $FF 00 100 5 无 无 无 无 386 $66 $67
JMP 跳转 16[寄32] $FF 00 100 5 无 无 无 无 386 $67 $66
JMP 跳转 32[寄32] $FF 00 100 5 无 无 无 无 386 $6766 无
JMP 跳转 16[寄16+位移8] $FF 01 100 5 9 无 无 无 8086 无 $6766
JMP 跳转 32[寄16+位移8] $FF 01 100 5 9 无 无 无 386 $66 $67
JMP 跳转 16[寄32+位移8] $FF 01 100 5 9 无 无 无 386 $67 $66
JMP 跳转 32[寄32+位移8] $FF 01 100 5 9 无 无 无 386 $6766 无
JMP 跳转 16[寄16+位移16] $FF 10 100 5 9 无 无 无 8086 无 $6766
JMP 跳转 32[寄16+位移16] $FF 10 100 5 9 无 无 无 386 $66 $67
JMP 跳转 16[寄32+位移32] $FF 10 100 5 9 无 无 无 386 $67 $66
JMP 跳转 32[寄32+位移32] $FF 10 100 5 9 无 无 无 386 $6766 无
JMP 跳转 近16[寄16] $FF 00 100 5 无 无 无 无 8086 无 $6766
JMP 跳转 近32[寄16] $FF 00 100 5 无 无 无 无 386 $66 $67
JMP 跳转 近16[寄32] $FF 00 100 5 无 无 无 无 386 $67 $66
JMP 跳转 近32[寄32] $FF 00 100 5 无 无 无 无 386 $6766 无
JMP 跳转 近16[寄16+位移8] $FF 01 100 5 9 无 无 无 8086 无 $6766
JMP 跳转 近32[寄16+位移8] $FF 01 100 5 9 无 无 无 386 $66 $67
JMP 跳转 近16[寄32+位移8] $FF 01 100 5 9 无 无 无 386 $67 $66
JMP 跳转 近32[寄32+位移8] $FF 01 100 5 9 无 无 无 386 $6766 无
JMP 跳转 近16[寄16+位移16] $FF 10 100 5 9 无 无 无 8086 无 $6766
JMP 跳转 近32[寄16+位移16] $FF 10 100 5 9 无 无 无 386 $66 $67
JMP 跳转 近16[寄32+位移32] $FF 10 100 5 9 无 无 无 386 $67 $66
JMP 跳转 近32[寄32+位移32] $FF 10 100 5 9 无 无 无 386 $6766 无
JMP 跳转 远16[寄16] $FF 00 101 5 无 无 无 无 8086 无 $6766
JMP 跳转 远32[寄16] $FF 00 101 5 无 无 无 无 386 $66 $67
JMP 跳转 远16[寄32] $FF 00 101 5 无 无 无 无 386 $67 $66
JMP 跳转 远32[寄32] $FF 00 101 5 无 无 无 无 386 $6766 无
JMP 跳转 远16[寄16+位移8] $FF 01 101 5 9 无 无 无 8086 无 $6766
JMP 跳转 远32[寄16+位移8] $FF 01 101 5 9 无 无 无 386 $66 $67
JMP 跳转 远16[寄32+位移8] $FF 01 101 5 9 无 无 无 386 $67 $66
JMP 跳转 远32[寄32+位移8] $FF 01 101 5 9 无 无 无 386 $6766 无
JMP 跳转 远16[寄16+位移16] $FF 10 101 5 9 无 无 无 8086 无 $6766
JMP 跳转 远32[寄16+位移16] $FF 10 101 5 9 无 无 无 386 $66 $67
JMP 跳转 远16[寄32+位移32] $FF 10 101 5 9 无 无 无 386 $67 $66
JMP 跳转 远32[寄32+位移32] $FF 10 101 5 9 无 无 无 386 $6766 无
JMP 跳转 短 $EB 无 无 无 无 10 无 无 8086 无 无
JMP 跳转 位移16 $E9 无 无 无 无 10 无 无 8086 无 $66
JMP 跳转 位移32 $E9 无 无 无 无 10 无 无 386 $66 无
JMP 跳转 近 $E9 无 无 无 无 10 无 无 8086 无 $66
JMP 跳转 近 $E9 无 无 无 无 10 无 无 386 $66 无
JMP 跳转 远(数段址:)偏移16 $EA 无 无 无 无 10 无 无 8086 无 $66
JMP 跳转 远(数段址:)偏移32 $EA 无 无 无 无 10 无 无 386 $66 无
JMP 跳转 数段址:偏移16 $EA 无 无 无 无 12 无 无 8086 无 $66
JMP 跳转 数段址:偏移32 $EA 无 无 无 无 12 无 无 386 $66 无
JMPE 跳转扩展 寄16 $0F00 11 110 3 无 无 无 无 IA64 无 $66
JMPE 跳转扩展 寄32 $0F00 11 110 3 无 无 无 无 IA64 $66 无
JMPE 跳转扩展 16[寄16] $0F00 00 110 5 无 无 无 无 IA64 无 $66
JMPE 跳转扩展 32[寄16] $0F00 00 110 5 无 无 无 无 IA64 $66 无
JMPE 跳转扩展 16[寄32] $0F00 00 110 5 无 无 无 无 IA64 无 $66
JMPE 跳转扩展 32[寄32] $0F00 00 110 5 无 无 无 无 IA64 $66 无
JMPE 跳转扩展 16[寄16+位移8] $0F00 01 110 5 9 无 无 无 IA64 无 $66
JMPE 跳转扩展 32[寄16+位移8] $0F00 01 110 5 9 无 无 无 IA64 $66 无
JMPE 跳转扩展 16[寄32+位移8] $0F00 01 110 5 9 无 无 无 IA64 无 $66
JMPE 跳转扩展 32[寄32+位移8] $0F00 01 110 5 9 无 无 无 IA64 $66 无
JMPE 跳转扩展 16[寄16+位移16] $0F00 10 110 5 9 无 无 无 IA64 无 $66
JMPE 跳转扩展 32[寄16+位移16] $0F00 10 110 5 9 无 无 无 IA64 $66 无
JMPE 跳转扩展 16[寄32+位移32] $0F00 10 110 5 9 无 无 无 IA64 无 $66
JMPE 跳转扩展 32[寄32+位移32] $0F00 10 110 5 9 无 无 无 IA64 $66 无
JMPE 跳转扩展 位移16 $0FB8 无 无 无 无 10 无 无 IA64 无 $66
JMPE 跳转扩展 位移32 $0FB8 无 无 无 无 10 无 无 IA64 $66 无
支持使用一个寄存器的不同长度的值
只包含通用寄存器
RIP-指向下一条执行的命令
RSP-指向栈顶
RBP-指向栈帧中心(稍后解释栈和栈帧)
SP与x86中esp相当
R11与x86中ebp相当
LR是link register的简称,用于保存调用者的地址方便返回
PC在ARM中指向两条指令之后(由于三级流水线的历史遗留问题)
一般指令执行时都会将返回的结果存储于寄存器中。
但寄存器数量很有限,于是我们需要经常的将它存入内存。
然后聪明的先人就创造了栈。
● 010 Editor
模板功能, Templates→Template Repository即可看到各种已有模板
Template的语法类似于C结构体,可自己直接编写并加载,且支持基本的C语法如循环、判断等
解析的结果会以列表的形式显示在Variables界面中
快速解析已知格式文件
二进制复制与粘贴支持
不同格式输入
编码支持较差
● EditPlus
编码支持相当好
二进制编辑能力较弱
UltraEdit、WinHex
● PE:CFF Explorer
● MachO:MachO View
● ELF:直接IDA
● Shellcode Helper
1.3.4 反汇编器 非侵入式
● IDA:Interactive Disassembler
反汇编界面使用
不同界面说明
设置Data、Code(d、c)
查看Cross Reference(x)
查看String List(Shift-F12)
F5反编译器使用
设置Type (变量、函数)(Y)
设置Calling Convention (Y)
1.3.5 调试器
命令行调试器
● gdb
支持平台全面,有强大社区支持
支持配合gdbserver进行远程调试
社区维护大量插件
● WinDBG
仅支持Win平台
强于解析结构体,尤善于Windows内部结构的解析与显示
同样支持插件,但数量相对较少
支持Win内核调试
支持Win远程调试
图形界面调试器
● OllyDBG
Win下老牌调试器
有强大的社区,
支持脚本和插件扩展
仅支持32位
快捷键:F8步过 F7步进 F4运行至 F9运行 F2下断点
/
pluginsdk 插件开发包
release x64dbg的主程序目录
支持32和64位
仍在活跃开发中
插件相对较少
快捷键与OD相同
逆向反汇编修改神器,免费开源x64/x32位动态调试器,适用Windows的专业程序调试器,软件原生支持中文界面和插件,其界面及操作方法与OllyDbg调试工具类似,
支持类似C的表达式解析器、
全功能的DLL和EXE文件调试、IDA般的侧边栏与跳跃箭头、动态识别模块和串、快反汇编、可调试的脚本语言自动化等多项实用分析功能。
DBG 是调试器的调试部分,它处理调试技术(使用的 TitanEngine),并为GUI提供数据。
GUI 是调试器的图形部分,它建立在Qt上,并提供用户交互界面。
Bridge 是DBG和GUI部分的通信库,它可以用于在新建功能上工作,而无需更新代码的其它部分。
修订了啥
简体中文修订说明:王苏 2020.06.10
附加进程 ALT + A
cpu 反汇编窗口
F2 断断点 同OD
F8 步过
空格键 编辑 汇编
python-2.7.3.msi
D:python273
D:python273Scripts
No module named setuptools
setuptools-2.1.2.zippip-1.2.python .setup.py install
网上的解决方法
查看python27.dll的位置
where python27.dll
查看注册表中 HKEY_LOCAL_MACHINESOFTWAREPythonPythonCore2.7InstallPath 的值是python2.7的安装路径
尽量用win7系统
我是重新安装了python环境和IDA pro
快捷键与OD相同
支持多种后端:
IDA内置调试器
gdb、windbg
支持远程调试
兼容gdbserver
官方支持ARM/ARM64、x86/x64指令集远程调试
支持Android iOS Win Linux
支持配合Hex-Rays调试
单步、查看运行过程中变量的值
步进
单步执行,遇到call调用时会跟进而不是跳过去
步过
单步执行,遇到call调用时会和别的指令一样跳过去
运行至指定位置
相当于临时下断点,碰到循环时可以方便的跳过去
运行
直接跑起来,而不是一条一条指令执行
F5 查看伪代码
1、apktool.bat;apktool.jar
官网下载地址 /
作用:最大程度的还原apk中的manifest文件和资源文件 。
使用apktool工具反编译apk文件比直接解压同一个apk文件大;
还可以将反编译之后的apk重新打包成apk文件,
但需要重新签名,才能安装使用。
2、dex2jar
官方下载地址/
作用:
将APK直接解压后,目录下包含的一个classes.dex
文件反编译为classes-dex2jar.jar文件。
3、jd-gui.jar
作用:直接查看classes-dex2jar.jar文件。
网盘资源 完整工具压缩包下载
输入命令apktool b xxx
3、jd-gui
官网地址:/
是 JetBrains 开发的一款.Net反编译工具,是.Net工具套件中的一个
dotPeek 是一款基于 ReSharper 捆绑反编译器的免费
独立工具。
它可以可靠地将任意 .NET 程序集反编译为对等的 C# 或 IL 代码。
支持包括库 (.dll)、可执行文件 (.exe) 和 Windows 元数据文件 (.winmd) 在内的多种格式。
将反编译代码导出至 Visual Studio 项目
在反编译完程序集后,您可以将其另存为 Visual Studio 项目 (.csproj)。
如果您需要从旧程序集恢复丢失的源代码,此举可以为您节省大量的时间。
下载源代码并调试第三方代码
dotPeek 可以根据 PDB 文件识别本地源代码,或者从 Microsoft Reference Source Center 或 SymbolSource 等源服务器中获取源代码。
dotPeek 还可以作为符号服务器运行,
为 Visual Studio 调试器提供调试程序集代码所需的信息。
smail汇编 - java代码 逆向
ARM汇编 指令 (二进制文件 - 普通代码语言) IDA
汇编 寄存器
hook插件 开发
NDK工具
修改so dll 等 关键文件
APK 防护 HOOK过掉
改函数 返回值 该参数 打印参数
— /data/app-lib/包名/lib
找so 几百kb 就不是 c++(几个MB)(有cocos2d引擎在里面)
res 资源 配置 图片 动画 xml 音频
org linux
META-INF 签名文件夹
assets 资源
RISC(精简指令集计算机)Reduced Instruction Set Computer
CISC(复杂指令集计算机)Complex Instruction Set Computer
当前CPU的两种架构。
区别在于不同的CPU设计理念和方法。
早期的CPU全部是CISC架构,
它的设计目的是要用最少的机器语言指令来完成所需的计算任务。
比如对于乘法运算,
在CISC架构的CPU上,
您可能需要这样一条指令:MUL ADDRA, ADDRB
就可以将ADDRA和ADDRB中的数相乘并将结果储存在ADDRA中。将ADDRA, ADDRB中的数据读入寄存器,相乘和将结果写回内存的操作
全部依赖于CPU中设计的逻辑来实现。
这种架构会增加CPU结构的复杂性和对CPU工艺的要求,但对于编译器的开发十分有利。
比如上面的例子,C程序中的a*=b就可以直接编译为一条乘法指令。
今天只有Intel及其兼容CPU还在使用CISC架构。
RISC架构要求软件来指定各个操作步骤。
上面的例子如果要在RISC架构上实现,
将ADDRA, ADDRB中的数据读入寄存器,相乘和将结果写回内存的操作
都必须由软件来实现,比如:
MOV A, ADDRA;
MOV B, ADDRB; MUL A, B; STR ADDRA, A。
这种架构可以降低CPU的复杂性
以及允许在同样的工艺水平下生产出功能更强大的CPU,
但对于编译器的设计有更高的要求。
计算机的组成结构
数字电路基础
编程的基础
实现 一个RISC指令集的CPU
要自己为这个CPU设计指令并且编码
英特尔的 叫特德·霍夫(Ted Hoff)的工程师
设计和生产专用集成电路芯片
用于实现桌面计算器
各实现一种特定的功能
想法:
为什么不能用一块通用的芯片加上程序来实现几块芯片的功能呢?
当需要某种功能时,只需要把实现该功能的一段程序代码(称为子程序)加载到通用芯片上,其功能与专用芯片会完全一样。
计算器的新的体系结构图,
其中包含4块芯片:
一块通用处理器芯片,实现所有的计算和控制功能;
一块可读写内存(RAM)芯片,用来存放数据;
一块只读内存(ROM)芯片,用来存放程序;
一块输入输出芯片,实现键入数据和操作命令、打印结果等等功能
例1-1:
mov eax,0
repeat:inc eax
jmp repeat
例1-2:
int main()
{
unsigned int i = 0;
while(1)
i++;
}
例1-3:
以上三个例子都产生了一个从0不断增加的序列
而且前两个例子会一直加到溢出又从0开始
(这个取决于计算机的字长也就是多少位的CPU,
eax是32位寄存器所以必然是加到4294967295然后回0,
而后面那个c程序则看不同编译器和不同平台不一样)
后面那个例子则看你用的是什么样的加法器和多少个D触发器
假设要一个递减的序列
例2-1:
mov eax,0
repeat:dec eax
jmp repeat
例2-2:
int main()
{
unsigned int i = 0;
while(1)
i--;
}
例2-3:
上面
(例1-3)中是个加法器,
减法器(例2-3)!
例3:
使用了一个加法器一个减法器,没比上面的电路省
(加上一个负数的补码确实就是减去一个数)
多了一组多路器,少了一组D触发器
而sel信号就是用来选择的(0是递增,1是递减)。
//缺省对堆栈操作的寄存器 ESP 和 EBP 扩展基址指针寄存器(extended base pointer)
一般使用 EBP 来存取堆栈
调用中有两个参数
在 push 第一个参数前的堆栈指针 ESP 为 X,那么压入两个参数后的 ESP 为 X-8
计算机转移到调用的 子程序 call指令
//把返回地址压入堆栈 ESP 为 X-C 这时已经在子程序中了
可以开始使用 EBP 来存取参数
为了在返回时恢复 EBP 的值,我们还是再需要一句 push ebp
来先保存 EBP 的值,这时 ESP 为 X-10
再执行一句 mov ebp,esp
实际上这时候 [ebp + 8] 就是参数1,[ebp + c]就是参数2
//用于将一个数据从源地址传送到目标地址
(寄存器间的数据传送本质上也是一样的)。
其特点是不破坏源地址单元的内容
-1=FFFFFFFF
1=00000000
显示调用 下断点
FPU :(Float Point Unit,浮点运算单元)
状态寄存器
控制寄存器
放在WINDOWS目录下SYSTEM32文件夹里的一个DLL文件
esp定律 向 堆栈 中压入下一行程序的地址
逆向破解 暴力破解 绕过注册机制 追踪注册码
混淆器 壳 侦壳程序进行识别 伪装技术来混淆侦壳程序
压缩壳 程序进行体积缩小化处理
保护壳混淆或加密代码防止他人进行逆向程序、破解程序
EP段
AX 8086CPU微处理器中8个 通用寄存器之一
按16位使用时主要用于存放数据 临时用于存放地址
每一个都可以拆开成为两个独立的8位寄存器使用
分别用高字节和低字节表示
AH,AL等,按8位使用时只能用于存放数据
系统 地址 寄存器
调用前 ESP存储的是栈顶地址,也是栈底地址
三个指针 系统中栈 栈的数据结构 后进先处
1.栈是用来存储临时变量,函数传递的中间结果。
2.操作系统维护的,对于程序员是透明的。
函数调用 栈实现 原理
函数压栈 再出栈
本文发布于:2024-02-04 08:08:04,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170702714553802.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |