Kudaes/Unwinder

cross compile asm

Closed this issue · 4 comments

Very good project. But I have some problems when I try to cross compile.
It seems that only the msvc environment can compile normally. MSYS2 failed.

warning: unwinder@0.1.1: x86_64-w64-mingw32-gcc: warning: src/gateway.asm: linker input file unused because linking not done
warning: unwinder@0.1.1: x86_64-w64-mingw32-ar: /projects/target/x86_64-pc-windows-gnu/release/build/unwinder-5f8cf206a3d006ec/out/src/gateway.o: No such file or directory

error: failed to run custom build command for `unwinder v0.1.1`

I purpose of this is to quickly obfuscate features via rust + OLLVM....
https://vrls.ws/posts/2023/06/obfuscating-rust-binaries-using-llvm-obfuscator-ollvm/

I've never tried to cross compile this code and I'm not completely sure if you can do so. I'll give it a try and let you know if I find any solution to your issue.

Not fully tested.

edit build.rs

extern crate nasm_rs;

fn main() {
    let out_dir = std::env::var("OUT_DIR").unwrap();
    nasm_rs::compile_library("gateway", &["src/gateway.asm"]).unwrap();
    println!("cargo:rerun-if-changed=src/gateway.asm");
    println!("cargo:rustc-link-search=native={}", out_dir);
    println!("cargo:rustc-link-lib=static=gateway");
}

edit gateway.asm

section .data
    struc   SPOOFER
        .FirstFrameFunctionPointer       resq 1
        .SecondFrameFunctionPointer      resq 1
        .JmpRbxGadget                    resq 1
        .AddRspXGadget                   resq 1

        .FirstFrameSize                  resq 1
        .SecondFrameSize                 resq 1
        .JmpRbxGadgetFrameSize           resq 1
        .AddRspXGadgetFrameSize          resq 1

        .StackOffsetWhereRbpIsPushed     resq 1

        .SpoofFunctionPointer            resq 1
        .ReturnAddress                   resq 1

        .Nargs                           resq 1
        .Arg01                           resq 1
        .Arg02                           resq 1
        .Arg03                           resq 1
        .Arg04                           resq 1
        .Arg05                           resq 1
        .Arg06                           resq 1
        .Arg07                           resq 1
        .Arg08                           resq 1
        .Arg09                           resq 1
        .Arg10                           resq 1
        .Arg11                           resq 1

        .Sys                           resd 0
        .SysId                           resd 0
    endstruc


section .text
	bits 64

    global add_numbers
    global spoof_call
    global get_current_rsp


add_numbers:
    mov rax, rdi
    add rax, rsi
    ret

get_current_rsp:
    mov rax, rsp
    add rax, 8
    ret

restore:
    mov     rsp, rbp
    mov     rbp, [rsp+08h]
    mov     rbx, [rsp+10h]
    ret


parameter_handler:
    cmp		qword [rcx + SPOOFER.Nargs], 11
    je		handle_eleven
    cmp		qword [rcx + SPOOFER.Nargs], 10
    je		handle_ten
    cmp		qword [rcx + SPOOFER.Nargs], 9
    je		handle_nine
    cmp		qword [rcx + SPOOFER.Nargs], 8
    je		handle_eight
    cmp		qword [rcx + SPOOFER.Nargs], 7
    je		handle_seven
    cmp		qword [rcx + SPOOFER.Nargs], 6
    je		handle_six
    cmp		qword [rcx + SPOOFER.Nargs], 5
    je		handle_five
    cmp		qword [rcx + SPOOFER.Nargs], 4
    je		handle_four
    cmp		qword [rcx + SPOOFER.Nargs], 3
    je		handle_three
    cmp		qword [rcx + SPOOFER.Nargs], 2
    je		handle_two
    cmp		qword [rcx + SPOOFER.Nargs], 1
    je 		handle_one
    cmp		qword [rcx + SPOOFER.Nargs], 0
    je 		handle_none
spoof_call:

    mov qword [rsp + 8], rbp
    mov     [rsp+10h], rbx
    mov     rbp, rsp

    lea rax, [rel restore]
    push    rax

    lea     rbx, [rsp]

    push   qword [rcx + SPOOFER.FirstFrameFunctionPointer]

    mov     rax, [rcx + SPOOFER.ReturnAddress]
    sub     rax, [rcx + SPOOFER.FirstFrameSize]

    sub     rsp, [rcx + SPOOFER.SecondFrameSize]
    mov     r10, [rcx + SPOOFER.StackOffsetWhereRbpIsPushed]
    mov     [rsp+r10], rax

    push   qword [rcx + SPOOFER.SecondFrameFunctionPointer]

    sub     rsp, [rcx + SPOOFER.JmpRbxGadgetFrameSize]
    push   qword [rcx + SPOOFER.JmpRbxGadget]
    sub     rsp, [rcx + SPOOFER.AddRspXGadgetFrameSize]

    push   qword [rcx + SPOOFER.AddRspXGadget]

    mov     r11, [rcx + SPOOFER.SpoofFunctionPointer]
    jmp     parameter_handler

handle_eleven:
    push	r15
    mov		r15, [rcx + SPOOFER.Arg11]
    mov		[rsp+60h], r15
    pop		r15
    jmp		handle_ten

handle_ten:
    push	r15
    mov		r15, [rcx + SPOOFER.Arg10]
    mov		[rsp+58h], r15
    pop		r15
    jmp		handle_nine

handle_nine:
    push	r15
    mov		r15, [rcx + SPOOFER.Arg09]
    mov		[rsp+50h], r15
    pop		r15
    jmp		handle_eight

handle_eight:
    push	r15
    mov		r15, [rcx + SPOOFER.Arg08]
    mov		[rsp+48h], r15
    pop		r15
    jmp		handle_seven

handle_seven:
    push	r15
    mov		r15, [rcx + SPOOFER.Arg07]
    mov		[rsp+40h], r15
    pop		r15
    jmp		handle_six

handle_six:
    push	r15
    mov		r15, [rcx + SPOOFER.Arg06]
    mov		[rsp+38h], r15
    pop		r15
    jmp		handle_five

handle_five:
    push	r15
    mov		r15, [rcx + SPOOFER.Arg05]
    mov		[rsp+30h], r15
    pop		r15
    jmp		handle_four

handle_four:
    mov		r9, [rcx + SPOOFER.Arg04]
    jmp		handle_three

handle_three:
    mov		r8, [rcx + SPOOFER.Arg03]
    jmp		handle_two

handle_two:
    mov		rdx, [rcx + SPOOFER.Arg02]
    jmp		handle_one

handle_one:
    cmp		qword [rcx + SPOOFER.Sys], 0
    jne		execute_syscall
    mov		rcx, [rcx + SPOOFER.Arg01]
    jmp		handle_none


handle_none:
    jmp		execute


execute:
    jmp     r11


execute_syscall:
    mov 	r10, [rcx + SPOOFER.Arg01]
    mov 	eax, [rcx + SPOOFER.SysId]
    mov 	rcx, [rcx + SPOOFER.Arg01]
    jmp 	r11

edit Cargo.toml

# add
[build-dependencies]
nasm-rs = "0.3.0"

test

use std::ffi::c_void;
use std::time::Instant;
use untitled1::call_function;

fn main() {
    let start_time = Instant::now();
    let k32 = dinvoke_rs::dinvoke::get_module_base_address("kernel32.dll");
    let sleep = dinvoke_rs::dinvoke::get_function_address(k32, "Sleep"); // Memory address of kernel32.dll!Sleep()
    let miliseconds = 5000i32;
    unsafe {
        call_function!(sleep, false, miliseconds);

    }
    let end_time = Instant::now();
    let elapsed_time = end_time - start_time;

    println!("Execution time: {} microseconds", elapsed_time.as_micros());
}

build cargo build --release --target x86_64-pc-windows-gnu

Great you solved it, thank you for the update!

Help me, if I use the asm you provided and compile it under msvc environment the indirect_syscall call is normal, when I try to modify the version of asm and compile it under gnu environment the indirect_syscall call exception