2023柏鹭杯部分wp

j1ya Lv5

Reverse

rev_imm

整个main函数就断点处有对输入的处理

调试可知是输入的两位转16进制即23->0x23

vmovdqu ymm0, ymmword ptr [ebp-40h]把0x31AF220F等数据给ymm0

之后ymm0异或四字节一组的输入

vpshufb ymm0, ymm0, ymmword ptr [ebp-60h] shuffle意为置换,且此时[ebp-60h]开头的内容为上面的常量,观察可以发现每个字节都小于32且无重复,大概可以猜测[ebp-60h]开头的内容作为下标取ymm0中的元素作为新的结果

密文

代码如下

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
key = [
0xCD, 0xEB, 0x5E, 0x76, 0x0F, 0x22, 0xAF, 0x31,
0x82, 0x92, 0x3C, 0xEF, 0xB8, 0xC1, 0x76, 0x06,
0x18, 0x2F, 0xB5, 0x7D, 0x7F, 0x0A, 0xEA, 0x85,
0x92, 0x00, 0x89, 0xA3, 0x2C, 0xE2, 0xE7, 0x32
]
shuffle = [
0x0A, 0x07, 0x06, 0x0E, 0x02, 0x0B, 0x03, 0x0D,
0x01, 0x09, 0x00, 0x05, 0x04, 0x0F, 0x08, 0x0C,
0x1B, 0x18, 0x17, 0x1F, 0x14, 0x1E, 0x12, 0x13,
0x15, 0x1D, 0x16, 0x1C, 0x11, 0x10, 0x19, 0x1A
]
expected = [
0x5F, 0x91, 0x99, 0xE8, 0x4E, 0xD0, 0xB0, 0x92,
0xB1, 0x3C, 0x4F, 0xF4, 0x17, 0x76, 0xDA, 0x12,
0x2A, 0x35, 0x01, 0x15, 0xF9, 0x97, 0x5E, 0x19,
0x9D, 0xC2, 0x15, 0x99, 0x70, 0x7D, 0x9F, 0xCC
]
# pshufb 的逆操作:source[shuffle[i]] = expected[i]
xor_result = bytearray(32)
for index, value in enumerate(expected):
xor_result[shuffle[index]] = value

code = bytes(a ^ b for a, b in zip(xor_result, key)).hex().upper()

print(code)
#825A10C618D636A058AE633FAA539E70655FEB648697FF84A79F4589B5207027

Misc

签到

qd.txt全是空格,空格数量当作ascii码

1
2
3
4
5
6
7
8
9
10
11
12
def count_spaces_per_line(file_path):
flag=""
with open(file_path, 'r') as file:
lines = file.readlines()
for line_num, line in enumerate(lines, start=1):
space_count = line.count(' ')
flag=flag+chr(int(space_count))
print(f"第{line_num}行空格数量:{space_count}")
print(flag)

file_path = 'qd.txt'
count_spaces_per_line(file_path)

代码吞噬者

打开a反射加载decode.dex

也会打开diff更新dex然后反射调用loadKey

静态无法分析,可以点击提交按钮后在内存中导出所有dex文件

classes.dex对应decode.dex,classes02.dex对应update_1_.dex

分析classes02.dex中的真实loadKey方法

加密两个一组,后一个替换前一个

1
2
3
4
5
6
7
8
dict = "9>AG3OCP1N2-4L5K6M7+BQD&EVF=0@8$"
password = '+>M=+K-@MN+-MK-@MN++MK+OM=M&MK'
for i in range(len(dict)-1,-1,-2):
c2 = dict[i]
c1 = dict[i-1]
password = password.replace(c2,c1)
print(bytes.fromhex(password))
#b'you are awesome'

自毁代码指会把update_1_.dex删掉

对delete进行hook,直接阻止删除

1
2
3
4
5
6
7
8
9
Java.perform(function () {
const File = Java.use("java.io.File");

File.delete.overload().implementation = function () {
console.log("[阻止删除] " + this.getAbsolutePath());
return false;
};
console.log("已Hook");
});

这个时候去内存中pull update_2_.dex

看到最终的calculateFlag就是md5加密

通过decrypt方法解出calculateFlag第二个参数

第三个参数来自DIFF_HEX

手动还原也能算出MD5值

1
2
3
4
5
6
7
8
9
10
11
12
import hashlib
dict = "B*6(7_F;D'E!C#1%2^4+5}0@8$9]A?3-"
update_dex = "++}$+++]+(+(@^@@_@%}@@@@($@@@@@@_@@@@@@@_+@^@@@@@@@-@@@@!#@+@@@@}#@}@@@@;#@(@@@@?@%+@@@@+#@!@@@@%$@;@@@@%@@;@@@@%$%+@@@@*#@;@@@@_#@_@@@@}@@;@@@@@$@;@@@@$+%+@@@@%$@;@@@@]?#;?!?@;]%-^^@''}'?'!;@+!;^'+@*(%+?!+-$%%^]@(@+@$@#@_@_@#@}@-@^@^@-@}@^@(@'@^';@@^@@@@((((;_^('(%_+@@@]_*+]}-+}+-^'^}_-_'@@@}@_@(@+@$@'@@@@@-@(@]@}@%@#@@@^@@@@@@%-@@^^@@@(@_@-@'@]@}@-@%%@@@^%@@@@@@%-@@@@@@*$@!@@@@@@@@@@@$@@@(@'@^@%@}@%%_@@@%%'%-@@%@@@};@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%@@@@@@@@@@@@@@@@@@@^@@@@@@@@@@@@@@@_@@@@@@%@@;@@@@@$@@@@@@%@@;@@@@@@@@@%@%(?@-@@@@@@%'+*(]@@@@@@@%@%@-@@@-@@@-@@@@@@}'@;@@@@%]@@@@@@%^%@_%-@@*@@^%@@@#@%_%%@@'@@@%@@@#@%^-@@^^@@_%%@@!@@@%@@@#@%%^@^+'@%@@@^%?@%_;@@_%^@%'@@@%@@@#@@%%@@@@@@@%@@@$@@@+@@@@%?@%%?@%%?@%%?@%%?@%%?@%%?@%%?@}$%$@@+'@^^@%@]?$^@@%@]!#^@@%@?*#%;@@@@@@@@@@@%@@@_@@@@@@@%@@@@@@%%@@@@@@@@@@@@@@@_@@@@@@%$@;@@@@%$%+@@@@$+%+@@@@"
for i in range(0,len(dict),2):
c1 = dict[i]
c2 = dict[i+1]
update_dex = update_dex.replace(c2,c1)
patch_bytes = bytes.fromhex(update_dex)

digest = hashlib.md5(patch_bytes).hexdigest()
print(digest)
# 41a2369f6b586047b628d570c11d66f1
  • 标题: 2023柏鹭杯部分wp
  • 作者: j1ya
  • 创建于 : 2023-10-15 21:58:18
  • 更新于 : 2026-10-05 22:11:35
  • 链接: https://j1ya-22.github.io/2023/10/15/2023柏鹭杯部分wp/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
2023柏鹭杯部分wp