remy🐀

@_mattata@infosec.exchange
1.1K Followers
785 Following
268 Posts
Dad, Vulnerability Research, Packet connoisseur. He/Him. Cyber Security Architect GreyNoise. Top percentage Rattata
Twitterhttps://twitter.com/_mattata
Personal Bloghttps://remyhax.xyz
Professional Bloghttps://www.greynoise.io/blog
PronounsHe/Him

Android APK’s have a dedicated loader for Ghidra, but they’re also Archives with nested files which is a different loader. This causes quirks.

Here’s how to get around that and use the best tool.

Ghidra Is Best: Android Reverse Engineering

https://remyhax.xyz/posts/android-with-ghidra/

Ghidra is best: Android Reverse Engineering

Ghidra is the best Android app RE tool. It just seems like it’s not, because the loader has easily fixed quirks. Let me demonstrate.

REMY HAX

There’s a lot of “VPN’s are snakeoil, just use HTTPS” discourse again, so here, I’ll sell the farm for the sake of demonstrating exactly how wrong this argument is for phones.

You Want a VPN for Your Phone, Because Apps.

https://remyhax.xyz/posts/you-want-a-vpn-for-your-phone/

You want a VPN for your phone, because apps.

VPN: phone, not desktop. WiFi: N/A. These statements are correct. Or at least as correct as is applicable to the general user in the scope of the following contextual blog which generally recommends that:

REMY HAX

Graph Theory for Reverse Engineers

Or “everything actually is a nail, you just need a bigger hammer”

https://remyhax.xyz/posts/graph-theory-for-reverse-engineers/

Graph Theory for Reverse Engineers

Or “everything actually is a nail, you just need a bigger hammer” Graph Theory is a really neat subject matter relating to the modeling of pairwise relations between objects. When you understand graph theory, everything steadily becomes a graph theory problem, because pretty much anything can be.

REMY HAX

Step One: How2 Z3

or "I hate math and always re-use the same z3 template when solving crackmes and CTF's and use BitVector because I can represent anything as BitVector and never need to learn more z3, so here's how I finally wrote it down"

https://remyhax.xyz/posts/z3/

Step One: How2 Z3

This article is a long time coming. z3, the constraint solver, is commonly used in crackmes and CTF challenges. Wherever possible, I just lift to angr for symbolic execution and bruteforce that way, since z3 is basically math bruteforce anyways.

Bots associated with this botnet can typically be recognized by distinctive hexadecimal banners featuring strings such as `head[...]1111` or `head[...]11111111`, predominantly appearing on TCP port 17000.

Since its initial detection, our ERT has closely monitored the activities and growth of #Eleven11bot . Early assessments indicate a large and geographically distributed botnet presence, spanning multiple countries such as the United States, Canada, Israel, Spain, the United Kingdom, Brazil, Taiwan, Romania, and Japan, among others.

Local, Private, AI Code Assistant in VSCode. The easy and free way.

https://remyhax.xyz/posts/local-llm-code-ai/

Local, Private, AI Code Assistant

Recently, products like Claude Code, Cursor, and Copilot have sprung to the forefront of my social media. I’ve ignored these for quite some time, but a coworker recommended that I try out <some product I can't remember> after I was fighting a particularly gnarly public codebase that had opaque documentation and involved a LOT of state machines.

Your LLMs were backdoored years ago.

https://remyhax.xyz/posts/plagairism/

Your LLMs were backdoored years ago.

Plagiarism is an ethical violation. Always has been. As such: “A computer can never be held accountable, therefore a computer must never make a management decision”.

The Xiaohongshu 小红书 REDnote 小红书国际版 "Backdoor"

Analysis: The existence of “backdoor” in the Xiaohongshu 小红书 REDnote app appears to be a problem in the connotation of the word itself among a global community, and nothing more.

https://remyhax.xyz/posts/xiaohongshu-rednote-backdoor/

The Xiaohongshu 小红书 REDnote 小红书国际版 "Backdoor"

