2026盘古石初赛-服务器取证(zzx)

案情分析、概览

犯罪/运营方搭建了一个“金鳞资本”理财投资平台,表面上提供注册、实名、充值、法币交易、杠杆交易、客服聊天等功能,实际通过机器人、假聊天、假交易、假流水来营造平台活跃和盈利假象,诱导用户充值或继续投入资金。

这套平台部署在 三节点 PVE 集群 + Ceph 分布式存储 上。集群名是 pgscup2026,业务虚机是 VM 100 (web),磁盘放在 Ceph RBD 池 Ceph_pgscup_pool 里。也就是说,出题人没有只给一个网站目录,而是模拟了一套较完整的企业级基础设施。

一开始业务虚机不可用,关键原因不是网站坏了,而是 Ceph monitor 绑定到了不可用的 **192.168.170.x** 网段,导致 RBD 磁盘不可读。恢复 Ceph 后,才能看到 vm-100-disk-0,再对业务虚机磁盘做离线取证。

从 Nginx 和 Laravel 配置看,网站域名是 jlzb.vip,站点根目录是 /var/www/html/public,应用名指向“金鳞资本”。技术栈是 Nginx + PHP-FPM + Laravel 5.5 + MariaDB。数据库名是 jinqin,里面有用户、实名、钱包、聊天、商家、法币交易、杠杆交易等模块。 有用户体系,有余额,有钱包流水,有商家,有交易,有杠杆,有客服聊天。

数据库中聊天表是 user_chat,聊天记录数多,并且存在 20 个机器人账号。材料中还提到机器人身份包括客服、导师、专员、财务、经理等,话术围绕充值、提现、收益、杠杆、风险安抚、限时名额等内容。

服务器有加密和混淆:

第一条是 .env.obf,它不是明文 .env,而是通过 XOR、Base64、自定义替换、Hex 等方式混淆。
第二条是 /root/encrypt_tool.py,它用于数据库备份加密,包含 XOR 密钥 0x5A 和备份密码 JDSJ2026@Backup

起pve集群

起镜像磁盘要选两个;打开之后三个机子设置成nat

这里ens160是关掉的 要起以下

ip link set ens160 up //起网卡
ip link set vmbr0 up //起桥
ip link set ens160 master vmbr0 2>/dev/null || true //把网卡加到桥当中;让外部网络流量进到 vmbr0
ip addr flush dev vmbr0 //清空vmbr0上所有ip
ip addr add 192.168.0.50/24 dev vmbr0	//给vmbr0配置静态地址
ip route replace default via 192.168.0.1 dev vmbr0 //设置默认路由(或替换旧默认路由)到网关 192.168.0.1。
ip -br a
bridge link
ping -c 3 192.168.0.1

node2/3 ip分别配置为51/52,这里三个机子配置好了就可以ssh了。

分析pve集群,请给出pve主机版本号?[答案格式:1.2.3]

9.1.1

pveversion
pveversion -v

PVE 主版本号/ 内部构建号 /当前运行的 Linux 内核版本

分析pve集群,请给出pve主机内核版本?[答案格式:1.2.3-123-abc]

6.17.2-1-pve

uname -r
pveversion

见上题

进前端管理界面

pve管理系统是8006,192.168.0.50:8006

分析pve集群,请给出pve集群名?[答案格式:abc132]

答案:pgscup2026

法一:

法二:

pvecm status
cat /etc/pve/corosync.conf

corosync.conf存放:

  • 集群名称
  • 所有 PVE 节点 IP、节点名字
  • 心跳通信端口、通信网卡
  • 集群超时、投票机制配置
  • 加密、认证相关参数

分析pve集群,请给出加入集群所用指纹的前6位?[答案格式:AA:BB:CC]

FD:11:CE

分析pve集群,请给出pve集群中主机所用的时间服务器地址?答案格式:[www.baidu.com]

答案:ntp.aliyun.com

ntp: Network Time Protocol 网络时间协议

cat /etc/systemd/timesyncd.conf
cat /etc/chrony/chrony.conf

  • timesyncd.confNTP=ntp.aliyun.com

Chrony 是一个用于时间同步的软件,它旨在提供高精度的系统时钟同步。Chrony 软件包括一个 NTP(Network Time Protocol,网络时间协议)服务器和客户端,可以帮助计算机系统与网络时间服务器同步,以确保系统时钟的准确性。

  • chrony.confserver ntp.aliyun.com iburst

