Spoof Serversided Position based on KMP Section Offset [Sponge]
#1
Spoof Serversided Position based on KMP Section Offset [Sponge]

Spoofs your coordinates sent to other players based on the Section Offset you specify.

The first code cycles one Section entry per execution and resets after the final entry, whilst the second code chooses a random Section entry each time the code executes.

XX = Section Offset
YY = Section Offset minus 0x8, then divided by 0x2


The following sections are usable as they have 3D Position Vectors:

0x8 - Kart Point (KTPT)
0x10 - Enemy Point (ENPT)
0x18 - Item Point (ITPT)
0x28 - Geo Object (GOBJ)
0x2C - Area (AREA)
0x30 - Camera (CAME)
0x34 - Jugem Point (JGPT)
0x38 - Cannon Point (CNPT)
0x40 - Mission Success Point (MSPT)

Note: Code 1 uses the byte at address 0x80001600. Ensure no other codes read or write to this address.

Code 1:

PAL
C258CBA0 00000017
7C8B2378 3D80809C
818CD6E8 806C00XX
81830008 3C809000
7C0C2040 40800008
8183000C 48000025
1C0810FF 140810FF
140810FF 14FF04FF
3C0C300C 48141C08
1C080CFF 1C080000
7CE802A6 388000YY
38A40001 7CA728AE
280500FF 41820050
7C8720AE 7D876378
7D8C2A14 3CC08000
A0661600 A0E70004
28070000 41820030
38630001 7C033840
41800008 38600000
B0661600 7C6321D6
7C0C1C6E D00100F0
C00C0004 D00100F8
C00C0008 7D645B78
7FA3EB78 00000000

NTSC-U
C258637C 00000017
7C8B2378 3D80809C
818C8F28 806C00XX
81830008 3C809000
7C0C2040 40800008
8183000C 48000025
1C0810FF 140810FF
140810FF 14FF04FF
3C0C300C 48141C08
1C080CFF 1C080000
7CE802A6 388000YY
38A40001 7CA728AE
280500FF 41820050
7C8720AE 7D876378
7D8C2A14 3CC08000
A0661600 A0E70004
28070000 41820030
38630001 7C033840
41800008 38600000
B0661600 7C6321D6
7C0C1C6E D00100F0
C00C0004 D00100F8
C00C0008 7D645B78
7FA3EB78 00000000

NTSC-J
C258C520 00000017
7C8B2378 3D80809C
818CC748 806C00XX
81830008 3C809000
7C0C2040 40800008
8183000C 48000025
1C0810FF 140810FF
140810FF 14FF04FF
3C0C300C 48141C08
1C080CFF 1C080000
7CE802A6 388000YY
38A40001 7CA728AE
280500FF 41820050
7C8720AE 7D876378
7D8C2A14 3CC08000
A0661600 A0E70004
28070000 41820030
38630001 7C033840
41800008 38600000
B0661600 7C6321D6
7C0C1C6E D00100F0
C00C0004 D00100F8
C00C0008 7D645B78
7FA3EB78 00000000

NTSC-K
C257ABF8 00000017
7C8B2378 3D80809B
818CBD28 806C00XX
81830008 3C809000
7C0C2040 40800008
8183000C 48000025
1C0810FF 140810FF
140810FF 14FF04FF
3C0C300C 48141C08
1C080CFF 1C080000
7CE802A6 388000YY
38A40001 7CA728AE
280500FF 41820050
7C8720AE 7D876378
7D8C2A14 3CC08000
A0661600 A0E70004
28070000 41820030
38630001 7C033840
41800008 38600000
B0661600 7C6321D6
7C0C1C6E D00100F0
C00C0004 D00100F8
C00C0008 7D645B78
7FA3EB78 00000000


Code 2:

PAL
C258CBA0 00000016
7C8B2378 3D80809C
818CD6E8 806C00XX
81830008 3C809000
7C0C2040 40800008
8183000C A08C0004
28040000 41820074
38600000 3CE0800F
60E72EE0 7CE903A6
4E800421 48000025
1C0810FF 140810FF
140810FF 14FF04FF
3C0C300C 48141C08
1C080CFF 1C080000
7CE802A6 388000YY
38C40001 7CC730AE
280600FF 41820024
7D8C3214 7C8720AE
7C6321D6 7C0C1C6E
D00100F0 C00C0004
D00100F8 C00C0008
7D645B78 7FA3EB78
60000000 00000000

