From b818b0d1fe9e7b563c7bf80bcf012e3946d51de6 Mon Sep 17 00:00:00 2001 From: Maschell Date: Sat, 22 Oct 2016 18:52:14 +0200 Subject: [PATCH] First commit. Only ls() is working so far Started to port. Many functions are missing. Some implementend are working, some are complety untested --- .gitignore | 1 + README.md | 5 + src/de/mas/wupclient/IoctlvResult.java | 28 ++ src/de/mas/wupclient/ReadDirReturn.java | 52 +++ src/de/mas/wupclient/Result.java | 41 +++ src/de/mas/wupclient/Starter.java | 16 + src/de/mas/wupclient/Utils.java | 30 ++ src/de/mas/wupclient/WUPClient.java | 449 ++++++++++++++++++++++++ 8 files changed, 622 insertions(+) create mode 100644 README.md create mode 100644 src/de/mas/wupclient/IoctlvResult.java create mode 100644 src/de/mas/wupclient/ReadDirReturn.java create mode 100644 src/de/mas/wupclient/Result.java create mode 100644 src/de/mas/wupclient/Starter.java create mode 100644 src/de/mas/wupclient/Utils.java create mode 100644 src/de/mas/wupclient/WUPClient.java diff --git a/.gitignore b/.gitignore index cd2946a..11ddb8b 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,4 @@ $RECYCLE.BIN/ Network Trash Folder Temporary Items .apdisk +*.class diff --git a/README.md b/README.md new file mode 100644 index 0000000..d2a501a --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +A port of smea's client (WUPClient.py) for the wupserver. + +https://github.com/smealum/iosuhax/tree/master/wupserver + +Everything is from Smea, I'm just porting it! \ No newline at end of file diff --git a/src/de/mas/wupclient/IoctlvResult.java b/src/de/mas/wupclient/IoctlvResult.java new file mode 100644 index 0000000..abbfc68 --- /dev/null +++ b/src/de/mas/wupclient/IoctlvResult.java @@ -0,0 +1,28 @@ +package de.mas.wupclient; + +public class IoctlvResult{ + private int resultValue; + private byte[][] data; + + public IoctlvResult(int result, byte[][] data) { + setData(data); + setResultValue(result); + } + + public byte[][] getData() { + return data; + } + + public void setData(byte[][] data) { + this.data = data; + } + + public int getResultValue() { + return resultValue; + } + + public void setResultValue(int resultValue) { + this.resultValue = resultValue; + } + +} diff --git a/src/de/mas/wupclient/ReadDirReturn.java b/src/de/mas/wupclient/ReadDirReturn.java new file mode 100644 index 0000000..1235cd8 --- /dev/null +++ b/src/de/mas/wupclient/ReadDirReturn.java @@ -0,0 +1,52 @@ +package de.mas.wupclient; + +public class ReadDirReturn { + private int result; + private String filename; + private boolean isFile; + private byte[] unknowndata; + + public ReadDirReturn(int result,String filename, boolean isFile, byte[] unknowndata) { + setResult(result); + setFilename(filename); + setFile(isFile); + setUnknowndata(unknowndata); + } + + public ReadDirReturn(int resultValue) { + setResult(resultValue); + } + + public byte[] getUnknowndata() { + return unknowndata; + } + + public void setUnknowndata(byte[] unknowndata) { + this.unknowndata = unknowndata; + } + + public boolean isFile() { + return isFile; + } + + public void setFile(boolean isFile) { + this.isFile = isFile; + } + + public String getFilename() { + return filename; + } + + public void setFilename(String filename) { + this.filename = filename; + } + + public int getResult() { + return result; + } + + public void setResult(int result) { + this.result = result; + } + +} diff --git a/src/de/mas/wupclient/Result.java b/src/de/mas/wupclient/Result.java new file mode 100644 index 0000000..1f5862c --- /dev/null +++ b/src/de/mas/wupclient/Result.java @@ -0,0 +1,41 @@ +package de.mas.wupclient; + +public class Result { + private int resultValue; + private int int_value; + private byte[] data; + + public Result(int result, byte[] data){ + setData(data); + setResultValue(result); + } + + public Result(int resultValue2, int int_value) { + setResultValue(resultValue2); + setInt_value(int_value); + } + + public int getResultValue() { + return resultValue; + } + + public void setResultValue(int resultValue) { + this.resultValue = resultValue; + } + + public byte[] getData() { + return data; + } + + public void setData(byte[] data) { + this.data = data; + } + + public int getInt_value() { + return int_value; + } + + public void setInt_value(int int_value) { + this.int_value = int_value; + } +} diff --git a/src/de/mas/wupclient/Starter.java b/src/de/mas/wupclient/Starter.java new file mode 100644 index 0000000..cbafcc6 --- /dev/null +++ b/src/de/mas/wupclient/Starter.java @@ -0,0 +1,16 @@ +package de.mas.wupclient; + +import java.io.IOException; + +public class Starter { + public static void main(String args[]){ + WUPClient w = new WUPClient("192.168.0.035"); + try { + w.ls("/vol/storage_mlc01/"); + w.FSA_Close(w.get_fsa_handle()); + w.closeSocket(); + } catch (IOException e) { + e.printStackTrace(); + } + } +} diff --git a/src/de/mas/wupclient/Utils.java b/src/de/mas/wupclient/Utils.java new file mode 100644 index 0000000..c4fdede --- /dev/null +++ b/src/de/mas/wupclient/Utils.java @@ -0,0 +1,30 @@ +package de.mas.wupclient; + +import java.util.Arrays; + +public class Utils { + public static String ByteArrayToString(byte[] ba) + { + if(ba == null) return null; + StringBuilder hex = new StringBuilder(ba.length * 2); + for(byte b : ba){ + hex.append(String.format("%02X", b)); + } + return hex.toString(); + } + + public static T[] concatAll(T[] first, T[]... rest) { + int totalLength = first.length; + for (T[] array : rest) { + totalLength += array.length; + } + T[] result = Arrays.copyOf(first, totalLength); + int offset = first.length; + for (T[] array : rest) { + System.arraycopy(array, 0, result, offset, array.length); + offset += array.length; + } + return result; + } + +} diff --git a/src/de/mas/wupclient/WUPClient.java b/src/de/mas/wupclient/WUPClient.java new file mode 100644 index 0000000..4090bdc --- /dev/null +++ b/src/de/mas/wupclient/WUPClient.java @@ -0,0 +1,449 @@ +package de.mas.wupclient; + +import java.io.DataOutputStream; +import java.io.IOException; +import java.net.Socket; +import java.net.UnknownHostException; +import java.nio.ByteBuffer; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class WUPClient { + private String IP; + private int fsaHandle = -1; + private String cwd = ""; + private Socket socket; + + public WUPClient(String ip){ + setIP(ip); + createSocket(ip); + setFsaHandle(-1); + setCwd("/vol/storage_mlc01"); + } + + public Result send(int command, byte[] data) throws IOException{ + DataOutputStream outToServer = new DataOutputStream(getSocket().getOutputStream()); + ByteBuffer destByteBuffer = ByteBuffer.allocate(data.length + 4); + destByteBuffer.order(ByteOrder.BIG_ENDIAN); + destByteBuffer.putInt(command); + destByteBuffer.put(data); + try { + outToServer.write(destByteBuffer.array()); + + } catch (IOException e) { + e.printStackTrace(); + } + destByteBuffer.clear(); + destByteBuffer = ByteBuffer.allocate(0x600); + byte[] result = new byte[0x0600]; + int size = getSocket().getInputStream().read(result); + destByteBuffer.put(result, 0, size); + int returnValue = destByteBuffer.getInt(); + return new Result(returnValue,Arrays.copyOfRange(result, 4,result.length)); + } + + public byte[] read(int addr, int len) throws IOException{ + ByteBuffer destByteBuffer = ByteBuffer.allocate(8); + destByteBuffer.order(ByteOrder.BIG_ENDIAN); + destByteBuffer.putInt(addr); + destByteBuffer.putInt(len); + Result result = send(1,destByteBuffer.array()); + if(result.getResultValue() == 0){ + return result.getData(); + }else{ + System.out.println("Read error: " + result.getResultValue()); + return null; + } + } + + public int write(int addr, byte[] data ) throws IOException{ + ByteBuffer destByteBuffer = ByteBuffer.allocate(4 + data.length); + destByteBuffer.order(ByteOrder.BIG_ENDIAN); + destByteBuffer.putInt(addr); + destByteBuffer.put(data); + + Result result = send(0,destByteBuffer.array()); + if(result.getResultValue() == 0){ + return result.getResultValue(); + }else{ + System.out.println("write error: " + result.getResultValue()); + return -1; + } + } + + public int svc(int svc_id, int[] arguments) throws IOException{ + ByteBuffer destByteBuffer = ByteBuffer.allocate(4 + (arguments.length * 0x04)); + destByteBuffer.order(ByteOrder.BIG_ENDIAN); + destByteBuffer.putInt(svc_id); + for(int i = 0;i 0){ + int out_address = alloc(outbuf_size); + int[] buffer = new int[6]; + buffer[0] = handle; + buffer[1] = cmd; + buffer[2] = in_address; + buffer[3] = inbuf.length; + buffer[4] = out_address; + buffer[5] = outbuf_size; + ret = svc(0x38, buffer); + out_data = read(out_address, outbuf_size); + free(out_address); + }else{ + int[] buffer = new int[6]; + buffer[0] = handle; + buffer[1] = cmd; + buffer[2] = in_address; + buffer[3] = inbuf.length; + buffer[4] = 0; + buffer[5] = 0; + ret = svc(0x38, buffer); + } + free(in_address); + return new Result(ret,out_data); + } + + public int iovec(int[][] inputData) throws IOException{ + ByteBuffer destByteBuffer = ByteBuffer.allocate(inputData.length * (0x04*3)); + destByteBuffer.order(ByteOrder.BIG_ENDIAN); + for (int[] foo : inputData){ + destByteBuffer.putInt(foo[0]); + destByteBuffer.putInt(foo[1]); + destByteBuffer.putInt(0); + } + return load_buffer(destByteBuffer.array()); + } + + /** + * UNTESTED! + */ + public IoctlvResult ioctlv(int handle, int cmd,byte[][] inbufs,int[] outbuf_sizes,int[][] ínbufs_ptr,int[][] outbufs_ptr) throws IOException{ + int new_inbufs[][] = new int[inbufs.length][2]; + int i = 0; + for(byte[] data : inbufs){ + new_inbufs[i][0] = load_buffer(data, 0x40); + new_inbufs[i][1] = data.length; + i++; + } + int new_outbufs[][] = new int[outbuf_sizes.length][2]; + i = 0; + for(int cur_size : outbuf_sizes){ + new_outbufs[i][0] = alloc(cur_size, 0x40); + new_outbufs[i][1] = cur_size; + i++; + } + + int[][] iovecs_buffer = Utils.concatAll(new_inbufs,ínbufs_ptr,outbufs_ptr,new_outbufs); + + int iovecs = iovec(iovecs_buffer); + int[] buffer = new int[5]; + buffer[0] = handle; + buffer[1] = cmd; + buffer[2] = new_inbufs.length + ínbufs_ptr.length; + buffer[3] = new_outbufs.length + outbufs_ptr.length; + buffer[4] = iovecs; + int ret = svc(0x39, buffer); + + byte[][] out_data = new byte[new_outbufs.length][]; + i=0; + for (int[] foo : new_outbufs){ + out_data[i] = read(foo[0],foo[1]); + i++; + } + i=0; + int[][] free_buffer = Utils.concatAll(new_inbufs,new_outbufs); + for (int[] foo : free_buffer){ + free(foo[0]); + i++; + } + free(iovecs); + return new IoctlvResult(ret,out_data); + } + + public int get_fsa_handle() throws IOException{ + if(getFsaHandle()== -1){ + setFsaHandle(open("/dev/fsa", 0)); + } + return getFsaHandle(); + } + + public Result FSA_OpenDir(int handle, String path) throws IOException{ + byte[] inbuffer = new byte[0x520]; + byte[] string = path.getBytes(); + + System.arraycopy(string , 0, inbuffer, 4, string.length); + inbuffer[string.length + 4] = 0; + + Result res = ioctl(handle, 0x0A, inbuffer, 0x293); + byte[] data = res.getData(); + ByteBuffer destByteBuffer = ByteBuffer.allocate(data.length); + destByteBuffer.order(ByteOrder.BIG_ENDIAN); + destByteBuffer.put(data); + + return new Result(res.getResultValue(),destByteBuffer.getInt(4)); + } + + public byte[] intToByteArray(int number){ + ByteBuffer destByteBuffer = ByteBuffer.allocate(4); + destByteBuffer.order(ByteOrder.BIG_ENDIAN); + destByteBuffer.putInt(number); + return destByteBuffer.array(); + } + + private ReadDirReturn FSA_ReadDir(int fsa_handle, int dirhandle) throws IOException { + byte[] inbuffer = new byte[0x520]; + System.arraycopy(intToByteArray(dirhandle), 0, inbuffer, 4, 4); + Result res = ioctl(fsa_handle, 0x0B, inbuffer, 0x293); + + byte[] rawdata = res.getData(); + byte[] data = new byte[rawdata.length-4]; + System.arraycopy(rawdata, 4, data, 0, rawdata.length-4); + byte[] unknowndata = new byte[0x64]; + System.arraycopy(data, 0, unknowndata, 0, 0x64); + + + int i = 0; + while(data[0x64 + i] != 0 && (i +0x64) < data.length){ + i++; + } + byte[] stringData = new byte[i]; + boolean isFile = false; + if(unknowndata[0] == 0) isFile =true; + System.arraycopy(data, 0x64, stringData, 0, i); + if(res.getResultValue() == 0){ + return new ReadDirReturn(res.getResultValue(),new String(stringData, "UTF-8"),isFile,unknowndata); + }else{ + return new ReadDirReturn(res.getResultValue()); + } + } + + public int FSA_Close(int handle) throws IOException{ + int[] buffer = new int[1]; + buffer[0] = handle; + int result = svc(0x34, buffer); + if(result == 0){ + setFsaHandle(-1); + } + return result; + } + + public int FSA_CloseDir(int handle, int dirhandle) throws IOException{ + byte[] inbuffer = new byte[0x520]; + System.arraycopy(intToByteArray(dirhandle), 0, inbuffer, 4, 4); + Result res = ioctl(handle, 0x0D, inbuffer, 0x293); + return res.getResultValue(); + } + + public List ls() throws IOException{ + return ls(null,false); + } + public List ls(boolean return_data) throws IOException{ + return ls(null,return_data); + } + public List ls(String targetPath) throws IOException{ + return ls(targetPath,false); + } + public List ls(String targetPath,boolean return_data) throws IOException{ + List results = new ArrayList<>(); + int fsa_handle = get_fsa_handle(); + String path = targetPath; + if(targetPath == null || targetPath.isEmpty()){ + path = getCwd(); + } + + Result res = FSA_OpenDir(fsa_handle, path); + if(res.getResultValue() != 0x0){ + System.out.println("opendir error : " + String.format("%08X",res.getResultValue())); + } + + int dirhandle = res.getInt_value(); + while(true){ + ReadDirReturn result = FSA_ReadDir(fsa_handle, dirhandle); + if (result.getResult() != 0){ + break; + } + if(!return_data){ + if(result.isFile()){ + System.out.println(result.getFilename()); + }else{ + System.out.println(result.getFilename() + "/"); + } + }else{ + results.add(result); + } + } + int result; + if((result = FSA_CloseDir(fsa_handle, dirhandle)) != 0){ + System.err.println("CloseDirdone failed!" + result); + } + return results; +} + + private Socket createSocket(String ip) { + Socket clientSocket = null; + try { + clientSocket = new Socket(ip, 1337); + } catch (UnknownHostException e) { + System.err.println("Unkown Host"); + e.printStackTrace(); + } catch (IOException e) { + System.err.println("IO Error Host"); + e.printStackTrace(); + } + setSocket(clientSocket); + System.out.println("Connected"); + return clientSocket; + } + + public void closeSocket(){ + Socket socket = getSocket(); + if(socket!= null){ + try { + socket.close(); + } catch (IOException e) { + } + } + } + public String getIP() { + return IP; + } + public void setIP(String iP) { + IP = iP; + } + private int getFsaHandle() { + return fsaHandle; + } + private void setFsaHandle(int fsaHandle) { + this.fsaHandle = fsaHandle; + } + private String getCwd() { + return cwd; + } + private void setCwd(String cwd) { + this.cwd = cwd; + } + public Socket getSocket() { + return socket; + } + public void setSocket(Socket socket) { + this.socket = socket; + } + +}