Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Get account ID #21

Open
wants to merge 72 commits into
base: master
Choose a base branch
from
Open
Changes from 10 commits
Commits
Show all changes
72 commits
Select commit Hold shift + click to select a range
089bf96
First version of uGecko.
vincent-coding May 16, 2021
73775c5
Update README.md
vincent-coding May 16, 2021
e6af50d
uGecko v1.0.1 - Test...
vincent-coding Jun 13, 2021
dd7f108
Fix writeString()
vincent-coding Jun 30, 2021
bf932c1
Fix: Timeout on connection attempt
vincent-coding Jul 1, 2021
b4cf56c
uGecko 1.1
vincent-coding Jul 10, 2021
e59ea86
Added return types to most functions and changed serialPoke
NessieHax Jul 29, 2021
99d23d3
Updated function arguments type
NessieHax Jul 29, 2021
956e2bd
Fixed isValidMemoryArea
NessieHax Jul 29, 2021
6330ace
Updated Documentation
NessieHax Aug 2, 2021
b8b987e
Updated call return size and added getTitleID
NessieHax Aug 2, 2021
2b0abc6
Updated Documentations
NessieHax Aug 2, 2021
3d2ef1e
Updated .gitignore
NessieHax Aug 2, 2021
6ec6271
Updated Documentations
NessieHax Aug 2, 2021
fd31b73
Added return type to getTitleID
NessieHax Aug 2, 2021
84e3934
Merge pull request #1 from NessieHax/master
vincent-coding Aug 3, 2021
ab1ef02
Correction of the spelling of the word "length"
vincent-coding Aug 3, 2021
945f5ae
Added better error handling
vincent-coding Aug 3, 2021
2722d32
uGecko 1.1.2
vincent-coding Aug 3, 2021
86a19f4
uGecko 1.1.3
vincent-coding Aug 3, 2021
736db9c
uGecko 1.2 (BETA)
vincent-coding Aug 5, 2021
bd2f0c9
Fixed Typo
NessieHax Aug 7, 2021
c897763
Added support for more testing files
NessieHax Aug 7, 2021
c18fab1
Refactored read function
NessieHax Aug 7, 2021
81b013c
Added getSystemInfo and changed upload function
NessieHax Aug 7, 2021
4a4870a
Added getSystemInfo and changed upload function
NessieHax Aug 7, 2021
131c53d
Added issues file
NessieHax Aug 7, 2021
eb2e80e
Updated Documentation
NessieHax Aug 7, 2021
d8ae5ef
Updated Documentation
NessieHax Aug 7, 2021
680856d
Added decoding option to readString
NessieHax Aug 7, 2021
a06ca30
Updated Documentation
NessieHax Aug 7, 2021
1be308a
Updated Documentation
NessieHax Aug 7, 2021
311c484
Updated Documentation
NessieHax Aug 7, 2021
d432b07
Updated Documentation
NessieHax Aug 7, 2021
cf561e0
Updated Documentation
NessieHax Aug 7, 2021
a944ea6
Updated Documentation
NessieHax Aug 7, 2021
2871953
Updated Documentation
NessieHax Aug 7, 2021
b3d0690
Updated Documentation
NessieHax Aug 7, 2021
51d293a
Fixed typo
NessieHax Aug 7, 2021
9caac0e
Fix and updated getSystemInfo
NessieHax Aug 13, 2021
a1c81be
Updated Issues
NessieHax Aug 13, 2021
6972b74
Removed debug print
NessieHax Aug 13, 2021
644a222
Made getSystemInfo more readable
NessieHax Aug 16, 2021
7597e23
Merge pull request #2 from NessieHax/master
vincent-coding Aug 23, 2021
c6e36de
uGecko 1.2.1 (BETA)
vincent-coding Aug 23, 2021
ed69359
Updated upload function
NessieHax Sep 1, 2021
a0698bd
Added malloc and free and made call recieve amout 4 by default
NessieHax Sep 1, 2021
a0fd081
Fix and clean up
NessieHax Sep 1, 2021
27355d5
Merge branch 'master' of https://github.com/NessieHax/uGecko
NessieHax Sep 1, 2021
d2ce33a
rm
NessieHax Sep 1, 2021
21eef8b
removed debug print
NessieHax Sep 1, 2021
9f5e2d6
Updated Docs
NessieHax Sep 1, 2021
0940ffd
Updated Docs
NessieHax Sep 1, 2021
a1e46bc
Merge pull request #3 from NessieHax/master
vincent-coding Sep 19, 2021
deb3749
Added a condition to display the debug line in the upload function
vincent-coding Sep 21, 2021
67a209b
Beta 1.3
vincent-coding Dec 21, 2021
6af290f
Add files via upload
vincent-coding Dec 21, 2021
4ebd530
Rename DOCUMENTATION.md to README.md
vincent-coding Dec 21, 2021
20d843e
Update setup.py
vincent-coding Dec 21, 2021
73d4af0
Update setup.py
vincent-coding Dec 21, 2021
9aa4d95
Update uGecko.py
vincent-coding Dec 21, 2021
1ca2840
Update setup.py
vincent-coding Dec 21, 2021
c1720c9
Update README.md
vincent-coding Dec 21, 2021
0f3d16e
uGecko 1.3.2
vincent-coding Dec 31, 2021
af1b3d2
Fixed the "call" function that was crashing
vincent-coding May 8, 2022
5a8ac6c
Correction of a mistake
vincent-coding May 8, 2022
bdfa2f1
Update __init__.py
vincent-coding May 8, 2022
030dd65
Update setup.py
vincent-coding May 8, 2022
7436fe5
Update README.md
vincent-coding May 8, 2022
0cbd8c7
Create __init__.py
vincent-coding May 8, 2022
83b79d8
Create __init__.py
vincent-coding May 8, 2022
07e3d63
Update README.md
vincent-coding May 8, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@