NTSC-U
C258637C 00000016
7C8B2378 3D80809C
818C8F28 806C00XX
81830008 3C809000
7C0C2040 40800008
8183000C A08C0004
28040000 41820074
38600000 3CE0800F
60E72E40 7CE903A6
4E800421 48000025
1C0810FF 140810FF
140810FF 14FF04FF
3C0C300C 48141C08
1C080CFF 1C080000
7CE802A6 388000YY
38C40001 7CC730AE
280600FF 41820024
7D8C3214 7C8720AE
7C6321D6 7C0C1C6E
D00100F0 C00C0004
D00100F8 C00C0008
7D645B78 7FA3EB78
60000000 00000000

NTSC-J
C258C520 00000016
7C8B2378 3D80809C
818CC748 806C00XX
81830008 3C809000
7C0C2040 40800008
8183000C A08C0004
28040000 41820074
38600000 3CE0800F
60E72E00 7CE903A6
4E800421 48000025
1C0810FF 140810FF
140810FF 14FF04FF
3C0C300C 48141C08
1C080CFF 1C080000
7CE802A6 388000YY
38C40001 7CC730AE
280600FF 41820024
7D8C3214 7C8720AE
7C6321D6 7C0C1C6E
D00100F0 C00C0004
D00100F8 C00C0008
7D645B78 7FA3EB78
60000000 00000000

NTSC-K
C257ABF8 00000016
7C8B2378 3D80809B
818CBD28 806C00XX
81830008 3C809000
7C0C2040 40800008
8183000C A08C0004
28040000 41820074
38600000 3CE0800F
60E72F58 7CE903A6
4E800421 48000025
1C0810FF 140810FF
140810FF 14FF04FF
3C0C300C 48141C08
1C080CFF 1C080000
7CE802A6 388000YY
38C40001 7CC730AE
280600FF 41820024
7D8C3214 7C8720AE
7C6321D6 7C0C1C6E
D00100F0 C00C0004
D00100F8 C00C0008
7D645B78 7FA3EB78
60000000 00000000


Code 1 Source:
Code:
#Inject at 8058CBA0 PAL
#Inject at 8058637C NTSC-U
#Inject at 8058C520 NTSC-J
#Inject at 8057ABF8 NTSC-K

.set currentEntry, 0x80001600
.set region, '' # Specify which region to compile for
.set SectionOffset, 0xXX # Specify which Section Offset we want to load
.if    (region == 'P' || region == 'p') # RMCP
        .set RacePointer, 0x809BD6E8
        .set UtilRandom, 0x800F2EE0
.elseif (region == 'E' || region == 'e' || region == 'U' || region == 'u') # RMCE
        .set RacePointer, 0x809B8F28
        .set UtilRandom, 0x800F2E40
.elseif (region == 'J' || region == 'j') # RMCJ
        .set RacePointer, 0x809BC748
        .set UtilRandom, 0x800F2E00
.elseif (region == 'K' || region == 'k') # RMCK
        .set RacePointer, 0x809ABD28
        .set UtilRandom, 0x800F2F58
.else # Invalid Region
        .abort
.endif

  mr r11, r4 # Backup r4 safely so we can restore it later on
  lis r12, RacePointer@ha
  lwz r12, RacePointer@l(r12)
  lwz r3, SectionOffset(r12) # Load the section offset we specified
  lwz r12, 0x8(r3)
  lis r4, 0x9000
  cmplw r12, r4 # Check if r12 has the mem90 pointer loaded
  bge notAREA
  lwz r12, 0xC(r3) # All other Sections load from 0x8 whilst AREA loads from 0xC

  notAREA:
  bl offsetLength # Use the bl trick to setup the lengths of each Section and distance from the first Position Vector

  .long 0x1C0810FF
  .long 0x140810FF
  .long 0x140810FF
  .long 0x14FF04FF
  .long 0x3C0C300C
  .long 0x48141C08
  .long 0x1C080CFF
  .long 0x1C080000

  offsetLength:
  mflr r7
  li r4, ((SectionOffset- 0x8) / 0x2)
  addi r5, r4, 0x1
  lbzx r5, r7, r5
  cmplwi r5, 0xFF
  beq exit # Exit the code early if r5 is 0xFF, these Sections lack Position Vectors
  lbzx r4, r7, r4
  mr r7, r12
  add r12, r12, r5 # Add the value from r5 to align r12 with the first Position Vector
  lis r6, currentEntry@ha
  lhz r3, currentEntry@l(r6) # Load the last stored entry
  lhz r7, 0x4(r7) # Load the number of entries in the specified section
  cmplwi r7, 0
  beq exit # Exit code early if the Section lacks any entries
  addi r3, r3, 1
  cmplw r3, r7
  blt validEntry # Cycle through each entry until we reach the final entry, then reset the counter
  li r3, 0

  validEntry:
  sth r3, currentEntry@l(r6) # Store the entry for the next time the code executes
  mullw r3, r3, r4 # Load entry length into r4 and multiply it with the random number from the call earlier
  lfsux f0, r12, r3 # Load and store the position of the entry to our sent coordinates
  stfs f0, 0xF0(r1)
  lfs f0, 0x4(r12)
  stfs f0, 0xF8(r1)
  lfs f0, 0x8(r12)

  exit:
  mr        r4, r11 # Restore r4 back from r11
  mr        r3, r29 # Default Instruction