分析pve集群,请给Ceph存储的资源池名?[答案格式:Abc_def]

答案:Ceph_pgscup_pool

法一:

法二:

cat /etc/pve/storage.cfg

  • storage.cfg 中:
rbd: Ceph_pgscup_pool
    pool Ceph_pgscup_pool
  • ceph osd pool ls detail 中存在 pool 2 'Ceph_pgscup_pool'

分析pve集群,请给出Ceph存储资源池的类别?[答案格式:ABC]

主答案:replicated

ceph osd pool ls detail
root@pve-node1:~# ceph osd pool ls detail
pool 1 '.mgr' replicated size 1 min_size 1 crush_rule 0 object_hash rjenkins pg_num 1 pgp_num 1 autoscale_mode on last_change 532 flags hashpspool stripe_width 0 pg_num_max 32 pg_num_min 1 application mgr read_balance_score 3.03
pool 2 'Ceph_pgscup_pool' replicated size 1 min_size 1 crush_rule 0 object_hash rjenkins pg_num 32 pgp_num 32 autoscale_mode on last_change 531 lfor 0/450/448 flags hashpspool,selfmanaged_snaps stripe_width 0 application rbd read_balance_score 3.03
Ceph_pgscup_pool pool 名称
replicated 副本池
size 1 每个对象只保存 1 份
min_size 1 1 份可用就允许读写
pg_num 32 有 32 个 PG
pgp_num 32 用于放置的 PG 数也是 32
application rbd 该 pool 用于 RBD 块存储
selfmanaged_snaps RBD 快照相关标志
autoscale_mode on PG 自动伸缩开启

PVE Storage 后端类类别是 RBD

分析pve集群,请给出Ceph集群的ID的前8位??[答案格式:a1b2c3d4]

3f28d8bb

cat /etc/ceph/ceph.conf

fsid = 3f28d8bb-e754-475b-b471-b9c97161bbf7

分析pve集群,请给出Ceph存储设置的最小副本数?[答案格式:123]

2

cat /etc/ceph/ceph.conf
ceph osd pool ls detail

分析pve集群,请给出pve集群中虚拟机的快照创建时间?[答案格式:2025-01-11-11:01:01]

2026-04-16-15:05:19

法一:

法二

