Skip to content

Instantly share code, notes, and snippets.

@stong
Last active May 26, 2020 04:22
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save stong/d485cae516cccab2d37a77db3c92ec4a to your computer and use it in GitHub Desktop.
Save stong/d485cae516cccab2d37a77db3c92ec4a to your computer and use it in GitHub Desktop.
Automated script for cracking Sublime Text and Sublime Merge
# Disclaimer and license
# This code is provided without any warranty whatsoever, express or implied. I don't take responsibility for what you choose to do with it.
# Only use this code in accordance with United States and local law. It is provided for educational purposes only.
# Don't use the code unless you already own a legitimate product license for Sublime Text or Sublime Merge.
# By using or studying the code you agree to abide by these terms and conditions.
# Do not contact me if the script is broken because I am not offering support for it.
# You may freely redistribute this code as long as this license is also attached.
# this script should be run in the binaryninja console
def yeet():
fake_license = bv.find_next_data(here, '00000000000000000000000000000000')
license_xrefs = bv.get_code_refs(fake_license)
for xref in license_xrefs:
func = xref.function
llil_index = func.llil.get_instruction_start(xref.address)
if not llil_index: continue
mlil_index = func.llil.get_medium_level_il_instruction_index(llil_index)
if not mlil_index: continue
mlil_insn = func.mlil[mlil_index]
if not mlil_insn: continue
if mlil_insn.operation != MediumLevelILOperation.MLIL_CALL: continue
call_params = mlil_insn.operands[2]
if not (len(call_params) == 2 and call_params[1].operation == MediumLevelILOperation.MLIL_CONST_PTR and call_params[1].value.value == fake_license): continue
check_branch = xref.address + 13 # hardcoded offset hack, should be replaced by disassembling forwards
mlil_index = func.mlil.get_instruction_start(check_branch)
if not mlil_index: continue
if func.mlil[mlil_index].operation != MediumLevelILOperation.MLIL_IF: continue
patch_bb = func.get_basic_block_at(func.mlil[func.mlil[mlil_index].false].address)
if not patch_bb:
print('FAILED!')
return False
print('located patch spot around', hex(patch_bb.start), ':', mlil_insn)
cur_insn_addr = patch_bb.start
patched_call, patched_branch = False, False
for disasm, insn_len in patch_bb:
mlil_index = func.mlil.get_instruction_start(cur_insn_addr)
if mlil_index:
mlil_insn = func.mlil[mlil_index]
if str(disasm[0]) == 'call':
# patch license check function
print('located call at', hex(cur_insn_addr), ':', mlil_insn)
check_func = bv.get_function_at(mlil_insn.operands[1].value.value)
if not check_func:
print('FAILED!')
return False
bv.write(check_func.start,check_func.arch.assemble('mov eax, 1\nret'))
patched_call = True
elif str(disasm[0]) == 'jne':
# patch license check check
print('located conditional jump at', hex(cur_insn_addr), ':', mlil_insn)
if not bv.always_branch(cur_insn_addr):
print('FAILED!')
return False
patched_branch = True
break
cur_insn_addr += insn_len
if patched_call and patched_branch:
print('success :)')
return True
else:
print('failed to find patch instructions')
return False
print('failed to find patch location')
return False
if yeet():
outname = 'sublime_text_patched.exe'
bv.save(outname)
print('saved to', outname)
@stong
Copy link
Author

stong commented May 25, 2020

also, i should patch the deferred callback

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment