Hacking TCP Gecko Server Feature Requests

BullyWiiPlaza

Nintendo Hacking <3
OP
Member
Joined
Aug 2, 2014
Messages
1,932
Trophies
0
XP
2,467
Country
Germany
In this topic I want to collect features that would be great to have in the TCP Gecko server code.
  • Support compressed sending/receiving of bytes to save network transmission time using an open-source compression library like zlib or even lzma. Unfortunately, I'm getting Z_MEM_ERROR when calling deflateInit(). Alternatively, there is lzma:
Code:
LzmaCompress(unsigned char *dest, size_t *destLen,
               const unsigned char *src, size_t srcLen,
               unsigned char *outProps,
               size_t *outPropsSize, /* *outPropsSize must be = 5 */
               int level,            /* 0 <= level <= 9, default = 5 */
               unsigned dictSize,    /* default = (1 << 24) */
               int lc,               /* 0 <= lc <= 8, default = 3  */
               int lp,               /* 0 <= lp <= 4, default = 0  */
               int pb,               /* 0 <= pb <= 4, default = 2  */
               int fb,               /* 5 <= fb <= 273, default = 32 */
               int numThreads        /* 1 or 2, default = 2 */
              );

I've found that the Wii U handles 0x4000 zlib compression pretty well and it makes your transfers about 40% faster
  • Support dumping memory to the SD Card for performance reasons explained here
  • Support multiple clients to be connected to the server at once to avoid having to disconnect when switching clients
  • Support setting breakpoints to find out what reads from or writes to an address. Also execute breakpoints for assembly (Everything like on Wii). I heard that Chadderz got it to work so I'm positive this can be done already without an IOSU exploit release. Also Kinnay made breakpoint execute for Diibugger so it could be integrated into the TCP Gecko Installer
  • Support pausing and resuming the game to allow more fine-grained memory searches. Some cheat codes can hardly be made without
  • Merge kernel exploit and TCP Gecko installer
  • Implement a search function for known values that returns all addresses matching the condition (==, !=, >, <, >=, <=) similar to the search function already implemented:
    Code:
    case COMMAND_MEMORY_SEARCH: {
        // Receive the initial data
        ret = recvwait(bss, clientfd, buffer, 4 * 5);
        ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (memory search information)")
        int startingAddress = ((int *) buffer)[0];
        int length = ((int *) buffer)[1];
        int resultsLimit = ((int *) buffer)[2];
        int aligned = ((int *) buffer)[3];
        int searchBytesCount = ((int *) buffer)[4];
    
        // Receive the search bytes
        char searchBytes[searchBytesCount];
        ret = recvwait(bss, clientfd, searchBytes, searchBytesCount);
        ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (memory search bytes)")
    
        int iterationIncrement = aligned ? searchBytesCount : 1;
        int searchBytesOccurrences = 0;
    
        // Perform the bytes search and collect the results
        for (int currentAddress = startingAddress;
             currentAddress < startingAddress + length;
             currentAddress += iterationIncrement) {
            if (memcmp((void *) currentAddress, searchBytes, searchBytesCount) == 0) {
                // Search bytes have been found
                ((int *) buffer)[1 + searchBytesOccurrences] = currentAddress;
                searchBytesOccurrences++;
    
                if ((resultsLimit == searchBytesOccurrences)
                    || (searchBytesOccurrences == ((DATA_BUFFER_SIZE / 4) - 1))) {
                    // We bail out
                    break;
                }
            }
        }
    
        ((int *) buffer)[0] = searchBytesOccurrences * 4;
        ret = sendwait(bss, clientfd, buffer, 4 + (searchBytesOccurrences * 4));
        ASSERT_FUNCTION_SUCCEEDED(ret, "recvwait (Sending search bytes occurrences)")
    
        break;
    }
This will allow the initial searching time for known value searches to be optimized.
  • Support multi-threaded memory dumping (once again for performance reasons)
    You can also add some coroutines or multi-processor functions to increase the speed
  • Add screenshot support
  • Allow replacing files on the file system
    Code:
    case COMMAND_REPLACE_FILE: {
        // TODO Write 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
                    ret = FSWriteFile(client, commandBlock, fileBuffer, 1,
                                      dataLength, handle, 0, FS_RET_ALL_ERROR);
                    ASSERT_FUNCTION_SUCCEEDED(ret, "FSWriteFile")
                } else {
                    // Done
                    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;
    }

  • Allow adding files to the file system
    Cafiine source.
The TCP Gecko Installer source code is here.

Please post your suggestions below if you have any that haven't been mentioned yet. :)

@Maschell
@gudenaurock
@NWPlayer123
@Marionumber1
@Onion_Knight
@wj44
@shinyquagsire23
@Hykem
@MrRean
 
Last edited by BullyWiiPlaza,

BullyWiiPlaza

Nintendo Hacking <3
OP
Member
Joined
Aug 2, 2014
Messages
1,932
Trophies
0
XP
2,467
Country
Germany
A dedicated hardware device for conecting a PC directly, would not impact the network and could have less overhead if done well, more throughput.
We don't really need a USB Gecko'ish device since it will cost extra money for everyone. Performance will be good enough when optimized software-wise I believe. Also the Wii USB Gecko was still slow. Yes, the GameCube memory card slots weren't fast to begin with but still, which slot would you propose to provide more throughput? Most likely not possible or not worth it.
 
Last edited by BullyWiiPlaza,

gudenau

Largely ignored
Member
Joined
Jul 7, 2010
Messages
3,882
Trophies
2
Location
/dev/random
Website
www.gudenau.net
XP
5,365
Country
United States
We don't really need a USB Gecko'ish device since it will cost extra money for everyone. Performance will be good enough when optimized software-wise I believe. Also the Wii USB Gecko was still slow. Yes, the GameCube memory card slots weren't fast to begin with but still, which slot would you propose to provide more throughput?
Yeah, but for the few that would use it (like me) it could be useful. The fastest you can get with the networking goes though a few layers in software. USB, IP, TCP, Handler. A USB device could just be USB,Handler.

Even optimizing the search tools to not transfer much data would not eleviate the utility of memory dumps.

Probably a good idea to make two builds, one with tcp and the other with USB.
 
  • Like
Reactions: BullyWiiPlaza

rbsk

Well-Known Member
Newcomer
Joined
May 10, 2016
Messages
64
Trophies
0
Age
39
XP
96
Country
United States
@BullyWiiPlaza Is it at all possible to get a feature for finding what 'write/reads to/from this address'?
Like, a watch on a single address for either what is writing to this address or reading from this address or both as you go about and change things.
That is my favorite thing about BitSlicer (OSXs equivalent to cheat engine). Or would this fall solely under the client piece and not the server?
 
Last edited by rbsk,
  • Like
Reactions: BullyWiiPlaza

BullyWiiPlaza

Nintendo Hacking <3
OP
Member
Joined
Aug 2, 2014
Messages
1,932
Trophies
0
XP
2,467
Country
Germany
@BullyWiiPlaza Is it at all possible to get a feature for finding what 'write/reads to/from this address'?
Like, a watch on a single address for either what is writing to this address or reading from this address or both as you go about and change things.
That is my favorite thing about BitSlicer (OSXs equivalent to cheat engine). Or would this fall solely under the client piece and not the server?
Yeah, it's for the server. This is indeed something I forgot. It's called setting breakpoints.
 
  • Like
Reactions: rbsk

RandomUser

Rosalina in Plush Form
Member
Joined
May 9, 2010
Messages
967
Trophies
1
XP
1,042
Country
United States
I don't know if it would be possible, perhaps a way to load cheats from SD card, like GeckoOS, also if possible being able to select which cheats you want enabled from said SD card. Actually may want to scratch that, to many potential for online abuse, as currently too much codes sent through the Network interface will interfere with online communication, thus making it a little less convenience to cheat online.
 

BullyWiiPlaza

Nintendo Hacking <3
OP
Member
Joined
Aug 2, 2014
Messages
1,932
Trophies
0
XP
2,467
Country
Germany
Actually may want to scratch that, to many potential for online abuse, as currently too much codes sent through the Network interface will interfere with online communication, thus making it a little less convenience to cheat online.
The suggestions are for the codehandler server which has nothing to do with the SD Card. About your concern: It doesn't really matter. The network for sending codes or whatever doesn't get "less stable" during online play.
 

BullyWiiPlaza

Nintendo Hacking <3
OP
Member
Joined
Aug 2, 2014
Messages
1,932
Trophies
0
XP
2,467
Country
Germany
So I was trying to implement a bytes search but it's not working right...
Code:
int compareMemory(unsigned char *buffer, void* address, int size) {
    void* current_address = address;

    int buffer_index = 0;
    for (; current_address < address + size; current_address++) {
        char memory_value = *(char *) current_address;
        char buffer_value = buffer[buffer_index];

        if (memory_value != buffer_value) {
            return false;
        }

        buffer_index++;
    }

    return true;
}
Code:
case 0x73: { /* cmd_search_bytes */
                data_size = 0x400;
                ret = recvwait(bss, clientfd, buffer, data_size);
                CHECK_ERROR(ret < 0);

                int starting_address = ((int *) buffer)[0];
                int end_address = ((int *) buffer)[1];
                int value_bytes_length = ((int *) buffer)[2];
                unsigned char* value_bytes = &buffer[3];

                int found_address = 0;
                for (int current_address = starting_address;
                     current_address < end_address;
                     current_address++) {
                    if (compareMemory(value_bytes, (void *) current_address, value_bytes_length)) {
                        found_address = current_address;
                        break;
                    }
                }

                ((int *) buffer)[0] = found_address;
                ret = sendwait(bss, clientfd, buffer, 4);
                CHECK_ERROR(ret < 0);
                break;
            }
Can someone please take a look and maybe tell me what went possibly wrong? The idea is to receive the address to start search from, the end address of the search interval, the amount of bytes to compare against and finally the actual bytes.

On Linux, the following example code worked:
Code:
#include <malloc.h>
#include <stdlib.h>
#include <stdbool.h>

int compareMemory(unsigned char *buffer, void *address, int size) {
    void *current_address = address;

    int buffer_index = 0;
    for (; current_address < address + size; current_address++) {
        char memory_value = *(char *) current_address;
        char buffer_value = buffer[buffer_index];

        if (memory_value != buffer_value) {
            return false;
        }

        buffer_index++;
    }

    return true;
}

int main() {
    unsigned char buffer[7];
    buffer[0] = 0;
    buffer[1] = 0;
    buffer[2] = 0;
    buffer[3] = 1;
    buffer[4] = 2;
    buffer[5] = 3;
    buffer[6] = 4;

    size_t size = 4 * sizeof(char);
    char *allocated = (char *) malloc(size);
    allocated[0] = 1;
    allocated[1] = 2;
    allocated[2] = 3;
    allocated[3] = 4;

    printf("The same: %i", compareMemory(&buffer[3], allocated, 4));

    return EXIT_SUCCESS;
}
Thanks!
 
Last edited by BullyWiiPlaza,

Site & Scene News

Popular threads in this forum

General chit-chat
Help Users
  • No one is chatting at the moment.
    SylverReZ @ SylverReZ: https://www.youtube.com/watch?v=ftyFz0yBxj8