一起学习 代码审计、安全开发、web攻防、逆向等。。。
私信联系
EIP是一个寄存器,用来存储CPU要读取指令的地址。
CPU通过EIP寄存器读取即将要执行的指令。
每次CPU执行完相应的汇编指令之后,EIP寄存器的值就会增加
windows 逆向 软件保护
IDA扩展
正向开发
.net 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下断点
https://x64dbg.com/
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:\python273\Scripts
No module named setuptools
setuptools-2.1.2.zip
pip-1.2.1.tar.gz
python .\setup.py install
网上的解决方法
查看python27.dll的位置
where python27.dll
查看注册表中 HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.7\InstallPath 的值是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
官网下载地址 https://ibotpeaches.github.io/Apktool/install/
作用:最大程度的还原apk中的manifest文件和资源文件 。
使用apktool工具反编译apk文件比直接解压同一个apk文件大;
还可以将反编译之后的apk重新打包成apk文件,
但需要重新签名,才能安装使用。
2、dex2jar
官方下载地址https://sourceforge.net/projects/dex2jar/
作用:
将APK直接解压后,目录下包含的一个classes.dex
文件反编译为classes-dex2jar.jar文件。
3、jd-gui.jar
作用:直接查看classes-dex2jar.jar文件。
网盘资源 完整工具压缩包下载
https://pan.baidu.com/s/1u9ZAIlnMMHJx9LWRO7OWcA
输入命令apktool b xxx
3、jd-gui
官网地址:https://www.jetbrains.com/decompiler/
是 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++;
}
以上三个例子都产生了一个从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.操作系统维护的,对于程序员是透明的。
函数调用 栈实现 原理
函数压栈 再出栈