Skip to content

Commit b8414b2

Browse files
committed
support shellcode offset
1 parent 046f539 commit b8414b2

4 files changed

Lines changed: 290 additions & 20 deletions

File tree

Cargo.lock

Lines changed: 211 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,4 @@ edition = "2018"
88

99
[dependencies]
1010
bindings = { package = "rs_shellcode_bindings", path = "bindings" }
11+
clap = "3.0.0-beta.2"

README.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,40 @@ Build:
2323
cargo build
2424
```
2525

26+
Usage:
27+
```
28+
rs_shellcode
29+
30+
USAGE:
31+
rs_shellcode.exe [FLAGS] [OPTIONS] -f <file>
32+
33+
FLAGS:
34+
-b set breakpoint in debugger
35+
-h, --help Prints help information
36+
-V, --version Prints version information
37+
38+
OPTIONS:
39+
-f <file> shellcode path
40+
-o <offset> shellcode offset
41+
```
42+
2643
Run:
2744

2845
```sh
29-
./target/debug/rs_shellcode.exe <SHELLCODE_PATH>
46+
./target/debug/rs_shellcode.exe -f <SHELLCODE_PATH>
3047
```
3148

49+
When your shellcode not start at offset 0, you can specify the offset use `-o`:
50+
51+
```sh
52+
./target/debug/rs_shellcode.exe -f <SHELLCODE_PATH> -o 0x30
53+
```
54+
55+
3256
Run with breakpoint flag (`-b`):
3357

3458
```sh
35-
./target/debug/rs_shellcode.exe <SHELLCODE_PATH> -b
59+
./target/debug/rs_shellcode.exe -f <SHELLCODE_PATH> -b
3660
```
3761

3862
use this flag, you can break just before your shellcode in the debugger, which will make your life easier.

src/main.rs

Lines changed: 52 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,81 @@
11
#![feature(asm)]
2+
#![feature(pattern)]
3+
24
// #![windows_subsystem = "windows"]
35
use bindings::windows::win32::system_services::VirtualAlloc;
6+
use clap::{App, Arg};
47
pub const PAGE_EXECUTE_READWRITE: u32 = 0x40;
58
pub const MEM_COMMIT: u32 = 0x1000;
69
pub const MEM_RESERVE: u32 = 0x2000;
710

811
fn main() {
9-
let args: Vec<String> = std::env::args().collect();
10-
if args.len() < 2 {
11-
println!("Usage: ./rs_shellcode \"C:\\Users\\Admin\\Desktop\\calc64.raw\" [-b]");
12-
return;
13-
}
14-
let mut set_breakpoint = false;
15-
if args.len() == 3 {
16-
set_breakpoint = &args[2] == "-b";
17-
println!("[*] Set breakpoint in debugger");
12+
let matches = App::new("rs_shellcode")
13+
.arg(
14+
Arg::new("file")
15+
.short('f')
16+
.about("shellcode path")
17+
.takes_value(true)
18+
.required(true),
19+
)
20+
.arg(
21+
Arg::new("breakpoint")
22+
.short('b')
23+
.about("set breakpoint in debugger"),
24+
)
25+
.arg(
26+
Arg::new("offset")
27+
.short('o')
28+
.about("shellcode offset")
29+
.takes_value(true),
30+
)
31+
.get_matches();
32+
33+
let set_breakpoint = matches.is_present("breakpoint");
34+
if set_breakpoint {
35+
println!("[*] Breakpoint flag set!");
1836
}
19-
let fp = &args[1];
20-
// let fp = "C:\\Users\\Admin\\Desktop\\calc64.raw".to_owned();
37+
let fp: String = matches.value_of_t("file").unwrap_or_else(|e| e.exit());
38+
let offset: u64 = match matches.value_of("offset") {
39+
Some(offset) => {
40+
if offset.find("0x") == Some(0) {
41+
let without_prefix = offset.trim_start_matches("0x");
42+
u64::from_str_radix(without_prefix, 16).unwrap_or(0)
43+
} else {
44+
u64::from_str_radix(offset, 10).unwrap_or(0)
45+
}
46+
}
47+
_ => 0,
48+
};
2149
println!("[*] Reading shellcode from path: {:?}", fp.clone());
2250
let contents = std::fs::read(fp).unwrap();
2351
let flen = contents.len();
2452

25-
let test_buf = unsafe {
53+
if flen as u64 <= offset {
54+
println!(
55+
"[*] Offset too big, offset: {}, file length: {}",
56+
offset, flen
57+
);
58+
return;
59+
}
60+
let new_buf = unsafe {
2661
VirtualAlloc(
2762
std::ptr::null_mut(),
2863
flen,
2964
MEM_COMMIT | MEM_RESERVE,
3065
PAGE_EXECUTE_READWRITE,
3166
)
3267
};
33-
if test_buf == std::ptr::null_mut() {
68+
if new_buf == std::ptr::null_mut() {
3469
println!("[*] Failed to allocate memory");
3570
return;
3671
}
37-
let test_buf_ptr: *mut u8 = test_buf as *mut u8 as _;
38-
unsafe { std::ptr::copy_nonoverlapping(contents.as_ptr(), test_buf_ptr, flen) };
39-
println!("[*] Before jmp to shellcode");
40-
72+
let new_buf_ptr: *mut u8 = new_buf as *mut u8 as _;
73+
unsafe { std::ptr::copy_nonoverlapping(contents.as_ptr(), new_buf_ptr, flen) };
74+
println!("[*] Starting jmp to shellcode at offset 0x{:x}", offset);
4175
unsafe {
4276
if set_breakpoint {
4377
asm!("int 3");
4478
}
45-
asm!("jmp {}",in(reg) test_buf)
79+
asm!("jmp {}",in(reg) new_buf.offset(offset as isize))
4680
};
4781
}

0 commit comments

Comments
 (0)