Skip to content

Instantly share code, notes, and snippets.

@kulinacs
Created April 5, 2021 01:51
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kulinacs/c087d6ac27ac9e0ddc6d67ca010023f8 to your computer and use it in GitHub Desktop.
Save kulinacs/c087d6ac27ac9e0ddc6d67ca010023f8 to your computer and use it in GitHub Desktop.
slippi discord bot
import json
import sys
import frida
import requests
WEBHOOK = ""
def get_player(uid):
return requests.get(f"https://users-rest-dot-slippi.uc.r.appspot.com/user/{uid}").json()
def send_results(content):
players = {player["uid"]: get_player(player["uid"]) for player in content["players"]}
title = " vs. ".join(f"{player['displayName']} ({player['connectCode']})" for player in players.values())
message = {
"content": title,
"embeds": [
{
"title": title,
"description": "Slippi Netplay Match Stats",
"fields": [
{
"name": "Match Number",
"value": content["gameIndex"]
},
{
"name": "Duration",
"value": f"{content['gameDurationFrames'] / 60} seconds"
}
]
}
]
}
for player in content["players"]:
message["embeds"][0]["fields"].append(
{
"name": f"{players[player['uid']]['displayName']} ({players[player['uid']]['connectCode']})",
"value": f"Damage Done: {player['damageDone']}\nStocks Remaining: {player['stocksRemaining']}",
"inline": True
})
requests.post(WEBHOOK, json=message)
def on_message(message, data):
try:
payload = message['payload']
if payload['type'] == 'matchResult':
send_results(json.loads(payload['content']))
except KeyError:
print("unable to handled malformed message")
def main():
session = frida.attach("Slippi Dolphin.exe")
script = session.create_script("""
console.log("starting script");
var CurlEasySetOpt = ptr('0xeecef0'); // function address pulled from Ghidra
Interceptor.attach(CurlEasySetOpt, {
onEnter: function (args) {
let opt = args[1].toInt32()
if (opt == 10015) {
console.log("Match completed, sending webhook")
send({"type": "matchResult", "content": args[2].readCString()})
}
},
// When function is finished
onLeave: function (retval) {
}
});
""")
script.on('message', on_message)
script.load()
print("[!] Ctrl+D on UNIX, Ctrl+Z on Windows/cmd.exe to detach from instrumented program.\n\n")
sys.stdin.read()
session.detach()
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment