2022HITCON

HITCON

密码学考试前夕的一场热身赛,RE只有三道题目,难度适中。虽然最后被打烂了,但AK的快感还是慰藉人心的。

密码学考后整理的wp,顺便把题目记录在此,以便今后CUMT的学弟学妹们参考~

image-20221128195338916

2020CUMT-Crypto

基本不考察理论背诵和算法记忆(除了AES、DES、SM4)

第一大题(30分)

  1. 画出Feistel一轮的流程图
  2. 给定消息bit数问hash(MD5)的填充方式
  3. 给定6位密码包括0-9和a-z分析秘钥空间
  4. 给定一串字符计算游程的个数(要首尾连接)
  5. aes的子密钥多少bit,简述生成过程
  6. 给6bit值计算des的sbox替换

第二大题(30分)

  1. 给定仿射加密式求解密,本次解密结果为CUMT
  2. AES列混淆中GF(2^8)域上的乘法,多项式运算,本年计算0x2*0xc1
  3. RSA给定p、q、e小数据,要求解密密文

第三大题(20)

  1. 证明DES有代数互补性、画出CBC的解密图
  2. LFSR给定一个特征多项式,要求画出LFSR的图和给出f函数,第二问是给定初始状态求输出序列和周期

第四大题(20)

一大题,三小问,本年度考察EIGAMAL算法,公钥只要求记忆RSA的算法,所以EIGAMAL和ECC的算法都会给出。

  1. EIGAMAL的公钥和私钥(5)
  2. 证明算法的正确性(5)
  3. 给定参数实现加密和解密(10)

REVERSE

Checker

checker程序主要就是使用DeviceIoControl函数向驱动程序发送控制码。

image-20221128171839437

驱动程序中还包括其他的控制码并进行运算,并控制了一个bool数组,当bool数组全为1时check通过,所以出题人是要我们向驱动程序按某种顺序传入控制码,满足条件后运行checker即输出correct。

image-20221128172044008

在驱动初始化时使用了一些重定位来隐藏真正访问的变量,通过计算恢复各个偏移指向的虚拟地址。

image-20221128172322731

func_encrypt指向的是0x140001B30 地址,并且每次进入sub_1400014D0函数后,都会在调用前进行对其进行异或和调用后异或,异或的常量通过传入的参数来找偏移。

image-20221128172420910

所以之后就要确定正确的调用顺序,这里观察到对data_buf数据的处理是单字节,且存在ecx中,可以观察异或后sub_140001B30函数的汇编来确认异或顺序,这里我使用capstone手撸的

