When you power on an SGI IRIS workstation, the processor begins running a program in the PROM (the chip that holds the computer firmware). This program checks all the IO devices for basic functionality, spins up and handshakes all of the connected disks, and starts the graphics running as what is called a textport.
The textport is a window drawn in the middle of the screen that holds the output of any program run before XWindows starts up. Interaction with the PROM, standalone programs, and IRIX in single-user mode all happen through the textport, which is coded in the PROM. As IRIX starts up XWindows, it re-connects its console device from the textport to the X console, which is an instance of XWsh, the standard IRIX terminal emulator.
The PROM on the SGI computers since about 1993 also contains some graphical menus, buttons, and mouse cursor routines, which look just like Motif. These graphics are not very functional, and only are used to make a more friendly interface for booting, installing the system, and choosing the keyboard map. You cannot use the mouse cursor in the PROM to select or edit input, it only works on the buttons such as "Exit".
'stand' is for Standalone, which refers to all of the programs compiled to run on the bare hardware, without the OS or libraries. There are a few of these you may see.
sash is the disk loader program. The IRIS PROM contains routines that can load standalone programs from only a few places, like the volume header (volhdr) of a local disk, a local tftp server, or from tape. To load a program from a filesystem the PROM relies on sash, which it loads automatically when you tell it to boot a file.
sash also has the ability to read files and directories on the disk. You can use ls or cat commands from the sash prompt. On a working IRIX disk, sash is always found in the volume header.
ide is the hardware test and diagnostic program. You would use it when testing a machine you just acquired, or when hunting down hardware issues. It can run torture tests of the different systems in the machine, and keep a list of errors it encountered to show you later on. Supposedly there are two versions of ide for each processor: one is shipped to customers and the other is for factory burn-in. ide usually lives in /usr/stand/ide and requires sash to be loaded, although in some cases it is in the volhdr and can be loaded without sash, by pressing 3 "Run Diagnostics" in the Maintenance Menu.
symmon is a resident kernel debugger that can be used to debug a running IRIX kernel. You won't need this unless you're hacking the kernel or device drivers. It usually lives in the volhdr when it's installed.
When you first turn on your IRIS, you see a dialog that asks you if you want to stop for maintenance. If you do nothing, the PROM will automatically start booting IRIX after about 5 seconds. If you click the dialog's button, or hit the Escape key, the boot sequence stops and you are shown the Maintenance Menu. On the post-1993 machines this is a graphical menu with 6 options, including Starting the System, Installing System Software, Running Diagnostics, Restoring from Backup, Command Prompt, and Keyboard Layout. The earlier machines only had numbered choices from a text menu, and hitting a number key from 1 to 6 works equally well on the new, graphical menu.
To open the textport and type commands at the PROM Monitor, hit the 5 key or click on Command Prompt. Now you can list the hardware makeup of the machine with hinv, or set the time in the battery-powered clock with date. Typing help or ? lists some of the commands available, but a few are missing from the list. The PROM understands names of devices to tell it where you are trying to load files from. As mentioned above, it cannot read filesystems. The acceptable devices are in either a traditional form or a new form. In almost all cases you can use the traditional form, which is much easier to type.
| Traditional | New |
|---|---|
| dksc(0,1,0) | scsi(0)disk(1)partition(0) |
| tpsc(0,2,0) | scsi(0)tape(2)tape(0) |
The PROM doesn't support any kind of input editing, so keep your fingers off the arrow keys. It also doesn't support using the numeric pad to enter numbers, use the top number keys.
January 14, 1995 06:17:09 GMT>> ? date date: date [mmddhhmm[ccyy|yy][.ss]]>> date 101507152005
October 15, 2005 07:15:00 GMT
Some other NVRAM variables of interest are eaddr, which shows the hardware Ethernet MAC address of the IRIS, and is generally used as a dongle for software licenses; console, which chooses whether the main interface to the machine is via the monitor and keyboard (g) or via a serial port (d, d1, d2); volume, which sets how loud the startup chimes are played; diagmode, which chooses whether to display a window when the power first comes on (if set to v), showing the results of the basic IO tests, and the model numbers of all attached drives; and various others.
ls will show the contents of the main disk's volhdr. You should see at least sash there, and maybe disklabel as well. If so you can enter sash by typing either boot or sash. You will see a version banner, then you can run standalone programs, like fx or ide, that live on a filesystem. Sash has input editing, but it doesn't use arrow keys. Instead you can use Control-p and Control-n to go through the command history, and Control-b and Control-f to move the cursor in the input line.
130768+22320+3184+341792+48560d+4604+6816 entry: 0x97fa60d0 Standalone Shell SGI Version 6.5 ARCS Apr 29, 1998 (32 Bit) sash:
scsi(0)disk(1)rdisk(0)partition(8)/: sgilabel sash scsi(0)disk(1)rdisk(0)partition(0)/: . .. hw ns Mac bin dev etc lib opt tmp usr var .ucp .web proc sbin dumpster unix .dtEnvPref .netscape .webcache .sgihelprc .desktop-IRIS CDROM Desktop nsmail .acrorc .cshrc stand debug .neditdb .ebtpriv .wshttymode .varupdate .syserr .Sgiresources lib32 .login .sh_history -c.lock .showcaserc .profile .desktophost
Whew. So we can see that files and directory names are printed exactly the same (sbin is a directory, but unix is a file). There's no way to make it show which is which, you just have to know. Display a directory with ls, a file with cat. If you get it wrong you'll get a cryptic error. Pause output with Control-s, resume with Control-q.
sash: cat dksc(0,1,0)/.syserr#2.0 NOTIFICATION=2 AUDIO=1 LOCALBLOCK=
I have no idea what that file does (like a lot of them) but it's short enough to include here as an example. To display a file inside a directory you would just change the command line: (press Control-p to go back to a previous command input)
sash: cat dksc(0,1,0)/etc/passwd root:0z5nP1UbeZrec:0:0:Super-User:/:/bin/csh sysadm:*:0:0:System V Administration:/usr/admin:/bin/sh cmwlogin:*:0:994:CMW Login UserID:/usr/CMW:/sbin/csh diag:*:0:996:Hardware Diagnostics:/usr/diags:/bin/csh[... shortened for brevity ...]
EZsetup::992:998:System Setup:/var/sysadmdesktop/EZsetup:/bin/csh demos:*LK*:993:997:Demonstration User:/usr/demos:/bin/csh OutOfBox:*LK*:995:997:Out of Box Experience:/usr/people/OutOfBox:/bin/csh guest:*:998:998:Guest Account:/usr/people/guest:/bin/csh 4Dgifts:*:999:998:4Dgifts Account:/usr/people/4Dgifts:/bin/csh nobody:*:60001:60001:SVR4 nobody uid:/dev/null:/dev/null noaccess:*:60002:60002:uid no access:/dev/null:/dev/null haxor::4554:994:HaXoR Q. VaNdAl:/usr/people/haxor:/bin/tcsh
If the second field is empty (the two enclosing colons are right next to each other) then no password is set, so no password prompt will be given when you try to log in. If the field is * or *LK* then logging in is not allowed. Otherwise the field holds 13 characters which are a one-way hash of an 8-character password.
One special case: If the second field of the entry for "root" is *, then that password is stored in a different file, /etc/shadow. Replace /etc/passwd with /etc/shadow in all of the steps.
But if the root password was a secure one, with a lot of
control-characters and no obvious dictionary words, then you're stuck.
Except you aren't: you have physical access to the machine and the
ability to write to its disk blocks (with fx). So all you need is to
replace the 13-character password that's already there with a different
13 characters that encrypt an empty password. There are 4096 such, one
for each possible value of the salt (read a unix textbook for an explanation). One of them is 0z5nP1UbeZrec (case-sensitive, the sixth char is a one, not lowercase L).
Now the problem is how to get that written into the passwd file without being able to boot into unix! If you had another computer that could read and write XFS filesystems in an SGI partitioned disk, you could just mount your system disk on that and do it. Short of that, you're going to have to be inventive. I have never seen this technique described before, and it's a little bit complicated, so bear with me on this.
[You will need a pencil and a pad of paper, plus a good engineering calculator that can do arithmetic on hexadecimal (base 16) numbers. I strongly recommend the HP48. A program for the HP48 to automate the process is in the Appendix.]The disk is composed, at its most basic level, of a number of sectors each assigned a number from 0 up to the end of the disk. The actual arrangement of cylinders and tracks is irrelevant, since the software addresses the disk in linear block addresses. Each sector is 512 bytes long. The disk is structured into partitions, in the SGI architecture there are up to 16 of them. There are some number of usable partitions which are nonoverlapping, plus a couple which overlap all of the others and are used for maintenance tasks such as cloning whole disks. The very first partition on the disk is called the volhdr and contains the partition map, which defines the layout of all the partitions on the disk. This layout is stored in the very first sector on disk, sector 0, but the volhdr continues for another few thousand sectors in order to hold files in a small area that can be used by the PROM. This area is not a filesystem per se, and can only store up to 15 small, contiguous files for system purposes. Normally there are only 1 or 2 files stored.
130768+22320+3184+341792+48560d+4604+6816 entry: 0x97fa60d0 Currently in safe read-only mode. Do you require extended mode with all options available? (no) SGI Version 6.5 ARCS BE Oct 1, 1999 fx: "device-name" = (dksc) fx: ctlr# = (0) fx: drive# = (1) ...opening dksc(0,1,0) ...drive selftest...OK Scsi drive type == SGI QUANTUM XP32150 S89C ----- please choose one (? for help, .. to quit this menu)----- [exi]t [d]ebug/ [l]abel/ [b]adblock/ [exe]rcise/ [r]epartition/ fx>
----- partitions ----- part type blocks Megabytes (base+size) 0: xfs 266240 + 4138249 130 + 2021 1: raw 2048 + 264192 1 + 129 8: volhdr 0 + 2048 0 + 1 10: volume 0 + 4404489 0 + 2151
The first sector of the root partition contains a data structure central to the filesystem called the superblock. The superblock is the first information read from the filesystem and is used to reach everything else. This means that it contains a pointer to other structures, which eventually reach every file on the filesystem. These pointers are held in a structure which is too complicated to describe here, but I will summarize the information to the minimum needed for our hacking purposes.
The structure which holds the root directory of the filesystem (the root directory of the whole system, since we are talking about the root partition) is a directory inode. This structure in turn points to other structures that hold the list of the directory's contents. So by following these pointers we can move from the superblock, to the root directory inode, to inferior directories, to the data blocks that hold a file in one of those directories. A complication to all this is that the pointers are not represented as disk addresses. Instead they are represented using various different formats such as inode numbers and filesystem block numbers.
I mentioned that the XFS filesystem partition is not located at the beginning of the disk. It is located after the volhdr and the swap partition (type raw). So all of the pointers in the XFS structures are not in terms of disk addresses, but addresses within this partition. To convert a sector number within the partition to a sector number on disk, we add the base of the partition in blocks. In the example partition table above, this is 266240 sectors. (Think of "blocks" by itself as a synonym for sectors.) In hexadecimal this number is 0x41000.
This menu has various features including seek, readbuf, dumpbuf, editbuf, and number.
The debug menu has a notion of a buffer of bytes, and a current position on disk.
fx/debug> seek 0 fx/debug> readbuf 20 1 fx/debug> dumpbuf s 0 266We should see some output very close to this:
0x0000> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .....A..../unix... 0x0012> 0000 0BE5 A941 0000 0001 2F75 6E69 7800 0000 .................. 0x0024> 0000 0000 0000 0000 0000 0000 0EF8 0000 0014 .....s............ 0x0036> 0000 0000 0073 0200 0000 0000 0000 0000 0000 .................. 0x0048> 0000 0000 0000 0000 0000 0000 0000 0000 0086 }.sgilabel........ 0x005a> 7D2E 7367 696C 6162 656C 0000 0002 0000 0200 sash..........N.sy 0x006c> 7361 7368 0000 0000 0000 0003 0004 4E00 7379 mmon.....*..h.ide. 0x007e> 6D6D 6F6E 0000 0000 022A 0005 6800 6964 6500 ..........N..ymmon 0x0090> 0000 0000 0000 06FE 0004 4E00 0079 6D6D 6F6E ...........ymmon.. 0x00a2> 0000 FFFF FFFF 0000 0000 0079 6D6D 6F6E 0000 .................. 0x00b4> FFFF FFFF 0000 0000 0000 0000 0000 0000 0000 .......ash........ 0x00c6> 0000 0000 0000 0061 7368 0000 0000 FFFF FFFF .....ash.......... 0x00d8> 0000 0000 0061 7368 0000 0000 FFFF FFFF 0000 ...de............. 0x00ea> 0000 0064 6500 0000 0000 FFFF FFFF 0000 0000 .de..............a 0x00fc> 0064 6500 0000 0000 FFFF FFFF 0000 0000 0061 sh................ 0x010e> 7368 0000 0000 FFFF FFFF 0000 0000 0000 0000 .................. 0x0120> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ...........de..... 0x0132> 0000 0000 0000 0000 0000 0064 6500 0000 0000 .........~m....... 0x0144> FFFF FFFF 0000 0000 007E 6D2E 0008 1000 0000 .................. 0x0156> 000A 0008 0000 0000 1000 0000 0003 0000 0000 .................. 0x0168> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x017a> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x018c> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x019e> 0000 0000 0000 0000 0000 0000 0000 0000 1000 .................. 0x01b0> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ....}............. 0x01c2> 0000 0086 7D2E 0000 0000 0000 0006 0000 0000 .................. 0x01d4> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01e6> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01f8> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ...W.a.... 0x020a> 0000 C357 C861 0000 0000
Now don't get overwhelmed by this! All of this is really very easy and simple. The numbers on the left are showing the offset (in hexadecimal) of the beginning of each line of data from the start of the buffer. We always start displaying the buffer from 0, so they always start with 0. The middle section of each row are the hexadecimal bytes in the sector, grouped into words. On the far right, fx shows any ASCII characters encoded by the bytes of data.
The first actual word in the sector is 0x0BE5A941, which we have put at position 20 in the buffer (hexadecimal 0x14). It is a magic number that identifies this as an SGI partition map. On the right you will see the letter 'A', because 0x41 is the ASCII encoding for 'A'.
fx/debug> s 0x81000
fx/debug> r 20 1
fx/debug> d s 0
fx/debug/dumpbuf: nshorts = (266) 0x0000> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ..XFSB............ 0x0012> 0000 5846 5342 0000 1000 0000 0000 000F CDA5 ................1W 0x0024> 0000 0000 0000 0000 0000 0000 0000 0000 3157 ...^......i..k.... 0x0036> CEEE 135E 101C 87E9 0800 690A 1C6B 0000 0000 .................. 0x0048> 0008 0004 0000 0000 0000 0080 0000 0000 0000 .................. 0x005a> 0081 0000 0000 0000 0082 0000 0010 0001 F9B5 .................. 0x006c> 0000 0008 0000 0000 0000 0490 1094 0200 0100 .................. 0x007e> 0010 0000 0000 0000 0000 0000 0000 0C09 0804 ..........(....... 0x0090> 1100 0019 0000 0000 0001 2880 0000 0000 0000 .Y.......[........ 0x00a2> 0A59 0000 0000 0005 015B 0000 0000 0000 0000 .................. 0x00b4> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x00c6> 0000 0000 0002 0000 0000 0000 0000 0000 0000[truncated for brevity]
Here are buried some more global parameters for the filesystem that we'll need to write down for later. All of these constants are 32-bit ints.
First, at offset 0x4 in the block (add 20 for where it will be located in the fx buffer, so here we get 0x18) is the size of a file system block, or FSB. We want to keep track of how many disk sectors are in each FSB, so we want to divide this number here by 512. In the case shown, 0x1000 / 512 = 8. Call this number FSBSIZE.
Next at offset 0x3C in the block (offset 0x50 in the fx buffer) is the number of the root inode. Write this down and save it for later.
At offset 0x54 in the block (offset 0x68 in the fx buffer) is a constant called the Allocation Group Size, measured in FSBs. Write this down as AGSIZE. Then, derive another constant from it by rounding it up to a power of 2. You can do this by taking the Log of AGSIZE, dividing by the Log of 2, rounding up to the next whole number, and raising 2 to that power. Write this down as AGMASK.
At offset 0x58 in the block (offset 0x6C in the fx buffer) is the number of allocation groups on the partition, AGCOUNT.
Now we want to look at the next object in our filesystem chain, the root inode, which holds the root directory. From the previous step you should have the inode number (inum) of the root inode. In XFS, inodes are 256 bytes in size, which is half of a disk sector. Here are the steps for converting an inode number into a FSB number:
fx/debug> s 0x81040
fx/debug> r 20 1
fx/debug> d s 0
fx/debug/dumpbuf: nshorts = (266) 0x0000> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ..INA............. 0x0012> 0000 494E 41ED 0102 0020 0000 0000 0000 0000 ................=. 0x0024> 0000 0020 0000 0000 0000 0000 0000 0000 3DCF .5..,(=.?d...|=.?d 0x0036> 0D35 0BA5 2C28 3DCA 3F64 09BF EC7C 3DCA 3F64 ...&.............. 0x0048> 09C0 1526 0000 0000 0000 1000 0000 0000 0000 .................. 0x005a> 0001 0000 0000 0000 0001 0000 0002 0000 0000 .................. 0x006c> 0000 0000 0000 0000 FFFF FFFF 0000 0000 0000 ......8`....xfsres 0x007e> 0000 0000 0000 3860 0001 8319 7866 7372 6573 torehousekeepingdi 0x0090> 746F 7265 686F 7573 656B 6565 7069 6E67 6469 r.........orphanag 0x00a2> 7200 0000 0000 2000 8009 6F72 7068 616E 6167 e................. 0x00b4> 6500 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x00c6> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x00d8> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x00ea> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x00fc> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ......IN.......... 0x010e> 0000 0000 0000 494E 8000 0102 0001 0000 0000 .................. 0x0120> 0000 0000 0000 0001 0000 0000 0000 0000 0000 ..........,B.k..j. 0x0132> 0000 0000 0000 0000 0000 2C42 136B 1B18 6AA8 ,B.k..j........... 0x0144> 2C42 136B 1B18 6AA8 0000 0000 0000 0000 0000 .................. 0x0156> 0000 0000 0000 0000 0000 0000 0000 0000 0002 .................. 0x0168> 0000 0000 0000 0004 0000 0000 FFFF FFFF 0000 .................. 0x017a> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x018c> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x019e> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01b0> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01c2> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01d4> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01e6> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01f8> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .......... 0x020a> 0000 0000 0000 0000 0000
Do you notice a pattern with the first word in every sector? The filesystem structures always start with a magic number. In this case it is 'IN' for an Inode (hex 0x494e). At offset 4 in the sector are two bytes, which should always be 0x01 and 0x02. These are the inode version and the inode format. If this word isn't 0x0102, something is wrong. Check your last step and make sure you calculated this sector correctly, because nothing in this document can help you if it isn't 0x0102.
XFS inodes hold pointers to extents, which are contiguous runs of FSBs. At offset 0x40 in the inode is an 8-byte doubleword containing the number of FSBs tracked by this inode. At offset 0x48 is the number of extents to which these same FSBs belong. The length of the file tracked by this inode is an 8-byte doubleword at offset 0x38. The extent records begin at offset 0x64 in the inode, and number up to eight.
Each extent record has three parts: 8 bytes give the file position at the start of the extent, 6 bytes give the extent's address as an FSB number multiplied by 32, and the last 2 bytes give the length of the extent in FSBs.
Since the file position of each extent isn't that interesting, I have highlighted in red the last 8 bytes of the first extent record on the sample filesystem. The extent's address is given as 0x3860, an FSB number times 32. This extent is 0x01 FSB long.
XFS inodes are handles which point to files, and keep track of their extents. While this is true of "normal" files, like the passwd file we are trying to find, it is also true of directories, which XFS treats as a type of file. Directories have a special internal structure, organized as a B-tree so that they can efficiently contain millions of entries. When the B-tree is more than one FSB long, it begins with at least one header block, which contains information about the hashing algorithm that sorts file entries between the other blocks. The file entries themselves are in "leaf" directory nodes, which begin after the first block (if the directory is bigger than will fit in a single block). The root directory we are looking for is not, in all likelihood, very large, but it will span multiple blocks on a disk with a small FSBSIZE.
If we look at the extent records of the inode, we see the file blocks broken up into one or more extents, each with an address and a length. If we are looking for a file that has been recently modified, such as passwd in the /etc directory, it is more expedient to search beginning with the last extent, since that is where new files are often put. Likewise, if the directory is made up of multiple blocks, we can skip searching the first block, because it is only a header node, not a leaf node with file entries.
Take the 6-byte address of the extent and divide it by 32. Then use the same procedure outlined in § 5.5.2 to find the disk sector address of the extent.
Since the length of directory nodes is a full FSB, it isn't useful to read a single sector from the disk. So when using the readbuf command, enter the length of the extent where we had 1 before. The extent is as long as the number in the last 2 bytes of the record, times the FSBSIZE. When the very long output appears on the screen, use the Control-S key to pause output while you read it. Control-Q will resume output, but any other key should do so as well.
fx/debug> s 0x81e18 fx/debug> r 20 8 fx/debug> d s 0
fx/debug/dumpbuf: nshorts = (2058)
0x0000> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .............../.!
0x0012> 0000 0000 0000 0000 0000 FEEB 0000 002F 0121 .A................
0x0024> 0D41 0100 0198 0BA9 0D94 000B 0DB8 000F 0000 ................4w
0x0036> 002E 0FF7 0100 0000 172E 0FED 0200 0000 3477 ......7s..........
0x0048> 0EC8 0200 0000 3773 0ED2 0200 0018 B4EE 0EBD ....2.......zc....
0x005a> 0300 0019 32F6 0EDC 0300 0019 7A63 0EE7 0300 ..4........t......
0x006c> 001B 34E2 0EF2 0300 001B F874 0EFD 0300 001C ........6.......y.
0x007e> F0F4 0F08 0300 001D 36F0 0F13 0300 001D 79F2 .........)........
0x0090> 0F1E 0300 001D B0F2 0F29 0300 05DD F2E2 0FE1 .......4...x...@..
0x00a2> 0400 0E1C B7E3 0F34 0400 0E78 B4EE 0F40 0400 .}...........L....
0x00b4> 0E7D F0F0 0D88 0400 0EB4 E59D 0F4C 0800 0EBB ...s....cs.......:
0x00c6> B4F8 0E73 0400 12D7 6373 0FD0 0900 14C0 F63A ......q..m..01.(.\
0x00d8> 0FBE 0A00 1D9A 7185 0D6D 0600 3031 8228 0F5C ..8.......=|$..q..
0x00ea> 0D00 3894 A7C9 0DC7 0500 3D7C 24DF 0F71 0700 >z8.....>.wc....>.
0x00fc> 3E7A 3815 0EAF 0600 3E98 7763 0F80 0500 3EC6 Z6....L....f..M<..
0x010e> 5A36 0D9F 0800 4CB8 BAE1 0E66 0500 4D3C F5B4 ....NA#.....`z.z..
0x0120> 0DD4 0500 4E41 23E1 0DF7 0800 607A 9A7A 0E07 ..nj*y.>..z[......
0x0132> 0B00 6E6A 2A79 0E3E 0B00 7A5B B1DD 0E7F 0A00 ...u.........'...{
0x0144> 8DFC FA75 0E1A 0500 93AE ADD9 0E27 0F00 9C7B ..._...yDx.Q.....0
0x0156> F605 0D5F 0600 AE79 4478 0E51 0D00 B98F CF30 .....8.......8.2..
0x0168> 0DE1 0E00 CD38 99B4 0F8D 0500 CD38 9B32 0F9A .......{..........
0x017a> 0500 CDF8 F0EA 0D7B 0500 CDF9 F598 0EA1 0600 .y2`.A.......N....
0x018c> EC79 3260 0D41 0500 F292 F68A 0D4E 0900 FC87 ..................
0x019e> B5F3 0E91 0800 FEC9 F3B9 0FA7 0C00 0000 0000 ..................
[... very long output elided for brevity's sake ...]
0x0e6a> 0000 8D2E 5367 6972 6573 6F75 7263 6573 0000 .....jdebug......o 0x0e7c> 0000 0002 A86A 6465 6275 6700 0000 0000 056F >unix......!..varu 0x0e8e> 3E75 6E69 7800 0000 0000 0021 192E 7661 7275 pdate......!..prof 0x0ea0> 7064 6174 6500 0000 0000 0021 182E 7072 6F66 ile......!..login. 0x0eb2> 696C 6500 0000 0000 0021 172E 6C6F 6769 6E00 .....!..cshrc..... 0x0ec4> 0000 0000 0021 162E 6373 6872 6300 0000 0000 ..qbin.......'hw.. 0x0ed6> 001F 7162 696E 0000 0000 00C0 0327 6877 0000 ......ns.......&de 0x0ee8> 0000 00A0 0307 6E73 0000 0000 0020 0326 6465 v.......#etc...... 0x0efa> 7600 0000 0000 C003 2365 7463 0000 0000 00A0 ..lib........opt.. 0x0f0c> 0303 6C69 6200 0000 0000 2003 206F 7074 0000 .....hsat.....@4xt 0x0f1e> 0000 0000 1F68 7361 7400 0000 0000 4034 7874 mp.....`..usr..... 0x0f30> 6D70 0000 0000 0060 00BF 7573 7200 0000 0000 ...var........proc 0x0f42> C000 8276 6172 0000 0000 00A0 0082 7072 6F63 .....`..sbin.....@[truncated for brevity]
There's a magic number again, but this time it's at offset 0x8 in the block instead of 0. '0xFEEB' means this is a leaf directory node, which we want. By visually searching the screen for the letters "etc", we found the file entry for the /etc directory. Look on the line below for the ASCII code for the letters "etc", which is 0x657463. The 8 bytes preceding the name holds the number of this file's inode, which on the sample is 0xc00323.
By repeating the steps in § 5.5.1 to 5.5.3, we can find the inode for /etc. In this sample, it is an odd inum, so we should remember to use the last inode in the respective sector.
fx/debug> s 0x66e381
fx/debug> r 20 1
fx/debug> d s 0
fx/debug/dumpbuf: nshorts = (266) 0x0000> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ..INA............. 0x0012> 0000 494E 41ED 0101 0002 0000 0000 0000 0000 ................=. 0x0024> 0000 0002 0000 0000 0000 0000 0000 0000 3DCA G.3.F.:9...t!.:9.. 0x0036> 47B5 3305 4691 3A39 B0E0 0074 21AD 3A39 B0E0 .t!............... 0x0048> 0074 21AD 0000 0000 0000 001D 0000 0000 0000 .................. 0x005a> 0000 0000 0000 0000 0000 0000 0002 0000 0000 .................` 0x006c> 0000 0000 0000 0000 FFFF FFFF 0000 0000 0060 .B........^.libi4s 0x007e> 0342 0100 0000 0000 C5C4 5E0B 6C69 6269 3473 hl.sop...p...r...o 0x0090> 686C 2E73 6F70 9E88 0F70 A1A0 0F72 FCC4 0F6F ...o.|.o.<.o...s6. 0x00a2> DDE0 0F6F DE7C 0F6F DF3C 0F6F E0CC 0F73 3694 .s;h.s<..sA<.sF..s 0x00b4> 0F73 3B68 0F73 3CC0 0F73 413C 0F73 46E4 0F73 O..v...v...p.`.p.. 0x00c6> 4F00 0F76 C3DC 0F76 C410 0F70 9B60 0F70 9CFC .v...p.4.s...s.d.t 0x00d8> 0F76 C28C 0F70 A334 0F73 F3F0 0F73 FB64 0F74 .$.t...t...t...t.4 0x00ea> 0124 0F74 07C0 0F74 04B0 0F74 0380 0F74 0134 .s.l.s...t.P.s...t 0x00fc> 0F73 ED6C 0F73 EED4 0F74 0050 0F73 F8B4 0F74 ...p.dINA......... 0x010e> 0510 0F70 9064 494E 41ED 0102 0010 0000 0000 .................. 0x0120> 0000 0000 0000 0010 0000 0000 0000 0000 0000 ..=...:..r=..?.M.Z 0x0132> 0000 3DCF 0CFB 3AB6 1A72 3DCF 0C3F 184D 9F5A =..?.M.Z......0... 0x0144> 3DCF 0C3F 184D 9F5A 0000 0000 0000 3000 0000 .................. 0x0156> 0000 0000 0003 0000 0000 0000 0002 0000 0002 .................. 0x0168> 0000 0000 0000 0000 0000 0000 FFFF FFFF 0000 .................. 0x017a> 0000 0000 0000 0000 0180 0620 0001 0000 0000 .........`...o.P.o 0x018c> 0000 0200 0000 018B 1060 0002 0F6F 1C50 0F6F ...o...z...rn..r.T 0x019e> 1CB4 0F6F 11E8 0F7A 1CF0 0F72 6EDC 0F72 8E54 .r...z.0.r...r...r 0x01b0> 0F72 86A0 0F7A 1C30 0F72 8EF0 0F72 86D4 0F72 x..r...r.P.o...o.. 0x01c2> 7884 0F72 8C10 0F72 8750 0F6F 1BD8 0F6F 16F8 .z...r...z.8.rl..r 0x01d4> 0F7A 1BDC 0F72 900C 0F7A 1C38 0F72 6C84 0F72 n..z...rl..r.H.r.. 0x01e6> 6E04 0F7A 1CBC 0F72 6CEC 0F72 8448 0F72 84C0 .r...r...o...o...z 0x01f8> 0F72 84F8 0F72 8580 0F6F 1C18 0F6F 16C0 0F7A ...r.`.z.. 0x020a> 1A80 0F72 9060 0F7A 1AB8
This inode tracks a file 0x3000 bytes long, totalling 0x03 FSBs in 0x02 extents. The first extent record is 1 FSB long, which since this is a directory, means that it only holds a header node. So we proceed straight to the other extent, which must, by inference, contain the leaf nodes.
By repeating step § 5.6.1, we can read the /etc directory.fx/debug> s 0x69a608 fx/debug> r 20 16 fx/debug> d s 0
fx/debug/dumpbuf: nshorts = (2058)
0x0000> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ...............`..
0x0012> 0000 0000 0002 0000 0000 FEEB 0000 0060 028D .-................
0x0024> 0A2D 0100 0320 070D 0A8F 0014 0ABF 0013 0000 ................:t
0x0036> 002E 0FF7 0100 0000 172E 0FED 0200 0000 3A74 .......c..........
[... very, very long output elided ...]
0x0a32> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ..._.pcp.env...... 0x0a44> 0000 C35F 1C70 6370 2E65 6E76 0000 0000 00C0 ..opasswd......... 0x0a56> 0083 6F70 6173 7377 6400 0000 0000 0000 0000 ...........orbix_p 0x0a68> 0000 0000 0000 0000 C000 9A6F 7262 6978 5F70 rofile.........gfs 0x0a7a> 726F 6669 6C65 0000 0000 00C0 009E 2E67 6673 lock........resolv 0x0a8c> 6C6F 636B 0000 0000 00C0 0093 7265 736F 6C76 .conf............. 0x0a9e> 2E63 6F6E 6600 0000 0000 0000 0000 0000 0000 ..............uiop 0x0ab0> 0000 0000 0000 0000 0000 0000 C4E2 7569 6F70 erms.......mrmtab. 0x0ac2> 6572 6D73 0000 0000 00C5 886D 726D 7461 6200 .................. 0x0ad4> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .......ksnmpd.star 0x0ae6> 0000 0000 00C5 886B 736E 6D70 642E 7374 6172 t.......jpeer_nov. 0x0af8> 7400 0000 0000 C588 6A70 6565 725F 6E6F 7600 ......imtab......A 0x0b0a> 0000 0000 C588 696D 7461 6200 0000 0000 C441 Psavecore......R.r 0x0b1c> 5073 6176 6563 6F72 6500 0000 0000 C452 8972 eboot............. 0x0b2e> 6562 6F6F 7400 0000 0000 0000 0000 0000 0000 ..............TIME 0x0b40> 0000 0000 0000 0000 0000 00C0 0115 5449 4D45 ZONE......Raxfsres 0x0b52> 5A4F 4E45 0000 0000 00C4 5261 7866 7372 6573 tore......A1fstyp. 0x0b64> 746F 7265 0000 0000 00C4 4131 6673 7479 702E d......AIprtvtoc.. 0x0b76> 6400 0000 0000 C441 4970 7274 7674 6F63 0000 .....vbootptab.... 0x0b88> 0000 00C4 F676 626F 6F74 7074 6162 0000 0000 ..Rwmntproc......A 0x0b9a> 00C4 5277 6D6E 7470 726F 6300 0000 0000 C441 2ftimer........eth 0x0bac> 3266 7469 6D65 7200 0000 0000 C50F 0065 7468 ers......A+devnm.. 0x0bbe> 6572 7300 0000 0000 C441 2B64 6576 6E6D 0000 ....Rkdatemsk..... 0x0bd0> 0000 00C4 526B 6461 7465 6D73 6B00 0000 0000 .R.shutdown......R 0x0be2> C452 8B73 6875 7464 6F77 6E00 0000 0000 C452 .stdcshrc......AMr 0x0bf4> 9173 7464 6373 6872 6300 0000 0000 C441 4D72 estore......A8inst 0x0c06> 6573 746F 7265 0000 0000 00C4 4138 696E 7374 all......AOrrestor 0x0c18> 616C 6C00 0000 0000 C441 4F72 7265 7374 6F72 e......A/fsstat... 0x0c2a> 6500 0000 0000 C441 2F66 7373 7461 7400 0000 ...Rjcshrc......AT 0x0c3c> 0000 C452 6A63 7368 7263 0000 0000 00C4 4154 sysinfo......ABnch 0x0c4e> 7379 7369 6E66 6F00 0000 0000 C441 426E 6368 eck......R`xfsdump 0x0c60> 6563 6B00 0000 0000 C452 6078 6673 6475 6D70 .......Amiser_repa 0x0c72> 0000 0000 00C4 FC41 6D69 7365 725F 7265 7061 ck.conf.......Bmis 0x0c84> 636B 2E63 6F6E 6600 0000 0000 C4FC 426D 6973 er_system.conf.... 0x0c96> 6572 5F73 7973 7465 6D2E 636F 6E66 0000 0000 ..Rldevice.tab.... 0x0ca8> 00C4 526C 6465 7669 6365 2E74 6162 0000 0000 ..Rfbrutab.......@ 0x0cba> 00C4 5266 6272 7574 6162 0000 0000 00C4 FC40 miser_default.conf 0x0ccc> 6D69 7365 725F 6465 6661 756C 742E 636F 6E66 ......A5growfs.... 0x0cde> 0000 0000 00C4 4135 6772 6F77 6673 0000 0000 .`.Dcron.d......R. 0x0cf0> 0060 0344 6372 6F6E 2E64 0000 0000 00C4 5285 projid......A:labe 0x0d02> 7072 6F6A 6964 0000 0000 00C4 413A 6C61 6265 lit......AKrdump.. 0x0d14> 6C69 7400 0000 0000 C441 4B72 6475 6D70 0000 ....K.rc3.d....... 0x0d26> 0000 0080 4BE4 7263 332E 6400 0000 0000 A003 .rc2.d.......$rc0. 0x0d38> 0472 6332 2E64 0000 0000 00C0 0324 7263 302E d......R.passwd.sg 0x0d4a> 6400 0000 0000 C452 7F70 6173 7377 642E 7367 i.......Lsyslog.co 0x0d5c> 6900 0000 0000 C4FC 4C73 7973 6C6F 672E 636F nf........passwd.. 0x0d6e> 6E66 0000 0000 00C0 011B 7061 7373 7764 0000 ....AVuadmin...... 0x0d80> 0000 00C4 4156 7561 646D 696E 0000 0000 00C4 Rzmrouted.conf.... 0x0d92> 527A 6D72 6F75 7465 642E 636F 6E66 0000 0000 ..t.xtab......A^wt 0x0da4> 00C5 740F 7874 6162 0000 0000 00C4 415E 7774 mp......A\wall.... 0x0db6> 6D70 0000 0000 00C4 415C 7761 6C6C 0000 0000 ....uucp......AZut 0x0dc8> 00E0 0304 7575 6370 0000 0000 00C4 415A 7574 mp......ASswap....[output truncated]
A word of caution is due here. There are sometimes three different files under /etc which contain the word "passwd" on IRIX systems. "opasswd" is a backup of the passwd file, not the version in use. "passwd.sgi" is a file containing some extra information about users on a system, that controls how accounts are displayed by the graphical login program. Neither of these is what we want. Additionally, if in § 4 you determined that you needed to use the "/etc/shadow" file, you should search for that instead of "passwd".
Repeat the appropriate steps again, and read in the inode for the passwd file. Remember that hexadecimal digits B, D, and F are odd, when you determine which inode in the sector to use.
fx/debug> s 0x66e27d
fx/debug> r 20 1
fx/debug> d s 0
fx/debug/dumpbuf: nshorts = (266) 0x0000> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ..IN.............. 0x0012> 0000 494E 8100 0102 0001 0000 0000 0000 0000 ................9l 0x0024> 0000 0001 0000 0000 0000 0000 0000 0000 396C ....nK:M.E2..-:M.E 0x0036> F60C 07DE 6E4B 3A4D FF45 32C1 C02D 3A4D FF45 2..-.............. 0x0048> 32C1 C02D 0000 0000 0000 0000 0000 0000 0000 .................. 0x005a> 0000 0000 0000 0000 0000 0000 0002 0000 0000 .................. 0x006c> 0000 0000 0000 0001 FFFF FFFF 0000 0000 00A0 ..........A.visfly 0x007e> 011A 0200 0000 0000 CEF1 410E 7669 7366 6C79 info.rgb.......B.v 0x0090> 696E 666F 2E72 6762 0000 0000 00CE F142 0E76 isflylogo.xpm..... 0x00a2> 6973 666C 796C 6F67 6F2E 7870 6D00 0000 0000 .................. 0x00b4> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x00c6> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x00d8> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x00ea> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x00fc> 0000 0000 0000 0000 0000 0000 0000 0000 0000 ......IN.......... 0x010e> 0000 0000 0000 494E 81A4 0102 0001 0000 0000 .................. 0x0120> 0000 0000 0000 0001 0000 0000 0000 0000 0000 ..=..j.\..:M.q#... 0x0132> 0000 3DCF 0D6A 1C5C A51E 3A4D FF71 23DB F2D8 :M.q#..........^.. 0x0144> 3A4D FF71 23DB F2D8 0000 0000 0000 045E 0000 .................. 0x0156> 0000 0000 0001 0000 0000 0000 0001 0000 0002 .................. 0x0168> 0000 0000 0000 0000 0000 0010 FFFF FFFF 0000 .................. 0x017a> 0000 0000 0000 0000 0188 C600 0001 0000 0000 .................. 0x018c> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x019e> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01b0> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01c2> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01d4> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01e6> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .................. 0x01f8> 0000 0000 0000 0000 0000 0000 0000 0000 0000 .......... 0x020a> 0000 0000 0000 0000 0000
In this example, there is only one extent and one FSB for the file. By repeating the appropriate steps you can find the sector address of the passwd file. If there was more than one block, you would take the first one, since the root passwd is almost always the first line of the file.
View the first few lines of the file, and confirm that root does, in fact, have a password. (If it was blank, you just wasted a few hours. Don't ask me about it.) You are now going to change that password into something else, by writing over those characters. First make sure you have the sector number of the passwd file written down on paper.
Now quit and re-enter fx. Type Control-D or click the textport's Exit button, and start fx again. (Reread § 2 if you've forgotten how.) This time enable "Expert mode". (Either use flag -x or say "yes" when you're asked if you require all options.) Take the default on all the other questions.
fx> dfx/debug/editbuf: itype = (bytes) fx/debug/editbuf: buf offset = (0) 20 fx/debug/editbuf: value = (114) fx/debug/editbuf: value = (111) fx/debug/editbuf: value = (111) fx/debug/editbuf: value = (116) fx/debug/editbuf: value = (58)["root:" is decimal 114,111,111,116,58]
From here on the values are the ASCII codes of the 13-letter encrypted password. Just enter the new value at each prompt. The program understands hex notation with a leading "0x", and might also understand characters between single-quotes. But decimal codes work just as well. After you have entered all 13 letters of the new password, type Control-C on the next line. Or, type two dots on this line:
fx/debug/editbuf: value = (58) ..Verify what you just did by displaying it using dumpbuf. Then, if you're satisfied, commit the changes to disk.
fx/debug> w 20 1Now restart by hitting Control-D. Congratulations, you just did what most people still think is impossible.
It took me a while to write the program, but once it is typed in, it can be used to hack the disk with virtually no effort. Just find an HP48 calculator and define these variables:
The HP48 has three shift keys on the lower left edge. [Alpha], [Left], and [Right]. There are six soft-keys along the screen; when the Alpha annunciator is off, they refer to the commands in the screen menu. The HP48 has a very useful feature that allows the entry of binary numbers, including automatic binary arithmetic on such numbers. The syntax for binary numbers looks like # FEEDBABEh where the last letter shows the radix, either h, d, o, or b. The radix mode can be changed globally, which redisplays all the binary numbers in the new base, without changing their value.
Now finding the disk sector that holds a particular File-System Block (FSB) is as simple as entering the hex number using [Right]÷ [Alpha][Alpha] typing the number using the A-F softkeys for the A through F hex digits, and then [Alpha] again, then press the A softkey for the FSB command. The program does the step of dividing by 32 itself.
Similarly, the disk sector that holds a particular Inode can be found the same way, except hitting the B softkey for the INUM command. Remember if the Inum was even or odd! Even means it is first in its sector, odd means it is last. Hex digits B, D, and F are odd.
For readers who already know how to operate the calculator, here is the program.| BASE | Start sector of the XFS partition. |
| FSBSIZE | Size of a File-System Block in sectors. |
| AGSIZE | Size of an Allocation Group in FSBs. |
| AGMASK | AGSIZE B→R LOG 2 LOG / CEIL 2 SWAP ^ R→B |
| FLOOR2 | « DUP2 / DUP TYPE 10 ≠ « FLOOR » IFT DUP 4 ROLLD ∗ − » |
| FSB | « AGMASK FLOOR2 SWAP AGSIZE ∗ + FSBSIZE ∗ BASE + » |
| INUM | « FSBSIZE 2 ∗ FLOOR2 2 FLOOR2 DROP SWAP FSB + » |
| CST | { { "FSB" « 32 / FSB » } INUM } |
Greetz: All former employees of Silicon Graphics, especially the authors of xfs_db. rs, h3x, Impact, telemnstr, berkeley, SkyWriter, demize, tarachian, phuzzy, Farm_Guy, KMR. Keep the dream alive: keep on hacking the IRIS!