Unencrypt/Unscramble Existing Recordings

From DVRpedia

Jump to: navigation, search



Unfortunately, there is no simple way to unscramble encrypted recordings. But if you're comfortable telnetting into your Tivo, copying kernels around, etc., then it's certainly doable. Parts of this writeup will probably seem DirecTivo-centric, but then (A) this is a largely DTivo-centric forum, and (B) that's all I own so I tend to view the world in a DTivo-centric fashion. I'll upload a copy of this writeup to the files section.

Disclaimer and Credits

This is based on what has worked for other but there are no guarantees. You could destroy your precious recordings, make your Tivo inoperative, put several hundred clowns out of work, etc.

This writeup is based on info from Cheer at DDB. Credit for the tools belongs to alldeadhomiez, ScrambleThis, rc3105, HD TeAm, mrblack51, Jamie, and all of the other geniuses at DDB that that have made this process possible.

Required Downloads

Important Concepts to Understand

I. Tivo Kernel Version versus Linux Kernel Version versus Tivo Software Version

Version numbers on the Tivo can be very confusing. It's important to understand the distinctions. If you are using an HR10-250, then you're using either 3.1.5something or 6.3something. The "something" after 3.1.5 could be nothing, or a letter from a-f; after 6.3, it could be nothing or a letter from a-c. If you're using an SD DTivo, you're probably using 6.2 or 6.2a unless it's an R10. And so on.

These version numbers are Tivo Software version numbers. However, if you've hacked your Tivo, you've very likely installed a killhdinitrd-compromised kernel (assuming you didn't get a PROM mod). This kernel is probably either a 3.1.5 (no letter) kernel or a 7.2.2-oth-K1 kernel. These version numbers are Tivo Kernel version numbers. Note that the Tivo Kernel version DOES NOT HAVE TO MATCH the Tivo Software version. Why? Because what *really* matters is the Linux Kernel version.

The Linux Kernel version for 3.1.5x/5.x/6.x/7.x/8.x Tivo Software is 2.4.20. If you've still got a Tivo running 4.0, that was Linux Kernel version 2.4.18. SD DTivos running 3.1.x used Linux Kernel version 2.4.4. With a couple of minor exceptions, you can use a kernel with any Tivo Kernel version so long as it is the same Linux Kernel version. (The most notable exception, insofar as this forum is concerned, is that a 3.1.5 kernel will have issues on 6.3x if DHCP is used; I recommend a 7.2.2-oth-K1 kernel in those cases.)

Why is all of this important? Because:

  • You need to know what Tivo Kernel versions you can use
  • Setting up S2_Unscramble means using a custom kernel
  • Using a custom kernel means using a kernel module
  • Using kernel modules means that the kernel modules MUST match the Linux Kernel version

Killhdinitrd-compomised Kernels, Custom Kernels, Two-Card Monte, and the Chain of Trust

How do we compromise our Tivos in order to make modifications? Unless you have one of the so-called "S2.5" units (DirecTV R10, one of the TCD540xxx "night light" units, the S2DT) or the Series 3, you've probably got a killhdinitrd-compromised kernel installed. Well, what is that, exactly?

By default, Tivo kernels include an "initrd" that checks the filesystem for changes and wipes them out. (I am oversimplifying.) Tivo kernels are signed with a public/private key system. The public key is stored in the PROM of the unit itself. When the Tivo kernels are built by Tivo Inc., an SHA-1 hash is computed, signed with the private portion of the key, and added to the end of the kernel. As the Tivo boots, the PROM computes its own SHA-1 hash and, using the public portion of the key, compares it to the signed version in the kernel. If there is a mismatch, execution halts. (Again, somewhat oversimplifying.)

Killhdinitrd works because some very clever folks have found a way to disable the initrd in certain, specific kernels such that the kernel *still* passes the SHA-1 check. It's a fortuitous set of circumstances, and it's only possible in a few kernels: for Linux Kernel version 2.4.4, 3.1.U5 and 3.1.1c Tivo Kernel versions worked; for Linux Kernel version 2.4.18, 4.0.1a Tivo Kernel version worked, and for 2.4.20, 3.1.5 and 7.2.2-oth-K1 Tivo Kernel versions worked. So. Under normal circumstances you just replace your stock kernel with a kernel that matches your Linux Kernel version, and you're good to go.

Which is fine, until you want to run a custom kernel. Why? Because a custom kernel is, by definition, a kernel that has been built by someone other than Tivo. If Tivo didn't build it, then it won't be signed by Tivo's private key, and it will never pass the PROM check.

Enter monte. Monte allows us to chainload kernels -- in other words, we can configure the Tivo to boot using a normal, killhdinitrd-compromised kernel to pass the PROM checks, and then transfer control to a custom kernel. Monte was originally popular as a way to add LBA-48 (large hard drive) support to Tivos on older software versions and as part of older compromise schemes. (I actually use it on several of my Tivos to load a custom kernel tuned for performance so I get faster extractions.) But it will also allow us to load a custom kernel with the unscrambling stuff added.

Linux Kernel Versions and Monte: Two Ways to Go

So by now I expect you understand that we need to use monte to chainload a custom kernel. But how exactly do we go about that?

As confusing as all the versioning stuff is, I am about to make it worse. Now you have to keep track of the version of the kernel you are monte-ing FROM and the version of the kernel you are monte-ing TO. It's important to remember:

  • The kernel you are monte-ing FROM must be a killhdinitrd-compromised kernel
  • The kernel you are monte-ing TO must be one of the S2_Unscramble kernels

OK. So. One would assume that the FROM kernel should be the same as the one you're using now, right? Well...maybe not.

As I mention above, kernel module versions have to match the Linux Kernel version. In other words, modules are compiled for specific kernel versions. Why does this matter to us? Well...monte has been compiled for 2.4.4 and 2.4.20. (It's also been compiled for 2.4.18 but that's not really relevant right now.) Your FROM kernel must be of the same version. However...only the 2.4.4 version has proven to be completely stable. "Aha," I hear you say, and with good reason. Odds are, readers of this forum are running a 6.x-varient (or one of the 3.1.5 varients), all of which are Linux Kernel version 2.4.20.

So this leaves us with two choices, each of which has benefits and risks.

Choice 1: Use a 3.1.1c killhdinitrd-compromised kernel (which, if you will recall, is Linux Kernel version 2.4.4) as a FROM kernel, and use the 2.4.4 version of monte. Pros: this version of monte is stable and works without issue. Cons: you probably have to change your boot kernel, and if you make a mistake on the monte config, it's pretty much guaranteed the box won't boot. Plus, if either your kernel (boot) partition OR root partition extend beyond the 137GB (LBA-48) boundary, this may not boot successfully.

Choice 2: Use a 3.1.5 or 7.2.2-oth-K1 killhdinitrd-compromised kernel (either of which, if you will recall, is Linux Kernel version 2.4.20) as a FROM kernel, and use the 2.4.20 version of monte. Pros: you probably don't have to change your boot kernel, and in certain cases if you make a mistake you still might successfully boot. Cons: may not work, and if it doesn't, you're in a reboot loop until you pull the drive.

I'm not going to tell you which way to go. I've seen both work, and I've seen both blow up. So long as you are copacetic with pulling the drive in case it goes all to hell, I'd suggest starting with choice 2; it's simpler.

Unscrambling Methods

The S2_Unscrable process can support two methods of unscrambling content: extraction and in-place. I am not going to cover in-place unscrambling. Why? Because (A) it strikes me as more dangerous, since it involves actually writing to MFS, (B) it's more complicated, and this whole thing is complicated enough, and (C) I've never done it. :)

