跳到主要内容

微信数据库破解

· 阅读需 33 分钟

项目展示

获取所有微信好友信息

picture 86

derived from hacked db: Contact/wccontact_new2.db

导出与微信好友的聊天记录

picture 87

derived from hacked dbs: Message/msg_*.db

监控实时聊天

picture 88

derived from real-time terminal

其他

动机背景

一切,都要从南川的计算机小群里 Shining LavenderLe Penseur 同学聊到“爱”这个高深的话题,继而聊到了“soulmate”,而我最近恰好看了《Intouchables》:

picture 66

所以和 Le Penseur 同学一下探讨到了凌晨……

上半场刚结束,基友群表示对这个话题也很感兴趣,遂我们又来回肝完了半个通宵。

下半场也结束后,我发现我很想把这些闪烁智慧与思考、彭拜着荷尔蒙与伤感的青春文字记录整理下来,但是无奈微信未能提供满足我这种需求的便利。

自然而然地,作为一名合格的程序员,兵来将挡水来土掩,我们又上场了……

历时一天,彻底拿下!

技术概览

思路还是比较通用的。

github search until wechat-decipher-macos

首先,第一步,去 github 搜索是否已经有破解微信聊天记录相关的开源仓库,结果,应有尽有,一应尽全 - Search · wechat history

picture 68

可以看到,至少在这一页前几个仓库中,安卓、iOS、mac 都有,windows 倒不确定。

我目前手机用的是安卓,电脑是 mac,但我用电脑比较多,所以我倾向于选择 mac 的方案,于是第一选择这个仓库 - nalzok/wechat-decipher-macos: Scripts to extract chat history from WeChat on macOS

不过这个仓库,起手难度可不低,仓库介绍十分简练,但真的是字字珠玑!

picture 70

对于用户(我)来说,这个仓库的主要功能在前三者,一定要仔细理解,每个字都很宝贵:

macos/eavesdropper.d

macos/eavesdropper.d是用于实时、高速打印微信与数据库之间的信息流的,具体什么样子呢?我运行一下给你们看一下。

picture 72

picture 71

可以看到,我在微信中发送的聊天内容,会被明文显示到控制台中,并且在不同的时间点被打印了两遍。

当然,这不是微信自己打印的,是我们(他的)脚本打的,并且把结构体都打出来了,这个结构体和最终存到数据库里的数据结构基本是差不多的。

比如这是我们数据库中的样子:

picture 73

但是,由于这是用于实时的,也就是过去的就没有了,所以不满足我的需求,因为我也没有深究这个脚本(比如为啥打印两次,强迫症的我接受不了,至少接受不了这么大面积的冗余)。

macos/dbcracker.d

其实我一开始没有看懂macos/dbcracker.d这个脚本用来干啥的,并且以为第四个脚本devel/xlogger.d才是我的目标,但显然,这个想法错的离谱。

cracker是“撕裂者”的意思,dbcracker就是“数据库撕裂者”,听起来还是很可怕吧!

事实上,它真地很可怕 !

而且,我后续所有的工作都是基于它完成的!

但它的操作,就没有第一个脚本 macos/eavesdropper.d那么容易上手了。

首先,注意它的描述:Since it can only capture secrets when WeChat.app opens these files, you need to perform a login while the script is running.,也就是你需要先运行脚本,然后重启微信,才能看到效果。

不过经过我的测试,正确流程是这样的,先退出微信登录(或者直接杀掉,然后启动),保留微信在登录界面(但还没有登录),接着运行脚本(否则会报基于没有进程导致的后续错误),然后扫码登录成功,这个时候就能飞速地看到命令行有很多数据在跑了,其实就是微信所有(大部分)的数据库的文件位置、秘钥、参数等。

值得注意的是,秘钥是用来干啥的。

一般用惯了mysql或者mongodb之类数据库的人(别”人“了,就是我),其实根本不知道这个秘钥(既然不是用户密码)用来干嘛,这才是本项目的第一大难点。

这个时候,细心地读下一句:Simply copy & paste the script output to invoke SQLCipher and supply the respective PRAGMAs.,翻译过来就是,把命令行的输简单地出复制粘贴,已启动SQLCipher并分别用于PRAGMA

很绕,也一脸懵逼是不,是就对了!

答案在那个超链接 sqlcipher/sqlcipher: SQLCipher is a standalone fork of SQLite that adds 256 bit AES encryption of database files and other security features. 上,所以你为了使用 A 项目,不得不去先啃 B 项目了。

