Litcrypt replaced by litcrypt2

This commit is contained in:
Kudaes
2023-11-14 16:29:57 +01:00
parent 1e13ef6e9d
commit cfc12c2f67
10 changed files with 26 additions and 27 deletions
+16 -16
View File
@@ -18,18 +18,18 @@ All the credits go to the creators of the original C# implementation of this too
* [FuzzySec (b33f)](https://twitter.com/FuzzySec)
* [cobbr](https://twitter.com/cobbr_io)
## Content
- [Resolve exported function](#Resolving-Exported-APIs)
- [Dynamically invoke unmanaged code](#Invoking-Unmanaged-Code)
- [Execute Indirect Syscall](#Executing-indirect-syscall)
- [Manually map a PE from disk or memory](#Manual-PE-mapping)
- [Overload memory section](#Overload-memory-section)
- [Module fluctuation](#Module-fluctuation)
- [Use hardware breakpoints to spoof syscall parameters](#Syscall-parameters-spoofing)
# Usage
Since we are using [LITCRYPT](https://github.com/anvie/litcrypt.rs) plugin to obfuscate string literals, it is required to set up the environment variable LITCRYPT_ENCRYPT_KEY before compiling the code:
C:\Users\User\Desktop\DInvoke.rs\dinvoke_rs> set LITCRYPT_ENCRYPT_KEY="yoursupersecretkey"
After that, you can open the project using your favorite IDE and start implementing your own code using all the functionalities offered by DInvoke_rs.
C:\Users\User\Desktop\DInvoke.rs\dinvoke_rs> code .
# Example 1 - Resolving Exported APIs
## Resolving Exported APIs
The example below demonstrates how to use DInvoke_rs to dynamically find and call exports of a DLL (ntdll.dll in this case).
@@ -66,7 +66,7 @@ fn main() {
```
# Example 2 - Invoking Unmanaged Code
## Example 2 - Invoking Unmanaged Code
In the example below, we use DInvoke_rs to dynamically call RtlAdjustPrivilege in order to enable SeDebugPrivilege for the current process token. This kind of execution will bypass any API hooks present in Win32. Also, it won't create any entry on the final PE Import Address Table, making it harder to detect the PE's behaviour without executing it.
```rust
@@ -102,7 +102,7 @@ fn main() {
```
# Example 3 - Executing indirect syscall
## Example 3 - Executing indirect syscall
In the next example, we use DInvoke_rs to execute the syscall that corresponds to the function NtQueryInformationProcess. Since the macro dinvoke::execute_syscall!() dynamically allocates and executes the shellcode required to perform the desired syscall, all hooks present in ntdll.dll are bypassed. The memory allocated is release once the syscall returns, avoiding the permanent presence of memory pages with execution permission.
```rust
@@ -149,7 +149,7 @@ fn main() {
```
# Example 4 - Manual PE mapping
## Example 4 - Manual PE mapping
In this example, DInvoke_rs is used to manually map a fresh copy of ntdll.dll, without any EDR hooks. Then that fresh ntdll.dll copy can be used to execute any desired function.
This manual map can also be executed from memory (use manually_map_module() in that case), allowing the perform the classic reflective dll injection.
@@ -186,7 +186,7 @@ fn main() {
```
# Example 5 - Overload memory section
## Example 5 - Overload memory section
In the following sample, DInvoke_rs is used to create a file-backed memory section, overloading it afterwards by manually mapping a PE. The memory section will point to a legitimate file located in %WINDIR%\System32\ by default, but any other decoy module can be used.
This overload can also be executed mapping a PE from memory (as it is shown in the following example), allowing to perform the overload without writing the payload to disk.
@@ -224,7 +224,7 @@ fn main() {
```
# Example 6 - Module fluctuation
## Example 6 - Module fluctuation
DInvoke_rs allows to hide mapped PEs when they are not being used, making it harder for EDR memory inspection to detect the presence of a suspicious dll in your process.
For example, lets say we want to map a fresh copy of ntdll.dll in order to evade EDR hooks. Since two ntdll.dll in the same process could be considered a suspicious behaviour, we can map ntdll and hide it whenever we are not using it. This is very similar to the shellcode fluctuation technique, althought in this scenario we can take advantage of the fact that we are mapping a PE into a legitimate file-backed memory section, so we can replace the ntdll's content for the original decoy module's content that the section is pointing to.
@@ -277,7 +277,7 @@ fn main() {
```
# Example 7 - Syscall parameters spoofing
## Example 7 - Syscall parameters spoofing
In order to spoof the first 4 parameters of a syscall, DInvoke_rs has support for hardware breakpoints in combination with exception handlers. This allows to send not malicious parameters to a NT function, and after the EDR has inspected them, they are replaced by the original parameters before the syscall instruction is executed. For further information, check out the repository where the original idea comes from: [TamperingSyscalls](https://github.com/rad9800/TamperingSyscalls).
For now, this feature is implemented for the functions NtOpenProcess, NtAllocateVirtualMemory, NtProtectVirtualMemory, NtWriteVirtualMemory and NtCreateThreadEx. In order to use it, it's just needed to activate the feature, set the exception handler and call the desired function through Dinvoke.
-1
View File
@@ -5,7 +5,6 @@ edition = "2021"
# From https://stackoverflow.com/questions/29008127/why-are-rust-executables-so-huge
[profile.release]
opt-level = 'z' # Optimize for size.
strip = true
[dependencies]
+1 -1
View File
@@ -12,7 +12,7 @@ strip = true
data = { path = "../data" }
libc = "0.2.101"
winproc = "0.6.4"
litcrypt = "0.3"
litcrypt2 = "0.1.0"
winapi = "*"
rand = "*"
+2 -2
View File
@@ -1,5 +1,5 @@
#[macro_use]
extern crate litcrypt;
extern crate litcrypt2;
use_litcrypt!();
use std::cell::UnsafeCell;
@@ -16,7 +16,7 @@ use data::{ApiSetNamespace, ApiSetNamespaceEntry, ApiSetValueEntry, DLL_PROCESS_
PVOID, PeMetadata, CONTEXT, NtAllocateVirtualMemoryArgs, EXCEPTION_POINTERS, NtOpenProcessArgs, CLIENT_ID, PROCESS_QUERY_LIMITED_INFORMATION, NtProtectVirtualMemoryArgs,
PAGE_READONLY, NtWriteVirtualMemoryArgs, ExceptionHandleFunction, PS_ATTRIBUTE_LIST, NtCreateThreadExArgs, LptopLevelExceptionFilter};
use libc::c_void;
use litcrypt::lc;
use litcrypt2::lc;
use winproc::Process;
use winapi::shared::ntdef::LARGE_INTEGER;
use rand::Rng;
+1 -1
View File
@@ -12,7 +12,7 @@ strip = true
rand = "*"
manualmap = { path = "../manualmap" }
data = { path = "../data" }
litcrypt = "0.3"
litcrypt2 = "0.1.0"
dinvoke = { path = "../dinvoke" }
[dependencies.windows]
+1 -1
View File
@@ -1,5 +1,5 @@
#[macro_use]
extern crate litcrypt;
extern crate litcrypt2;
use_litcrypt!();
use std::{collections::HashMap, cell::UnsafeCell};
+1 -1
View File
@@ -11,7 +11,7 @@ strip = true
[dependencies]
dinvoke = { path = "../dinvoke" }
data = { path = "../data" }
litcrypt = "0.3"
litcrypt2 = "0.1.0"
os_info = { version = "3.0", default-features = false }
winapi = "*"
+2 -2
View File
@@ -1,5 +1,5 @@
#[macro_use]
extern crate litcrypt;
extern crate litcrypt2;
use_litcrypt!();
@@ -24,7 +24,7 @@ use data::{IMAGE_FILE_HEADER, IMAGE_OPTIONAL_HEADER64, MEM_COMMIT, MEM_RESERVE,
SECTION_MEM_READ, SECTION_MEM_WRITE, FILE_EXECUTE, FILE_READ_ATTRIBUTES, SYNCHRONIZE, FILE_READ_DATA, FILE_SHARE_READ, FILE_SHARE_DELETE,
FILE_SYNCHRONOUS_IO_NONALERT, FILE_NON_DIRECTORY_FILE, SECTION_ALL_ACCESS, SEC_IMAGE, PeManualMap};
use litcrypt::lc;
use litcrypt2::lc;
/// Manually maps a PE from disk to the memory of the current process.
+1 -1
View File
@@ -12,7 +12,7 @@ strip = true
dinvoke = { path = "../dinvoke" }
data = { path = "../data" }
manualmap = { path = "../manualmap" }
litcrypt = "0.3"
litcrypt2 = "0.1.0"
winproc = "0.6.4"
rand = "0.8.4"
+1 -1
View File
@@ -1,5 +1,5 @@
#[macro_use]
extern crate litcrypt;
extern crate litcrypt2;
use_litcrypt!();
use std::{env, fs, path::Path};