exp

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
data1=[0x40, 0x53, 0x48, 0x83, 0xEC, 0x20, 0x48, 0x8B, 0x05, 0x3B, 0x0C, 0x00, 0x00, 0x48, 0x8B, 0xDA, 0x48, 0x8B, 0x4A, 0x10, 0x48, 0x39, 0x08, 0x75, 0x37, 0x48, 0x8B, 0x4A, 0x08, 0xFF, 0x15, 0x1D]
cd=[0x19, 0xBC, 0x8F, 0x82, 0xD0, 0x2C, 0x61, 0x34, 0xC0, 0x9F, 0xF6, 0x50, 0xD5, 0xFB, 0x0C, 0x6E, 0xD0, 0xEB, 0xE5, 0xE3, 0xCE, 0xB5, 0x4C, 0xCA, 0x45, 0xAA, 0x11, 0xB2, 0x3E, 0x62, 0x6F, 0x7D, 0xD0, 0xEB, 0xA9, 0xE3, 0xB2, 0x2F, 0x06, 0x47, 0x7C, 0x28, 0xC5, 0xDE, 0xDE, 0x1A, 0x4E, 0xD6, 0xD8, 0x2D, 0x93, 0x4F, 0x82, 0x65, 0x64, 0xFD, 0x08, 0x62, 0x4B, 0x87, 0x7E, 0x52, 0x47, 0x30, 0xB7, 0xBA, 0xD0, 0x39, 0x68, 0x53, 0x50, 0xAB, 0x20, 0xD5, 0xCA, 0x84, 0x26, 0x71, 0x6F, 0x91, 0x1B, 0x36, 0x46, 0x11, 0xA5, 0xF1, 0x4E, 0x58, 0x6C, 0x74, 0xD4, 0x9C, 0x15, 0xE2, 0x28, 0xD5, 0xD9, 0x0F, 0x3D, 0x83, 0xF3, 0xFC, 0xD1, 0x13, 0x1A, 0x62, 0x12, 0x40, 0xAA, 0xEA, 0xCD, 0xCB, 0xE1, 0xC6, 0x08, 0x81, 0x98, 0xF6, 0x68, 0x88, 0xBE, 0x23, 0xB5, 0x9E, 0x55, 0xB9, 0xE2, 0x7D, 0x5A, 0xDA, 0x39, 0x07, 0xF0, 0x2E, 0x32, 0x20, 0x59, 0x56, 0x4C, 0xB4, 0x8F, 0x3E, 0x07, 0x61, 0xD9, 0x0F, 0x2D, 0x61, 0xF1, 0x91, 0x33, 0x14, 0xCB, 0x49, 0x68, 0xFE, 0x1F, 0xD4, 0x8A, 0xFE, 0xE1, 0xC6, 0x18, 0x63, 0x9A, 0x9B, 0x8A, 0x8A, 0x7F, 0x08, 0xC3, 0xE8, 0xE1, 0xEC, 0x0B, 0x8F, 0x3B, 0x00, 0x94, 0xA5, 0x11, 0xE7, 0x47, 0x66, 0xC4, 0x9F, 0x98, 0x18, 0x70, 0xF0, 0x30, 0xF6, 0x94, 0x71, 0xB1, 0x95, 0xD1, 0xF0, 0x6F, 0xB7, 0xD9, 0x3D, 0x05, 0x9E, 0xC1, 0x53, 0x33, 0x76, 0x9B, 0x4B, 0x69, 0xCA, 0xDE, 0xFD, 0x7D, 0x67, 0xB8, 0x29, 0x2B, 0xC7, 0xC5, 0x84, 0x2C, 0xD1, 0x87, 0x87, 0xF1, 0x98, 0x97, 0x74, 0xAD, 0x4B, 0x32, 0xF0, 0x4A, 0x51, 0x72, 0xEA, 0x09, 0xF7, 0x38, 0xFD, 0x27, 0xBD, 0x1C, 0x52, 0x71, 0x43, 0x95, 0x9C, 0x1A, 0x86, 0xF2, 0xC0, 0xF9, 0xF8]
code=[0x80, 0xE9, 0x22, 0x80, 0xF1, 0xAD, 0x0F, 0xB6, 0xC1, 0x6B, 0xC8, 0x11, 0xB8, 0x9E, 0x00, 0x00, 0x00,0x2A,0xC1,0xc3]
"""
.text:0000000140001B30 sub_140001B30 proc near ; CODE XREF: sub_1400014D0+1A4↑p
.text:0000000140001B30 ; sub_1400014D0+1B6↑p ...
.text:0000000140001B30 sub cl, 22h ; '"'
.text:0000000140001B33 xor cl, 0ADh
.text:0000000140001B36 movzx eax, cl
.text:0000000140001B39 imul ecx, eax, 11h
.text:0000000140001B3C mov eax, 9Eh
.text:0000000140001B41 sub al, cl
.text:0000000140001B43 retn
.text:0000000140001B43 sub_140001B30 endp
"""
from capstone import *

def print_asm(code):
print('=====================')
CODE =bytes(code)
md = Cs(CS_ARCH_X86, CS_MODE_64)
for i in md.disasm(CODE, 0x140001B30):
print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))
print('=====================')
print_asm(code)
c=code[:]
for i in range(16):
c[i]=c[i]^data1[i]^data1[i+16]

# 14 15
"""
0x140001b30: movzx edx, cl
0x140001b33: mov eax, edx
0x140001b35: shl dl, 3
0x140001b38: shr eax, 5
0x140001b3b: or al, dl
0x140001b3d: ret
"""
c1=c[:]
for i in range(16):
c1[i]^=cd[14*16+i]^cd[15*16+i]
# 4 5
"""
0x140001b30: xor cl, 0x26
0x140001b33: movzx eax, cl
0x140001b36: ret
"""
c2=c1[:]
for i in range(16):
c2[i]^=cd[4*16+i]^cd[5*16+i]

# 12 13
"""
0x140001b30: movzx edx, cl
0x140001b33: mov eax, edx
0x140001b35: shl dl, 4
0x140001b38: shr eax, 4
0x140001b3b: or al, dl
0x140001b3d: ret
"""
c3=c2[:]
for i in range(16):
c3[i]^=cd[12*16+i]^cd[13*16+i]
# 0 1
"""
0x140001b30: lea eax, [rcx + 0x37]
0x140001b33: ret
"""
c4=c3[:]
for i in range(16):
c4[i]^=cd[i]^cd[16+i]


# 2 3
"""
0x140001b30: lea eax, [rcx + 0x7b]
0x140001b33: ret
"""
c5=c4[:]
for i in range(16):
c5[i]^=cd[3*16+i]^cd[2*16+i]
"""
0x140001b30: movzx edx, cl
0x140001b33: mov eax, edx
0x140001b35: shl dl, 7
0x140001b38: shr eax, 1
0x140001b3a: or al, dl
0x140001b3c: ret
"""
# 8 9
c6=c5[:]
for i in range(16):
c6[i]^=cd[8*16+i]^cd[9*16+i]



# 6 7
"""
0x140001b30: movzx eax, cl
0x140001b33: imul eax, eax, 0xad
0x140001b39: ret
"""
c7=c6[:]
for i in range(16):
c7[i]^=cd[6*16+i]^cd[7*16+i]
# 10 11
"""
0x140001b30: movzx edx, cl
0x140001b33: mov eax, edx
0x140001b35: shl dl, 2
0x140001b38: shr eax, 6
0x140001b3b: or al, dl
0x140001b3d: ret
"""

# for j in range(8): # 一段一段的测 单字节处理 输入存在ecx中
# tmp=c1[:]
# for i in range(16):
# tmp[i]^=cd[i+32*j]
# print(f'j={j}')
# print_asm(tmp[:16])
enc=[0x63, 0x60, 0xA5, 0xB9, 0xFF, 0xFC, 0x30, 0x0A, 0x48, 0xBB, 0xFE, 0xFE, 0x32, 0x2C, 0x0A, 0xD6, 0xE6, 0xFE, 0xFE, 0x32, 0x2C, 0x0A, 0xD6, 0xBB, 0x4A, 0x4A, 0x32, 0x2C, 0xFC, 0xFF, 0x0A, 0xFD, 0xBB, 0xFE, 0x2C, 0xB9, 0x63, 0xD6, 0xB9, 0x62, 0xD6, 0x0A, 0x4F]
def rol3(x):
return (x<<3 | x>>5)&0xff

for i in range(len(enc)):
enc[i]=rol3(enc[i])
enc[i]^=0x26
enc[i]=(enc[i]<<4 | enc[i]>>4)&0xff
enc[i]=(enc[i]+0x37+0x7b)&0xff
enc[i] = (enc[i] << 7 | enc[i] >> 1) & 0xff
enc[i]=(enc[i]*0xad)&0xff
enc[i] = (enc[i] << 2 | enc[i] >> 6) & 0xff
print(bytes(enc))

meow_way

通过交叉引用可知,使用 initterm函数将全局变量与函数绑定。

image-20221128173406614

访问函数题可见经典的32位程序调用64位代码的格式,代码比较短也用capstone

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
.rdata:004031C0 loc_4031C0:                             ; DATA XREF: sub_401000+3↑o
.rdata:004031C0 push 33h ; '3'
.rdata:004031C2 call $+5
.rdata:004031C7 add dword ptr [esp], 5
.rdata:004031CB retf

#x64 code context
=====================
0x403224: xor rax, rax
0x403227: mov rax, qword ptr gs:[rax + 0x60]
0x40322c: movzx rax, byte ptr [rax + 2]
0x403231: mov ecx, dword ptr [esp + 0x1c]
0x403236: mov dword ptr [ecx], eax
0x403239: test eax, eax
0x40323b: jne 0x403255
0x40323d: mov edi, dword ptr [esp + 4]
0x403242: mov esi, dword ptr [esp + 0xc]
0x403247: mov ecx, dword ptr [esp + 0x14]
0x40324c: add cl, byte ptr [esi]
0x40324f: xor cl, 0xba
0x403252: mov byte ptr [edi], cl ; (a + c)^0xba
=====================
....

.rdata:004031FD call $+5
.rdata:00403202 mov dword ptr [esp+4], 23h ; '#'
.rdata:0040320A add dword ptr [esp], 0Dh
.rdata:0040320E retf
.rdata:0040320F ; ---------------------------------------------------------------------------
.rdata:0040320F retn

