Hacking RPC Execute Assembly

BullyWiiPlaza

Nintendo Hacking <3
OP
Member
Joined
Aug 2, 2014
Messages
1,932
Trophies
0
XP
2,433
Country
Germany
For executing assembly in the form of a char array I wrote the following code:
Code:
#define ASSEMBLY_BUFFER_SIZE 0x190
Code:
void receiveString(struct pygecko_bss_t *bss,
                   int clientfd,
                   char *stringBuffer,
                   int bufferSize) {
    // Receive the string length
    char lengthBuffer[4] = {0};
    int ret = recvwait(bss, clientfd, lengthBuffer, 4);
    ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (string length)")
    int stringLength = ((int *) lengthBuffer)[0];

    if (stringLength >= 0 && stringLength <= bufferSize) {
        // Receive the actual string
        ret = recvwait(bss, clientfd, stringBuffer, stringLength);
        ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (string)")
    } else {
        OSFatal("String buffer size exceeded");
    }
}
Code:
case COMMAND_EXECUTE_ASSEMBLY: {
    char assemblyBuffer[ASSEMBLY_BUFFER_SIZE] = {0};

    // Receive the assembly
    receiveString(bss, clientfd, assemblyBuffer, ASSEMBLY_BUFFER_SIZE);

    // Execute the assembly
    void (*function)() = (void *) assemblyBuffer;
    function();

    break;
}
The client sends the length of the assembly bytes and the assembly bytes themselves:
Code:
public void executeAssembly(byte[] assembly) throws Exception
{
    int assemblyLength = assembly.length;
    if (assemblyLength <= 0 || assemblyLength % 4 != 0)
    {
        throw new IllegalStateException("Bad assembly bytes length: " + assemblyLength);
    }

    assembly = Assembler.forceReturnStatement(assembly);

    try (CloseableReentrantLock ignored = reentrantLock.acquire())
    {
        sendCommand(Command.EXECUTE_ASSEMBLY);
        dataSender.writeInt(assembly.length);
        dataSender.write(assembly);
        dataSender.flush();
    }
}
When I use this e.g. like with the following assembly:
Code:
byte[] bytes = Assembler.assembleBytes("lis r12, 0x1200\n" +
        "ori r12, r12, 0x0000\n" +
        "li r11, 0x1337\n" +
        "stw r11, 0 (r12)");
executeAssembly(bytes);
The console crashes with an Exception ISI:
z9d1OvA.jpg

The code dump shows the assembly I gave it to execute and how a blr instruction is added at the end so the code returns to the caller. Furthermore, the link register LR contains an invalid address which might have been the reason for the crash.

Why is this happening and how to fix it? I guess the intention is clear: I want to send over some bytes and have them execute via the TCP Gecko Installer thread and continue its execution right after.

@NWPlayer123
@QuarkTheAwesome
@FIX94
@dimok
@Maschell
@CosmoCortney
 

QuarkTheAwesome

Working for Hugs
Member
Joined
Apr 19, 2015
Messages
942
Trophies
1
Age
21
Location
Stuck in the PowerPC
XP
3,107
Country
Australia
For executing assembly in the form of a char array I wrote the following code:
Code:
#define ASSEMBLY_BUFFER_SIZE 0x190
Code:
void receiveString(struct pygecko_bss_t *bss,
                   int clientfd,
                   char *stringBuffer,
                   int bufferSize) {
    // Receive the string length
    char lengthBuffer[4] = {0};
    int ret = recvwait(bss, clientfd, lengthBuffer, 4);
    ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (string length)")
    int stringLength = ((int *) lengthBuffer)[0];

    if (stringLength >= 0 && stringLength <= bufferSize) {
        // Receive the actual string
        ret = recvwait(bss, clientfd, stringBuffer, stringLength);
        ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (string)")
    } else {
        OSFatal("String buffer size exceeded");
    }
}
Code:
case COMMAND_EXECUTE_ASSEMBLY: {
    char assemblyBuffer[ASSEMBLY_BUFFER_SIZE] = {0};

    // Receive the assembly
    receiveString(bss, clientfd, assemblyBuffer, ASSEMBLY_BUFFER_SIZE);

    // Execute the assembly
    void (*function)() = (void *) assemblyBuffer;
    function();

    break;
}
The client sends the length of the assembly bytes and the assembly bytes themselves:
Code:
public void executeAssembly(byte[] assembly) throws Exception
{
    int assemblyLength = assembly.length;
    if (assemblyLength <= 0 || assemblyLength % 4 != 0)
    {
        throw new IllegalStateException("Bad assembly bytes length: " + assemblyLength);
    }

    assembly = Assembler.forceReturnStatement(assembly);

    try (CloseableReentrantLock ignored = reentrantLock.acquire())
    {
        sendCommand(Command.EXECUTE_ASSEMBLY);
        dataSender.writeInt(assembly.length);
        dataSender.write(assembly);
        dataSender.flush();
    }
}
When I use this e.g. like with the following assembly:
Code:
byte[] bytes = Assembler.assembleBytes("lis r12, 0x1200\n" +
        "ori r12, r12, 0x0000\n" +
        "li r11, 0x1337\n" +
        "stw r11, 0 (r12)");
executeAssembly(bytes);
The console crashes with an Exception ISI:
z9d1OvA.jpg

