Skip to content

Commit e63b5bf

Browse files
committed
v0.0.9
1 parent 256b6ed commit e63b5bf

File tree

4 files changed

+55
-22
lines changed

4 files changed

+55
-22
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ulexec"
3-
version = "0.0.8"
3+
version = "0.0.9"
44
edition = "2021"
55
license = "MIT"
66
readme = "README.md"

PKGBUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# Maintainer: VHSgunzo <vhsgunzo.github.io>
22
pkgname='ulexec-bin'
33
binname="${pkgname%-bin}"
4-
pkgver='0.0.8'
4+
pkgver='0.0.9'
55
pkgrel='1'
66
pkgdesc='A tool for loading and executing PE on Windows and ELF on Linux from memory'
77
arch=("x86_64")

README.md

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,28 +47,49 @@ Options:
4747
## Examples
4848
The tool fully supports static and dynamically compiled Linux executables and Windows PE (portable executable). Simply pass the filename of the binary to `ulexec` and any arguments you want to supply to the binary. The environment will be directly copied over from the environment in which you execute `ulexec`
4949

50+
The file path can be passed directly or with `~~f | ~~file` argument or env var `ULEXEC_FILE`
51+
5052
```
5153
ulexec /bin/ls -lha
5254
```
5355

54-
You can have it read a binary from `stdin` if you specify `~~s | ~~stdin` argument
56+
You can read a binary from `stdin` if you specify `~~s | ~~stdin` argument or env var `ULEXEC_STDIN=1`
5557

5658
```
5759
cat /bin/ls|ulexec ~~s -lha
5860
# or
5961
ulexec ~~s</bin/ls -lha
6062
```
6163

62-
To download a binary into memory and immediately execute it you can use `~~u | ~~url`
64+
To download a binary into memory and immediately execute it you can use `~~u | ~~url` argument or env var `ULEXEC_URL` or pass the URL directly
65+
66+
```
67+
ulexec http://example.com/bin/ls -lha
68+
```
69+
70+
If the resource (for example https://temp.sh) on which the binary file is located requires using the POST method instead of GET to start downloading, you can specify this with the `~~p | ~~post` argument or env var `ULEXEC_POST=1`
71+
72+
```
73+
ulexec ~~p http://temp.sh/ABCDEF/ls -lha
74+
```
75+
76+
For executable files that need to fork themselves, you can use the `~~re | ~~reexec` argument or env var `ULEXEC_REEXEC=1`
77+
78+
```
79+
ulexec ~~re http://example.com/bin/tun2proxy --unshare --setup --proxy socks5://127.0.0.1:1080 -- /bin/bash
80+
ulexec ~~re http://example.com/bin/gocryptfs /tmp/cryptfs /tmp/mnt
81+
```
82+
83+
To self remove `ulexec` at startup, you can use the `~~r | ~~remove` argument or env var `ULEXEC_REMOVE=1`
6384

6485
```
65-
ulexec ~~u http://example.com/bin/ls -lha
86+
ulexec ~~r http://example.com/bin/ls -lha
6687
```
6788

68-
If the resource (for example https://temp.sh) on which the binary file is located requires using the POST method instead of GET to start downloading, you can specify this with the `~~p | ~~post` argument
89+
You can pass `stdin` data to the executed binary
6990

7091
```
71-
ulexec ~~p ~~u http://temp.sh/ABCDEF/ls -lha
92+
ulexec http://example.com/bin/tar -xzvf-</path/to/local.tar.gz
7293
```
7394

7495
## References

src/main.rs

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,15 @@ fn get_env_var(env_var: &str) -> String {
4949
ret
5050
}
5151

52+
fn unset_env_vars_with_prefix(prefix: &str) {
53+
let current_vars = env::vars();
54+
for (key, _value) in current_vars {
55+
if key.starts_with(prefix) {
56+
env::remove_var(key);
57+
}
58+
}
59+
}
60+
5261
fn parse_args() -> Args {
5362
let env_args: Vec<String> = env::args().skip(1).collect();
5463
let mut args = Args::default();
@@ -113,7 +122,16 @@ fn parse_args() -> Args {
113122
}
114123
if args.url.is_none() {
115124
let var = get_env_var("ULEXEC_URL");
116-
if !var.is_empty() { args.url = Some(var) }
125+
if !var.is_empty() {
126+
args.url = Some(var)
127+
} else {
128+
if !args.exec_args.is_empty() {
129+
let arg = &args.exec_args[0];
130+
if arg.starts_with("http://") || arg.starts_with("https://") {
131+
args.url = Some(args.exec_args.remove(0));
132+
}
133+
}
134+
}
117135
}
118136
if args.file.is_none() {
119137
let var = get_env_var("ULEXEC_FILE");
@@ -184,6 +202,8 @@ fn main() {
184202
}
185203
}
186204

205+
unset_env_vars_with_prefix("ULEXEC_");
206+
187207
let mut exec_file: Vec<u8> = Vec::new();
188208
let mut file_path = PathBuf::new();
189209

@@ -233,15 +253,7 @@ fn main() {
233253
if !file_path.to_str().unwrap().is_empty() && exec_file.is_empty() {
234254
match read(&file_path) {
235255
Ok(data) => {
236-
exec_file = data;
237-
#[cfg(target_os = "linux")]
238-
if args.reexec && is_child {
239-
file_path = PathBuf::new();
240-
env::remove_var("ULEXEC_URL");
241-
env::remove_var("ULEXEC_FILE");
242-
env::remove_var("ULEXEC_CHILD");
243-
env::remove_var("ULEXEC_REEXEC");
244-
}
256+
exec_file = data
245257
}
246258
Err(err) => {
247259
eprintln!("Failed to read the binary file: {err}: {:?}", file_path);
@@ -340,14 +352,14 @@ fn main() {
340352
}
341353

342354
if args.reexec && !is_child && !args.mfdexec {
343-
let fifo_path = &env::temp_dir().join(random_string(8));
344-
if let Err(err) = mkfifo(fifo_path, Mode::S_IRWXU) {
355+
let fifo_path = env::temp_dir().join(random_string(8));
356+
if let Err(err) = mkfifo(&fifo_path, Mode::S_IRWXU) {
345357
eprintln!("Failed to create fifo: {err}: {:?}", fifo_path);
346358
exit(1)
347359
}
348360
env::set_var("ULEXEC_CHILD", "1");
349361
env::set_var("ULEXEC_REEXEC", "1");
350-
env::set_var("ULEXEC_FILE", fifo_path);
362+
env::set_var("ULEXEC_FILE", &fifo_path);
351363
let fifo_path = fifo_path.clone();
352364
let exec_file = exec_file.clone();
353365
spawn(move || {
@@ -377,10 +389,10 @@ fn main() {
377389
.envs(env::vars())
378390
.status().unwrap().code().unwrap())
379391
} else {
380-
if file_path.to_str().unwrap().is_empty() && !exec_file.is_empty() {
392+
if !file_path.exists() && !exec_file.is_empty() {
381393
match &memfd_create(
382394
CString::new(memfd_name).unwrap().as_c_str(),
383-
MemFdCreateFlag::MFD_CLOEXEC,
395+
MemFdCreateFlag::MFD_CLOEXEC
384396
) {
385397
Ok(memfd) => {
386398
let memfd_raw = memfd.as_raw_fd();

0 commit comments

Comments
 (0)