=.=用了最麻烦的方法手撸

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
from capstone import *
def print_asm(code):
print('=====================')
CODE =bytes(code)
md = Cs(CS_ARCH_X86, CS_MODE_64)
for i in md.disasm(CODE, 0x403224):
print("0x%x:\t%s\t%s" %(i.address, i.mnemonic, i.op_str))
print('=====================')

enc=[0x96, 0x50, 0xCF, 0x2C, 0xEB, 0x9B, 0xAA, 0xFB, 0x53, 0xAB, 0x73, 0xDD, 0x6C, 0x9E, 0xDB, 0xBC, 0xEE, 0xAB, 0x23, 0xD6, 0x16, 0xFD, 0xF1, 0xF0, 0xB9, 0x75, 0xC3, 0x28, 0xA2, 0x74, 0x7D, 0xE3, 0x27, 0xD5, 0x95, 0x5C, 0xF5, 0x76, 0x75, 0xC9, 0x8C, 0xFB, 0x42, 0x0E, 0xBD, 0x51, 0xA2, 0x98]

"""
0x403252: sub cl, byte ptr [esi]
0x403255: xor cl, 0xf7
"""
print(chr((107-(enc[7]^0xf7)+0x100)&0xff),end='')
"""
0x40324c: add cl, byte ptr [esi]
0x40324f: xor cl, 0xd0
0x403252: mov byte ptr [edi], cl
"""
print(chr(((enc[8]^0xd0)-36 + 0x100)&0xff),end='')
"""
0x40324c: add cl, byte ptr [esi]
0x40324f: xor cl, 0x1f
0x403252: mov byte ptr [edi], cl
"""
print(chr(((enc[9]^0x1f)-85 + 0x100)&0xff),end='')
"""
0x403252: sub cl, byte ptr [esi]
0x403255: xor cl, 0xa8
0x403258: mov byte ptr [edi], cl
"""
print(chr((18-(enc[10]^0xa8)+0x100)&0xff),end='')
"""
0x40324c: sub cl, byte ptr [esi]
0x40324f: xor cl, 0x3d
0x403252: mov byte ptr [edi], cl
"""
print(chr((53-(enc[11]^0x3d)+0x100)&0xff),end='')
"""
0x403252: add cl, byte ptr [esi]
0x403255: xor cl, 0xc7
0x403258: mov byte ptr [edi], cl
"""
print(chr(((enc[12]^0xc7)-118 + 0x100)&0xff),end='')
"""
0x40324c: add cl, byte ptr [esi]
0x40324f: xor cl, 0xa5
0x403252: mov byte ptr [edi], cl
"""
print(chr(((enc[13]^0xa5)-231 + 0x100)&0xff),end='')
"""
0x40324c: sub cl, byte ptr [esi]
0x40324f: xor cl, 0x47
0x403252: mov byte ptr [edi], cl
"""
print(chr((251-(enc[14]^0x47)+0x100)&0xff),end='')
"""
0x40324c: add cl, byte ptr [esi]
0x40324f: xor cl, 0x68
0x403252: mov byte ptr [edi], cl
"""
print(chr(((enc[15]^0x68)-160 + 0x100)&0xff),end='')
"""
0x40324c: add cl, byte ptr [esi]
0x40324f: xor cl, 0xd7
0x403252: mov byte ptr [edi], cl
"""
print(chr(((enc[16]^0xd7)-218 + 0x100)&0xff),end='')
"""
0x40324c: sub cl, byte ptr [esi]
0x40324f: xor cl, 0x4a
0x403252: mov byte ptr [edi], cl
"""
print(chr((52-(enc[17]^0x4a)+0x100)&0xff),end='')
"""
0x403252: add cl, byte ptr [esi]
0x403255: xor cl, 0x96
0x403258: mov byte ptr [edi], cl
"""
print(chr(((enc[18]^0x96)-132 + 0x100)&0xff),end='')
print(chr((180-(enc[19]^0x91)+0x100)&0xff),end='')
print(chr(((enc[20]^0x2e)-200 + 0x100)&0xff),end='')
print(chr(((enc[21]^0x19)-155 + 0x100)&0xff),end='')
print(chr(((enc[22]^0xc5)-239 + 0x100)&0xff),end='')
print(chr(((enc[23]^0xe3)-180 + 0x100)&0xff),end='')
print(chr(((enc[24]^0x88)-185 + 0x100)&0xff),end='')
print(chr((10-(enc[25]^0xbd)+0x100)&0xff),end='')
print(chr(((enc[26]^0x4e)-87 + 0x100)&0xff),end='')
print(chr(((enc[27]^0x93)-92 + 0x100)&0xff),end='')
print(chr((254-(enc[28]^0x13)+0x100)&0xff),end='')
print(chr((197-(enc[29]^0xf1)+0x100)&0xff),end='')
print(chr(((enc[30]^0xcc)-106 + 0x100)&0xff),end='')
print(chr(((enc[31]^0x47)-115 + 0x100)&0xff),end='')
print(chr(((enc[32]^0xab)-73 + 0x100)&0xff),end='')
print(chr(((enc[33]^0xc9)-189 + 0x100)&0xff),end='')
print(chr((17-(enc[34]^0x48)+0x100)&0xff),end='')
print(chr((214-(enc[35]^0x2b)+0x100)&0xff),end='')
print(chr(((enc[36]^0x9)-143 + 0x100)&0xff),end='')
print(chr((107-(enc[37]^0x50)+0x100)&0xff),end='')
print(chr(((enc[38]^0x4f)-10 + 0x100)&0xff),end='')
print(chr((151-(enc[39]^0xe9)+0x100)&0xff),end='')
print(chr((171-(enc[40]^0xc0)+0x100)&0xff),end='')
print(chr(((enc[41]^0x5e)-78 + 0x100)&0xff),end='')
print(chr((237-(enc[42]^0xef)+0x100)&0xff),end='')
print(chr((254-(enc[43]^0x8b)+0x100)&0xff),end='')
print(chr((151-(enc[44]^0x85)+0x100)&0xff),end='')
print(chr((249-(enc[45]^0xcb+0x100)&0xff)),end='')
print(chr(((enc[46]^0x55)-152 + 0x100)&0xff),end='')