但实际上,sqlcipher更难看懂,尤其是一上来就教你怎么编译,非常硬核(然而还有坑):

picture 74

编就编吧,还有依赖,看看:

You must define SQLITE_HAS_CODEC and either SQLITE_TEMP_STORE=2 or SQLITE_TEMP_STORE=3
You will need to link against a support cryptographic provider (OpenSSL, LibTomCrypt, CommonCrypto/Security.framework, or NSS)

让我们定义变量(一开始以为是环境变量,后来发现是头文件内部变量),还要链接一个加密库……

一脸懵逼吧。

我一开始也看不懂,然后瞎编了一下。

结果果然报错了……

接着就一顿乱搜,然后找到了对本项目影响最大的一篇博客:- (25 条消息) Mac 终端使用 Sqlcipher 加解密基础过程详解_Martin.Mu `s Special Column-CSDN 博客_mac sqlcipher

这个事实充分证明,只要你想干的事情足够大众,你就能找到非常不错的伙伴,或者说,前辈。

该文章基本包括了sqlcipher如何编译、安装的问题,以及(非常前瞻性地)解决了里面的一些坑,节省了我可期的很多时间。

picture 75

基于这篇文章,我熟悉了 sqlcipher 的使用,意识到 sqlciphersqlite3 的加密版,每个数据库可以独立地用一个KEY加密,然后还可以解密,并导出无加密版本的sqlite3

所以在那之后,我才真正地意识到 macos/dbcracker.d 是用来干什么的:

  1. 用该脚本,通过监听微信启动时打开数据库的动作,暴露微信所有数据库的文件位置与秘钥信息
  2. 接下来数据库秘钥都有了,做啥就取决于自己了,比如说把所有好友的信息都导出成一张 excel 表这种

以下是该脚本监控到的数据库,与微信实际数据库对比。

Almost all (especially the core ones, such as Contacts/Messages relative) the tables are tracked.

picture 54

Hence, it's pretty good for our further work.

Also, the db-list.txt is derived from:

picture 55

And the db-list-tracked.txt is derived from:

picture 56

The track.log is derived from:

picture 57

pcbakchat/gather.d

这个脚本其实也挺有用的,它能捕获备份时的数据流。

在说这个之前,我们有必要明确一下微信中的备份是啥意思(尤指 mac 平台)。

其实是这样的, 由于登录设备差异,同一个微信账户在不同设备(win、mac、ios、android)上的聊天记录是不完全一致的,一般手机上的才是完整的,电脑上(如果你没有一直登)是不完整的。

所以 mac 平台上的备份就包括

  1. 从手机备份到 mac
  2. 从 mac 备份到手机

我一开始以为备份是指把 mac 上的数据备份到另一个文件夹内,这个理解是不对的,其实如果去看微信的数据库设计部分,每个数据库是有单独的.db.bak的,尽管不大(也许里面压根就没有备份的数据,或者是压缩后的),但微信确实都有数据库级别备份的意图。

那无论是从手机备份到 mac 还是从 mac 备份到手机,都涉及到两台机器之前通信的问题,再明确一点,他们要彼此在同一个局域网内,用 socket 进行文件传送的。

所以其实 pcbakchat/gather.d就是劫持这部分局域网通信,把所有要备份的聊天记录都曝光出来,达到了给我们自己处理的目的。

具体可以见本仓库对备份部分的详细说明 - wechat-decipher-macos/devel at main · nalzok/wechat-decipher-macos

picture 76

可以看到还是比较复杂的,我一开始本来是走的这个思路,但是当时我还没对微信的数据库有较高的认识,所以当时这个方案跑起来了但是我没用。

其实这个方案应该最适合我的需求,因为我想获得的好友/群组的信息是已知的、数量不多的,我可以分别对这几个好友/群组进行备份动作,这样可以很方便地直接得到与他们的聊天记录(还可以在备份时选择时间,并且是手机上的聊天记录,也就是更完整)。

但考虑到我后来一直在研究数据库加解密上,并且在获得数据库秘钥之后,通过操作数据库也能获得我所有想要的聊天记录(因为当时我聊天的部分恰好都在 mac 上),所以 macos/dbcracker.d 已经能够满足我的要求。

所以本篇也会重点基于 macos/dbcracker.d 进行介绍,尽管 pcbakchat/gather.d 更适合导出与指定好友的(更完整的)聊天记录,更具有“社会”价值,但前者更具有“娱乐”(bushi,研究)价值。

devel/xlogger.d

这个其实就是把 mac 微信上所有的消息流都劫持了,打印出非常多的东西,所以只适合“黑客”自己二度开发相要的功能。

我们的需求没必要用这个,并且它一打开,微信就卡死了……可能是影响了微信的运行速度,然后假死,这是异常行为,可能有封号风险,所以谨慎。

总结

我们全部的工作,主要还是建立在 - nalzok/wechat-decipher-macos: Scripts to extract chat history from WeChat on macOS 的基础上,Qingyao Sun做了出色的工作(尽管部分地方有一些瑕疵),没有他精致(还记得我怎么评价的吗?“字字珠玑”)的项目文档,与合理的项目结构设计,我是不太可能一到两天就“攻破”微信的数据库的,感谢!

picture 77

update@2022-02-08: 关于加密字段

备份数据库的cipher_page_size不是默认值(1024),而是 4096!

所以原作中打印出这些信息是很有必要的!

picture 19

reference

如果您想自己攻破微信的数据库系统,以下是一些我认为比较核心的参考资料,包括各大平台的。

万变不离其中的是,微信的数据库使用的是基于sqlite3加密的sqlcipher,并且是sqlcipher 3 defaults配置,所以理解与熟悉该数据库才是全部工作的最大攻坚战。当你攻破之后,怎么做,就是你的事情了。

⚠️ 友情提醒:不要乱动微信的数据库,否则引起的一切后果,与本文无关,本文不涉及任何修改微信数据库的实现

各大平台仓库合集

mac 版

windows 版

ios 版

sqlcipher 相关

picture 79

pragma 相关

pragmasqlite3 中的一种关键字,具体我也不太懂,我们项目只需要会用很简单的几条语句即可,是操作 sqlcipher 必须的。

frida 相关

frida 是用于逆向的,原以为要用到,后来发现没有(至少我的应用级别没用到),也是捏了一把冷汗。以防需要,所以也补一份。项目底层监控微信部分,应该是用到了 frida 的。

hack manual

download sqlite

download any sqlite versions from here SQLite Download Page or directly download mac (x86) version from https://www.sqlite.org/2022/sqlite-tools-osx-x86-3370200.zip

test sqlite

unzip the downloaded sqlite zip, and test the sqlite.

➜  sqlite-tools-osx-x86-3370200 tree .
.
├── sqldiff
├── sqlite3
└── sqlite3_analyzer

0 directories, 3 files

picture 14

install openssl to replace the built-in libressl on MacOS

!!!warning brew need to be pre-installed

install openssl via brew

brew install openssl

config openssl into path

According to the brew instruction on openssl:

picture 15

We can directly write all the three commands into shell and make them work:

# if you use bash, change $SHELL to be `~/.bashrc`
SHELL=~/.zshrc
cat <<EOF >> $SHELL
heredoc> export PATH="/usr/local/opt/openssl@3/bin:$PATH"
heredoc> export LDFLAGS="-L/usr/local/opt/openssl@3/lib"
heredoc> export CPPFLAGS="-I/usr/local/opt/openssl@3/include"
heredoc> export PKG_CONFIG_PATH="/usr/local/opt/openssl@3/lib/pkgconfig"
heredoc> EOF

source $SHELL

result

before changing openssl, the default openssl is libressl:

picture 16

after that it becomes openssl:

picture 17

!!!tip 因为将 openssl 的路径加入了 path(并且在默认搜索路径之前),所以现在输入openssl会优先检索到我们的 openssl,如果想换回默认的libressl,则一方面可以在~/.zshrc配置文件中把我们新加入的几句话注释掉,这样每次重启 SHELL 就不会有;同时,我们还要在 SHELL 中重置一下 path,如下:

![picture 19](https://mark-vue-oss.oss-cn-hangzhou.aliyuncs.com/mac-wechat-hack-1644052792755-dfbab4a924d8531c5199ef3f75dc6c635ba7f965452f14a7e7f701cc735d93dd.png)

参考:
- [How to Reset the PATH Variable on Mac to Default macOS PATH](https://techpp.com/2021/09/13/reset-path-variable-on-mac-guide/)
- [macos - How do I reset the $PATH variable on Mac OS X? - Super User](https://superuser.com/questions/121870/how-do-i-reset-the-path-variable-on-mac-os-x)

confirm openssl

According to the brew install openssl command result, our openssl source codes are under /usr/local/Cellar/openssl@xxx:

picture 20

Have a check:

picture 21

!!!tip 可以看到,我们其实默认是有一个openssl@1.1的,然后我们新装了一个openssl@3,所以实际上我 follow 的那个帖子并不完全正确。

至少在我们安装homebrew后,就已经有了`openssl`(不单单是mac的`libressl`)。

这意味着其实我们(可能)没有必要再安装一个`openssl`,直接把目前这个`openssl`相关的信息写入环境变量即可。(待验证这种方式是否有效)

compile sqlcipher

官方 sqlcipher/sqlcipher: SQLCipher is a standalone fork of SQLite that adds 256 bit AES encryption of database files and other security features.对编译是这么写的:

picture 23

在我没有define SQLITE_HAS_CODEC and either SQLITE_TEMP_STORE=2 or SQLITE_TEMP_STORE=3之前(引申阅读: 1. VC++下的 sqlite 数据库加密 | 离别歌, 2. SQLite Forum: SQLITE_HAS_CODE is gone?),运行的命令行会报错:

./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" \
LDFLAGS="/usr/local/Cellar/openssl@3/3.0.1/lib/libcrypto.a"

picture 22

但你定义上述变量还比较麻烦,要去某个.h里,我都不知道它们在哪……其次,也不一定只是定义这个问题。

在我们的中文教程 (25 条消息) Mac 终端使用 Sqlcipher 加解密基础过程详解_Martin.Mu `s Special Column-CSDN 博客_mac sqlcipher 里他摸索出来的结果是这样的:

