Announcement

Collapse
No announcement yet.

A simple Disc Mod

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • A simple Disc Mod

    I tried to hex-edit a code into a game's ELF, so that I wouldn't need to use a cheat device anymore, but can't get it to work.


    The code is a simple constant write to a RAM address. Here's what it looks like, ready to be used with a cheat device that accepts raw codes.


    F0100008 0026F787
    2043AAB4 00000000


    So I read a few things about MIPS assembly, and how to hook my own functions into the game. I have to thank GameMasterZer0 and bungholio for their tutorials on the subject, and Gtlcpimp for his excellent Code Designer tool. Without all these people, I wouldn't have gotten anywhere. I'm new to all this stuff and I'm struggling to make it work.


    Anyway, here's what I did so far:
    -extracted the elf, opened it up in ps2dis, invoked the analyzer and imported labels from label mates
    -looked for room to place my own function (rows of nop)
    -found the scesifsendcmd label and the "jr ra" at the end of the function
    -used Code Designer to write a jump to the "empty space" and injected it to replace the "jr ra"
    -wrote my own function that should store the zeros into the RAM and injected it at the empty space
    -copied the modified ELF file onto my USB stick and plugged it in my softmodded PS2
    -loaded the ELF file with ESR's "launch app" option by locating and executing it through ulaunch on the stick (the game DVD is ESR patched)


    Here's the code of my hook in Code Designer.
    Code:
    // Hook
    address $0025d4e4
    j $003d8a40
    I choose "file inject" at this address: 0015d5e4 (003d8a40 - fff00).




    Here's the code of my function in Code Designer (it's supposed to write this data: 00000000 at this address: 0043AAB4).
    Code:
    // Mod
    address $003d8a40
    lui t0, $0x0000
    li t0, $0x0000
    lui t1, $0x0043
    nop
    sw t0,$AAB4(t1)
    nop
    jr ra
    I choose "file inject" at this address: 002d8b40 (003d8a40 - fff00).


    Here are screenshots from ps2dis, before and after injecting the hook (I only added the label "hook").






    Here's a screenshot from ps2dis after injecting the function (I only added the label "mod").




    I must've screwed up somewhere, because the game loads and plays like it hasn't been modified at all. I hope someone can help me.

  • #2
    Your code won't work for a number of reasons. Your started off fine with address 0x0025D4E4 (not where you jumped to, though).

    - You are making your hook jump into RAM. Don't just use any row of nops you see fit. You never know how the game occupies that space of memory. Hook your code into the kernel memory instead (somewhere between 0x000C0000 - 0x000FFFFF). Be careful, as ESR occupies the area in 0x000C0000. Every time I used this area for subroutines, my games always crashed during the color test (I don't recall the exact name for this). I changed my code to use the 0x000FFFFF region instead, and the code/game worked fine.

    - Your mod code looks odd to me. It can be coded in a number of ways and you can achieve the same result of the RAM code with a simple ASM patch (the area of coding that writes to the address). Something like this should work (I grabbed the file real quick to give you a test code):

    0025D4E4 0803FFCO
    000FFF00 3C010044
    000FFF04 8C21A9B4
    000FFF08 24030000
    000FFF0C A423FBA4
    000FFF10 03E00008

    I did a lot of fiddling around to find the offset used in the above code (a bit rusty with the PS2). I'm too tired to explain how I came to said value, but you should be able to figure it out on your own. You can also try hard-coding the value that writes to 0x0043AAB4 by pressing space bar on it, then F3 to trace all referrers to it. Modify the "li, register, $FFFFFFFF" addresses before it to store 0000 instead (modify the FFFF part of them). That should work.

    I don't know if you missed this, but Gtlcpimp wrote a guide on this here: http://www.thegshi.org/vb/threads/44...evice-required

    Pyriel wrote one of the best guides to date on the CMP that covers subroutines: http://www.gshi.org/vb/threads/1587-...om-Subroutines

    You can also check out a text file with info on the PS2 memory map here: http://psx-scene.com/forums/f19/ps2-...-layout-64760/

    I'm out...
    Last edited by Hacc; 03-24-2011, 01:10:25 AM.

    Comment


    • #3
      Why do you need a hook, isn't it just loading a modified ELF? also why jr ra and not jal?
      Last edited by kh2k4; 03-24-2011, 04:41:09 AM.
      http://bh-re-db.pcriot.com/ <- Biohazard / Resident Evil
      Code Database

      Comment


      • #4
        Originally posted by kh2k4
        Why do you need a hook, isn't it just loading a modified ELF?
        I need to constantly write a value at a specific RAM address. The hook is there to call my "write function" constantly. Maybe I should explain the thoughts behind my code:

        lui t0, $0x0000
        -write zeros into the temporary register t0
        -I use temporary registers, because I use a "jump to return address" (jr ra) at the end of my code, and afaik that means I can safely use the temporary registers without corrupting the game

        li t0, $0x0000
        -after reading up on the lui command, I think this line is redundant
        -I wasn't sure if the lui command writes the zeros in the upper and lower bits, I wanted to be sure that t0 is now 00000000

        lui t1, $0x0043
        -now I want to get the upper bits of the RAM address into t1, t1 should now be 00430000

        nop
        -I wanted to wait, because I read that load commands take a while to execute

        sw t0,$AAB4(t1)
        -this is the line where I want to overwrite the RAM address (0043AAB4) with 8 zeros
        -the value at the RAM address 0043AAB4 should now be 00000000

        nop
        -I just wanted to leave some space in case I have to add a line

        jr ra
        -jumps back to the return address, which I didn't change anywhere, so I hope this resumes the game as usual


        Originally posted by kh2k4
        also why jr ra and not jal?
        A jal changes the "ra" register, I didn't want to overwrite its contents, so that I can simply return and jump back savely at the end of my code.



        Originally posted by Hacc View Post
        Something like this should work (I grabbed the file real quick to give you a test code):

        0025D4E4 0803FFCO
        000FFF00 3C010044
        000FFF04 8C21A9B4
        000FFF08 24030000
        000FFF0C A423FBA4
        000FFF10 03E00008
        Thx, let me try to figure out what your code does, line by line (I decompiled with Code Designer).

        j $000FFC30
        -the jump to the function at fff00
        -problem: this address is the very beginning of the ELF file and I would destroy the header if I'd inject the function into this part of the ELF file

        lui at, $0044
        -the value 0044 is shifted left 16bits and stored in the register "at", the lower 16 bits are set to zeros ("at" is now 00440000)
        -why are you using "at", isn't that reserved by the assembler?

        lw at, $A9B4(at)
        -the value at the address 0044A9B4 is loaded into the register "at"
        -why would you load a word into "at", thus overwriting its value?
        -you also don't know what value the address 0044A9B4 holds, doesn't this mean that the value in "at" is now unknown?

        addiu v1, zero, $0000
        -v1 is zero + 0000, the const 0000 is sign-extended to 32bit (I guess that means v1 is now 00000000)

        sh v1, $FBA4(at)
        -I think v1 is written to an unknown address (because the value in at is unknown)
        -why only store a half word, I need to write a word (00000000) in RAM and not only half (0000) of it

        jr ra
        -jump back, no prob here
        Last edited by 1CC; 03-24-2011, 09:35:27 AM.

        Comment


        • #5
          Excuse my explanation on the subject, as I never really had to explain it to others in much detail. I just retain (to an extent) what I learn from other hackers codes and the guides written on making ASM codes.

          Originally posted by 1CC
          j $000FFC30
          -the jump to the function at fff00
          -problem: this address is the very beginning of the ELF file and I would destroy the header if I'd inject the function into this part of the ELF file

          I'm sure I read correctly that it was safe to jump to that area of memory from reading the guide. I'll make a quick modification to a small game and see what happens when I do.

          lui at, $0044
          -the value 0044 is shifted left 16bits and stored in the register "at", the lower 16 bits are set to zeros ("at" is now 00440000)
          -why are you using "at", isn't that reserved by the assembler?

          I used "at" and the address 0x0043A9B4 because it was the closest one I found to your continues code. It's also used as a pointer. Meaning, the value held at it is used for something, which I don't know what, as I don't have the game (I just grabbed the SLUS file from our resident librarian who has a database of game files). I also took a chance hoping that the value might be consistent throughout the game.

          lw at, $A9B4(at)
          -the value at the address 0044A9B4 is loaded into the register "at"
          -why would you load a word into "at", thus overwriting its value?
          -you also don't know what value the address 0044A9B4 holds, doesn't this mean that the value in "at" is now unknown?

          - If you inputted my code into PS2DIS, you would have seen that it was loading the value stored at 0x0043A9B4. I wrote the code in PS2DIS to make sure it jumped where I wanted it, too.

          - As I stated before, the address is used as a pointer and holds a 32-bit value.

          - I did know what the value was beforehand. It's 0043AF10 in an unmodified/non-dumped SLUS. One of the other reasons, as to why I used this pointer address. Now that I look at my code again, that value (0043AF10) was probably the reason why I got confused trying to find the correct offset to use for the code. Confusion combined with tiredness = fail, cuss, etc.


          addiu v1, zero, $0000
          -v1 is zero + 0000, the const 0000 is sign-extended to 32bit (I guess that means v1 is now 00000000)

          It's just to make sure that the value being written to said register is the only one; nothing else. That is the best explanation I can come up with for now. As I said before, I never had to explain this stuff in great detail, but to a select few of hackers who were learning to use PS2DIS. When I did, it was in my own layman's terms. I just read and apply "X" info to satisfy my needs when the time comes. I only started to take ASM hacks more seriously when I had to deal with a troublesome PSX game that used DMA (Dynamic Memory Allocation). Making only RAM hacks over time gets boring. The possibilities of ASM hacks makes RAM hacks look like child's play.

          sh v1, $FBA4(at)
          -I think v1 is written to an unknown address (because the value in at is unknown)
          -why only store a half word, I need to write a word (00000000) in RAM and not only half (0000) of it

          - See my previous points. I was initially going to write to v0 instead, as that is normally the register that holds the current value of whatever is being written to in the games that I have hacked. But I saw from tracing through the code, that it mainly read/write to "v1".

          - The store register used is not always important. Depending on the value written in RAM, you can just apply the proper register to accompany it (sb for 8-bit; sh for 16-bit; sw for 32-bit). I also used "sh" because it came to my mind first. It should not affect the outcome of the code in any way.


          jr ra
          -jump back, no prob here

          Yatta! (I did it!) lol
          Last edited by Hacc; 03-24-2011, 12:06:20 PM.

          Comment


          • #6
            Originally posted by Hacc
            Originally posted by 1CC
            j $000FFC30
            -the jump to the function at fff00
            -problem: this address is the very beginning of the ELF file and I would destroy the header if I'd inject the function into this part of the ELF file
            I'm sure I read correctly that it was safe to jump to that area of memory from reading the guide. I'll make a quick modification to a small game and see what happens when I do.
            I really don't know why you're talking about "jumping into memory". I'm jumping into other parts of the ELF file, namely the part where I injected my own function. I should've asked this before, when you said this in your first post.

            Originally posted by Hacc
            You are making your hook jump into RAM.
            I didn't make my hook jump into RAM, I jumped to another address within the ELF file.




            Originally posted by Hacc
            Don't just use any row of nops you see fit. You never know how the game occupies that space of memory.
            This also contradicts what Gtlcpimp wrote in his tutorial on Disc Mods.

            Originally posted by Gtlcpimp
            Now open the (ELF) file in your hex editor. Look for any unused space (a large area of NULL data hex bytes: 0x00).



            Originally posted by Hacc
            Originally posted by 1CC
            lui at, $0044
            -the value 0044 is shifted left 16bits and stored in the register "at", the lower 16 bits are set to zeros ("at" is now 00440000)
            -why are you using "at", isn't that reserved by the assembler?
            I used "at" and the address 0x0043A9B4 because it was the closest one I found to your continues code. It's also used as a pointer. Meaning, the value held at it is used for something, which I don't know what, as I don't have the game (I just grabbed the SLUS file from our resident librarian who has a database of game files). I also took a chance hoping that the value might be consistent throughout the game.
            But all of this is unnecessary, because I know the exact location that I want to write to already. There is no need to retrieve a pointer. You're overcomplicating things.




            Originally posted by Hacc
            - If you inputted my code into PS2DIS, you would have seen that it was loading the value stored at 0x0043A9B4. I wrote the code in PS2DIS to make sure it jumped where I wanted it, too.
            Thx for bringing this to my attention, because that is it! That's the problem with my code. If I want to write to the RAM address 0043AAB4 I have to write to 0044AAB4. The correct offset for that part of the RAM seems to be 0x00010000. PS2DIS shows the adress after the analyzer is invoked. How could I miss that? It's even visible in the screenshot in my opening post.



            I don't want to write to 0042aab4, I want to write to 0043aab4, thus the "lui" above has to be changed to take the offset into account.

            The only change I had to make to my initial code, was to exchange this line
            Code:
            lui t1, $0x0043
            with this one.
            Code:
            lui t1, $0x0044
            I also deleted the redundant "li" and a nop line. The new code of my function thus looks like this:
            Code:
            //Mod
            address $003d8a40
            lui t0, $0x0000
            lui t1, $0x0044
            nop
            sw t0,$AAB4(t1)
            jr ra
            (injected with Code Designer at 002d8b40)


            I tested it and it seems to work fine now.
            Last edited by 1CC; 03-25-2011, 06:46:43 AM.

            Comment


            • #7
              Too lazy to quote...

              When I say memory, I mean a specific area of the PS2 executable. Each section is divided accordingly. Your code is indeed jumping into RAM. Any address not found in the ASM (the game's machine code. I.E., sceSifSendCmd) region, is RAM. I also noticed you did without even having the file at the time from this pic: http://img17.imageshack.us/img17/5209/ownfunction.jpg. The desolate area of nops and seeing 42B40000 gave it away.

              Gtlcpimp, obviously didn't want to go into much detail about some things mentioned in his guide. Yes, he said and gave a specific area to look for null data (zeros), but some games might use the area chosen to write the routine in some way. It's best to just find a suitable area with PS2DIS than a hex editor. You can also write your code in it to make sure it is writing where you want it, too. Then, apply it to Code Designer.

              As for my code, you have to remember that there is more than one way to handle the task at hand. I intentionally wrote it that way to show you this. Like I said before, the effect of a subroutine hack could be simply achieved with a tiny modification to the coding that controls your RAM address (0x0043AAB4).

              As for your code, congrats on getting it to work. I can't explain what I wanted to say about your code, as I have to go. However, I will quickly say that you realized some things about it, but interpreted the info you got from it wrong.
              Last edited by Hacc; 03-25-2011, 06:56:31 PM.

              Comment


              • #8
                Originally posted by Hacc
                When I say memory, I mean a specific area of the PS2 executable.
                I guess this means the executable is loaded into RAM?


                Originally posted by Hacc
                Your code is indeed jumping into RAM. Any address not found in the ASM (the game's machine code. I.E., sceSifSendCmd) region, is RAM.
                How do I tell which section "is RAM" and which isn't?


                Originally posted by Hacc
                It's best to just find a suitable area with PS2DIS than a hex editor. You can also write your code in it to make sure it is writing where you want it, too. Then, apply it to Code Designer.
                That's exactly what I did.


                Originally posted by Hacc
                As for my code, you have to remember that there is more than one way to handle the task at hand. I intentionally wrote it that way to show you this.
                I appreciate your help, but do you wanted to show me that it could be done in a much more complicated and harder to understand way?


                Originally posted by Hacc
                Like I said before, the effect of a subroutine hack could be simply achieved with a tiny modification to the coding that controls your RAM address (0x0043AAB4).
                I haven't found the code that controls my RAM address. I could search for it, and might be able to find and modify it accordingly, now that I know the correct offset and address to search for (0x0044AAB4) but why should I?


                Originally posted by Hacc
                I will quickly say that you realized some things about it, but interpreted the info you got from it wrong.
                If you find the time, I'd like to know what I interpreted wrong, to not make the same mistake in the future.
                Last edited by 1CC; 03-26-2011, 08:00:34 AM.

                Comment


                • #9
                  Originally posted by Hacc View Post
                  Hook your code into the kernel memory instead (somewhere between 0x000C0000 - 0x000FFFFF). Be careful, as ESR occupies the area in 0x000C0000. Every time I used this area for subroutines, my games always crashed during the color test (I don't recall the exact name for this). I changed my code to use the 0x000FFFFF region instead, and the code/game worked fine.
                  Kernel is only 0x80000000 - 0x8007FFFF.
                  User space RAM is 0x00080000 - 0x02000000.


                  Originally posted by 1CC View Post
                  I guess this means the executable is loaded into RAM?
                  Correct.


                  Originally posted by 1CC View Post
                  How do I tell which section "is RAM" and which isn't?
                  RAM (Random Access Memory) is the memory where everything is stored when it is loaded "onto" the console. It's all RAM, no matter what address, it's still part of the RAM.



                  On a side note, the guide I wrote for full cheats via disc mod was a quick draft (I hate going into detail). Was more aimed towards people with knowledge at hand already than the beginners...

                  Comment


                  • #10
                    Thanks for the corrections and explanations, Gtlcpimp.

                    @ 1CC: I don't know when that will be, as some real life matters at hand need to be dealt with. I don't know when I'll be back. Some of the more advanced hackers here can help you out in the meantime.

                    Comment


                    • #11
                      Originally posted by Gtlcpimp
                      Originally posted by 1cc
                      I guess this means the executable is loaded into RAM?
                      Correct.
                      That sounds a bit frightening. Doesn't it mean that a game could overwrite and completely alter its excutable at runtime? And doesn't it also mean that, without inspecting every part of the ELF, I can never be sure that the rows of nops I selected for my own subroutine won't be overwritten, after they've been loaded into RAM? Is there a way to quickly identify unused space?


                      Originally posted by hacc
                      Hook your code into the kernel memory instead
                      If I replace my "game hook", with a "kernel hook", how does that help me with the location of my subroutine within the ELF? Or can I write the entire subroutine within that part of the ELF file, that will be loaded into "kernel memory"?

                      If so, where exactly is that space located in the ELF file? This would also answer the above question about quickly locating unused space.


                      Originally posted by Gtlcpimp
                      On a side note, the guide I wrote for full cheats via disc mod was a quick draft (I hate going into detail). Was more aimed towards people with knowledge at hand already than the beginners...
                      Yes, it wasn't aimed at neither my skill level nor task, as I just wanted to do a rather simple disc modification. Is there a tutorial out there on how to make a patch, thus hardcoding a cheat? I had to string together bits and pieces from these two threads.

                      http://www.gshi.org/vb/threads/3638-...memory+scanner
                      http://www.gshi.org/vb/threads/1587-...om-Subroutines

                      It would've worked if the "hidden" offset wouldn't have gotten in the way. I can't remember reading about this 0x00010000 offset in a tutorial before, is it only in this particular game, or do all PS2 games use it?
                      Last edited by 1CC; 03-28-2011, 05:29:16 AM.

                      Comment


                      • #12
                        Originally posted by 1CC View Post
                        That sounds a bit frightening. Doesn't it mean that a game could overwrite and completely alter its excutable at runtime? And doesn't it also mean that, without inspecting every part of the ELF, I can never be sure that the rows of nops I selected for my own subroutine won't be overwritten, after they've been loaded into RAM?
                        If designed to yes. Most generally no the ELF will not, since the applications are normally written to allocate memory for read / writes outside of the space used by the file itself.

                        Originally posted by 1CC View Post
                        Is there a way to quickly identify unused space?
                        Yes, and flawless too. Read the header of the ELF file, it will tell you exactly what get's loaded to where. It will tell you what parts of the file is being loaded, so you can just consume the parts that aren't being loaded and add in another extension on the header to load it. In commercial games there is usually a large amount of blank space between the end of the header and the beginning of the function data. Most of the time the headers will show it starts loading from the point the function data is at, thus leaving the blank space between unused and untouched. You can put all the routines you want (that can fit) in that area, and then extend the header out to perform a load from that unused space to store to whatever memory address you want.

                        Originally posted by 1CC View Post
                        If I replace my "game hook", with a "kernel hook", how does that help me with the location of my subroutine within the ELF? Or can I write the entire subroutine within that part of the ELF file, that will be loaded into "kernel memory"?
                        If you choose the route of the modded header, then the simplest way of installing a kernel hook would be to change the entry point to a start up function you have to make. Write out the start up function to install a kernel hook to execute your other function, and then jump back to the original entry point. Your functions don't have to be in kernel memory to be executed from the kernel.

                        Comment

                        Working...
                        X