Skip to content
KitploitKITPLOIT
도구익스플로잇블로그
Log in
제출
도구익스플로잇블로그
제출

해킹, 침투 테스트 및 사이버 보안 도구를 당신의 보안 무기고에!

Kitploit은 해킹, 사이버 보안 및 침투 테스트 도구 디렉토리입니다. 최신 프로젝트 업데이트를 발견하여 취약점을 찾고, 시스템을 분석하고, 테스트를 자동화하고, 보안을 강화하세요.

··피드·문의·개인정보·© 2026 Kitploit

도구 디렉토리

카테고리

모든 카테고리 보기
Loading categories
DInvoke_rs — 임의의 비관리 코드를 동적으로 호출 | Kitploit
도구/GitHubGitHub/kudaes/dinvoke_rs
IDS/IPS EvasionShellcodePost-ExploitationBinary AnalysisRed TeamingPayload Development
GitHubkudaes/dinvoke_rs

DInvoke_rs

임의의 비관리 코드를 동적으로 호출

저장소 보기
36643143개월 전Kitploit 검토 완료

인기

모두 보기 →

커뮤니티에서 가장 많이 사용되는 도구를 찾아보세요.

모든 도구 탐색

도구 컬렉션을 둘러보세요

모든 도구 보기 →
공유

DInvoke_rs

Dinvoke의 Rust 포팅 버전입니다. DInvoke_rs는 PE 파싱, 동적 내보내기 함수 해석, 런타임 시 PE 플러그인 동적 로딩, API 후크 우회 등 다양한 용도로 사용할 수 있습니다.

기능:

  • Rust에서 문서화되지 않은 Windows API를 동적으로 해석하고 호출합니다.
  • 전략적 API 후크 우회를 가능하게 하는 프리미티브.
  • 간접 시스템 콜. x64 전용
  • 디스크 또는 메모리에서 직접 PE 모듈을 수동으로 매핑합니다.
  • PE 헤더 파싱.
  • PE 모듈을 디스크의 임의 모듈이 지원하는 섹션에 매핑합니다. OPSEC에 부적합
  • 매핑된 PE를 숨기기 위한 모듈 플럭추에이션(동시성 지원). OPSEC에 부적합
  • 예외 필터 + 하드웨어 중단점을 통한 시스템 콜 매개변수 스푸핑. x64 전용
  • 모듈 스톰핑 및 셸코드 플럭추에이션.
  • 템플릿 스톰핑.

크레딧

이 도구의 원본 C# 구현 제작자에게 모든 공로가 있습니다:

  • The Wover
  • FuzzySec (b33f)
  • cobbr

목차

  • 내보내기 함수 해석
  • 비관리 코드 동적 호출
  • 간접 시스템 콜 실행
  • 디스크 또는 메모리에서 PE 수동 매핑
  • 메모리 섹션 오버로드
  • 모듈 플럭추에이션
  • 하드웨어 중단점을 사용하여 시스템 콜 매개변수 스푸핑
  • 모듈 스톰핑 및 셸코드 플럭추에이션
  • 템플릿 스톰핑

사용법

이 크레이트를 프로젝트에 가져오려면 cargo.toml에 다음 줄을 추가하세요:```rust [dependencies] dinvoke_rs = "0.2.2"

# 예제
## 내보낸 API 확인

아래 예제에서는 DInvoke_rs를 사용하여 DLL(이 경우 `ntdll.dll`)의 내보낸 함수를 동적으로 찾아 호출하는 방법을 보여줍니다.

1) ntdll의 기본 주소를 가져옵니다.
2) `get_function_address()`를 사용하여 이름으로 `ntdll.dll` 내의 내보낸 함수를 찾습니다. 이는 DLL의 EAT를 탐색하고 구문 분석하여 수행됩니다.
3) `get_function_address_by_ordinal()`을 호출하여 서수(ordinal)로 내보낸 함수를 찾을 수도 있습니다.```rust

fn main() {

    // Dynamically obtain ntdll.dll's base address. 
    let ntdll = dinvoke_rs::dinvoke::get_module_base_address("ntdll.dll");

    if ntdll != 0 
    {
        println!("ntdll.dll base address is 0x{:X}", ntdll);
        
        // Dynamically obtain the address of a function by name.
        let nt_create_thread = dinvoke_rs::dinvoke::get_function_address(ntdll, "NtCreateThread");
        if nt_create_thread != 0
        {
            println!("NtCreateThread is at address 0x{:X}", nt_create_thread);
        }

        // Dynamically obtain the address of a function by ordinal.
        let ordinal_8 = dinvoke_rs::dinvoke::get_function_address_by_ordinal(ntdll, 8);
        if ordinal_8 != 0 
        {
            println!("The function with ordinal 8 is located at addresss 0x{:X}", ordinal_8);
        }
    }   
}

비관리 코드 호출

아래 예제에서는 DInvoke_rs를 사용하여 RtlAdjustPrivilege를 동적으로 호출함으로써 현재 프로세스 토큰에 대해 SeDebugPrivilege를 활성화합니다. 이러한 종류의 실행은 Win32에 존재하는 모든 API 후크를 우회합니다. 또한 최종 PE의 가져오기 주소 테이블(Import Address Table)에 항목을 생성하지 않으므로, 실행하지 않고 PE의 동작을 탐지하기가 더 어려워집니다.```rust

fn main() {

// Dynamically obtain ntdll.dll's base address. 
let ntdll = dinvoke_rs::dinvoke::get_module_base_address("ntdll.dll");

if ntdll != 0 
{
    unsafe 
    {
        let func_ptr:  unsafe extern "system" fn (u32, u8, u8, *mut u8) -> i32; // Function header available at data::RtlAdjustPrivilege
        let ret: Option<i32>; // RtlAdjustPrivilege returns an NSTATUS value, which in Rust can be represented as an i32
        let privilege: u32 = 20; // This value matches with SeDebugPrivilege
        let enable: u8 = 1; // Enable the privilege
        let current_thread: u8 = 0; // Enable the privilege for the current process, not only for the current thread
        let e = u8::default(); // https://github.com/Kudaes/rust_tips_and_tricks/tree/main#transmute
        let enabled: *mut u8 = std::mem::transmute(&e); 
        dinvoke_rs::dinvoke::dynamic_invoke!(ntdll,"RtlAdjustPrivilege",func_ptr,ret,privilege,enable,current_thread,enabled); 

        match ret {
            Some(x) => 
            	if x == 0 { println!("NTSTATUS == Success. Privilege enabled."); } 
              	else { println!("[x] NTSTATUS == {:X}", x as u32); },
            None => panic!("[x] Error!"),
        }
    } 
}   

}

## 간접 syscall 실행

다음 예제에서는 `NtQueryInformationProcess` 함수에 해당하는 syscall을 실행하기 위해 DInvoke_rs를 사용합니다. 매크로 `execute_syscall!()` 는 원하는 syscall을 수행하는 데 필요한 셸코드를 동적으로 할당하고 실행하므로, `ntdll.dll`에 존재하는 모든 후크를 우회합니다. 할당된 메모리는 syscall이 반환되면 해제되어, 실행 권한이 있는 메모리 페이지가 영구적으로 존재하는 것을 방지합니다.```rust

use std::mem::size_of;
use windows::Win32::System::Threading::{GetCurrentProcess, PROCESS_BASIC_INFORMATION};
use dinvoke_rs::data::{NtQueryInformationProcess, PVOID};

fn main() {

    unsafe 
    {
        let function_type:NtQueryInformationProcess;
        let ret: Option<i32>; //NtQueryInformationProcess returns a NTSTATUS, which is a i32.
        let handle = GetCurrentProcess();
        let p = PROCESS_BASIC_INFORMATION::default();
        let process_information: PVOID = std::mem::transmute(&p); 
        let r = u32::default();
        let return_length: *mut u32 = std::mem::transmute(&r);
        dinvoke_rs::dinvoke::execute_syscall!(
            "NtQueryInformationProcess",
            function_type,
            ret,
            handle,
            0,
            process_information,
            size_of::<PROCESS_BASIC_INFORMATION>() as u32,
            return_length
        );

        let pbi: *mut PROCESS_BASIC_INFORMATION;
        match ret {
            Some(x) => 
                if x == 0 {
                    pbi = std::mem::transmute(process_information);
                    let pbi = *pbi;
                    println!("The Process Environment Block base address is 0x{:X}", pbi.PebBaseAddress as u64);
                },
            None => println!("[x] Error executing direct syscall for NtQueryInformationProcess."),
        }  

    }
}

수동 PE 매핑

이 예제에서 DInvoke_rs는 EDR 후크가 없는 ntdll.dll의 새 복사본을 수동으로 매핑하는 데 사용됩니다. 그런 다음 해당 새 ntdll.dll 복사본을 사용하여 원하는 함수를 실행할 수 있습니다.

이 수동 매핑은 메모리에서도 실행할 수 있으며(이 경우 manually_map_module() 사용), 전형적인 reflective dll injection을 수행할 수 있게 해줍니다.```rust

use dinvoke_rs::data::PeMetadata;

fn main() {

unsafe 
{

    let ntdll: (PeMetadata, usize) = dinvoke_rs::manualmap::read_and_map_module(r"C:\Windows\System32\ntdll.dll", true, false).unwrap();

    let func_ptr:  unsafe extern "system" fn (u32, u8, u8, *mut u8) -> i32; // Function header available at data::RtlAdjustPrivilege
    let ret: Option<i32>; // RtlAdjustPrivilege returns an NSTATUS value, which is an i32
    let privilege: u32 = 20; // This value matches with SeDebugPrivilege
    let enable: u8 = 1; // Enable the privilege
    let current_thread: u8 = 0; // Enable the privilege for the current process, not only for the current thread
    let e = u8::default();
    let enabled: *mut u8 = std::mem::transmute(&e); 
    dinvoke_rs::dinvoke::dynamic_invoke!(ntdll.1,"RtlAdjustPrivilege",func_ptr,ret,privilege,enable,current_thread,enabled);

    match ret {
        Some(x) => 
            if x == 0 { println!("NTSTATUS == Success. Privilege enabled."); } 
            else { println!("[x] NTSTATUS == {:X}", x as u32); },
        None => panic!("[x] Error!"),
    }

}

}

## 메모리 섹션 오버로드
다음 샘플에서는 DInvoke_rs를 사용하여 파일 지원 메모리 섹션(file-backed memory section)을 생성한 후, PE를 수동으로 매핑하여 이를 오버로드합니다. 메모리 섹션은 기본적으로 `%WINDIR%\System32\`에 있는 합법적인 파일을 가리키지만, 다른 디코이 모듈도 사용할 수 있습니다.

이 오버로드는 메모리에서 PE를 매핑하여 실행할 수도 있습니다(다음 예제에서 볼 수 있음). 이를 통해 페이로드를 디스크에 쓰지 않고 오버로드를 수행할 수 있습니다.```rust

use dinvoke_rs::data::PeMetadata;

fn main() {

    unsafe 
    {

        let payload: Vec<u8> = your_download_function();
도구 다운로드