testLIb.py
__pycache__
17 changes: 9 additions & 8 deletions DOCUMENTATION.md
Original file line number Diff line number Diff line change
@@ -13,13 +13,13 @@ This file is intended to explain and show how to use the functions of ___uGecko_
|poke16()|Allows to change the value in the ram|`gecko.poke16(address, 0x0000)`| None
|poke32()|Allows to change the value in the ram|`gecko.poke32(address, 0x00000000)`| None
|serialPoke()|Allows to write a specific value on several addresses of the ram.|`gecko.poke32(addressTable, 0x3F800000)`| None
|kernelWrite()| | `gecko.kernelWrite(0x10000000, 0x00000000)`| None
|kernelWrite()| Writes a value to memory with Kernel Privileges | `gecko.kernelWrite(0x10000000, 0x00000000)`| None
||||
|read()| Allows to know what is the value of an address | `gecko.read(address, length)` | Value
|kernelRead()| | `gecko.kernelRead(address)`| Value
|kernelRead()| Reads a value to memory with Kernel Privileges | `gecko.kernelRead(address)`| Value
||||
|writeString()| Allows you to write text in the ram | `gecko.writeString(address, "Hello World!")` | None
|readString() | Allows to read a string in the ram | `gecko.readString(address, length)` | UTF-8
|readString() | Allows to read a string in the ram | `gecko.readString(address, length)` | String(UTF-8)
|clearString()| Allows you to delete text written in the ram | `gecko.clearString(startAddress, endAddress)` | None
||||
|isConsolePaused()|Allows to know if the console is paused or not|`gecko.isConsolePaused()`| Boolean
@@ -28,20 +28,21 @@ This file is intended to explain and show how to use the functions of ___uGecko_
||||
|getServerStatus()| Allows to know the status of the server | `gecko.getServerStatus()`| Int (0 or 1)
|getServerVersion()| Get the server version (TCPGecko version) | `gecko.getServerVersion()`| String
|getOsVersion()| Allows to recover the version of the console | `gecko.getOsVersion()`| Int
|getOsVersion()| Allows to get the version of the console | `gecko.getOsVersion()`| Int
|getVersionHash()| Allows to get the hash of the version | `gecko.getVersionHash()`| Int
|getAccountID()| Allows you to retrieve the identifier of the account currently connected to the console. | `gecko.getAccountID()`| String
|getCoreHandlerAddress()| Allows you to get the address of the core handler. | `gecko.getCoreHandlerAddress()`| Hex
|getDataBufferSize()| | `gecko.getDataBufferSize()`| Int
|getEntryPointAddress()| | `gecko.getEntryPointAddress()`| Hex
|getDataBufferSize()| return the Max size of the DataBuffer | `gecko.getDataBufferSize()`| Int
|getTitleID()| returns the current app titleID | `gecko.getTitleID()`| Int
|getEntryPointAddress()| returns the Entry point of the currently running app | `gecko.getEntryPointAddress()`| Hex
|runKernelCopyService()| | `gecko.runKernelCopyService()`| None
||||
|search()| Allows you to do a very simple search | `gecko.search(startAddress, value, length)`| Hex
|advancedSearch()| Allows you to do more advanced searches. | `gecko.advancedSearch(start, length, value, kernel, limit, aligned = 1)`| Hex (Table)
||||
|getSymbol()| Allows you to get the address of a function on the console | `gecko.getSymbol(rplname, sysname, data = 0)`| Int (Used for call)
|getSymbol()| Allows you to get the address of a function on the console | `gecko.getSymbol(rplname, sysname, data = 0)`| Int (function pointer/function address)
|call()| Allows to execute functions on the console. Often used with getSymbol (see example) | `gecko.call(address, *args)`| It all depends on the function executed
||||
|clearAssembly()| | `gecko.clearAssembly()`| None
|excecuteAssembly()| | `gecko.excecuteAssembly(assembly)`| None
|excecuteAssembly()| executes parsed assembly | `gecko.excecuteAssembly(assembly)`| None
|persistAssembly()| | `gecko.persistAssembly(assembly)`| None
165 changes: 71 additions & 94 deletions uGecko.py
Original file line number Diff line number Diff line change
@@ -16,30 +16,29 @@ def __init__(self, ip):
if not onlyCharactersIpAdd(ip): raise BaseException("The entered IP address is not only composed of numbers and dots.")
if not checkip(ip): raise BaseException("The entered IP address does not have a valid structure!")
self.ip = ip
self.connected = False

