Skip to content

Commit

Permalink
Added --show-text. Documented --custom in README
Browse files Browse the repository at this point in the history
  • Loading branch information
six-two committed Aug 31, 2024
1 parent 0e527ce commit 6910700
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 5 deletions.
27 changes: 24 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ It is entirely client-site, your files do not get uploaded to a server.

## Installation

There are both a web and a python version. The web version is not actively developed anymore and very bare bones, but easy to use and requires no installation. The Python version has more features and is generally recommended.

### Current feature comparision

Currently the python version has the most features.
Expand All @@ -36,9 +38,10 @@ Automatic detection of most efficient algorithms | no | yes
### Python version

A Python script to generate self extracting web pages is under `python/main.py`.
It just requires a modern Python version (probably Python3.9+) and has no required external dependencies (but you need to install `pycryptodomex` if you want to encrypt contents).
It just requires a modern Python version (probably Python3.9+) and has no mandatory external dependencies.
But if you want to use the encryption feature, you need to install `pycryptodomex` with pip.

You can also install it with `pip`:
You can install it with `pip`:

```bash
python3 -m pip install -U self-unzip-html
Expand All @@ -49,11 +52,13 @@ Example usage of the pip package:
self-unzip-html -t download -o psexec.html ~/Downloads/SysinternalsSuite/PsExec.exe
```

Or if you wanted to password-protect it:
Or if you wanted to password-protect the output:
```bash
self-unzip-html -t download -o psexec.html -p YourPasswordHere ~/Downloads/SysinternalsSuite/PsExec.exe
```

You can show all flags with the `--help` flag and can see some example commands in `./test.sh`.

#### Phishing

If you want to use it for phishing (sending a download link to a malicious file), the `--driveby-redirect` is likely what you want. It starts a download and immediately redirects to any URL you choose, so that it looks like the other site started the download:
Expand All @@ -77,6 +82,18 @@ You can automatically decrypt a page by adding the password as the hash in a URL
The hash will not be sent to the server, so your password may only be stored locally (in your browsing history).
Otherwise a prompt will ask you for the password.

#### Custom actions

With the `--custom` flag you can specify your own JavaScript that should handle the unpacked data. The data is passed via the `og_data` parameter.
The value is an Uint8Array which represents the bytes of the input file. If you want to interpret it as UTF-8 text and convert it to a string, you can use `new TextDecoder().decode(og_data)`.
If you want to build your payload based on one of the builtin payloads, you can find them in `python/self_unzip_html/static_js.py`

When debugging your own payload it can be useful to see go through it step by step. For this I find it easiest to create an page with:
```bash
self-unzip-html README.md --custom 'window.og_data = og_data' -o test_custom.html
```
The resulting page exposes og_data in the global scope. You can then paste your payload into the JavaScript console piece by piece and inspect the output or DOM in between.

### Web version

There is a bare-bones page generator written in plain HTML and JavaScript.
Expand Down Expand Up @@ -127,6 +144,10 @@ closure-compiler output/main.js --js_output_file output/main.min.js

## Notable changes

### Head

- Added `--show-text` action, which shows the payload as plain text

### Version 0.2.0

- **Breaking change**: Replaced the `--type` parameter with specific flags like `--download`, `--driveby-redirect`, `--eval`, `--replace`, and `--custom`.
Expand Down
6 changes: 5 additions & 1 deletion python/self_unzip_html/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from typing import Optional, Any
# local
from .minified_js import B64DECODE, B85DECODE, DECRYPT, UNZIP
from .static_js import HEXDUMP, DECODE_AND_EVAL_ACTION, JS_DOWNLOAD, JS_DRIVEBY_REDIRECT, JS_EVAL, JS_REPLACE
from .static_js import HEXDUMP, DECODE_AND_EVAL_ACTION, JS_DOWNLOAD, JS_DRIVEBY_REDIRECT, JS_EVAL, JS_REPLACE, JS_SHOW_TEXT

SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
DEFAULT_TEMPLATE_FILE = os.path.join(SCRIPT_DIR, "template.html")
Expand All @@ -22,6 +22,8 @@ def get_javascript(args: Any, file_name: str) -> str:
return JS_EVAL
elif args.replace:
return JS_REPLACE
elif args.show_text:
return JS_SHOW_TEXT
elif args.driveby_redirect != None:
return JS_DRIVEBY_REDIRECT.replace("{{REDIRECT_URL}}", args.driveby_redirect).replace("{{NAME}}", file_name)
elif args.custom != None:
Expand Down Expand Up @@ -172,6 +174,7 @@ def replace_in_template(self, library_code: str, glue_code: str, payload_code: s


def main() -> None:
# @TODO: Support multiple input files for certain options (download, driveby, etc)?
ap = argparse.ArgumentParser()
# ap_input = ap.add_argument_group("input options")
# ap_input_mutex = ap_input.add_mutually_exclusive_group(required=True)
Expand All @@ -188,6 +191,7 @@ def main() -> None:
payload_option_mutex.add_argument("--download", nargs="?", metavar="FILE_NAME", const="", help="show a download link to download the payload as a file. If you specify an argument that is used as the name of the file to download")
payload_option_mutex.add_argument("--eval", action="store_true", help="pass the payload to eval() to run it as JavaScript code")
payload_option_mutex.add_argument("--replace", action="store_true", help="replace the page's content with the payload. Use this to compress HTML pages")
payload_option_mutex.add_argument("--show-text", action="store_true", help="use this to show plain text. Unlike --replace this does not interpret HTML tags and does not change whitespace")
payload_option_mutex.add_argument("--driveby-redirect", metavar="REDIRECT_URL", help="downlaod the payload as a file in the background and immediately redirect the user to another site. Useful for phishing")
payload_option_mutex.add_argument("--custom", metavar="YOUR_JAVASCRIPT_CODE", help="run your own action. Provide a JavaScript snippet that uses the decoded payload, which is stored in the 'og_data' variable. Note that data is a byte array, so you likely want to use 'new TextDecoder().decode(og_data)' to convert it to Unicode")

Expand Down
4 changes: 3 additions & 1 deletion python/self_unzip_html/static_js.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@
JS_EVAL = "setTimeout(new TextDecoder().decode(og_data))"

# since decryption is async we do not catch the onload event anymore
JS_REPLACE = 'setTimeout(()=>{let n=document.open("text/html","replace");n.write(new TextDecoder().decode(og_data));n.close()}, 50);'
JS_REPLACE = 'setTimeout(()=>{let n=document.open();n.write(new TextDecoder().decode(og_data));n.close()}, 50);'

JS_SHOW_TEXT = 'setTimeout(()=>{let d=document.open(); d.write("<!DOCTYPE html><html><body><style>textarea {width:100vw;height:100vh;padding:0px;margin:0px;border:none;outline: none;white-space: pre-wrap; overflow-x: none;}</style><textarea readonly></textarea></body></html>");d.querySelector("textarea").value=new TextDecoder().decode(og_data)}, 50);'

JS_DOWNLOAD = 'let b=new Blob([og_data],{type:"application/octet-stream"});let u=URL.createObjectURL(b);document.body.innerHTML=`<h1>Unpacked {{NAME}}</h1><a href="${u}" download="{{NAME}}">Click here to download</a>`'

Expand Down
1 change: 1 addition & 0 deletions test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ self-unzip-html.py README.md -o test_b85_gzip_encrypt.html -e ascii85 -c gzip -p
# other modes
echo 'alert("Looks like it still works :)")' | self-unzip-html.py - -o test_eval_b64_gzip.html -e base64 -c gzip --eval
self-unzip-html.py README.md -o test_download_b85_encrypt.html -e ascii85 -c none -p test --download
self-unzip-html README.md -e base64 -c none --show-text -o test_show.html
self-unzip-html.py README.md -o test_custom.html -e ascii85 -c none -p test --custom 'alert(og_data)'
# Usually you want to redirect to a thank you page, since this legitimizes the downlod you just started
self-unzip-html.py README.md -o test_driveby.html -e ascii85 -c none -p test --driveby-redirect https://anydesk.com/en/downloads/guide/thank-you
Expand Down

0 comments on commit 6910700

Please sign in to comment.