image-20221128232909594

因为他是单字节加密,patch一个printf,使用subprocess爆破也可以。

😭 gocrygo

go的恶意软件修复题,加密为3DES加密一个随机数据作为秘钥流,搜寻秘钥可以结合被加密文件首部的8字节随机数在core中搜索。因为是流密码,所以找到3DES秘钥扩展后的秘钥patch进去调试即可解密。

1
2
3
__int64 __fastcall sub_222A30(__int64, __int64, __int64, __int64 *)
"crypto/cipher: invalid buffer overlap"
"crypto/des: invalid buffer overlap"

内存中的一些base64解密后再base85可见明文,关于题目的提示信息。

image-20221128195719030

1
2
3
4
5
6
7
8
./linux/gocrygo_victim_directory 
Please run this binary on Linux
Hey! I don't want to break your file system. Please create a directory './gocrygo_victim_directory' and place all the files you want to encrypt in it.
Cannot access directory 'gocrygo_victim_directory': permission denied.
Failed to encrypt %v: lucky you~~
Oops, your file system has been encrypted.
Sadly, 'gocrygo' currently does not provide any decryption services.
You're doomed. Good luck ~

L29iaw==解密后是.qq也就是加密文件新后缀,sub_2214EB是负责解密数据的函数,这样大概能调了,.gocrygo表示已经加密过,调试的时候注意删除。

sub_2126AE 函数是DES的秘钥扩展,使用了3次,3DES可能,key是生成的24字节随机数。

image-20221128195750062

3DES的加密,sub_2123D为其feistel结构,用3DES加密获取的8字节rand2。

image-20221128195809229

1
2
3
4
5
6
7
from Crypto.Cipher import DES3
rand1=[0x9A, 0x8E, 0x87, 0xB4, 0x54, 0xB5, 0x0D, 0xD2, 0x25, 0xE9, 0xA3, 0xA8, 0xB8, 0xD3, 0x55, 0x1E, 0x81, 0xD0, 0x9B, 0x7F, 0xE5, 0x0E, 0x8B, 0xAF]
rand2=[0x1F, 0x8B, 0x88, 0x03, 0xAE, 0x56, 0x15, 0x42]
ans=[0xD5, 0xB7, 0xA0, 0xF6, 0x09, 0x1D, 0x23, 0x1F]
des=DES3.new(bytes(rand1),DES3.MODE_ECB)
print(des.encrypt(bytes(rand2)).hex())
#d5b7a0f6091d231f

image-20221128195824173

之后会将rand2+1,然后继续使用3DES加密,直到生成0x200bit的密文,把生成的密文和文件的明文逐字节异或得到解密后的文件,会将初始的rand2写在被加密文件的前8字节。