def connect(self, timeout = 5):
if self.ip == None or self.ip == "": raise BaseException("No ip address has been entered!")
else:
if not self.connected:
try:
self.socket.settimeout(timeout)
self.socket.connect((str(self.ip), 7331))
self.socket.settimeout(None)
self.connected = True
except: raise BaseException(f"Unable to connect to {self.ip}!")
else: raise BaseException("A connection is already in progress!")

def disconnect(self):
self.connected:bool = False

def connect(self, timeout:int = 5)->None:
if self.ip and self.ip != "" and not self.connected:
try:
self.socket.settimeout(timeout)
self.socket.connect((str(self.ip), 7331))
self.socket.settimeout(None)
self.connected = True
except: raise BaseException(f"Unable to connect to {self.ip}!")
else: raise BaseException("A connection is already in progress!")


def disconnect(self)->None:
if self.connected:
self.socket.close() # TODO: Make checks
self.connected = False
else: raise BaseException("No connection is in progress!")

def isConnected(self):
def isConnected(self)->bool:
return self.connected

def validRange(self, address, length):
def validRange(self, address, length)->bool:
if 0x01000000 <= address and address + length <= 0x01800000: return True
elif 0x0E000000 <= address and address + length <= 0x10000000: return True #Depends on game
elif 0x10000000 <= address and address + length <= 0x50000000: return True #Doesn't quite go to 5
@@ -52,7 +51,7 @@ def validRange(self, address, length):
elif 0xFFFE0000 <= address and address + length <= 0xFFFFFFFF: return True
else: return False

def validAccess(self, address, length, access):
def validAccess(self, address:int, length:int, access:str)->bool:
if 0x01000000 <= address and address + length <= 0x01800000:
if access.lower() == "read" : return True
if access.lower() == "write": return False
@@ -85,81 +84,61 @@ def validAccess(self, address, length, access):
if access.lower() == "write": return True
else: return False

def poke8(self, address, value, skip = False):
if self.connected:
if not skip:
if not self.validRange(address, 1): raise BaseException("Address range not valid")
if not self.validAccess(address, 1, "write"): raise BaseException("Cannot write to address")
def isValidMemoryArea(self,address:int, lenght:int, should_validate:bool)->bool:
if should_validate: return self.validRange(address, lenght) and self.validAccess(address, lenght, "write")
return True

def poke8(self, address:int, value:int, skip:bool = False)->None:
if self.connected and self.isValidMemoryArea(address, 1, skip):
self.socket.send(b'\x01')
req = struct.pack(">II", int(address), int(value))
req = struct.pack(">II", address, value)
self.socket.send(req)
return
else: raise BaseException("No connection is in progress!")

def poke16(self, address, value, skip = False):
if self.connected:
if not skip:
if not self.validRange(address, 2): raise BaseException("Address range not valid")
if not self.validAccess(address, 2, "write"): raise BaseException("Cannot write to address")
def poke16(self, address:int, value:int, skip:bool = False)->None:
if self.connected and self.isValidMemoryArea(address, 2, skip):
self.socket.send(b'\x02')
req = struct.pack(">II", int(address), int(value))
req = struct.pack(">II", address, value)
self.socket.send(req)
return
else: raise BaseException("No connection is in progress!")

