Reconstrucción de estructuras e introducción al análisis forense
Introducción al análisis forense de sistemas GNU/Linux
Copyright © 2008 Javier Juan Martínez Cabezón.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 published by the Free Software Foundation; with no Invariant Sections, and with no Front-Cover Texts, and with no Back-Cover Texts. Full text of the license is at http://www.gnu.org/licenses/fdl.txt
Exploración de memoria física.
Éste será el primero de varios artículos que enviaré relacionados con el análisis forense de memoria física y también de disco duro. Al final los reuniré todos en un mismo macro-artículo que publicaré en el sitio. Éste se centrará más en la reconstrucción de estructuras para su posterior estudio y en el primer método de reconstrucción de tablas de procesos vía lista enlazada. Todas las rutas a ficheros de cabecera toman como raíz en directorio de las fuentes del núcleo.
Reconstrucción de estructuras.
Éstos datos los necesitaremos para conseguir interpretar adecuadamente las salidas del depurador. Existen ciertas partes que debemos saber interpretar para la reconstrucción entre las que destaco las siguientes.
-
Estructuras:
Básicamente se tratan de planillas. Voy a hacer un símil con un coche. Digamos que tenemos un renault XX, los renault y los no renault (seat, ford...) comparten ciertas características. Todas esas características comunes se juntan en una estructura. Aquí un ejemplo un poco chapucero:
struct coche_struct {
int ruedas; #número de ruedas que tendrá
char color_carrocería[10]; # color de la carrocería
unsigned short int cilindrada; #cilindrada del motor en centrímetros cúbicos
signed char abs; #tiene abs
signed char dirección_asistida; #tiene dirección asistida?
struct list_head *otro_coche;
}
Las estructuras siempre se definen de esta manera:
struct nombre_estructura {
contenido
}
Lo que haya entre las llaves son el contenido de la estructura.
Aquí tenemos un ejemplo de nuestra estructura coche_struct, vamos a utilizarla:
struct coche_struct Pegaso {
ruedas=8
color=''NEGRO''
cilindrada=3000
abs=1
dirección_asistida=1
otro_coche=*0xcbff3280 *0xcdeebb00
}
Con ésto podemos utilizar la misma planilla para los diferentes coches/camiones/tractores/motos que queramos.
Variable:
En nuestro caso variable es cada una de las partes de nuestra estructura es decir, todo aquello que puede variar entre los distintos tipos de marcas de coche/tractores etc..., en nuestro ejemplo variables serían: ruedas, color, cilindrada, abs, dirección_asistida y otro_coche.
Tipos:
Definen cómo van a ser los datos que van a entrar en nuestra variable, es decir, pueden ser arrays de caracteres (char[tamaño]) en nuestro caso de tamaño de 10 bytes (uno por char), valores enteros (int) cuyo valor depende de la arquitectura (32 bits en ia32, es decir, puede representar valores entre 0 y 2e32-1) etc....
Los tipos pueden ser con o sin signo, supongamos que queremos representar un valor que oscila entre -127 y 127, podemos entonces declarar una variable de esta forma: ``signed char variable'', con ésto nuestra variable podrá tener un valor entre -127 y 127 (2e8-1 en valor absoluto), si queremos que sea entre 0 y 255 puede ser de la siguiente forma: ``unsigned char variable''.
Existen más tipos, muchos más, como enteros largos (long int), enteros cortos (short int) cuyo valor oscila, long int es como mínimo siempre 32 bits, ``short int'' siempre es como mínimo 16 bits. También existen enteros largos largos (long long int) cuyo valor es siempre 64 bits (8 bytes), al igual que variables asignadas u64 o s64.
Antes coloqué una estructura como variable, ``struct list_head otro_coche'', ésto es muy común en el código fuente de Linux. Puede contener punteros (referencias a direcciones de memoria) a una parte de una estructura situada en otro lado o bien puede ser necesario sustituirlo por la estructura completa. En este caso, nuestra estructura contiene dos punteros a la siguiente estructura next.coche_struct o del next.coche_struct previo, es decir, a la dirección donde se encuentra el ``struct list_head'' de otra estructura coche_struct. Dichos punteros son siempre de 32 bits (en IA32).
El kernel linux tiene creados otros tipos propios, compatibles con posix que están definidos en include/asm/posix_types.h, los base están en en el fichero de cabecera types.h.
Task_struct
Definido en include/linux/sched.h. Define la estructuras de los procesos en Linux.
Aquí está el fichero de cabecera a analizar (por lo menos la sección relativa a sched.h:
struct task_struct {
Comienzo de la estructura.
volatile long state; /* -1 unrunnable, 0 runnable, >0 stopped */ void *stack; atomic_t usage; unsigned int flags; /* per process flags, defined below */
Aquí van los primeros 16 bytes.
STATE *STACK USAGE FLAGS
el estado es del tipo long, que sabemos se le reserva 4 bytes, *stack es un puntero, es decir, apunta a una dirección en la memoria física, en este caso a la pila del proceso. Sabemos que todos los punteros son de 4 bytes ( direcciones de 32 bits) en la arquitectura ia32 (y además little endian).
unsigned int ptrace; int lock_depth; /* BKL lock depth */ #ifdef CONFIG_SMP #ifdef __ARCH_WANT_UNLOCKED_CTXSW int oncpu; #endif #endif int prio, static_prio, normal_prio;
Ésto es interesante:
#ifdef CONFIG_SMP #ifdef __ARCH_WANT_UNLOCKED_CTXSW
Que esté ``int oncpu'' depende de dos factores:
- Que CONFIG_SMP esté activado en vuestro kernel (zless /proc/config.gz | grep CONFIG_SMP).
- Que se use __ARCH_WANT_UNLOCKED_CTXSW, ésto es un macro que se encuentra en las arquitecturas MIPS, SPARC y IA64, desgraciadamente tendréis que buscar dicho macro en las fuentes para saber donde está (grep sigue siendo vuestro amigo).
Puede ser que vuestro .config tenga CONFIG_SMP activado, pero para que ``oncpu'' aparezca en la estructura de tareas se requiere también de __ARCH_WANT_UNLOCKED_CTXSW, que no es nuestro caso, por tanto no lo usamos. La siguiente fila quedaría así:
PTRACE LOCK_DEPTH PRIO STATIC_PRIO
normal_prio será el primero de la siguiente fila.
struct list_head run_list; struct sched_class *sched_class;
Más cosas interesantes, ahora vemos una estructura. List_head está definida en include/linux/list.h y contiene dos punteros, al siguiente de lo que sea el primero y al previo de lo que sea después.
La lista run_list utiliza a esta estructura para crear una lista enlazada de los procesos que están en estado RUNNING por motivos de eficiencia. La siguiente fila quedará de la siguiente manera:
NORMAL_PRIO *RUN_LIST_NEXT *RUN_LIST_PREV *SCHED_CLASS.
Como ya vimos en arquitecturas de 32 bits, los punteros son de 32 bits, por tanto nos quedará como antes. Normal_prio es de tipo int que son otros 32 bits.
struct sched_entity se;
Más tela ahora se nos incrusta una estructura de tipo sched_entity de nombre se, que se define también en sched.h. Contiene lo siguiente:
struct sched_entity {
long wait_runtime;
unsigned long delta_fair_run;
unsigned long delta_fair_sleep;
unsigned long delta_exec;
s64 fair_key;
struct load_weight load; /* for load-balancing */
struct rb_node run_node;
unsigned int on_rq;
u64 exec_start;
u64 sum_exec_runtime;
u64 prev_sum_exec_runtime;
u64 wait_start_fair;
u64 sleep_start_fair;
#ifdef CONFIG_SCHEDSTATS
u64 wait_start;
u64 wait_max;
s64 sum_wait_runtime;
u64 sleep_start;
u64 sleep_max;
s64 sum_sleep_runtime;
u64 block_start;
u64 block_max;
u64 exec_max;
unsigned long wait_runtime_overruns;
unsigned long wait_runtime_underruns;
#endif
#ifdef CONFIG_FAIR_GROUP_SCHED
struct sched_entity *parent;
/* rq on which this entity is (to be) queued: */
struct cfs_rq *cfs_rq;
/* rq "owned" by this entity/group: */
struct cfs_rq *my_q;
#endif
};
Bien comenzamos a desglosar:
long wait_runtime;
unsigned long delta_fair_run;
unsigned long delta_fair_sleep;
unsigned long delta_exec;
Wait_runtime es de tipo long, por tanto se le reservan cuatro bytes, delta_fair_run, delta_fair_sleep y delta_exec son del tipo unsigned long. Por tanto:
WAIT_RUNTIME DELTA_FAIR_RUN DELTA_FAIR_SLEEP DELTA_EXEC
s64 fair_key;
struct load_weight load; /* for load-balancing */
Otra estructura, primero vemos un s64 que es de 8 bytes, tras ello otra estructura de tipo load_weight llamada load. Si hacemos grep load_weight include/linux/* vemos que está definida en sched.h y contiene dos long sin signo, weight e inv_weight. Así que:
FAIR_KEY FAIR_KEY WEIGHT INV_WEIGHT struct rb_node run_node; unsigned int on_rq;
Aquí viene otra estructura, llamada run_node de tipo rb_node, haciendo un grep vemos muchas coincidencias, una de ellas en el fichero de cabecera rbtree.h que es el que examiné dado el parecido del nombre. La estructura contiene lo siguiente: una variable unsigned long rb_parent_color, y dos punteros a estructuras rb_node llamados rb_right y rb_left. Así que:
RB_PARENT_COLOR *RB_RIGHT *RB_LEFT ON_RQ u64 exec_start; u64 sum_exec_runtime;
Dos variables u64 que son cada una 8 bytes así queda:
EXEC_START EXEC_START SUM_EXEC_RUNTIME SUM_EXEC_RUNTIME
u64 prev_sum_exec_runtime;
u64 wait_start_fair
Y lo mismo ahora:
PREV_SUM_EXEC_RUNTIME PREV_SUM_EXEC_RUNTIME WAIT_START_FAIR WAIT_START_FAIR
Después viene u64 sleep_start_fair que es de 8 bytes y dos condicionales que al no estar definidas en mi .config se omiten (CONFIG SCHEDSTATS por ejemplo) por tanto finalizamos la estructura que es de 88 bytes.
Continuamos:
#ifdef CONFIG_PREEMPT_NOTIFIERS /* list of struct preempt_notifier: */ struct hlist_head preempt_notifiers; #endif unsigned short ioprio; #ifdef CONFIG_BLK_DEV_IO_TRACE unsigned int btrace_seq; #endif unsigned int policy;
Ninguna de las dos condicionales están en el .config, así que se omite tanto hlist_head preempt_notifiers como btrace_seq. Como curiosidad, hlist_head es parecido a list_head con la salvedad de usar sólo un puntero al anterior.
SLEEP_START_FAIR SLEEP_START_FAIR IOPRIO POLICY cpumask_t cpus_allowed; unsigned int time_slice; #if defined(CONFIG_SCHEDSTATS) || defined(CONFIG_TASK_DELAY_ACCT) struct sched_info sched_info; #endif struct list_head tasks;
Varias cosas, cpumask_t está definido como tipo en el fichero de cabecera linux/cpumask.h, como un DECLARE_BITMAP, que contiene un array de longs sin signo, pienso que en un sistema de un microprocesador, es de uno. Por tanto 4 bytes. No tengo activado CONFIG_SCHEDSTATS O TASK_DELAY_ACCT, por tanto sched_info se omite. Tasks apunta hacia el next.task_struct del próximo proceso o del previo (lista enlazada)
CPUS_ALLOWED TIME_SLICE *TASKS.NEXT *TASKS.PREV /* * ptrace_list/ptrace_children forms the list of my children * that were stolen by a ptracer. */ struct list_head ptrace_children; struct list_head ptrace_list; *PTRACE_CHILDREN.NEXT PTRACE_CHILDREN.PREV PTRACE_LIST.NEXT PTRACE_LIST.PREV struct mm_struct *mm, *active_mm; /* task state */ struct linux_binfmt *binfmt; int exit_state; *MM *ACTIVE_MM *BINFMT EXIT_STATE
Aquí tenemos tres punteros, *MM y *ACTIVE_MM suelen ser el mismo aunque lo veremos más adelante.
int exit_code, exit_signal; int pdeath_signal; /* The signal sent when the parent dies */ /* ??? */ unsigned int personality; EXIT_CODE EXIT_SIGNAL PDEATH_SIGNAL PERSONALITY unsigned did_exec:1; pid_t pid; pid_t tgid; #ifdef CONFIG_CC_STACKPROTECTOR /* Canary value for the -fstack-protector gcc feature */ unsigned long stack_canary; #endif /* * pointers to (original) parent process, youngest child, younger sibling, * older sibling, respectively. (p->father can be replaced with * p->parent->pid) */ struct task_struct *real_parent; /* real parent process (when being debugged) */ DID_EXEC PID TGID *REAL_PARENT
El valor de pid_t lo podéis sacar de include/asm/posix_types.h que es tipo int, por tanto 32 bits.
struct task_struct *parent; /* parent process */ /* * children/sibling forms the list of my children plus the * tasks I'm ptracing. */ struct list_head children; /* list of my children */ struct list_head sibling; /* linkage in my parent's children list */ *PARENT *CHILDREN.NEXT CHILDREN.PREV SIBLING.NEXT struct task_struct *group_leader; /* threadgroup leader */ /* PID/PID hash table linkage. */ struct pid_link pids[PIDTYPE_MAX]; struct list_head thread_group;
Pid_link pids se sustituye por: struct_hlist_node node; struct pid *pid o lo que es lo mismo: hlist_node *next hlist_node **pprev *pid. El valor de PIDTYPE_MAX es 3, dado a que PIDTYPE_MAX pertenece al tipo pid_type definido en pid.h y es un tipo enum, por tanto PIDTYPE_PID es 0, PGID es 1 SID 2 y MAX es 3., dado ésto sabemos que se reservan 36 (12x3) bytes para la estructura, por tanto queda así:
SIBLING.PREV *GROUP_LEADER *HLIST_NODE.NEXT *HLIST_NODE.PREV *PID *HLIST_NODE_NEXT *HLIST_NODE_PPREV *PID *HLIST_NODE_NEXT *HLIST_NODE_PPREV *PID THREAD_GROUP_NEXT struct completion *vfork_done; /* for vfork() */ int __user *set_child_tid; /* CLONE_CHILD_SETTID */ int __user *clear_child_tid; /* CLONE_CHILD_CLEARTID */ unsigned int rt_priority; *VFORK_DONE *SET_CHILD_TID CLEAR_CHILD_TID RT_PRIORITY cputime_t utime, stime; unsigned long nvcsw, nivcsw; /* context switch counts */ cputime_t está definido como tipo en include/asm-generic/cputype.h y es de tipo unsigned long. UTIME STIME NVCSW NIVCSW struct timespec start_time; /* monotonic time */ struct timespec real_start_time; /* boot based time */
Aquí hay una estructura timespec que se usa por duplicado, dicha estructura se define en varios sitios, uno en coda.h que estará relacionado con el sistema de archivos coda y que no nos interesa. Otro en include/time.h que es el que nos interesa (que además es la que está incluida en sched.h). Timespec equivale a: time_t tv_sec; long tv_usec; time_t está localizado en types.h, y es de tipo __kernel_time_t :), el cuál se localiza en asm/posix_types.h como tipo unsigned long. Por tanto:
TV_SEC TV_USEC TV_SEC TV_USEC /* mm fault and swap info: this can arguably be seen as either mm-specific or thread-specific */ unsigned long min_flt, maj_flt; cputime_t it_prof_expires, it_virt_expires; MIN_FLT MAJ_FLT IT_PROF_EXPIRES IT_VIRT_EXPIRES unsigned long long it_sched_expires; struct list_head cpu_timers[3];
unsigned long long es de 64 bit, cpu_timers es un array de tres estructuras list_head (24 bytes), así queda:
SCHED_EXPIRES SCHED_EXPIRES *CPU_TIMER_NEXT *CPU_TIMERS_PREV *CPU_TIMERS_NEXT *CPU_TIMERS_PREV *CPU_TIMERS_NEXT *CPU_TIMERS_PREV /* process credentials */ uid_t uid,euid,suid,fsuid; gid_t gid,egid,sgid,fsgid;
uid_t y gid_t están definidos en linux/types.h que deriva a __kernel_uid_t __gid_t en asm/posix_types.h que los marca como unsigned short, por tanto 4 bytes para cada:
UID EUID SUID FSUID GID EGID SGID FSGID struct group_info *group_info; kernel_cap_t cap_effective, cap_inheritable, cap_permitted;
kernel_cap_t está definido en linux/capability.h, aquí algo me desorientó, si no estoy equivocado el chequeo que se realiza, chequea si está definido __KERNEL__ para incluir asm/current.h y en ese caso si está definido STRICT_CAP_T_TYPECHECKS se define como __u32 cap; al no ser así el tipo es __u32 kernel_cap_t, que es de 4 bytes. Desconozco la razón de por qué hacen ésto:
*GROUP_INFO CAP_EFFECTIVE CAP_INHERITABLE CAP_PERMITTED unsigned keep_capabilities:1; struct user_struct *user; #ifdef CONFIG_KEYS struct key *request_key_auth; /* assumed request_key authority */ struct key *thread_keyring; /* keyring private to this thread */ unsigned char jit_keyring; /* default keyring to attach requested keys to */ #endif /* * fpu_counter contains the number of consecutive context switches * that the FPU is used. If this is over a threshold, the lazy fpu * saving becomes unlazy to save the trap. This is an unsigned char * so that after 256 times the counter wraps and the behavior turns * lazy again; this to deal with bursty apps that only use FPU for * a short time */ unsigned char fpu_counter; int oomkilladj; /* OOM kill score adjustment (bit shift). */
Mi .config no tiene definido CONFIG_KEYS por tanto:
KEEP_CAPABILITIES *USER FPU_COUNTER OOMKILLADJ char comm[TASK_COMM_LEN]; /* executable name excluding path - access with [gs]et_task_comm (which lock it with task_lock()) - initialized normally by flush_old_exec */
TASK_COMM_LEN está marcado en sched.h como 16, es decir, COMM es un array de 16 caracteres (un byte por carácter).
COMM COMM COMM COMM /* file system info */ int link_count, total_link_count; #ifdef CONFIG_SYSVIPC /* ipc stuff */ struct sysv_sem sysvsem; #endif /* CPU-specific state of this task */ struct thread_struct thread;
Tengo definido CONFIG_SYSVIPC, la estructura sysv_sem se define en linux/sem.h y contiene un puntero a una estructura tipo sem_undo_list, por tanto:
LINK_COUNT TOTAL_LINK_COUNT *UNDO_LIST A.
En el offset 480 comienza la estructura thread_struct, definido en asm/processor.h (por tanto arquitectura dependiente):
struct thread_struct {
/* cached TLS descriptors. */
struct desc_struct tls_array[GDT_ENTRY_TLS_ENTRIES];
unsigned long esp0;
unsigned long sysenter_cs;
unsigned long eip;
Primera en la frente :), tls_array es un... array de estructuras desc_struct de tamaño GDT_ENTRY_TLS_ENTRIES, dicha estructura está definida en processor.h y contiene dos variables de tipo unsigned long a y b. GDT_ENTRY_TLS_ENTRIES está definido en asm/segment.h y tiene valor 3, por tanto:
B A B A B ESP0 SYSENTER_CS EIP unsigned long esp; unsigned long fs; unsigned long gs; ESP FS GS DEBUGREG0 /* Hardware debugging registers */ unsigned long debugreg[8]; /* %%db0-7 debug registers */ DEBUGREG1 DEBUGREG2 DEBUGREG3 DEBUGREG4 DEBUGREG5 DEBUGREG6 DEBUGREG7 CR2 /* fault info */ unsigned long cr2, trap_no, error_code; /* floating point info */ union i387_union i387; TRAP_NO ERROR_CODE CWD SWD
union i387_union i387 está definido en processor.h también y contiene tres estructuras unidas de tipo i387_fsave_struct, fxsave y soft_struct, contienen lo siguiente:
TWD FIP FCS FOO FOS ST_SPACE0 ST_SPACE1 ST_SPACE2 ST_SPACE3 ST_SPACE4 ST_SPACE5 ST_SPACE6 ST_SPACE7 ST_SPACE8 ST_SPACE9 ST_SPACE10 ST_SPACE11 ST_SPACE12 ST_SPACE13 ST_SPACE14 ST_SPACE15 ST_SPACE16 ST_SPACE17 ST_SPACE18 ST_SPACE19 STATUS CWD/SWD TWD/FOP
En i387_fxsave_struct cwd, swd, twd y fop están definidos como short unsigned int, que son 2 bytes.
FIP FCS FOO FOS MXCSR MXCSR_MASK ST_SPACE0 ST_SPACE1 ST_SPACE2 ST_SPACE3 ST_SPACE4 ST_SPACE5 ST_SPACE6 ST_SPACE7 ST_SPACE8 ST_SPACE9 ST_SPACE10 ST_SPACE11 ST_SPACE12 ST_SPACE13 ST_SPACE14 ST_SPACE15 ST_SPACE16 ST_SPACE17 ST_SPACE18 ST_SPACE19 ST_SPACE20 ST_SPACE21 ST_SPACE22 ST_SPACE23 ST_SPACE24 ST_SPACE25 ST_SPACE26 ST_SPACE27 ST_SPACE28 ST_SPACE29 ST_SPACE30 ST_SPACE31 XMM_SPACE0 XMM_SPACE1 XMM_SPACE2 XMM_SPACE3 XMM_SPACE4 XMM_SPACE5 XMM_SPACE6 XMM_SPACE7 XMM_SPACE8 XMM_SPACE9 XMM_SPACE10 XMM_SPACE11 XMM_SPACE12 XMM_SPACE13 XMM_SPACE14 XMM_SPACE15 XMM_SPACE16 XMM_SPACE17 XMM_SPACE18 XMM_SPACE19 XMM_SPACE20 XMM_SPACE21 XMM_SPACE22 XMM_SPACE23 XMM_SPACE24 XMM_SPACE25 XMM_SPACE26 XMM_SPACE27 XMM_SPACE28 XMM_SPACE29 XMM_SPACE30 XMM_SPACE31 PADDING0 PADDING1 PADDING2 PADDING3 PADDING4 PADDING5 PADDING6 PADDING7 PADDING8 PADDING9 PADDING10 PADDING11 PADDING12 PADDING13 PADDING14 PADDING15 PADDING16 PADDING17 PADDING18 PADDING19 PADDING20 PADDING21 PADDING22 PADDING23 PADDING24 PADDING25 PADDING26 PADDING27 PADDING28 PADDING29 PADDING30 PADDING31 PADDING32 PADDING33 PADDING34 PADDING35 PADDING36 PADDING37 PADDING38 PADDING39 PADDING40 PADDING41 PADDING42 PADDING43 PADDING44 PADDING45 PADDING46 PADDING47 PADDING48 PADDING49 PADDING50 PADDING51 PADDING52 PADDING53 PADDING54 PADDING55 CWD SWD RWD FIP FCS FOO FOS ST_SPACE0 ST_SPACE1 ST_SPACE2 ST_SPACE3 ST_SPACE4 ST_SPACE5 ST_SPACE6 ST_SPACE7 ST_SPACE8 ST_SPACE9 ST_SPACE10 ST_SPACE11 ST_SPACE12 ST_SPACE13 ST_SPACE14 ST_SPACE15 ST_SPACE16 ST_SPACE17 ST_SPACE18 ST_SPACE19 ST_SPACE20 FTOP/CHANGED/LOOKAHEAD/NO_UPDATE RM/ALIMIT
Aquí hay varias variables de tipo unsigned char, al que sólo le reservan 1 byte, salvo a alimit que imagino que lo hacen como ``padding''.
/* virtual 86 mode info */ struct vm86_struct __user * vm86_info; unsigned long screen_bitmap; *INFO ENTRY_EIP *VM86_INFO SCREEN_BITMAP unsigned long v86flags, v86mask, saved_esp0; unsigned int saved_fs, saved_gs; /* IO permissions */ unsigned long *io_bitmap_ptr; V86FLAGS V86MASK SAVED_ESP0 *IO_BITMAP_PTR unsigned long iopl; /* max allowed port in the bitmap, in bytes: */ unsigned long io_bitmap_max; }; /* filesystem information */ struct fs_struct *fs; /* open file information */ struct files_struct *files; IOPL IO_BITMAP_MAX *FS *FILES /* namespaces */ struct nsproxy *nsproxy; /* signal handlers */ struct signal_struct *signal; struct sighand_struct *sighand; sigset_t blocked, real_blocked; sigset_t saved_sigmask; /* To be restored with TIF_RESTORE_SIGMASK */ *NSPROXY *SIGNAL *SIGHAND BLOCKED BLOCKED REAL_BLOCKED REAL_BLOCKED SAVED_SIGMASK struct sigpending pending;
struct sigpending está definida en include/linux/signal.h y contiene una estructura list_head list y una variable tipo sigset_t llamada signal, por tanto:
SAVED_SIGMASK *LIST.NEXT *LIST.PREV SIGNAL unsigned long sas_ss_sp; size_t sas_ss_size; int (*notifier)(void *priv); SIGNAL SAS_SS_SP SAS_SS_SIZE *NOTIFIER void *notifier_data; sigset_t *notifier_mask; void *security; struct audit_context *audit_context; *NOTIFIER_DATA *NOTIFIER_MASK *SECURITY *AUDIT_CONTEXT seccomp_t seccomp; /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; /* Protection of (de-)allocation: mm, files, fs, tty, keyrings */ spinlock_t alloc_lock; /* Protection of the PI data structures: */ spinlock_t pi_lock; #ifdef CONFIG_RT_MUTEXES /* PI waiters blocked on a rt_mutex held by this task */ struct plist_head pi_waiters; PARENT_EXEC_ID SELF_EXEC_ID PRIO_PI_WAITERS_NEXT PRIO_PI_WAITERS_PREV
La estructura plist_head está definida en el fichero de cabecera plist.h
/* Deadlock detection and priority inheritance handling */ struct rt_mutex_waiter *pi_blocked_on; #endif #ifdef CONFIG_DEBUG_MUTEXES /* mutex deadlock detection */ struct mutex_waiter *blocked_on; #endif #ifdef CONFIG_TRACE_IRQFLAGS unsigned int irq_events; int hardirqs_enabled; unsigned long hardirq_enable_ip; unsigned int hardirq_enable_event; unsigned long hardirq_disable_ip; unsigned int hardirq_disable_event; int softirqs_enabled; unsigned long softirq_disable_ip; unsigned int softirq_disable_event; unsigned long softirq_enable_ip; unsigned int softirq_enable_event; int hardirq_context; int softirq_context; #endif #ifdef CONFIG_LOCKDEP # define MAX_LOCK_DEPTH 30UL u64 curr_chain_key; int lockdep_depth; struct held_lock held_locks[MAX_LOCK_DEPTH]; unsigned int lockdep_recursion; #endif /* journalling filesystem info */ void *journal_info;
rt_mutex_waiter está definida en $KERNEL_DIR/kernel/rtmutex_common.h sólo apunta a una posición dentro de la estructura por tanto 4 bytes. Las condicionales presentes en el anterior fragmento son negativas, por tanto las omito. Por último *journal_info de tipo void es un puntero (4 bytes). Por tanto:
PRIO_NODE_WAITERS_NEXT PRIO_NODE_WAITERS_PREV *PI_BLOCKED_ON *JOURNAL_INFO /* stacked block device info */ struct bio *bio_list, **bio_tail; /* VM state */ struct reclaim_state *reclaim_state; struct backing_dev_info *backing_dev_info;
La estructura bio está definida en include/linux/bio.h son dos punteros de 4 bytes cada uno.
reclaim_state está definido en include/linux/swap.h y contiene una variable de tipo unsigned long llamada reclaimed_slab, por tanto otros 4 bytes. Backing_dev_info se localiza en include/linux/backing_dev.h es otro puntero a la estructura total, por tanto 4 bytes más:
BIO_LIST BIO_TAIL RECLAIM_STATE BACKING_DEV_INFO struct io_context *io_context; unsigned long ptrace_message; siginfo_t *last_siginfo; /* For ptrace use. */ /* * current io wait handle: wait queue entry to use for io waits * If this thread is processing aio, this points at the waitqueue * inside the currently handled kiocb. It may be NULL (i.e. default * to a stack based synchronous wait) if its doing sync IO. */ wait_queue_t *io_wait;
Ahora tenemos tres punteros y una variable unsigned_long. io_context está definido en include/linux/blkdev.h, siginfo_t está definido en asm-generic/siginfo.h, wait_queue_t está definido en include/linux/wait.h:
*IO_CONTEXT PTRACE_MESSAGE *LAST_SIGINFO *IO_WAIT #ifdef CONFIG_TASK_XACCT /* i/o counters(bytes read/written, #syscalls */ u64 rchar, wchar, syscr, syscw; #endif struct task_io_accounting ioac; #if defined(CONFIG_TASK_XACCT) u64 acct_rss_mem1; /* accumulated rss usage */ u64 acct_vm_mem1; /* accumulated virtual memory usage */ cputime_t acct_stimexpd;/* stime since last update */ #endif #ifdef CONFIG_NUMA struct mempolicy *mempolicy; short il_next; #endif #ifdef CONFIG_CPUSETS struct cpuset *cpuset; nodemask_t mems_allowed; int cpuset_mems_generation; int cpuset_mem_spread_rotor; #endif struct robust_list_head __user *robust_list; #ifdef CONFIG_COMPAT struct compat_robust_list_head __user *compat_robust_list; #endif struct list_head pi_state_list; struct futex_pi_state *pi_state_cache;
Todas las condicionales son negativas. Robust_list está definida en include/linux/futex.h y futex_pi_state en kernel/futex.c Así queda:
*ROBUST_LIST PI_STATE_LIST_NEXT PI_STATE_LIST_PREV *PI_STATE_CACHE atomic_t fs_excl; /* holding fs exclusive resources */ struct rcu_head rcu; /* * cache last used pipe for splice */ struct pipe_inode_info *splice_pipe; #ifdef CONFIG_TASK_DELAY_ACCT struct task_delay_info *delays; #endif #ifdef CONFIG_FAULT_INJECTION int make_it_fail; #endif };
Y acabamos, ambas condicionales son falsas por lo tanto sólo tenemos que:
fs_excl tiene 4 bytes reservados, la estructura rcu_head está definida en include/linux/rcupdate.h y tiene 8 bytes, pipe_inode_info son 4 bytes
FS_EXCL *RCU *RCU *SPLICE_PIPE
Habréis observado que existen dos variables de tipo spinlock_t, hasta mi entendimiento tienen reservados 8 bytes por si se obtiene el lock, el problema es que en sistemas monoprocesador sin preemptibilidad no se usan (ya que no hay dos micros distintos intentando acceder al mismo recurso). Es decir oficialmente mi task_struct tiene 1320 bytes + 8 de spinlocks.
Reconstrucción de la tabla de procesos en base a su task_struct
Para ésto conviene que tengáis a mano varios terminales. Como root acceded al depurador (debe coincidir la versión del núcleo que estáis corriendo con el vmlinux:
#gdb /usr/src/linux-2.6.23-1/vmlinux /proc/kcore
Primero necesitaréis la dirección del proceso swapper, también llamado ``init_task'' presente en /usr/src/linux-2.6.23-1/System.map
#grep init_task /usr/src/linux-2.6.23-1/System.map
en mi caso 0xc06d0280
Sabemos que la estructura de tareas (en mi caso) es de 1328 bytes (en caso de ser smp, se usan todos, al no serlo los ocho últimos no se usan), 332 palabras. Por tanto es la cantidad de pondremos en gdb para que nos muestre:
(gdb)x/332 0xc06d0280 0xc06d0280 : 0x00000000 0xc0774000 0x00000002 0x00002000 0xc06d0290 : 0x00000000 0xffffffff 0x0000008c 0x00000078 0xc06d02a0 : 0x0000008c 0xc06d02a4 0xc06d02a4 0xc076fe40 0xc06d02b0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d02c0 : 0x00000000 0x00000000 0x00000400 0x00400000 0xc06d02d0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d02e0 : 0x0c46696a 0x00000000 0x0c46696a 0x00000000 0xc06d02f0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0300 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0310 : 0x00000001 0x00000064 0xc20fcb28 0xf6bba0c8 0xc06d0320 : 0xc06d0320 0xc06d0320 0xc06d0328 0xc06d0328 0xc06d0330 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0340 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0350 : 0x00000000 0x00000000 0x00000000 0xc06d0280 0xc06d0360 : 0xc06d0280 0xc20fcb7c 0xc20fc64c 0xc06d036c 0xc06d0370 : 0xc06d036c 0xc06d0280 0x00000000 0xc06d9310 0xc06d0380 : 0xc06d9300 0x00000000 0xc20fc664 0xc06d9300 0xc06d0390 : 0x00000000 0xc20fc670 0xc06d9300 0x00000000 0xc06d03a0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d03b0 : 0x00000000 0x00000000 0x00035b8a 0x00000000 0xc06d03c0 : 0x00025ccc 0x00000000 0x00000000 0x00000000 0xc06d03d0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d03e0 : 0x00000000 0x00000000 0x00000000 0xc06d03ec 0xc06d03f0 : 0xc06d03ec 0xc06d03f4 0xc06d03f4 0xc06d03fc 0xc06d0400 : 0xc06d03fc 0x00000000 0x00000000 0x00000000 0xc06d0410 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0420 : 0x00000000 0xc06d8fe0 0xfffffeff 0x00000000 0xc06d0430 : 0xffffffff 0x00000000 0xc06d8b60 0x00000000 0xc06d0440 : 0x00000000 0x70617773 0x00726570 0x00000000 0xc06d0450 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0460 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0470 : 0x00000000 0x00000000 0xc0776000 0x00000060 0xc06d0480 : 0xc056a8b3 0xc0775fbc 0x00000000 0x00000000 0xc06d0490 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d04a0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d04b0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d04c0 : 0x0000037f 0x00000000 0x00000000 0x00000000 0xc06d04d0 : 0xc076fbc4 0x00000000 0x00001f80 0x0000ffff 0xc06d04e0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d04f0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0500 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0510 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0520 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0530 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0540 : 0x00000000 0x800bf600 0x00004015 0x00000000 0xc06d0550 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0560 : 0x0000005a 0x00000000 0x00000000 0x00000000 0xc06d0570 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0580 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0590 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d05a0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d05b0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d05c0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d05d0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d05e0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d05f0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0600 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0610 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0620 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0630 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0640 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0650 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0660 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0670 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0680 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0690 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d06a0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d06b0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d06c0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d06d0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d06e0 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d06f0 : 0xc06d29c0 0xc06d29e0 0xc06d94d8 0xc06d2aa0 0xc06d0700 : 0xc06d2c40 0x00000000 0x00000000 0x00000000 0xc06d0710 : 0x00000000 0x00000000 0x00000000 0xc06d071c 0xc06d0720 : 0xc06d071c 0x00000000 0x00000000 0x00000000 0xc06d0730 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0740 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0750 : 0xc06d0750 0xc06d0750 0xc06d0758 0xc06d0758 0xc06d0760 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0770 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0780 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d0790 : 0x00000000 0x00000000 0x00000000 0x00000000 0xc06d07a0 : 0x00000000 0x00000000 0x00000000 0x00000000
Información relevante a destacar en base a mi estructura:
Offset 0: estado, indica si el proceso se encuentra, (en este caso 0, ``runnable''),
Offset 152: dirección a la siguiente tarea. (0xc20fcb28)
Offset 156: tarea previa. (0xf6eeec08)
Offset 176: puntero a la estructura mm del proceso (nulo si es un hilo del kernel (0)
Offset 212: Pid del proceso. (0)
Offset 392: UID efectivo (0)
Offset 408: GID efectivo (0)
Offset 424: Privilegios efectivos (0xfffffeff, todos salvo CAP_SETPCAP)
Offset 452: Nombre del proceso (70617773 00726570 00000000 00000000, que traducido tabla ascii en mano y teniendo en cuenta que es little endian se traduce como swapper)
Offset 1136: Puntero a estructura fs (0xc06d29c0)
Offset 1140: Puntero a estructura files (0xc06d29e0)
Por brevedad sólo colocaré la tarea previa, para que veáis su mm_struct, pid y demás.
(gdb) x/294 0xf6bba0c8 0xf6bba0c8: 0xf79025f8 0xc23f60c8 0xf6bba0d0 0xf6bba0d0 0xf6bba0d8: 0xf6bba0d8 0xf6bba0d8 0xf6da1040 0xf6da1040 0xf6bba0e8: 0xc06ddbf8 0x00000000 0x00000000 0x00000011 0xf6bba0f8: 0x00000000 0x00000000 0x00000001 0x00000ae7 0xf6bba108: 0x00000ae7 0xc23f6030 0xc23f6030 0xf6bba114 0xf6bba118: 0xf6bba114 0xc23f6114 0xc23f6114 0xf6bba030 0xf6bba128: 0x00000000 0xc20fb5b0 0xc20fb5a0 0x00000000 0xf6bba138: 0xc20fb5b4 0xc20fb5a0 0xc23f6140 0xc21fa474 0xf6bba148: 0xc21fa45c 0xf6bba14c 0xf6bba14c 0x00000000 0xf6bba158: 0xb7e21708 0xb71dbb68 0x00000000 0x00000048 0xf6bba168: 0x00000004 0x000119a2 0x000001bf 0x00000ce1 0xf6bba178: 0x17410f2f 0x00000ce1 0x17410f2f 0x00001685 0xf6bba188: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba198: 0x00000000 0xf6bba19c 0xf6bba19c 0xf6bba1a4 0xf6bba1a8: 0xf6bba1a4 0xf6bba1ac 0xf6bba1ac 0x000003e8 0xf6bba1b8: 0x000003e8 0x000003e8 0x000003e8 0x000003e8 0xf6bba1c8: 0x000003e8 0x000003e8 0x000003e8 0xf7fed180 0xf6bba1d8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba1e8: 0xf7b13500 0x00000000 0x00000000 0x0078796c 0xf6bba1f8: 0x65740000 0x6e656d6e 0x006d0074 0x00000000 0xf6bba208: 0x00000000 0x00000000 0xbb20ffff 0xb7dff21d 0xf6bba218: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba228: 0xf6bc5ff8 0x00000060 0xc056a8b3 0xf6bc5b2c 0xf6bba238: 0x00000000 0x00000033 0x00000000 0x00000000 0xf6bba248: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba258: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba268: 0x00000000 0x00000000 0x4020037f 0x039d0000 0xf6bba278: 0x0819e84d 0x00000073 0xbf9c85a8 0x0000007b 0xf6bba288: 0x00001f80 0x0000ffff 0x00000000 0x00000000 0xf6bba298: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba2a8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba2b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba2c8: 0x00000000 0x00000000 0x00000000 0xa0000000 0xf6bba2d8: 0x00004002 0x00000000 0x00000000 0x80000000 0xf6bba2e8: 0x00003fff 0x00000000 0x00000000 0x00000000 0xf6bba2f8: 0x00000000 0x00000000 0x00000000 0xd0000000 0xf6bba308: 0x00004004 0x00000000 0x00000000 0x00000000 0xf6bba318: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba328: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba338: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba348: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba358: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba368: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba378: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba388: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba398: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba3a8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba3b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba3c8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba3d8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba3e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba3f8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba408: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba418: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba428: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba438: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba448: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba458: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba468: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba478: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba488: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba498: 0x00000000 0x00000000 0xc2108cc0 0xc20fdec0 0xf6bba4a8: 0xc06d94d8 0xf6e73ac0 0xf6bb3040 0x00000000 0xf6bba4b8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba4c8: 0x00000000 0xf6bba4cc 0xf6bba4cc 0x00000000 0xf6bba4d8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba4e8: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba4f8: 0x0000000d 0x0000000e 0xf6bba500 0xf6bba500 0xf6bba508: 0xf6bba508 0xf6bba508 0x00000000 0x00000000 0xf6bba518: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba528: 0xc21373e0 0x00000000 0x00000000 0x00000000 0xf6bba538: 0x00000000 0xf6bba53c 0xf6bba53c 0x00000000 0xf6bba548: 0x00000000 0x00000000 0x00000000 0x00000000 0xf6bba558: 0x00000000 0x00000000
Notad algo, solo imprimo 294 bytes, la razón es que empiezo en task_struct+152 que es la dirección a donde apuntan tanto next_task como prev_task. Para ver la información previa (como el estado deberéis restar a la dirección de next_task 152 y apuntar allí el gdb).
Por tanto aquí en offset 0 está la dirección de la siguiente tarea, 0xf79025f8 y en offset 4 la de la previa 0xc23f60c8.
El puntero mm está ahora en el offset 24 (176-152) que ahora apunta a una estructura mm que contiene información acerca de su mapa de memoria. (0xf6da1040).
Pid del proceso (ae7) que convertido a decimal es 2791
UID efectivo ahora en el offset 240 (392-152), ahora 3e8, en decimal 1000. Podéis hacer un x 0xf6bba0c8+240 si os resulta más cómodo.
GID efectivo: en offset 256, su valor es 3e8 o 1000 en decimal.
Privilegios efectivos, haciendo las cuentas vemos que está en el offset 272, su valor actual es 0, dado a que sólo el superusuario las tiene concedidas.
COMM: el nombre del proceso, su valor es 0078796c 65740000 6e656d6e 006d0074 que traducido al castellano tabla ascii en mano es: NULxyl etNULNUL nemn NULmNULt, desconozco el por qué de los últimos bytes (tenment), supongo que será algún leak, fijáos en los primeros bytes, es xyl, que al ser little endian es lyx, el software con el que estoy escribiendo este artículo.
Por último pongo en negrita tanto el puntero al fs_struct como el del files_struct del proceso lyx.
Con ésto ya podéis seguir reconstruyendo la tabla de procesos, lo más natural es hacerlo partiendo del init_task ir al siguiente proceso (init) y después al siguiente hasta acabar llegando otra vez al inicio (es una lista circular), esta técnica detecta troyanos en ring 3 como aquellos que se basan en (por ejemplo) la modificación de llamadas al sistema. Aún así no es perfecta ya que no detecta desenlazados de la lista circular (que el siguiente no apunte al siguiente sino dos más etc). Para ésto ya encontraremos solución, como la reconstrucción de la tabla en base a sus ``slabs''.
- Inicie sesión o regístrese para enviar comentarios
- 2274 lecturas

Bueno, las potencias no se han convertido.
2 elevado a 32 -1 y 2 elevado a 8 -1
---
"Don't accept that what's happening;
Is just a case of others' suffering;
Or you'll find that you're joining in"
-Pink Floyd- On the turning away.
Respuesta a Bueno, las potencias no se
El on your debian system sobra de la licencia, creo que la vista previa juega malas pasadas
---
"Don't accept that what's happening;
Is just a case of others' suffering;
Or you'll find that you're joining in"
-Pink Floyd- On the turning away.
Muyyy interesante, de verdad que seguire muy de cerca tus articulos, entendi bastante bien las estructuras propias de los procesos y los punteros, lo que no sabia es que fuese circular es decir que el ultimo proceso volviese a apuntar al primero, empezaré con pruebas basicas, en una debian virtualizada, ver los procesos en memoria y hacer un dump de la memoria fisica a archivo y hacer un miniprograma para reconstruir la lista de procesos, me ha encantado el articulo
Felicidades Javi ;)
---
La seguridad es solo un estado mental.
Entre la satisfacción y la total decepción hay solo una acción.
Solo se que se todo lo que no se
Respuesta a Muyyy interesante, de verdad que
Phrack escribió un artículo de como saltarse ésto, es decir, quitar un proceso de la lista enlazada y visible sólo por el scheduler. Hay otro método que documentaré que se basa en el task_struct_cachep reconstruyendo la lista enlazada en base a los slabs (almacenes de estructuras del mismo tipo) que sí los detecta (o por lo menos eso pienso). Vamos que no te fíes al 100% de la lista enlazada.
---
"Don't accept that what's happening;
Is just a case of others' suffering;
Or you'll find that you're joining in"
-Pink Floyd- On the turning away.
Respuesta a Phrack escribió un artículo de
si no me equivoco, ¿quieres decir no hacer caso a los punteros? y leer espacios de memoria contigua?, es decir, leyendo estructuras slab, que creo que pueden tener 3 estados (aparte de la informacion que contengan) vacio, parcial y lleno, si no me equivoco esto esta relacionado con la memoria cacheada y con una mejora de los kernels 2.6.24 (aunque existia de mucho antes), siempre me ha resultado una estructura muy compleja, aunque no imposible de entender.
---
La seguridad es solo un estado mental.
Entre la satisfacción y la total decepción hay solo una acción.
Solo se que se todo lo que no se
Respuesta a Phrack escribió un artículo de
Ummm y esto esta en el kernel?, tengo que buscarlo pues no lo se, pero tiene buena pinta (SLUB en lugar de SLAB), parece es la respuesta a un posible problema con SLAB, me informo mejor y comento.
http://lwn.net/Articles/229984/
---
La seguridad es solo un estado mental.
Entre la satisfacción y la total decepción hay solo una acción.
Solo se que se todo lo que no se
Respuesta a Ummm y esto esta en
Me respondo a mi mismo no me di cuenta de lo que pone al final
the SLUB allocator is in the -mm tree now and could hit the mainline as soon as 2.6.22
---
La seguridad es solo un estado mental.
Entre la satisfacción y la total decepción hay solo una acción.
Solo se que se todo lo que no se
Respuesta a si no me equivoco, ¿quieres
si no me equivoco, ¿quieres decir no hacer caso a los punteros? y leer espacios de memoria contigua?
Cada técnica es capaz de detectar más o menos cosas, por ejemplo:
Puedes reconstruir toda la lista de procesos en base a su mm_struct, ya que cada proceso tiene una asignada, salvo en el caso de los hilos del kernel que no (por tanto su límite es ese), la lista enlazada puede ser modificada sacando de la lista un proceso, tal como dicen los de phrack.
Te voy a hacer una comparación de como funcionan los slabs:
Tienes 5 cajones en tu escritorio. A cada cajón le metes una rejilla que lo subdivide en muchos minicompartimentos de tamaño fijo, aunque las rejillas de cada cajón son de tamaños distintos (unas más grandes que otras) sabes que puedes meter en ellas x objetos de su tamaño. Existen filas que están llenas de objetos (todas las casillas ocupadas), otras llenas a medias y otras en las que no has puesto ningún objeto, pero que pueden ser usadas en un futuro. Los slabs se basan en eso.
Tú sabes que cada objeto llama al siguiente por la lista enlazada aunque eso puede ser cambiado (llamando a dos procesos más en vez de uno), lo que es más complejo es que se saque ese objeto del cajón en el que se encuentra. En ese cajón están todas las estructuras tipo task.
---
"Don't accept that what's happening;
Is just a case of others' suffering;
Or you'll find that you're joining in"
-Pink Floyd- On the turning away.
Me sigue sorprendiendo que u tío que no es informático ni de lejos como tú (o Colivas, por ejemplo) se dediquen a estas tareas de chinos y yo que vivo de esta mierda de negocio pase completamente del tema.
A veces pienso si no me hubiese ido mejor dejar la informática como hobby y dedicarme a reparar electrodomésticos para ganarme la vida.
En fins, enhorabuena Javi.
Si quieres otra charla trascendental sobre procesos y memoria del SO llámame y nos tomamos un algo :)
---
The "El Bierzo" stories
Respuesta a Me sigue sorprendiendo que u
Hombre yo cuando hablé del artículo de análisis forense por primera vez dije que podríamos hacerlo conjunto, mi oferta sigue en pie.
PD: conmigo cerca la reparación de lavadoras tiene futuro.
---
"Don't accept that what's happening;
Is just a case of others' suffering;
Or you'll find that you're joining in"
-Pink Floyd- On the turning away.
Respuesta a Sabemos como las probarias (Espero
Pues no, no se ve bien, se me olvidó poner el modo html XD.
---
La seguridad es solo un estado mental.
Entre la satisfacción y la total decepción hay solo una acción.
Solo se que se todo lo que no se
Respuesta a Pues no, no se ve
Espero que lo que hay en el vaso no sea zumo de grosellas.
---
The "El Bierzo" stories
Respuesta a Espero que lo que hay
Bueno lo pongo porque cuesta saber que es el "Dibujo", es una calabera XD
---
La seguridad es solo un estado mental.
Entre la satisfacción y la total decepción hay solo una acción.
Solo se que se todo lo que no se
Respuesta a Bueno lo pongo porque cuesta
Y yo que le veía cierto parecido conmigo...
---
"Don't accept that what's happening;
Is just a case of others' suffering;
Or you'll find that you're joining in"
-Pink Floyd- On the turning away.
Respuesta a Y yo que le veía
Yo vi los pantalones de Mickey Mouse, ¿tengo algo de qué preocuparme?
---
"Rendirse ante la ignorancia y llamarla dios siempre ha sido prematuro, y aún sigue siéndolo"
(Isaac Asimov)