1
2
3
4
5
6
7
8
while ( v154 != v155 )
{
if ( v113 == v155 || v112 == v155 || v8 == v155 )
goto LABEL_203;
v16 = (__int64)v201;
v201[v155] = *(_BYTE *)(v202 + v155) ^ *(_BYTE *)(v114 + v21 + v155);
++v155;
}

rand2被写在文件前8字节,所以主要就是找rand1的24个字节了,针对flag.txt加密的。

1
2
#flag.txt的rand2
58 7E 75 76 AA 07 F4 01 -> 58 7E 75 76 AA 07 F4 41

突然发现变换后的rand2 和 最后异或的流秘钥在内存中十分接近,也就是直接在转储中搜58 7E 75 76 AA 07 F4 41 !!!

image-20221128195848588

搜索被加密文件首部八字节定位存储的轮秘钥。

image-20221128195902741

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
f1=open(r'core','rb')
buf=f1.read()[0x9fa88:]
f1.close()
f2=open(r'flаg.txt.qq','rb')
enc=f2.read()[8:]
f2.close()
ans=[]
for i in range(len(enc)):
ans.append(enc[i]^buf[i])
print(bytes(ans).decode())
"""
Cyrillic letters are fun right?
First part: `HITCON{always_gonna_make_you_`
Hint: The second part is at `Pictures/rickroll.jpg`
_ _.--.____.--._
( )=.-":;:;:;;':;:;:;"-._
\\\\\\:;:;:;:;:;;:;::;:;:;:\\
\\\\\\:;:;:;:;:;;:;:;:;:;:;\\
\\\\\\:;::;:;:;:;:;::;:;:;:\\
\\\\\\:;:;:;:;:;;:;::;:;:;:\\
\\\\\\:;::;:;:;:;:;::;:;:;:\\
\\\\\\;;:;:_:--:_:_:--:_;:;\\
\\\\\\_.-" "-._\\
\\\\
\\\\
\\\\
\\\\
\\\\
\\\\
"""

这仅能解密直接小于512的文件,因为存储的流秘钥512字节一组并不断更新。

image-20221128195927010

发现文件路径和rand2之间的3DES扩展秘钥等比较容易定位,在dump出的内存中搜索首部8字节,并dump其上的768字节在3DES生成扩展秘钥后patch。

image-20221128195949539

调试即可完成解密,和以往恶意软件常用的RC4、Sasal20类似,3DES的OFB模式生成的轮秘钥

getflag

在core里面找patch数据直接搜加密文件的前8字节,前面有768字节并且会有路径的字符串。

image-20221128234421690

