看来大部分的个人团队双休的比赛个人赛都不会下很狠的手。

计算机取证

1. 计算机中曾挂载的Bitlocker加密分区的恢复密钥后6位为?(答案格式:6位数字)

700755

2. 请写出曾远程连接过该计算机的IP;(答案格式:6.6.6.6)

192.168.50.227

3. 计算机中曾挂载的vhd非加密分区驱动器号为?(答案格式:大写,如D)

4. 接上题,分区中最后修改时间的文件MD5值为?(答案格式:全大写)

为啥这个会卡住

0A7152C5AA002A3D65DC5C5C5FAAB868

5. 请找到计算机中的Veracrypt加密容器,并写出其解密密码?(答案格式:字母大小写与实际需一致)

这道题考了嵌套检材:

一个方法是可以看到这里压缩文件里面有个超大的备份文件

另一个办法是可以看到这里有个超大文件

查了一下这玩意是夜神模拟器的备份文件。。

火眼直接能识别成压缩文件,然后扔到火眼中去即可:

聊天记录的图片有:1P2P3$$pian5p6p78pian

6. 请写出IP为202.113.81.243的发件人向机主发送的邮件附件MD5值;(答案格式:全大写)

一共涉及三个,第一个没附件,第二个两个附件,所以做题角度肯定只有第三个 附件是一个rar

