""" Please make sure you read the README COMPLETELY BEFORE reading anything below. It is very critical that you read coding guidelines in Section E in README file. """ from xnu import * from utils import * from string import * from socket import * from enum import IntEnum import xnudefines from netdefines import * from routedefines import * ###################################### # Globals ###################################### """ Refer to in bsd/net/ntstat.c """ NSTAT_PROCDETAILS_MAGIC = 0xfeedc001 NSTAT_GENERIC_SHADOW_MAGIC = 0xfadef00d TU_SHADOW_MAGIC = 0xfeedf00d """ Refer to nstat_provider_type_t in bsd/net/ntstat.h """ class NSTAT_PROVIDER(IntEnum): NONE = 0 ROUTE = 1 TCP_KERNEL = 2 TCP_USERLAND = 3 UDP_KERNEL = 4 UDP_USERLAND = 5 IFNET = 6 SYSINFO = 7 QUIC_USERLAND = 8 CONN_USERLAND = 9 UDP_SUBFLOW = 10 ###################################### # Helper functions ###################################### def FieldPtrToStructPtr(field_ptr, field_name, element_type): """ Given a pointer to a field with a structure, return a pointer to the structure itself params: field_ptr - value : pointer to the field field_name - str : string name of the field which holds the list links. element_type - str : type of elements to be linked in the list returns: value : A pointer to the start of the structure """ out_string = "" if (field_ptr) : tmp_element = Cast(field_ptr, element_type) tmp_element_plus_offset = addressof(tmp_element.__getattr__(field_name)) offset = tmp_element_plus_offset - tmp_element original_ptr_as_char_ptr = Cast(field_ptr, 'char *') amended_ptr = original_ptr_as_char_ptr - offset return kern.GetValueFromAddress(unsigned(amended_ptr), element_type) return field_ptr def ReverseIterateTAILQ_AnonymousHEAD(headval, field_name, element_type): """ reverse iterate over a TAILQ_HEAD in kernel. refer to bsd/sys/queue.h params: headval - value : value object representing the head of the list field_name - str : string name of the field which holds the list links. element_type - str : type of elements to be linked in the list returns: A generator does not return. It is used for iterating. value : an object that is of type as headval->tqh_last. Always a pointer object example usage: list_head = kern.GetGlobalVariable('ctl_head') for entry in ReverseIterateTAILQ_AnonymousHEAD(list_head, 'next', 'struct kctl *'): print(entry) """ head_first = headval.__getattr__('tqh_first') if head_first: head_first_addr = FieldPtrToStructPtr(addressof(head_first),field_name, element_type) head_last = headval.__getattr__('tqh_last') iter_val = FieldPtrToStructPtr(head_last, field_name, element_type) while (unsigned(iter_val) != unsigned(head_first_addr)) and (unsigned(iter_val) != 0) : yield iter_val element = Cast(iter_val, element_type) tmp = element.__getattr__(field_name).__getattr__('tqe_prev') iter_val = FieldPtrToStructPtr(tmp, field_name, element_type) #end of yield loop def ShowNstatTUShadow(inshadow): """ Display summary for an nstat_tu_shadow struct params: inshadow : cvalue object which points to 'struct nstat_tu_shadow *' """ shad = Cast(inshadow, 'struct nstat_tu_shadow *') procdetails = shad.shad_procdetails out_string = "" if shad : format_string = "nstat_tu_shadow {0: <#0x}: next={1: <#020x} prev={2: <#020x} context (necp_client *)={3: <#020x} live={4: