PDA

View Full Version : Disassembling and understanding MIPS code (split from: tivoapp patches)



SteveT
09-29-2004, 12:46 PM
Here are all of the patches for 3.1.1d. Credit goes to AhoyMatey for the scramble/encryption patch. The rest I found myself. All of these have been tested.



Fix Offset Original New
scramble 00632fec 0320f809 3c020000
30 seconds 00315564 10400024 14400068
backdoors 003206a4 02802821 24050001
dir sort 00270378 a22000e1 a22200e1


I found out the hard way that the 00632fec offset for scramble is not correct. I went a-searching for the origin and found it (see below). Note that AhoyMatey states 0xA32fec in the text, but then uses 0x632fec in his example code (dec 6500332). The 0xa32fec (dec 10694636) worked for me.


I have not installed 3.1.1d, nor tested this patch. Looking at the tivoapp for 3.1.1d, the line to modify is at 0xa32fec. To disable the tystream encryption for a series 2 dtivo:


echo -ne "\x3C\x02\x00\x00" | dd conv=notrunc of=tivoapp bs=1 seek=6500332

mrblack51
09-29-2004, 01:03 PM
I found out the hard way that the 00632fec offset for scramble is not correct. I went a-searching for the origin and found it (see below). Note that AhoyMatey states 0xA32fec in the text, but then uses 0x632fec in his example code (dec 6500332). The 0xa32fec (dec 10694636) worked for me.

the reason that the mistake is easy is because file offsets are 0x400000 different from the offsets you see in disassembly, due to the way the file gets loaded.

falcontx
09-30-2004, 11:42 AM
I found out the hard way that the 00632fec offset for scramble is not correct. I went a-searching for the origin and found it (see below). Note that AhoyMatey states 0xA32fec in the text, but then uses 0x632fec in his example code (dec 6500332). The 0xa32fec (dec 10694636) worked for me.
That's odd. If I go to 0xa32fec in my tivoapp, the original code is "53 74 72 69" which is "Stri" in ASCII, which happens to be a part of a string ("String() zero length string, err = %s..."). So I deduced that this was not the proper location.

On the other hand, when I go to 0x632fec, I find the original code to be "03 20 f8 09", which is exactly what it should be. And changing it as AhoyMatey instructed got rid of the scrambling.

AhoyMatey
09-30-2004, 02:18 PM
That's odd. If I go to 0xa32fec in my tivoapp, the original code is "53 74 72 69" which is "Stri" in ASCII, which happens to be a part of a string ("String() zero length string, err = %s..."). So I deduced that this was not the proper location.

On the other hand, when I go to 0x632fec, I find the original code to be "03 20 f8 09", which is exactly what it should be. And changing it as AhoyMatey instructed got rid of the scrambling.
MrBlack51 stated it correctly. The offset in the file is 0x632fec. Once tivoapp is loaded, the offset is at 0xa32fec (relatively, I guess). I assume SteveT is modifying tivoapp while it's resident with kmem or something like that...

Disassembling with objdump provides the loaded address of 0xa32fec.

SteveT
10-01-2004, 09:18 AM
MrBlack51 stated it correctly. The offset in the file is 0x632fec. Once tivoapp is loaded, the offset is at 0xa32fec (relatively, I guess). I assume SteveT is modifying tivoapp while it's resident with kmem or something like that...

