Difference between revisions of "Creport"

From Nintendo Switch Brew
Jump to navigation Jump to search
Line 91: Line 91:
 
nnMain:
 
nnMain:
 
* Two input arguments are now used+required, see above.
 
* Two input arguments are now used+required, see above.
* ...
+
* During init near the start of this func, u64 val0 is now written to x24+32.
 +
* A lot of new code was added.
 
* TID handling block was updated, see above.
 
* TID handling block was updated, see above.
 
* The check for <is_blacklisted> was changed from "if(val<=0)<branch>" to "if(val<1)<branch>".
 
* The check for <is_blacklisted> was changed from "if(val<=0)<branch>" to "if(val<1)<branch>".

Revision as of 02:46, 3 August 2017

This process is launched by NS when PM signals that there is a crashing process.

Creport takes a string containing a pid formatted in base10 as input, and generates an error report. This error report can later be sent to the cloud server by Eupld services.

[2.1.0+]: An additional input argument string is now used. Only the first byte is used: inarg_flag = argv[1][0]; This is compared with '1' only with the below titleID code, and near the end of nnMain().

Crash dumping

It uses the svcDebugActiveProcess to start a debug-session for the pid. It loops svcGetDebugEvent to fetch all debug events.

It has a event buffer of 128 u64's that starts with "CREP\x01\x00\x00\x00".

It only cares about type EXCEPTION and ATTACH_PROCESS events.

For ATTACH_PROCESS events it saves the title-id of the crashed process (this is the first u64 of the type-specific data), and a flag whether to dump stack.

For EXCEPTION events, it adds records to the buffer.

Each exception record starts with 2x u64's: exception type, and exception address.

Then depending on exception type it stores:

  • UNDEFINED_INSTRUCTION (0): Always (u64) 0.
  • PREFETCH_ABORT (1): Always (u64) 0.
  • DATA_ABORT (2): (u64) Fault register.
  • UNALIGNED_ACCESS (3): (u64) Fault register.
  • UNDEFINED_SYSCALL (8): (u64) Syscall id.
  • ? (9): Always (u64) 0.

For all exceptions, it then adds more data from svcGetDebugThreadParam/svcGetDebugThreadContext. "Usually" (when is this not the case?), this data includes a size u64 for the register dump region + the values of all general purpose registers+SP and PC, as well as 0x80 of stack. This reads the flag from ATTACH_PROCESS to determine whether to read 0x10 bytes using svcReadDebugProcessMemory.

All other events (USER_BREAK, etc) don't store any extra data except type and address.

After it has fetched all events, if it didn't encounter USER_BREAK it constructs an error report:

  • Field10 "ErrorCode": (String) Error-code string formatted with "%04d-%04d".
  • Field115 "ProgramId": (String) Title-id snprintf'ed as "%08llx".
  • Field116 "AbortFlag": (Bool) 0.

It does *not* add the event buffer to the report(blacklisted) if title-id is any of the following(swkbd and all web-applets except offline-applet):

  • 0100000000001008
  • 010000000000100A
  • 010000000000100B
  • 0100000000001010
  • 0100000000001011

[2.1.0+] It also blacklists the creport-sysmodule title-id. Then, if inarg_flag(see above) is set to '1', all title-ids are blacklisted except for the following whitelist:

  • 0x0100704000B3A000 "Snipperclips" (Game)
  • 0x01007EF00011E000 "The Legend of Zelda: Breath of the Wild"
  • 0x01009B500007C000 "ARMS"
  • 0x0100D87002EE0000 "Snipperclips - Cut it out, together!"
  • 0x0100F8F0000A2000 "Splatoon 2" (EUR)
  • 0x010000A00218E000 "Splatoon 2 Global Testfire"
  • 0x01000320000CC000 "1-2 Switch"
  • 0x0100152000022000 "Mario Kart 8 Deluxe"
  • 0x01003BC0000A0000 "Splatoon 2" (USA)
  • 0x01003C700009C000 "Splatoon 2" (JPN)

This is probably because of privacy concerns (software keyboard + browser could contain passwords and personal info).

For all other title-ids, it generates a random AES-128 key and CTR using csrng.

It encrypts the entire event buffer with this AES key and CTR. Then it encrypts the key-iv-pair using RSA-PSS with a hardcoded pubkey and exponent 0x10001.

These are added to the error report:

  • Field206 "EncryptionKey": (Raw) RSA-encrypted AES-key.
  • Field207 "EncryptedExceptionInfo": (Raw) Encrypted crash-info.

Thus you need the private key to decrypt the crash dump.

Finally, the error report is sent to "erpt:c" cmd1.

It uses "ns:dev" to terminate the pid. If certain checks pass, then it throws the following fatal-err depending on exception type:

  • 0 -> 0xA8
  • 1 -> 0x2A8
  • 2 -> 0x4A8,
  • 3 -> 0x6A8,
  • 6 -> No fatal-err
  • 8 -> 0x10A8
  • Default: 0x4A2

2.1.0

Exactly the following code was changed:

  • nnMain(): Updated.
  • L_1ee0(prev ver L_1c90): Updated.
  • L_ad34: New func, svcQueryDebugProcessMemory.
  • L_e290: New func. "L_12cf0(<inparams>); return inx0;"
  • L_12cf0: New func. Only called by L_e290.

nnMain:

  • Two input arguments are now used+required, see above.
  • During init near the start of this func, u64 val0 is now written to x24+32.
  • A lot of new code was added.
  • TID handling block was updated, see above.
  • The check for <is_blacklisted> was changed from "if(val<=0)<branch>" to "if(val<1)<branch>".
  • The code block at the very end of this func was updated.
    • Prev code: if(<loadedval> != 1)return; New code: if(<loadedval> != 1)<jump over the two following func calls which are the same as prev ver>
    • Following the two funcs mentioned above, prev code: if(<loadedval> == 1 && (u8 *(ptr+1) & 1) == 0)<call func>; return; New code: if(inarg_flag != '1' && (u8 *(ptr+1) & 1) == 0 && ((u8 *(ptr+0) ^ 0x1) & 0x1) == 0)<call func>; return;
    • <call func> here is throw_fatalerr(ptr+4). The above second block basically changed the conditions required for throwing fatal-error. For example, fatal-error is no longer thrown when applications crash.