Last active
May 26, 2020 04:22
-
-
Save stong/d485cae516cccab2d37a77db3c92ec4a to your computer and use it in GitHub Desktop.
Automated script for cracking Sublime Text and Sublime Merge
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
also, i should patch the deferred callback