diff options
-rw-r--r-- | include/ntapi/nt_ipc.h | 20 | ||||
-rw-r--r-- | include/ntapi/ntapi.h | 4 | ||||
-rw-r--r-- | project/common.mk | 1 | ||||
-rw-r--r-- | src/internal/ntapi.c | 20 | ||||
-rw-r--r-- | src/internal/ntapi_fnapi.h | 4 | ||||
-rw-r--r-- | src/internal/ntapi_impl.h | 26 | ||||
-rw-r--r-- | src/ipc/ntapi_ipc_connect.c | 249 | ||||
-rw-r--r-- | src/process/ntapi_tt_fork.c | 20 |
8 files changed, 342 insertions, 2 deletions
diff --git a/include/ntapi/nt_ipc.h b/include/ntapi/nt_ipc.h index 80fc34c..1dae3b3 100644 --- a/include/ntapi/nt_ipc.h +++ b/include/ntapi/nt_ipc.h @@ -32,4 +32,24 @@ typedef int32_t __stdcall ntapi_ipc_create_pipe( __out void ** hpipe_write, __in uint32_t advisory_buffer_size __optional); + +typedef int32_t __stdcall ntapi_ipc_connect_by_attr( + __out void ** hport, + __in nt_port_attr * attr); + + +typedef int32_t __stdcall ntapi_ipc_connect_by_name( + __out void ** hport, + __in nt_port_name * name); + + +typedef int32_t __stdcall ntapi_ipc_connect_by_symlink( + __out void ** hport, + __in void * hsymlink); + + +typedef int32_t __stdcall ntapi_ipc_connect_by_port( + __in void * hconn, + __in nt_port_attr * attr); + #endif diff --git a/include/ntapi/ntapi.h b/include/ntapi/ntapi.h index c2ff0e5..b3071c1 100644 --- a/include/ntapi/ntapi.h +++ b/include/ntapi/ntapi.h @@ -388,6 +388,10 @@ typedef struct _ntapi_vtbl { ntapi_tt_open_physical_parent_directory * tt_open_physical_parent_directory; /* nt_ipc.h */ + ntapi_ipc_connect_by_attr * ipc_connect_by_attr; + ntapi_ipc_connect_by_name * ipc_connect_by_name; + ntapi_ipc_connect_by_symlink * ipc_connect_by_symlink; + ntapi_ipc_connect_by_port * ipc_connect_by_port; ntapi_ipc_create_pipe * ipc_create_pipe; /* nt_ldr.h */ diff --git a/project/common.mk b/project/common.mk index c1b5b1b..59d9317 100644 --- a/project/common.mk +++ b/project/common.mk @@ -23,6 +23,7 @@ COMMON_SRCS = \ src/internal/ntapi_debug.c \ src/internal/ntapi_entry_point.c \ src/internal/ntapi_open.c \ + src/ipc/ntapi_ipc_connect.c \ src/ipc/ntapi_tt_create_pipe_v1.c \ src/ipc/ntapi_tt_create_pipe_v2.c \ src/ldr/ntapi_ldr_create_state_snapshot.c \ diff --git a/src/internal/ntapi.c b/src/internal/ntapi.c index 336b5db..da91cfe 100644 --- a/src/internal/ntapi.c +++ b/src/internal/ntapi.c @@ -130,6 +130,20 @@ static int32_t __fastcall __ntapi_init_once(ntapi_vtbl ** pvtbl) if (status != NT_STATUS_SUCCESS) return status; + /* ipc connection list */ + if ((status = dalist_init_ex( + &internals->ipc_conns, + sizeof(nt_ipc_conn), + NT_ALLOCATION_GRANULARITY, + __ntapi_ipc_page_alloc, + DALIST_MEMFN_CUSTOM))) + return status; + + dalist_deposit_memory_block( + &internals->ipc_conns, + &__ntapi_img_bss.ipc_buffer, + __NT_BSS_IPC_BUFFER_SIZE); + /* hashed import table */ __ntapi_tt_populate_hashed_import_table( pe_get_ntdll_module_handle(), @@ -165,6 +179,12 @@ static int32_t __fastcall __ntapi_init_once(ntapi_vtbl ** pvtbl) __ntapi->tt_open_logical_parent_directory = __ntapi_tt_open_logical_parent_directory; __ntapi->tt_open_physical_parent_directory = __ntapi_tt_open_physical_parent_directory; + /* nt_ipc.h */ + __ntapi->ipc_connect_by_attr = __ntapi_ipc_connect_by_attr; + __ntapi->ipc_connect_by_name = __ntapi_ipc_connect_by_name; + __ntapi->ipc_connect_by_symlink = __ntapi_ipc_connect_by_symlink; + __ntapi->ipc_connect_by_port = __ntapi_ipc_connect_by_port; + /* nt_ldr.h */ __ntapi->ldr_load_system_dll = __ntapi_ldr_load_system_dll; __ntapi->ldr_create_state_snapshot = __ntapi_ldr_create_state_snapshot; diff --git a/src/internal/ntapi_fnapi.h b/src/internal/ntapi_fnapi.h index 546c335..8ff01f5 100644 --- a/src/internal/ntapi_fnapi.h +++ b/src/internal/ntapi_fnapi.h @@ -46,6 +46,10 @@ ntapi_tt_open_physical_parent_directory __ntapi_tt_open_physical_parent_directo /* nt_ipc.h */ +ntapi_ipc_connect_by_attr __ntapi_ipc_connect_by_attr; +ntapi_ipc_connect_by_name __ntapi_ipc_connect_by_name; +ntapi_ipc_connect_by_symlink __ntapi_ipc_connect_by_symlink; +ntapi_ipc_connect_by_port __ntapi_ipc_connect_by_port; ntapi_ipc_create_pipe __ntapi_ipc_create_pipe_v1; ntapi_ipc_create_pipe __ntapi_ipc_create_pipe_v2; diff --git a/src/internal/ntapi_impl.h b/src/internal/ntapi_impl.h index aca201b..870e5fd 100644 --- a/src/internal/ntapi_impl.h +++ b/src/internal/ntapi_impl.h @@ -39,6 +39,10 @@ #ifndef __NT_SYNC_BLOCK_LOCK_TRIES #define __NT_SYNC_BLOCK_LOCK_TRIES 1024 #endif + +#ifndef __NT_IPC_PAGES +#define __NT_IPC_PAGES 64 +#endif /* user-defined options: tail */ /* internal page size */ @@ -48,23 +52,27 @@ /* .bss section */ #ifndef __NT_BSS_RESERVED_PAGES -#define __NT_BSS_RESERVED_PAGES 8 +#define __NT_BSS_RESERVED_PAGES 10 #endif /* runtime buffers */ #define __NT_BSS_ARGV_BUFFER_SIZE __NT_INTERNAL_PAGE_SIZE * 2 +#define __NT_BSS_IPC_BUFFER_SIZE __NT_INTERNAL_PAGE_SIZE * 2 + #define __NT_BSS_ARGV_MAX_IDX __NT_BSS_ARGV_BUFFER_SIZE \ / sizeof(uintptr_t) #define __NT_BSS_ARGS_BUFFER_SIZE __NT_INTERNAL_PAGE_SIZE \ * __NT_BSS_RESERVED_PAGES \ - - __NT_BSS_ARGV_BUFFER_SIZE + - __NT_BSS_ARGV_BUFFER_SIZE \ + - __NT_BSS_IPC_BUFFER_SIZE /* ntapi .bss section structure */ typedef struct ___ntapi_img_sec_bss { wchar16_t * argv_envp_array[__NT_BSS_ARGV_MAX_IDX]; char args_envs_buffer[__NT_BSS_ARGS_BUFFER_SIZE]; + size_t ipc_buffer[__NT_BSS_IPC_BUFFER_SIZE / sizeof(size_t)]; } __ntapi_img_sec_bss; @@ -85,6 +93,9 @@ typedef struct __attr_ptr_size_aligned__ _ntapi_internals { void ** csr_port_handle_addr; void * hdev_mount_point_mgr; void * hany[8]; + struct dalist_ex ipc_conns; + void * ipc_pages[__NT_IPC_PAGES]; + int32_t ipc_page; intptr_t hlock; uintptr_t v1_pipe_counter; ntapi_tt_get_csr_port_handle_addr_by_logic * tt_get_csr_port_handle_addr_by_logic; @@ -92,6 +103,15 @@ typedef struct __attr_ptr_size_aligned__ _ntapi_internals { } ntapi_internals; +/* ipc internals */ +typedef struct _nt_ipc_conn { + nt_port_attr attr; + void * hsection; + void * secaddr; + size_t secsize; +} nt_ipc_conn; + + /* __ntapi_img_sec_data */ typedef struct __attr_ptr_size_aligned__ ___ntapi_img_sec_rdata { ntapi_hashed_symbol __ntapi_import_table[__NT_IMPORTED_SYMBOLS_ARRAY_SIZE]; @@ -120,6 +140,8 @@ ntapi_internals * __cdecl __ntapi_internals(void); int32_t __ntapi_tt_open_file_utf8(void ** hfile, void * hat, const char * arg, int fprivate, wchar16_t *, uint32_t); int32_t __ntapi_tt_open_dir_utf8(void ** hfile, void * hat, const char * arg, int fprivate, wchar16_t *, uint32_t); +/* ipc internals */ +int __ntapi_ipc_page_alloc(struct dalist_ex * dlist, void ** addr, size_t * alloc_size); /* debug */ #define __ntidx(x) (&(((ntapi_vtbl *)0)->x)) / sizeof(size_t) diff --git a/src/ipc/ntapi_ipc_connect.c b/src/ipc/ntapi_ipc_connect.c new file mode 100644 index 0000000..d61e869 --- /dev/null +++ b/src/ipc/ntapi_ipc_connect.c @@ -0,0 +1,249 @@ +/********************************************************/ +/* ntapi: Native API core library */ +/* Copyright (C) 2013--2017 Z. Gilboa */ +/* Released under GPLv2 and GPLv3; see COPYING.NTAPI. */ +/********************************************************/ + +#include <psxtypes/psxtypes.h> +#include <ntapi/nt_file.h> +#include <ntapi/nt_string.h> +#include <ntapi/nt_atomic.h> +#include <ntapi/ntapi.h> +#include "ntapi_impl.h" + +static int32_t __ipc_connect_return( + intptr_t * hlock, + int32_t status) +{ + at_store(hlock,0); + return status; +} + + +static int32_t __ipc_connect_by_attr( + void ** hport, + const nt_port_attr * attr, + nt_unicode_string * str, + void * hconn, + __out void ** hsection, + __out void ** secaddr, + __out size_t * secsize) +{ + int32_t status; + struct dalist_node_ex * node; + const nt_port_attr * conn; + nt_port_attr * nconn; + nt_ipc_conn * ipc; + intptr_t * hlock; + ntapi_internals * __internals; + + /* init */ + __internals = __ntapi_internals(); + + /* lock */ + hlock = &(__internals->hlock); + + if (at_locked_cas(hlock,0,1)) + return NT_STATUS_RESOURCE_NOT_OWNED; + + /* already connected? */ + node = (struct dalist_node_ex *)__internals->ipc_conns.head; + + for (; node; node=node->next) { + ipc = (nt_ipc_conn *)&node->dblock; + conn = &ipc->attr; + + if ((attr->keys.key[0] == conn->keys.key[0]) + && (attr->keys.key[1] == conn->keys.key[1]) + && (attr->keys.key[2] == conn->keys.key[2]) + && (attr->keys.key[3] == conn->keys.key[3]) + && (attr->keys.key[4] == conn->keys.key[4]) + && (attr->keys.key[5] == conn->keys.key[5]) + && !__ntapi->tt_guid_compare( + &attr->guid, + &conn->guid)) { + /* already connected */ + if (hconn) + return __ipc_connect_return( + hlock, + ((uintptr_t)hconn == node->key) + ? NT_STATUS_SUCCESS + : NT_STATUS_CONTEXT_MISMATCH); + + *hport = (void *)node->key; + *hsection = ipc->hsection; + *secaddr = ipc->secaddr; + *secsize = ipc->secsize; + + return __ipc_connect_return(hlock,NT_STATUS_SUCCESS); + } + } + + /* allocate list node */ + if ((status = dalist_get_free_node( + &__internals->ipc_conns, + (void **)&node))) + return __ipc_connect_return(hlock,status); + + /* connect as needed */ + if (!hconn) { + status = __ntapi->zw_connect_port( + &hconn,str,0,0,0,0,0,0); + + if (status) { + dalist_deposit_free_node( + &__internals->ipc_conns, + node); + + return __ipc_connect_return(hlock,status); + } + } + + /* add connection */ + node->key = (uintptr_t)hconn; + ipc = (nt_ipc_conn *)&node->dblock; + nconn = &ipc->attr; + + __ntapi->tt_aligned_block_memcpy( + (uintptr_t *)nconn, + (uintptr_t *)attr, + sizeof(nt_port_attr)); + + ipc->hsection = 0; + ipc->secaddr = 0; + ipc->secsize = 0; + + dalist_insert_node_by_key( + &__internals->ipc_conns, + node); + + /* all done */ + *hport = hconn; + *hsection = 0; + *secaddr = 0; + *secsize = 0; + + return __ipc_connect_return(hlock,NT_STATUS_SUCCESS); +} + + +int32_t __stdcall __ntapi_ipc_connect_by_attr( + __out void ** hport, + __in nt_port_attr * attr) +{ + nt_port_name name; + nt_unicode_string str; + + __ntapi->tt_port_name_from_attr( + &name,attr); + + str.strlen = ((size_t)&(((nt_port_name *)0)->null_termination)); + str.maxlen = 0; + str.buffer = &name.base_named_objects[0]; + + return __ipc_connect_by_attr( + hport,attr,&str,0, + &(void *){0}, + &(void *){0}, + &(size_t){0}); +} + + +int32_t __stdcall __ntapi_ipc_connect_by_name( + __out void ** hport, + __in nt_port_name * name) +{ + int32_t status; + nt_port_attr attr; + nt_unicode_string str; + + if ((status = __ntapi->tt_port_attr_from_name(&attr,name))) + return status; + + str.strlen = ((size_t)&(((nt_port_name *)0)->null_termination)); + str.maxlen = 0; + str.buffer = &name->base_named_objects[0]; + + return __ipc_connect_by_attr( + hport,&attr,&str,0, + &(void *){0}, + &(void *){0}, + &(size_t){0}); +} + + +int32_t __stdcall __ntapi_ipc_connect_by_symlink( + __out void ** hport, + __in void * hsymlink) +{ + int32_t status; + nt_port_attr attr; + nt_port_name * name; + size_t namelen; + uintptr_t buffer[512/sizeof(uintptr_t)]; + nt_unicode_string * str; + + str = (nt_unicode_string *)buffer; + str->strlen = 0; + str->maxlen = sizeof(buffer) - sizeof(nt_unicode_string); + str->buffer = (wchar16_t *)&str[1]; + + if ((status = __ntapi->zw_query_symbolic_link_object( + hsymlink,str,&namelen))) + return status; + + if (str->strlen != ((size_t)&(((nt_port_name *)0)->null_termination))) + return NT_STATUS_INVALID_PORT_ATTRIBUTES; + + name = (nt_port_name *)str->buffer; + + if ((status = __ntapi->tt_port_attr_from_name(&attr,name))) + return status; + + return __ipc_connect_by_attr( + hport,&attr,str,0, + &(void *){0}, + &(void *){0}, + &(size_t){0}); +} + + +int32_t __stdcall __ntapi_ipc_connect_by_port( + __in void * hconn, + __in nt_port_attr * attr) +{ + return __ipc_connect_by_attr( + &(void *){0},attr,0,hconn, + &(void *){0}, + &(void *){0}, + &(size_t){0}); +} + + +int __ntapi_ipc_page_alloc( + struct dalist_ex * dlist, + void ** addr, + size_t * alloc_size) +{ + int32_t status; + ntapi_internals * __internals; + + __internals = __ntapi_internals(); + + if (__internals->ipc_page == __NT_IPC_PAGES) + return NT_STATUS_QUOTA_EXCEEDED; + + if ((status = __ntapi->zw_allocate_virtual_memory( + NT_CURRENT_PROCESS_HANDLE, + addr,0,alloc_size, + NT_MEM_COMMIT, + NT_PAGE_READWRITE))) + return status; + + dalist_deposit_memory_block( + dlist,*addr,*alloc_size); + + __internals->ipc_pages[__internals->ipc_page++] = *addr; + + return 0; +} diff --git a/src/process/ntapi_tt_fork.c b/src/process/ntapi_tt_fork.c index 58cf2c3..9c0d2de 100644 --- a/src/process/ntapi_tt_fork.c +++ b/src/process/ntapi_tt_fork.c @@ -24,6 +24,7 @@ static intptr_t __fastcall __ntapi_tt_fork_finalize( int32_t status; nt_oa oa; nt_cid cid; + int page; ntapi_internals * __internals; __internals = __ntapi_internals(); @@ -53,6 +54,25 @@ static intptr_t __fastcall __ntapi_tt_fork_finalize( &oa,&cid))) return status; + if ((status = dalist_init_ex( + &__internals->ipc_conns, + sizeof(nt_ipc_conn), + NT_ALLOCATION_GRANULARITY, + __ntapi_ipc_page_alloc, + DALIST_MEMFN_CUSTOM))) + return status; + + dalist_deposit_memory_block( + &__internals->ipc_conns, + __internals->ntapi_img_sec_bss->ipc_buffer, + __NT_BSS_IPC_BUFFER_SIZE); + + for (page=0; __internals->ipc_page; page++) + dalist_deposit_memory_block( + &__internals->ipc_conns, + __internals->ipc_pages[page], + NT_ALLOCATION_GRANULARITY); + return 0; } |