Code 2 source:
Code:
#Inject at 8058CBA0 PAL
#Inject at 8058637C NTSC-U
#Inject at 8058C520 NTSC-J
#Inject at 8057ABF8 NTSC-K


.set region, '' # Specify which region to compile for
.set SectionOffset, 0xXX # Specify which Section Offset we want to load
.if    (region == 'P' || region == 'p') # RMCP
        .set RacePointer, 0x809BD6E8
        .set UtilRandom, 0x800F2EE0
.elseif (region == 'E' || region == 'e' || region == 'U' || region == 'u') # RMCE
        .set RacePointer, 0x809B8F28
        .set UtilRandom, 0x800F2E40
.elseif (region == 'J' || region == 'j') # RMCJ
        .set RacePointer, 0x809BC748
        .set UtilRandom, 0x800F2E00
.elseif (region == 'K' || region == 'k') # RMCK
        .set RacePointer, 0x809ABD28
        .set UtilRandom, 0x800F2F58
.else # Invalid Region
        .abort
.endif

  mr        r11, r4 # Backup r4 safely so we can restore it later on
  lis r12, RacePointer@ha
  lwz r12, RacePointer@l(r12)
  lwz r3, SectionOffset (r12) # Load the section offset we specified
  lwz r12, 0x8(r3)
  lis r4, 0x9000
  cmplw r12, r4 # Check if r12 has the mem90 pointer loaded
  bge notAREA
  lwz r12, 0xC(r3) # All other Sections load from 0x8 whilst AREA loads from 0xC

  notAREA:
  lhz r4, 0x4(r12) # Load the number of entries in the specified section
  cmplwi r4, 0
  beq exit # Exit code early if the Section lacks any entries
  li        r3, 0
  lis r7, UtilRandom@ha
  ori r7, r7, UtilRandom@l
  mtctr r7
  bctrl # Call UtilRandom, the result will be placed in r3

  bl offsetLength # Use the bl trick to setup the lengths of each Section and distance from the first Position Vector

  .long 0x1C0810FF
  .long 0x140810FF
  .long 0x140810FF
  .long 0x14FF04FF
  .long 0x3C0C300C
  .long 0x48141C08
  .long 0x1C080CFF
  .long 0x1C080000

  offsetLength:
  mflr r7
  li        r4, ((SectionOffset- 0x8) / 0x2)
  addi r6, r4, 0x1
  lbzx r6, r7, r6
  cmplwi r6, 0xFF
  beq exit # Exit the code early if r6 is 0xFF, these Sections lack Position Vectors
  add r12, r12, r6 # Add the value from r6 to align r12 with the first Position Vector
  lbzx r4, r7, r4
  mullw r3, r3, r4 # Load entry length into r4 and multiply it with the random number from the call earlier

  lfsux f0, r12, r3 # Load and store the position of the entry to our sent coordinates
  stfs f0, 0xF0(r1)
  lfs f0, 0x4(r12)
  stfs f0, 0xF8(r1)
  lfs f0, 0x8(r12)

  exit:
  mr        r4, r11 # Restore r4 back from r11
  mr        r3, r29 # Default Instruction
Reply
#2
Nice work.
Reply
#3
I realized after posting this that I originally wrote this code to work with only one type of Section and as a result it would null pointer if you attempted to use any other Section Offset. I've updated the code to fix this issue, made it so the section specified uses the correct size and also disabled the spoofing if data is missing from the Section.
Reply
#4
Updated the code again. I've added a variant of the code that will cycle through each entry based on the specified Section rather than choosing a random entry.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)