7. 计算机中Will Wight - Cradle Series (Books 1-12)- MOBI.torrent文件的下载地址为?(答案格式:http://…)

先找到文件

然后依照多年下载经验,肯定是在浏览器里面下的

[http://suprbaydvdcaynfo4dgdzgxb4zuso7rftlil5yg5kqjefnw4wq4ulcad.onion/attachment.php?aid=4130](http://suprbaydvdcaynfo4dgdzgxb4zuso7rftlil5yg5kqjefnw4wq4ulcad.onion/attachment.php?aid=4130)

8. 计算机中lqrazqq016j41.jpg文件的删除时间为?(UTC+0800)(答案格式:1990-01-01 01:01:01)

2024-11-09 21:59:48

9. Fikret Ceker曾经向机主发送过一张照片,请找到该图片写出其拍摄的GPS坐标;(答案格式:保留小数点后4位,如33.3333N,33.3333E)

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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# -*- coding: utf-8 -*-
"""
把 “度;分;秒” 坐标转换为十进制度,并自动添加 N/E/S/W 标记。
"""

def dms_to_dd(s: str) -> float:
""" "度;分;秒" → 十进制度 """
# 统一分隔符,去掉空格,再拆分
parts = [p for p in s.replace(';', ';').replace(',', ';').split(';') if p.strip()]
deg, minute, sec = map(float, parts) # 直接转 float
return deg + minute / 60.0 + sec / 3600.0 # 十进制度公式


def dd_with_dir(value: float, is_lat: bool) -> str:
"""
把十进制度数值转换为 “数值° 方向” 的字符串。

参数
----
value : 十进制度(正数或负数)
is_lat : True → 处理纬度,False → 处理经度

返回
----
如 "40.0112° N"、"-112.7001° W" → "112.7001° W"
"""
# 方向决定
if is_lat: # 纬度
direction = 'N' if value >= 0 else 'S'
else: # 经度
direction = 'E' if value >= 0 else 'W'

# 取绝对值后拼接
return f"{abs(value):.12f}° {direction}"


# ------------------- 示例 -------------------
if __name__ == '__main__':
# 你的原始数据(可以自行改成其它字符串)
lat_raw = "40;0;40.3800000000046566"
lon_raw = "112; 42; 0.289999999978931555"

# 转换
lat_dd = dms_to_dd(lat_raw)
lon_dd = dms_to_dd(lon_raw)

# 自动加方向标记
lat_str = dd_with_dir(lat_dd, is_lat=True)
lon_str = dd_with_dir(lon_dd, is_lat=False)

print(f"Latitude : {lat_str}")
print(f"Longitude : {lon_str}")

Latitude : 40.0112N16666667°

Longitude : 112.7000E80555556°变成112.7001E

10. 计算机中用户“李四”在最后一次成功登录之前登录失败了多少次?(答案格式:纯数字)

6

手机取证

1. 分析手机检材,写出苹果手机的序列号是多少?(答案格式:大小写与实际需一致)

FK3XDN2UKPJ5

2. 分析手机检材,写出嫌疑人facebook账号的密码是多少?(答案格式:大小写与实际需一致)

1234qwer

3. 分析手机检材,下列哪些地址是嫌疑人曾经去过的? (2.0分)

A. 南宁市清秀区 B. 南宁市江南区 C. 济南市历城区 D. 上海市松江区 E. 上海市宝山区

从地图上来看除开松江没去以外,其他都去了(吐槽一点火眼没有区这个标签。。)

4. 分析手机检材,嫌疑人安装了用于记账的APP,请问该APP的包名是什么?(答案格式:com.abc.abc)

com.maicai.freejizhang

?5. 分析手机检材,嫌疑人记账APP中记录的使用支付宝支付的用于礼金红包的金额一共是多少?(答案格式:请写整数金额,如1230元)

从火眼自带分析中跳转到数据库

发现支付宝uuid是12

我合理怀疑是弘连是这个比赛之后才加上的这个软件的分析的。。因为去年的wp写个题目还没有这个软件分析

找到这个对应的数据库之后,看对应的typeid=1701的就是礼金,如果说今年的数证杯还有新的软件的话还是要翻一翻数据库、注意价格的合理性(这里是按照打车去机场=15900这个来看,价格合理是159元,但是还是想吐槽一下这个密室花了2000+比较贵啊,也可能是很多人一起玩。。)

170000

?6. 分析手机检材,嫌疑人家里路由器密码是多少?(答案格式:大小写与实际需一致)

法一:爆搜“路由器”

法二:

从知道

这是一个笔记软件,这里可以知道

至于没有去看自带的备忘录原因是这个:

一眼其他都没文件啊

7. 分析手机检材,写出嫌疑人最新家庭地址;(答案格式:XX市XX区XX路XX弄)

上海市浦东新区张杨北路 2899 弄

?8. 分析手机检材,嫌疑人团伙走私的“大麻”的单价是每克多少元?(答案格式:XX元/克)

第一遍做的时候其实有想到聊天里面的照片有藏东西,结果真有的。。

foremost一下

首先用txt打开发现最后有个

结合一下ai的回复,试着用表格打开,输入密码(mm20241105)就能发现价格了:

344

码一下吧 到把我ban了

服务器取证

参考:

【2024-数证杯】决赛_个人赛(服务器)_2024数证杯-CSDN博客

这位老师写的很好。

netstat -natp 是一个用于查看系统网络连接状态的命令

1. 重建完整的系统后,redis对外暴露的端口号是多少?(答案格式:数字)

16379

2. 请找出加密mysql数据库连接密码所用的加密密钥(盐值)?(答案格式:注意大小写)

分析题目这个需要找到源码的配置,从上题得出有docker其中运行着一个jdk环境进入容器中先查看一下历史命令他做了什么操作

进入正在运行的 Docker(id=79d2dfa52a5e,jdk) 容器内部,开启一个交互式的 Bash 终端会话:

docker exec -it 79d2dfa52a5e /bin/bash,然后再看history(终端命令历史)

这里的命令是进入到了/home/date/s048文件夹中

所以访问一下:

我们可以解析.jar和.yml配置文件

看一下这里的yml文件:

看得出密码是加密过的,所以加密信息在jar包中

现很多功能都是在zwz目录下面实现的,所以我们分析jar包时可以着重看zwz目录,最终就能找到这个内容

F*DZ-kZMs5qt

找配置文件的办法其实还有一个:docker inspect + id

docker inspect 79d2dfa52a5e

能看到配置的目录

3. 请分析得出相亲网站的后台数据库中哪张表存放了会员相关信息,写出表名? (6.0分)

可以搜“table”/“会员”等等

直接搜索“会员”,能看到对应的table:a_member_st

4. 已知用户在系统中的所有操作都会被记录,请找出用户在“查询角色”时,其请求的后端路径地址为?(格式:/api/query/…)

我现在要用前面的盐值对加密的密文解密,所以在jar包中找解密函数:

分析一下:

1
2
3
4
5
6
7
8
9
10
11
12
// 必需参数:要解密的字符串和密钥
private static final String[][] VALID_REQUIRED_ARGUMENTS = {
new String[]{"input"},
new String[]{UsernamePasswordAuthenticationFilter.SPRING_SECURITY_FORM_PASSWORD_KEY} // 实际值为"password"
};

// 可选参数
private static final String[][] VALID_OPTIONAL_ARGUMENTS = {
new String[]{"verbose"}, new String[]{"algorithm"},
new String[]{"keyObtentionIterations"}, new String[]{"saltGeneratorClassName"},
// ... 更多加密配置参数
};

跟踪SPRING_SECURITY_FORM_PASSWORD_KEY发现结果是password字段

所以为了恢复yml中的加密字段,有两种办法:

一个是创建java项目(可是我不会)参见:

【2024-数证杯】决赛_个人赛(服务器)_2024数证杯-CSDN博客

另外一个就是用指令:

首先看一下这个解密函数的依赖包

将原jar包改后缀为zip之后解压,找到BOOT-INF/lib/jasypt-1.9.3.jar

用终端

1
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI  input="ij+NuXpx6CZwYB1oGHA2M2E2na0G8Tux"  password="F*DZ-kZMs5qt"
1
2
3
4
5
6
7
8
9
----ENVIRONMENT-----------------
Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 25+37-LTS-3491

----ARGUMENTS-------------------
input: ij+NuXpx6CZwYB1oGHA2M2E2na0G8Tux
password: F*DZ-kZMs5qt

----OUTPUT----------------------
mA0:xA0^

至此获得了admin的数据库的密码。

还有另外一个root的:

1
java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringDecryptionCLI  input="064l9Wwf9KjXlSz0phcwvg+R5xwzCNl7"  password="F*DZ-kZMs5qt"
1
2
3
4
5
6
7
8
9
----ENVIRONMENT-----------------
Runtime: Oracle Corporation Java HotSpot(TM) 64-Bit Server VM 25+37-LTS-3491

----ARGUMENTS-------------------
input: 064l9Wwf9KjXlSz0phcwvg+R5xwzCNl7
password: F*DZ-kZMs5qt

----OUTPUT----------------------
kidsk&klf^rv

然后再通过隧道连接mysql数据库:

首先找到监听端口

再用navicat连接,使用ssh

注意常规这里的主机地址:

172.19.0.2

也可以用这个指令docker inspect mysql | grep IPAddress

即可连接。终于到数据库查询阶段了

/zwz/role/getAllByPage

5. 请分析得出数据库用户表中status为-1状态值的含义为?(格式:学生)

先找到这里

说实话有点难找 有很多。。

禁用

6. 请统计平均月均收入第二高的省份(省份包含三大类:省、直辖市、自治区)(答案格式:请写出完整的省份名(或直辖市名、自治区名),如江西省、天津市、西藏自治区)

这里有两个数据库,这里打开第二个数据库

找到数据库中对应的数据,让ai跑一个sql查询语句,

1
sql查询语句:database=blind_date2,table=a_member_st中address列中把地址的省份解析出来(只读address列的每条数据的前两个字作为省份),解析出来之后,算出同一省份的“income”列的平均值,排序
1
2
3
4
5
6
7
8
9
SELECT
SUBSTR(address, 1, 2) AS province, -- 解析省份,取address的前两个字
AVG(income) AS average_income -- 计算同一省份的平均收入
FROM
a_member_st
GROUP BY
province -- 按省份分组
ORDER BY
average_income DESC; -- 按平均收入降序排序

这里用到了优化算法:取address前两位作为省份

内蒙古自治区

后面有空了试试把服务器搭建起来

程序功能分析

1. 分析APK检材,请问程序申请了几项系统权限?(答案格式:6)

4

2. 分析APK检材,请写出程序的入口邀请码;(答案格式:与实际大小写保持一致)

可以看到这里有isString检验,但是没有再java代码中,所以转到libc库中看:

能找到对应的函数:

这里部分是邀请码检验的具体步骤,比较的是ascii码,附上对照表:

细看一下这里是先检验了偏移量1,然后是3,然后再是2,所以这里1是A,3是B,2是C(试了一下各种本地AI跑出来都是ABCDEF,在线AI一跑就出来了)

据此可以知道邀请码是ACBDEF

3. 分析APK检材,该程序进行恶意行为时保存的文件使用的加密算法及加密模式是?(答案格式:大写,如XXX-XXX)

4. 分析APK检材,该程序进行恶意行为时保存的文件使用的加密密钥是?(答案格式:与实际大小写保持一致)

其实在分析第2题的时候能看到函数表中有另外一个函数,且跟isString的函数名字很像,所以应该是有用的

到动态库中找:

1
2
3
4
5
6
7
8
9
10
11
12
13
__int64 __fastcall Java_com_example_gallery_GalleryActivity_stringFromJNI(__int64 _0123456789abcdef0123456789abcdef)
{
char *_0123456789abcdef0123456789abcdef_1; // rbx
__int64 v2; // r14

_0123456789abcdef0123456789abcdef_1 = (char *)operator new(0x28u);
strcpy(_0123456789abcdef0123456789abcdef_1, "0123456789abcdef0123456789abcdef");
v2 = (*(__int64 (__fastcall **)(__int64, char *))(*(_QWORD *)_0123456789abcdef0123456789abcdef + 1336LL))(
_0123456789abcdef0123456789abcdef,
_0123456789abcdef0123456789abcdef_1);
operator delete(_0123456789abcdef0123456789abcdef_1);
return v2;
}

0123456789abcdef0123456789abcdef

5. 分析APK检材,该程序上传文件的服务器通信URL是多少?(答案格式:https://xxxx/xx/xx)

[https://biwuzhuanyongurl.com/upload](https://biwuzhuanyongurl.com/upload)

?6. 分析APK检材,以下哪个是该程序存在的恶意行为? (1.0分)

A. 偷偷调用前置摄像头拍照并上传图片至服务器
B. 偷偷调用后置摄像头拍照并上传图片至服务器
C. 后台偷偷录音并上传音频至服务器
D. 偷偷获取通讯录信息并上传服务器
E. 偷偷获取短信信息并上传服务器

查字段front、camerah

网络流量分析(详见流量包专题)

流量包专题

数据分析

1. 分析数据库检材,该数据库中会员姓名包含“强”字的会员数量为多少?(答案格式:纯数字)

法一:

1
2
SELECT * FROM member 
WHERE username LIKE '%强%';

法二:导出wps

2945

2. 属于会员id“89378”的直接下级用户数为多少?(答案格式:纯数字)

观察一下这里有个parentid列,也就是上级id列,所以再在上级id列查89378即可

法一:

1
2
SELECT * FROM member 
WHERE parentid LIKE '89378';

法二:wps上级id列筛选89378

11

3. 请计算每名会员的总返佣金额,写出总返佣金额最大的会员id;(答案格式:纯数字)

猜想1:最后一次出现的newblance就是总佣金
1
mysql数据库中,salary表中,按照时间先后(即creationtime从小到大)读取每条数据,记录下该条数据的userid和newblance的数据,当userid相同时,更新他们newblance列的数据,最后按照newblance列从高到低排序
1
2
3
4
5
6
7
8
9
10
SELECT userid, newblance
FROM (
SELECT
userid,
newblance,
ROW_NUMBER() OVER (PARTITION BY userid ORDER BY creationtime DESC) AS rn
FROM salary
) AS sub
WHERE rn = 1
ORDER BY newblance DESC;

16321057

猜想2:newblance之和最大
1
mysql数据库中,salary表中,读取每条数据,当userid相同时,将他们newblance列数据相加,最后按照newblance列相加的数据从高到低排序
1
2
3
4
SELECT userid, SUM(newblance) AS total_newblance
FROM salary
GROUP BY userid
ORDER BY total_newblance DESC;

35775530

以上猜想都不对,实际上new-old之和最大才行。
1
mysql数据库中,salary表中,读取每条数据将他们newblance列数据减去oldblance列,当userid相同时,将他们相减后的数据相加,最后按照该数据从高到低排序
1
2
3
4
5
6
7
8
9
10
SELECT 
userid,
SUM(newblance - oldblance) AS total_diff
FROM
salary
GROUP BY
userid
ORDER BY
total_diff DESC;

87314

吐槽:这个跟四川警校那个有的一拼,列表很多不说清楚,只能猜。四川那个更甚。

4. 计算在2023年5月1日到2024年5月30日之间(包含5月1日和5月30日),总提现金额大于1000的用户数量;(答案格式:纯数字)

注意时间范围,时间戳编码:

1682870400000-1717084800000

1702030794000

1717084800

1
mysql数据库中,withdraw表中,读取每条数据,当withdrawid相同、时间creationtime列在1682870400000-1717084800000之间时,将他们withdrawamount列数据相加,选择相加数据大于1000的数据,最后按照withdrawamount列相加的数据从高到低排序。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT 
withdrawid,
SUM(withdrawamount) AS total_amount
FROM
withdraw
WHERE
creationtime BETWEEN 1682870400 AND 1717084800
GROUP BY
withdrawid
HAVING
SUM(withdrawamount) > 1000
ORDER BY
total_amount DESC;

这不对withdrawid是提现的数据数,所以应该改成userid(也不能用bankcardid,因为bankcardid可能不同但是同一个人操作的,这样的鉴定为同一个人。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT COUNT(DISTINCT bankcardid) AS user_count
FROM (
SELECT
bankcardid,
SUM(withdrawamount) AS total_amount
FROM
withdraw
WHERE
creationtime BETWEEN 1682870400000 AND 1717084800000
GROUP BY
bankcardid
HAVING
SUM(withdrawamount) > 1000
) AS filtered_withdraws;