Hacking Replacing (Disk) Files

BullyWiiPlaza

Nintendo Hacking <3
OP
Member
Joined
Aug 2, 2014
Messages
1,932
Trophies
0
XP
2,477
Country
Germany
For the TCP Gecko Installer I tried to implement a function to replace files on games. However, I'm getting an ACCESS_ERROR when calling FSOpenFile():
Code:
case COMMAND_REPLACE_FILE: {
    // Receive the file path
    char file_path[FS_MAX_FULLPATH_SIZE] = {0};
    receiveString(bss, clientfd, file_path, FS_MAX_FULLPATH_SIZE);

    considerInitializingFileSystem();

    // Create an empty file for writing. Its contents will be erased
    int handle;
    int status = FSOpenFile(client, commandBlock, file_path, "w", &handle, FS_RET_ALL_ERROR);

    if (status == FS_STATUS_OK) {
        // Send the OK status
        ((int *) buffer)[0] = status;
        ret = sendwait(bss, clientfd, buffer, 4);
        ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (OK status)")

        // Set the file handle position to the beginning
        ret = FSSetPosFile(client, commandBlock, handle, 0, FS_RET_ALL_ERROR);
        ASSERT_FUNCTION_SUCCEEDED(ret, "FSSetPosFile")

        // Allocate the file bytes buffer
        unsigned int file_buffer_size = 0x2000;
        char *fileBuffer = (char *) OSAllocFromSystem(file_buffer_size, FS_IO_BUFFER_ALIGN);
        ASSERT_ALLOCATED(fileBuffer, "File buffer")

        // Send the maximum file buffer size
        ret = sendwait(bss, clientfd, &file_buffer_size, 4);
        ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (maximum file buffer size)")

        while (true) {
            // Receive the data bytes length
            unsigned int dataLength;
            ret = recvwait(bss, clientfd, &dataLength, 4);
            ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (File bytes length)")
            ASSERT_MAXIMUM_HOLDS(file_buffer_size, dataLength, "File buffer overrun attempted")

            if (dataLength > 0) {
                // Receive the data
                ret = recvwait(bss, clientfd, fileBuffer, dataLength);
                ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (File buffer)")

                // Write the data (and advance file handle position implicitly)
                ret = FSWriteFile(client, commandBlock, fileBuffer, 1,
                                  dataLength, handle, 0, FS_RET_ALL_ERROR);
                ASSERT_FUNCTION_SUCCEEDED(ret, "FSWriteFile")
            } else {
                // Done with receiving the new file
                break;
            }
        }

        /*// Flush the file back
        ret = FSFlushFile(client, commandBlock, handle, FS_RET_ALL_ERROR);
        CHECK_FUNCTION_FAILED(ret, "FSFlushFile")*/

        // Close the file
        ret = FSCloseFile(client, commandBlock, handle, FS_RET_ALL_ERROR);
        ASSERT_FUNCTION_SUCCEEDED(ret, "FSCloseFile")

        // Free the file buffer
        OSFreeToSystem(fileBuffer);
    } else {
        // Send the status
        ((int *) buffer)[0] = status;
        ret = sendwait(bss, clientfd, buffer, 4);
        ASSERT_FUNCTION_SUCCEEDED(ret, "sendwait (status)")
    }

    break;
}
Client code in Java:
Code:
public FileSystemStatus replaceFile(String remoteFilePath, String localFilePath) throws IOException
{
    // Read the file bytes
    Path localFile = Paths.get(localFilePath);
    byte[] fileBytes = Files.readAllBytes(localFile);

    try (CloseableReentrantLock ignored = reentrantLock.acquire())
    {
        // Send the command and remote file path
        sendCommand(Command.REPLACE_REMOTE_FILE);
        writeString(remoteFilePath);
        dataSender.flush();

        FileSystemStatus status = readFileSystemStatus();

        // Continue if the file has been opened successfully
        if (status == FileSystemStatus.OK)
        {
            sendFileBytes(fileBytes);
        }

        return status;
    }
}

private void sendFileBytes(byte[] fileBytes) throws IOException
{
    int maximumChunkSize = dataReceiver.readInt();
    int fileBytesIndex = 0;

    // Send the file bytes in chunks
    while (fileBytesIndex < fileBytes.length)
    {
        int chunkSize = fileBytes.length - fileBytesIndex;

        if (chunkSize > maximumChunkSize)
        {
            chunkSize = maximumChunkSize;
        }

        // Send the current chunk size
        dataSender.writeInt(chunkSize);
        sendPartialBytes(fileBytes, fileBytesIndex, chunkSize);
        dataSender.flush();

        fileBytesIndex += chunkSize;
    }

    // Let the server know that we're done
    dataSender.writeInt(0);
    dataSender.flush();
}

private void sendPartialBytes(byte[] bytes, int startingIndex, int length) throws IOException
{
    byte[] sendBytes = new byte[length];
    System.arraycopy(bytes, startingIndex, sendBytes, 0, length);
    dataSender.write(sendBytes);
}
In case you're wondering, Cafiine does not actually replace files the same way I'm trying to. It only fools the Wii U into pulling the files from the network instead of the disk. However, I'm trying to just replace the file so the replacement file is being used from now on instead without requesting it over the network over and over again. I'm not sure if this is even possible since the SDK says this about the error message:
Code:
Access mode is invalid (e.g. specified "r+" for read-only media).
It might mean that disks just aren't writable (I'm using the digital version though) but isn't there maybe a way to do it? This project might help as well. Thanks :)

@dimok
@QuarkTheAwesome
@Maschell
@FIX94
@wj44
@NWPlayer123
 
Last edited by BullyWiiPlaza,

wj44