picture 24

所以我基于他给出的命令行改成了如下(1. 删除了--prefix=yourlibdir这个参数; 2. 修改了LDFLAGS参数为我们实际的libcrypto.a位置):

./configure  --disable-tcl --disable-shared --enable-static=yes --enable-tempstore=yes --with-crypto-lib=none CFLAGS="-DSQLITE_HAS_CODEC -DSQLCIPHER_CRYPTO_OPENSSL" LDFLAGS="/usr/local/Cellar/openssl@3/3.0.1/lib/libcrypto.a"

然后一下就编译成功了!

picture 25

接着就是make一下,最终会生成sqlcipher可执行文件:

picture 26

以上就代表我们的编译过程顺利完成。

UPDATE: 静态编译

刚刚那个编译好像属于动态编译,后续我在编译 python 版本的pysqlcipher3的时候又出现了ld: library not found for -lsqlcipher的问题:

picture 43

所以还是静态编译可能比较好。

重新回顾一下 sqlcipher 的编译教程,我们只需要知道 libcrypto.a的位置就可以了。

picture 44

(南川)注意看我是怎么找到 libcrypto.a的位置的,当我只知道他在Cellar下的时候。(其中的realpath命令需要brew install coreutils)

picture 45

接着拷贝该位置到安装参数内。

