Skip to content

Commit 36ff2eb

Browse files
committed
v0.0.7
1 parent 33d4ce8 commit 36ff2eb

File tree

4 files changed

+84
-63
lines changed

4 files changed

+84
-63
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,10 @@ jobs:
3939
upx --force -9 --best target/x86_64-pc-windows-gnu/release/ulexec.exe -o target/x86_64-pc-windows-gnu/release/ulexec-upx.exe;
4040
cp target/x86_64-pc-windows-gnu/release/{ulexec,ulexec-upx}.exe . ;
4141
42-
- name: Build archlinux package
43-
uses: countstarlight/arch-makepkg-action@master
44-
with:
45-
scripts: "makepkg -fsCc --noconfirm"
42+
# - name: Build archlinux package
43+
# uses: countstarlight/arch-makepkg-action@master
44+
# with:
45+
# scripts: "makepkg -fsCc --noconfirm"
4646

4747
- name: Release
4848
uses: softprops/action-gh-release@v1

Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "ulexec"
3-
version = "0.0.6"
3+
version = "0.0.7"
44
edition = "2021"
55
license = "MIT"
66
readme = "README.md"
@@ -24,7 +24,7 @@ memexec = "0.2.0"
2424
reqwest = { version = "0.12.8", features = ["blocking", "rustls-tls"] }
2525

2626
[target.'cfg(target_os = "linux")'.dependencies]
27-
goblin = "0.8.2"
27+
goblin = "0.9.0"
2828
memfd-exec = "0.2.1"
2929
userland-execve = "0.2.0"
3030
nix = { version = "0.29.0", features = [ "fs", "process" ] }

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.6'
4+
pkgver='0.0.7'
55
pkgrel='1'
66
pkgdesc='A tool for loading and executing PE on Windows and ELF on Linux from memory'
77
arch=("x86_64")

src/main.rs