def poke32(self, address, value, skip = False):
if self.connected:
if not skip:
if not self.validRange(address, 4): raise BaseException("Address range not valid")
if not self.validAccess(address, 4, "write"): raise BaseException("Cannot write to address")
def poke32(self, address:int, value:int, skip:bool = False)->None:
if self.connected and self.isValidMemoryArea(address, 4, skip):
self.socket.send(b'\x03')
req = struct.pack(">II", int(address), int(value))
req = struct.pack(">II", address, value)
self.socket.send(req)
return
else: raise BaseException("No connection is in progress!")

def serialPoke(self, addressTable, value, skip = False):
if self.connected:
if isinstance(addressTable, list):
for address in addressTable:
if not skip:
if not self.validRange(address, 4): raise BaseException("Address range not valid")
if not self.validAccess(address, 4, "write"): raise BaseException("Cannot write to address")
self.socket.send(b"\x03")
req = struct.pack(">II", address, value)
self.socket.send(req)
return
else: raise BaseException("Address is not a list!")
else: raise BaseException("No connection is in progress!")
def serialPoke(self, addressTable:list, value:int, skip:bool = False)->None:
for address in addressTable:
if type(address)==int: self.poke32(address, value,skip)

def writeString(self, address, string, skip = False):
def writeString(self, address:int, string:str, skip:bool = False)->None:
if self.connected:
if type(string) != bytes: string = bytes(string, "UTF-8") #Sanitize
if len(string) % 4: string += bytes((4 - (len(string) % 4)) * b"\x00")
pos = 0
for x in range(int(len(string) / 4)):
self.poke32(address, struct.unpack(">I", string[pos:pos + 4])[0], skip)
address += 4;pos += 4
return
else: raise BaseException("No connection is in progress!")

def clearString(self, startAddress, endAddress, skip = False):
def clearString(self, startAddress:int, endAddress:int, skip = False)->None:
if self.connected:
length = endAddress - startAddress
i = 0
while i <= length:
self.poke32(startAddress + i, 0x00000000, skip)
i += 4
return
else: raise BaseException("No connection is in progress!")

def readString(self, address, length, skip = False):
def readString(self, address:int, length:int, skip:bool = False)->str:
if self.connected:
string = self.read(address, length, skip)
return string.decode('UTF-8')
else: raise BaseException("No connection is in progress!")

def read(self, address, length, skip = False):
def read(self, address:int, length:int, skip:bool = False)->bytearray:
if self.connected:
if not skip:
if length == 0: raise BaseException("Reading memory requires a length!")
@@ -194,95 +173,93 @@ def read(self, address, length, skip = False):
return ret
else: raise BaseException("No connection is in progress!")

def kernelWrite(self, address, value, skip = False):
def kernelWrite(self, address:int, value:int, skip:bool = False)->None:
if self.connected:
if not skip:
if not self.validRange(address, 4): raise BaseException("Address range not valid")
if not self.validAccess(address, 4, "write"): raise BaseException("Cannot write to address")
self.socket.send(b'\x0B')
req = struct.pack(">II", int(address), int(value))
self.socket.send(req)
return
else: raise BaseException("No connection is in progress!")

def kernelRead(self, address, skip = False):
if self.connected:
if not skip:
if not self.validRange(address, 4): raise BaseException("Address range not valid")
if not self.validAccess(address, 4, "read"): raise BaseException("Cannot read to address")
def kernelRead(self, address:int, skip:bool = False)->int:
if self.connected and self.isValidMemoryArea(address, 4, skip):
self.socket.send(b'\x0C')
req = struct.pack(">I", int(address))
self.socket.send(req)
return struct.unpack(">I", self.socket.recv(4))[0]
else: raise BaseException("No connection is in progress!")

def getServerStatus(self):
def getServerStatus(self)->int:
if self.connected:
self.socket.send(b'\x50')
return int.from_bytes(self.socket.recv(1), "big")
else: raise BaseException("No connection is in progress!")

def isConsolePaused(self):
def isConsolePaused(self)->bool:
if self.connected:
self.socket.send(b'\x84')
val = int.from_bytes(self.socket.recv(1), "big")
if val == 1: return True
else: return False
return int.from_bytes(self.socket.recv(1), "big")
else: raise BaseException("No connection is in progress!")

def pauseConsole(self):
def pauseConsole(self)->None:
if self.connected: self.socket.send(b'\x82')
else: raise BaseException("No connection is in progress!")

def resumeConsole(self):
def resumeConsole(self)->None:
if self.connected: self.socket.send(b'\x83')
else: raise BaseException("No connection is in progress!")

def getServerVersion(self):
def getServerVersion(self)->str:
if self.connected:
self.socket.send(b'\x99')
return self.socket.recv(16).decode("UTF-8").replace('\n', '')
else: raise BaseException("No connection is in progress!")