Extraction method: the S2_Unscrambles tarfile includes modified binaries for mfs_ftp and tserver (TyTool). They are old, however. The mfs_ftp binaries are the old mfs_export and mfs_tarstream-style binaries, and if you're using the latest unified mfs_* utils with mfs_uberexport, and if you've already got the latest patches on your mfs_ftp, then using these older binaries will be problematic.

So I recommend using the included tserver_mfs with TyTool. Note that you can use TyTool for extraction but then use tytompg or whatever tool you like for conversion. This modified tserver is an older version too, however, and does not have the integrated NowShowing code, so you need a standalone NowShowing.tcl file. There's one included in the "src" package for the latest mfs_* utils; I've included a link above.


You should have, on-hand, the following items:

  • Your killhdinitrd-compromised FROM kernel. This

may already be installed on your Tivo, but have it handy anyway in case something goes wrong. You can get these kernels from the $5 Enhanced LBA-48 Boot CD at dvrupgrade.com. If you have decided on choice 1, this should be the 2.4.4 kernel. For choice 2, use the 7.2.2-oth-K1 kernel (or if you have an older version of the CD, the 3.1.5 kernel).

  • The 3.1.5x S2_Unscramble kernel from the S2_Unscramble

kernels tarfile. The actual filename should be vmlinux.px.3.1.5x.

  • The file "monte" from the monte-mips tarfile.
  • The appropriate "kmonte.o" file from the monte-mips

tarfile. For choice 1, this should be the 2.4.4 version, and for choice 2, this should be the 2.4.20 version.

  • The "tserver_mfs" file from the S2_Unscramble


  • The "NowShowing.tcl" file from the mfs-utils "src"


Got everything together? Good, because now it's time to rock and roll.


Telnet into the Tivo. From a bash prompt, type "uname -r" and hit Enter. You'll get back the current Linux Kernel version, which really should be 2.4.20. If it's something else, then stop -- I've made the assumption that you're running a fairly recent version of the Tivo software. If you get something like 2.4.4 or 2.4.18, then you aren't. Send me a note so we can explore what you might have to do.

