Page 5 of 6
Re: UmdImageCreator
Posted: Thu Oct 05, 2023 4:31 am
by sarami
I tried it. _sceUmdExecReadMKICmd() succeeded but bufMKI is all zero bytes except bufMKI[2].
Code: Select all
unsigned char bufMKI[448] = {};
bufMKI[2] = 8;
char* p = (char*)(0x08800000);
memset(p, 0x00, 0x8000);
sceKernelDcacheInvalidateRange(p, 0x4000);
res = _sceUmdExecReadMKICmd(pUmdDrive, bufMKI, 8, p);
Re: UmdImageCreator
Posted: Thu Oct 05, 2023 4:59 am
by Edness
I think the address has to be 0x1C0, it seems to be firmware hardcoded. sceUmdExecReadMKICmd() (and also sceUmdExecRead10Cmd()) both call a subroutine which contains a function named sceUmdManSPKGetMKI() - this always returns 0x1C0. And after that, it calls another d-cache function sceKernelDcacheWritebackInvalidateRange(0x1C0, 0x4000), arg0 coming from SPKGetMKI, and arg1 coming from 8 << 11, the 8 coming from ReadMKI's arg2.
Without a debugger to see what exactly it's doing, it's hard to know if those addresses are relocated by the system or not. However, could you try calling sceUmdManSPKGetMKI() on its own and print out what address it returns? Maybe this will give an answer whether you truly have to put 0x1C0 or not. (And you could likely use the output of that to set up the ReadMKI call.)
----------
This is unrelated, but I did a bit more research about the SCSI commands that umdman.prx has functions for. Some firmware revisions have functions that send the commands 0xA3 and 0xA4, but neither of them have any NIDs associated. And today I noticed what looks to be an array of whitelisted commands it can send. In addition to the FW NID map function I wrote a few replies back, it looks like it would allow commands 0x00, 0x23, 0x25, 0xA3, 0xA4, 0xB6, 0xBB, and vendor specific commands 0xF5, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD. None of these also have a specific NID-hashed function.
However, sceUmdExecReadCapacityCmd() seems to be the only function that allows putting your own command as arg0, followed by the UMD drive as arg1 of course. While I assume this is where you would normally put 0x23/0x25, I wonder if it would be possible to exploit and take advantage of this function to send other commands. Though there is no function that calls it in any firmware it looks like (checked 1.50, 3.52, 6.60), so knowing that it wants for arg2 and arg3 will need guesswork.
I've edited the 3.70-6.60 NID map to also include this function commented with "Any?"
Re: UmdImageCreator
Posted: Thu Oct 05, 2023 8:30 am
by sarami
Edness wrote:could you try calling sceUmdManSPKGetMKI() on its own and print out what address it returns?
p is 0x880f1240
Edness wrote:sceUmdExecReadCapacityCmd() seems to be the only function that allows putting your own command as arg0, followed by the UMD drive as arg1 of course.
Yes. I've already comfirmed that this func can be called and succeeded.
Code: Select all
unsigned char bufCapa[8] = {};
res = _sceUmdExecReadCapacityCmd(0x25, pUmdDrive, 8, bufCapa);
The result is here. (Dissidia 012: Duodecim Final Fantasy)
1st 4 bytes show total sectors. It matches redump db. 2nd 4 bytes show the block size in bytes. It's always 0x800.
Re: UmdImageCreator
Posted: Thu Oct 05, 2023 8:59 am
by Edness
sarami wrote:
p is 0x880f1240
Looks like that is in kernel module address space 0x88000000-0x8837FFFF,
per documentation.
This does make more sense than just plain 0x1C0, but now part of me wonders if this is a valid region of data that can be overwritten, or if this is just the offset of the module itself, indicating its base is at 0x880F1080. I am probably overthinking it, but do try the ReadMKI function with the SPKGetMKI address (if it allows you to write to kernel memory like that). At worst it'll just blank out assembly instructions of the module and crash
Also, at first I couldn't find any mention of this MKI thing anywhere on the internet, but I just now stumbled upon
an archived thread that mentions "UMD MKI" once. Doesn't say what it stands for, but it's something.
Re: UmdImageCreator
Posted: Thu Oct 05, 2023 10:25 am
by sarami
Edness wrote:I am probably overthinking it, but do try the ReadMKI function with the SPKGetMKI address (if it allows you to write to kernel memory like that). At worst it'll just blank out assembly instructions of the module and crash
The result is no error and no crash but buffer is all zero bytes except buffer[2].
Re: UmdImageCreator
Posted: Thu Oct 05, 2023 10:31 am
by Edness
Hmm, can you memcpy the 0x4000 or 0x8000 bytes of data back from the SPKGetMKI address? It likely wrote something there and left the buffer for the function arg alone. Normally it's supposed to just be a separate 5 byte buffer that's passed to the ReadMKI function anyway, so I'm not expecting much to be written there.
For good measure maybe also copy the data from the MKI address before memset'ing it to 00, to see if there's already something there.
Re: UmdImageCreator
Posted: Fri Oct 06, 2023 8:06 am
by sarami
Code: Select all
unsigned char bufSPK[0x4000] = {};
void* p1 = _sceUmdManSPKGetMKI();
memcpy(bufSPK, p1, 0x4000);
It crashed by memcpy.
Edness wrote:Normally it's supposed to just be a separate 5 byte buffer that's passed to the ReadMKI function anyway, so I'm not expecting much to be written there.
5 bytes = 40 bits. DVD has 40 bits key of CSS, so I've expected that UMD also has some kind of 40 bits key (media key?).
SPK is SPecial Key? SPecific Key?
Re: UmdImageCreator
Posted: Fri Oct 06, 2023 10:04 am
by Edness
sarami wrote:5 bytes = 40 bits. DVD has 40 bits key of CSS, so I've expected that UMD also has some kind of 40 bits key (media key?).
SPK is SPecial Key? SPecific Key?
Possible.
Another guess I have could be it's some form of Disc ID - Sony already has a unique ID for every disc on PS2 and PS3. (If not from the MKI command, maybe from another one.)
On PS2 the (DNAS) Disc ID is also 5 bytes long. And while currently on Redump only the first two bytes are removed due to being serialized/random, from my observations I'm pretty sure it's supposed to be the first three bytes (see
[PS2] Burnout Revenge (Europe, Australia) (En,Fr,De) as an example) followed by the region on the 4th byte (0x20 = Asia, 0x30 = USA, 0x40 = Europe etc.), making it 16.7 million unique Disc IDs for each game on PS2.
Likewise, PS3's Disc ID being 16 bytes long, the last 4 bytes are also removed for each entry, also followed by the region on the 5th byte (0x01 = Asia, 0x03 = USA, 0x04 = Europe etc.), making it theoretically 4.2 billion unique IDs per game.
With this in mind, I wouldn't be surprised if Sony also had some form of unique Disc ID for PSP, too. Although wouldn't the 0x08 written at buf[2] interfere with it?
Re: UmdImageCreator
Posted: Sat Oct 07, 2023 4:52 am
by sarami
Edness wrote:On PS2 the (DNAS) Disc ID is also 5 bytes long.
Edness wrote:PS3's Disc ID being 16 bytes long
How do we get it?
Re: UmdImageCreator
Posted: Sat Oct 07, 2023 7:29 am
by Edness
I'm not sure, your guess is as good as mine. It could be one of the 0xF0 commands, or it could be something completely different.
Another note, I noticed the SCSI command whitelist in older FW revisions normally has 3 x int32 values per element, the 3rd one always seemingly being null. However FW 1.50 actually uses that 3rd value as a pointer to a string with the original command name. (In newer FW like 6.60 the array is 2x int8.) The command names for 0x00-0xC0 are pretty standard besides DVD->UMD replacements, but the 0xF0 command names without any associated function/NID could be useful too.
Code: Select all
{0x00, 0x01}, // TEST_UNIT_READY
{0x03, 0x02}, // REQUEST_SENSE
{0x12, 0x02}, // INQUIRY
{0x1B, 0x01}, // START_STOP_UNIT
{0x1E, 0x01}, // PREVENT_ALLOW_MEDIA
{0x23, 0x02}, // READ_FORMAT_CAPACITIES
{0x25, 0x02}, // READ_UMD_CAPACITY
{0x28, 0x08}, // READ10
{0x2B, 0x01}, // SEEK
{0x34, 0x01}, // PREFETCH10
{0x46, 0x02}, // GET_CONFIGURATION
{0x4A, 0x02}, // GET_STAT_EVENT
{0x55, 0x04}, // MODE_SELECT10
{0x5A, 0x02}, // MODE_SENSE10
{0xAD, 0x02}, // READ_UMD_STRUCTURE
{0xB6, 0x04}, // SET_STREAMING
{0xBB, 0x01}, // SET_SPEED
{0xBD, 0x02}, // MECHANISM_STATUS
{0xF0, 0x02}, // DETECT_UMD_PSP
{0xF1, 0x08}, // READ_UMD_MKI
{0xF2, 0x02}, // REPORT_CACHE
{0xF3, 0x01}, // CLEAR_CACHE_INFO
{0xF4, 0x02}, // GET_MEDIA_INFO
{0xF5, 0x02}, // TEST
{0xF6, 0x01}, // SET_ACCESS_LIMIT
{0xF7, 0x01}, // SET_LOCK_LENGTH
{0xF8, 0x01}, // SET_AREA_LIMIT
{0xF9, 0x02}, // GET_ERROR_LOG
{0xFA, 0x02}, // TEST_PI
{0xFB, 0x04}, // TEST_PO
{0xFC, 0x02}, // GET_ADJUST_DATA
{0xFD, 0x04}, // SET_ADJUST_DATA