Skip to content

Commit

Permalink
Add script support for 0.6.3
Browse files Browse the repository at this point in the history
  • Loading branch information
CarlGao4 committed Jun 24, 2024
1 parent 18df3df commit e75f0af
Show file tree
Hide file tree
Showing 2 changed files with 85 additions and 7 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ See [sts](sts.md) for more information.

Actually, I didn't find out how this file is encrypted. Instead, I used [frida](https://frida.re/) and other deassemblers to trace the MuseSamplerCoreLib and read the memory.

I've created a demo Python script ([read-decrypted-sfz.py](read-decrypted-sfz.py)) to capture all decrypted chunks by reading the memory. The script is only designed for Windows and MuseSampler version `0.5.1`. To use it, you will need to start MuseScore Studio 4 and run the script (You may need to install `frida-tools`).
I've created a demo Python script ([read-decrypted-sfz.py](read-decrypted-sfz.py)) to capture all decrypted chunks by reading the memory. The script is only designed for Windows and MuseSampler version `0.5.1` and `0.6.3`. To use it, you will need to start MuseScore Studio 4 and run the script (You may need to install `frida-tools`).

If your MuseSampler version is different, you can download version `0.5.1` from [release](https://github.com/CarlGao4/Muse-Sounds/releases/tag/MuseSamplerCoreLib) and replace the MuseSamplerCoreLib.dll file (usually located at `C:\Windows\System32\`).
90 changes: 84 additions & 6 deletions read-decrypted-sfz.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,109 @@

import frida
import sys
import threading

assert sys.platform == "win32", "This script is for Windows only"


# TODO: Change this to your MuseSampler version
MuseSampler_version = "0.6.3" # Change this to your version
# TODO: Set this to False if you don't want to print the output to console
print_output = True
# TODO: Set this to True if you want to save the output to decrypted.out
save_output = False
# TODO: Set this to True to try to find the correct address automatically
auto_find_address = False


# Is it possible to just search for "F3 0F7F 0B" in MuseSamplerCoreLib.dll?
# The address below is the next instruction after the above instruction
# The next instruction is "48 83 C3 10"
# I found 3 addresses in MuseSamplerCoreLib.dll that match the above pattern
# The first one is the correct one, but I can't guarantee it will work for all versions
# Maybe the best way is to add breakpoints to all 3 addresses and see which one works?
version_mappings = {
"0.5.1": "0x205772",
"0.6.3": "0x20B562"
}

session = frida.attach("MuseScore4.exe")

if auto_find_address:
script_code_find_addr = """
var modules = Process.enumerateModulesSync();
function toUTF16(inputString) {
const utf16CodeUnits = [];
for (let i = 0; i < inputString.length; i++) {
const charCode = inputString.charCodeAt(i);
utf16CodeUnits.push(charCode & 0xff);
utf16CodeUnits.push((charCode >> 8) & 0xff);
}
return new Uint8Array(utf16CodeUnits);
}
for (var i = 0; i < modules.length; i++) {
var module = modules[i];
if (module.name === "MuseSamplerCoreLib.dll") {
var base = module.base;
var pattern = "F3 0F 7F 0B 48 83 C3 10";
var matches = Memory.scanSync(base, module.size, pattern);
for (var j = 0; j < matches.length; j++) {
send("match", toUTF16(matches[j].address.sub(module.base).add(4).toString()));
}
break;
}
}
send("find_done");
"""
found_event = threading.Event()
addr_auto = ""
def on_message_find_addr(message, data):
if message["type"] == "send" and message["payload"] == "match":
print(f"Found address: MuseSamplerCoreLib.dll+{data.decode('utf-16')[2:]}")
global addr_auto
if not addr_auto:
addr_auto = data.decode("utf-16")
if message["type"] == "send" and message["payload"] == "find_done":
found_event.set()
script_find_addr = session.create_script(script_code_find_addr)
script_find_addr.on("message", on_message_find_addr)
script_find_addr.load()
found_event.wait()
script_find_addr.unload()
if not addr_auto:
print("Failed to find address automatically")
sys.exit(1)
print(f"Using address: MuseSamplerCoreLib.dll+{addr_auto[2:]}")


script_code = """
Interceptor.attach(Module.findBaseAddress("MuseSamplerCoreLib.dll").add(0x205772), {
Interceptor.attach(Module.findBaseAddress("MuseSamplerCoreLib.dll").add(%s), {
onEnter: function (args) {
const buf = ptr(this.context.rbx).readByteArray(16);
send("decode", buf);
}
});
"""
session = frida.attach("MuseScore4.exe")
""" % (addr_auto if auto_find_address else version_mappings[MuseSampler_version])
out = b""


def on_message(message, data):
global out
if message["type"] == "send" and message["payload"] == "decode":
out += data
if print_output:
print(data.rstrip(b"\x00").decode("utf-8"), end="")
if data.endswith(b"\x00"):
print("\n" + "-" * 20)


script = session.create_script(script_code)
script.on("message", on_message)
script.load()

input("Press Enter to stop monitoring and save captured outputs to decrypted.out (overwrite)")
with open("decrypted.out", mode="wb") as f:
f.write(out)
input("Press Enter to stop monitoring")
script.unload()
session.detach()
if save_output:
with open("decrypted.out", mode="wb") as f:
f.write(out)

0 comments on commit e75f0af

Please sign in to comment.