(.pyenv) ➜  sqlcipher git:(master) ✗ ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="/usr/local/Cellar/openssl@3/3.0.1/lib/libcrypto.a"

但是报错了:

picture 46

这个问题其实正好就是我们动态编译错过了的但是博主碰到了的问题:

picture 47

跟着他的经验,也别管他的命令行怎么写的,加上参数:

(.pyenv) ➜  sqlcipher git:(master) ✗ ./configure --enable-tempstore=yes CFLAGS="-DSQLITE_HAS_CODEC" LDFLAGS="/usr/local/Cellar/openssl@3/3.0.1/lib/libcrypto.a" --with-crypto-lib=none

立即通过!然后再运行make install即可。

picture 48

注意,install之后,可以看到,其实是把libsqlcipher.a等写入到了/usr/local/lib下面,这个路径要记得,以后其他库一般也会编到这里。

test sqlcipher workflow

step 1. crypto a plain database (which is generated by our sqlite before)

picture 27

Among the commands, the attach database XXX as encrypted key YYY would generate a database named XXX, which is encrypted by key YYY.

step2. test: operate on an encrypted database without key (expect: failure)

picture 28

step3. test: dump the encrypted database into plain with key (expect: success)

picture 29

step4. test: open the decrypted database without key (expect: success)

picture 30

✨✨ decrypt database

DEPRECIATED: pragma config of sqlcipher 3 defaults