Well-Known Member
Member
Joined
Jun 18, 2015
Messages
477
Trophies
0
XP
506
Country
Gambia, The
If you really want to replace the file you either need to use libiosuhax or the MCPCopyFile Command(eShop games only). Alternativly You can just write the file to the sd and open It everywhere with libiosuhax.
 
  • Like
Reactions: BullyWiiPlaza

BullyWiiPlaza

Nintendo Hacking <3
OP
Member
Joined
Aug 2, 2014
Messages
1,932
Trophies
0
XP
2,477
Country
Germany
If you really want to replace the file you either need to use libiosuhax
Wouldn't that be permanent? A temporary replacement would be better I guess since FTPiiu everywhere is probably best suited for permanent replacements. How would go about using libiosuhax to replace the file(s)?
Usually odd03 has the content. Some games have content on odd04. The data you get from there is /code /content /meta, as required by loadiine.
The code should look similar to this then?
Code:
// initialize IOSUHAX
int res = IOSUHAX_Open();

// initialize FSA fd
int fsaFd = IOSUHAX_FSA_Open();

// mount "/dev/odd03" to "/vol/storage_virt_odd" and bind it to our virt PPC path "odd:/"
// if 3rd parameter is NULL it only binds the /vol path (e.g. /vol/system)  to our virt PPC path
res = mount_fs("odd", fsaFd, "/dev/odd03", "/vol/storage_virt_odd");

// Open the file, write and close it again
IOSUHAX_FSA_OpenFile(fsaFd, systemXmlPath, "wb", &slcFd);
IOSUHAX_FSA_WriteFile(fsaFd, data, size, cnt, pFile, flags);
IOSUHAX_FSA_CloseFile(fsaFd, slcFd);
// ...
Haxchi makes a nice example of writing with iosuhax :P
 
Last edited by BullyWiiPlaza,
  • Like
Reactions: KiiWii

wj44

Well-Known Member
Member
Joined
Jun 18, 2015
Messages
477
Trophies
0
XP
506
Country
Gambia, The
Wouldn't that be permanent? A temporary replacement would be better I guess since FTPiiu everywhere is probably best suited for permanent replacements. How would go about using libiosuhax to replace the file(s)?

The code should look similar to this then?
Code:
// initialize IOSUHAX
int res = IOSUHAX_Open();

// initialize FSA fd
int fsaFd = IOSUHAX_FSA_Open();

// mount "/dev/odd03" to "/vol/storage_virt_odd" and bind it to our virt PPC path "odd:/"
// if 3rd parameter is NULL it only binds the /vol path (e.g. /vol/system)  to our virt PPC path
res = mount_fs("odd", fsaFd, "/dev/odd03", "/vol/storage_virt_odd");

// Open the file, write and close it again
IOSUHAX_FSA_OpenFile(fsaFd, systemXmlPath, "wb", &slcFd);
IOSUHAX_FSA_WriteFile(fsaFd, data, size, cnt, pFile, flags);
IOSUHAX_FSA_CloseFile(fsaFd, slcFd);
// ...
Haxchi makes a nice example of writing with iosuhax :P
Of course this would be permanent. If you want temporaly you need to make fs patches like in Cafiine.
 

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • Xdqwerty @ Xdqwerty:
    good night
  • Sicklyboy @ Sicklyboy:
    sup nerds
    +1
  • BigOnYa @ BigOnYa:
    Sup dawg, watching old rap vids so feel like I gotta talk...Real
  • BigOnYa @ BigOnYa:
    Not really just funny. I'm definitely a nerd!
  • ShinyLuxio @ ShinyLuxio:
    Hi there, it's any way to recover original LFCS if I don't have a NAND backup?
  • ShinyLuxio @ ShinyLuxio:
    Bought second hand 3DS, it seems it was "unbanned" but that was before I bought it
  • K3Nv2 @ K3Nv2:
    I got these in today for $20 stink buds they aren't that bad https://a.co/d/fOMSn8g
    +1
  • ShinyLuxio @ ShinyLuxio:
    @BigOnYa thanks but my question isn't there
  • BigOnYa @ BigOnYa:
    You ask your questions there, create a new thread if its not already answered, then eventually a 3ds genius will respond.
  • ShinyLuxio @ ShinyLuxio:
    I will, thanks
    +1
  • BigOnYa @ BigOnYa:
    No prob and btw, welcome to gbatemp! :grog:
  • BigOnYa @ BigOnYa:
    @K3Nv2 I got some cheapies at wallys, that are pretty good, already have lost a few expensive ones (one falls out and gone, can't find) while cutting grass so bought some cheap ones, and of course never lose these cheap ones. (Cheap meaning only $35, compared to air buds which I only have 1 of 2 now)
  • BigOnYa @ BigOnYa:
    They need to add air tags to they airbuds..
  • The Real Jdbye @ The Real Jdbye:
    @BigOnYa the airtags are bigger than the airpods, they won't fit
    +1
  • BigOnYa @ BigOnYa:
    Be cool tech tho. Of course they want to lose them anyways. Buy and buy again.
  • K3Nv2 @ K3Nv2:
    Apple could make a find my AirPods thing pretty easily
    +1
  • BigOnYa @ BigOnYa:
    You would think, esp using bluetooth, not GPS, like a "your getting hot-er" meter on your phone.
  • BigOnYa @ BigOnYa:
    I think they should tie up diddy, and let all the victims come and abuse him, we'll make a holiday of it every year. (jk, maybe)
  • BigOnYa @ BigOnYa:
    I'm starting to sound like a Tck Gonna cut myself off.
  • K3Nv2 @ K3Nv2:
    It's not 4th of July yet
  • Veho @ Veho:
    It is in India.
    Veho @ Veho: It is in India.