Lines changed: 77 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@ fn main() {
164164
let mut args: Args;
165165

166166
let is_child = get_env_var("ULEXEC_CHILD") == "1";
167+
167168
#[cfg(target_os = "windows")]
168169
{
169170
if is_child {
@@ -235,12 +236,11 @@ fn main() {
235236
exec_file = data;
236237
#[cfg(target_os = "linux")]
237238
if args.reexec && is_child {
238-
let _ = std::fs::remove_file(&file_path);
239239
file_path = PathBuf::new();
240+
env::remove_var("ULEXEC_URL");
241+
env::remove_var("ULEXEC_FILE");
240242
env::remove_var("ULEXEC_CHILD");
241243
env::remove_var("ULEXEC_REEXEC");
242-
env::remove_var("ULEXEC_FILE");
243-
env::remove_var("ULEXEC_URL");
244244
}
245245
}
246246
Err(err) => {
@@ -277,11 +277,15 @@ fn main() {
277277
#[cfg(target_os = "linux")]
278278
{
279279
use std::time;
280+
use std::process;
281+
use std::fs::File;
280282
use std::ffi::CString;
281283
use std::os::fd::AsRawFd;
282-
use nix::unistd::{write, close};
283284
use std::thread::{spawn, sleep};
285+
286+
use nix::sys::stat::Mode;
284287
use goblin::elf::{Elf, program_header};
288+
use nix::unistd::{write, close, mkfifo};
285289
use memfd_exec::{Stdio, MemFdExecutable};
286290
use nix::sys::memfd::{memfd_create, MemFdCreateFlag};
287291

@@ -301,23 +305,55 @@ fn main() {
301305
}
302306
}
303307

304-
if args.reexec && !is_child {
305-
let tmp_file = env::temp_dir().join(std::process::id().to_string());
306-
match std::fs::File::create(tmp_file.clone()) {
307-
Ok(mut file) => {
308-
if let Err(err) = file.write_all(&exec_file) {
309-
eprintln!("Failed to write the binary file: {err}: {:?}", file_path);
308+
fn ul_exec(file_path: PathBuf, exec_args: Vec<String>) {
309+
let mut args_cstrs: Vec<CString> = exec_args.iter()
310+
.map(|arg|
311+
CString::new(arg.clone()).unwrap()
312+
).collect();
313+
314+
let file_cstr = CString::new(
315+
file_path.to_str().unwrap()
316+
).unwrap();
317+
args_cstrs.insert(0, file_cstr);
318+
319+
let envs: Vec<CString> = env::vars()
320+
.map(|(key, value)|
321+
CString::new(format!("{}={}", key, value)).unwrap()
322+
).collect();
323+
324+
userland_execve::exec(
325+
&file_path,
326+
&args_cstrs,
327+
&envs,
328+
)
329+
}
330+
331+
if args.reexec && !is_child && !args.mfdexec {
332+
let fifo_path = &env::temp_dir().join(process::id().to_string());
333+
if let Err(err) = mkfifo(fifo_path, Mode::S_IRWXU) {
334+
eprintln!("Failed to create fifo: {err}: {:?}", fifo_path);
335+
exit(1)
336+
}
337+
env::set_var("ULEXEC_CHILD", "1");
338+
env::set_var("ULEXEC_REEXEC", "1");
339+
env::set_var("ULEXEC_FILE", fifo_path);
340+
let fifo_path = fifo_path.clone();
341+
let exec_file = exec_file.clone();
342+
spawn(move || {
343+
match File::create(&fifo_path) {
344+
Ok(mut fifo) => {
345+
if let Err(err) = fifo.write_all(&exec_file) {
346+
eprintln!("Failed to write the binary file to fifo: {err}: {:?}", fifo_path);
347+
exit(1)
348+
}
349+
let _ = std::fs::remove_file(&fifo_path);
350+
}
351+
Err(err) => {
352+
eprintln!("Failed to open fifo: {err}: {:?}", fifo_path);
310353
exit(1)
311354
}
312-
env::set_var("ULEXEC_CHILD", "1");
313-
env::set_var("ULEXEC_REEXEC", "1");
314-
env::set_var("ULEXEC_FILE", tmp_file.clone());
315-
}
316-
Err(err) => {
317-
eprintln!("Failed to create the binary file: {err}: {:?}", file_path);
318-
exit(1)
319355
}
320-
}
356+
});
321357
}
322358

323359
let memfd_name = "exec";
@@ -330,54 +366,39 @@ fn main() {
330366
.envs(env::vars())
331367
.status().unwrap().code().unwrap())
332368
} else {
333-
let mut args_cstrs: Vec<CString> = args.exec_args.iter()
334-
.map(|arg|
335-
CString::new(arg.clone()).unwrap()
336-
).collect();
369+
if file_path.to_str().unwrap().is_empty() && !exec_file.is_empty() {
370+
match &memfd_create(
371+
CString::new(memfd_name).unwrap().as_c_str(),
372+
MemFdCreateFlag::MFD_CLOEXEC,
373+
) {
374+
Ok(memfd) => {
375+
let memfd_raw = memfd.as_raw_fd();
337376

338-
match &memfd_create(
339-
CString::new(memfd_name).unwrap().as_c_str(),
340-
MemFdCreateFlag::MFD_CLOEXEC,
341-
) {
342-
Ok(memfd) => {
343-
let memfd_raw = memfd.as_raw_fd();
344-
345-
if file_path.to_str().unwrap().is_empty() && !exec_file.is_empty() {
346377
file_path = PathBuf::from(
347378
format!("/proc/self/fd/{}", memfd_raw.to_string())
348379
);
380+
349381
if let Err(err) = write(memfd, &exec_file) {
350382
eprintln!("Failed to write the binary file to memfd: {err}: {:?}", file_path);
351383
exit(1)
352384
}
385+
drop(exec_file);
386+
387+
spawn(move || {
388+
sleep(time::Duration::from_millis(1));
389+
close(memfd_raw).unwrap()
390+
});
391+
392+
ul_exec(file_path, args.exec_args)
393+
}
394+
Err(err) => {
395+
eprintln!("Failed to create memfd: {err}");
396+
exit(1)
353397
}
354-
drop(exec_file);
355-
356-
let file_cstr = CString::new(
357-
file_path.to_str().unwrap()
358-
).unwrap();
359-
args_cstrs.insert(0, file_cstr);
360-
361-
let envs: Vec<CString> = env::vars()
362-
.map(|(key, value)|
363-
CString::new(format!("{}={}", key, value)).unwrap()
364-
).collect();
365-
366-
spawn(move || {
367-
sleep(time::Duration::from_millis(1));
368-
close(memfd_raw).unwrap()
369-
});
370-
371-
userland_execve::exec(
372-
&file_path,
373-
&args_cstrs,
374-
&envs,
375-
)
376-
}
377-
Err(err) => {
378-
eprintln!("Failed to create memfd: {err}");
379-
exit(1)
380398
}
399+
} else {
400+
drop(exec_file);
401+
ul_exec(file_path, args.exec_args)
381402
}
382403
}
383404
}

0 commit comments

Comments
 (0)