The popular social media app “TikTok” is likely facing an iminent ban in the United States in the coming days. This has resulted in a mass migration to the Chinese app 小红书 (meaning “little red book”), Xiaohongshu, or simply “REDnote”.

Since this vulnerability is being successfully exploited in the wild, it probably is worth knowing if your system has been compromised, right?

A compromised box can easily fake (internal AND external) ICT results, and it can also fake the factory reset process as well. So is all hope lost?

Well, in the vast sea of bits on VirusTotal, apparently some good samaritan has uploaded a bootable ISO that can both decrypt an Ivanti ICS filesystem, as well as run the stand-alone ICT in a way that is truly stand-alone. i.e. it doesn't rely on your maybe-compromised running system not lying to you.

With some brief testing, it seems to work. And perhaps can be trustable as much as you trust a computer to boot from the media you specify.
https://www.virustotal.com/gui/file/2d76293e1639152e4871fba67cb5bdb010e444a3cd66bdf943503c48bba412c0/details

VirusTotal

VirusTotal

remember when google blocked access to /sdcard/Android/data for "security" reasons?

lmao
×

Since this vulnerability is being successfully exploited in the wild, it probably is worth knowing if your system has been compromised, right?

A compromised box can easily fake (internal AND external) ICT results, and it can also fake the factory reset process as well. So is all hope lost?

Well, in the vast sea of bits on VirusTotal, apparently some good samaritan has uploaded a bootable ISO that can both decrypt an Ivanti ICS filesystem, as well as run the stand-alone ICT in a way that is truly stand-alone. i.e. it doesn't rely on your maybe-compromised running system not lying to you.

With some brief testing, it seems to work. And perhaps can be trustable as much as you trust a computer to boot from the media you specify.
https://www.virustotal.com/gui/file/2d76293e1639152e4871fba67cb5bdb010e444a3cd66bdf943503c48bba412c0/details

Using a 1-line change of the BishopFox PoC for CVE-2025-0282, we can easily see the vulnerable Ivanti web server crash.
https://github.com/BishopFox/CVE-2025-0282-check

Given that there's no stack canary, and there's only 9 bits of ASLR entropy, we can probably successfully brute force a successful exploit if we want to.

GitHub - BishopFox/CVE-2025-0282-check: Safely detect if an Ivanti server is vulnerable to CVE-2025-0282

Safely detect if an Ivanti server is vulnerable to CVE-2025-0282 - BishopFox/CVE-2025-0282-check

GitHub
Since Ivanti graciously provided a copy of gdb on ICS devices, we can see the stack trace of the crash quite easily right on the ICS device itself.

watchTowr has published details on their strategy for exploiting this vulnerability:
https://labs.watchtowr.com/exploitation-walkthrough-and-techniques-ivanti-connect-secure-rce-cve-2025-0282/

However, since we're not as smart as the people at watchTowr, is there anything else we might be able to accomplish?

Well, depending on how much we overflow our buffer, we might be able to take advantage of the fact that the Ivanti web binary has a fork() in it without a corresponding execve(). Forked processes are clones of the parent, and as such, you can crash the forked process and each time it will have the same process/library/stack/heap memory layout.

What this means is that each forked child will behave identically to the parent with respect to memory locations. So if we have some way to figure out a way to get control of EIP, it will do that every single time.

In this case I cheated because I knew the address of the web binary AND the stack. And in the end, I didn't need to do anything clever at all like a faked vtable. If we need to brute force both the 32-bit ASLR'd address of the web server binary AND the stack, that could be several days worth of requests before a successful exploitation happens.

If I have some spare time, I may try achieving what watchTowr has outlined to get a more elegant solution.

But either way that you approach the problem, attackers benefit from the fact that the Ivanti ICS web server is a 32-bit process that doesn't use stack canaries, here in the year 2025.

