Reading from Wii U Logger

Discussion in 'Wii U - Hacking & Backup Loaders' started by BullyWiiPlaza, Apr 13, 2017.

  1. BullyWiiPlaza
    OP

    BullyWiiPlaza Nintendo Hacking <3

    Member
    1,693
    1,377
    Aug 2, 2014
    Germany
    In various Wii U homebrew applications such as this one there are logger.c and logger.h functions which apparently write debug logs over the network. I've been wondering how to get them to work properly so I can see them in a console window.

    Which IP address has to be passed in log_init()? The Wii U's or PC's local IP address? I assume it's the PC's since that makes a lot more sense so I edited the call respectively:
    Code:
    log_init("192.168.2.103");
    Then on the PC I assume that I need to run some kind of client to connect to the Wii U's IP address and port 4405 since the latter is hardcoded. We then keep reading the messages indefinitely. To do this, I wrote the following client code in Java:
    Code:
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.ConnectException;
    import java.net.Socket;
    
    public class EchoClient
    {
       public static void main(String[] arguments) throws Exception
       {
          System.out.println("Connecting...");
          Socket socket;
    
          // Keep trying to connect
          while (true)
          {
             try
             {
                socket = new Socket("192.168.2.101", 4405);
                break;
             } catch (ConnectException ignored)
             {
    
             }
          }
         
          BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
          System.out.println("Connected!");
    
          // Keep reading from the network and print it out
          while (true)
          {
             String line = bufferedReader.readLine();
             System.out.println(line);
          }
       }
    }
    
    When I start the Java client on the PC and the homebrew application on the Wii U, the Java client never connects and stays stuck on "Connecting...". Can someone help? I haven't seen an explanation for this anywhere except for here but it does pretty much what I do.

    At second thought, in case the PC is the server (which again makes more sense), I tried this code:
    Code:
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class Server
    {
        public static void main(String[] arguments) throws Exception
        {
            System.out.println("Creating server socket...");
    
            try (ServerSocket listener = new ServerSocket(4405))
            {
                System.out.println("Waiting for client...");
    
                while (true)
                {
                    try (Socket socket = listener.accept())
                    {
                        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
                        System.out.println("Client connected...");
    
                        while (true)
                        {
                            String line = bufferedReader.readLine();
                            System.out.println(line);
                        }
                    }
                }
            }
        }
    }
    Same problem, it never connects when I start the server and then load the homebrew application. Clearly, log_init() is called and written to from the Wii U.

    @QuarkTheAwesome
    @gudenaurock
    @Maschell
    @dimok
    @shinyquagsire23
    @NWPlayer123
     
  2. QuarkTheAwesome

    QuarkTheAwesome Working for Hugs

    Member
    765
    1,868
    Apr 19, 2015
    Australia
    Stuck in the PowerPC
    Dimok wrote an app to read from loggers like that, which is what I use. Find that here.
    As an aside, you have to make sure logging is turned on in logger.h. There's a line - #define DEBUG_LOGGER 1 - that needs to be present in order for any logging to happen. It's usually commented out, so you may need to fix that.
    The IP address is that of the PC, as you guessed. Other than that, the usual networking caveats apply - make sure they're on the same network/subnet etc. etc.
     
    BullyWiiPlaza likes this.
  3. BullyWiiPlaza
    OP

    BullyWiiPlaza Nintendo Hacking <3

    Member
    1,693
    1,377
    Aug 2, 2014
    Germany
    Thanks for the tool link, this is what I needed. Also yes, the DEBUG_LOGGER macro was defined as 1 so it should've ran and since other networking tools work, I'm not worried about the networking caveats either right now.

    It works with dimok's tool. :)
     
    Last edited by BullyWiiPlaza, Apr 14, 2017
  4. gudenau

    gudenau Never a unique idea

    Member
    3,244
    1,216
    Jul 7, 2010
    United States
    /dev/random
    It uses UDP.
     
    BullyWiiPlaza and Maschell like this.
  5. Maschell

    Maschell GBAtemp Advanced Fan

    Member
    887
    1,282
    Jun 14, 2008
    Gambia, The
    Something like this should work if you want Java code

    Code:
    @Log
    public final class UDPLogger implements Runnable {
        private final DatagramSocket sock;
    
        public static void main(String[] args) {
             new Thread(UDPLogger.getInstance(), "UDP Server").start();
        }
    
        private UDPLogger() throws SocketException {
            sock = new DatagramSocket(4405);
        }
    
        static UDPLogger getInstance() {
            UDPLogger result = null;
            try {
                result = new UDPLogger();
            } catch (Exception e) {
                log.info("Can't bind the socket!");
            }
            return result;
        }
    
        @Override
        public void run() {
            log.info("UDPServer running.");
            byte[] receiveData = new byte[1400];
            while (true) {
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                try {
                    sock.receive(receivePacket);
                } catch (IOException e) {
                    continue;
                }
                byte[] data = Arrays.copyOf(receivePacket.getData(), receivePacket.getLength());
                System.out.print(new String(data));
            }
    
        }
    }
    
     
    Last edited by Maschell, Apr 14, 2017
    BullyWiiPlaza likes this.
  6. ::Phoenix::

    ::Phoenix:: GBAtemp Regular

    Member
    184
    169
    May 11, 2010
    Italy
    On Linux, you can just use the nc command:
    nc -l -u 4405
     
    BullyWiiPlaza likes this.
  7. BullyWiiPlaza
    OP

    BullyWiiPlaza Nintendo Hacking <3

    Member
    1,693
    1,377
    Aug 2, 2014
    Germany
    @Maschell thanks.

    Which framework do you use for the
    Code:
    @log
    annotations? By default, this doesn't work.

    Here would be the code without them so it compiles easily:
    Code:
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.SocketException;
    import java.util.Arrays;
    
    public class UDPLogger implements Runnable
    {
        private final DatagramSocket sock;
    
        public static void main(String[] args)
        {
            new Thread(UDPLogger.getInstance(), "UDP Server").start();
        }
    
        private UDPLogger() throws SocketException
        {
            sock = new DatagramSocket(4405);
        }
    
        private static UDPLogger getInstance()
        {
            UDPLogger result = null;
            try
            {
                result = new UDPLogger();
            } catch (Exception e)
            {
                System.out.println("Can't bind the socket!");
            }
            return result;
        }
    
        @Override
        public void run()
        {
            System.out.println("UDPServer running.");
            byte[] receiveData = new byte[1400];
            while (true)
            {
                DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
                try
                {
                    sock.receive(receivePacket);
                } catch (IOException e)
                {
                    continue;
                }
                byte[] data = Arrays.copyOf(receivePacket.getData(), receivePacket.getLength());
                System.out.print(new String(data));
            }
        }
    }
     
  8. Maschell

    Maschell GBAtemp Advanced Fan

    Member
    887
    1,282
    Jun 14, 2008
    Gambia, The
    https://projectlombok.org/index.html

    You should use this anyway, it's really helpful!
     
    BullyWiiPlaza likes this.
  9. BullyWiiPlaza
    OP

    BullyWiiPlaza Nintendo Hacking <3

    Member
    1,693
    1,377
    Aug 2, 2014
    Germany
  10. BullyWiiPlaza
    OP

    BullyWiiPlaza Nintendo Hacking <3

    Member
    1,693
    1,377
    Aug 2, 2014
    Germany
    Uhm, so today I tried the Java code out myself but it doesn't receive the messages at all. It is stuck on receive() even when something is sent but the C server by dimok works of course. Since the port can only be used once, I had to close dimok's program to run the Java one (also obvious). Any help @Maschell ?
     
  11. Maschell

    Maschell GBAtemp Advanced Fan

    Member
    887
    1,282
    Jun 14, 2008
    Gambia, The
    I'm using the exact Code I've posted without any issues.
     
  12. BullyWiiPlaza
    OP

    BullyWiiPlaza Nintendo Hacking <3

    Member
    1,693
    1,377
    Aug 2, 2014
    Germany
    It really doesn't. Here is an example output of dimok's UDP Reader when clicking the Pause button twice in JGecko U (Pause/Resume Wii U):

    [​IMG]

    [​IMG]

    Works.

    The C code looks like this:
    Code:
    int (*AVMGetDRCScanMode)(int);
    
    unsigned long getConsoleStatePatchAddress() {
        if (AVMGetDRCScanMode) {
            log_print("Already acquired!\n");
        } else {
            // Acquire the RPL and function
            log_print("Acquiring...\n");
            unsigned int avm_handle;
            OSDynLoad_Acquire("avm.rpl", (u32 * ) & avm_handle);
            ASSERT_ALLOCATED(avm_handle, "avm.rpl")
            OSDynLoad_FindExport((u32) avm_handle, 0, "AVMGetDRCScanMode", &AVMGetDRCScanMode);
            ASSERT_ALLOCATED(AVMGetDRCScanMode, "AVMGetDRCScanMode")
            log_print("Acquired!\n");
        }
    
        return (unsigned long) (AVMGetDRCScanMode + 0x44);
    }
    
    typedef enum {
        PAUSED = 0x38000001, RUNNING = 0x38000000
    } ConsoleState;
    
    void writeConsoleState(ConsoleState state) {
        // Get the value to write
        int patchValue = state;
        log_printf("Patch value: %x\n", patchValue);
    
        // Write the value
        unsigned int patchAddress = getConsoleStatePatchAddress();
        log_printf("Patch address: %x\n", patchAddress);
        pygecko_memcpy((unsigned char *) patchAddress, (unsigned char *) &patchValue, 4);
    }
    
    bool isConsolePaused() {
        unsigned int patchAddress = getConsoleStatePatchAddress();
        log_printf("Patch address: %x\n", patchAddress);
        int value = *(unsigned int *) patchAddress;
    
        return value == PAUSED;
    }
    With your UDP reader code there is nothing printed when doing the same thing (Pause/Resume):

    [​IMG]

    Nothing received, it's stuck on the receive() method.

    I also copied the logger.c and logger.h files from your Function Patcher Example to make sure it's right because before it also didn't work with dimok's tool. Now it doesn't work with Java only. Hmm...

    TCP Gecko Installer source.

    You can see for yourself, just load the TCPGecko.elf in the Homebrew Launcher, connect JGecko U to your Wii U's IP address on the Wii U menu, run the Java UDP Debug Reader and click the Pause/Resume button in JGecko U. Nothing printed.

    Using the function patcher example, also nothing is printed unlike with dimok's tool.
     
    Last edited by BullyWiiPlaza, Apr 18, 2017