1
2
3
4
5
6
7
import ida_bytes
s=[184, 127, 170, 21, 45, 226, 177, 118, 82, 72, 36, 15, 167, 61, 45, 204, 182, 243, 164, 32, 167, 226, 15, 50, 47, 107, 186, 10, 221, 228, 181, 146, 79, 20, 242, 53, 211, 61, 168, 83, 20, 53, 155, 52, 41, 120, 240, 42, 253, 178, 120, 55, 76, 163, 6, 205, 206, 158, 205, 24, 188, 143, 78, 43, 177, 99, 218, 56, 109, 238, 181, 35, 255, 10, 89, 55, 212, 175, 80, 217, 22, 174, 75, 17, 179, 156, 250, 109, 56, 179, 69, 47, 3, 244, 70, 237, 141, 247, 45, 10, 92, 230, 75, 164, 79, 108, 196, 10, 204, 29, 61, 151, 218, 116, 55, 33, 163, 11, 217, 80, 199, 142, 7, 22, 221, 159, 218, 164, 125, 157, 68, 6, 81, 105, 26, 161, 65, 127, 170, 16, 78, 233, 129, 54, 95, 49, 214, 6, 238, 77, 144, 155, 251, 199, 19, 21, 233, 203, 203, 64, 113, 62, 0, 28, 113, 173, 4, 60, 188, 130, 38, 2, 58, 190, 134, 136, 244, 239, 128, 12, 16, 215, 63, 2, 9, 58, 16, 41, 118, 148, 32, 80, 47, 180, 197, 20, 240, 60, 74, 11, 188, 196, 17, 8, 29, 26, 99, 12, 210, 190, 36, 56, 148, 179, 6, 20, 142, 90, 142, 8, 175, 150, 145, 10, 226, 205, 80, 5, 143, 103, 51, 81, 71, 57, 3, 57, 247, 97, 208, 112, 175, 33, 10, 7, 235, 122, 132, 236, 157, 89, 53, 41, 75, 86, 65, 80, 40, 40, 148, 22, 18, 0, 24, 166, 7, 96, 162, 17, 192, 48, 165, 118, 12, 32, 150, 38, 5, 8, 160, 186, 26, 212, 26, 54, 132, 32, 171, 128, 6, 22, 72, 60, 137, 128, 12, 25, 192, 128, 107, 0, 9, 39, 198, 9, 196, 152, 225, 12, 32, 35, 118, 7, 36, 40, 149, 41, 42, 0, 96, 70, 21, 129, 197, 17, 64, 116, 86, 107, 5, 226, 17, 11, 64, 136, 99, 236, 24, 176, 4, 58, 4, 12, 42, 180, 26, 86, 14, 42, 136, 128, 153, 136, 64, 230, 104, 5, 9, 133, 27, 81, 200, 0, 227, 9, 32, 39, 208, 115, 164, 44, 179, 7, 32, 2, 196, 230, 0, 65, 53, 1, 21, 116, 85, 80, 189, 24, 225, 6, 122, 49, 194, 13, 235, 197, 8, 7, 173, 23, 35, 12, 183, 94, 140, 0, 220, 122, 49, 2, 112, 235, 197, 8, 194, 173, 23, 3, 132, 91, 47, 6, 17, 110, 189, 8, 70, 184, 245, 2, 24, 225, 214, 11, 98, 132, 91, 15, 139, 17, 110, 13, 47, 70, 184, 5, 94, 140, 112, 11, 210, 150, 186, 7, 164, 45, 117, 15, 147, 182, 212, 13, 79, 218, 82, 7, 61, 105, 75, 13, 247, 164, 45, 5, 221, 147, 182, 4, 117, 79, 218, 2, 234, 158, 180, 5, 169, 123, 210, 6, 165, 238, 73, 11, 150, 186, 39, 13, 91, 234, 158, 4, 109, 169, 123, 2, 180, 165, 238, 9, 105, 75, 221, 3, 82, 132, 36, 11, 165, 8, 73, 6, 149, 34, 36, 9, 86, 138, 144, 4, 89, 41, 66, 2, 100, 165, 8, 9, 146, 149, 34, 4, 73, 86, 138, 0, 146, 172, 20, 1, 72, 178, 82, 4, 33, 201, 74, 1, 132, 36, 43, 5, 17, 146, 172, 4, 69, 72, 178, 2, 20, 33, 201, 10, 41, 66, 146, 5, 191, 81, 14, 7, 126, 163, 28, 14, 251, 141, 114, 8, 238, 55, 202, 1, 184, 223, 40, 7, 225, 126, 163, 12, 135, 251, 141, 2, 28, 238, 55, 10, 57, 220, 111, 4, 229, 112, 191, 1, 148, 195, 253, 6, 81, 14, 247, 11, 70, 57, 220, 15, 27, 229, 112, 15, 111, 148, 195, 13, 223, 40, 135, 11, 210, 14, 96, 11, 165, 29, 192, 6, 149, 118, 0, 11, 86, 218, 1, 12, 91, 105, 7, 0, 108, 165, 29, 0, 176, 149, 118, 0, 192, 86, 218, 1, 128, 173, 180, 3, 0, 182, 210, 14, 3, 216, 74, 11, 14, 96, 43, 13, 59, 128, 173, 4, 237, 0, 182, 2, 180, 3, 216, 10, 105, 7, 176, 5, 4, 208, 34, 10, 9, 160, 69, 4, 37, 128, 22, 1, 148, 0, 90, 4, 81, 2, 104, 1, 68, 9, 160, 5, 17, 37, 128, 6, 69, 148, 0, 10, 139, 40, 1, 4, 45, 162, 4, 0, 180, 136, 18, 0, 208, 34, 74, 0, 64, 139, 40, 1, 0, 45, 162, 4, 1, 180, 136, 2, 2, 104, 17, 5, 189, 78, 21, 115, 82, 53, 76, 108]
adr=0x7F384901C580
for i in range(len(s)):
patch_byte(adr+i,s[i])
print('ok')
#always_gonna_make_you_cry_always_gonna_say_goodbye

image-20221128200025573

对称密码真就是逆向手的自我修养~


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!