def getOsVersion(self):
def getOsVersion(self)->int:
if self.connected:
self.socket.send(b'\x9A')
return int.from_bytes(self.socket.recv(4), "big")
else: raise BaseException("No connection is in progress!")

def getVersionHash(self):
def getVersionHash(self)->int:
if self.connected:
self.socket.send(b'\xE0')
return int.from_bytes(self.socket.recv(4), "big")
else: raise BaseException("No connection is in progress!")

def getAccountID(self):
def getAccountID(self)->str:
if self.connected:
self.socket.send(b'\x57')
return hex(int.from_bytes(self.socket.recv(4), "big")).replace("0x", "")
else: raise BaseException("No connection is in progress!")

def getCoreHandlerAddress(self):
def getCoreHandlerAddress(self)->int:
if self.connected:
self.socket.send(b'\x55')
return hex(int.from_bytes(self.socket.recv(4), "big"))
return int.from_bytes(self.socket.recv(4), "big")
else: raise BaseException("No connection is in progress!")

def getDataBufferSize(self):
def getDataBufferSize(self)->int:
if self.connected:
self.socket.send(b'\x51')
return int.from_bytes(self.socket.recv(4), "big")
else: raise BaseException("No connection is in progress!")

def search(self, startAddress, value, length):
def getTitleID(self)->int:
function = self.getSymbol("coreinit.rpl", "OSGetTitleID")
return self.call(function)

def search(self, startAddress:int, value:int, length:int)->int:
if self.connected:
self.socket.send(b'\x72')
req = struct.pack(">III", int(startAddress), int(value), int(length))
req = struct.pack(">III", startAddress, value, length)
self.socket.send(req)
return hex(int.from_bytes(self.socket.recv(4), "big"))
return int.from_bytes(self.socket.recv(4), "big")
else: raise BaseException("No connection is in progress!")

def advancedSearch(self, start, length, value, kernel, limit, aligned = 1):
def advancedSearch(self, start:int, length:int, value:int, kernel:int, limit:int, aligned:int = 1)->list:
if self.connected:
self.socket.send(b'\x73')
req_val = struct.pack(">I", int(value))
@@ -293,11 +270,11 @@ def advancedSearch(self, start, length, value, kernel, limit, aligned = 1):
count = int.from_bytes(self.socket.recv(4), "big") / 4
foundOffset = []
for i in range(int(count)):
foundOffset.append(hex(int.from_bytes(self.socket.recv(4), "big")))
foundOffset.append(int.from_bytes(self.socket.recv(4), "big"))
return foundOffset
else: raise BaseException("No connection is in progress!")

def getSymbol(self, rplname, sysname, data = 0):
def getSymbol(self, rplname:str, sysname:str, data = 0)->int:
if self.connected:
self.socket.send(b'\x71')
req = struct.pack('>II', 8, 8 + len(rplname) + 1)
@@ -311,7 +288,7 @@ def getSymbol(self, rplname, sysname, data = 0):
return self.socket.recv(4)
else: raise BaseException("No connection is in progress!")

def call(self, address, *args):
def call(self, address:int, *args):
if self.connected:
arguments = list(args)
if len(arguments) <= 8:
@@ -321,33 +298,33 @@ def call(self, address, *args):
req = struct.pack(">I8I", address, *arguments)
self.socket.send(b'\x70')
self.socket.send(req)
return struct.unpack('>I', self.socket.recv(8)[:4])[0]
return struct.unpack('>Q', self.socket.recv(8))[0]
else:
raise BaseException("Too many arguments!")
else: raise BaseException("No connection is in progress!")

def getEntryPointAddress(self):
def getEntryPointAddress(self)->int:
if self.connected:
self.socket.send(b'\xB1')
return hex(int.from_bytes(self.socket.recv(4), "big"))
return int.from_bytes(self.socket.recv(4), "big")
else: raise BaseException("No connection is in progress!")

def runKernelCopyService(self):
def runKernelCopyService(self)->None:
if self.connected: self.socket.send(b'\xCD')
else: raise BaseException("No connection is in progress!")

def clearAssembly(self):
def clearAssembly(self)->None:
if self.connected: self.socket.send(b'\xE2')
else: raise BaseException("No connection is in progress!")

def excecuteAssembly(self, assembly):
def excecuteAssembly(self, assembly:str)->None:
if self.connected:
self.socket.send(b'\x81')
req = assembly.encode('UTF-8')
self.socket.send(req)
else: raise BaseException("No connection is in progress!")

def persistAssembly(self, assembly):
def persistAssembly(self, assembly:str)->None:
if self.connected:
self.socket.send(b'\xE1')
req = assembly.encode('UTF-8')