阅读视图

发现新文章,点击刷新页面。
🔲 ⭐

云端部署FaceFusion-AI换脸

Featured image of post 云端部署FaceFusion-AI换脸

写在最前面:有些步骤可能需要魔法

号称***“Next generation face swapper and enhancer ”***的Facefusion 上周发布了2.2.1 版本。虽然对显卡要求没有以前的roop 和deepfake 那么夸张,但是GTX1650 跑起来还是比较吃力,所以决定云端部署。

这次依然是选择了老朋友恒源云,如果有动手能力也可以尝试白嫖Colab。

项目地址:https://github.com/facefusion/facefusion

官方文档:https://docs.facefusion.io/

这次创建镜像的时候选择的是PyTorch >2.0.0 >Cuda11.8.0 刚好符合项目需求。

一、文件下载

1
2
3
4
5
6
#安装cli
curl -L https://download.gpushare.com/download/gpushare-cli-linux -o /usr/local/bin/gpushare-cli
chmod u+x /usr/local/bin/gpushare-cli

#验证是否安装成功
gpushare-cli version

这一步是为了后续的文件传输,具体可以参考我之前的博客:https://fallen.wang/p/sovits/

然后下载模型文件:此链接由Bilibili用户 @AI百晓生 提供

https://pan.baidu.com/s/1U_vsRu9ILHn9FQ_5iph-YQ?pwd=f86f

*这是为Windows 系统准备的,Linux 只需要下载其中的models.7z即可*

将项目clone 到本地:

1
git clone https://github.com/facefusion/facefusion

如果因为众所周知的原因导致clone 失败,请使用魔法,或者自行搭建异次元通道,当然也可以下载压缩包到本地手动上传:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
cd /hy-tmp
#上传项目压缩包然后解压
unzip facefusion-master.zip
#创建模型目录,注意以.开头的文件夹是隐藏的
cd facefusion-master
mkdir .assets
#下载模型文件
gpushare-cli baidu down models.7z
#解压,注意文件约6G需要使用7za命令解压
7za x /usr/local/bin/models.7z
#将解压后的models文件夹移动至/.assets内
mv /models /hy-tmp/facefusion-master/.assets

二、环境部署

Python

该项目使用的是Python3.10 ,而恒源云的Ubuntu 自带的是Python3.8 ,因此需要升级:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
#更新包列表
sudo apt update
#安装依赖项
sudo apt install -y software-properties-common
#添加Python3.10 的PPA 到源列表中
sudo add-apt-repository ppa:deadsnakes/ppa
#若提示‘Press [ENTER] to continue or Ctrl-c to cancel adding it’则按回车
#安装Python3.10
sudo apt install -y python3.10
#验证
Python3.10 --version

FFmpeg

1
apt install ffmpeg

若询问是否继续输入y

cURL

1
apt install curl

若询问是否继续输入y

虚拟环境

接着创建虚拟环境:

1
2
cd /hy-tmp/facefusion-master
python3.10 -m venv venv

此时却出现了这样一条报错:

Error: Command ‘[’/hy-tmp/venv/bin/python3.10’, ‘-m’, ’ensurepip’, ‘–upgrade’, ‘–default-pip’]’ returned non-zero exit status 1.

此时已经创建了venv ,报错是因为缺少ensurepip 模块,具体原因尚不清楚。

1
2
3
4
5
6
#先把刚刚的venv删掉
rm -rf venv
#重新创建不带pip的venv
python3.10 -m venv --without-pip venv
#激活虚拟环境
source venv/bin/activate

三、安装项目

1
python install.py

报错:ModuleNotFoundError: No module named ‘inquirer’ 尝试pip 却依然报错。

查阅了官方discord后发现也有人遇到过类似问题,版主给出的解决方法是:

1
python -m pip install --upgrade pip

这时却提示缺少pip ,因为刚刚创建虚拟环境的时候留了一个伏笔--without-pip venv。手动装一个:

1
2
curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
python get-pip.py

安装了最新版pip 之后就可以运行 install.py了。

因为显卡是N卡,所以按方向键选择cuda,选择两次。cuda 耐心等待脚本执行完毕。 大致看一眼没有报错便可进入下一步。

1
python run.py

当出现Running on local URL: http://127.0.0.1:7860时即为成功启动了。此时服务器端访问127.0.0.1:7860即可,但是毕竟服务器端没有图形化界面,所以可以在launch()函数里设置share=True以获得可供外网访问的链接:不过我个人更喜欢配置一个端口转发。

以xshell为例,连接至实例时需要提供主机、端口、用户和密码,这些都可以在控制台界面找到。 user 点击登录指令复制按钮,得到如下信息: ssh -p 41624 root@i-2.gpushare.com 其中41624 为端口,root 为用户,i-2.gpushare.com 为主机,密码则单独列出。 新建会话,填写主机和端口,然后在侧边选项卡里找到SSH > 隧道> 添加,如图示填写: port 其中侦听端口可随意填写。 以ROOT 身份登录,输入密码,成功建立会话后在本地浏览器中输入127.0.0.1:8888即可访问web-ui。 webui

BTW,该项目引用了开源的NSFW 检测,具体代码位于/facefusion/content_analyser.py,可以尝试调整probability值。

🔲 ☆

淋巴造血系统病理(未完待续)

Featured image of post 淋巴造血系统病理(未完待续)

考纲

1.霍奇金病的病理特点、组织类型及其与预后的关系。 2.非霍奇金淋巴瘤的病理学类型、病理变化及其与预后的关系。 3.白血病的病因分类及各型白血病的病理变化及临床表现。


淋巴组织肿瘤概述

定义

淋巴组织肿瘤 来源于淋巴细胞及其前体细胞的恶性肿瘤,包括淋巴瘤、淋巴细胞白血病、毛细胞白血病、浆细胞肿瘤等
淋巴瘤 原发于淋巴结、结外淋巴组织的恶性肿瘤,分为霍奇金淋巴瘤、费霍奇金淋巴瘤
1
2
3
4
5
6
7
 ┌-→NK-T细胞
 ┌-→前体T细胞→初始T细胞→T免疫母细胞-┤
 │ └-→T细胞
淋巴干细胞-┤
 │ ┌-→B免疫母细胞→浆细胞样淋巴细胞-------------┐
 └-→前体B细胞→初始B细胞-┤ ├-→浆细胞
 └-→套细胞→中心母细胞→中心细胞→边缘带细胞→B细胞┘

WHO关于淋巴组织肿瘤的分类

T细胞
🔲 ☆

一次破解水卡的尝试

Featured image of post 一次破解水卡的尝试

**本文仅为探讨M1 卡加密原理,文中所述卡片均已格式化并物理销毁,如有利用该算法恶意刷取金额,所造成的任何问题及由此产生的一切后果由您自行承担!**

仅供技术交流使用,请勿用于违法用途,否则后果自负!

[TOC]

前言

本文只针对IC 卡下属的Mifare Classic 1k (简称M1 卡,目前国内大多数校园卡、公交卡、门禁卡等都在此列),其包含了16 个扇区,每个扇区有0-3 共4 个块,每块16 字节,共1024 字节。

只对离线数据有效!(例如,充值后需要去激活器上刷卡激活的卡片。部分卡片同时存储了离线数据和在线数据,如即充即用的圈存数据,和充值后需要刷卡激活的水卡数据,则只能修改后者。在线数据存储在服务器中,即使修改了本地缓存也无效)

如何确认自己的卡是否属于M1 卡?可以使用带NFC功能的安卓手机进行检测。(参考正文第一段准备中的Mifare Classic Tool 软件)将卡片紧贴手机,打开软件,选择工具>显示标签信息>若出现如下截图:注意Tag Type属性

标签类型为MIFARE Classic 的即为M1 卡,其中SAK 值为08 代表s50 型号,18 代表s70 型号

一.准备

·需要准备的硬件:

一台有USB 接口的计算机

一部有NFC 功能的安卓手机

PN532 ,某宝上有集成板,约30 元

若干张水卡

一个健全的大脑

·需要准备的软件:

PC端:PN532 配套软件(链接:https://pan.baidu.com/s/1-FrJKKnw1JbR4lnyaRR22A?pwd=wa2v 提取码:wa2v 解压密码:pn532

安卓端:Mifare Classic Tool(链接:https://pan.baidu.com/s/11x10vu_GMiNZoJp5igiaHg?pwd=zc0y 提取码:zc0y )

二.读取数据

安装pn532 驱动后打开软件,准备若干张水卡。依次点击串口,连接设备,开始解卡,此时软件开始读取数据。

主界面

成功破解后当前卡片的数据会在表A 中列出。可以看到每个扇区都有4 个块,其中0-2 块储存数据,3 块储存密钥及控制位。

扇区和块

三.分析数据

将读取到的数据保存,然后去消费一定数量金额,再次解卡。将上一次保存的数据导入到表B 中,然后对比数据。可以发现,只有第10 扇区数据发生了变化,因此可以得出结论,金额数据存储在第10 扇区。

数据对比

观察表A和表B前两个块的数据发现,第三、四字节的数据分别为038A038C038E ,成等差数列。打开计算机自带的计算器,切换到程序员模式,选择十六进制(HEX ),输入038A ,得到对应的十进制数值(DEC )为906 。而此时卡里的金额为9.06 元,前一次消费时金额9.08 也与038C 对应,基本可以确定前四个字节存储的是金额。由于消费金额较少(0.02 ),可能会出现如图两块数据只有一块数据改变的情况。金额一旦确定,剩下的便是校验位的问题。为防止篡改,卡片会有一个安全算法,对金额进行加密。由于中间部分没有发生变化,所以可以合理假设最后两个字节为校验位。

一般来说校验位算法比较复杂,可能涉及异或、取反等多种运算,而我们现有的数据太少难以发现规律,因此首先可以考虑克隆。由于掌握了密钥,我们可以对卡里的数据进行复制和更改。消费掉一定金额后,将表A的数据再次刷入,然后观察读卡器,金额又变回了9.06 ,这一思路是可行的。但是多次以同一金额重复刷卡测试会导致卡片锁死(惨痛教训),除非本来卡内金额较多可以支撑长时间使用外,我们不得不考虑更改数据。

然而要更改数据必然涉及到校验位算法。前前后后忙活了近一年,仍然没有取得实质性进展。然而某一天阅读维修文档时发现,有一类卡片报错是由于CRC 校验错误引起的。这给我带来了灵感,我并不需要知道具体的校验算法是什么,只要能得到校验后的数据就行。可以参考这个在线计算CRC 的网站:https://www.lammertbies.nl/comm/info/crc-calculation,选择HEX 模式,将第一块的数据复制进去,得到0000038a00000000000000000000271f 的CRC-16 校验值为F0BE ,而第二块数据0000038c000000000000000000003997 的CRC-16 校验值也是F0BE

注意选择HEX模式,CRC-16校验

CRC-16校验值相同

同理,对表B的数据进行验证,校验值 依然是F0BE 。也就是说,无论这个神秘的校验算法是什么,最终整个块的CRC-16 校验值是不变的,因此我们有了这样一个逆向思路:

输入我想要的金额→校验算法对金额加密并输出到最后两字节→整体CRC-16 校验值不变,为F0BE →穷举最后两字节16×16×16×16=65536 种可能组合,与块中前14 个不变字节拼接并分别计算CRC-16 校验值→找到校验值同为F0BE 的组合→其末尾两个字节即为我们需要的校验算法得到的数据

人工计算65536 个16 字节字符串显然不现实,这里使用Python 辅助。C 语言和Java 同理。

四.破解

(由于对CRC 并不熟悉,所以代码让ChatGPT 写了个模板,自己稍微改了改,这时候就觉得人工智能真牛逼QAQ)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import binascii
import crcmod

# 定义计算CRC16校验值的函数
def crc16(data):
 crc16_func = crcmod.predefined.Crc('crc-16')
 crc16_func.update(data)
 return crc16_func.hexdigest()

# 打开shuju.txt文件并穷举65536个字符串
with open("shuju.txt", "w") as f:
 hex_data = input("请输入16进制数据:")
 for i in range(65536):
 new_data = hex(i)[2:].zfill(4).upper()
 f.write(hex_data + new_data + "\n")

# 打开shuju.txt文件并计算每个字符串的CRC16校验值
with open('shuju.txt', 'r') as f:
 lines = f.readlines()

# 将字符串及其CRC16校验值输出到shuju_crc.txt中
with open('shuju_crc.txt', 'w') as f:
 for line in lines:
 data = binascii.unhexlify(line.strip())
 crc = crc16(data)
 f.write('{} {}\n'.format(line.strip(), crc))

例如,将金额设置为100 元,在计算器中输入10000 ,可知对应的16 进制数值为2710 ,运行上述代码,输入前14 个不变字节0000271000000000000000000000 ,程序将会在末尾加上从0000 递增到 FFFF 的字符串,并将这65536 个新的字符串输出到shuju.txt 中。接着对这些数据分别计算CRC-16 校验值,并将原始数据和对应的校验值输出到shuju_crc.txt 中。

由于CRC-16 涉及到多项式计算,65536 个数据可能对CPU 有一定要求,以我为例,穷举过程只用了不到0.5 秒,计算CRC则用了约15 秒。结束后得到如下数据:

注意是shuju_crc.txt,不是shuju.txt

crtl+F 呼出查找界面,查找F0BE 应该会有两个结果,一个是作为穷举数据出现在原字符串末尾的;另一个是作为CRC-16 计算结果,与原始字符串间隔了一个空格的,我们需要的是后者。如图,看到该字符串结尾是8BB5 ,即2710 经过神秘校验算法得到的数值为8BB5 。同理,我们对99.98 对应的16 进制数据270E 进行如上操作,得到末尾两字节为EB9D 。此时我们将00002710000000000000000000008BB50000270E00000000000000000000EB9D 刷入第10 扇区的前两个块,然后任意消费验证,金额变成了100 元。至此M1 卡破解完毕。


五.后续

仅仅是破解了CRC 校验并没有让我满足,毕竟至今我还未曾解开校验算法的神秘面纱。以及,每张卡的密钥是不同的,且似乎与卡号有着某种联系。遗憾的是对于异或、取余、取反等运算不够熟悉,且样本量太小,还没有头绪。先挖个坑吧,将来有机会一定补上。

草稿

本文仅为探讨M1 卡加密原理,文中所述卡片均已格式化并物理销毁,如有利用该算法恶意刷取金额,所造成的任何问题及由此产生的一切后果由您自行承担!

❌