!!!warning 我的 sqlcipher 版本是 3.36.0,这个版本默认是 sqlcipher 4的配置了(盲猜),而腾讯的加密用的是 sqlcipher 3,所以在解密文件时,必须将配置都对上(可以按照 GUI 软件DB Browser for SQLite一一对上),否则会出现file is not a databaseout of memory等错误

picture 31

PRAGMA cipher_compatibility = 3;
PRAGMA kdf_algorithm = 0;
PRAGMA hmac_algorithm = 0;
PRAGMA kdf_iter = 64000;
PRAGMA cipher_page_size = 1024;

ref

BEST-PRACTICE: pragma config of sqlcipher 3 defaults

As mentioned at: - rigglemania/pysqlcipher3: Python 3 bindings for SQLCipher, we only need to add one line of PRAGMA cipher_compatibility = 3" after setting "PRAGMA key='password'".

picture 40

Here is the tested result:

picture 41

check salt of specific database file

usage

xxd -p -l 16 -g 0 '/path/to/foo.db'

sample

picture 32

verification

picture 34

ref

picture 33

decrypt and dump specific database file

  1. open our custom hook script and get the database secret info:

picture 35

  1. copy the PRAGMA XXX statements for specific database file

  2. dump specific database file after decrypting

ATTACH DATABASE 'plaintext.db' AS plaintext KEY "";
SELECT sqlcipher_export("plaintext");
DETACH DATABASE plaintext;

picture 37

ref

test dumped database file (via sqlcipher or sqlite3)

Since the database dumped has been decrypted, so using sqlcipher or sqlite3 are both ok!

picture 38

!!!tip As a contrary, if we using sqlite3 to open an encrypted database file, then the PRAGMA commands are always invalid, and there would be no way to decrypt the database.