OK. Now that we know it's 2.4.20, type "bootpage -p /dev/hda" and hit Enter. One of the parameters you will see is "root=/dev/hda#" where "#" is either 4 or 7. Write this down -- this is your ROOT partition. Your BOOT (or kernel) partition will be one less -- so if your root partition is 4, your boot is 3; if your root partition is 7, your boot is 6. I will use the & symbol to represent this number, and the # symbol will continue to represent your active root partition. It's very important you not mix these numbers up, or Bad Things Will Happen.

Right. So, remount your root filesystem as read-write so you can make changes by typing "mount -o remount,rw /dev/hda#" (remembering to replace the # symbol with the number of your root partition, which, again, is either 4 or 7) and hitting Enter. Now type "mkdir /unscramble" and hit Enter; this will be our unscramble directory. (Clever, eh?)

Now use your favorite ftp program (I like FlashFXP on Windows and gFTP on Linux, but the choice is yours) and upload all of your ingredients to the Tivo in the /unscramble directory. This should go fast.

Now go back to your telnet session. Type "cd /unscramble" and hit Enter. Type "ls -l" and hit Enter and make sure all of your ingredients are there. If they are...sit back, and take a deep breath. We're about to change things.

IF and ONLY IF you have decided on choice 1:

  • Your 2.4.4 killhdinitrd-compromised kernel from

the LBA-48 Enhanced Boot CD is probably compressed with gzip. It's also probably named VMLINUX_.gz. If so, type "gzip -d VMLINUX_.gz" and hit Enter, and the file will be replaced with a file called VMLINUX_. (Adjust the command if the spelling or case is different -- remember, Linux is case sensitive.)

  • Copy this kernel to your boot (kernel) partition

by doing the following: "dd if=/unscramble/VMLINUX_ of=/dev/hda& bs=1024" and hitting Enter. Adjust the spelling of the kernel name if need be. Remember that & represents your boot partition number, and it should be either 3 or 6. If you're not sure, STOP RIGHT NOW BEFORE THINGS BREAK!

OK. The rest of the instructions are pretty much the same for either choice 1 or choice 2. The next dangerous step is modifying our rc.sysinit file. Normally veteran hackers will tell you to leave this file alone, right? Well, in this case, we really don't have a choice.

I prefer a method called the "rc.sysinit.real" approach. I didn't invent this method, but I've used it and it works very well.

Change to your rc.d directory: "cd /etc/rc.d" and hit Enter. Now, RENAME your rc.sysinit file with the following command: "mv /etc/rc.d/rc.sysinit /etc/rc.d/rc.sysinit.real" and hit Enter. Then, create a new rc.sysinit file with vi ("vi /etc/rc.d/rc.sysinit"). A blank file should load up. Press the i key to turn on insert mode, then paste in the following code (between the lines -- don't include the lines):

# bogus rc.sysinit - checks for monte 


bootparm=`/sbin/bootpage -p /dev/hda`

if [ "$sp" != "true" ]; then
echo "sp=\"$sp\" must be first pass, trying to run monte..."
/sbin/insmod -f /unscramble/kmonte.o
/unscramble/monte /unscramble/vmlinux.px.3.1.5x "$bootparm sp=true"

echo "sp=\"$sp\" must be second pass"
exec /etc/rc.d/rc.sysinit.real

echo "monte sysinit wrapper complete, you're on your own!"

Once that's pasted, hit ESC, then type ":wq" to write the file and quit vi. (You can use another editor if you prefer, of course.) Now, for verification purposes, type "cat /etc/rc.d/rc.sysinit" and hit Enter. It should look exactly as above. If it doesn't, fix it. (Extra spaces at the beginning of lines do not matter.)

Once it looks good, be sure to make it executable with the following command: "chmod 755 /etc/rc.d/rc.sysinit" and hit Enter.

What does all that do? See the Appendix.

OK. Now...take a deep breath. Double-check your work. And...reboot!

If the Tivo reboots successfully...congratulations. You've done the hard part. Telnet back in. Grab your remote, and play the first few seconds of a couple of your scrambled shows. Then, from your telnet session, type "tail -100 /var/log/kernel" and hit Enter. You should see several lines referring to the CSO keys. If so, congratulations again: you've done the hard part SUCCESSFULLY. Your custom kernel is running, and it's caching CSO keys from scrambled shows.

(Note that ciphercheck may give funny results now, because the kernel may confuse it.)

OK. Now the easy part. Fire up TyTool on your PC. You will need to make one minor change. Go to Options, then Preferences. Click on Server. Write down your current server execute string, so you can change it back when you're done. Change the server execute string to "/unscramble/tserver_mfs -s /unscramble/NowShowing.tcl" (without the quotes). Click Apply, then Close. Go to the Server menu, then Start Server. Click Refresh...and BAM, you should get your list of shows.

Click on one of your scrambled shows, and click Get. Once it's done downloading...it's unscrambled. :) Process or edit as you would any other extracted video.

Undoing Everything

So you've unscrambled all of your shows and you're ready to remove all of this. Good for you.

IF and ONLY IF you decided on choice 1 (3.1.1c killhdinitrd-compromised kernel and the 2.4.4 version of monte), you need to have a 2.4.20-type killhdinitrd-compromised kernel (either 3.1.5 or 7.2.2-oth-K1).

For choice 1 users ONLY:

  • Telnet into your Tivo
  • Remount the root filesystem as read-write

("mount -o remount,rw /" and Enter)

  • Change to the /unscramble directory ("cd

/unscramble" and Enter)

  • Remove the old 2.4.4 kernel that you put

there during installation ("rm VMLINUX_" and Enter; adjust for spelling/case)

  • Using ftp, upload the 2.4.20-type kernel

to /unscramble

  • Uncompress it ("gzip -d VMLINUX_.gz")
  • Copy the 2.4.20-type kernel to your boot


dd if=/unscramble/VMLINUX_ of=/dev/hda& bs=1024

and hit Enter

For everyone:

  • Telnet into your Tivo (if you haven't already)
  • Remount the root filesystem as read-write (if

you haven't already) ("mount -o remount,rw /" and Enter)

  • Rename the "fake" rc.sysinit file to something

else ("mv /etc/rc.d/rc.sysinit /etc/rc.d/rc.sysinit.monte")

  • Put the real rc.sysinit back where it belongs

("mv /etc/rc.d/rc.sysinit.real /etc/rc.d/rc.sysinit")

  • Reboot

Assuming a successful reboot, telnet back in and clean up the excess stuff:

  • Remount as read-write ("mount -o remount,rw /")
  • Remove the bogus sysinit

("rm /etc/rc.d/rc.sysinit.monte")

  • Remove the /unscramble folder ("rm -r /unscramble")
  • Remount as read-only ("mount -o remount,ro /")

You're done!

Appendix (a.k.a what is that rc.sysinit crap doing)

So let's look at the bogus rc.sysinit to understand what it is doing, shall we? Below is another copy of it, but with my notes added, prefixed by [CDH])>. Remember, this file will get executed TWICE -- once during initial boot, and once as the chainloaded kernel boots.

#!/bin/bash [CDH])> Like any good shell script, we
need this line first

# bogus rc.sysinit - checks for monte [CDH])> a comment


the path above is temporary and will be overridden by the "real" rc.sysinit, as well as your .author file, if any. This is likely excessive, but better too many entries than not enough.

bootparm=`/sbin/bootpage -p /dev/hda`

The bootparm statement simply creates a variable called (you guessed it) bootparm, and sets it equal to the results returned by the bootpage command. So, at this point in the script, bootparm is identical to your bootpage. You'll see why we need this in a moment.

if [ "$sp" != "true" ]; then

sp is another variable and, at the first runthru, isn't set to anything, so it's NOT true and the first section of this "if" is executed

echo "sp=\"$sp\" must be first pass, trying to run monte..."

This is just an entry for the console/log.

/sbin/insmod -f /unscramble/kmonte.o

This loads the kmonte.o kernel module for monte, which makes all the magic happen. :)

/unscramble/monte /unscramble/vmlinux.px.3.1.5x "$bootparm sp=true"

[CDH])> This executes monte, and chainloads the kernel. Note the bit at the end in quotes. This passes kernel parameters. The $bootparm variable passes the bootpage (see above), but we've added the sp variable and set it to true. When the SECOND pass of this file occurs, sp will be true and the other part of the "if" will be run. At this point, execution of this script halts as the new kernel loads and the boot process restarts.


OK. After the chainload happens, this file will be run again. The difference is, we set the sp variable to be true. So when the "if" condition is hit, the first choice will be bypassed and the "else" condition will be run.

echo "sp=\"$sp\" must be second pass"

An entry for the console/log

exec /etc/rc.d/rc.sysinit.real

Since it's the second pass, we know we don't need to run monte again, so now we run the "real" rc.sysinit file, and boot continues as normal.


echo "monte sysinit wrapper complete, you're on your own!"


Suggested reading (all at ddb -- note that many of these threads are old and will have outdated information regarding exploits, but the fundamental concepts are still worth understanding):

Understanding the "chain of trust" on Series 2/Series2.5/Series 3 Tivos, by alldeadhomiez: [1]

killhdinitrd support thread: [2]

The S2_Unscramble thread: [3]

The original monte thread: [4]

The updated (ish) monte thread: [5]

Original How-to Post on Yahoo! Group HD-TiVo group: [6]

Personal tools