Skip to content

Instantly share code, notes, and snippets.

@Aqcurate
Last active August 9, 2022 00:33
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 Aqcurate/53d4027d95bedfd347bfc36e07464be0 to your computer and use it in GitHub Desktop.
Save Aqcurate/53d4027d95bedfd347bfc36e07464be0 to your computer and use it in GitHub Desktop.
major malfunction writeup

Major Malfunction

We see that there are long notes (4 beats) and short notes (1 beat) throughout the midi file given. The long notes represent the intended key and the short notes encode the flag in base 7 depending on its degree in the long note's key.

So for example, for the first measure, if we had c as the long note, and [d,e,f,c] as the short notes. This would translate to 1230.

If we have a key and a note, then the below code will get the degree of that note.

degrees = [0, 2, 4, 5, 7, 9, 11, 12]
degree = degrees.index((note - key) % 12)

After translating the midi file, we get

35325334165314424130161654514441250625262113221342661226243366520364044001356220465061044030136561452062650045543215005166210306640

which decodes to uscg{b9e87122589167966989853582e619906bb24648}.

from mido import MidiFile
import mido as mido
from Crypto.Util.number import long_to_bytes
midi_file = MidiFile('major.midi')
degrees = [0, 2, 4, 5, 7, 9, 11, 12]
def select_notes_from_file(midi_file):
midi_file = MidiFile(midi_file)
track = mido.merge_tracks(midi_file.tracks)
notes = []
on = []
for msg in track:
m = msg.dict()
if m.get('type') == 'note_on' and m.get('velocity') != 0:
on.append(m.get('note'))
if m.get('type') == 'note_off':
if len(on) == 2:
notes.append(on[:])
on.remove(m.get('note'))
return notes
notes = select_notes_from_file('major.midi')
notes.append([48, 48]) # temp note to make hack parsing work
res = ''
for i in range(0, len(notes), 4):
block = notes[i:i+4]
# hacky parsing
# note that appears in all four beats = long note representing key
key = set(block[0])
for x in block:
key &= set(x)
key = list(key)[0]
for x in block:
x.remove(key)
indicies = [degrees.index((x[0] - key) % 12) for x in block]
res += ''.join([str(x) for x in indicies])
res = res[:-1] # remove temp note
res = int(res, 7)
res = long_to_bytes(res)
print(res.decode())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment