-
二进制逆向工程师_Reverse 一款逆向工程工具
2020-12-28 16:56:34Reverse是一个用来解析二进制文件的逆向工程工具,而且它可以生成更具可读性的代码(类C语言)并带有彩色标识的语法,便于研究人员进行阅读代码。目前,其交互模式仍在做进一步开发。使用环境要求1、python 版本需要在...Reverse是一个用来解析二进制文件的逆向工程工具,而且它可以生成更具可读性的代码(类C语言)并带有彩色标识的语法,便于研究人员进行阅读代码。目前,其交互模式仍在做进一步开发。
使用环境要求1、python 版本需要在 3.4及以上版本;2、具备capstone反汇编框架,其能提供丰富的反汇编指令;3、具备python-pyelftools模块,用于解析ELF文件(ELF文件除了机器码外,还包含其它额外的信息,如段的加载地址,运行地址,重定位表,符号表等)以及DWARF调试信息,详细请点击链接:pyelftools;4、具备python-pefile模块,以用于解析PE文件(如exe、dll、vxd、sys和vdm等),详细请点击链接:PEfile;5、具备python-msgpack模块,用于序列化运算,详细请点击链接:msgpack;6、具备256色终端;可以通过运行requirements.sh检测是否符合所有的要求反编译功能因为二进制文件中包含了符号型的main,所以其中的-x main是可选的。具体使用如下,$ ./reverse.py tests/server.bin交互模式在此模式下有更多的命令可以使用(da,db等),当然我们也可以通过help查看更多的命令。TODO列表1、添加命令:setbe/setle rawbase(用于原文件格式);2、如果从shell获取的文件为raw文件,则进行加载。视觉模式在交互模式中,我们可以通过使用命令 v 来切换到视觉模式。但该模式需要ncurses动态库的支持。1、代码/功能的定义2、内联注释3、外部参照TODO列表1、当分析器修改代码时,自动进行重载;2、多行注释;3、创建数据/数组;4、符号重命名;5、堆栈变量;6、结构、枚举;7、提高分析器的性能。分析shellcode其中对于每一个Int 0×80,该工具都会尝试通过参数检测syscall函数$ ./reverse.py --raw x86 tests/shellcode.bin
文章来源及下载:
https://github.com/plasma-disass ... b/master/reverse.py
你可能喜欢
逆向工程师手中的利器-Sublime Text中的模糊匹配
安卓源码逆向
-
Stage 222222 —— 逆向工程拆除“二进制炸弹”程序
2018-10-26 21:45:32bomb.c:代码框架,bomb主程序即main函数,没有细节。 bomb: bomb的可执行程序。linux下的可执行程序,需要0或1个命令行参数。 二、bomb.c文件 L34’' FILE *infile; --------------- 变量:“从外部文件输入...简介
一、文件
bomb.c:代码框架,bomb主程序即main函数,没有细节。
bomb: bomb的可执行程序。linux下的可执行程序,需要0或1个命令行参数。二、bomb.c文件
L34’'
FILE *infile; --------------- 变量:“从外部文件输入到终端”L35’'
argc,argv 用命令行编译程序时有用。
主函数main中变量(int argc,char *argv[ ])的含义
argc: 整数,用来统计运行程序时送给main函数的命令行参数的个数
argv[ ]: 指针数组,用来存放指向字符串参数的指针,每一个元素指向一个参数
即:argv 的元素个数是argc,存放指向每一个参数的指针
argv[0] 指向程序运行的全路径名(包括路径 eg:“F:/VC/Ex1/Debug/Ex1.exe”)
argv[1] 指向在DOS命令行中执行程序名后的第一个字符串
argv[2] 指向执行程序名后的第二个字符串
…
argv[argc]为NULL。L43’'
大致看懂了。三、工具:objdump命令
objdump命令是Linux下的反汇编目标文件或者可执行文件的命令
实例:
1)显示文件头信息
objdump -f test
2)显示Section Header信息
objdump -h test
3)显示全部Header信息
objdump -x test
4)显示全部Header信息,并显示对应的十六进制文件代码
objdump -s test
5)输出目标文件的符号表
objdump -t obj
6)输出目标文件的所有段概述
objdump -h obj
7)反汇编test中的需要执行指令的那些section
objdump -d test
8)反汇编test中的所有section
objdump -D test
9)反汇编出源码(指定section)
objdump -Slj .text obj
10)对任意二进制文件进行反汇编
objdump -D -b binary -m i386 a.bin
11)将bomb的汇编代码写入asm.txt中:
objdump –d bomb > asm.txt
【更多:】
https://www.aliyun.com/jiaocheng/104464.html
https://blog.csdn.net/beyondioi/article/details/7796414
(哈哈哈哈哈。四、工具:gdb调试器
GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具,GDB主要可帮助工程师完成下面4个方面的功能:
启动程序,可以按照工程师自定义的要求随心所欲的运行程序。
让被调试的程序在工程师指定的断点处停住,断点可以是条件表达式。
当程序被停住时,可以检查此时程序中所发生的事,并追索上文。
动态地改变程序的执行环境。实例:
注1:需要调试的程序在编译的时候要加 -g 选项,程序才能进行调试
注2:以下所有命令都可以简写首字母,例:info break ==> i b 除特殊声明外#gdb program // 进入调试模式
#list file.c:fanction // 显示file.c文件中的fanction函数
#break file.c:fanction // 在file.c文件中的fanction函数处打一个断点
#break file.c:100 // 在file.c文件中的第100行打一个断点
#info break // 查看所有断点
#delete break num // 删除断点号为 num 的断点
#run // 开始运行程序
#bt // 显示程序的栈
#watch expr // 监视 expr 变量,(每次运行到变量处就会打印变量的值)(watch 不能简写)
#print expr // 打印处 expr 变量的值,(当前运行函数中的变量)
#c // 继续运行程序
#next // 单步运行
#quit // 退出调试
https://blog.csdn.net/yvhqbat/article/details/51393313
https://www.cnblogs.com/mingcaoyouxin/p/4225619.html拆炸弹
一、Phase1:字符串比较
read_line(); ------输入一个字符串,如果正确,这个phase的bomb就会被解除。操作 一.1
-都10月27号了kali可以拖拽文件了吗?
-不能
虚拟机中登录xxx,下载该压缩文件
从tar中提取bomb文件,在终端中打开,执行objdump -d命令,把汇编代码写入txt文件
操作 一.2
x86汇编程序基础(AT&T语法)
sub/add $0x8 , %rsp
堆栈指针rsp的地址减去8,程序入栈;加上8,程序出栈
movl $1, %eax
这是一条数据传送指令,CPU内部产生一个数字1, 然后传送到eax寄存器中。mov后边的l表示long,说明是32位的传送指令。CPU内部产生的数称为立即数,在汇编程序中立即数前面加"$",寄存器前面加"%",以便跟符号名区分开
【x86汇编的两种语法:intel语法和AT&T语法
mov %edx,%eax 这条指令如果用intel语法来写,就是 mov eax,edx,寄存器名不加 % 号,并且源操作数和目标操作数的位置互换。】start_loop: cmpl $0, %eax je loop_exit
循环。
比较eax的值是不是0,如果是0就要跳出循环。
cmpl指令将两个操作数相减,但计算结果并不保存,只是根据计算结果改变eflags寄存器中的标志位。
如果两个操作数相等,则计算结果为0,eflags中的ZF位置1。
je是一个条件跳转指令,它检查eflags中的ZF位,ZF位为1则发生跳转,ZF位为0则不跳转继续执行下一条指令。
je的e就表示equal。----------------------------------
几个通用寄存器:
%eax
%ebx
%ecx
%edx
%edi
%esi
另外几个用于特殊目的的寄存器:%ebp
%esp
%eip
%eflags----------------------------------
在调用一个函数之前,首先将所有参数以相反的声明顺序入栈,之后再调用call指令
call主要做两件事:1、它将下一条指令的地址入栈 2、将%eip设置为函数的初始地址以上phase1:
1)进入GDB调试
应该是-q进入GDB调试
2)在esp寄存器对应地址处 设置断点
3)run一下
4)查看字符串
关于x命令:https://www.cnblogs.com/liuyimin/p/7274184.html
5)拆弹
试了一次一直爆炸,可能是之前设置了一个断点?
shell命令退出了之后重新进来run就成功了!
终于知道咋拆弹了。。。一、Phase2:循环
根据上一炸弹的经验,
汇编太难了!!!
以下是一些分析过程 -
jsp显示二进制图片,一直显示空
2017-06-13 16:15:27具体情况是这样的, 数据库保存的是二进制图片,然后用逆向工程生成的po 图片转化为string类型了,请问怎么将这个图片显示到jsp页面,框架为ssh -
PREF, 可移植逆向工程框架.zip
2019-09-18 05:39:53PREF, 可移植逆向工程框架 PREF ( 可移植逆向工程框架) 旨在成为逆向工程的瑞士军刀。 基本思想是对运行Qt5的每个平台都有一个用于二进制和文件格式分析的软件。 插件功能:010编辑器脚本/模板兼容性。二进制文件 -
【iOS越狱过程】越狱工具做了什么事情?( iOS系统结构、常见的二进制文件类型)
2017-08-10 14:29:37前言iOS系统结构一、iOS系统结构访问iOS全系统文件是逆向工程的首要前提。 iOS 由OS X演化而来,而OS X则是基于unix操作系统的。 1)通过FHS标准了解类unix的文件目录结构,OS X则是在FHS基础上形成自己的hier(7)...文章目录
前言
I、什么是越狱
1.1 越狱后可以做哪些原来做不了的事情
- 安装任意签名的普通应用和系统应用
- 安装 SSH
- 添加命令行程序
- 添加 Daemon
- 任意添加、删除文件
- 获取任意 Mach Task
- 伪造 Entitlements
- 使内存页同时具有可写、可执行属性
1.2 破坏了 iOS 系统的哪些保护机制
- 破坏代码签名机制
- 破坏对内存页的保护机制(W+X)
- 破坏对磁盘分区(/dev/disk0s1s1)的保护
- 破坏 Rootless 保护机制,主要用于保护系统的完整性;
越狱中“狱”指 iOS 的保护机制,越狱是指破坏这些保护机制。
1.3 攻击的目标
- 内核、amfid、libmiss.dylib:三者配合实现了代码签名
- 内核:对内存页属性的保护完全在内核中实现
- 获取 root 权限:重新 mount 磁盘分区需要 root 权限
1.4 、 越狱工具做了什么事情?
- 修改 /etc/fstab,挂载系统盘为rw
- 安装一个软件包管理器(Installer.app),然后安装第三方软件
- 给系统打补丁(解锁,换壁纸,铃声)
为了做这些事情,我们需要:
- 修改系统文件
- 破坏 iOS 引导链
围绕着这两件事情,苹果跟安全研究员们展开了斗智斗勇。
II 、iOS系统结构
访问iOS全系统文件是逆向工程的首要前提。
iOS 由OS X演化而来,而OS X则是基于unix操作系统的。
1)通过FHS标准了解类unix的文件目录结构,OS X则是在FHS基础上形成自己的hier(7)框架
FHS:/boot 存放能使系统成功启动的所有文件 – iOS在此目录中为空
/dev 存放设备文件:块设备(硬盘)、字符设备(调制解调器)
/bin 提供用户级基础功能 :ps ls
/sbin 提供系统级基础功能:reboot 、netstat
/lib 存放系统库文件、内核模块、设备驱动-- iOS中此目录为空
/mnt 存放临时的文件系统挂载点- iOS中此目录为空
/var 存放一些经常更改的文件:日志、用户数据、临时文件,其中/var/mobile /var/root 分别存放mobile用户和root用户的文件
2.1、文件权限
说明文件的属主用户、属主组以及其他人能做什么。
SUID \SGID \sticky
III 、iOS二进制文件类型
iOS程序类型分为3类:Application, Dynamic Library,后台Daemon。 这三类文件的分工不同、其目录结构和文件权限也不同。
几个基本概念的理解:
3.1 bundle
一种按照某种标准结构来组织的目录,其中包含二进制文件以及运行所需的资源。
framework也是bundle,只是其中存放的是一个dylib,而不是可执行文件。相对来说一个app的地位比frame来得低,因为app只要依赖framework的接口来实现。3.2、app 目录结构
1)Info.plist:
使用Xcode自带的命令行工具plutil 进行查看devzkndeMacBook-Pro:WLqinbaowan devzkn$ plutil -p Info.plist
2)lproj 目录
存放各种本地化字符串。
3)系统app :/application 目录下存放的系统app和从Cydia 下载的app
它和storeApp的区别在于:
*目录结构(storeapp的数据目录在/var/mobile/containers/data;以mobile权限运行的系统app的数据目录在/var/mobile 下; 以root的权限运行的系统app的数据目录在/var/root)
*安装包格式以及权限: Cydia的app的安装包格式为deb ,属主用户和属主组一般都是root 和admin;而storeapp的属主用户和属主组一般都是mobile。
*沙盒:可以看作权限的一种表现形式,属于iOS的访问限制机制,授权文件也是沙盒的一部分。3.3、 Dynamic Library
只有当app需要dylib的时候,才会将其加载到内存,成为app进程的一部分;其本身并不是可执行文件,不能独立运行,只能为别的进程服务,成为进程的一部分,权限取决于寄生的app。
3.4、Daemon
iOS系统是有后台多任务的
1)守护进程,即windows的service。daemon 为后台运行而生,为用户提供各种守护。
2)iOS中的daemon 主要由一个可执行文件和一个plist文件组成。
这里的plist文件的作用是记录daemon的基本信息。3)iOS的根进程launchd ,它会在开机的时候检查/System/Library/LaunchDaemon 和/Library/LaunchDaemon 目录下的所有格式符合规定的plist文件,然后启动对应的Daemon
see also
-
rizin:类似UNIX的逆向工程框架和命令行工具集-源码
2021-02-05 23:44:12Rizin是便携式的,可用于分析二进制文件,反汇编代码,调试程序,作为取证工具,可打开磁盘文件的可编写脚本的命令行十六进制编辑器等等! 要了解有关Rizin的更多信息,您可能需要阅读。 如何安装 您可以在找到... -
cpp-r2类似unix的逆向工程框架和命令行工具
2019-08-16 02:29:34r2是从零开始重写radare,以便提供一组库和工具来处理二进制文件。 -
miasm:Python中的逆向工程框架-源码
2021-02-03 01:15:45Miasm旨在分析/修改/生成二进制程序。 以下是功能的不完整列表: 打开/修改/生成PE / ELF 32/64 LE / BE 组装/拆卸X86 / ARM / MIPS / SH4 / MSP430 使用中间语言表示汇编语义 使用JIT进行仿真(动态代码分析,... -
10以内逆向运算题_Z3在逆向中运用
2020-12-27 01:46:34CTF 领域来说,能够用约束求解器搞定的问题常见于密码题、二进制逆向、符号执行、Fuzzing 模糊测试等。此外,著名的二进制分析框架 angr 也内置了一个修改版的 Z3。官方使用文档:https://rise4...亲爱的,关注我吧
9/17
文章共计7370个词
预计阅读10分钟
来和我一起阅读吧
介绍
Z3 在工业应用中实际上常见于软件验证、程序分析等。然而由于功能实在强大,也被用于很多其他领域。CTF 领域来说,能够用约束求解器搞定的问题常见于密码题、二进制逆向、符号执行、Fuzzing 模糊测试等。此外,著名的二进制分析框架 angr 也内置了一个修改版的 Z3。
官方使用文档:https://rise4fun.com/z3/tutorialcontent/guidez3py 功能手册:https://z3prover.github.io/api/html/namespacez3py.htmlz3py 使用文档:https://ericpony.github.io/z3py-tutorial/guide-examples.htmz3 所使用的语法标准:http://smtlib.cs.uiowa.edu/papers/smt-lib-reference-v2.6-r2017-07-18.pdf
安装
这里安装的是 python 库版本,编译好的二进制版本在 Github 下载。https://github.com/Z3Prover/z3/releases
简单使用
from z3 import *x = Int('x') #设置整型变量xy = Int('y') #设置整型变量ysolve(x > 2, y < 10, x + 2*y == 7) #写入方程# [y = 0, x = 7]
进阶使用
设置变量
批量设置变量见补充
Int - 整数型
# 声明单个变量x = Int('x')# 声明多个变量y,z = Ints('y z')
|
运算需要初始化为Int
变量
Real - 实数型
# 声明单个变量x = Real('x')# 声明多个变量y,z = Reals('y z')
BitVec - 向量(位运算)
# 声明单个 16 位的变量x = BitVec('x',16)# 声明多个 16 位的变量y,z = BitVecs('y z',16)
只有 BitVec 变量可以进行异或
solver.add(BitVec('x',8)^BitVec('y',8)==5)
BitVec 变量值之间可进行
>
或<
或=
或>=
或<=
的比较BitVec('a',8)>=BitVec('b',8)BitVec('a',8)<=BitVec('b',8)BitVec('a',8)<=9BitVec('a',8)==9
BitVecVal 值之间不能进行
>
或<
比较,只能转换成 python 认识的类型才可以比较if BitVecVal(98,8)>BitVecVal(97,8)#错误,不是python类型if BitVecVal(98,8)==98:if BitVecVal(98,8).as_long()>97if BitVecVal(98,8).as_long()>BitVecVal(97,8).as_long()
变量设置的类型可能会影响到最后求解的结果。可以先 check 一下看看有没有解,然后再判断是否需要切换变量的类型。
Solver 对象
实际做题时,约束条件肯定不会想上面例子这么少,所以需要实例化一个
Solver()
对象,方便我们添加更多的约束条件。创建约束求解器:
solver = Solver()
添加约束条件
一行一个约束条件,这里的约束条件就是方程等式:
solver.add(x**2+y**2==74)solver.add(x**5-y==z)# [y = -7, x = 5, z = 3132]
z3 中不允许列表与列表之间添加
==
约束条件:判断是否有解
if solver.check() == sat: print("solver")else: print("no solver")
求解并输出
ans = solver.model()print(ans)
补充
限制结果为可见字符
通常如果是做题的话,解密出来很可能是 flag ,也就是 ascii 码,所以为了进一步约束范围可以给每一个变量都加上额外的一条约束,约束其结果只能在可见 ascii 码范围以内:
solver.add(x < 127)solver.add(x >= 32)
快速添加变量
添加 50 个 Int 变量 s :
s=[Int('s%d' % i) for i in range(50)]
添加 50 个 Real 变量 s :
s=[Real('s%d' % i) for i in range(50)]
添加 50 个 16 位 BitVec 变量 s :
s=[BitVec ('s%d' % i,16) for i in range(50)]
在约束条件中用下标索引使用:
solver.add(s[18] * s[8] == 5)solver.add(s[4] * s[11] == 0)
将结果按顺序打印出来:
这是使用列表管理变量的好处,如果不使用列表 print(answer) 输出的结果是无序的。
answer=solver.model()#print(answer)result="".join([str(answer[each]) for each in s])print(result)
练习例题
2020 羊城杯 login
题目前面还有一步逆向 pyinstaller 打包的 exe 文件,这里不赘述直接给出源码:
import sysinput1 = input('input something:')if len(input1) != 14: print('Wrong length!') sys.exit()code = []for i in range(13): code.append(ord(input1[i]) ^ ord(input1[i + 1]))code.append(ord(input1[13]))a1 = code[2]a2 = code[1]a3 = code[0]a4 = code[3]a5 = code[4]a6 = code[5]a7 = code[6]a8 = code[7]a9 = code[9]a10 = code[8]a11 = code[10]a12 = code[11]a13 = code[12]a14 = code[13]if ((((a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5) + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36) + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60) + a14 * 29 == 22748) & ((((a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25) + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66) + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39) + a14 * 17 == 7258) & ((((a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65) + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33) + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34) + a14 * 23 == 26190) & ((((a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59) + a5 * 49 + a6 * 81 + a7 * 25 + (a8 << 7) - a9 * 32) + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60) + a14 * 29 == 37136) & (((a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52) + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36) + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915) & ((((a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45) + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26) + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61) + a14 * 28 == 17298) & ((((a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42) + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47) + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44) + a14 * 65 == 19875) & (((a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85) + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30) + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784) & ((((a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85) + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36) + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64) + a14 * 27 == 9710) & (((((a1 * 67 - a2 * 68) + a3 * 68 - a4 * 51 - a5 * 43) + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38) + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52) + a14 * 31 == 13376) & ((((a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51) + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6) + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67) + a14 * 78 == 24065) & ((((a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5) + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35) + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61) + a14 * 20 == 27687) & (((a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25) + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92) + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250) & (((a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43) + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36) + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317): print('flag is GWHT{md5(your_input)}') print('Congratulations and have fun!')else: print('Sorry,plz try again...')import sysinput1 = input('input something:')if len(input1) != 14: print('Wrong length!') sys.exit()code = []for i in range(13): code.append(ord(input1[i]) ^ ord(input1[i + 1]))code.append(ord(input1[13]))a1 = code[2]a2 = code[1]a3 = code[0]a4 = code[3]a5 = code[4]a6 = code[5]a7 = code[6]a8 = code[7]a9 = code[9]a10 = code[8]a11 = code[10]a12 = code[11]a13 = code[12]a14 = code[13]if ((((a1 * 88 + a2 * 67 + a3 * 65 - a4 * 5) + a5 * 43 + a6 * 89 + a7 * 25 + a8 * 13 - a9 * 36) + a10 * 15 + a11 * 11 + a12 * 47 - a13 * 60) + a14 * 29 == 22748) & ((((a1 * 89 + a2 * 7 + a3 * 12 - a4 * 25) + a5 * 41 + a6 * 23 + a7 * 20 - a8 * 66) + a9 * 31 + a10 * 8 + a11 * 2 - a12 * 41 - a13 * 39) + a14 * 17 == 7258) & ((((a1 * 28 + a2 * 35 + a3 * 16 - a4 * 65) + a5 * 53 + a6 * 39 + a7 * 27 + a8 * 15 - a9 * 33) + a10 * 13 + a11 * 101 + a12 * 90 - a13 * 34) + a14 * 23 == 26190) & ((((a1 * 23 + a2 * 34 + a3 * 35 - a4 * 59) + a5 * 49 + a6 * 81 + a7 * 25 + (a8 << 7) - a9 * 32) + a10 * 75 + a11 * 81 + a12 * 47 - a13 * 60) + a14 * 29 == 37136) & (((a1 * 38 + a2 * 97 + a3 * 35 - a4 * 52) + a5 * 42 + a6 * 79 + a7 * 90 + a8 * 23 - a9 * 36) + a10 * 57 + a11 * 81 + a12 * 42 - a13 * 62 - a14 * 11 == 27915) & ((((a1 * 22 + a2 * 27 + a3 * 35 - a4 * 45) + a5 * 47 + a6 * 49 + a7 * 29 + a8 * 18 - a9 * 26) + a10 * 35 + a11 * 41 + a12 * 40 - a13 * 61) + a14 * 28 == 17298) & ((((a1 * 12 + a2 * 45 + a3 * 35 - a4 * 9 - a5 * 42) + a6 * 86 + a7 * 23 + a8 * 85 - a9 * 47) + a10 * 34 + a11 * 76 + a12 * 43 - a13 * 44) + a14 * 65 == 19875) & (((a1 * 79 + a2 * 62 + a3 * 35 - a4 * 85) + a5 * 33 + a6 * 79 + a7 * 86 + a8 * 14 - a9 * 30) + a10 * 25 + a11 * 11 + a12 * 57 - a13 * 50 - a14 * 9 == 22784) & ((((a1 * 8 + a2 * 6 + a3 * 64 - a4 * 85) + a5 * 73 + a6 * 29 + a7 * 2 + a8 * 23 - a9 * 36) + a10 * 5 + a11 * 2 + a12 * 47 - a13 * 64) + a14 * 27 == 9710) & (((((a1 * 67 - a2 * 68) + a3 * 68 - a4 * 51 - a5 * 43) + a6 * 81 + a7 * 22 - a8 * 12 - a9 * 38) + a10 * 75 + a11 * 41 + a12 * 27 - a13 * 52) + a14 * 31 == 13376) & ((((a1 * 85 + a2 * 63 + a3 * 5 - a4 * 51) + a5 * 44 + a6 * 36 + a7 * 28 + a8 * 15 - a9 * 6) + a10 * 45 + a11 * 31 + a12 * 7 - a13 * 67) + a14 * 78 == 24065) & ((((a1 * 47 + a2 * 64 + a3 * 66 - a4 * 5) + a5 * 43 + a6 * 112 + a7 * 25 + a8 * 13 - a9 * 35) + a10 * 95 + a11 * 21 + a12 * 43 - a13 * 61) + a14 * 20 == 27687) & (((a1 * 89 + a2 * 67 + a3 * 85 - a4 * 25) + a5 * 49 + a6 * 89 + a7 * 23 + a8 * 56 - a9 * 92) + a10 * 14 + a11 * 89 + a12 * 47 - a13 * 61 - a14 * 29 == 29250) & (((a1 * 95 + a2 * 34 + a3 * 62 - a4 * 9 - a5 * 43) + a6 * 83 + a7 * 25 + a8 * 12 - a9 * 36) + a10 * 16 + a11 * 51 + a12 * 47 - a13 * 60 - a14 * 24 == 15317): print('flag is GWHT{md5(your_input)}') print('Congratulations and have fun!')else: print('Sorry,plz try again...')
分析之后确定需要先求解出 a1~a14 的值,然后再经过一次异或获得 flag 。
这里我们手动添加多个变量,因为源码中的方式形式为 ax 。如果我们用列表管理变量,方程需要手动修改,消耗更多时间得不偿失。z3 脚本:
这里我们需要将有移位运算的那一条方程注释掉,因为 Int 没有这种运算方法。然后我们知道 a1~a14 是两两整数异或而来,所以加上约束大于等于 0 ,否则由于缺少一条方程解出来的值含有负数。
如果不想注释那条方程,完全使用全部方程,那么就将变量定义为:
BitVec('an', 16)
,那么就能够使用移位运算。然后就是还原异或加密:
a1 = 119a2 = 24a3 = 10a4 = 7a5 = 104a6 = 43a7 = 28a8 = 91a9 = 52a10 = 108a11 = 88a12 = 74a13 = 88#121a14 = 33code = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]code[0] = a3code[1] = a2code[2] = a1code[3] = a4code[4] = a5code[5] = a6code[6] = a7code[7] = a8code[9] = a9code[8] = a10code[10] = a11code[11] = a12code[12] = a13code[13] = a14flag = []flag.append(chr(code[13]))for i in list(range(13))[::-1]: code[i] = (code[i] ^ code[i + 1]) for i in code: print(chr(i),end='')#flag:U_G07_th3_k3y!
2020 CISCN z3
用 IDA 分析题目得知,程序将输入值经过运算后与 Dst 的密文对比,也就是知道解,求出未知数。
Dst 定义是 int 型(8 字节),将密文提取出来:
de = [0x4F17,0x9CF6,0x8DDB,0x8EA6,0x6929,0x9911,0x40A2,0x2F3E,0x62B6,0x4B82,0x486C,0x4002,0x52D7,0x2DEF,0x28DC,0x640D,0x528F,0x613B,0x4781,0x6B17,0x3237,0x2A93,0x615F,0x50BE,0x598E,0x4656,0x5B31,0x313A,0x3010,0x67FE,0x4D5F,0x58DB,0x3799,0x60A0,0x2750,0x3759,0x8953,0x7122,0x81F9,0x5524,0x8971,0x3A1D]
这里还是用手动申请变量,因为避免修改方程表达式。这道例题可以用 Int 也可以用 BitVec ,这里就用 BitVec
from z3 import *de = [0x4F17,0x9CF6,0x8DDB,0x8EA6,0x6929,0x9911,0x40A2,0x2F3E,0x62B6,0x4B82,0x486C,0x4002,0x52D7,0x2DEF,0x28DC,0x640D,0x528F,0x613B,0x4781,0x6B17,0x3237,0x2A93,0x615F,0x50BE,0x598E,0x4656,0x5B31,0x313A,0x3010,0x67FE,0x4D5F,0x58DB,0x3799,0x60A0,0x2750,0x3759,0x8953,0x7122,0x81F9,0x5524,0x8971,0x3A1D]v46=BitVec('v46',8)v47=BitVec('v47',8)v48=BitVec('v48',8)v49=BitVec('v49',8)v50=BitVec('v50',8)v51=BitVec('v51',8)v52=BitVec('v52',8)v53=BitVec('v53',8)v54=BitVec('v54',8)v55=BitVec('v55',8)v56=BitVec('v56',8)v57=BitVec('v57',8)v58=BitVec('v58',8)v59=BitVec('v59',8)v60=BitVec('v60',8)v61=BitVec('v61',8)v62=BitVec('v62',8)v63=BitVec('v63',8)v64=BitVec('v64',8)v65=BitVec('v65',8)v66=BitVec('v66',8)v67=BitVec('v67',8)v68=BitVec('v68',8)v69=BitVec('v69',8)v70=BitVec('v70',8)v71=BitVec('v71',8)v72=BitVec('v72',8)v73=BitVec('v73',8)v74=BitVec('v74',8)v75=BitVec('v75',8)v76=BitVec('v76',8)v77=BitVec('v77',8)v78=BitVec('v78',8)v79=BitVec('v79',8)v80=BitVec('v80',8)v81=BitVec('v81',8)v82=BitVec('v82',8)v83=BitVec('v83',8)v84=BitVec('v84',8)v85=BitVec('v85',8)v86=BitVec('v86',8)v87=BitVec('v87',8)v4=de[0]v5=de[1]v6=de[2]v7=de[3]v8=de[4]v9=de[5]v10=de[6]v11=de[7]v12=de[8]v13=de[9]v14=de[10]v15=de[11]v16=de[12]v17=de[13]v18=de[14]v19=de[15]v20=de[16]v21=de[17]v22=de[18]v23=de[19]v24=de[20]v25=de[21]v26=de[22]v27=de[23]v28=de[24]v29=de[25]v30=de[26]v31=de[27]v32=de[28]v33=de[29]v34=de[30]v35=de[31]v36=de[32]v37=de[33]v38=de[34]v39=de[35]v40=de[36]v41=de[37]v42=de[38]v43=de[39]v44=de[40]v45=de[41]s=Solver()s.add(v4 == 34 * v49 + 12 * v46 + 53 * v47 + 6 * v48 + 58 * v50 + 36 * v51 + v52)s.add(v5 == 27 * v50 + 73 * v49 + 12 * v48 + 83 * v46 + 85 * v47 + 96 * v51 + 52 * v52)s.add(v6 == 24 * v48 + 78 * v46 + 53 * v47 + 36 * v49 + 86 * v50 + 25 * v51 + 46 * v52)s.add(v7 == 78 * v47 + 39 * v46 + 52 * v48 + 9 * v49 + 62 * v50 + 37 * v51 + 84 * v52)s.add(v8 == 48 * v50 + 14 * v48 + 23 * v46 + 6 * v47 + 74 * v49 + 12 * v51 + 83 * v52)s.add(v9 == 15 * v51 + 48 * v50 + 92 * v48 + 85 * v47 + 27 * v46 + 42 * v49 + 72 * v52)s.add(v10 == 26 * v51 + 67 * v49 + 6 * v47 + 4 * v46 + 3 * v48 + 68 * v52)s.add(v11 == 34 * v56 + 12 * v53 + 53 * v54 + 6 * v55 + 58 * v57 + 36 * v58 + v59)s.add(v12 == 27 * v57 + 73 * v56 + 12 * v55 + 83 * v53 + 85 * v54 + 96 * v58 + 52 * v59)s.add(v13 == 24 * v55 + 78 * v53 + 53 * v54 + 36 * v56 + 86 * v57 + 25 * v58 + 46 * v59)s.add(v14 == 78 * v54 + 39 * v53 + 52 * v55 + 9 * v56 + 62 * v57 + 37 * v58 + 84 * v59)s.add(v15 == 48 * v57 + 14 * v55 + 23 * v53 + 6 * v54 + 74 * v56 + 12 * v58 + 83 * v59)s.add(v16 == 15 * v58 + 48 * v57 + 92 * v55 + 85 * v54 + 27 * v53 + 42 * v56 + 72 * v59)s.add(v17 == 26 * v58 + 67 * v56 + 6 * v54 + 4 * v53 + 3 * v55 + 68 * v59)s.add(v18 == 34 * v63 + 12 * v60 + 53 * v61 + 6 * v62 + 58 * v64 + 36 * v65 + v66)s.add(v19 == 27 * v64 + 73 * v63 + 12 * v62 + 83 * v60 + 85 * v61 + 96 * v65 + 52 * v66)s.add(v20 == 24 * v62 + 78 * v60 + 53 * v61 + 36 * v63 + 86 * v64 + 25 * v65 + 46 * v66)s.add(v21 == 78 * v61 + 39 * v60 + 52 * v62 + 9 * v63 + 62 * v64 + 37 * v65 + 84 * v66)s.add(v22 == 48 * v64 + 14 * v62 + 23 * v60 + 6 * v61 + 74 * v63 + 12 * v65 + 83 * v66)s.add(v23 == 15 * v65 + 48 * v64 + 92 * v62 + 85 * v61 + 27 * v60 + 42 * v63 + 72 * v66)s.add(v24 == 26 * v65 + 67 * v63 + 6 * v61 + 4 * v60 + 3 * v62 + 68 * v66)s.add(v25 == 34 * v70 + 12 * v67 + 53 * v68 + 6 * v69 + 58 * v71 + 36 * v72 + v73)s.add(v26 == 27 * v71 + 73 * v70 + 12 * v69 + 83 * v67 + 85 * v68 + 96 * v72 + 52 * v73)s.add(v27 == 24 * v69 + 78 * v67 + 53 * v68 + 36 * v70 + 86 * v71 + 25 * v72 + 46 * v73)s.add(v28 == 78 * v68 + 39 * v67 + 52 * v69 + 9 * v70 + 62 * v71 + 37 * v72 + 84 * v73)s.add(v29 == 48 * v71 + 14 * v69 + 23 * v67 + 6 * v68 + 74 * v70 + 12 * v72 + 83 * v73)s.add(v30 == 15 * v72 + 48 * v71 + 92 * v69 + 85 * v68 + 27 * v67 + 42 * v70 + 72 * v73)s.add(v31 == 26 * v72 + 67 * v70 + 6 * v68 + 4 * v67 + 3 * v69 + 68 * v73)s.add(v32 == 34 * v77 + 12 * v74 + 53 * v75 + 6 * v76 + 58 * v78 + 36 * v79 + v80)s.add(v33 == 27 * v78 + 73 * v77 + 12 * v76 + 83 * v74 + 85 * v75 + 96 * v79 + 52 * v80)s.add(v34 == 24 * v76 + 78 * v74 + 53 * v75 + 36 * v77 + 86 * v78 + 25 * v79 + 46 * v80)s.add(v35 == 78 * v75 + 39 * v74 + 52 * v76 + 9 * v77 + 62 * v78 + 37 * v79 + 84 * v80)s.add(v36 == 48 * v78 + 14 * v76 + 23 * v74 + 6 * v75 + 74 * v77 + 12 * v79 + 83 * v80)s.add(v37 == 15 * v79 + 48 * v78 + 92 * v76 + 85 * v75 + 27 * v74 + 42 * v77 + 72 * v80)s.add(v38 == 26 * v79 + 67 * v77 + 6 * v75 + 4 * v74 + 3 * v76 + 68 * v80)s.add(v39 == 34 * v84 + 12 * v81 + 53 * v82 + 6 * v83 + 58 * v85 + 36 * v86 + v87)s.add(v40 == 27 * v85 + 73 * v84 + 12 * v83 + 83 * v81 + 85 * v82 + 96 * v86 + 52 * v87)s.add(v41 == 24 * v83 + 78 * v81 + 53 * v82 + 36 * v84 + 86 * v85 + 25 * v86 + 46 * v87)s.add(v42 == 78 * v82 + 39 * v81 + 52 * v83 + 9 * v84 + 62 * v85 + 37 * v86 + 84 * v87)s.add(v43 == 48 * v85 + 14 * v83 + 23 * v81 + 6 * v82 + 74 * v84 + 12 * v86 + 83 * v87)s.add(v44 == 15 * v86 + 48 * v85 + 92 * v83 + 85 * v82 + 27 * v81 + 42 * v84 + 72 * v87)s.add(v45 == 26 * v86 + 67 * v84 + 6 * v82 + 4 * v81 + 3 * v83 + 68 * v87)print(s.check())flag=""if s.check() == sat: m = s.model() print(m)else: print("no answer")flag = ""for d in m.decls(): print("%s = %s" % (d.name(), m[d]))
极客大挑战 REConvolution
这条题目演示用批量申请堆方法
题目关键函数:
加密过程并不是前两题的方程了,而是循环异或,没有修改方程变量名的问题,所以我们可以用 for 循环申请变量。
数独
z3 还能处理数独问题,下面是官方 demo :
#!/usr/bin/env python# -*- coding: utf-8 -*-# @Author : MrSkYe# @Email : skye231@foxmail.comfrom z3 import *# 9x9整数变量矩阵X = [ [ Int("x_%s_%s" % (i+1, j+1)) for j in range(9) ] for i in range(9) ]# 每个单元格包含{1,…,9}中的值cells_c = [ And(1 <= X[i][j], X[i][j] <= 9) for i in range(9) for j in range(9) ]# 每行最多包含一个数字一次rows_c = [ Distinct(X[i]) for i in range(9) ]# 每列最多包含一个数字cols_c = [ Distinct([ X[i][j] for i in range(9) ]) for j in range(9) ]# 每个3x3正方形最多包含一个数字sq_c = [ Distinct([ X[3*i0 + i][3*j0 + j] for i in range(3) for j in range(3) ]) for i0 in range(3) for j0 in range(3) ]sudoku_c = cells_c + rows_c + cols_c + sq_c# 数独实例,我们用'0'表示空单元格instance = ((0,0,0,0,9,4,0,3,0), (0,0,0,5,1,0,0,0,7), (0,8,9,0,0,0,0,4,0), (0,0,0,0,0,0,2,0,8), (0,6,0,2,0,1,0,5,0), (1,0,2,0,0,0,0,0,0), (0,7,0,0,0,0,5,2,0), (9,0,0,0,6,5,0,0,0), (0,4,0,9,7,0,0,0,0))instance_c = [ If(instance[i][j] == 0, True, X[i][j] == instance[i][j]) for i in range(9) for j in range(9) ]s = Solver()s.add(sudoku_c + instance_c)if s.check() == sat: m = s.model() r = [ [ m.evaluate(X[i][j]) for j in range(9) ] for i in range(9) ] print_matrix(r)else: print("failed to solve")
参考文章
Z3 学习笔记 https://blog.csdn.net/qq_33438733/article/details/82011892)
z3 solver学习 http://3xp10it.cc/auxilary/2017/11/14/z3-solver%E5%AD%A6%E4%B9%A0/)
实验推荐
CTF-REVERSE练习之逆向初探 https://www.hetianlab.com/expc.do?ec=ECID172.19.104.182014111410002900001(本实验将通过具体的实例介绍Ollydbg/IDA Pro/PEiD等工具在逆向分析中的基本使用方法,并通过动态调试和静态分析两种方法来找到程序密码。)
戳
-
Radee2:类似UNIX的逆向工程框架和命令行工具集-源码
2021-01-31 19:26:28Radare项目起初是一个取证工具,是一个可编写脚本的命令行十六进制编辑器,能够打开磁盘文件,但后来增加了对二进制文件分析,反汇编代码,调试程序,附加到远程gdb服务器的支持... 了解更多 要了解更多信息,您... -
python z3库学习
2020-09-13 21:42:23Z3 在工业应用中实际上常见于软件验证、程序分析等。...领域来说,能够用约束求解器搞定的问题常见于密码题、二进制逆向、符号执行、Fuzzing 模糊测试等。此外,著名的二进制分析框架 angr 也内置了一个修改版的 Z3。 -
Android逆向之hook框架Frida:Frida的环境搭建及入门实战
2020-01-09 23:14:39Frida是一款基于python + javascript 的hook框架,可运行在android ios linux windows osx等各平台,主要使用动态二进制插桩技术;由于是基于脚本(javascript)的交互,因此相比xposed和substrace cydia更加便捷 官网... -
抖音数据采集教程,详解Hook框架frida,让你在逆向工作中效率成倍提升!
2021-02-08 21:25:04一、frida简介frida是一款基于python + java 的hook框架,可运行在androidioslinuxwinosx等各平台,主要使用动态二进制插桩技术。本期“安仔课堂”,ISEC实验室为大家详解frida,认真读完这篇文章会让你在逆向工作中... -
linux 逆向工具 radare2入门
2019-08-17 06:18:08radare2是一个开源的逆向工程和二进制分析框架,包括反汇编、分析数据、打补丁、比较数据、搜索、替换、虚拟化等等,同时具备超强的脚本加载能力,它可以运行在几乎所有主流的平台(GNU/Linux, .Wind... -
逆向angr学习
2020-10-06 20:20:41angr 是一个基于符号执行和模拟执行的二进制框架,可以用在很多的场景,比如逆向分析,漏洞挖掘等。 符号执行简单来说就是用符号来模拟程序执行,在我看来就相当于暴力破解,比如一个程序要求你进行一个复杂的运算,... -
180130 逆向-Angr入门(1)
2018-02-03 11:31:511625-5 王子昂 总结《2018年1月29日》 【连续第486天总结】 A. 蓝鲸whale-angr学习 B. Angr是一个多架构的...后来发展出了动态的符号执行,模拟执行该程序来工作Angr载入二进制文件后,会将其转换为中间语言(字节 -
3-RPC框架中的序列化
2020-04-12 00:11:07服务提供方可以从二进制数据中分割出不同的请求,根据请求类型和序列化类型,把二进制的数据逆向还原成请求对象,这个过程叫反序列化。 常用序列化 JDK原生序列化 序列化过程就是在读取对象数据的时候,不断加入... -
retools:retools:用于规范的逆向工程工具包-源码
2021-02-05 04:31:52旨在进行逆向工程任务的工具(反汇编程序,仿真器,二进制解析器)的集合,更具体地说,是与错误查找相关的工具。 当前,我们以ARMv7和Mach-O为目标,尽管将来计划更多的体系结构和格式。 retools在某种程度上是... -
网安知识图谱和框架推荐
2021-02-20 00:57:47文章目录初阶安全产品基础知识Web安全二进制安全密码学渗透测试代码审计软件的安全生命周期相关学习资源中阶网络安全二进制安全(中级)逆向技术(中级)大数据安全分析安全体系云安全相关学习资源高阶威胁情报漏洞... -
Z3求解器入门介绍(Python3)
2020-09-29 00:18:28一、简介 ...CTF 领域来说,能够用约束求解器搞定的问题常见于密码题、二进制逆向、符号执行、Fuzzing 模糊测试等。此外,著名的二进制分析框架 angr 也内置了一个修改版的 Z3。 二、快速入门 (一. -
安卓逆向——Frida安装和使用
2020-12-14 20:28:21Frida 安装和使用 简介 frida 是一款基于 python+javascript 的 hook 框架,可运行在 android、ios、linux、win等各个平台,主要使用的动态二进制插桩技术。 -
c语言反编译工具_Reverse 一款逆向工程工具
2020-11-18 16:10:39Reverse是一个用来解析二进制文件的逆向工程工具,而且它可以生成更具可读性的代码(类C语言)并带有彩色标识的语法,便于研究人员进行阅读代码。目前,其交互模式仍在做进一步开发。使用环境要求1、python 版本需要在... -
ctf-tools:一些用于安全研究工具的设置脚本-源码
2021-02-26 02:14:32二进制分析和逆向工程框架。 二元 目录 用于二进制文件的静态分析工具。 二元 图书馆 多体系结构反汇编框架。 二元 目录 检查二进制强化设置。 二元 目录 语义二进制代码分析框架。 二元 目录 交叉编译器和跨... -
逆向工具angr的快捷教程(2):符号执行实战
2016-06-12 16:24:30Angr是一个基于Python开发的二进制程序分析(Binary analysis)框架,可以用于开展动态符号执行(Symbolic Execution)和多种静态分析。本文将通过一个实例来讨论如何利用angr对程序进行基于Symbolic Execution的... -
逆向工具angr的快捷教程(1):安装、排雷、CFG范例
2016-03-18 19:47:08Angr是一个基于Python开发的二进制程序分析(Binary analysis)框架,可以用于开展动态符号执行(Symbolic Execution)和多种静态分析。作为系列文章的第一篇,本文将介绍安装angr的基本步骤,尤其是其中可能遇到的... -
详解Hook框架frida,为工作效率提速!
2019-08-08 14:31:16frida是一款基于python + java 的hook框架,可运行在androidioslinuxwinosx等各平台,主要使用动态二进制插桩技术。本期“安仔课堂”,ISEC实验室为大家详解frida,认真读完这篇文章会让你在逆向工作中效率成倍提升... -
使用LuaQEMU对BCM WiFi框架进行仿真和利用
2017-09-13 14:39:00本文讲的是使用LuaQEMU对BCM WiFi框架进行...例如,当设计一套逆向工程嵌入式解决方案,如蜂窝基带或自定义操作系统代码时,研究人员通常都需要借助某种二进制分析工具才能查看到运行时的协议栈、操作系统任务和内... -
跟着小生一起学习Android——IO框架
2020-11-06 15:18:16在绝大部分的时候我们后续写代码的执行是需要io的返回值的,这个时候我们就要用到回调。而今天小编就来带大家一起去...对于计算机来说,数据都是以二进制形式读出或写入。我们可以把文件想象为一个桶,通过管道将桶里的 -
Tutorial for Unicorn:Unicorn Engine 的开发和使用
2020-03-02 21:58:21作为一款著名的开源CPU 模拟框架,很多二进制逆向分析软件都用到了 Unicorn ,或者使用到了它的思想。比如 Radare2、Pwndbg、gdb-gef。Unicorn 在 QEMU 的基础上,增加了许多新特性,以及对 CPU 仿真更好的支持 1 ... -
摘自网络--- 反编译工具汇总
2019-07-27 05:46:091 angr:来自UCSB的Seclab的下一代... 2 BARF:多平台,开源二进制分析和逆向工程框架。 https://github.com/programa-stic/barf-project 3 binnavi:用于基于图形可视化的逆向工程的二进制分析IDE。 https://gith...
-
jadx反编译最新版下载
-
udig2.0中文语言包.rar
-
vue 第六天(条件判断)
-
基于SSM框架的超市管理系统
-
具有非对称T形DGS谐振器的双带阻滤波器
-
MySQL 函数、用户自定义函数
-
GUI规范漫谈
-
sql、xlsx格式的食谱大全.rar
-
安卓开发软件培训!不断提升自己创造溢价的能力,年薪超过80万!
-
14.易课寄在线购课系统部署-CentOS6环境搭建ZooKeeper集群
-
libFuzzer视频教程
-
springboot2.1.5.RELEASE构建项目时候报错Failure to find org.eclipse.m2e:lifecycle-mapping:pom:1.0.0
-
安卓手机系统开发!一篇文章教你搞定计算机网络面试,先收藏了
-
MHA 高可用 MySQL 架构与 Altas 读写分离
-
应急广播国标IP协议解析工具V1.24.1
-
股份:事件发生的地方广场-源码
-
MySQL 高可用工具 heartbeat 实战部署详解
-
牛牛量化策略交易
-
Archimedes_spiral.zip
-
MySQL 查询与高级查询(多表、嵌套和正则表达式)