![picture 39](https://mark-vue-oss.oss-cn-hangzhou.aliyuncs.com/mac-wechat-hack-1644069321523-f78eba6a3271f2e2e9cf3c2c04a83fda5e5d6e26f5289e3d3b82ad09af2bd042.png)

wechat design

design of contact fields

以某好友资料为例:

picture 62

对应的可以看到数据表信息为:

picture 64

可以知道,最有用的字段主要如下:

gUsrName: wxid(自动、唯一标识号)
m_nsAliasName: 好友的注册id
nickname: 好友自己设置的对外显示的昵称
m_nsRemark: 你给好友设置的备注

其他还有一些拼音相关的有时也比较适合模糊搜索,不过全拼和简拼比较适合中文,英文的话全拼不变,简拼没有(另外也可以看到腾讯的命名规则也不统一,并且还中英文混杂……):

m_nsFullPY: 好友昵称全拼
m_nsShortPY: 好友昵称简拼
m_nsRemarkPYFull: 好友备注全拼
m_nsRemarkPYShort: 好友备注简拼

design of user id to contact id: md5

picture 51

picture 52

ref

IMPROVE: get self id

搜索自己的昵称,但是发现没有找到,说明contact表里是没有自己的。

picture 65

所以,我们需要知道自己的 id 信息在哪里获取。

UPDATE-2022-02-06:聊天文件是以聊天对象的 md5 值作为数据库名存储的,尽管在聊天记录中基于你和对象的微信 id 使用了一个字段表示聊天方向,但同时还有另外一个整型字段标志着是否是自己,所以尽管在联系人数据库中找不到自己的 id,但不影响对聊天记录中聊天方向的识别。

TODO: get image from xml

要遍历本地找!

sample

<!-- StrRes1 -->
<?xml version="1.0"?>\n<msg>\n\t<img aeskey="252260f7cd231a2ee75e997483fdbe26" encryver="0" cdnthumbaeskey="252260f7cd231a2ee75e997483fdbe26" cdnthumburl="3059020100045230500201000204d3e741cc02030f5bd102041be0cdcb020461fd7c48042b777875706c6f61645f777869645f636b3835787570386231626a32315f3335395f313634343030323337330204011d0a020201000400" cdnthumblength="2906" cdnthumbheight="120" cdnthumbwidth="55" cdnmidheight="0" cdnmidwidth="0" cdnhdheight="0" cdnhdwidth="0" cdnmidimgurl="3059020100045230500201000204d3e741cc02030f5bd102041be0cdcb020461fd7c48042b777875706c6f61645f777869645f636b3835787570386231626a32315f3335395f313634343030323337330204011d0a020201000400" length="1" md5="ac0d0d7ae1c546233d2dd8bdfbaa9d37" hevc_mid_size="77982" />\n</msg>\n
<!-- messageType -->
<msgsource>\n\t<bizflag>0</bizflag>\n\t<sec_msg_node>\n\t\t<uuid>e78ea49721c227614ead30b94f1dea68_</uuid>\n\t</sec_msg_node>\n\t<signature>v1_IC/iNhD5</signature>\n</msgsource>\n

ref

py-sqlcipher instruction

core ref

compile

编译步骤永远都是最烦的哎,不过还好都顺利通过了。

首先是下载源代码。

git clone https://github.com/rigglemania/pysqlcipher3
cd pysqlcipher3

picture 80

其次是编译,有两种方案。

由于我现在系统中已经静态编译过 sqlcipher 已经有了 libsqlcipher,所以我直接python setup.py install 就能成功。

find /usr/local/lib -name libsqlcipher.a
# output: /usr/local/lib/libsqlcipher.a

picture 81

否则的话,我需要把在 sqlcipher 动态编译产生的 sqlite.[ch] 文件都拷贝到当前目录下。

picture 82

再编译python setup.py build_amalgamation又会发现src/python3/connection.h报错找不到sqlcipher.h了。

picture 83

所以我们再……把 amalgamation 文件夹拷贝到 src/python3/下,并重命名为sqlcipher……(真忙啊……)

然后编译:

python setup.py build_amalgamation

python setup.py install

成功通过!

picture 84

这样,你才能在 python 中使用 from pysqlcipher3 import dbapi2 as sqlite

测试是否有 pysqlcipher

picture 85

connection

如果是已解密/未加密的数据库,则使用 sqlite3 或者 sqlcipher 皆可。d

但如果是加密的数据库,则必须使用 sqlcipher 进入解密。

以下皆以 sqlcipher 演示。

命令行版:

# 一句话搞定
sqlcipher DB/PATH

-- 验证
sqlite> PRAGMA key = "XXXX";
sqlite> PRAGMA cipher_compatibility = 3;

-- 测试
sqlite> .tables

python 版:

# Python 3.9.10

from pysqlcipher3 import dbapi2 as sqlite
from pysqlcipher3.dbapi2 import Connection

def auth_db(ddb_path: str, db_key: str) -> Connection:

logger.info({"dp_path": db_path})
conn = sqlite.connect(db_path)

conn.execute(f'PRAGMA key = "{db_key}";')
conn.execute(f"PRAGMA cipher_compatibility = 3;")
conn.commit()

logger.info(f"authenticated {db_file}")
return conn

table

list all the tables

If you are using pure sqlite/sqlcipher, then using .tables can list all the tables. However, it won't in the py program.

In programme, I need to using the following:

SELECT name FROM sqlite_master WHERE type = "table"

And the python may be:

tables = list(c.execute('SELECT name FROM sqlite_master WHERE type = "table"'))

And the sample result of tx-contact table is:

picture 49

ref

list the columns of table (get table schema)

In sql, we can use:

-- to list all the tables in the database:
.tables

-- to show the schema for a given tablename:
.schema tablename

Otherwise:

PRAGMA table_info(table_name);

And to get column names in py:

columns = list(i[1] for i in conn.execute(f"PRAGMA table_info({table_name})"))

ref

format rows display

-- to show current configuration
.show

-- to show rows of columns
.headers ON
.mode columns
.nullvalue -

ref

list rows in one table

SELECT * from XXXTABLE

-- limit rows, skip/offset rows
SELECT * FROM table LIMIT -1 OFFSET 10

sample

picture 50

ref

extended

how to know my openssl version/info

$ openssl version -a

LibreSSL 2.8.3
built on: date not available
platform: information not available
options: bn(64,64) rc4(16x,int) des(idx,cisc,16,int) blowfish(idx)
compiler: information not available
OPENSSLDIR: "/private/etc/ssl"

the OPENSSLDIR is the config info for openssl other than the src files.

$ tree /private/etc/ssl

/private/etc/ssl
├── cert.pem
├── certs
├── openssl.cnf
└── x509v3.cnf

1 directory, 3 files

And as mentioned from Mac 终端使用 Sqlcipher 加解密基础过程详解_Martin.Mu `s Special Column-CSDN 博客_mac sqlcipher, the built-in openssl on MacOS may not be suitable for our project target.

picture 13

ref

bugfix: error: C compiler cannot create executables

ref

本项目合作伙伴

某攻防工程师,w哥

某支持工程师,z妹