0%

解析酷狗二进制编码的krc歌词文件

解开明文算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import zlib

# 实际krc是用zlib将歌词压缩之后与enc_key执行了简单的异或加密
# 解析的过程就是解密后解压
# 但是解开明文之后歌词的字符编码通常是UTF-8-BOM | UTF-8-SIG
def decompress_krc(krc_binary_bytes):
enc_key = bytearray([64, 71, 97, 119, 94, 50, 116, 71, 81, 54, 49, 45, 206, 210, 110, 105])

content_bytes = krc_binary_bytes[4:]
compressed_bytes = []

for i in range(0, len(content_bytes)):
compressed_bytes.append(content_bytes[i] ^ enc_key[i % 16])

return zlib.decompress(bytearray(compressed_bytes))

一个把krc解析出明文文件并打印出来的例子

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
import zlib
import sys
import os

def decompress_krc(krc_bytes):
enc_key = bytearray([64, 71, 97, 119, 94, 50, 116, 71, 81, 54, 49, 45, 206, 210, 110, 105])

content_bytes = krc_bytes[4:]
compressed_bytes = []

for i in range(0, len(content_bytes)):
compressed_bytes.append(content_bytes[i] ^ enc_key[i % 16])

return zlib.decompress(bytearray(compressed_bytes))

if len(sys.argv) != 2:
print('usage : parse_krc <krc path>')
sys.exit(0)

filename = sys.argv[1]
target_filename = os.path.splitext(filename)[0] + '_plaintext.krc'

with open(filename, 'rb') as f:
plaintext_bytes = decompress_krc(bytearray(f.read()))

fp = open(target_filename, 'wb')
fp.write(plaintext_bytes)
fp.close()

plaintext = plaintext_bytes.decode('utf-8')
print(plaintext)

识别二进制或纯文本krc例子

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
def _is_utf8_char(buffer, idx):
buffer_len = len(buffer)
if buffer_len == 0:
return False

def _scan_remain(_s):
for i in range(idx + 1, min(buffer_len, idx + _s)):
if (buffer[i] & 0xC0) != 0x80:
return 0
return _s

if (buffer[idx] & 0x80) == 0x00:
return 1
elif (buffer[idx] & 0xE0) == 0xC0:
return _scan_remain(2)
elif (buffer[idx] & 0xF0) == 0xE0:
return _scan_remain(3)
elif (buffer[idx] & 0xF8) == 0xF0:
return _scan_remain(4)
else:
return 0

def _scan_utf8_buffer(buffer):
i = 0
length = 0
max_length = 20

while i < len(buffer):
flag = _is_utf8_char(buffer, i)
if flag == 0:
return False

length += 1
if length >= max_length:
break

i += flag

return True

with open('song.krc', 'rb') as f:
if f.peek()[:3] == b'krc' and not _scan_utf8_buffer(f.peek()[3:]):
print('binary')
# 解密 & 解压...
# raw_bytes = ...
else:
print('text')
raw_bytes = f.read()

# plaintext = raw_bytes.decode('utf-8')
请我喝瓶肥仔快乐水?

欢迎关注我的其它发布渠道