Disassembling with objdump provides the loaded address of 0xa32fec. :( Sorry for the unneeded confusion. I'm certainly no expert at doing this, so I'm thinking maybe I changed both places? I'll take a peek next week (out of town until then) and see what I did (to satisfy my own curiousity).

Now, is there any way to remove (or move) the last several posts from this excellent thread?

Lost Dog
10-02-2004, 10:58 AM
All these 4.x 'New Values' are wrong. They should be 10440068

I suspect, but I'm not sure that the 3.x ones are wrong too.

NutKase

Hi NutKase,

I'm running 4.0 and for the 30 second skip using 14400068. It's been running this way for several weeks with no issues. If others are using 10440068 maybe it works both ways?

NutKase
10-02-2004, 12:27 PM
Hi NutKase,

I'm running 4.0 and for the 30 second skip using 14400068. It's been running this way for several weeks with no issues. If others are using 10440068 maybe it works both ways?

You're right, I've just confirmed that either 14400068 OR 10440068 will work.

Double tested.

I thought I'd created the 14400068 as a typo which was used to update the patches list and I was trying to clear that up. It doesn't matter now.

Hey! We've learned something today :).

Since the 14400068 'New Value' is most accepted let's delete our posts so the issue is dead.

[EDIT]Leaving this post for background.


NutKase

alldeadhomiez
10-02-2004, 12:44 PM
You're right, I've just confirmed that either 14400068 OR 10440068 will work.

Will work, or happens to work now?

Where does the value in $a0 come from?


0: 14400068 bnez v0,0x1a4
4: 10440068 beq v0,a0,0x1a8

NutKase
10-02-2004, 12:51 PM
Will work, or happens to work now?

Where does the value in $a0 come from?


0: 14400068 bnez v0,0x1a4
4: 10440068 beq v0,a0,0x1a8

I guess 'happens' to work would be the correct answer. I'm not sure what you mean by 'now', it's been working for 6 months since I typo'd it.

I think you're trying to teach me something again. :) I just don't get it.

Just so you'll know, I've done most of the porting with only hex editing and don't know much about reading assembly. I can read jumps, jne, and know when values are put in variables, etc but I haven't learned bnez, beq and get lost. I just found a thread on mips assembly. In other words, I think I'm capable but need a pointer.

I think I haven't persued my assembly learning as much as hex/tcl is that I'm not sure I have 'good' tools yet. What do you use for disassembly?

You did that pretty fast. So far, I've been using tmesis' mipsdisassembler04 script and then XyByre's viewmips to depict it in a gui... BUT, It's tedious and slow.

I've also used IDA but I'm not sure I have the right symbols or whatever for tivo mips.

Can we move the last few posts and continue this?

[EDIT]Thanks, alldeadhomiez, for starting a new thread

NutKase

alldeadhomiez
10-02-2004, 03:14 PM
Just so you'll know, I've done most of the porting with only hex editing and don't know much about reading assembly. I can read jumps, jne, and know when values are put in variables, etc but I haven't learned bnez, beq and get lost.

beq takes the branch if the two arguments are equal. bne takes the branch if the two arguments are not equal.

Many MIPS instructions are "shortened" versions of a few primitives. For example, let's look at 14400068 (bnez v0,0x68). In binary it looks like:


3 2 1 0
1 3 5 7
000101 00010 00000 0000000001101000
opcode sssss ttttt offset

sssss and ttttt refer to registers, so it literally translates into: bne $2, $0, 0x68. That is to say, the branch is taken if $2 ($v0) is not $0 ($0/$zero is hard-wired to zero on MIPS). Thus, bnez means "branch if not equal to zero." By changing the instruction to compare against $a0, we introduce an unknown quantity - $a0 was never originally part of the decision.

How do you calculate the destination address from the offset? Add $pc + 4 (the length of the instruction) + offset*4. In the example posted above, 4+0x68*4 = 0x1a4. The least significant two bits are not encoded because every instruction must be word-aligned.

Things to play with:

What happens when you change the instruction to 10000068? Or 00000000? Or ffffffff? MN's patch inverts the behavior so that the 30 second skip is the default, instead of skip-to-end. What effect does the SPS30 sequence have when you force the branch to always be taken? What about when you skip it entirely?

For more information:

General information on porting patches (http://www.dealdatabase.com/forum/showthread.php?p=172548#post172548)
MIPS instruction encoding / reference (http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html)
Overview of assembly language and intro to MIPS (http://www.cs.umd.edu/class/spring2003/cmsc311/Notes/Overall/instruction.html)
MIPS ABI (http://www.caldera.com/developers/devspecs/mipsabi.pdf) (describes higher level constructs, calling conventions, etc.)

Many "intro to asm" courses at universities use the MIPS architecture, so if you don't like the materials I found, google around to look for one that's better suited to your needs.

alldeadhomiez
10-02-2004, 03:39 PM
Here are a few options for disassembling MIPS code:

To use objdump from GNU binutils:

Build a MIPS toolchain: build_mips_x_compiler.sh from http://tivoutils.sourceforge.net/ . Or, download the binary version from the same place.

Or build it on cygwin (http://www.dealdatabase.com/forum/showthread.php?t=27280) so it runs under Windows.

Or, on Debian, apt-get install binutils-multiarch to install a version of objdump that can disassemble code for ~12 different architectures.

Once you have objdump working, you can invoke it in a few different ways:

objdump -xd /path/to/binary will disassemble the code sections to standard out. It does not resolve or compensate for the $gp-relative offsets seen in relocatable MIPS code (consult the ABI for more information on this).

The tmesis postprocessor (http://www.dealdatabase.com/forum/showthread.php?t=27553) runs objdump against a binary, adds strings, and generally cleans up the listing to make it more human-readable. I use a variant of the tmesis code to disassemble MIPS ELF objects.

To disassemble fragments of code that are not in an ELF binary, such as the PROM or individual instructions (as seen above), try something like this (thanks for the hints MN):

echo -ne "\x14\x40\x00\x68\x10\x44\x00\x68" > foo.bin
mips-TiVo-linux-objdump -b binary -EB -m mips -D --adjust-vma=0x0 foo.bin

Other options:

Find a copy of IDA Pro Advanced (http://www.datarescue.com/idabase/). I've tried 4.30 and wasn't too impressed with the MIPS support. I have heard that it is better in 4.6+.

Try to get REC (http://www.backerstreet.com/rec/rec.htm) to work. I did not have any luck with this application. Note that this is a decompiler, not a disassembler.

Try some other disassemblers. (http://directory.google.com/Top/Computers/Programming/Disassemblers/) Who knows, maybe somebody wrote one that doesn't suck.

Or, write your own disassembler or objdump postprocessor. MIPS is simple... almost too simple. Keeping track of a few dozen registers in your head can get a little hairy. Tools could be written to make the code and data easier to follow.

alldeadhomiez
10-02-2004, 03:59 PM
General information on porting patches (http://www.dealdatabase.com/forum/showthread.php?p=172548#post172548)

Recall that this post referred to PPC, not MIPS. The concepts are the same, but a few things are different:

MIPS has a branch delay slot; PPC does not.

The .text/.rodata VMA offset in MIPS is typically 0x400000, not 0x1800000 as in PPC:


LOAD off 0x00000000 vaddr 0x00400000 paddr 0x00400000 align 2**12
filesz 0x00de2040 memsz 0x00de2040 flags r-x
LOAD off 0x00de3000 vaddr 0x10000000 paddr 0x10000000 align 2**12
filesz 0x0007ea6c memsz 0x0008ffd8 flags rw-

Obviously it will not be a constant for .data, since the length of the first section varies across executables.

OT: I was recently asked about self-modifying code in tivoapp. As you can see from objdump -x, the pages containing the .text and .rodata segments normally have r-x permissions. You can flip a bit in the ELF program header to change it to rwx. The structures you need to understand can be found in /usr/include/elf.h .

NutKase
10-02-2004, 05:49 PM
alldeadhomiez,

I can't thank you enough for your last three posts.

This will keep me busy for a while. Thank you again for a road ahead, now I have something to tackle.

Although, this thread is in development, my plan is to post my experiences as I climb the learning curve, and ask for help as needed :)...

...which may be frequently. What I won't do is ask just for answers and I won't ask w/out trying to learn from available sources first.

Thanks again,


NutKase

PS. I wish we had an Ollydebug for ELF! :)

NutKase
10-03-2004, 03:46 PM
The tmesis postprocessor (http://www.dealdatabase.com/forum/showthread.php?t=27553) runs objdump against a binary, adds strings, and generally cleans up the listing to make it more human-readable. I use a variant of the tmesis code to disassemble MIPS ELF objects.

I have a linux cross-compiler and one on Cygwin which I use just as much. I'm using tmesis mips.dasm.pl version 0.4.2 as updated by DrNull.

Do you plan on posting your 'variants' on tmesis' code for others? /me wonders what nice changes might've occurred :).


To disassemble fragments of code that are not in an ELF binary...

echo -ne "\x14\x40\x00\x68\x10\x44\x00\x68" > foo.bin
mips-TiVo-linux-objdump -b binary -EB -m mips -D --adjust-vma=0x0 foo.bin

Jeez! My learning curve was straight up yesterday. I missed this line and hex patched my tivoapp 4 times with the different values, then, disassembled each separately to compare and find the differences :)! DUH!


NutKase

NutKase
10-03-2004, 04:17 PM
For example, let's look at 14400068 (bnez v0,0x68). In binary it looks like:


3 2 1 0
1 3 5 7
000101 00010 00000 0000000001101000
opcode sssss ttttt offset

Haven't figured out where the bolded items come from.


so it literally translates into: bne $2, $0, 0x68. That is to say, the branch is taken if $2 ($v0) is not $0 ($0/$zero is hard-wired to zero on MIPS).

It took me a while to realize that $2 is 00010 in binary but then it clicked.


1440 0 0 68
bnez 2 0 0x068


Still not sure how $2 became == $v0? [EDIT]The registers are numbered $0 to $31, and by MIPS Registers and Usage Conventions (http://www.cis.unisa.edu.au/howto/spim/quickref.html) coding standards, the third one ($2) is $v0.


The least significant two bits are not encoded because every instruction must be word-aligned.

Light not on yet :) Still reading.


How do you calculate the destination address from the offset? Add $pc + 4 (the length of the instruction) + offset*4. In the example posted above, 4+0x68*4 = 0x1a4.

So $pc is program counter. Got it.


tivoapp patch location is 0x0051cc90+0x00400000=0x0091cc90
(0x00400000 is for the entry point offset)

0x0091cc90 is the disassembled vma address
0x0091cc90+0x1a4=0x0091ce34

0x0091ce34 is the 'branch to' location.


Things to play with:

What happens when you change the instruction to 10000068?

Or 00000000? Or ffffffff?


tivoapp.401b2.original.10400068.S (135195491 bytes)
---
< 0x0091cc90 beqz v0,0x0091ce34 # Branch if equal to zero, Unpatched it branches.
0x0091cc94 addiu v0,s2,299
0x0091cc98 sltiu v0,v0,599


tivoapp.401b2.30patched.14400068.S (135195493 bytes)
---
< 0x0091cc90 bnez v0,0x0091ce34 # Branch if not equal to zero. Properly patched it doesn't branch.
< 0x0091cc94 addiu v0,s2,299
< 0x0091cc98 sltiu v0,v0,599


tivoapp.401b2.10000068.S (135195488 bytes)
---
> 0x0091cc90 b 0x0091ce34 # Branch (Always)????? Skips to end, just like the unpatched
> 0x0091cc94 addiu v0,s2,299
> 0x0091cc98]sltiu v0,v0,599 # Still researching this... might be the end of a branch.


tivoapp.401b2.ffffffff.S (135195419 bytes)
---
< 0x0091cc90 sd ra,-1(ra) # Reboots tivo, Illegal instruction, Signal 4
0x0091cc94 addiu v0,s2,299
0x0091cc98 sltiu v0,v0,599


tivoapp.401b2.00000000.S (135195478 bytes)
---
< 0x0091cc90 nop # Nop, Operates just like a properly patched tivoapp, i.e. BRANCH!
0x0091cc94 addiu v0,s2,299
0x0091cc98 sltiu v0,v0,599


# Branches to here
0x0091ce34]lw a0,196(s0)

The question I have is, that if there are several ways to patch the app to branch, why the worry over 144? I guess to keep good coding standards :).


NutKase

NutKase
10-03-2004, 10:34 PM
Sorry, but, I'm still learning. :)

What I still have no idea about is 'how' did someone find out that 'this' particular command 'should' branch to enable 30-second skip?

Maybe we're just trying to 'opposite' the bne or bez's then boot and see what happens?

Anyway, I just thought I'd put some of the process up for others. I'll add notes as my mind develops.


NutKase

mrblack51
10-04-2004, 11:54 AM
the correlation of $2 to $v0 or whatnot is based on mips standards. mips registers are general purpose, and are numbered $0 through $31 (forgot if there are more for this system). however, to aid programmers and to develop conventions, there is a standard name mapping for various registers. $0 is $zero, a special register which equates similar to /dev/null in that it always has zeros in it. other registers get assigned names like $gp, $a0, $a1, $v0, etc. by assigning names, it makes it easier to program by hand, and it allows for better standardization - such as all $aX registers are for return values(?).

as for why the patch methods matter? well, it depends on what functionality you want. flipping the check from beq to bnez means that you could use the remote backdoor code to toggle it, but its turned on by default. using a branch or a nop (to skip the branch) would leave it on permenantly. in addition, there are often numerous ways to do the same thing, such as set $v0 to zero or 1 or whatnot (a li instruction, or an add)

edit: note, my register nemonics may be off, its been a while since i looked at the standards and such, but the idea is there and accurate.

NutKase
10-04-2004, 12:06 PM
the correlation of $2 to $v0 or whatnot is based on mips standards. mips registers are general purpose, and are numbered $0 through $31 (forgot if there are more for this system).

Thanks for the information. I did find out about the 32 registers 0-31, when ffffffff seg faulted my tivo :)



Oct 3 21:14:05 (none) kernel: [myworld:151] Illegal instruction ffffffff at 0091cc90 ra=0091cc8c
Oct 3 21:14:05 (none) kernel: Tmk Fatal Error: Thread myworld <151> died due to signal 4
Oct 3 21:14:05 (none) kernel: pc 0x91cc94 status 0x8001bc13 cause 0x000028 bva 0x7f6072fc hi 00000000
lo 00000000

# These seem to be the content of the registers 0-31 for a total of 32 registers ?
Oct 3 21:14:05 (none) kernel: R00 0x00000000 R01 0x10088244 R02 0x00000000 R03 0x00000002
Oct 3 21:14:05 (none) kernel: R04 0x7f56fe1c R05 0x7f56fe1c R06 0x0000002b R07 0x011bffb0
Oct 3 21:14:05 (none) kernel: R08 0x00000001 R09 0x00000000 R10 0x00000000 R11 0x000003e8
Oct 3 21:14:05 (none) kernel: R12 0x00000000 R13 0xfa000000 R14 0x0002e85f R15 0x0a000000
Oct 3 21:14:05 (none) kernel: R16 0x7f595720 R17 0x7f595720 R18 0x00000064 R19 0x00000064
Oct 3 21:14:05 (none) kernel: R20 0x00000000 R21 0x00000001 R22 0x7f5ab1b0 R23 0x7f5b9e90
Oct 3 21:14:05 (none) kernel: R24 0x00000000 R25 0x01005974 R26 0x00000001 R27 0x00000000
Oct 3 21:14:05 (none) kernel: R28 0x1005eb60 R29 0x7fff63c0 R30 0x00000001 R31 0x0091cc8c
Oct 3 21:14:05 (none) kernel: F00 0x41731b99cccccccd F02 0x000000000131b99c
Oct 3 21:14:05 (none) kernel: F04 0xffffffffffffffff F06 0xffffffffffffffff
Oct 3 21:14:05 (none) kernel: F08 0xffffffffffffffff F10 0xffffffffffffffff
Oct 3 21:14:05 (none) kernel: F12 0xffffffffffffffff F14 0xffffffffffffffff
Oct 3 21:14:05 (none) kernel: F16 0xffffffffffffffff F18 0xffffffffffffffff
Oct 3 21:14:05 (none) kernel: F20 0xffffffffffffffff F22 0xffffffffffffffff
Oct 3 21:14:05 (none) kernel: F24 0xffffffffffffffff F26 0xffffffffffffffff
Oct 3 21:14:05 (none) kernel: F28 0xffffffffffffffff F30 0xffffffffffffffff
Oct 3 21:14:05 (none) kernel: csr 0x001004 eir 0x005410



as for why the patch methods matter? well, it depends on what functionality you want. flipping the check from beq to bnez means that you could use the remote backdoor code to toggle it, but its turned on by default. using a branch or a nop (to skip the branch) would leave it on permenantly. in addition, there are often numerous ways to do the same thing, such as set $v0 to zero or 1 or whatnot (a li instruction, or an add)

Uh-Oh... I think you answered one of my alldeadhomiez challenge questions for me :(... I was still contemplating the 'if we branch, regardless of the method, we're in the same boat' issue and totally forgot about the 'remote' capability. :)

Thanks for the info... more reading to follow... At least I'm not talking to myself anymore :).


NutKase

mrblack51
10-04-2004, 12:50 PM
Uh-Oh... I think you answered one of my alldeadhomiez challenge questions for me :(... I was still contemplating the 'if we branch, regardless of the method, we're in the same boat' issue and totally forgot about the 'remote' capability. :)

Thanks for the info... more reading to follow... At least I'm not talking to myself anymore :).


NutKase

heres a challenge question of my own: can you come up with at least 3 different ways to set a given register, such as $v0, to zero using only one instruction?

hint: this is useful when bypassing functions...challenge question 2 - why is it useful?

NutKase
10-04-2004, 04:54 PM
heres a challenge question of my own: can you come up with at least 3 different ways to set a given register, such as $v0, to zero using only one instruction?

hint: this is useful when bypassing functions...challenge question 2 - why is it useful?

That generated some interesting research :). Still absorbing. Here's a stab at it. Don't give me the answer but you might let me know if I'm way off base or if one answer is so wrong that it shows I have no concept or totally don't understand a command. That'll show me where to study.



1. sub $v0, $s3, $s3 #Subtract $s3 from itself and store in $v0...=0
2. add $v0, $zero, $zero #Add 0 to 0 and store in $v0
3. sgt $v0, $s3, $s3 #If $s3 is greater than itself (not) set 1
otherwise set 0. $v0 becomes 0.
4. slt $v0, $s3, $s3 #If $s3 is less than itself (not) set 1
otherwise set 0. $v0 becomes 0.



Also, do you mean "Why is it useful to bypass functions?"?

[EDIT]Number #2 is under review

[EDIT]Removed/Replaced #2. Early attempt was :). - "lw $v0, $0 #load the hardwired zero from $0 into $v0??


NutKase

nova1
10-04-2004, 11:51 PM
The load instruction is for loading from memory and not used for moving contents from register to register. The mnemonic for $0 is $zero.

You might also consider downloading the MIPS simulator from http://www.cs.wisc.edu/~larus/spim.html.

NutKase
10-05-2004, 02:47 AM
The load instruction is for loading from memory and not used for moving contents from register to register. The mnemonic for $0 is $zero.

You might also consider downloading the MIPS simulator from http://www.cs.wisc.edu/~larus/spim.html.

Thanks, I was questioning my understanding of that anyway.

Also, the spim threads were one of the sources I was using, and a pretty explanatory one at that. I wasn't sure if the mips processor version mattered/changed that much. I'll look into it.

...Side note, pretty sharp for a 'first' post.:)


NutKase

mrblack51
10-05-2004, 04:19 PM
Also, do you mean "Why is it useful to bypass functions?"?

no, i mean how is the above technique useful in bypassing functions. take a look at what some of the super patch does...specifically, instrucitons that are replaced one after the other (ie: XXXXXX4, XXXXXX8). think about common functions that we wish to bypass, and what they might look like, how they might work.

NutKase
10-05-2004, 05:08 PM
I've got SPIM working. It seems to help. At least I can write a program and wonder why it doesn't work :).

I've compiled 2 MIPS assembly programs: 'Hello World' and the 'Numbers' example from Getting Started with MIPS Assembly Programming (http://www.cis.unisa.edu.au/howto/spim/assemblerguide.html).

Note that the final examples contain errors.


Hello World - mesg vs msg
Numbers - In if and else: used jal print with no function included
In print function example: called jal printf vs jal print
Manually printed in test (not an error)


I've included my working file for others to play with. I tested out the different ways of printing, i.e. using the function or commenting it out and using what I call the manual way. There's probably a programmer's term for it :). But I"m not a programmer... yet!

BTW, I'm having a blast but now I must go to work. :(

[EDIT]The print function was printing all the messages and I didn't notice. I've got it working 100% now but I left the print function and my thought processes in for others to see how it reacted.


NutKase
Numbers_NutKase.txt (4.6 KB, 4 views)

NutKase
10-10-2004, 08:38 PM
I've been at this a couple of days...

I'm learning and now have a suite of good reference material that I refer to as I try to understand what's going on.

My goal now is to...

take a look at what some of the super patch does...specifically, instructions that are replaced one after the other (ie: XXXXXX4, XXXXXX8). think about common functions that we wish to bypass, and what they might look like, how they might work.

...as mrblack51 suggested.

I don't think I'm there or even close. I'm still laying the ground work for a place from which to start.

I'm tired... just posting this to see if anyone wants it or can tell me if I'm on the right track as far as the 'ground work' is concerned.

The file is my rambling through the superpatch-4all 4.0 array, converting decimal to hex to vma addresses, then breaking the hex dump in each location into assembly instructions.

I'm trying to use my brain as a disassembler for a few commands. I think I'm going to stop this and just compare the unpatched vs patched disassembly's and try to figure out WHY they knew the patch location was there in the first place.

If anyone sees see logic errors, or any other thing I'm boneheading, feel free to comment.


NutKase

mrblack51
10-11-2004, 11:28 AM
think about these two things:
what a basic function looks like throughout its lifecycle
branch delay slots

using the info about the patches along with a disassembled copy of tivoapp may help

NutKase
10-11-2004, 12:05 PM
think about these two things:
what a basic function looks like throughout its lifecycle
branch delay slots

using the info about the patches along with a disassembled copy of tivoapp may help

I got the first two but, by info about the patches, do mean my dissecting of the commands? I have patched and unpatched tivoapp dissassemblies and, I'm staring hard... :)


NutKase

mrblack51
10-11-2004, 04:39 PM
I got the first two, but by info about the patches do mean my dissecting of the commands? I have patched and unpatched tivoapp dissassemblies I'm staring hard...


NutKase

um, let me put it to you this way...maybe it will help.

if you dont want a function to do something, you can either prevent it from running in the first place, or you can stop it as soon as it starts (make it do nothing). if you understand how to do both those things, you will be well on your way.

a good thing to try would be to write a simple program:

#include <stdio.h>

void foo(int *y)
{
*y = 5;
}

int main()
{
int x = 0;

foo(&x);
printf("x = %d", x);
}

compile it for mips, then see if you can make it print "x = 0" using the two methods i mention. that should give you some insight.

rpl
10-11-2004, 07:11 PM
Things to play with:

What happens when you change the instruction to 10000068? Or 00000000? Or ffffffff? Sorry to take this thread back a little bit, but looking at the HMO patch I see it takes 000003e9 and changes it to ffffffff. This isn't an instruction but ...data? Why does the patch needs to change this part of the file and what does the ffffffff signify?

mrblack51
10-11-2004, 07:13 PM
Sorry to take this thread back a little bit, but looking at the HMO patch I see it takes 000003e9 and changes it to ffffffff. This isn't an instruction but ...data? Why does the patch needs to change this part of the file and what does the ffffffff signify?

you are very correct, that change is definitely in the data area, not an instruction change. ffffffff is not a valid instruction anyway last i checked.

NutKase
10-17-2004, 01:48 PM
if you dont want a function to do something, you can either prevent it from running in the first place, or you can stop it as soon as it starts (make it do nothing). if you understand how to do both those things, you will be well on your way.

<snip>

compile it for mips, then see if you can make it print "x = 0" using the two methods i mention. that should give you some insight.

Ok, I've spent a little time with this, compiled the program, disassembled it and I'm stopping the jump to foo so this should 'prevent a function from running in the first place' right?

# x=5 when jump to foo completes.
# 0x00400834 nop
# x=0 when you nop it.

Note my disassembly output looks strange after the patch but it works. I'll look into it later.

I guess I'm learning but there's much still to learn. Anyone who knows this stuff should feel free to jump in. I'll take hits from all comers :).


NutKase

mrblack51
10-17-2004, 03:19 PM
Ok, I've spent a little time with this, compiled the program, disassembled it and I'm stopping the jump to foo so this should 'prevent a function from running in the first place' right?

# x=5 when jump to foo completes.
# 00400834 nop
# x=0 when you nop it.

Note my disassembly output looks strange after the patch but it works. I'll look into it later.

I guess I'm learning but there's much still to learn. Anyone who knows this stuff should feel free to jump in. I'll take hits from all comers :).


NutKase

yup, that looks like it. its nice that the compiler you are using utilizes gp based addressing, since thats what tivoapp uses. once you figure out the other method, the follow up is what are some situations where you would want to use one method over the other.

NutKase
10-17-2004, 08:46 PM
yup, that looks like it. its nice that the compiler you are using utilizes gp based addressing, since thats what tivoapp uses. once you figure out the other method, the follow up is what are some situations where you would want to use one method over the other.

Well, it's good to know that I'm on the right track. The hunt (for knowledge :)) is on!...

Thanks for your time and guidance. It's slow going as I have to be a husband every now and then too :).

As fas as compiler, I assume you were meaning 'cross'? I'm just using the standard gcc crosscompiler to compile your .c program for mips, or are you implying that I have/or should have, a mips assembly compiler.

IOW, I was learning how to write straight assembly programs to compile to mips... then you gave me the C program (I don't know much C) to crosscompile to mips, and that's what I did.

The rest was just converting VMA to decimal for the patch location I wanted to change, then figuring out what I wanted to change the assembly instructions to and converting them to binary then hex.

That trail soon bumps up against my knowledge wall, as you can see by my "everything below this line is junk, ignore" comment :).

For instance, the last 16 binary places can be several things:

address, values or ?...

Still learning, and I haven't had this much fun in a while.


NutKase

mrblack51
10-18-2004, 07:06 PM
As fas as compiler, I assume you were meaning 'cross'? I'm just using the standard gcc crosscompiler to compile your .c program for mips, or are you implying that I have/or should have, a mips assembly compiler.

IOW, I was learning how to write straight assembly programs to compile to mips... then you gave me the C program (I don't know much C) to crosscompile to mips, and that's what I did.

you did what you were supposed to do. I was just somewhat surprised and pleased to see that even on a small program like that, gp based addressing is used. thats really good, because that is what tivoapp uses.


That trail soon bumps up against my knowledge wall, as you can see by my "everything below this line is junk, ignore" comment :).

For instance, the last 16 binary places can be several things:

address, values or ?...

im not sure i follow. are you refering to your initial disassembly of the superpatch stuff? remember that there are 3 instruction formats for mips, not just one. jumps are i think 8 bits for the instruction and 24 for the jump destination.

NutKase
10-19-2004, 09:05 PM
im not sure i follow. are you refering to your initial disassembly of the superpatch stuff? remember that there are 3 instruction formats for mips, not just one. jumps are i think 8 bits for the instruction and 24 for the jump destination.

Oh, I see.

[EDIT] - Hit enter by accident before I finished my post. Correcting now...

1. Register Encoding - not completed yet.

2. Immediate Encoding - 6 bits for opcode, 5 bits for first register, 5 bits for 2nd register, and 16 bits for 'immediate' data
(wondering how it's interpreted differently for different instructions)

3. Jump Encoding - 6 bits for opcode, 26 bits for jump destination




...reading fast (http://www.student.cs.uwaterloo.ca/~isg/res/mips/opcodes) but learning slow :).


NutKase

Vegas
03-15-2005, 07:47 PM
um, let me put it to you this way...maybe it will help.

if you dont want a function to do something, you can either prevent it from running in the first place, or you can stop it as soon as it starts (make it do nothing). if you understand how to do both those things, you will be well on your way.



Ok, I've been at this for a week now and I feel like I'm learning, (been reading the referance material from this thread. Also found a good introduction to mips assembly here (http://chortle.ccsu.edu/AssemblyTutorial/TutorialContents.html). They give a lot of code examples and the Spim simulator is integrated into the early lessons.) so I'm goiing to take a stab at this.

I understand preventing the function from running as shown in OPTION 1 in the code below. I'm a little unclear on "stoping it as soon as it starts". It would seem that OPTION 2a would accomplish this by returning, but I see no advantage over OPTION 1.

OPTION 2b however would allow us to control what the function does with x. I can see advantages here over OPTION 1. ie: Lets say foo were to set values for x and y but we are only interested in influencing x. We would have to let the function run to set or return a value for y.

OPTION 2c is just another way to set x to 0.

I still have a lot to learn, just hope I'm on the right track here... comments welcome.


#
# ---- Procedure: foo ----
#
00400840]lui gp,0xfc0 # gp = 0x0fc00000
00400844 addiu gp,gp,30736 # gp = 0x0fc07810

### OPTION 2a Return (do nothing)
### Change 0x00400840 to jr ra
### Change 0x00400844 to nop
### Patch the binary by changing 0x00400840 to 03e00008
### and 0x00400844 to 00000000



00400848 addu gp,gp,t9 # gp = 0x10008050
0040084c addiu sp,sp,-16
00400850 sw gp,0(sp) # gp = 0x10008050
00400854 sw s8,12(sp)
00400858 sw gp,8(sp) # gp = 0x10008050
0040085c move s8,sp
00400860 sw a0,16(s8)
00400864 li v1,5 # v1 = 0x00000005

### OPTION 2b change foo to set x to whatever we want.
### Change the instruction at 0x00400864 to li v1,0 (0 could be
### whatever value you want x to be.)
### Patch the binary by changeing 0x00000864 to 34030000

00400868 lw v0,16(s8)
0040086c nop
00400870 sw v1,0(v0) # v1 = 0x00000005

### OPTION 2c
### OR to make x=0 you could change 0x00400870 to sw zero,0(v0)
### Patch the binary by changeing 0x00000870 to ac400000


00400874 move sp,s8
00400878 lw s8,12(sp)
0040087c jr ra
00400880 addiu sp,sp,16
#
# ---- Procedure: main ----
#
00400884]lui gp,0xfc0 # gp = 0x0fc00000
00400888 addiu gp,gp,30668 # gp = 0x0fc077cc
0040088c addu gp,gp,t9 # gp = 0x10008050
00400890 addiu sp,sp,-48
00400894 sw gp,16(sp) # gp = 0x10008050
00400898 sw ra,40(sp)
0040089c sw s8,36(sp)
004008a0 sw gp,32(sp) # gp = 0x10008050
004008a4 move s8,sp
004008a8 sw zero,24(s8)
004008ac addiu a0,s8,24
004008b0 lw t9,-32720(gp) # __gmon_start__
004008b4 nop
004008b8 jalr t9 # __gmon_start__

### OPTION 1 Skip the jump to foo and leave x set to 0
### Change 0x004008b8 to nop
### Patch the binary by changeing 0x000008b8 to 00000000


004008bc nop
004008c0 lw gp,16(s8) # gp = 0x10008050
004008c4 nop
004008c8 lw a0,-32744(gp) # 0x00400000
004008cc nop

Vegas

Vegas
03-15-2005, 08:32 PM
Been trying to figure this out for a while and am at a loss.

In the code below the pointer to the start of the function foo is stored at memory location 0x10000080 at run time. However I can't determine what value is stored there just by looking at the disassembly dump. The only way I could find the value was to load the binary file into a hex editer and read the value. Feel like I'm missing something here. Can this be determined just from the dump?

Also notice that in the post from Nutkase his disassembly shows the value for t9 and referances it as foo. Where as mine referances __gmon_start__.

I've tried many differant options with gcc but always get the same referance here. Could be a differance in our tool chains or a gcc option I'm missing???

Not really looking for direct answers here.... but a push in the right direction would help.


#
# ---- Procedure: foo ----
#
00400840]lui gp,0xfc0 # gp = 0x0fc00000
00400844 addiu gp,gp,30736 # gp = 0x0fc07810
00400848 addu gp,gp,t9 # gp = 0x10008050
0040084c addiu sp,sp,-16
00400850 sw gp,0(sp) # gp = 0x10008050
00400854 sw s8,12(sp)
00400858 sw gp,8(sp) # gp = 0x10008050
0040085c move s8,sp
00400860 sw a0,16(s8)
00400864 li v1,5 # v1 = 0x00000005
00400868 lw v0,16(s8)
0040086c nop
00400870 sw v1,0(v0) # v1 = 0x00000005
00400874 move sp,s8
00400878 lw s8,12(sp)
0040087c jr ra
00400880 addiu sp,sp,16
#
# ---- Procedure: main ----
#
00400884]lui gp,0xfc0 # gp = 0x0fc00000
00400888 addiu gp,gp,30668 # gp = 0x0fc077cc
0040088c addu gp,gp,t9 # gp = 0x10008050
00400890 addiu sp,sp,-48
00400894 sw gp,16(sp) # gp = 0x10008050
00400898 sw ra,40(sp)
0040089c sw s8,36(sp)
004008a0 sw gp,32(sp) # gp = 0x10008050
004008a4 move s8,sp
004008a8 sw zero,24(s8)
004008ac addiu a0,s8,24
--->004008b0 lw t9,-32720(gp) # __gmon_start__<---
### Here t9 is loaded with whats stored at 0x10000080
004008b4 nop
--->004008b8 jalr t9 # __gmon_start__<---
### Here t9 = 0x00400840


004008bc nop
004008c0 lw gp,16(s8) # gp = 0x10008050
004008c4 nop
004008c8 lw a0,-32744(gp) # 0x00400000
004008cc nop

Attaching the full output of the dissambly below.

Thanks

Vegas

mrblack51
03-15-2005, 10:00 PM
Been trying to figure this out for a while and am at a loss.

In the code below the pointer to the start of the function foo is stored at memory location 0x10000080 at run time. However I can't determine what value is stored there just by looking at the disassembly dump. The only way I could find the value was to load the binary file into a hex editer and read the value. Feel like I'm missing something here. Can this be determined just from the dump?

Thanks

Vegas

as far as i know, the only way to see the value is to look at the binary. I have generally been using both IDA Pro Advanced as well as these dumps to disassemble stuff. The main benefit of IDA is that you can cross reference data and instructions and such.

of course, you could edit the analysis script to dump in some data from the binary by having it calculate the offset and such.

mrblack51
03-15-2005, 10:05 PM
Ok, I've been at this for a week now and I feel like I'm learning, (been reading the referance material from this thread. Also found a good introduction to mips assembly here (http://chortle.ccsu.edu/AssemblyTutorial/TutorialContents.html). They give a lot of code examples and the Spim simulator is integrated into the early lessons.) so I'm goiing to take a stab at this.

I understand preventing the function from running as shown in OPTION 1 in the code below. I'm a little unclear on "stoping it as soon as it starts". It would seem that OPTION 2a would accomplish this by returning, but I see no advantage over OPTION 1.

OPTION 2b however would allow us to control what the function does with x. I can see advantages here over OPTION 1. ie: Lets say foo were to set values for x and y but we are only interested in influencing x. We would have to let the function run to set or return a value for y.

OPTION 2c is just another way to set x to 0.

I still have a lot to learn, just hope I'm on the right track here... comments welcome.


#
# ---- Procedure: foo ----
#
00400840]lui gp,0xfc0 # gp = 0x0fc00000
00400844 addiu gp,gp,30736 # gp = 0x0fc07810

### OPTION 2a Return (do nothing)
### Change 0x00400840 to jr ra
### Change 0x00400844 to nop
### Patch the binary by changing 0x00400840 to 03e00008
### and 0x00400844 to 00000000



00400848 addu gp,gp,t9 # gp = 0x10008050
0040084c addiu sp,sp,-16
00400850 sw gp,0(sp) # gp = 0x10008050
00400854 sw s8,12(sp)
00400858 sw gp,8(sp) # gp = 0x10008050
0040085c move s8,sp
00400860 sw a0,16(s8)
00400864 li v1,5 # v1 = 0x00000005

### OPTION 2b change foo to set x to whatever we want.
### Change the instruction at 0x00400864 to li v1,0 (0 could be
### whatever value you want x to be.)
### Patch the binary by changeing 0x00000864 to 34030000

00400868 lw v0,16(s8)
0040086c nop
00400870 sw v1,0(v0) # v1 = 0x00000005

### OPTION 2c
### OR to make x=0 you could change 0x00400870 to sw zero,0(v0)
### Patch the binary by changeing 0x00000870 to ac400000


00400874 move sp,s8
00400878 lw s8,12(sp)
0040087c jr ra
00400880 addiu sp,sp,16
#
# ---- Procedure: main ----
#
00400884]lui gp,0xfc0 # gp = 0x0fc00000
00400888 addiu gp,gp,30668 # gp = 0x0fc077cc
0040088c addu gp,gp,t9 # gp = 0x10008050
00400890 addiu sp,sp,-48
00400894 sw gp,16(sp) # gp = 0x10008050
00400898 sw ra,40(sp)
0040089c sw s8,36(sp)
004008a0 sw gp,32(sp) # gp = 0x10008050
004008a4 move s8,sp
004008a8 sw zero,24(s8)
004008ac addiu a0,s8,24
004008b0 lw t9,-32720(gp) # __gmon_start__
004008b4 nop
004008b8 jalr t9 # __gmon_start__

### OPTION 1 Skip the jump to foo and leave x set to 0
### Change 0x004008b8 to nop
### Patch the binary by changeing 0x000008b8 to 00000000


004008bc nop
004008c0 lw gp,16(s8) # gp = 0x10008050
004008c4 nop
004008c8 lw a0,-32744(gp) # 0x00400000
004008cc nop

Vegas

you got it for the most part. Basically, its an issue of what actual functionality needs to be bypassed. In the case of the blowfish bypass in the superpatch, it worked for enabling mrv stuff, but at the cost of disabling decryption of other certificates (such as guide data stuff). Then a patch was released which was a "selective bypass". since that particular functionality was needed in some places but not others, instead of returning right away, it was better to patch each call of the function that needed to be bypassed

SR712
04-03-2005, 01:02 PM
I have been following this thread with interest. I hope to someday offset the amount of help I have taken from these talented programmers with some contributions of my own. I have been able to disassemble mips apps, and think I have a good, though elementary, grasp of machine code. What I can't seem to get together is how do you determine where in the code the routine you are looking for is found? Do you do a memory dump, and backtrack from an address that has values that you are looking for? Its not like you can set breakpoints or anything. Pray tell, how do I get over this hurdle? Any help would be appreciated.

mrblack51
04-03-2005, 02:58 PM
I have been following this thread with interest. I hope to someday offset the amount of help I have taken from these talented programmers with some contributions of my own. I have been able to disassemble mips apps, and think I have a good, though elementary, grasp of machine code. What I can't seem to get together is how do you determine where in the code the routine you are looking for is found? Do you do a memory dump, and backtrack from an address that has values that you are looking for? Its not like you can set breakpoints or anything. Pray tell, how do I get over this hurdle? Any help would be appreciated.

Easy ways to start are to go from a known function and then trace where it is called or what calls it. For example, in the brf investigation, you can figure out what funciton parses brf files by looking for all the string instances of a "whatever.brf" in tivoapp. from there, you will see that numerous places call the same function after loading that type of string's address.

also, if any sort of debug message or log trace is generated for the functionality, that can assist as well.

justmike
04-03-2005, 06:16 PM
What I can't seem to get together is how do you determine where in the code the routine you are looking for is found?

Well I remember when I was playing around with disassembly in the old C64 days that it really helped to understand the physical archecture of the machine as well. Example if the serial port was mapped into a specific memory range and you were wanting to bypass code that checked for a dongle then that little piece of information was valuable.

It also help to study what those who when before you did which I think is some of the clues that Mr. Black has been dropping in this thread as well.

Compairing the disassembly of the stock code with the disassembly of someones patch will often add more clues.

Hope some of this helps :cool:

Justin Thyme
04-09-2005, 04:03 PM
Boy does that date you Mike.

Don Lancaster's articles on hacking Applewriter on the Apple ][ was where I first learned some of these skills. As I recall, his motivation was to hook up his laserwriter to work properly with applewriter.

One trick for ID'ing routines was to redirect mysterious calls to a routine that did a known thing. I used to beep the apple ][ speaker, because I couldn't muck up the screen with trace messages. In the case of hacking a printer, I blinked the panel lights (after following traces on the board back to an controller chip that basically mapped to IO addresses as Mike described.

I shoved the original call or jump address on the stack, then would blink a number of times indicating where it was, then it would wait for a front panel button press to continue. If I pressed a different button, it would disable the break at that location and simply use the pushed address for the call or the jump. That saved me from having to burn tons of roms. I could litter the code with my generalized "prospecting" routine, and after disabling all the uninteresting / high frequency calls, I could get to serious experients to id under what conditions the routines in question would fire.

Very late in the project I understood how to pass data back through the parallel port, and I had very robust trace statements posted to my screen.

With the internet link, you may be able to do something very robust early, but they are complicated and could induce such radical changes of machine state that they would interfere with your observations.

I don't know how much of this you can apply to Tivo- all this stuff you guys are doing looks like a blast and I really hope I can get some time to mess around with it, but so far I have no practical experience with it.

There are tons of techniques you can use. There are a lot of good tutors here. Aren't any of these reverse engineering techiniques written down anywhere in some concentrated form? [Edit- I looked around, and A. Huang discussed some really cool techniques such as use of FPGA's to hack the XBox. http://www.amazon.com/exec/obidos/tg/detail/-/1593270291/qid=1113106202/sr=8-1/ref=pd_csp_1/002-6220315-0057657?v=glance&s=books&n=507846 Luckily, Tivo has not yet gone to the lengths that MS went to in order to protect protect it from hacking. It is a futile exercize.]

Understanding how to figure out relationships between what the circuit board tells you and what the code tells you may be pretty hard now especially with all the multilayer boards where you can't see all the traces, and custom chips with no data on them. But the internet as a research and collaborative tool I think more than equalizes the proposition so I figure you guys have it a lot easier than it was in the early days. [Then again maybe not- it really surprized me there was only a promo sheet on the web about the 2.5's BCM7317- no pinout diagrams, descriptions of how to use the lines and their timings etc. I suppose they think that will make them more secure. Whatever.]

I have read these threads for a little while and have not heard any mention of what we used to call hardware debuggers, but there used to be these useful interface boards that firmware design engineers would use that had a connector that would piggeyback the cpu. Those were super powerful, because you could do a hardware pause of the cpu when an address or data value came acrosss. You could see on an external PC where in the code it was. The really fancy ones I used to drool over when visiting engineering labs had the ability to muck with everything- change registers, memory locations, whatever you liked, and then when you let go of the cpu, it would continue along its merry way. Jeez, with one of those, I could have learned in an afternoon what it took me weeks to painstakingly figure out by patching code and burning roms.

But that would probably be a nasty hack job (use extreme care with your jumper wire lengths, solder tidiness- signal crosstalk can generate intermittent and behavior that will drive you nuts because if you don't catch it fast you probably will think it is your sw hacks doing it). Maybe this is totally useless information these days- I have no idea what products might be out there now that could be reused for the broadcom or whatever cpu you are talking to. Certainly it would have to be a contemporary board so maybe expensive- the interface has to be able to handle the operation speed of the subject cpu.

Such an approach might have broader uses than as an investigation tool. I can imagine some applications where you could have a PC collaborate with the Tivo in order to add mind blowing functionality. It definately would be a high risk and expensive hardware hack though.

[No one responded so I took a look around and am adding this extended Edit- It looks like the BCM7317 chips have a robust architecture for hardware debugging. Really very convenient. Lauterbach sells a hardware debugger using this connection plus support for embedded linux and Bcm7317, but it probably costs a megabuck. I would think a cheap probe with tools could probably be constructed. The BCM7317 clearly states it supports EJTAG, so this looks like a worthy avenue for investigation. Not only for investigating the system, but adding a an additional CPU to augment the TIVO as I speculated on above. A description of EJTAG support for hardware debugging may be found at http://www.mips.com/content/PressRoom/TechLibrary/WhitePapers/ejtag

S2.0's look like the better choice since the NEC cpu is better documented. It's hardware debugging support uses N-wire, not EJtag. I found information by searching for "N-wire" in volume 2 of the manual (http://www.necelam.com/docs/files/1375_V2.pdf) The N-wire connection is straightforward (is there a diagnostic connection point on the S2.0 board like CN16 on the S2.5? Much harder part (at least for me) would be the bus probe. The pro units with these are way too pricey, but fortunately Huang stated how to do this part in one of his MIT XBox hack papers, describing a cheap bus interogator using an FPGA. So maybe there reason to believe that a hardware breakpoint trigger could be constructed for the $50 he spent.

AlldeadHomiez's observation in his interesting writeup on S2.5 architecture was tthat EJTAG type exploits have limitted utility without a mechanism of persistence. That is so. Does the mechanism of persistence being a second CPU mean that most of the hacks are impossible/ impractical to load on the fly? Does adding an XP cpu beg the question why not just get an MC if you want connectivity/flexibility. I wouldn't be at all surprized that what I'm exploring is impractical since all the real experience I have to contribute at this point is my ancient knowlege of hardware debuggers and assembler language patches to reverse engineered source code. Now you guys may wave me off as a grandpa babbling irrelevant stuff about carburetors in a world of fuel injection but I do know this- A lowend XP/Tivo married system would deliver the reliability of a Tivo with the extensibility and connectivity the XP for a lower price than a Media center. An external cpu can test Tivo configuration and intelligently install appropriate patches in an automated way as well as restore state prior to the patch without making those nasty stupid erors that Novices/ and even experienced hackers can oftentimes make at the worst time.

Besides, maybe what many would regard an unwholesome union takes Tivo quickly to a position it ought to explore. There is an argument that dual processors (with trusted/untrusted hw&sw) is the way Tivo Corp. needs to move. After all, that's the direction the cell phone architecture has gone.]

-JT

santa8claws
04-20-2005, 01:25 AM
Hi, I was trying to find the NoCSO patch for my Toshiba DVDR running 5.4.1-01-2-565 (which there doesn't seem to be too many users here)
my original tivoapp (18,145,600 bytes) MD5 is: b138346af4a80a564405d7b8e4d77602

So in this thread, I figured that 5.2.2 might be worth as a starting point
http://www.dealdatabase.com/forum/showthread.php?t=33946&page=3&pp=15

It just so happens that at the given address (VMA: ee9190) is the right 'jalr' opcode, but patching my tivoapp didn't disable encryption:


0x00ee915c 0x8fbc0018 lw gp,24(sp) # gp = 0x10072070
0x00ee9160 0x02602021 move a0,s3
0x00ee9164 0xa3b20084 sb s2,132(sp) # s2 = 0x00000001
0x00ee9168 0x3c190000 lui t9,0x0 # t9 = 0x00000000
0x00ee916c 0x033cc821 addu t9,t9,gp # t9 = 0x10072070
0x00ee9170 0x8f39c0a8 lw t9,-16216(t9) # LUAL t9 = [0x1006e118] = 0x0045876c
0x00ee9174 0x0320f809 jalr t9 # 0x0045876C
0x00ee9178 0x00000000 nop
0x00ee917c 0x8fbc0018 lw gp,24(sp) # gp = 0x10072070
0x00ee9180 0x27a40088 addiu a0,sp,136
0x00ee9184 0x3c190000 lui t9,0x0 # t9 = 0x00000000
0x00ee9188 0x033cc821 addu t9,t9,gp # t9 = 0x10072070
0x00ee918c 0x8f39c290 lw t9,-15728(t9) # LUAL t9 = [0x1006e300] = 0x00460700
0x00ee9190 0x0320f809 jalr t9 # 0x00460700
0x00ee9194 0x00000000 nop
0x00ee9198 0x8fbc0018 lw gp,24(sp) # gp = 0x10072070
0x00ee919c 0x5440ffd0 bnezl v0,0x00ee90e0
0x00ee91a0 0x8ec40004 lw a0,4(s6)
0x00ee91a4 0x1000ff4c b 0x00ee8ed8
0x00ee91a8 0x8fa20060 lw v0,96(sp)
0x00ee91ac 0x8fa40070 lw a0,112(sp)
0x00ee91b0 0x3c190000 lui t9,0x0 # t9 = 0x00000000
0x00ee91b4 0x033cc821 addu t9,t9,gp # t9 = 0x10072070
0x00ee91b8 0x8f39fb48 lw t9,-1208(t9) # LUAL t9 = [0x10071bb8] = 0x0090aaa4
0x00ee91bc 0x0320f809 jalr t9 # 0x0090AAA4

From AllDeadHomiez hex dump of the 5.1.1b version area for the NoCSO patch (file address 0989c00) in: http://www.dealdatabase.com/forum/showpost.php?p=178198&postcount=245


0000000000d89be0 <.data>:
d89be0: 8f39631c lw t9,25372(t9)
d89be4: 0320f809 jalr t9
d89be8: 00000000 nop
d89bec: 8fbc0010 lw gp,16(sp)
d89bf0: ae500000 sw s0,0(s2)
d89bf4: 8f998254 lw t9,-32172(gp)
d89bf8: 00000000 nop
d89bfc: 273996d8 addiu t9,t9,-26920
d89c00: 0320f809 jalr t9
d89c04: 00000000 nop
d89c08: 8fbc0010 lw gp,16(sp)
d89c0c: 10400018 beqz v0,0xd89c70
d89c10: 02003021 move a2,s0
d89c14: 8e84000c lw a0,12(s4)
d89c18: 8e250000 lw a1,0(s1)
d89c1c: 3c190001 lui t9,0x1
d89c20: 033cc821 addu t9,t9,gp
d89c24: 8f397708 lw t9,30472(t9)
d89c28: 0320f809 jalr t9
d89c2c: 00000000 nop


Also looking at older versions, there seems to be some connection to the code block "CreateClipKey", so I disassembled that area (VMA: 5d84b4) in my tivoapp looking for some hints:


0x005d8628 0x8f3984d4 lw t9,-31532(t9) # LUAL t9 = [0x1006a544] = 0x0040d348
0x005d862c 0x0320f809 jalr t9 # 0x0040D348
0x005d8630 0x00000000 nop
0x005d8634 0x8fbc0010 lw gp,16(sp) # gp = 0x10072070
0x005d8638 0xae300000 sw s0,0(s1)
0x005d863c 0x8f9981c8 lw t9,-32312(gp) # printf
0x005d8640 0x00000000 nop
0x005d8644 0x27393348 addiu t9,t9,13128 # LA t9 = 0x00410690
0x005d8648 0x0320f809 jalr t9 # 0x00410690
0x005d864c 0x00000000 nop
0x005d8650 0x8fbc0010 lw gp,16(sp) # gp = 0x10072070
0x005d8654 0x10400018 beqz v0,0x005d86b8
0x005d8658 0x02003021 move a2,s0
0x005d865c 0x8e84000c lw a0,12(s4)
0x005d8660 0x8e450000 lw a1,0(s2)
0x005d8664 0x3c190001 lui t9,0x1 # t9 = 0x00010000
0x005d8668 0x033cc821 addu t9,t9,gp # t9 = 0x10082070
0x005d866c 0x8f39afd0 lw t9,-20528(t9) # LUAL t9 = [0x1007d040] = 0x005c3830
0x005d8670 0x0320f809 jalr t9 # 0x005C3830
0x005d8674 0x00000000 nop
0x005d8678 0x8fbc0010 lw gp,16(sp) # gp = 0x10072070
0x005d867c 0x8f8481d0 lw a0,-32304(gp) # 0x01460000
0x005d8680 0x00000000 nop
#
# LA Possible reference to string: ""
#
0x005d8684 0x24841110 addiu a0,a0,4368 # LA a0 = 0x01461110
0x005d8688 0x8f8781d0 lw a3,-32304(gp) # 0x01460000
0x005d868c 0x00000000 nop
#
# LA Possible reference to string: "CreateClipKey"
#
0x005d8690 0x24e71100 addiu a3,a3,4352 # LA a3 = 0x01461100
0x005d8694 0x00802821 move a1,a0
0x005d8698 0x10400007 beqz v0,0x005d86b8


So I figured this was the right patch for opcode at VMA 0x005d8648 above (with decimal file offset 1934920)?
I've tested it and it works!
-- S8C

7.1
02-09-2006, 07:45 PM
iwantmydtvnow had some questions over here (http://www.dealdatabase.com/forum/showthread.php?p=249178#post249178) related to porting the 7.2.1 superpatch port from the -oth version to the -tak version. It seems more directly relevant to this thread, so I'm answering here, with a crosslink.

The patch in question is this one:

VMA Orig Value New Value
---------------------------------------------
*7.2.1-oth
0x00c39430 0c16aed9 0c36171a To understand this patch, it's useful to disassembly the before and after values. ADH showed us how to disassembly one liners here (http://www.dealdatabase.com/forum/showpost.php?p=186919&postcount=11):

echo -ne "\x0c\x16\xae\xd9" > foo.bin
mips-TiVo-linux-objdump -b binary -EB -m mips -D --adjust-vma=0x0 foo.bin
This shows us that the original code was a "jump and link" (a function call):

jal 0x5abb64
the new code decompiles to:

jal 0xd85c68still an function call, but now with a different address.

If you look carefully through the 7.2.1-oth patch, you'll see a list of patches that start at VMA 0xd85c68. That's the location this new patched instruction is jumping to.

In order to port this patch to 7.2.1-tak, you'll need to map the patches starting at VMA 0xd85c68 from -oth to -tak. If I'm reading your notes right, you've already done that and determined that 0x00e57648 is the patch location in 7.2.1-tak that corresponds to 0xd85c68 in 7.2.1-oth.

Next you'll need to figure out how to encode the jal instruction with that address. If you look at a mips instruction set reference (this (http://www.mrc.uidaho.edu/mrc/people/jff/digital/MIPSir.html) one, for example), you'll see that you'll want to divide the target address by 4 and or it in with the JAL instruction opcode ( 0x0c000000). So, in the 7.2.1-other case, the "jal 0xd85c68" instruction gets encode as:
0x0c000000 | (0xd85c68 /4) = 0x0c36171aYou can see that matches the "New Value" for 7.2.1-oth. You'll do the same thing for -tak, substituting the corresponding target address there. You could probably get the assembler to do this work for you if you prefer not to do the math yourself.

Incidently, this part of the patch addresses an issue discussed here (http://www.dealdatabase.com/forum/showthread.php?p=175584#post175584).

iwantmydtvnow
02-13-2006, 05:11 PM
Just want to start off by saying thank you, 7.1, for that detailed explanation. It definitely spells out an important piece of the puzzle for this novice!

I calculated the equivalent missing replacement value for the patch in question:

7.2.1-oth:
0x00c39430 0c16aed9 0c36171a
translates in 7.2.1-tak to:
0x00d0732c 0c17c7e4 0c395d92 After making this change and applying the would-be port, I had some success, but remain short of the mark. My superpatched 6.2 Dtivo could see my now superpatched 7.2.1-tak and vice-versa, including each's Now Showing. HMO functions seemed to work (music, photos), however, MRV would only work in one direction: from 6.2 -> 7.2.1-tak. When I tried moving a recording the other way, the 6.2 box stumbled and failed to play the recording. The box at first indicated that my 7.2.1 wasn't configured for MRV, then on a second attempt transfered the recording (at an unusual snail's pace) but wouldn't display the show - with the same symptoms as described in one of your referenced (http://www.dealdatabase.com/forum/showpost.php?p=175584&postcount=1) posts.

I've since gone through considerable trial and error and strongly suspect that my port of the superpatch is flawed or incomplete. In testing, the superpatch 6.2 box easily MRV'ed with another 6.2 box, so network setup shouldn't be an issue. I was able to pull an unencrypted recording onto my laptop, so scrambling (of recordings) doesnt seem to be a problem. Lastly, I've triple checked the patch locations and am confident they're accurate (based on strong code similarities of a comparison between disassembly dump files). I've also tried encoding a jump and loop replacement value for the above location to target locations immediately before and after the one we've discussed (as the superpatch does with other s/w versions) and have had no luck.

I'm left wondering if there remains some form of MRV encryption from 7.2.1-tak to 6.2 that the patch didn't nuke. Similarly, could the selective blowfish locations have changed very significantly between s/w versions? Any pointers, suggestions or solutions would be a godsend!

7.1
02-13-2006, 06:36 PM
Any pointers, suggestions or solutions would be a godsend!Does it sound anything like this (http://www.dealdatabase.com/forum/showthread.php?p=240859#post240859)? Any chance this (http://www.dealdatabase.com/forum/showthread.php?p=241272#post241272) script helps?

I'll look over the patch when I get a chance, but it might be a few days.

iwantmydtvnow
02-14-2006, 09:35 AM
I'll look over the patch when I get a chance, but it might be a few days. Thank you for the offer, but I managed to work through it. When I posted my previous message, I felt as though I had exhausted all avenues of approach. Since then, I managed to access a different tivoapp, and went scanning through the patch locations. As it turns out, one of my patch locations (which corresponds to 0x0bb647c in 7.2.1-oth) was wrong. Once corrected, all worked fine. Also, FYI, the extra patch you mentioned in 7.2.1-oth (0x0bb44a4) didn't seem to have any effect whatsoever - out of curiosity, what is it intended for?

Anyhow, thanks very much for your time, 7.1 - believe me when I say that it is very appreciated. I'll post a .diff file shortly for other -tak users in the Superpatch thread.

7.1
02-14-2006, 12:03 PM
Also, FYI, the extra patch you mentioned in 7.2.1-oth (0x0bb44a4) didn't seem to have any effect whatsoever - out of curiosity, what is it intended for?My recollection is hazy, but IIRC, there we were nulling out a call to a function (00f0d18c) in one place but not in another. The extra patch nulled out the second call too. It may be code that is never reached, due to the other changes in the superpatch.

Glad you got it working. 7.2.2 is coming soon, so be prepared for another port :D

ScanMan
11-27-2006, 11:52 AM
It seems one particular patch location is causing some difficulty in porting Superpatch to software 8.1 (at least for me, I'll only speak for myself ;) ), it's this particular patch (from 7.3.1)

0x0c7fb5c "10400033 00000000"After some disassembly comparison it appears the code that is "avoided" in 7.3.1 (b/c of the NOOP at 0x0c7fb5c) looks like:


loc_C7FC2C: # CODE XREF: sub_C7F9C4+198j
.text:00C7FC2C jal 0x2A3FB08
.text:00C7FC30 move $a0, $0
.text:00C7FC34 sw $v0, 0x88+var_78($sp)
.text:00C7FC38 li $a1, 3
.text:00C7FC3C la $a2, aTvnvdataclient # "TvNvDataClient.C"
.text:00C7FC44 la $a3, aCouldnTEncrypt # "Couldn't encrypt clip-key for part (%s)"...
.text:00C7FC4C jal 0x2A3A7A8
.text:00C7FC50 move $a0, $0
.text:00C7FC54 jal 0x2A26244
.text:00C7FC58 lw $a0, 0x88+var_58($fp)
.text:00C7FC5C jal 0x2A26244
.text:00C7FC60 lw $a0, 0x88+var_60($fp)
.text:00C7FC64 li $v0, 0x2C0008
.text:00C7FC6C b loc_C7FBE8
.text:00C7FC70 lw $sp, 0x88+var_3C($fp)
.text:00C7FC70 # End of function sub_C7F9C4
This code appears to have changed or is at least not present in the same form in 8.1. A search for "TvNvDataClient.C" reveals a couple of locations but nothing with that structure or reference to "clip-key". However, a search for "clip key" reveals a few strings. The one I am currently interested in is this:


loc_CBC84C: # CODE XREF: sub_CBC604+88j
.text:00CBC84C la $a2, aTvnvdataserver # "TvNvDataServer.C"
.text:00CBC854 la $a3, aScramblerCou_0 # "SCRAMBLER: Couldn't create clip key.\n"
.text:00CBC85C b loc_CBC82C
.text:00CBC860 li $a1, 3
.text:00CBC860 # End of function sub_CBC604Although the code looks very different from the 7.3.1 function, the cross-reference is similar:


0CBC68C beqz $v0, loc_CBC84CIt's the same "branch if equal to 0" instruction in 7.3.1. I know that doesn't mean much by itself as I have already tested a NOOP at "0x0cbc78c" with a similar instruction and although the tivo booted, when I tried to play the MRV'd show, it rebooted my tivo, and I've attached /var/log/tverr

Most of where I'm looking is where the "SCRAMBLER" string appears. Here are the other references to SCRAMBLER.

.rodata:019554E0 aScramblerGener:.ascii "SCRAMBLER: Generating a new key.\n"<0>
.rodata:019554E0 # DATA XREF: sub_CBC604+34o
.rodata:01955502 .align 2
.rodata:01955504 aScramblerEncry:.ascii "SCRAMBLER: Encrypted Read Failed.\n"<0>
.rodata:01955504 # DATA XREF: sub_CBC604+100o
.rodata:01955527 .align 2
.rodata:01955528 aScramblerUnenc:.ascii "SCRAMBLER: Unencrypted Read Failed.\n"<0>
.rodata:01955528 # DATA XREF: sub_CBC604+198o
.rodata:0195554D .align 4
.rodata:01955550 aScramblerEnc_0:.ascii "SCRAMBLER: Encryption Okay.\n"<0>
.rodata:01955550 # DATA XREF: sub_CBC604+1E4o
.rodata:0195556D .align 4
.rodata:01955570 aScramblerCould:.ascii "SCRAMBLER: Couldn't initialize clip key.\n"<0>
.rodata:01955570 # DATA XREF: sub_CBC604+220o
.rodata:0195559A .align 2
.rodata:0195559C aScramblerCou_0:.ascii "SCRAMBLER: Couldn't create clip key.\n"<0>
.rodata:0195559C # DATA XREF: sub_CBC604+250o
.rodata:019555C2 .align 2
Do any of these look more promising? Am I even in the right neighborhood? I plan on testing the NOOP at "0x0CBC68C" I listed above, probably over the next day. I would really like to learn more about this and any pointers would be extremely appreciated. Thanks in advance.

[EDIT] So I tried the NOOP at "0x0CBC68C" and after MRV the recording shows as encrypted (via ciphercheck) but instead of rebooting when I tried to play it, I got the "The DVR could not record because there was no video signal etc." message. Also, tverr now shows:

Nov 27 17:33:42 (none) TmkLogDebugAssertionFailure[223]: false: Clip unusable: 0x1f0001 (16) (void TvCryptoManager::DecryptClipKey(TmkMempool*, const TmkByteString*, ref<TmkByteString>&), line 377 (TvCryptoManager.C) Backtrace: 0x02a83238 0x00e3f214 0x00e41584 0x00e3ffe0 0x00e3fde4 0x00c943b8 0x00bdd034 0x00cb867c 0x00cb8edc 0x00cb84a0 0x00cb84cc 0x00cb7684 0x00cb76dc 0x00cb76fc 0x02a2a02c 0x02a31704 )
Nov 27 17:35:38 (none) TmkLogDebugAssertionFailure[223]: false: Clip unusable: 0x1f0001 (16) (void TvCryptoManager::DecryptClipKey(TmkMempool*, const TmkByteString*, ref<TmkByteString>&), line 377 (TvCryptoManager.C) Backtrace: 0x02a83238 0x00e3f214 0x00e41584 0x00e3ffe0 0x00e3fde4 0x00c943b8 0x00bdd034 0x00cb867c 0x00cb8edc 0x00cb84a0 0x00cb84cc 0x00cb7684 0x00cb76dc 0x00cb76fc 0x02a2a02c 0x02a31704 )
Nov 27 17:37:24 (none) TmkLogDebugAssertionFailure[215]: false: Clip unusable: 0x1f0001 (16) (void TvCryptoManager::DecryptClipKey(TmkMempool*, const TmkByteString*, ref<TmkByteString>&), line 377 (TvCryptoManager.C) Backtrace: 0x02a83238 0x00e3f214 0x00e41584 0x00e40374 0x00e4016c 0x00d5b288 0x00ca4800 0x00c97488 0x00cb07e4 0x004b8a00 0x00487378 0x00c9b348 0x02a2a02c 0x00449ab4 0x00fe2c50 0x02a6adc0 )
Nov 27 17:37:25 (none) TmkLogDebugAssertionFailure[215]: false: Clip unusable: 0x1f0001 (16) (void TvCryptoManager::DecryptClipKey(TmkMempool*, const TmkByteString*, ref<TmkByteString>&), line 377 (TvCryptoManager.C) Backtrace: 0x02a83238 0x00e3f214 0x00e41584 0x00e40374 0x00e4016c 0x00d5b288 0x00ca4800 0x00c97488 0x00cb07e4 0x004b8a00 0x00487378 0x00c9b348 0x02a2a02c 0x00449ab4 0x00fe2c50 0x02a6adc0 )
I think I might try looking into this "TvCryptoManager.C" string next...

shutterfriend
11-27-2006, 07:16 PM
ScanMan,

I am not sure if this is where we should be looking as 7.3.1 also has all of this code also. Anyway, I will look and see if this leads to anything.

Will keep you posted.

angra
01-20-2007, 06:39 PM
I just read through this whole thread (and a few others as well).

I have begun digging around to do some mods to tivoapp, read through the threads with suggestions on tools, and have settled on trying to get IDA Pro to work for me. I've done a fair bit of disassembly, reverse engineering, and binary mod work in the past, but never on MIPS code. Past work has been mostly on x86, and motorola family (6502 lineage, etc).

My normal preferred method to start with where I am is to hunt around based on cross references on strings that I know or can reasonably guess what they do. Hence the preference for the GUI tools.

Anyway, IDA is a bit of a change from what I've worked with before, and so is the MIPS. I'm not getting any cross references to anything in the disassembler. I tried doing a memory mapping from 0x400000 to 0 and also vice versa (based on the difference between memory and file mods), but that doesn't seem to help. Anybody using this tool for tivoapp dissassembly? If so, I could probably use a pointer or two on getting the it properly set up.

I realize this is an old, old, incredibly old school thread, but it did seem like the best place to ask. Thanks for any pointers.

mrpenguin
01-20-2007, 08:30 PM
what ver ida are you using? Ida works great. just open up tivoapp in it, choose mips processor, wait about 10-30 minutes for it to do its analysis and you can do all the figuring out you need. any code it does not automatically convert from data to code, just hit the c key on keyboard and it converts it. Great app for disassembling

angra
01-21-2007, 06:24 PM
I'm using 5.0. Looking some more, I have found _some_ crossreferences, but a lot of strings that I expect to have a xref don't. So the answer may just be more study and better understanding of MIPS assembly on my part for a while.

thanks for the response. Loading up 3 different tivoapp versions has helped for comparisons (I have 3.1.5, 6.2, and 8.1 running in my house).

Red_Dog
05-03-2007, 10:54 AM
I decided to try learning to patch tivoapp. I have current experience with PIC microcontroller assembly and way back I did a lot of forward and reverse assembly on my C64. Yep, I'm old.

I started by running resource.tcl to get MFS text items. That was easy.
I tried to get mips.dasm.pl.042 working with cygwin, but my dumpobj did not work. So I went with a different approach. I loaded VMware player and downloaded the browser sample.

Good news, that browser sample runs Ubuntu linux and has perl. I can't move files to and from VMplayer, so I used ftp with the tivo as a middle man.
I chose to start with tivoapp 3.1.5f because it's not too large and that's my only TiVo that is not recording all the time. (for when I mess it up, a backup is ready)

I thought it would be best to start by studying existing patches before I try a new one. I picked the backdoor patch to look at first. I see that one instruction gets changed.

Before:
ADDU $a1,$s4,$0 That copies a saved register that apparently holds the "backdoor on" flag to an argument register.

After:
ADDIU $a1,$0,1 That copies a immediate 1 (in PIC it's called literal) to the same argument register. "1" must be back door on.

That is seems easy; the hard part is finding the location to patch.

I know that the "system information page" shows "Backdoor: Enabled!" and my 315.res file holds that text in two consecutive entries. If I find that text in the annotated dump, then I'll be well on the way. Too bad that did not work; that text was NOT in the dump.
Since the "system information page" holds many lines, maybe the MFS pointers are stored in a table instead of loaded into a resister as a constant.

[EDIT - I see that none of the MFS resources are in the annotated dump. I did notice that the "Find Jump Targets" did not report back a result
during the disassembly also I had the "no symbols" problem with dumpobj and I used the change "symbol" to "disassembly"

I just found this...For this to work, you need to include the def line for the getResource function in your .proc file....
That's why it did not work!
~EDIT]


Does anyone have a proc file for 3.1.5f?
Is my table idea way off base?

Learning more every day,
Red_Dog

Red_Dog
05-04-2007, 10:26 PM
I re-read all the posts in a couple threads again except this time I did it slowly.

It took just a couple minutes of searching the ".S" file to find the address of the getResource procedure. I searched for "# a1 = 0x00020215" {Backdoors:} and some others and they all call 0x000AB6EB4. That procedure get called 1985 times.

The System info screen calls each MFS item from individual constants.

Life is good,
Red_Dog

woracan
09-17-2009, 10:36 AM
I find the graph view in IDA to be helpful, but IDA doesn't find all the string refs that the tmesis disassembler (http://dealdatabase.com/forum/showthread.php?t=27553) does. So, after using tmesis disassembler to create my tivoapp.S file, I ran the following grep command to make a file with all the string references and the offset they apply to.
grep -A2 "LA Possible reference to string" tivoapp.S > out.txt

Next, I opened out.txt in Vim and performed the following four substitutions:
%s/\\/\\\\/g
%s/# LA Possible reference to string: "\(.*\)"\n.*\n\([^ ]*\) .*# \(LA.*\)\n.*/MakeComm(\2,MyQuOtE\1\\n\3MyQuOtE);/
%s/"/\\"/g
%s/MyQuOtE/"/g

The number of lines is too many to copy and paste as an IDC script, so I saved it as an IDC file. IDA complained because it expects the ICC script to contain a function, so I added the following two lines to the beginning of the file
static main()
{


An open brace must be closed, so I added a close brace to the end of the file like so:
}

The final step to get these 22280 helpful comments added to the IDA disassembly is to run the IDC file just created.

woracan
09-17-2009, 01:41 PM
In a similar manner, I added comments for most of the jalr statements to the IDA disassembly.

First,

grep jalr.*# tivoapp.S > out.txt

Next, with out.txt in Vim:

%s/\(.*\) jalr.*# \(.*\)/MakeComm(\1,"\2");/

Before saving as an IDC file and exiting Vim add a closing brace as the last line of the file and the following two lines at the beginning of the file:

static main()
{

Running the resulting IDC file in IDA added comments for jalr in 260,188 places.