Step 1:逆向验证流程
校验流程
- 离线校验
- 获取激活请求:registration_file.bin
- 一个Base64 Encode后的JSON
- 内部带有aakore_id、installation_id、installation_hwid、instance_name四个字段
- 上传激活文件:activation_file.bin
- 返回一个带有很多operations的json文件,同样是base64后的
- 处理接口:http://127.0.0.1:9877/api/account_server/onprem_operations
- 可定位到处理进程:account_server.exe
离线激活流程
- account_server.exe基本情况:
- golang,符号基本保留
- IDA Pro 7.7 SP1可以解析其结构体,可以进行逆向
- 花了几天时间解决了Golang多返回值的支持
- 激活文件格式:
激活文件样例- 很多个operation,似乎是先注册、然后关联账号,最后设置license key
- 带有sign,具体签名逻辑未知
- 逆向激活逻辑:
- 具体验证位于
git.acronis.com_ab_account_server_internal_logic_onprem_operations._ptr_OperationsFile.Verify
- 计算sha256 sum后,使用rsa提供的VerifyPS5函数校验签名
- 证书由
git.acronis.com_ab_account_server_account_server.ParseConfig
解析ValidationKeys并一路传入
Step 2:完成破解
破解思路:
- 配置文件中竟然提供了override的配置项:
on_prem_operations_override_validation_key
重新签名激活文件
- 直接使用Golang反着写出来一个SignPS5的工具就可以了
- 写这个工具的时候全是坑,Acronis将激活文件读入之后再重新serialize来计算checksum,导致json格式有多个地方与源文件有所不同,通过打断点取出变量内容后观察写了一些变换规则
破解修改配置文件来修改证书
- 在onprem模式下,配置文件有校验checksum
- 校验发生在
main_parseConfig
中,通过serialize程序的配置信息为一行行的内容来签名 - 默认使用算法为sha256,而可选的checksum算法有md5 sha256 debug
- 其中debug是将每行用”|” join的结果作为checksum
- 由于他的serialize过程过于复杂,直接下断点在account_server_.exe中捕获checksum结果更方便。
git_acronis_com_abc_struct_checksum__ptr_HashCheckSumCalculator_Check
// git.acronis.com/abc/struct-checksum.(*HashCheckSumCalculator).Check
error __golang git_acronis_com_abc_struct_checksum__ptr_HashCheckSumCalculator_Check(
_ptr_structchecksum_HashCheckSumCalculator a1,
interface_ a2,
_slice_uint8 a3)
{
const char *v3; // rdi
retval_187AD60 v4; // [rsp+18h] [rbp-30h]
v4 = git_acronis_com_abc_struct_checksum__ptr_HashCheckSumCalculator_Sum(a1, a2);
if ( v4.1.tab )
return v4.1;
if ( v4.0.len == a3.len && runtime_memequal((__int64)v4.0.ptr, (__int64)a3.ptr, v4.0.len) )
return (error)0LL;
fmt_Errorf(v3);
return *(error *)&v4.0.cap;
}
尝试修改配置:
- need_account_for_trial: true→false
- allow_licenses_cloud_sync: true→false
- restrict_licensing_for_deactivated: true→false
- demo_mode_duration: 720h→100y
- activation_frequency: 24h→100h
- need_account_for_trial: true->false
- allow_licenses_cloud_sync: true->false
- demo_mode_duration: 720h->876000h
- replace all "acronis.com" to "acronis_.com"
- add "on_prem_operations_override_validation_key"
尝试激活
- 在docker中激活时总会莫名其妙出错,原因不明。
- 无论是我自己签名的还是官方签名的都无法正常激活
- 但多重启、重build几次docker之后又会正常
- 在配置修改错误时会导致无法将license assign到具体设备上
- 激活会成功,但是添加设备时显示没有license
- 少改了几处后重新尝试激活又能成功了
- 激活与installation_hwid相关,installation_hwid似乎和cpu信息有关,具体计算方式不明,需要慎重观察
Step 3:打包Docker
- 继承自12.5的docker
- 从centos的systemd换成了ubuntu的systemd,更加稳定易用
- 每次生成新的machine id,希望它能每次build出不同的hwid
- 用上了docker 1.2新出的syntax,可以直接将安装包mount进来了,不需要multistage复制来复制去了
- persistence做了很久
- 需要persist这些目录:
"/home", "/var/lib/Acronis", "/var/lib/alsdb", "/etc/Acronis", "/opt/acronis/management_agent/var", "/var/etc_pass"
- 继承12.5使用systemd在basic target之前将这些目录拷贝
- 始终有问题,调研后发现之前的systemd unit写的一直不对。
- systemd启动流程是local-fs.target→basic.target→sysinit.target→multi-user.target
- DefaultDependencies不关的情况下,systemd会默认require sysinit,而我们希望能被basic require,导致循环依赖。
- 正确写法是:
[Unit]
Description=Sync /etc/passwd to config volume
DefaultDependencies=no
Requires=local-fs.target
After=local-fs.target
Before=sysinit.target
[Service]
Type=simple
ExecStart=/usr/local/libexec/sync_passwd.sh
[Install]
RequiredBy=basic.target
/etc/passwd不能是符号链接,而我又想做持久化- 尝试通过osync同步,但其只支持目录同步
- 找到了unison,支持只同步两个文件
- 加了个systemd服务每5分钟执行一次同步
- 自己的用户死活不能登录
- 第一层问题:这个docker base image的systemd少了/lib/systemd/system/multi-user.target.wants里面的东西,导致systemd-user-sessions没起来,每次都存在/run/nologin,导致pam_nologin一直拒绝登录
- ln -s ../systemd-user-sessions.service到wants目录即可
- 第二层问题:acronis的pam鉴权工具没有支持密码登录
- /etc/pam.d/acronisagent里面没有写password开头的directive,导致只有他一个白名单文件中的用户能登录(默认里面只有root)
- 把/etc/pam.d/acronisagent整个注释掉扬了
docker run -d --name acronis_agent \
--restart always \
--privileged \
--net host \
--add-host nas-school6.misty.moe:172.17.0.1 \
-it \
ccr.ccs.tencentyun.com/misty/acronis_agent
docker run -d --name acronis_server \
--restart always \
-v /volume1/docker/acronis_server/home:/home \
-v /volume1/docker/acronis_server/var_lib_Acronis:/var/lib/Acronis \
-v /volume1/docker/acronis_server/var_lib_alsdb:/var/lib/alsdb \
-v /volume1/docker/acronis_server/etc_Acronis:/etc/Acronis \
-v /volume1/docker/acronis_server/opt_Acronis_var:/opt/acronis/management_agent/var \
-v /volume1/docker/acronis_server/var_etc_pass:/var/etc_pass \
--tmpfs /tmp --tmpfs /run --tmpfs /run/lock -v /sys/fs/cgroup:/sys/fs/cgroup:ro \
-p 9877:9877 -p 7780:7780 \
--net=host \
--add-host nas-school6.misty.moe:172.17.0.1 -h nas-school6.misty.moe \
-it \
ccr.ccs.tencentyun.com/misty/acronis_server