qm listsnapshot 100
qm config 100
`-> first    2026-04-16 15:05:19    no-description

嵌套虚拟化

node1有嵌套虚拟化 的一个机子 看到是100

需要把这个虚拟化打开

node1中看看100的配置

kvm: 0,也就是禁用了 KVM 硬件虚拟化,QEMU 退回纯软件模拟(TCG);这个时候直接起会发现这个直接崩溃了

CentOS 7 这套老内核(3.10.0-957.el7)在这种模拟硬件组合下,容易触发 APIC/timer 初始化失败。截图里已经给了直接证据:

MP-BIOS bug: 8254 timer not connected to IO-APIC
Kernel panic - not syncing: IO-APIC + timer doesn't work

所以 kvm=1 → 允许内核开启虚拟化,能建虚拟机

设置成1即可

起起来之后发现没办法登录 所以需要绕密:

参考CentOS7 紧急模式恢复 root 密码:超详细步骤(含避坑指南)_centos7重置root密码-CSDN博客

现在好了;但是毕竟他这个主要还是镜像,把ssh连接起起来:

  • 改了 SSH 配置文件:/etc/ssh/sshd_config
  • 具体改动(从备份 diff 核实):
    • PermitRootLogin yes(从注释改为生效)
    • PasswordAuthentication yes(从注释改为生效)
    • ChallengeResponseAuthentication no(从注释改为生效)
    • UseDNS no(从注释改为生效)

然后就可以ssh了

对集群内的服务器进行分析,提取该服务器使用的Linux内核完整版本号?[答案格式:1.2.3-123abc_123]

3.10.0-957.el7.x86_64

原因:

  • 离线盘已确认来宾系统为 CentOS Linux 7 (Core)
  • 虚机配置挂载的是 CentOS-7-x86_64-Minimal-1810.iso
  • CentOS 7.6.1810 的默认内核通常为 3.10.0-957.el7.x86_64
  • 但来宾机在当前环境中反复“可启动/不稳定/端口超时”,未能成功拿到 uname -r 的 live 输出

建议:

  • 这题如果要用于正式提交,最好在 guest SSH 稳定后执行:
uname -r
uname -a
root@pve-node1:~# uname -a
Linux pve-node1 6.17.2-1-pve #1 SMP PREEMPT_DYNAMIC PMX 6.17.2-1 (2025-10-21T11:55Z) x86_64 GNU/Linux

对集群内的服务器进行分析,提取该服务器SSH服务监听的TCP端口号?[答案格式:123]

答案:22

法一:ss -tulnp

法二:

查看方式:

grep -R -n -E "^(Port|ListenAddress)" /etc/ssh/sshd_config*

离线盘关键证据:

  • sshd_configPort 22

对集群内的服务器进行分析,提取该服务器网卡的IP地址?[答案格式:127.0.0.1]

答案:192.168.0.70

法一:

法二:

查看方式:

cat /etc/sysconfig/network-scripts/ifcfg-eth0

关键证据:

IPADDR="192.168.0.70"
PREFIX="24"
GATEWAY="192.168.0.1"

对集群内的服务器进行分析,提取金麟资本理财网站对应的域名?[答案格式:baidu.com]

答案:jlzb.vip

查看方式:

cat /etc/nginx/conf.d/jinqin.conf
server {
    listen 80;
    server_name jlzb.vip;
    root /var/www/html/public;
    index index.php index.html;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }

    location ~ /\.ht {
        deny all;
    }
}

关键证据:

server_name jlzb.vip;
root /var/www/html/public;

对集群内的服务器进行分析,服务器中有个加密工具,请给出该工具的名字?[答案格式:abc_def.sh]

答案:encrypt_tool.py

查看方式:

find / -type f -iname '*encrypt*'
sed -n '1,260p' /root/encrypt_tool.py

关键证据:

  • 文件位于 /root/encrypt_tool.py
  • 内层脚本头部注释明确写着:
    • 加密工具 - 用于服务器取证
    • 适用于数据库备份
[root@localhost ~]# find / -type f -iname '*encrypt*'
/root/.trae-cn-server/bin/stable-fff89fe15d9b570cf2aae145a60174373f4c6f64-debian10/node_modules/@logifier/logger-base/dist/encrypt.js
/root/encrypt_tool.py
/var/www/html/app/Http/Middleware/EncryptCookies.php
/var/www/html/framework-standard-edition/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.crt
/var/www/html/framework-standard-edition/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.key
/var/www/html/framework-standard-edition/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.crt
/var/www/html/framework-standard-edition/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.key
/var/www/html/p2p-lending/source/lending/system/libraries/Encrypt.php
/var/www/html/vendor/laravel/framework/src/Illuminate/Contracts/Encryption/Encrypter.php
/var/www/html/vendor/laravel/framework/src/Illuminate/Contracts/Encryption/EncryptException.php
/var/www/html/vendor/laravel/framework/src/Illuminate/Cookie/Middleware/EncryptCookies.php
/var/www/html/vendor/laravel/framework/src/Illuminate/Encryption/Encrypter.php
/var/www/html/vendor/laravel/framework/src/Illuminate/Encryption/EncryptionServiceProvider.php
/var/www/html/vendor/laravel/framework/src/Illuminate/Session/EncryptedStore.php
/var/www/html/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.crt
/var/www/html/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt.key
/var/www/html/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.crt
/var/www/html/vendor/swiftmailer/swiftmailer/tests/_samples/smime/encrypt2.key
/usr/share/doc/wpa_supplicant-2.6/examples/openCryptoki.conf
/usr/share/doc/pygpgme-0.3/examples/encrypt.py
/usr/share/doc/pygpgme-0.3/tests/test_encrypt_decrypt.py
/usr/share/doc/pecl/zip/examples/encryption.php
/usr/share/mime/application/pgp-encrypted.xml
/usr/share/mime/multipart/encrypted.xml

/root/encrypt_tool.py

用binwalk一下这个文件

发现了一个gz

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
加密工具 - 用于服务器取证
适用于数据库备份

加密层次:
  第1层: XOR加密 (密钥: 0x5A, 位置偏移 i%256)
  第2层: Base64编码
  第3层: 字符替换表 (ABCD...+/ -> ZYXW...+/)
  第4层: 十六进制转换

用法:
  python encrypt_tool.py --input <文件路径> --output <输出路径>
  python encrypt_tool.py <输入路径> <输出路径>
  python encrypt_tool.py --db --output <输出路径>
"""

import os
import sys
import base64
import gzip
import subprocess
import argparse

try:
    import codecs
    def read_file(path):
        with codecs.open(path, 'r', encoding='utf-8') as f:
            return f.read()
    def write_file(path, content):
        with codecs.open(path, 'w', encoding='utf-8') as f:
            f.write(content)
except ImportError:
    # Python 2
    def read_file(path):
        with open(path, 'rb') as f:
            return f.read().decode('utf-8')
    def write_file(path, content):
        with open(path, 'wb') as f:
            f.write(content.encode('utf-8'))

XOR_KEY = 0x5A
BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
CUSTOM_TABLE = "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba9876543210+/"


def xor_encrypt(data):
    """第1层: XOR加密"""
    result = []
    for i, c in enumerate(data):
        result.append(chr(ord(c) ^ (XOR_KEY + i) % 256))
    return ''.join(result)


def char_swap_encode(data):
    """第3层: 字符替换编码"""
    trans = str.maketrans(BASE64_TABLE, CUSTOM_TABLE)
    return data.translate(trans)


def obfuscate(data):
    """4层混淆加密"""
    step1 = xor_encrypt(data)
    step2 = base64.b64encode(step1.encode('utf-8')).decode('ascii')
    step3 = char_swap_encode(step2)
    step4 = step3.encode('utf-8').hex()
    return step4


def encrypt_file(input_path, output_path):
    """加密目标文件"""
    content = read_file(input_path)
    obfuscated = obfuscate(content)
    write_file(output_path, obfuscated)
    print("[OK] %s -> %s" % (input_path, output_path))


def main():
    is_db = '--db' in sys.argv

    # 参数位置判断
    if len(sys.argv) >= 3 and not sys.argv[1].startswith('-'):
        input_path = sys.argv[1]
        output_path = sys.argv[2]
    else:
        parser = argparse.ArgumentParser(description='加密文件加密工具')
        parser.add_argument('--input', '-i', help='输入文件路径')
        parser.add_argument('--output', '-o', help='输出文件路径')
        parser.add_argument('--db', action='store_true', help='数据库备份模式')
        args = parser.parse_args()

        input_path = args.input if not args.db else None
        output_path = args.output
        is_db = args.db

    print("=" * 60)
    print("  数据库文件加密工具")
    print("=" * 60)
    print("")

    if is_db:
        db_user = 'root'
        db_pass = 'pgscup@o26'
        db_name = 'jinqin'
        password = 'JDSJ2026@Backup'

        print("[*] 正在备份数据库...")
        print("    数据库: %s" % db_name)
        print("    输出: %s" % output_path)
        print("")

        try:
            # 步骤1: mysqldump -> 临时gz文件
            temp_sql = '/tmp/backup_temp.sql'
            dump_cmd = 'mysqldump -uroot -p"pgscup@o26" --single-transaction --quick %s > %s' % (db_name, temp_sql)
            print("[*] 执行mysqldump...")
            ret = os.system(dump_cmd)
            if ret != 0:
                print("[ERROR] mysqldump失败, 返回码: %d" % ret)
                sys.exit(1)
            print("[OK] mysqldump完成")

            # 步骤2: gzip压缩
            temp_gz = '/tmp/backup_temp.sql.gz'
            gzip_cmd = 'gzip -9 -c < %s > %s' % (temp_sql, temp_gz)
            print("[*] 执行gzip压缩...")
            ret = os.system(gzip_cmd)
            if ret != 0:
                print("[ERROR] gzip失败, 返回码: %d" % ret)
                os.remove(temp_sql)
                sys.exit(1)
            print("[OK] gzip压缩完成")
            os.remove(temp_sql)

            # 步骤3: openssl加密 (去掉-pbkdf2选项,兼容老版本openssl)
            print("[*] 执行openssl加密...")
            openssl_cmd = 'openssl aes-256-cbc -salt -pass pass:%s -in %s -out %s' % (password, temp_gz, output_path)
            ret = os.system(openssl_cmd)
            if ret != 0:
                print("[ERROR] openssl失败, 返回码: %d" % ret)
                os.remove(temp_gz)
                sys.exit(1)
            print("[OK] openssl加密完成")
            os.remove(temp_gz)

            size = os.path.getsize(output_path)
            print("")
            print("[OK] 完成: %s (%.2f MB)" % (output_path, size/1024/1024))
            print("")
            print("[INFO] 数据库备份密码: %s" % password)

        except Exception as e:
            print("[ERROR] %s" % str(e))
            sys.exit(1)

    else:
        if not input_path or not output_path:
            print("[ERROR] 请指定输入和输出文件路径")
            print("用法: python encrypt_tool.py --input <文件> --output <输出>")
            sys.exit(1)

        if not os.path.exists(input_path):
            print("[ERROR] 文件不存在: %s" % input_path)
            sys.exit(1)

        parent_dir = os.path.dirname(output_path)
        if parent_dir and not os.path.exists(parent_dir):
            os.makedirs(parent_dir)

        encrypt_file(input_path, output_path)
        print("")
        print("[OK] 加密完成")


if __name__ == "__main__":
    main()

看前面的注释就能发现就这个文件

对集群内的服务器进行分析,服务器中加密工具在加密数据库备份文件时使用的密码是什么?[答案格式:ABC@123]

答案:JDSJ2026@Backup

上面的py中有

另外,file /tmp/encrypted_backup/jinqin_backup.sql.gz.enc 也确认该文件为 openssl enc'd data with salted password

对集群内的服务器进行分析,服务器中加密工具第1层加密的XOR密钥是什么?[答案格式:按实际填写]

答案:0x5A

对集群内的服务器进行分析,给出MySQL数据库root用户的密码?[答案格式:abc@123]

答案:pgscup@o26

上面的py里有

以下是ai给我证据:

  1. 反解 .env.obf 得到:
DB_USERNAME=root
DB_PASSWORD=pgscup@o26
  1. 备份脚本:
mysqldump -uroot -ppgscup@o26 jinqin > /tmp/jinqin_backup.sql
  1. 大量 /tmp/*.php 取证脚本都使用:
new mysqli("127.0.0.1", "root", "pgscup@o26", "jinqin");

起前端网页服务

ssh -o StrictHostKeyChecking=no -T root@192.168.0.50 "rbd export --export-format 1 Ceph_pgscup_pool/vm-100-disk-0 -" > "~\服务器\100\vm100-current.raw"

导出镜像、导入到火眼中,后面有用。

<font style="color:rgb(0, 0, 0);background-color:rgba(0, 0, 0, 0);">9000</font>:PHP 服务默认端口→ Nginx 自己不执行 PHP,交给专门的 PHP 服务处理 ;然而都没有9000端口的服务;所以php相关服务需要起一下;127.0.0.1:9000 通常是 php-fpm 的监听地址

systemctl start php-fpm
systemctl status php-fpm

这个时候再访问是500

php-fpm 起了以后,首页变成 500 Internal Server Error;看 Laravel的变成日志 日志:

tail -n 50 /var/www/html/storage/logs/laravel.log
[2026-04-16 17:57:42] production.ERROR: No application encryption key has been specified. {"exception":"[object] (RuntimeException(code: 0): No application encryption key has been specified. at /var/www/html/vendor/laravel/framework/src/Illuminate/Encryption/EncryptionServiceProvider.php:42)
[stacktrace]
#0 /var/www/html/vendor/laravel/framework/src/Illuminate/Support/helpers.php(1038): Illuminate\\Encryption\\EncryptionServiceProvider->Illuminate\\Encryption\\{closure}(NULL)
#1 /var/www/html/vendor/laravel/framework/src/Illuminate/Encryption/EncryptionServiceProvider.php(46): tap(NULL, Object(Closure))
....

No application encryption key has been specified.

说明/var/www/html/.env 不存在,现场只有 .env.obf;这个项目把真实 .env 做了自定义混淆:

尝试用encrypt_tool.py写个解密代码跑一下(借助一下ai):

.env.obf 的正向加密顺序是:

  • 第1层:XOR
  • 第2层:Base64
  • 第3层:自定义字符表替换
  • 第4层:Hex

所以解密就反过来:

  • Hex -> 文本
  • 替换表反向恢复
  • Base64 解码
  • XOR 还原

100 上直接跑这个就能把 .env.obf 打印出来:

python3 - <<'PY'
import base64
from pathlib import Path

XOR_KEY = 0x5A
BASE64_TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
CUSTOM_TABLE = "ZYXWVUTSRQPONMLKJIHGFEDCBAzyxwvutsrqponmlkjihgfedcba9876543210+/"

hexdata = Path('/var/www/html/.env.obf').read_text().strip()

# step4 逆:hex -> step3
step3 = bytes.fromhex(hexdata).decode('utf-8')

# step3 逆:CUSTOM_TABLE -> BASE64_TABLE
trans = str.maketrans(CUSTOM_TABLE, BASE64_TABLE)
step2 = step3.translate(trans)

# step2 逆:base64 -> step1
step1 = base64.b64decode(step2).decode('utf-8')

# step1 逆:XOR
plain = ''.join(chr(ord(c) ^ ((XOR_KEY + i) % 256)) for i, c in enumerate(step1))

print(plain)
PY

结果如下:

APP_NAME=金鳞资本
APP_ENV=local
APP_KEY=base64:QmhkrWMLYbZsQkINFr5Jd1eNiDEVduTbfSNlotS+rWI=
APP_DEBUG=true
APP_URL=http://192.168.0.70

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=jinqin
DB_USERNAME=root
DB_PASSWORD=pgscup@o26

BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=database
QUEUE_CONNECTION=sync

恢复好之后放回去。恢复 .env 后,再看日志,新的报错是:

[2026-05-12 17:33:11] local.ERROR: SQLSTATE[HY000] [1049] Unknown database 'jinqin' {"exception":"[object] (Doctrine\\DBAL\\Driver\\PDOException(code: 1049): SQLSTATE[HY000] [1049] Unknown database 'jinqin' at /var/www/html/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:31, PDOException(code: 1049): SQLSTATE[HY000] [1049] Unknown database 'jinqin' at /var/www/html/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOConnection.php:27)
[stacktrace]
#0 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php(64): Doctrine\\DBAL\\Driver\\PDOConnection->__construct('mysql:host=127....', 'root', 'pgscup@o26', Array)
#1 /var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connectors/Connector.php(43): Illuminate\\Database\\Connectors\\Connector->createPdoConnection('mysql:host=127....', 'root', 'pgscup@o26', Array)

Unknown database 'jinqin'

说明:MariaDB 服务是起来的;但应用要连的库 jinqin 不存在;找到备份文件

导入火眼的目的是找到这个jinqin的备份数据库;依然是前面的加密算法做的备份,所以可以把改备份解密;以下是解密代码:

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
decrypt_db_backup.py

用于解密 encrypt_tool.py --db 生成的数据库备份文件。

原始加密方式:
  mysqldump -> .sql
  gzip -> .sql.gz
  openssl aes-256-cbc -salt -pass pass:<password> -in .sql.gz -out .enc

解密流程:
  .enc -> openssl aes-256-cbc -d -> .sql.gz -> gzip -> .sql

用法:
  python decrypt_db_backup.py -i jinqin_backup.sql.gz.enc -o jinqin_backup.sql --password '你的备份密码'

也可以只解出 gzip:
  python decrypt_db_backup.py -i jinqin_backup.sql.gz.enc --gz-out jinqin_backup.sql.gz --password '你的备份密码'
"""

import os
import sys
import gzip
import argparse
import subprocess
import tempfile


def run_openssl_decrypt(input_path, gz_output_path, password, md=None):
    """
    调用 openssl 解密 aes-256-cbc。

    md:
      None    使用当前 openssl 默认摘要算法
      md5     兼容老版本 openssl
      sha256  兼容新版本 openssl 常见默认行为
    """
    cmd = [
        "openssl",
        "aes-256-cbc",
        "-d",
        "-salt",
        "-pass",
        "pass:%s" % password,
        "-in",
        input_path,
        "-out",
        gz_output_path,
    ]

    if md:
        cmd.extend(["-md", md])

    proc = subprocess.run(
        cmd,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        text=True,
    )

    if proc.returncode != 0:
        raise RuntimeError(proc.stderr.strip() or "openssl 解密失败")


def gzip_decompress(gz_path, sql_output_path):
    """
    解压 .sql.gz 为 .sql。
    """
    with gzip.open(gz_path, "rb") as f_in:
        with open(sql_output_path, "wb") as f_out:
            while True:
                chunk = f_in.read(1024 * 1024)
                if not chunk:
                    break
                f_out.write(chunk)


def decrypt_backup(input_path, sql_output_path=None, gz_output_path=None, password=None):
    if not os.path.exists(input_path):
        raise FileNotFoundError("输入文件不存在: %s" % input_path)

    if not password:
        raise ValueError("必须提供备份密码")

    if not sql_output_path and not gz_output_path:
        raise ValueError("必须指定 --output 或 --gz-out")

    temp_gz = None

    try:
        if gz_output_path:
            gz_path = gz_output_path
        else:
            fd, temp_gz = tempfile.mkstemp(suffix=".sql.gz")
            os.close(fd)
            gz_path = temp_gz

        parent_dir = os.path.dirname(gz_path)
        if parent_dir and not os.path.exists(parent_dir):
            os.makedirs(parent_dir)

        # 依次尝试几种 OpenSSL 派生摘要。
        # 因为不同 OpenSSL 版本默认 md 可能不同。
        last_error = None
        tried = [None, "md5", "sha256"]

        for md in tried:
            try:
                print("[*] 尝试 openssl 解密,md=%s" % (md or "default"))
                run_openssl_decrypt(input_path, gz_path, password, md=md)

                # 验证是否是合法 gzip
                with gzip.open(gz_path, "rb") as test:
                    test.read(1)

                print("[OK] openssl 解密成功,md=%s" % (md or "default"))
                last_error = None
                break

            except Exception as e:
                last_error = e
                if os.path.exists(gz_path):
                    try:
                        os.remove(gz_path)
                    except Exception:
                        pass

        if last_error:
            raise RuntimeError("所有 openssl 解密方式都失败,最后错误: %s" % last_error)

        if sql_output_path:
            parent_dir = os.path.dirname(sql_output_path)
            if parent_dir and not os.path.exists(parent_dir):
                os.makedirs(parent_dir)

            print("[*] 正在 gzip 解压...")
            gzip_decompress(gz_path, sql_output_path)
            print("[OK] SQL 文件已生成: %s" % sql_output_path)

        if gz_output_path:
            print("[OK] gzip 文件已生成: %s" % gz_output_path)

    finally:
        if temp_gz and os.path.exists(temp_gz):
            os.remove(temp_gz)


def main():
    parser = argparse.ArgumentParser(description="解密 OpenSSL AES-256-CBC 数据库备份")
    parser.add_argument("-i", "--input", required=True, help="输入 .enc 文件路径")
    parser.add_argument("-o", "--output", help="输出 .sql 文件路径")
    parser.add_argument("--gz-out", help="输出 .sql.gz 文件路径")
    parser.add_argument("--password", help="备份密码,也可用环境变量 BACKUP_PASSWORD")

    args = parser.parse_args()

    password = args.password or os.environ.get("BACKUP_PASSWORD")

    try:
        decrypt_backup(
            input_path=args.input,
            sql_output_path=args.output,
            gz_output_path=args.gz_out,
            password=password,
        )
    except Exception as e:
        print("[ERROR] %s" % e)
        sys.exit(1)


if __name__ == "__main__":
    main()

python decrypt_db_backup.py \
  -i jinqin_backup.sql.gz.enc \
  -o jinqin_backup.sql \
  --password 'JDSJ2026@Backup'

导入即可:

#新建 jinqin 库
mysql -uroot -ppgscup@o26 -e "CREATE DATABASE jinqin CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
#导入库
mysql -uroot -ppgscup@o26 jinqin < /var/www/html/jinqin.sql

接下来我们在看网页端就好了

mysql运行中 结合前面的账密用ssh隧道连一下

对集群内的服务器进行分析,请给出网站后台数据库中存放聊天记录的数据表名字?[答案格式:adb_def]

答案:user_chat

同时也能在/var/www/html/app/UserChat.php中看到

protected $table = 'user_chat';

对集群内的服务器进行分析,分析网站后台用户密码加密算法中type=0时的初始盐值是什么[答案格式:ABC]

答案:ABCDEFG

全局搜一下找到合适的文件:/var/www/html/app/Users.php

    public static function MakePassword($password, $type = 0)
    {
        if ($type == 0) {
            $salt = 'ABCDEFG';
            $passwordChars = str_split($password);
            foreach ($passwordChars as $char) {
                $salt .= md5($char);
            }
        } else {
            $salt = 'TPSHOP' . $password;
        }
        return md5($salt);
    }

if ($type == 0) {

        $salt = '`ABCDEFG`';

对集群内的服务器进行应用取证,提取该Laravel应用的APP_KEY值的后8位?[答案格式:英文数字混合字符串]

前面解密的env

APP_NAME=金鳞资本
APP_ENV=local
APP_KEY=base64:QmhkrWMLYbZsQkINFr5Jd1eNiDEVduTbfSNlotS+rWI=
APP_DEBUG=true
APP_URL=http://192.168.0.70

LOG_CHANNEL=stack

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=jinqin
DB_USERNAME=root
DB_PASSWORD=pgscup@o26

BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=database
QUEUE_CONNECTION=sync

对集群内的服务器进行取证分析,金麟资本理财网站后台有多少个机器人?[答案格式:123]

3

数据库可以看得到,3个

对集群内的服务器进行资金流水取证,提取该平台数据库中聊天记录总数?[答案格式:123]

11494

数据多的话这个很不稳定,截图是11340,刷新一下又变了;所以尽量还是用sql语句查

select COUNT(*) as count from user_chat;

对集群内的服务器进行数据库取证,提取该平台数据库中注册用户总记录数?[答案格式:123]

答案:21679

SELECT COUNT(*) as cnt FROM users;

对集群内的服务器进行取证分析,提取平台内用户季丽华的sfz号?[答案格式:18位sfz]

3701*****436(发公众号会被ban)

select * from user_real where name = '季丽华';

后台

/var/www/html/routes/web.php

~/admin/login

前面的/var/www/html/app/Users.php中有提到相关加密算法

if ($type == 0) {
    $salt = 'ABCDEFG';
    foreach ($passwordChars as $char) {
        $salt .= md5($char);
    }
    return md5($salt);
}

结合数据库

要么是修改这个数据的内容,要么是反推(用弱口令爆破);这里弱口令爆破出来密码是admin123

对集群内的服务器进行数据库取证,提取该平台数据库中注册用户总记录数?[答案格式:123](不确定)

21699后续有答案会补充

直接查会踩坑,没有加机器人的数量

对集群内的服务器进行资金流水取证,提取该平台数据库中钱包流水金额第二大的用户名字?[答案格式:张三]

林斌

看 wallet_log 表里的钱包流水,change 就是每笔钱包流水的金额变化;

因为题目问“流水金额大”,通常看的是流水规模,不区分流入还是流出,所以把正负号去掉,统计绝对值总和;

按 user_id 分组,同时排除 user_id = 0 这种系统记录

ur.name IS NOT NULL AND ur.name <> ''排除没有实名名字的记录

SELECT wl.user_id, ur.name, SUM(ABS(wl.`change`)) AS total
FROM wallet_log wl
LEFT JOIN user_real ur ON ur.user_id = wl.user_id
WHERE wl.user_id > 0
  AND ur.name IS NOT NULL
  AND ur.name <> ''
GROUP BY wl.user_id, ur.name
ORDER BY total DESC, wl.user_id ASC
LIMIT 10;

对集群内的服务器进行数据库取证,提取该平台法币交易中交易笔数最多的卖家的交易笔数?[答案格式:123]

存疑 1267后续有答案会补充

<font style="color:rgb(26, 28, 31);">legal_deal</font>表里的每一条法币交易记录,如果笔数相同,再按 seller_id 从小到大排,保证结果稳定;c2c_deal 是另一组 C2C 交易记录

SELECT seller_id, COUNT(*) AS cnt
FROM c2c_deal
GROUP BY seller_id
ORDER BY cnt DESC, seller_id ASC
LIMIT 5;

对集群内的服务器进行资金流水取证,提取该平台已完成结算的杠杆交易中保证金总额最多的用户的保证金总额?[答案格式:100.00]

存疑 37240.76 后续有答案会补充

源码里 status = 3 对应 CLOSED,也就是“已平仓/已完成”;把该用户所有已完成杠杆单的 caution_money 加总

SELECT user_id, SUM(caution_money) AS total_margin
FROM lever_transaction
WHERE status = 3
GROUP BY user_id
ORDER BY total_margin DESC, user_id ASC
LIMIT 5;

对集群内的服务器进行资金流水取证,提取该平台商家中余额最小的商家的手机号?[答案格式:18036310808]

15860623709

看 seller 表,按 seller_balance 从小到大排

SELECT user_id, mobile, seller_balance
FROM seller
ORDER BY seller_balance ASC, id ASC
LIMIT 5;

对集群内的服务器进行资金流水取证,提取该平台商家中余额最小的商家的余额?[答案格式:100.0]

8461.4

逻辑同上题

SELECT user_id, mobile, seller_balance
FROM seller
ORDER BY seller_balance ASC, id ASC
LIMIT 5;

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