If you're using a security product that has its origins in something made in 2010, and has only patched specific security bugs, as opposed to having had received a full refresh, make sure that you're aware of the security consequences of such behavior. Sure people make mistakes. And code written in C/C++ is going to have memory safety issues due to such mistakes. HOWEVER, if you're using a C/C++ product that doesn't bother with modern exploit mitigations (e.g. only partial adoption of PIE, no stack canaries, is 32-bit, etc.), well, have fun with that.

Exploitation Walkthrough and Techniques - Ivanti Connect Secure RCE (CVE-2025-0282)

As we saw in our previous blogpost, we fully analyzed Ivanti’s most recent unauthenticated Remote Code Execution vulnerability in their Connect Secure (VPN) appliance. Specifically, we analyzed CVE-2025-0282. Today, we’re going to walk through exploitation. Once again, however, stopping short of providing the world with a Detection Artifact

watchTowr Labs

Note that the watchTowr PoC for CVE-2025-0282 is out:
https://github.com/watchtowrlabs/CVE-2025-0282

Worth noting that this exploit admittedly leverages prior knowledge of memory offsets to properly function. Which either this is an exploit that was neutered to avoid use by the masses, or watchTowr never got a viable exploit that doesn't figure this out on its own.

I'm curious what the ITW exploits look like... 🤔

In fact, the watchTowr PoC on GitHub actually just AV's on AAAA with an ICS 22.7R2.4 or even 22.7R2.3 (which is what the watchTowr screenshot is of) system.

So presumably what's on gitHub was just an early test PoC that wasn't quite yet viable, hard-coded addresses aside.

And from @Rapid7Official 's @stephenfewer we have a (mostly) working exploit:
https://github.com/sfewer-r7/CVE-2025-0282

While my naive attempt to get control of EIP leveraged both a known heap address and a known stack address, I wasn't pretty pleased with it due to the combined entropy of the heap (14 bits) and the stack (12 bits).

Had I tried a bit harder, I could have found the bits that I needed all in a single loaded library (libdsplibs.so). And since it's a 32-bit app, we'll expect to see about 9 bits of entropy, which is very easily brute-forceable in a listening service that re-spawns itself when it crashes.

Tweaks necessary to get this to RCE properly (at least with my VMs):
1. Set keep-alive header
2. Set TLS version 1.2
3. Auto-increment the libdsplibs_base value with each attempt, as at least with my VM, the crashing web server is forked from a parent that does not crash, and as such the ICS web server will have the same memory layout every single time. As such, you can't keep a fixed address and re-try until the server matches what you're guessing. You need to guess a different value each time.

With these tweaks, I can pop my 22.7R2.4 ICS box in seconds. 🎉

The fact that a 2025 Ivanti ICS box has 32-bit binaries, no stack canaries (which is a mitigation that has been around for 20 years), and no official way to determine if a box is compromised that is sound makes it seem that Ivanti does not REALLY care about security. But please, draw your own conclusions here.

GitHub - sfewer-r7/CVE-2025-0282: PoC for CVE-2025-0282: A remote unauthenticated stack based buffer overflow affecting Ivanti Connect Secure, Ivanti Policy Secure, and Ivanti Neurons for ZTA gateways

PoC for CVE-2025-0282: A remote unauthenticated stack based buffer overflow affecting Ivanti Connect Secure, Ivanti Policy Secure, and Ivanti Neurons for ZTA gateways - sfewer-r7/CVE-2025-0282

GitHub

In a simple world, our CALL [ EAX + 0x48 ] (as outlined by watchTowr) would call to an address that's under our control and we get control of EIP. However I didn't find something so easy. I even poked around at partial overwrites, which would make ASLR *completey* irrelevant. But no such luck there.

But Stephen does something clever here where this CALL goes a location in libdsplibs.so. The bytes at this address happen to decode to an x86 PUSHF instruction, but that's a red herring. This gadget is in a non-executable segment of memory, which will trigger a SIGSEGV. And normally this would be game over.

HOWEVER, at this point even after the access violation in our gadget, the program flow continues at a massive jump table postamble. Why? The Ivanti code sets up a signal handler to handle SIGSEGVs and attempt to keep on chugging, which is quite courteous to attackers.

At the point of the RET at the end of a jump table postamble, our specially-crafted buffer controls exactly where we go next. At this point, we have full control of EIP, so we're good to ROP away as usual!

Since some kind soul uploaded the V22725-b3819 ICT to VirusTotal, we can actually kick the tires of the thing to see how it fares on the ICS VMs that we have handy.

Each one is a fresh install, so they should all come up clean, right? You clearly haven't been paying attention here if that's what you think. 😂 We all know that an ICS admin's job is meant to be as unpleasant as possible.

In each of the recent ICS 22.7 versions, the ICT reports 2 newly detected files. In an older ICS 22.6 version, the ICT reports that there are 18 new files.

Does this mean that the device should be investigated for compromise? No, aside from being fundamentally flawed in design, the ICT also has bugs that show up as false positives. These are all clean VMs that have been untouched in any way.

Are ICS admins to know that the ICT reporting newly detected files is expected on a clean device, and is not necessarily an indicator of compromise?

So what if we run the Ivanti ICT on a machine that *was* modified? In my test case, I placed 2 new files:
1 in the system root partition
1 in the data-backup-tgz file, which is a known persistence technique being used by attackers in the wild.
I also modified two files:
1 in the system root partition
1 in the data partition

Luckily, in 2024 Ivanti changed the ICT so that it no longer encrypts the output file to ease the load on their support team. When you download it, it has no file extension. But clever ICS admins will just know in their hearts that it's a .tgz.gz file. (Yes, they gzip a tgz file, because if you compress something once and it gets smaller, it's clear that compressing it a second time will make it even smaller!)

The web UI for the ICT shows us that we have 4 new files, and 4 newly-detected files. Knowing that the ICT by default has 2 false positives, that does match up with our 2-new-file, 2-modified-file test. So all is good, right?

Well, sorta. Although the web UI for the ICT tells you the count of the modified and new files, it does not tell you what the files are. And the no-longer-encrypted tarball that you can download does have actual files, it does not indicate which files are there because they're new and which are there because they're modified.

But even more glaring of a problem is that while the ICT does check for a couple of file types that might have been added to data-backup.tgz, you don't get a copy of the file, nor will you even be told what the filename was. But if you do the math of subtracting the 2 false positives from the combined new and modified files count and then compare it to the number of non-/tmp files in your tarball, you might be able to tell that you have a hijacked data-backup.tgz file on your ICS device. Easy peasy, right?

One of the things that nobody (that I know of) is talking about with this ITW Ivanti exploitation is how the attackers are getting root privileges to do their stuff.

EDIT: The Ivanti advisory says that CVE-2025-0283 is a buffer overflow to achieve privilege escalation. But nobody is talking about what this actually is.

Knowing that the Ivanti web server runs as "nr" instead of root, then why does the CVSS score for CVE-2025-0282 say that the CIA losses are all High? Is the CVSS score for CVE-2025-0282 wrong?

IMO, yes. The CVSS score is wrong.
The exploit was scored (as opposed to the vulnerability), it's fine. It allows full appliance compromise. However, that's not *just* CVE-2025-0282. If we want to be pedantic, when we assign a CVSS score to CVE-2025-0282, that score is for the single vulnerability captured as CVE-2025-0282 and nothing else.

However, the consumers of CVSS scores don't care about vulnerability-level precision. They don't care about what exploitation of an individual vulnerability can achieve. What's important is the complete exploit (chain). The days of single vulnerability exploits are mostly long gone by now. They are chains.

And if you're scoring individual links in a chain (i.e. CVEs), then good luck in knowing what the score of the chain as a whole is!

We know that CVE-2025-0282 isn't enough to compromise a system on its own.

And although they throw out this mystery CVE-2025-0283 as a privilege escalation that could fit that need, they are crystal clear that they have no evidence that CVE-2025-0283 is being used in the wild.

What can we conclude using simple logic here?
Ivanti doesn't know how attackers in the wild are compromising their systems. They only know part of the picture (CVE-2025-0282). 🤔

@wdormann Excellent find! TIL about LD_AUDIT, LD_SHOW_AUXV, and "secure-execution mode".

Interestingly, that latter does not seem to apply here... maybe because of how old Linux / ld is? https://www.man7.org/linux/man-pages/man8/ld.so.8.html

ld.so(8) - Linux manual page

@stephen0x2dfox
Yeah, I haven't really sifted through it too closely, but I think the dsrunpriv program explicitly avoids any protections that AT_SECURE might provide.

Specifically, at run time it sets the uid to match the euid. And at this point, the process will no longer receive the AT_SECURE protections, since there's no longer a difference between the two. My understanding is that when the values match, ld.so is hands off with AT_SECURE.

Does that sound about right?

@wdormann Oh I think I see now. You're saying dsrunpriv executes *another* program and dsrunpriv's "--set-env" argument allows you to set LD_AUDIT for the child process which is running as root because dsrunpriv is running as root.

@stephen0x2dfox
Correct. dsrunpriv is setuid root and spawns child processes with user-settable environment variables.

However, even in such a case, I think that one might get benefits from AT_SECURE if dsrunpriv did not take steps to ensure that the euid is equal to the uid at the time of the child process spawn. My understanding is that AT_SECURE is hands-off at that point, as those values being equal is an indicator that it's not just a standard invocation of a setuid root executable.

@wdormann so basically submit every ICT run to Support and ask them to validate for you? Seems they missed the boat
@pejacoby
Well a clever ICS admin might recognize it as false positives and not need to contact support.
But yeah, if the goal was to avoid support calls, not only should the output not be encrypted, but the tool should also not produce false positives if they really wanted to achieve that goal. 🤦‍♂️
A job done.
@wdormann Wait a moment... you mean they did the equivalent of "ON ERROR RESUME NEXT"? Wow.
@wdormann They neutered it: https://labs.watchtowr.com/exploitation-walkthrough-and-techniques-ivanti-connect-secure-rce-cve-2025-0282/. There's a more reasoned & detailed description of why that Ben (I think) shared elsewhere but the last paragraph of the blog covers the neutering also.
Exploitation Walkthrough and Techniques - Ivanti Connect Secure RCE (CVE-2025-0282)

As we saw in our previous blogpost, we fully analyzed Ivanti’s most recent unauthenticated Remote Code Execution vulnerability in their Connect Secure (VPN) appliance. Specifically, we analyzed CVE-2025-0282. Today, we’re going to walk through exploitation. Once again, however, stopping short of providing the world with a Detection Artifact

watchTowr Labs

@timb_machine
Yeah, I saw the general gist of the exploitation. But what's not clear to me is the whole getting past ASLR.

Yeah, it's only a 32-bit app, but if the exploitation requires 3 different independently randomized things (heap: 14 bits, stack: 12 bits, and binary: 9 bits), that adds up pretty quickly. 🤔

@timb_machine
As it turns out, exploitation can happen with only guessing the base address of a single loaded library.

https://infosec.exchange/@wdormann/113844874136359186

Will Dormann (@wdormann@infosec.exchange)

Attached: 4 images And from @Rapid7Official 's @stephenfewer we have a (mostly) working exploit: https://github.com/sfewer-r7/CVE-2025-0282 While my naive attempt to get control of EIP leveraged both a known heap address and a known stack address, I wasn't pretty pleased with it due to the combined entropy of the heap (14 bits) and the stack (12 bits). Had I tried a bit harder, I could have found the bits that I needed all in a single loaded library (libdsplibs.so). And since it's a 32-bit app, we'll expect to see about 9 bits of entropy, which is very easily brute-forceable in a listening service that re-spawns itself when it crashes. Tweaks necessary to get this to RCE properly (at least with my VMs): 1. Set keep-alive header 2. Set TLS version 1.2 3. Auto-increment the libdsplibs_base value with each attempt, as at least with my VM, the crashing web server is forked from a parent that does not crash, and as such the ICS web server will have the same memory layout every single time. As such, you can't keep a fixed address and re-try until the server matches what you're guessing. You need to guess a different value each time. With these tweaks, I can pop my 22.7R2.4 ICS box in seconds. 🎉 The fact that a 2025 Ivanti ICS box has 32-bit binaries, no stack canaries (which is a mitigation that has been around for 20 years), and no official way to determine if a box is compromised that is sound makes it seem that Ivanti does not REALLY care about security. But please, draw your own conclusions here.