The code dump shows the assembly I gave it to execute and how a blr instruction is added at the end so the code returns to the caller. Furthermore, the link register LR contains an invalid address which might have been the reason for the crash.

Why is this happening and how to fix it? I guess the intention is clear: I want to send over some bytes and have them execute via the TCP Gecko Installer thread and continue its execution right after.

@NWPlayer123
@QuarkTheAwesome
@FIX94
@dimok
@Maschell
@CosmoCortney

I'm pretty sure MEM2 isn't executable by default. You'll either need to read the data into somewhere executable (HBL area?) or make MEM2 executable with a BAT.
The crash is because the PowerPC has separate memory mappings for data and instructions. If an area is mapped for data but not instructions it essentially becomes non-executable, since trying to execute it is trying to run instructions at an unmapped address.
 
  • Like
Reactions: BullyWiiPlaza

BullyWiiPlaza

Nintendo Hacking <3
OP
Member
Joined
Aug 2, 2014
Messages
1,932
Trophies
0
XP
2,433
Country
Germany
I'm pretty sure MEM2 isn't executable by default. You'll either need to read the data into somewhere executable (HBL area?) or make MEM2 executable with a BAT.
The crash is because the PowerPC has separate memory mappings for data and instructions. If an area is mapped for data but not instructions it essentially becomes non-executable, since trying to execute it is trying to run instructions at an unmapped address.
Alright, what would be a good solution code-wise? mmap() does not exist so I'm not sure how to make it executable in a generic fashion.
 

BullyWiiPlaza

Nintendo Hacking <3
OP
Member
Joined
Aug 2, 2014
Messages
1,932
Trophies
0
XP
2,433
Country
Germany
Nevermind. I got it to work. The trick was like @QuarkTheAwesome said, to write the assembly to an executable data section and then executing it from there:
Code:
case COMMAND_EXECUTE_ASSEMBLY: {
    // Receive the assembly
    receiveString(bss, clientfd, (char *) buffer, DATA_BUFFER_SIZE);

    // Write the assembly to an executable code region
    int destinationAddress = 0x10000000 - DATA_BUFFER_SIZE;
    pygecko_memcpy((unsigned char *) destinationAddress, buffer, DATA_BUFFER_SIZE);

    // Execute the assembly from there
    void (*function)() = (void (*)()) destinationAddress;
    function();

    // Clear the memory contents again
    memset((void *) buffer, 0, DATA_BUFFER_SIZE);
    pygecko_memcpy((unsigned char *) destinationAddress, buffer, DATA_BUFFER_SIZE);

    break;
}
L33t h4x0r way of poking a value :D
74f96sc7.png
 
Last edited by BullyWiiPlaza,
General chit-chat
Help Users
  • Gift
  • Veho @ Veho:
    Also known as non-fuckable tokens.
    Gift
  • katebeyond @ katebeyond:
    Monster Hunter Stories 2 Save
    Does anyone have a 100% complete storyline save? pls
    Gift
  • Gift
  • Psionic Roshambo @ Psionic Roshambo:
    Literally hate 99% of the pumpkin spice stuff I have tried
    Gift
  • Gift
  • SG854 @ SG854:
    Nintendo Online Expansion sucks
    Gift
  • SG854 @ SG854:
    Graphical glitches, slowdows that wasn't part of original hardware, tinny audio sound. Crappy laggy online play.
    Gift
  • SG854 @ SG854:
    For $30 bucks I would expect top tier quality emulation not this crappy version we got
    Gift
  • Flame @ Flame:
    @SG854 Patience you should have be young padawan and wait and see for review
    Gift
  • SG854 @ SG854:
    Already saw a review and it sucks
    Gift
  • Gift
  • SG854 @ SG854:
    A bunch I different people I saw and laggy audio online play is a common occurrence
    Gift
  • SG854 @ SG854:
    Here's another video fog isn't being displayed properly on several games. Nintendo life also reported this. Water Temple in oot water reflection isn't emulated properly either the whole point of the gimmick of that room. Graphical glitches and poor emulation shouldn't be present at $30 bucks
    Gift
  • Gift
  • SG854 @ SG854:
    You can't save ghost data either in Mario Kart 64. Wasn't an issue on VC for Wii and Wii U.
    Gift
  • SG854 @ SG854:
    Even if they fix these issues I'm still not buying it. $30 for drip fed n64 games is fucking retarded. Their online service is still shit.
    Gift
  • Veho @ Veho:
    Youtube keeps pushing the Eternals trailer as the #1 recommendation. Fucking give it a rest already.
    Gift
  • Dakitten @ Dakitten:
    they really want you to know it is out there and is totes gonna be the bestest movie nobody ever asked for
    Gift
  • Dakitten @ Dakitten:
    until spider man a month afterward which will bury it into obscurity, anyways
    Gift
  • mthrnite @ mthrnite:
    We need some serious Warlock action if you ask me, not just random cocoons n'shit
    Gift
  • mthrnite @ mthrnite:
    Hulk+Warlock, that's what I want
    Gift
  • mthrnite @ mthrnite:
    wtf they turned eternals into a movie is beyond me
    Gift
  • mthrnite @ mthrnite:
    money woulda been better spent doing a decent Inhumans origin story
    Gift
  • Veho @ Veho:
    Hey mthrnite will you watch the new Dune?
    Gift
    Veho @ Veho: Hey mthrnite will you watch the new Dune?