Projects STRLCPY ekko-rs Commits b6e6be9f
🤬
  • Added functionality for dumping CONTEXT structure.

  • Loading...
  • memN0ps committed 2 years ago
    b6e6be9f
    1 parent ee765259
  • ■ ■ ■ ■ ■ ■
    src/ekko.rs
    1  -use std::{
    2  - ffi::c_void,
    3  - mem::{zeroed},
    4  - ptr::{null_mut},
    5  -};
    6 1  use ntapi::winapi::um::errhandlingapi::GetLastError;
     2 +use std::{ffi::c_void, mem::zeroed, ptr::null_mut};
    7 3  use windows_sys::Win32::{
    8 4   Foundation::{HANDLE, UNICODE_STRING},
    9 5   System::{
    10 6   Diagnostics::Debug::{CONTEXT, IMAGE_NT_HEADERS64},
    11 7   LibraryLoader::{GetModuleHandleA, GetProcAddress, LoadLibraryA},
    12  - Memory::{VirtualProtect, PAGE_EXECUTE_READ, PAGE_READWRITE},
     8 + Memory::{VirtualProtect, PAGE_EXECUTE_READ, PAGE_PROTECTION_FLAGS, PAGE_READWRITE},
    13 9   SystemServices::IMAGE_DOS_HEADER,
    14 10   Threading::{
    15 11   CreateEventW, CreateTimerQueue, CreateTimerQueueTimer, DeleteTimerQueue, SetEvent,
    skipped 22 lines
    38 34   // Creates or opens a named or unnamed event object.
    39 35   // https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-createeventw
    40 36   let h_event = unsafe { CreateEventW(null_mut(), 0, 0, null_mut()) };
     37 + log::info!("[+] h_event: {:#x}", h_event);
    41 38   
    42 39   // Creates a queue for timers. Timer-queue timers are lightweight objects that enable you to specify a callback function to be called at a specified time.
    43 40   // https://learn.microsoft.com/en-us/windows/win32/api/threadpoollegacyapiset/nf-threadpoollegacyapiset-createtimerqueue
    44 41   let h_timer_queue = unsafe { CreateTimerQueue() };
     42 + log::info!("[+] h_timer_queue: {:#x}", h_timer_queue);
    45 43   
    46 44   let nt_continue = unsafe {
    47 45   GetProcAddress(
    skipped 37 lines
    85 83   log::info!("[+] Calling CreateTimerQueueTimer with ctx_thread");
    86 84   // Creates a timer-queue timer. This timer expires at the specified due time, then after every specified period. When the timer expires, the callback function is called.
    87 85   // https://learn.microsoft.com/en-us/windows/win32/api/threadpoollegacyapiset/nf-threadpoollegacyapiset-createtimerqueuetimer
    88  - let success = unsafe {
     86 + let result = unsafe {
    89 87   CreateTimerQueueTimer(
    90 88   &mut h_new_timer,
    91 89   h_timer_queue,
    skipped 5 lines
    97 95   )
    98 96   };
    99 97   
    100  - if success != 0 {
    101  - unsafe {
    102  - log::info!("[+] Calling WaitForSingleObject for 0x32 ms");
    103  - // Waits until the specified object is in the signaled state or the time-out interval elapses.
    104  - // https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
    105  - WaitForSingleObject(h_event, 0x32);
    106  - }
     98 + if result == 0 {
     99 + panic!("[!] CreateTimerQueueTimer failed with error: {}", unsafe {
     100 + GetLastError()
     101 + });
     102 + }
    107 103   
    108  - log::info!("[+] Copying ctx_thread to rop chains");
    109  - let mut rop_prot_rw = ctx_thread.clone();
    110  - let mut rop_mem_enc = ctx_thread.clone();
    111  - let mut rop_delay = ctx_thread.clone();
    112  - let mut rop_mem_dec = ctx_thread.clone();
    113  - let mut rop_prot_rx = ctx_thread.clone();
    114  - let mut rop_set_evt = ctx_thread.clone();
     104 + log::info!("[+] Calling WaitForSingleObject for 0x32 ms");
     105 + // Waits until the specified object is in the signaled state or the time-out interval elapses.
     106 + // https://learn.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitforsingleobject
     107 + unsafe {
     108 + WaitForSingleObject(h_event, 0x32);
     109 + }
    115 110   
    116  - log::info!("[+] Building ROP chain");
    117  - // pub unsafe extern "system" fn VirtualProtect(lpaddress: *const c_void, dwsize: usize, flnewprotect: PAGE_PROTECTION_FLAGS, lpfloldprotect: *mut PAGE_PROTECTION_FLAGS) -> BOOL
    118  - // https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Memory/fn.VirtualProtect.html
    119  - rop_prot_rw.Rsp = -8 as isize as u64;
    120  - rop_prot_rw.Rip = VirtualProtect as u64;
    121  - rop_prot_rw.Rcx = image_base as u64;
    122  - rop_prot_rw.Rdx = image_size as u64;
    123  - rop_prot_rw.R8 = PAGE_READWRITE as u64;
    124  - rop_prot_rw.R9 = &mut old_protect as *mut u32 as u64;
     111 + log::info!("[+] Copying ctx_thread to rop chains");
     112 + let mut rop_prot_rw = ctx_thread.clone();
     113 + let mut rop_mem_enc = ctx_thread.clone();
     114 + let mut rop_delay = ctx_thread.clone();
     115 + let mut rop_mem_dec = ctx_thread.clone();
     116 + let mut rop_prot_rx = ctx_thread.clone();
     117 + let mut rop_set_evt = ctx_thread.clone();
    125 118   
    126  - // pub unsafe extern "system" fn SystemFunction036(randombuffer: *mut c_void, randombufferlength: u32) -> BOOLEAN
    127  - // https://docs.rs/windows-sys/latest/windows_sys/Win32/Security/Authentication/Identity/fn.SystemFunction036.html
    128  - rop_mem_enc.Rsp = -8 as isize as u64;
    129  - rop_mem_enc.Rip = sys_func032.unwrap() as u64;
    130  - rop_mem_enc.Rcx = &mut img as *mut UNICODE_STRING as *mut c_void as u64;
    131  - rop_mem_enc.Rdx = key.Length as u64;
     119 + log::info!("[+] Building ROP chain");
     120 + // pub unsafe extern "system" fn VirtualProtect(lpaddress: *const c_void, dwsize: usize, flnewprotect: PAGE_PROTECTION_FLAGS, lpfloldprotect: *mut PAGE_PROTECTION_FLAGS) -> BOOL
     121 + // https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Memory/fn.VirtualProtect.html
     122 + rop_prot_rw.Rsp = -8 as isize as u64;
     123 + rop_prot_rw.Rip = VirtualProtect as u64;
     124 + rop_prot_rw.Rcx = image_base as u64;
     125 + rop_prot_rw.Rdx = image_size as u64;
     126 + rop_prot_rw.R8 = PAGE_READWRITE as u64;
     127 + rop_prot_rw.R9 = &mut old_protect as *mut PAGE_PROTECTION_FLAGS as u64;
     128 + dump_virtual_protect_context(&rop_prot_rw);
    132 129  
    133  - // pub unsafe extern "system" fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WIN32_ERROR
    134  - // https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Threading/fn.WaitForSingleObject.html
    135  - rop_delay.Rsp = -8 as isize as u64;
    136  - rop_delay.Rip = WaitForSingleObject as u64;
    137  - rop_delay.Rcx = -1 as isize as u64; // NtCurrentProcess
    138  - rop_delay.Rdx = sleep_time as u64;
     130 + // pub unsafe extern "system" fn SystemFunction036(randombuffer: *mut c_void, randombufferlength: u32) -> BOOLEAN
     131 + // https://docs.rs/windows-sys/latest/windows_sys/Win32/Security/Authentication/Identity/fn.SystemFunction036.html
     132 + rop_mem_enc.Rsp = -8 as isize as u64;
     133 + rop_mem_enc.Rip = sys_func032.unwrap() as u64;
     134 + rop_mem_enc.Rcx = &mut img as *mut UNICODE_STRING as *mut c_void as u64;
     135 + rop_mem_enc.Rdx = key.Length as u64;
     136 + dump_system_function036_context(&rop_mem_enc);
    139 137   
    140  - // pub unsafe extern "system" fn SystemFunction036(randombuffer: *mut c_void, randombufferlength: u32) -> BOOLEAN
    141  - // https://docs.rs/windows-sys/latest/windows_sys/Win32/Security/Authentication/Identity/fn.SystemFunction036.html
    142  - rop_mem_dec.Rsp = -8 as isize as u64;
    143  - rop_mem_dec.Rip = sys_func032.unwrap() as u64;
    144  - rop_mem_dec.Rcx = &mut img as *mut UNICODE_STRING as *mut c_void as u64;
    145  - rop_mem_dec.Rdx = key.Length as u64;
     138 + // pub unsafe extern "system" fn WaitForSingleObject(hhandle: HANDLE, dwmilliseconds: u32) -> WIN32_ERROR
     139 + // https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Threading/fn.WaitForSingleObject.html
     140 + rop_delay.Rsp = -8 as isize as u64;
     141 + rop_delay.Rip = WaitForSingleObject as u64;
     142 + rop_delay.Rcx = -1 as isize as u64; // NtCurrentProcess
     143 + rop_delay.Rdx = sleep_time as u64;
     144 + dump_wait_for_single_object_context(&rop_delay);
    146 145   
    147  - // pub unsafe extern "system" fn VirtualProtect(lpaddress: *const c_void, dwsize: usize, flnewprotect: PAGE_PROTECTION_FLAGS, lpfloldprotect: *mut PAGE_PROTECTION_FLAGS) -> BOOL
    148  - // https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Memory/fn.VirtualProtect.html
    149  - rop_prot_rx.Rsp = -8 as isize as u64;
    150  - rop_prot_rx.Rip = VirtualProtect as u64;
    151  - rop_prot_rx.Rcx = image_base as u64;
    152  - rop_prot_rx.Rdx = image_size as u64;
    153  - rop_prot_rx.R8 = PAGE_EXECUTE_READ as u64;
    154  - rop_prot_rw.R9 = &mut old_protect as *mut u32 as u64;
     146 + // pub unsafe extern "system" fn SystemFunction036(randombuffer: *mut c_void, randombufferlength: u32) -> BOOLEAN
     147 + // https://docs.rs/windows-sys/latest/windows_sys/Win32/Security/Authentication/Identity/fn.SystemFunction036.html
     148 + rop_mem_dec.Rsp = -8 as isize as u64;
     149 + rop_mem_dec.Rip = sys_func032.unwrap() as u64;
     150 + rop_mem_dec.Rcx = &mut img as *mut UNICODE_STRING as *mut c_void as u64;
     151 + rop_mem_dec.Rdx = key.MaximumLength as u64;
     152 + dump_system_function036_context(&rop_mem_dec);
    155 153   
    156  - // https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Threading/fn.SetEvent.html
    157  - // pub unsafe extern "system" fn SetEvent(hevent: HANDLE) -> BOOL
    158  - rop_set_evt.Rsp = -8 as isize as u64;
    159  - rop_set_evt.Rip = SetEvent as u64;
    160  - rop_set_evt.Rcx = h_event as u64;
     154 + // pub unsafe extern "system" fn VirtualProtect(lpaddress: *const c_void, dwsize: usize, flnewprotect: PAGE_PROTECTION_FLAGS, lpfloldprotect: *mut PAGE_PROTECTION_FLAGS) -> BOOL
     155 + // https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Memory/fn.VirtualProtect.html
     156 + rop_prot_rx.Rsp = -8 as isize as u64;
     157 + rop_prot_rx.Rip = VirtualProtect as u64;
     158 + rop_prot_rx.Rcx = image_base as u64;
     159 + rop_prot_rx.Rdx = image_size as u64;
     160 + rop_prot_rx.R8 = PAGE_EXECUTE_READ as u64;
     161 + rop_prot_rx.R9 = &mut old_protect as *mut u32 as u64;
     162 + dump_virtual_protect_context(&rop_prot_rx);
    161 163   
    162  - log::info!("[+] Rop chain built");
    163  - log::info!("[+] Queue timers");
    164  - unsafe {
    165  - let result = CreateTimerQueueTimer(
    166  - &mut h_new_timer,
    167  - h_timer_queue,
    168  - std::mem::transmute(nt_continue),
    169  - &rop_prot_rw as *const _ as *const _,
    170  - 100,
    171  - 0,
    172  - WT_EXECUTEINTIMERTHREAD,
    173  - );
    174  - if result == 0 {
    175  - panic!("[!] Failed calling CreateTimerQueueTimer with rop_prot_rw (VirtualProtect RW) {:#x}", GetLastError());
    176  - }
     164 + // https://docs.rs/windows-sys/latest/windows_sys/Win32/System/Threading/fn.SetEvent.html
     165 + // pub unsafe extern "system" fn SetEvent(hevent: HANDLE) -> BOOL
     166 + rop_set_evt.Rsp = -8 as isize as u64;
     167 + rop_set_evt.Rip = SetEvent as u64;
     168 + rop_set_evt.Rcx = h_event as u64;
     169 + dump_set_event_context(&rop_set_evt);
    177 170   
    178  - let result = CreateTimerQueueTimer(
    179  - &mut h_new_timer,
    180  - h_timer_queue,
    181  - std::mem::transmute(nt_continue),
    182  - &rop_mem_enc as *const _ as *const _,
    183  - 100,
    184  - 0,
    185  - WT_EXECUTEINTIMERTHREAD,
    186  - );
    187  - if result == 0 {
    188  - panic!("[!] Failed calling CreateTimerQueueTimer with rop_mem_enc (SystemFunction036) {:#x}", GetLastError());
    189  - }
     171 + log::info!("[+] Rop chain built");
     172 + log::info!("[+] Queue timers");
    190 173   
    191  - let result = CreateTimerQueueTimer(
    192  - &mut h_new_timer,
    193  - h_timer_queue,
    194  - std::mem::transmute(nt_continue),
    195  - &rop_delay as *const _ as *const _,
    196  - 100,
    197  - 0,
    198  - WT_EXECUTEINTIMERTHREAD,
    199  - );
    200  - if result == 0 {
    201  - panic!("[!] Failed calling CreateTimerQueueTimer with rop_delay (WaitForSingleObject) {:#x}", GetLastError());
    202  - }
     174 + let result = unsafe {
     175 + CreateTimerQueueTimer(
     176 + &mut h_new_timer,
     177 + h_timer_queue,
     178 + std::mem::transmute(nt_continue),
     179 + &rop_prot_rw as *const _ as *const _,
     180 + 100,
     181 + 0,
     182 + WT_EXECUTEINTIMERTHREAD,
     183 + )
     184 + };
     185 + if result == 0 {
     186 + panic!(
     187 + "[!] Failed calling CreateTimerQueueTimer with rop_prot_rw (VirtualProtect RW) {:#x}",
     188 + unsafe { GetLastError() }
     189 + );
     190 + }
    203 191   
    204  - let result = CreateTimerQueueTimer(
    205  - &mut h_new_timer,
    206  - h_timer_queue,
    207  - std::mem::transmute(nt_continue),
    208  - &rop_mem_dec as *const _ as *const _,
    209  - 100,
    210  - 0,
    211  - WT_EXECUTEINTIMERTHREAD,
    212  - );
    213  - if result == 0 {
    214  - panic!("[!] Failed calling CreateTimerQueueTimer with rop_mem_dec (SystemFunction036) {:#x}", GetLastError());
    215  - }
     192 + let result = unsafe {
     193 + CreateTimerQueueTimer(
     194 + &mut h_new_timer,
     195 + h_timer_queue,
     196 + std::mem::transmute(nt_continue),
     197 + &rop_mem_enc as *const _ as *const _,
     198 + 100,
     199 + 0,
     200 + WT_EXECUTEINTIMERTHREAD,
     201 + )
     202 + };
     203 + if result == 0 {
     204 + panic!(
     205 + "[!] Failed calling CreateTimerQueueTimer with rop_mem_enc (SystemFunction036) {:#x}",
     206 + unsafe { GetLastError() }
     207 + );
     208 + }
    216 209   
    217  - let result = CreateTimerQueueTimer(
    218  - &mut h_new_timer,
    219  - h_timer_queue,
    220  - std::mem::transmute(nt_continue),
    221  - &rop_prot_rx as *const _ as *const _,
    222  - 100,
    223  - 0,
    224  - WT_EXECUTEINTIMERTHREAD,
    225  - );
    226  - if result == 0 {
    227  - panic!("[!] Failed calling CreateTimerQueueTimer with rop_prot_rx (VirtualProtect RX) {:#x}", GetLastError());
    228  - }
     210 + let result = unsafe {
     211 + CreateTimerQueueTimer(
     212 + &mut h_new_timer,
     213 + h_timer_queue,
     214 + std::mem::transmute(nt_continue),
     215 + &rop_delay as *const _ as *const _,
     216 + 100,
     217 + 0,
     218 + WT_EXECUTEINTIMERTHREAD,
     219 + )
     220 + };
     221 + if result == 0 {
     222 + panic!(
     223 + "[!] Failed calling CreateTimerQueueTimer with rop_delay (WaitForSingleObject) {:#x}",
     224 + unsafe { GetLastError() }
     225 + );
     226 + }
    229 227   
    230  - let result = CreateTimerQueueTimer(
    231  - &mut h_new_timer,
    232  - h_timer_queue,
    233  - std::mem::transmute(nt_continue),
    234  - &rop_set_evt as *const _ as *const _,
    235  - 100,
    236  - 0,
    237  - WT_EXECUTEINTIMERTHREAD,
    238  - );
    239  - if result == 0 {
    240  - panic!("[!] Failed calling CreateTimerQueueTimer with rop_set_evt (SetEvent) {:#x}", GetLastError());
    241  - }
     228 + let result = unsafe {
     229 + CreateTimerQueueTimer(
     230 + &mut h_new_timer,
     231 + h_timer_queue,
     232 + std::mem::transmute(nt_continue),
     233 + &rop_mem_dec as *const _ as *const _,
     234 + 100,
     235 + 0,
     236 + WT_EXECUTEINTIMERTHREAD,
     237 + )
     238 + };
     239 + if result == 0 {
     240 + panic!(
     241 + "[!] Failed calling CreateTimerQueueTimer with rop_mem_dec (SystemFunction036) {:#x}",
     242 + unsafe { GetLastError() }
     243 + );
     244 + }
    242 245   
    243  - log::info!("[+] Waiting for event...");
     246 + let result = unsafe {
     247 + CreateTimerQueueTimer(
     248 + &mut h_new_timer,
     249 + h_timer_queue,
     250 + std::mem::transmute(nt_continue),
     251 + &rop_prot_rx as *const _ as *const _,
     252 + 100,
     253 + 0,
     254 + WT_EXECUTEINTIMERTHREAD,
     255 + )
     256 + };
     257 + if result == 0 {
     258 + panic!(
     259 + "[!] Failed calling CreateTimerQueueTimer with rop_prot_rx (VirtualProtect RX) {:#x}",
     260 + unsafe { GetLastError() }
     261 + );
     262 + }
    244 263   
    245  - WaitForSingleObject(h_event, INFINITE); //0xFFFFFFFF
     264 + let result = unsafe {
     265 + CreateTimerQueueTimer(
     266 + &mut h_new_timer,
     267 + h_timer_queue,
     268 + std::mem::transmute(nt_continue),
     269 + &rop_set_evt as *const _ as *const _,
     270 + 100,
     271 + 0,
     272 + WT_EXECUTEINTIMERTHREAD,
     273 + )
     274 + };
    246 275   
    247  - log::info!("[+] Finished waiting for event");
    248  - }
     276 + if result == 0 {
     277 + panic!(
     278 + "[!] Failed calling CreateTimerQueueTimer with rop_set_evt (SetEvent) {:#x}",
     279 + unsafe { GetLastError() }
     280 + );
    249 281   }
    250 282   
     283 + log::info!("[+] Waiting for event...");
     284 + 
     285 + unsafe {
     286 + WaitForSingleObject(h_event, INFINITE);
     287 + } //0xFFFFFFFF
     288 + 
     289 + log::info!("[+] Finished waiting for event");
     290 + 
    251 291   // Deletes a timer queue. Any pending timers in the queue are canceled and deleted.
    252 292   // https://learn.microsoft.com/en-us/windows/win32/api/threadpoollegacyapiset/nf-threadpoollegacyapiset-deletetimerqueue
    253 293   unsafe {
    skipped 18 lines
    272 312   };
    273 313  }
    274 314   
     315 +fn dump_virtual_protect_context(rop: &CONTEXT) {
     316 + log::info!("[+] RSP: {:#x} RIP: {:#x} -> VirtualProtect({:#x}, {:#x}, {:#x}, {:#x})" , rop.Rsp, rop.Rip, rop.Rcx, rop.Rdx, rop.R8, rop.R9);
     317 +}
     318 + 
     319 +fn dump_system_function036_context(rop: &CONTEXT) {
     320 + log::info!("[+] RSP: {:#x} RIP: {:#x} -> SystemFunction036({:#x}, {:#x})" , rop.Rsp, rop.Rip, rop.Rcx, rop.Rdx);
     321 +}
     322 + 
     323 +fn dump_wait_for_single_object_context(rop: &CONTEXT) {
     324 + log::info!("[+] RSP: {:#x} RIP: {:#x} -> WaitForSingleObject({:#x}, {:#x})" , rop.Rsp, rop.Rip, rop.Rcx, rop.Rdx);
     325 +}
     326 + 
     327 +fn dump_set_event_context(rop: &CONTEXT) {
     328 + log::info!("[+] RSP: {:#x} RIP: {:#x} -> SetEvent({:#x})" , rop.Rsp, rop.Rip, rop.Rcx);
     329 +}
Please wait...
Page is in error, reload to recover