Infosec Exchange
@wdormann Could be a fun challenge / learning experience to exploit it.

@stephen0x2dfox
Yeah, this is definitely one of those things where I could choose to race the rest of the internet. And then see that once I get it done discover that somebody else had published their copy hours before I finished mine. 😂. (Yes, this is the voice of experience)

But yeah, assuming nobody else steps up, I may have a hack at it if I have time.

@wdormann Got it. If you're ever interested in collaborating on that, @seungminkang and I are looking to build more experience in binary exploitation (we've been doing CTF stuff for a little while, and it would be fun to possibly apply that to something real).
@wdormann How did you get a working VA of the vulnerable target? I used the v-22.7r2.3-b3431 original .OVA to deploy a VA in WMWare Workstation and do the initial setup. But when I launch the attack, nothing happens. No crash in the terminal. I think trere's something else that has to be done in order to exploit the vuln... Any ideas/suggestions?

@mcksysar
I used the python PoC from BishopFox and just added 1 line to get it to crash:
payload += b" clientCapabilities=" + b"A" * 1000
You can do something similar with the Rapid7 PoC, but I had to do a couple of tweaks to get that to work (outlined earlier in my thread here). There's nothing else that needs to be done. Just negotiating the IF-T TLS with a large clientCapabilities value is enough to trigger it.

You should see the "web" binary crash in dmesg output. R2.3 as well.

To get to R2.4 I installed an update PKG, as I couldn't find an R2.4 VM. I suspect Ivanti didn't build one for that version.

@wdormann I did that change in BishopFox's PoC, and got nothing on the terminal. I have several version of the software (2 from OVA's) and 2 more from upgrading from pkg's. But the attack shows nothing on the terminal (the handshake seems to work fine, since I got the 101 HTTP code and the version requests response; but when the overflow is sent, nothing happens in the terminal). That's why I asked you if there's is some extra config that must be done in ordere to exploit this...

@mcksysar
No, I didn't do any config other than answering the initial questions to get it to boot (certificate info and whatnot).

Anything larger than 256 bytes provided will trigger the crash. The properties of the crash will vary based on the size of the buffer.

@wdormann Damn! I'll keep trying... Do you know if there is any menu option in the terminal that I can use to see if the crash is happening? I found nothing in the log section...
@mcksysar
Ah, you're using the default terminal? I'm not sure you'd see any evidence of a crash there. Or even in the system logs for that matter.
@wdormann Yeah. I didn't figured out a way to get a shell in the VA (I spend a lot of time trying to create the target and get a crash)

@mcksysar
If you're running in VMware:
1. Boot the VM
2. Pause the VM
3. Edit the .vmem file in a hex editor
4. Replace "/home/bin/dsconfig.pl" with "/////////////bin/bash"
5. Resume the VM
6. Press Enter to get your shell

If you're using some other virtualization platform, you may have to do your own homework to see how you might be able to edit memory of a paused VM.

Oh, and my prior comment about not seeing anything in the logs was partly untrue. You can see the crash in the debug logs. But such debug logs are 3DES encrypted, because Ivanti doesn't want people to know what's happening with their devices. 😂

@wdormann WOW!!! I'll try that!! Thanks you very much!
@mcksysar
If you know what to look for, it's a somewhat universal way of rooting a locally-running VM. 😀
@wdormann I also changed and compiled the openconnect like watchtowr did, but got no crash in any of my VM's