3.03 - 3.11

These firmware versions all have the same getDiscData 0xffff * 3 * 8 buffer overflow of immediately controllable contents.

3.03 3.04J 3.04M 3.10 3.11
Symbols
getDiscData 0x23e150 0x23e138 0x25c9f0 0x258b98
getDiscByte 0x23e068 0x25c920 0x258ac8
currentDiscBytePointer 0x16ceee4 0x1411fe4 0x143b3e4
endDiscBytePointer 0x16ceee8 0x1411fe8 0x143b3e8
0xff * 3 * 8 overflow 0x23cb04 0x25b3bc 0x257564
fpIndex 0x16cf74a 0x141284a 0x143bc4a
fpArray 0x95ace8 0x5b9d40 0x3b3050
OOB call 0x23faac 0x25e388 0x25ab44
getBufferInternal 0x261548
pointToIFO 0x23dfc8
SifIopReboot 0x291528
SifInitRpc 0x208260
SifExitRpc 0x208400
SifIopReset 0x291358
SifIopSync 0x2914d8
Controlled memory ranges
Destination of large copy 0x16c8cd4 0x140bdd4 0x14351cc
Destination + max size 0x1848CBC 0x158BDBC 0x15B51B4
Sector buffer (getDiscByteInternal) 0x16cad40 0x140de40
Exploit values
currentDiscBytePointer value at overwrite 0x016ce444 0x01411544 0x0143a94c
Jump target 0x01800180 0x01500014 0x01500014
Address of jump target 0x95CF40 0x5f1f38 0x3EA438
IFO offsets
currentDiscBytePointer 0x2744 0x2744 0x277c
fpIndex
Payload 0x2d00 0x2bb4 0x2954

Conflicts

In order to merge 2 exploits into a single ISO there must be either:

We might also be able to force a non-conflict between 2 versions by making use of 2 different buffer overflows. That would need to be experimented with. Until then, here is a table for the versions with conflicting currentDiscBytePointer IFO offsets which we would need to be common controlled memory regions for:

Common controlled memory
3.04 + 3.10 Couldn't find any
3.04J + 3.04M

< 3.03

These firmwares don't use the same getDiscData stream reader API, instead they manually call getBuffer and then memcpy from that sectorBuffer somewhere else. They still contain the vulnerability, but as it occurs from memcpy of OOB memory into other OOB memory, it is not just immediately possible for the full memory range overflowed with to contain fully controlled contents.

Let's look at 3.02 specifically.

0x256668 - getBufferInternal
0x256888 - getBuffer

Searching calls to getBuffer, it's always a fixed number of sectors, 1 to 4, so as previously stated we can't just overflow straight into fpIndex with controlled contents as in > 3.02.

But, the buffer overflows definitely do still exist. The function at 0x23e560 is a nice self contained one:

long bufferOverflow(void) {
  long lVar1;
  
  lVar1 = getBuffer(s_VIDEO_TS.IFO_0090c210,(long)(int)DAT_013c7840,sectorBuffer,1,0);
  if (lVar1 == 0) {
    someLengthFromIFO = (ushort)sectorBuffer[0] * 0x100 + (ushort)sectorBuffer[1];
    DAT_013c7890 = ((long)(int)((uint)sectorBuffer[4] << 0x18) | (ulong)sectorBuffer[5] << 0x10) +
                   (ulong)sectorBuffer[6] * 0x100 + (ulong)sectorBuffer[7];
    memcpy(&PTR_DAT_013c7898,sectorBuffer + 8,(uint)someLengthFromIFO * 0xc);
    lVar1 = 0;
  }
  return lVar1;
}

The memcpy call can overwrite memory from 0x013c7898 to 0x148788C (0x013c7898 + 0xffff * 0xc). The buffer overflow we are triggering in all other exploits because it gives biggest size is at 0x240284:


      length2 = (ushort)sectorBuffer[uVar33 + 2] * 0x100 + (ushort)sectorBuffer[uVar33 + 3];
      length1 = (ushort)sectorBuffer[uVar33] * 0x100 + (ushort)sectorBuffer[uVar33 + 1];
      length3 = (ushort)sectorBuffer[uVar33 + 4] * 0x100 + (ushort)sectorBuffer[uVar33 + 5];
      DAT_013c9a2e = (ushort)sectorBuffer[uVar33 + 6] * 0x100 + (ushort)sectorBuffer[uVar33 + 7];
      memcpy(&DAT_013c9a30,sectorBuffer + uVar33 + 8,
             ((uint)length1 + (uint)length2 + (uint)length3) * 8);

fpIndex is at 0x13cfaca (leading to OOB call at 0x242f6c), and if we can set that to a controlled value we potentially have an exploit (if there's a good jump target).

fpIndex can be overwritten by either of the memcpy buffer overflows shown with a large enough size, but we're not corrupting it with data coming straight from disc; we only read at most 4 sectors (0x800 * 4) = 0x2000 into sectorBuffer, however we need to memcpy 0x609A bytes from sectorBuffer into 0x13c9a30 to overwrite fpIndex (0x13cfaca-0x13c9a30), so we'll be copying from uncontrolled OOB memory into fpIndex.

So, can we make that OOB memory contain controlled contents? Well, by making use of that buffer overflow, we can shift the question from "can we control fpIndex (0x13cfaca)", to "can we control sectorBuffer + 0x609A = 0x13D331A", since if we control that the memcpy will then copy into fpIndex from an address we can control the contents of.

Looking at all of the copies - maybe you will be lucky and find that it happens to line up that after a series of copies - some value you control ends up in fpIndex. Will need more time on it.