summaryrefslogtreecommitdiffhomepage
path: root/src/system
diff options
context:
space:
mode:
authormidipix <writeonce@midipix.org>2015-07-27 04:01:18 -0400
committermidipix <writeonce@midipix.org>2015-07-27 04:01:18 -0400
commitdd89bb8ad4fe184a34b5dbdda237e640fc82121b (patch)
tree5e80d2da35f5892f92be29f57982b2708e6bd99b /src/system
parentdcdadc2702712fa750ed255ed1dfa354522797a0 (diff)
downloadntapi-dd89bb8ad4fe184a34b5dbdda237e640fc82121b.tar.bz2
ntapi-dd89bb8ad4fe184a34b5dbdda237e640fc82121b.tar.xz
entered advanced internal development stage.
Diffstat (limited to 'src/system')
-rw-r--r--src/system/ntapi_tt_get_csr_port_handle_addr_by_logic.c197
-rw-r--r--src/system/ntapi_tt_get_system_directory.c257
-rw-r--r--src/system/ntapi_tt_get_system_info_snapshot.c89
3 files changed, 543 insertions, 0 deletions
diff --git a/src/system/ntapi_tt_get_csr_port_handle_addr_by_logic.c b/src/system/ntapi_tt_get_csr_port_handle_addr_by_logic.c
new file mode 100644
index 0000000..3f38067
--- /dev/null
+++ b/src/system/ntapi_tt_get_csr_port_handle_addr_by_logic.c
@@ -0,0 +1,197 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+/************************************************************/
+/* beginning with version 6.0, explicit thread registration */
+/* with csrss is no longer required. the code below should */
+/* work with all known versions of NT, however it will only */
+/* be used when run on the now-obsolete versions of the OS. */
+/************************************************************/
+
+/**
+ Nebbett was pretty much right in his interpretation of
+ the csrss port message; and as long as one changes
+ uint32_t to uintptr_t (especially when it comes to the
+ unknown parameters), then the structures behave as
+ expected according to his book.
+
+ SysInternals: ProcessExplorer: csrss.exe: the stack shows
+ a thread in csrsrv.dll that has CsrUnhandledExceptionFilter
+ as its start address, and ntdll!NtReplyWaitReceivePort as
+ its next function call. This suggests that csrss still
+ uses LPC (at least to some extent) for communication with
+ user processes.
+
+ Given the above, we may deduce that CsrClientCallServer
+ contains a call to ZwRequestWaitReplyPort. Assuming
+ the machine code in ntdll is as optimized as possible,
+ we may then conclude that on x86 machines, this would be
+ an E8 call using relative 32-bit addressing on both NT32
+ and NT64.
+
+ On the 32-bit variant of the operating system, the first
+ argument is passed on the stack, and is normally expressed
+ in terms of an offset from the ds register.
+
+ On the 64-bit variant of the operating system, the first
+ argument is passed in the rcx register. Here, again,
+ machine code optimization suggests that the address of
+ CsrPortHandle will be provided as a 32-bit relative address,
+ or else the code will be larger by several bytes.
+
+ The rest is based on simple logic and straight-forward
+ heuristics. Since we know the addresses of CsrClientCallSertver
+ and ZwRequestWaitReplyPort, we first find the call to the latter
+ function within the former. Once we have found that call, we
+ start going back to look for the argument-passing
+ opcode, and finally do the math to obtain the address of
+ CsrPortHandle.
+**/
+
+
+#if defined(__X86_MODEL)
+void ** __cdecl __ntapi_tt_get_csr_port_handle_addr_by_logic_i386(void)
+{
+ #define MAX_BYTES_BETWEEN_ARG1_PUSH_AND_E8_CALL 0x20
+ #define MAX_FN_BYTES_TO_TEST 0x800
+
+ typedef struct __attr_aligned__ (1) __attr_packed__ __x86_e8_call_signature {
+ unsigned char __opcode_current_e8;
+ unsigned char __addr_relative[4];
+ unsigned char __opcode_next_any;
+ } _x86_e8_call_signature;
+
+ typedef struct __attr_aligned__ (1) __attr_packed__ __x86_push_ds_signature {
+ unsigned char __push;
+ unsigned char __ds;
+ unsigned char __push_ds_arg;
+ } _x86_push_ds_signature;
+
+ unsigned char * ptr_test;
+ _x86_e8_call_signature * ptr_e8_call;
+ _x86_push_ds_signature * ptr_push_ds;
+ int32_t offset;
+
+ /* type-punned tyrants */
+ int32_t * prelative;
+ int32_t relative;
+ uintptr_t * pport_addr;
+
+
+ /* calling a function within the same library: assume E8 call */
+ for (offset = 0; offset < MAX_FN_BYTES_TO_TEST; offset++) {
+ ptr_test = (unsigned char *)__ntapi->csr_client_call_server
+ + offset;
+
+ if (*ptr_test == 0xE8) {
+ ptr_e8_call = (_x86_e8_call_signature *)ptr_test;
+
+ /* make our type-punned tyrant compiler happy */
+ prelative = (int32_t *)&(ptr_e8_call->__addr_relative);
+ relative = *prelative;
+
+ /* are we calling ZwRequestWaitReplyPort? */
+ if ((uintptr_t)(__ntapi->zw_request_wait_reply_port) ==
+ (uintptr_t)&(ptr_e8_call->__opcode_next_any)
+ + relative) {
+ /* assume ds relative address for arg1, go back to find it */
+ for (offset = 0; offset < MAX_BYTES_BETWEEN_ARG1_PUSH_AND_E8_CALL; offset++) {
+ ptr_push_ds = (_x86_push_ds_signature *)((uintptr_t)ptr_e8_call - offset);
+
+ if ((ptr_push_ds->__push == 0xFF) &&
+ (ptr_push_ds->__ds == 0x35)) {
+ /* bingo */
+ /* make our type-punned tyrant compiler happy */
+ pport_addr = (uintptr_t *)&(ptr_push_ds->__push_ds_arg);
+
+ /* all done */
+ return *(void ***)pport_addr;
+ }
+ }
+ }
+ }
+ }
+
+ /* CsrPortHandle not found */
+ return (void **)0;
+}
+#endif
+
+
+#if defined(__X86_64_MODEL)
+void ** __ntapi_tt_get_csr_port_handle_addr_by_logic_x86_64(void)
+{
+ #define MAX_BYTES_BETWEEN_ARG1_PUSH_AND_E8_CALL 0x20
+ #define MAX_FN_BYTES_TO_TEST 0x800
+
+ typedef struct __attr_aligned__ (1) __attr_packed__ __x86_e8_call_signature {
+ unsigned char __opcode_current_e8;
+ unsigned char __addr_relative[4];
+ unsigned char __opcode_next_any;
+ } _x86_e8_call_signature;
+
+ typedef struct __attr_aligned__ (1) __attr_packed__ __x86_move_rcx_rel_signature {
+ unsigned char __move;
+ unsigned char __rcx;
+ unsigned char __relative;
+ unsigned char __arg_32_relative[4];
+ unsigned char __opcode_next_any;
+ } _x86_move_rcx_rel_signature;
+
+ unsigned char * ptr_test;
+ _x86_e8_call_signature * ptr_e8_call;
+ _x86_move_rcx_rel_signature * ptr_move_rcx_rel;
+ int32_t offset;
+ int32_t relative;
+ int32_t * prelative; /* for type-punned tyrants */
+
+
+ /* calling a function within the same library: assume E8 call and 32-bit relative addressing */
+ for (offset = 0; offset < MAX_FN_BYTES_TO_TEST; offset++) {
+ ptr_test = (unsigned char *)__ntapi->csr_client_call_server
+ + offset;
+
+ if (*ptr_test == 0xE8) {
+ ptr_e8_call = (_x86_e8_call_signature *)ptr_test;
+
+ /* please our type-punned tyrant compiler */
+ prelative = (int32_t *)&(ptr_e8_call->__addr_relative);
+ relative = *prelative;
+
+ /* are we calling ZwRequestWaitReplyPort? */
+ /* comparing, not writing; ignore type-punned msgs. */
+ if ((uintptr_t)(__ntapi->zw_request_wait_reply_port) ==
+ (uintptr_t)&(ptr_e8_call->__opcode_next_any)
+ + relative) {
+ /* arg1 must be passed in rcx, so go back to find it */
+ for (offset = 0; offset < MAX_BYTES_BETWEEN_ARG1_PUSH_AND_E8_CALL; offset++) {
+ ptr_move_rcx_rel = (_x86_move_rcx_rel_signature *)((uintptr_t)ptr_e8_call - offset);
+
+ if ((ptr_move_rcx_rel->__move == 0x48) &&
+ (ptr_move_rcx_rel->__rcx == 0x8b) &&
+ (ptr_move_rcx_rel->__relative == 0x0d))
+ /* bingo */
+ /* make our type-punned tyrant compiler happy */
+ prelative = (int32_t *)&(ptr_move_rcx_rel->__arg_32_relative);
+ relative = *prelative;
+
+ /* all done */
+ return (void **)(
+ (uintptr_t)&ptr_move_rcx_rel->__opcode_next_any
+ + relative);
+ }
+ }
+ }
+ }
+
+ /* CsrPortHandle not found */
+ return (void **)0;
+}
+#endif
diff --git a/src/system/ntapi_tt_get_system_directory.c b/src/system/ntapi_tt_get_system_directory.c
new file mode 100644
index 0000000..28b9745
--- /dev/null
+++ b/src/system/ntapi_tt_get_system_directory.c
@@ -0,0 +1,257 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pemagine.h>
+#include <ntapi/nt_sysinfo.h>
+#include <ntapi/nt_memory.h>
+#include <ntapi/ntapi.h>
+#include <ntapi/nt_atomic.h>
+#include "ntapi_impl.h"
+
+int32_t __stdcall __ntapi_tt_get_system_directory_native_path(
+ __out nt_mem_sec_name * buffer,
+ __in uint32_t buffer_size,
+ __in wchar16_t * base_name,
+ __in uint32_t base_name_size,
+ __out nt_unicode_string * nt_path __optional)
+{
+ int32_t status;
+ wchar16_t * wch_src;
+ wchar16_t * wch_dst;
+ wchar16_t * wch_cap;
+ size_t maxlen_saved;
+ size_t info_size;
+
+ /* validation */
+ if (!buffer || !buffer_size)
+ return NT_STATUS_BUFFER_TOO_SMALL;
+ else if (base_name && !base_name_size)
+ return NT_STATUS_INVALID_PARAMETER_MIX;
+
+ /* init buffer */
+ buffer->section_name.strlen = 0;
+ buffer->section_name.maxlen = (uint16_t)(buffer_size - sizeof(nt_unicode_string));
+ buffer->section_name.buffer = buffer->section_name_buffer;
+
+ maxlen_saved = buffer->section_name.maxlen;
+ info_size = 0;
+
+ status = __ntapi->zw_query_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ pe_get_ntdll_module_handle(),
+ NT_MEMORY_SECTION_NAME,
+ buffer,
+ buffer_size,
+ &info_size);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* find directory portion */
+ wch_dst = buffer->section_name.buffer + (buffer->section_name.strlen / sizeof(wchar16_t));
+ wch_dst--;
+
+ while ((*wch_dst != '\\') && (wch_dst > buffer->section_name.buffer))
+ wch_dst--;
+
+ if (wch_dst == buffer->section_name.buffer)
+ return NT_STATUS_INTERNAL_ERROR;
+
+ /* base_name */
+ if (base_name) {
+ wch_dst++;
+ wch_src = base_name;
+ wch_cap = (wchar16_t *)((uintptr_t)wch_dst + base_name_size);
+
+ if ((uintptr_t)wch_cap - (uintptr_t)(buffer->section_name.buffer) > maxlen_saved)
+ return NT_STATUS_BUFFER_TOO_SMALL;
+
+ while (wch_dst < wch_cap) {
+ *wch_dst = *wch_src;
+ wch_dst++;
+ wch_src++;
+ }
+ }
+
+ /* null termination */
+ *wch_dst = 0;
+
+ /* nt_path */
+ if (nt_path)
+ __ntapi->rtl_init_unicode_string(
+ nt_path,
+ buffer->section_name.buffer);
+
+ return NT_STATUS_SUCCESS;
+}
+
+
+int32_t __stdcall __ntapi_tt_get_system_directory_handle(
+ __out void ** hsysdir,
+ __out nt_mem_sec_name * buffer __optional,
+ __in uint32_t buffer_size __optional)
+{
+ int32_t status;
+ nt_oa oa;
+ nt_iosb iosb;
+ nt_unicode_string path;
+ char _buffer[256];
+
+ /* validation */
+ if (!hsysdir)
+ return NT_STATUS_INVALID_PARAMETER_1;
+ else if (buffer_size && buffer_size < 0x20)
+ return NT_STATUS_BUFFER_TOO_SMALL;
+
+ /* buffer */
+ if (!buffer) {
+ buffer = (nt_mem_sec_name *)_buffer;
+ buffer_size = sizeof(_buffer);
+ __ntapi->tt_aligned_block_memset(buffer,0,sizeof(buffer));
+ }
+
+ /* sysdir path */
+ status = __ntapi_tt_get_system_directory_native_path(
+ buffer,
+ buffer_size,
+ (wchar16_t *)0,
+ 0,
+ &path);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* oa */
+ oa.len = sizeof(nt_oa);
+ oa.root_dir = (void *)0;
+ oa.obj_name = &path;
+ oa.obj_attr = 0;
+ oa.sec_desc = 0;
+ oa.sec_qos = 0;
+
+ /* open file/folder */
+ status = __ntapi->zw_open_file(
+ hsysdir,
+ NT_SEC_SYNCHRONIZE | NT_FILE_READ_ATTRIBUTES | NT_FILE_READ_ACCESS,
+ &oa,
+ &iosb,
+ NT_FILE_SHARE_READ | NT_FILE_SHARE_WRITE,
+ NT_FILE_DIRECTORY_FILE | NT_FILE_SYNCHRONOUS_IO_ALERT);
+
+ return status;
+}
+
+
+int32_t __stdcall __ntapi_tt_get_system_directory_dos_path(
+ __in void * hsysdir __optional,
+ __out wchar16_t * buffer,
+ __in uint32_t buffer_size,
+ __in wchar16_t * base_name,
+ __in uint32_t base_name_size,
+ __out nt_unicode_string * nt_path __optional)
+{
+ int32_t status;
+ nt_statfs statfs;
+ wchar16_t * wch;
+ wchar16_t * wch_src;
+ wchar16_t * wch_cap;
+ nt_iosb iosb;
+ nt_fni * fni;
+ uint32_t fni_length;
+
+ /* validation */
+ if (!buffer)
+ return NT_STATUS_INVALID_PARAMETER_2;
+
+ /* hsysdir */
+ if (!hsysdir) {
+ status = __ntapi_tt_get_system_directory_handle(
+ &hsysdir,
+ (nt_mem_sec_name *)buffer,
+ buffer_size);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+ }
+
+ /* statfs */
+ status = __ntapi->tt_statfs(
+ hsysdir,
+ (void *)0,
+ (nt_unicode_string *)0,
+ &statfs,
+ (uintptr_t *)buffer,
+ buffer_size,
+ NT_STATFS_DOS_DRIVE_LETTER);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* dos path name (always shorter than the native path, so buffer_size must be ok) */
+ wch = buffer;
+ *wch = '\\'; wch++;
+ *wch = '?'; wch++;
+ *wch = '?'; wch++;
+ *wch = '\\'; wch++;
+ *wch = statfs.nt_drive_letter; wch++;
+ *wch = ':'; wch++;
+
+ /* alignment */
+ fni = (nt_fni *)((uintptr_t)buffer + 0x10);
+
+ status = __ntapi->zw_query_information_file(
+ hsysdir,
+ &iosb,
+ fni,
+ buffer_size - 8 * sizeof(wchar16_t),
+ NT_FILE_NAME_INFORMATION);
+
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* fni->file_name_length: save */
+ fni_length = fni->file_name_length;
+
+ /* overwrite */
+ wch_src = fni->file_name;
+ wch_cap = (wchar16_t *)((uintptr_t)wch_src + fni_length);
+
+ while (wch_src < wch_cap) {
+ *wch = *wch_src;
+ wch++;
+ wch_src++;
+ }
+
+ /* ultimate path separator */
+ *wch = '\\'; wch++;
+
+ /* base_name */
+ if (base_name) {
+ wch_src = base_name;
+ wch_cap = (wchar16_t *)((uintptr_t)wch + base_name_size);
+
+ if ((uintptr_t)wch_cap - (uintptr_t)buffer - sizeof(wchar16_t) > buffer_size)
+ return NT_STATUS_BUFFER_TOO_SMALL;
+
+ while (wch < wch_cap) {
+ *wch = *wch_src;
+ wch++;
+ wch_src++;
+ }
+ }
+
+ /* null termination */
+ *wch = 0;
+
+ /* nt_path */
+ if (nt_path)
+ __ntapi->rtl_init_unicode_string(
+ nt_path,
+ buffer);
+
+ return NT_STATUS_SUCCESS;
+}
diff --git a/src/system/ntapi_tt_get_system_info_snapshot.c b/src/system/ntapi_tt_get_system_info_snapshot.c
new file mode 100644
index 0000000..bfe2978
--- /dev/null
+++ b/src/system/ntapi_tt_get_system_info_snapshot.c
@@ -0,0 +1,89 @@
+/********************************************************/
+/* ntapi: Native API core library */
+/* Copyright (C) 2013,2014,2015 Z. Gilboa */
+/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */
+/********************************************************/
+
+#include <psxtypes/psxtypes.h>
+#include <pemagine/pemagine.h>
+#include <ntapi/nt_sysinfo.h>
+#include <ntapi/nt_memory.h>
+#include <ntapi/ntapi.h>
+#include "ntapi_impl.h"
+
+int32_t __stdcall __ntapi_tt_get_system_info_snapshot(
+ __in_out nt_system_information_snapshot * sys_info_snapshot)
+{
+ int32_t status;
+
+ /* pre-allocated buffer? */
+ if (sys_info_snapshot->buffer)
+ status = __ntapi->zw_query_system_information(
+ sys_info_snapshot->sys_info_class,
+ sys_info_snapshot->buffer,
+ sys_info_snapshot->max_len,
+ &sys_info_snapshot->info_len);
+ else {
+ /* set initial buffer size */
+ sys_info_snapshot->max_len = NT_ALLOCATION_GRANULARITY;
+
+ /* allocate initial buffer */
+ status = __ntapi->zw_allocate_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void **)&sys_info_snapshot->buffer,
+ 0,
+ &sys_info_snapshot->max_len,
+ NT_MEM_COMMIT,
+ NT_PAGE_READWRITE);
+
+ /* verification */
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* loop until buffer is large enough to satisfy the system */
+ while ((status = __ntapi->zw_query_system_information(
+ sys_info_snapshot->sys_info_class,
+ sys_info_snapshot->buffer,
+ sys_info_snapshot->max_len,
+ &sys_info_snapshot->info_len))
+ == NT_STATUS_INFO_LENGTH_MISMATCH) {
+
+ /* free previously allocated memory */
+ status = __ntapi->zw_free_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void **)&sys_info_snapshot->buffer,
+ &sys_info_snapshot->max_len,
+ NT_MEM_RELEASE);
+
+ /* verification */
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+
+ /* reset buffer and increase buffer size */
+ sys_info_snapshot->buffer = (nt_system_information_buffer *)0;
+ sys_info_snapshot->max_len += NT_ALLOCATION_GRANULARITY;
+
+ /* reallocate buffer memory */
+ status = __ntapi->zw_allocate_virtual_memory(
+ NT_CURRENT_PROCESS_HANDLE,
+ (void **)&sys_info_snapshot->buffer,
+ 0,
+ &sys_info_snapshot->max_len,
+ NT_MEM_COMMIT,
+ NT_PAGE_READWRITE);
+
+ /* verification */
+ if (status != NT_STATUS_SUCCESS)
+ return status;
+ }
+ }
+
+ /* verification */
+ if (status == NT_STATUS_SUCCESS) {
+ sys_info_snapshot->pcurrent = &sys_info_snapshot->buffer->mark;
+ return NT_STATUS_SUCCESS;
+ } else {
+ sys_info_snapshot->pcurrent = (void *)0;
+ return status;
+ }
+}