PS2 Julian's various PS2 projects (Worklog)

There is an incompatibility in older versions of modload versus newer versions.

When returning the value "2" in the entrypoint of the module, this is parsed differently between modload versions
* < 1.2: Non-resident, unloads module after entrypoint executes.
* >= 1.2: Resident, flag marked as unloadable.

However, there is a way to keep the module compatible in all modload versions (no version checking needed to return the correct return value), while enabling module unloading. The fourth argument of the entrypoint contains a pointer to the module information. In this case, set 0x10 flag on the "newflags" member of ModuleInfo_t.
 
There are many ways registers are accessed.
For a lot of cases the direct address is being used e.g.
Code:
*((u32 *)0xBD000000) = hoge;
hoge = *((u32 *)0xBD000000);
Readability can be somewhat improved by using definitions
Code:
#define REG_MSCOM ((vu32 *)(0xBD000000))
// ...
*REG_MSCOM = hoge;
hoge = *REG_MSCOM;
But it is possible to do better (and what I'm working towards). Basically start with a structure offset and then access members.
Code:
typedef struct sif_regs_
{
vu32 mscom;
u32 pad04[3];
vu32 smcom;
u32 pad14[3];
//...
} sif_regs_t;
#define USE_SIF_REGS sif_regs_t *sif_regs = (sif_regs_t *)0xBD000000;
// inside function...
USE_SIF_REGS;
sif_regs->mscom = hoge;
hoge = sif_regs->mscom;
The dev9, smap, usb, and ieee1394 drivers in ps2sdk are already using this method.
 
Last edited:
How to mark elf and shell scripts as executable (when they are not already)
Code:
find . -type f -exec python3 -c 'import sys; bytez = open(sys.argv[1], "rb").read(20); cond = bytez == b"\x7F\x45\x4C\x46\x01\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x03\x00" or bytez[0:2] == b"#!"; sys.exit(0 if cond else 1)' {} \; -exec chmod +x {} \+

There is definitely a faster way to do this
 
The BSim feature in Ghidra is really helpful when you have a bunch of files with debug info/symbols in them and you want to apply them to another executable. It works better when you can find the same exact version compiled the same way. Some things that may need to be manually fixed up are syscalls and thunk functions (in that regard, Diaphora can handle those better).

https://github.com/NationalSecurity...raDocs/GhidraClass/BSim/BSimTutorial_Intro.md
 
Some tidbits about the OSDSYS in 1.00/1.01:

0x00204838: OSxxxxx loading code (in 1.01: 0x00204880)
0x002049e0: checks for and runs mcX:/BIEXEC-SYSTEM/osdsys.elf
0x00204af0: MBROWS loading code
0x00204d68: main loading code

The files starting with OS has 3 lines, which determines the version, filename of the compressed executable, and load address of the decompressed executable.
The compression format is the same as the compression for resources in newer OSDSYS.
OSBROWS is also checked on both memory cards.

The main OSDSYS executable contains mainly the loading, I/O, and sound related stuff, while MBROWS/MCLOCK/MOPEN are compressed raw EE executables corresponding to the browser, clock, and opening, respectively. Communication is performed using thread state (sleep/wakeup) and shared structure.

There appears to be a vulnerability in the OSxxxxx loading/parsing code:
Code:
undefined4 FUN_00204838(char *param_1,int param_2)
{
  int iVar1;
  int iVar2;
  char *pcVar3;
  char *pcVar4;
  char *pcVar5;
  char *__dest;
  char acStack_160 [256];
  ulong uVar6;
  iVar1 = sceOpen(param_1,1);
  uVar6 = (ulong)iVar1;
  if (-1 < (long)uVar6) {
    iVar1 = sceLseek(uVar6,0,2);
    if ((-1 < (long)iVar1) && (iVar2 = sceLseek(uVar6,0,0), -1 < iVar2)) {
      iVar1 = sceRead(uVar6,(uint)acStack_160,(long)iVar1);
      if (iVar1 < 0) {
        return 0;
      }
      iVar1 = sceClose(uVar6);
      if (-1 < iVar1) {
        pcVar3 = strchr(acStack_160,10);
        *pcVar3 = '\0';
        iVar1 = FUN_00217f38(acStack_160);
        if (*(int *)(&DAT_0041ef7c + param_2 * 0x414) < iVar1) {
          *(int *)(&DAT_0041ef7c + param_2 * 0x414) = iVar1;
          pcVar4 = strchr(pcVar3 + 1,10);
          __dest = (char *)(param_2 * 0x414 + 0x41eb70);
          *pcVar4 = '\0';
          strcpy(__dest,param_1);
          pcVar5 = FUN_00218c50(param_1,"rom");
          if ((pcVar5 == (char *)0x0) &&
             (pcVar5 = FUN_00218c50(param_1,"host"), pcVar5 == (char *)0x0)) {
            pcVar5 = FUN_00218c00(__dest,'/');
          }
          else {
            pcVar5 = strchr(__dest,0x3a);
          }
          strcpy(pcVar5 + 1,pcVar3 + 1);
          pcVar3 = (char *)(param_2 * 0x414 + 0x41ef70);
          strcpy(pcVar3,pcVar4 + 1);
          pcVar3 = strchr(pcVar3,10);
          *pcVar3 = '\0';
        }
        return 1;
      }
    }
  }
  return 0;
}
 
Hi @uyjulian

I have a problem with the emotion engine extension you mentioned for Ghidra a few pages back

Short version:
Two elf files in ps2 game. I tried loading both into Ghidra. The debug symbols arent working for the second elf file when I load that in on its own. If I load in the first elf file half of the functions are red and arent viewable. They seem to be in the second elf file.

Long version and what I've tried so far to load the elf files:

I used the elf_extract tool on a ps2 games bin file. The bin file has debug symbols inside it.

This tool found 2 elf files.

EXAMPLE.68
EXAMPLE.ELF

I loaded EXAMPLE.68 into Ghidra using the ghidra-emotionengine-reloaded extension

It was successfully detected as a PS2 Elf file with 40,000 debug symbols.

I then ran the analysis and everything is going great the functions have names.

However , half of the games functions which are listed in the Symbol Tree are red and non-clickable. If I click them it says "Can not navigate to function symbol: (Not in Memory)". These red function labels seem to be inside the second elf file EXAMPLE.ELF

So I did File -> Add to program option in Ghidra when inside the project that has the first Elf loaded

And I selected the second elf EXAMPLE.ELF. Then I reran the full analysis. It did not fix the problem.

I then started again from scratch. I re-loaded the first Elf file into a new empty Ghidra project but this time I ticked the checkbox "Load system libraries from disk" in the loader options. I added the full path to the second elf file EXAMPLE.ELF.

After waiting for the full analysis to complete and having ticked the STABS, Aggressive Instruction Finder, Decompiler Parameter ID Elf Scaler Operand References options etc for the loader to load everything

This did not fix the problem

Have I done something stupid or is this not working becauses of the emotion engine extension ?

I have also tried loading both Elfs at the same time into a new Ghidra project and running the analysis then. That did not solve the problem either.

I have spent hours trying to get this working -_- Any idea why this is happening?
problem.png
 
Hi @uyjulian

I have a problem with the emotion engine extension you mentioned for Ghidra a few pages back

Short version:
Two elf files in ps2 game. I tried loading both into Ghidra. The debug symbols arent working for the second elf file when I load that in on its own. If I load in the first elf file half of the functions are red and arent viewable. They seem to be in the second elf file.

Long version and what I've tried so far to load the elf files:

I used the elf_extract tool on a ps2 games bin file. The bin file has debug symbols inside it.

This tool found 2 elf files.

EXAMPLE.68
EXAMPLE.ELF

I loaded EXAMPLE.68 into Ghidra using the ghidra-emotionengine-reloaded extension

It was successfully detected as a PS2 Elf file with 40,000 debug symbols.

I then ran the analysis and everything is going great the functions have names.

However , half of the games functions which are listed in the Symbol Tree are red and non-clickable. If I click them it says "Can not navigate to function symbol: (Not in Memory)". These red function labels seem to be inside the second elf file EXAMPLE.ELF

So I did File -> Add to program option in Ghidra when inside the project that has the first Elf loaded

And I selected the second elf EXAMPLE.ELF. Then I reran the full analysis. It did not fix the problem.

I then started again from scratch. I re-loaded the first Elf file into a new empty Ghidra project but this time I ticked the checkbox "Load system libraries from disk" in the loader options. I added the full path to the second elf file EXAMPLE.ELF.

After waiting for the full analysis to complete and having ticked the STABS, Aggressive Instruction Finder, Decompiler Parameter ID Elf Scaler Operand References options etc for the loader to load everything

This did not fix the problem

Have I done something stupid or is this not working becauses of the emotion engine extension ?

I have also tried loading both Elfs at the same time into a new Ghidra project and running the analysis then. That did not solve the problem either.

I have spent hours trying to get this working -_- Any idea why this is happening?
problem.png
Not really sure about that, since I haven't encountered that issue before.
 
Now that MMC24 submission period is finished (phew), I'll start working on PS2 stuff again.

There are only a few more modules left, and they basically need polishing at this point. After those are done, probably next ones I'll take a look at are deci2, and rspu2/sd/csl/sk.

I'll also take a look at ipu portability, and make sure the code is debuggable so that I can do iteration faster.
 
Once module unloading is supported in modload, it does not immediately mean that all modules can be unloaded. Cleanup also needs to be done:
* Deallocate allocated memory
* Close files
* Delete thread, semaphores, timers, or other resources
* Shut down devices

Unlike the deinit callback in index 2 of the export table when IOP reboot/UDNL is performed, resources need to be released, so that other modules loaded afterwards can use them. It does not do it "automatically". (So only changing the return value from 0 to 2 of the module entrypoint without any cleanup code will leak resources)

---

When the update to modload is implemented, the following features will be added:
* Module unloading
* Wipe memory with break instructions on unload (good for debugging use-after-free issues)
* Streaming module loading (good if you want to keep debug symbols while using less memory)
* Unpaired hi/lo relocations
 
I dug up some remote controls from some old Sony DVD/BD players (RMT-D105A, RMT-P001, RMT-P002J, RMT-B119A). With my rmman2 implementation, they work but mostly with different commands (exception being the RMT-D105A).

With a RM-YD023 remote (Sony TV), it doesn't appear to work.

Would be interesting to see what other remotes work.
 

Similar threads

Back
Top