Created
September 21, 2024 08:25
-
-
Save lihaochen910/92e33548fe5b8313cd17897a972cdf30 to your computer and use it in GitHub Desktop.
Hopper Script: 自动patch CSP试用版验证方法
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
from typing import get_type_hints | |
class HPInstruction: | |
ARCHITECTURE_UNKNOWN = 0 | |
ARCHITECTURE_i386 = 1 | |
ARCHITECTURE_X86_64 = 2 | |
ARCHITECTURE_ARM = 3 | |
ARCHITECTURE_ARM_THUMB = tuple() | |
ARCHITECTURE_AARCH64 = tuple() | |
ARCHITECTURE_OTHER = 99 | |
def stringForArchitecture(): | |
pass | |
def getArchitecture(self): | |
pass | |
def getInstructionString(self) -> str: | |
pass | |
def getArgumentCount(self) -> int: | |
pass | |
def getRawArgument(self): | |
pass | |
def getFormattedArgument(self): | |
pass | |
def isAnInconditionalJump(self): | |
pass | |
def isAConditionalJump(self): | |
pass | |
def getInstructionLength(self): | |
pass | |
class HPSegment: | |
BAD_ADDRESS = -1 | |
TYPE_UNDEFINED = 0 | |
TYPE_OUTSIDE = 1 | |
TYPE_NEXT = 2 | |
TYPE_INT8 = 3 | |
TYPE_INT16 = 4 | |
TYPE_INT32 = 5 | |
TYPE_INT64 = 6 | |
TYPE_ASCII = 7 | |
TYPE_UNICODE = 8 | |
TYPE_ALIGN = 63 | |
TYPE_CODE = 65 | |
TYPE_PROCEDURE = 66 | |
TYPE_STRUCTURE = 67 | |
def stringForType(): | |
pass | |
def getName(self): | |
pass | |
def getStartingAddress(self): | |
pass | |
def getLength(self): | |
pass | |
def getFileOffset(self): | |
pass | |
def getFileOffsetForAddress(self): | |
pass | |
def getSectionCount(self): | |
pass | |
def getSection(self): | |
pass | |
def getSectionsList(self): | |
pass | |
def getSectionIndexAtAddress(self): | |
pass | |
def getSectionAtAddress(self): | |
pass | |
def readBytes(self): | |
pass | |
def readByte(self): | |
pass | |
def readUInt16LE(self): | |
pass | |
def readUInt32LE(self): | |
pass | |
def readUInt64LE(self): | |
pass | |
def readUInt16BE(self): | |
pass | |
def readUInt32BE(self): | |
pass | |
def readUInt64BE(self): | |
pass | |
def writeBytes(self): | |
pass | |
def writeByte(self): | |
pass | |
def writeUInt16LE(self): | |
pass | |
def writeUInt32LE(self): | |
pass | |
def writeUInt64LE(self): | |
pass | |
def writeUInt16BE(self): | |
pass | |
def writeUInt32BE(self): | |
pass | |
def writeUInt64BE(self): | |
pass | |
def markAsUndefined(self): | |
pass | |
def markRangeAsUndefined(self): | |
pass | |
def markAsCode(self): | |
pass | |
def markAsProcedure(self): | |
pass | |
def markAsDataByteArray(self): | |
pass | |
def markAsDataShortArray(self): | |
pass | |
def markAsDataIntArray(self): | |
pass | |
def isThumbAtAddress(self): | |
pass | |
def setThumbModeAtAddress(self): | |
pass | |
def setARMModeAtAddress(self): | |
pass | |
def getTypeAtAddress(self): | |
pass | |
def setTypeAtAddress(self): | |
pass | |
def makeAlignment(self): | |
pass | |
def getNextAddressWithType(self): | |
pass | |
def disassembleWholeSegment(self): | |
pass | |
def setNameAtAddress(self): | |
pass | |
def getNameAtAddress(self): | |
pass | |
def getDemangledNameAtAddress(self): | |
pass | |
def getCommentAtAddress(self): | |
pass | |
def setCommentAtAddress(self): | |
pass | |
def getInlineCommentAtAddress(self): | |
pass | |
def setInlineCommentAtAddress(self): | |
pass | |
def getInstructionAtAddress(self) -> HPInstruction: | |
pass | |
def getReferencesOfAddress(self) -> []: | |
pass | |
def getReferencesFromAddress(self): | |
pass | |
def addReference(self): | |
pass | |
def removeReference(self): | |
pass | |
def getLabelCount(self): | |
pass | |
def getLabelName(self): | |
pass | |
def labelIterator(self): | |
pass | |
def getLabelsList(self): | |
pass | |
def getNamedAddresses(self): | |
pass | |
def getProcedureCount(self): | |
pass | |
def getProcedureAtIndex(self): | |
pass | |
def getProcedureIndexAtAddress(self): | |
pass | |
def getProcedureAtAddress(self): | |
pass | |
def getInstructionStart(self): | |
pass | |
def getObjectLength(self): | |
pass | |
def isPartOfAnArray(self): | |
pass | |
def getArrayStartAddress(self): | |
pass | |
def getArrayElementCount(self): | |
pass | |
def getArrayElementAddress(self): | |
pass | |
def getArrayElementSize(self): | |
pass | |
class HPDocument: | |
FORMAT_DEFAULT = 0 | |
FORMAT_HEXADECIMAL = 1 | |
FORMAT_DECIMAL = 2 | |
FORMAT_OCTAL = 3 | |
FORMAT_CHARACTER = 4 | |
FORMAT_STACKVARIABLE = 5 | |
FORMAT_OFFSET = 6 | |
FORMAT_ADDRESS = 7 | |
FORMAT_FLOAT = 8 | |
FORMAT_BINARY = 9 | |
FORMAT_STRUCTURED = 10 | |
FORMAT_ENUM = 11 | |
FORMAT_ADDRESS_DIFF = 12 | |
FORMAT_NEGATE = 32 | |
FORMAT_LEADINGZEROES = 64 | |
FORMAT_SIGNED = 128 | |
def newDocument(): | |
pass | |
def getCurrentDocument(): | |
pass | |
def getAllDocuments(): | |
pass | |
def ask(): | |
pass | |
def askFile(): | |
pass | |
def askDirectory(): | |
pass | |
def message(): | |
pass | |
def closeDocument(self): | |
pass | |
def loadDocumentAt(self): | |
pass | |
def saveDocument(self): | |
pass | |
def saveDocumentAt(self): | |
pass | |
def getDocumentName(self): | |
pass | |
def setDocumentName(self): | |
pass | |
def backgroundProcessActive(self): | |
pass | |
def requestBackgroundProcessStop(self): | |
pass | |
def waitForBackgroundProcessToEnd(self): | |
pass | |
def assemble(self): | |
pass | |
def getDatabaseFilePath(self): | |
pass | |
def getExecutableFilePath(self): | |
pass | |
def setExecutableFilePath(self): | |
pass | |
def log(self): | |
pass | |
def rebase(self): | |
pass | |
def newSegment(self): | |
pass | |
def deleteSegment(self): | |
pass | |
def renameSegment(self): | |
pass | |
def getSegmentCount(self): | |
pass | |
def getSegment(self) -> HPSegment: | |
pass | |
def getSegmentByName(self): | |
pass | |
def getSectionByName(self): | |
pass | |
def getSegmentsList(self): | |
pass | |
def getSegmentIndexAtAddress(self): | |
pass | |
def getSegmentAtAddress(self): | |
pass | |
def getSectionAtAddress(self): | |
pass | |
def getCurrentSegmentIndex(self): | |
pass | |
def getCurrentSegment(self): | |
pass | |
def getCurrentSection(self): | |
pass | |
def getCurrentProcedure(self): | |
pass | |
def getCurrentAddress(self): | |
pass | |
def setCurrentAddress(self): | |
pass | |
def getSelectionAddressRange(self): | |
pass | |
def moveCursorAtAddress(self): | |
pass | |
def selectAddressRange(self): | |
pass | |
def getFileOffsetFromAddress(self): | |
pass | |
def getAddressFromFileOffset(self): | |
pass | |
def is64Bits(self): | |
pass | |
def getEntryPoint(self): | |
pass | |
def moveCursorAtEntryPoint(self): | |
pass | |
def getHighlightedWord(self): | |
pass | |
def setNameAtAddress(self): | |
pass | |
def getNameAtAddress(self): | |
pass | |
def getAddressForName(self): | |
pass | |
def refreshView(self): | |
pass | |
def moveCursorOneLineDown(self): | |
pass | |
def moveCursorOneLineUp(self): | |
pass | |
def getRawSelectedLines(self): | |
pass | |
def addTagAtAddress(self): | |
pass | |
def removeTagAtAddress(self): | |
pass | |
def hasTagAtAddress(self): | |
pass | |
def getTagCountAtAddress(self): | |
pass | |
def getTagAtAddressByIndex(self): | |
pass | |
def tagIteratorAtAddress(self): | |
pass | |
def getTagListAtAddress(self): | |
pass | |
def getTagCount(self): | |
pass | |
def getTagAtIndex(self): | |
pass | |
def tagIterator(self): | |
pass | |
def getTagList(self): | |
pass | |
def buildTag(self): | |
pass | |
def getTagWithName(self): | |
pass | |
def destroyTag(self): | |
pass | |
def hasColorAtAddress(self): | |
pass | |
def setColorAtAddress(self): | |
pass | |
def getColorAtAddress(self): | |
pass | |
def removeColorAtAddress(self): | |
pass | |
def readBytes(self): | |
pass | |
def readByte(self): | |
pass | |
def readUInt16LE(self): | |
pass | |
def readUInt32LE(self): | |
pass | |
def readUInt64LE(self): | |
pass | |
def readUInt16BE(self): | |
pass | |
def readUInt32BE(self): | |
pass | |
def readUInt64BE(self): | |
pass | |
def writeBytes(self): | |
pass | |
def writeByte(self): | |
pass | |
def writeUInt16LE(self): | |
pass | |
def writeUInt32LE(self): | |
pass | |
def writeUInt64LE(self): | |
pass | |
def writeUInt16BE(self): | |
pass | |
def writeUInt32BE(self): | |
pass | |
def writeUInt64BE(self): | |
pass | |
def getOperandFormat(self): | |
pass | |
def getOperandFormatRelativeTo(self): | |
pass | |
def setOperandFormat(self): | |
pass | |
def setOperandRelativeFormat(self): | |
pass | |
def getInstructionStart(self): | |
pass | |
def getObjectLength(self): | |
pass | |
def generateObjectiveCHeader(self): | |
pass | |
def produceNewExecutable(self): | |
pass | |
def setBookmarkAtAddress(self): | |
pass | |
def removeBookmarkAtAddress(self): | |
pass | |
def hasBookmarkAtAddress(self): | |
pass | |
def renameBookmarkAtAddress(self): | |
pass | |
def findBookmarkWithName(self): | |
pass | |
def getBookmarkName(self): | |
pass | |
def getBookmarks(self): | |
pass | |
trialSymbols = [ | |
'__ZN12Planeswalker4Urza21URApplicationBehavior38GetStringIDMessageQuestionTrialVersionEv', | |
'__ZN12Planeswalker4Urza21URApplicationBehavior35GetStringIDMessageErrorTrialVersionEv', | |
] | |
trialSymbols_GetStringIDMessageQuestionTrialVersionEv = '__ZN12Planeswalker4Urza21URApplicationBehavior38GetStringIDMessageQuestionTrialVersionEv' | |
trialSymbols_GetStringIDMessageErrorTrialVersionEv = '__ZN12Planeswalker4Urza21URApplicationBehavior35GetStringIDMessageErrorTrialVersionEv' | |
def byteListToString(byteList): | |
str = '[' | |
for byte in byteList: | |
str += '%02X ' % byte | |
str += ']' | |
return str | |
class PatchContext: | |
def __init__(self, doc : HPDocument, seg : HPSegment, addr : int): | |
self.doc = doc | |
self.seg = seg | |
self.addr = addr | |
class HPSegmentPatch: | |
PatchDescription = 'A base class for Patch' | |
def findPatternToPatch(doc : HPDocument) -> tuple: | |
raise NotImplementedError() | |
def backupOriginCode(): | |
pass | |
def applyPatch(context : PatchContext) -> bool: | |
raise NotImplementedError() | |
class Patch_SkipSelectTrialProductGradeType(HPSegmentPatch): | |
PatchDescription = '01. skip select trial product GradeType' | |
def findPatternToPatch(doc : HPDocument): | |
for seg_id in range(0, doc.getSegmentCount()): | |
seg : HPSegment = doc.getSegment(seg_id) | |
for label in seg.getLabelsList(): | |
if label == '__ZNK12Planeswalker4Urza22URRemoteControlManager37GetAlreadyStartedConnectionFromClientEv': | |
addr = doc.getAddressForName(label) | |
# print('found:', label, addr, type(addr)) | |
for xref in seg.getReferencesOfAddress(addr): | |
# i = seg.getInstructionAtAddress(xref) | |
print('xref: 0x%09x' % xref) | |
# using first xref | |
return True, PatchContext(doc, seg, xref) | |
break | |
def applyPatch(context : PatchContext) -> bool: | |
doc = context.doc | |
doc.moveCursorAtAddress(context.addr) | |
# move down 2 line | |
for _ in range(2): | |
doc.moveCursorOneLineDown() | |
cursorAddr = doc.getCurrentAddress() | |
instr = context.seg.getInstructionAtAddress(cursorAddr) | |
if not matchInstrcutionCmd( instr, 'je' ): | |
return False | |
# replace je with jne | |
# 0x74, 0x85 | |
# 0x75, 0x12 | |
# context.seg.writeByte( cursorAddr + 0, 0x75 ) | |
# context.seg.markAsCode( cursorAddr ) | |
# instr = context.seg.getInstructionAtAddress(cursorAddr) | |
# if not matchInstrcutionCmd( instr, 'jne' ): | |
# return False | |
return True | |
class Patch_BypassAllQuestionTrialVersion(HPSegmentPatch): | |
PatchDescription = '02. bypass all QuestionTrialVersion' | |
def findPatternToPatch(doc : HPDocument): | |
for seg_id in range(0, doc.getSegmentCount()): | |
seg : HPSegment = doc.getSegment(seg_id) | |
for label in seg.getLabelsList(): | |
if label == trialSymbols_GetStringIDMessageQuestionTrialVersionEv: | |
addr = doc.getAddressForName(label) | |
print('found:', label, addr, type(addr)) | |
patchContext = PatchContext(doc, seg, -1) | |
xrefs = [] | |
for xref in seg.getReferencesOfAddress(addr): | |
# i = seg.getInstructionAtAddress(xref) | |
# print('xref: 0x%09x' % xref) | |
xrefs.append(xref) | |
# using first xref | |
patchContext.xrefs = xrefs | |
return True, patchContext | |
def applyPatch(context : PatchContext) -> bool: | |
doc = context.doc | |
xrefs = context.xrefs | |
print( f'xrefs len: {len( xrefs )}' ) | |
for xref in xrefs: | |
doc.moveCursorAtAddress(xref) | |
xrefSegment = doc.getSegmentAtAddress(xref) | |
xrefSegment.setCommentAtAddress(xref, "xref to %s" % trialSymbols_GetStringIDMessageQuestionTrialVersionEv) | |
# move up 1 line | |
for _ in range(1): | |
doc.moveCursorOneLineUp() | |
cursorAddr = doc.getCurrentAddress() | |
instr = context.seg.getInstructionAtAddress(cursorAddr) | |
if not matchInstrcutionCmd( instr, 'jne' ): | |
print( f'found unsupported: {instr.getInstructionString()}' ) | |
return False | |
comment = "Instr Architecture: %s\n" % Instruction.stringForArchitecture(instr.getArchitecture()) | |
comment += f"Instruction: {instr.getInstructionString()}\n" | |
comment += f"Instruction Length: {instr.getInstructionLength()}\n" | |
comment += f"Instruction Args Count: {instr.getArgumentCount()}\n" | |
for idx in range(instr.getArgumentCount()): | |
comment += f"\targ{idx}: {instr.getFormattedArgument(idx)} {instr.getRawArgument(idx)}\n" | |
# jneParamBytes = [ 0xe9 ] | |
# argsHexStr = "" | |
# for j in range(2, instr.getInstructionLength()): | |
# argsHexStr += str("%02X " % xrefSegment.readByte(cursorAddr + j)) | |
# jneParamBytes.append(xrefSegment.readByte(cursorAddr + j)) | |
# comment += f"argsHex: {argsHexStr}\n" | |
# comment += f"overwrite below: E9 {argsHexStr}" | |
jneParamInstr = instr.getRawArgument(0) | |
xrefSegment.setCommentAtAddress(cursorAddr, comment) | |
# print( 'cursor instr: %s' % instr.getInstructionString() ) | |
# print( comment ) | |
# replace jmp | |
# 0x0f, 0x85 | |
# 0xe9 | |
# xrefSegment.writeByte( xref + 0, 0xe9 ) | |
doc.moveCursorAtAddress( xref ) | |
dst = 0 | |
# try: | |
# if jneParamInstr.startswith( "loc_" ): | |
# dst = int( f'0x{jneParamInstr.removeprefix("loc_")}', 16 ) | |
# print( f'parse loc_: {jneParamInstr} {dst:09x}' ) | |
# elif jneParamInstr.startswith( "_" ): | |
# dst = int( f'0x{doc.getAddressForName(jneParamInstr)}', 16 ) | |
# print( f'parse Name: {jneParamInstr} {dst:09x}' ) | |
# else: | |
# raise ValueError() | |
# except ValueError as e: | |
# print( f'ValueError on parse jneParamInstr: {jneParamInstr}' ) | |
# return False | |
try: | |
dst = int( jneParamInstr, 16 ) | |
except ValueError as e: | |
print( f'ValueError on parse jneParamInstr: {jneParamInstr}' ) | |
return False | |
# print( f'parse RawArgument: {jneParamInstr} {dst:09x}' ) | |
# return False | |
offset = dst - (xref + 5) # jmp Instr length in x86_64 | |
xrefSegment.writeByte(xref + 0, 0xE9) | |
xrefSegment.writeByte(xref + 1, ((offset >> 0) & 255)) | |
xrefSegment.writeByte(xref + 2, ((offset >> 8) & 255)) | |
xrefSegment.writeByte(xref + 3, ((offset >> 16) & 255)) | |
xrefSegment.writeByte(xref + 4, ((offset >> 24) & 255)) | |
xrefSegment.markAsCode(xref) | |
# # assemble | |
# # instrBytes = doc.assemble( f'jmp {jneParamInstr}', xref, 0 ) | |
# # instrBytes = doc.assemble( f'jmp {doc.getAddressFromFileOffset(jneParamInstr)}', xref, 0 ) | |
# paramAddr = doc.getFileOffsetFromAddress( int( f'0x{jneParamInstr.removeprefix("loc_")}', 16 ) ) | |
# instrBytes = doc.assemble( f'jmp {paramAddr}', xref, 0 ) | |
# if instrBytes: | |
# xrefSegment.writeBytes( xref, bytes( instrBytes ) ) | |
# xrefSegment.markAsCode( xref ) | |
# print( f'patched at: {xref} {byteListToString(instrBytes)}' ) | |
# return True | |
instr = xrefSegment.getInstructionAtAddress( xref ) | |
if not matchInstrcutionCmd( instr, 'jmp' ): | |
return False | |
else: | |
print( f'patched at: {xref:09x}' ) | |
return True | |
### Opcodes | |
nop_opcodes = { | |
1: 0x90, # 1 i386 | |
2: 0x90, # 2 x86_64 | |
3: 0x0000a0e1, # 3 ARM | |
} | |
### Functions | |
def write_nop(adr, arch, seg): | |
# doc.log("Writing NOP to 0x%08x" % adr) | |
seg.writeByte(adr, nop_opcodes[arch]) | |
seg.markAsCode(adr) | |
class Patch_BypassAllErrorTrialVersion(HPSegmentPatch): | |
PatchDescription = '03. bypass all ErrorTrialVersion' | |
def findPatternToPatch(doc : HPDocument): | |
for seg_id in range(0, doc.getSegmentCount()): | |
seg : HPSegment = doc.getSegment(seg_id) | |
for label in seg.getLabelsList(): | |
if label == trialSymbols_GetStringIDMessageErrorTrialVersionEv: | |
addr = doc.getAddressForName(label) | |
print('found:', label, addr, type(addr)) | |
patchContext = PatchContext(doc, seg, -1) | |
xrefs = [] | |
for xref in seg.getReferencesOfAddress(addr): | |
# i = seg.getInstructionAtAddress(xref) | |
# print('xref: 0x%09x' % xref) | |
xrefs.append(xref) | |
# using first xref | |
patchContext.xrefs = xrefs | |
return True, patchContext | |
def applyPatch(context : PatchContext) -> bool: | |
doc = context.doc | |
xrefs = context.xrefs | |
print( f'xrefs len: {len( xrefs )}' ) | |
for xref in xrefs: | |
doc.moveCursorAtAddress(xref) | |
xrefSegment = doc.getSegmentAtAddress(xref) | |
xrefSegment.setCommentAtAddress(xref, "xref to %s" % trialSymbols_GetStringIDMessageErrorTrialVersionEv) | |
sub_xrefs = [] | |
for sub_xref in xrefSegment.getReferencesOfAddress(xref): | |
sub_xrefs.append( sub_xref ) | |
instr = xrefSegment.getInstructionAtAddress(sub_xref) | |
arch = instr.getArchitecture() | |
if arch not in nop_opcodes: | |
doc.log("Error: CPU Architecture not supported") | |
else: | |
# arch_name = Instruction.stringForArchitecture(instr.getArchitecture()) | |
# doc.log("--- Inserting %s opcodes ---" % arch_name) | |
if arch != 3: # Ignore ARM | |
xrefSegment.setCommentAtAddress(sub_xref, "将要patch这里") | |
for index in range(instr.getInstructionLength()): | |
write_nop(sub_xref + index, arch, xrefSegment) | |
# print( f"write_nop({sub_xref + index})" ) | |
print( f'patched at: {xref:09x}' ) | |
return True | |
patchesForCSP = [ | |
Patch_SkipSelectTrialProductGradeType, | |
Patch_BypassAllQuestionTrialVersion, | |
Patch_BypassAllErrorTrialVersion | |
] | |
doc : HPDocument = Document.getCurrentDocument() | |
# seg = doc.getCurrentSegment() | |
# adr = doc.getCurrentAddress() | |
def print_exported_class(klass): | |
attrs = [k for k in klass.__dict__.keys() | |
if not k.startswith('__') | |
and not k.endswith('__')] | |
print('class %s:' % (klass.__name__)) | |
for attr in attrs: | |
attrTypeName = type(klass.__dict__[attr]).__name__ | |
if attrTypeName == 'function': | |
print('\tdef %s(self):' % (attr)) | |
print('\t\tpass\n') | |
elif attrTypeName == 'staticmethod': | |
print('\tdef %s():' % (attr)) | |
print('\t\tpass\n') | |
elif attrTypeName == 'int': | |
print('\t%s = %d' % (attr, klass.__dict__[attr])) | |
else: | |
print('unknown attrTypeName:', attrTypeName, attr) | |
print('\t%s = %s()' % (attr, attrTypeName)) | |
return attrs | |
# print_exported_class(Document) | |
# print_exported_class(seg.__class__) | |
# print_exported_class(Instruction) | |
def readInstructionToBytes(addr): | |
# bytes = [] | |
instr = seg.getInstructionAtAddress(addr) | |
bytes = seg.readBytes(addr, instr.getInstructionLength()) | |
bytesStr = '' | |
for b in bytes: | |
# print('byte: 0x%02x' % b) | |
bytesStr += '0x%02x, ' % b | |
print( bytesStr ) | |
return bytes | |
def matchInstructionString(instruction : HPInstruction, strToMatch : str) -> bool: | |
return parseLineInstructionString(instruction) == strToMatch | |
def matchInstrcutionCmd(instruction : HPInstruction, cmdToMatch : str) -> bool: | |
return instruction.getInstructionString() == cmdToMatch | |
def parseLineInstructionString(instruction : HPInstruction) -> str: | |
instructionStr = '%s ' % instruction.getInstructionString() | |
for i in range(instruction.getArgumentCount()): | |
if i < instruction.getArgumentCount() - 1: | |
instructionStr += '%s, ' % instruction.getFormattedArgument(i) | |
else: | |
instructionStr += '%s' % instruction.getFormattedArgument(i) | |
return instructionStr | |
def readCountInstructionAtAddress(addr, count): | |
index = 0 | |
addrCurrent = addr | |
while index < count: | |
print('readAtAddress: 0x%09x' % addrCurrent) | |
instr = seg.getInstructionAtAddress(addrCurrent) | |
instrBytes = readInstructionToBytes(addrCurrent) | |
doc.moveCursorAtAddress(addrCurrent) | |
doc.moveCursorOneLineUp() | |
doc.moveCursorOneLineUp() | |
cursorAddr = doc.getCurrentAddress() | |
print('cursorAddr: 0x%09x' % cursorAddr) | |
print('readCount:', index) | |
# print('instruction bytes:', instrBytes) | |
print('instruction count:', instr.getArgumentCount()) | |
print('instruction:', instr.getInstructionString()) | |
for i in range(instr.getArgumentCount()): | |
value = instr.getFormattedArgument(i) | |
print('instruction arg %d: %s %s' % (i, value, type(value))) | |
print('completed:', parseLineInstructionString(instr)) | |
print('matched:', matchInstructionString(instr, 'call __ZN12Planeswalker4Urza19URPreferenceSetting19SetProductGradeTypeEi')) | |
addrCurrent += instr.getInstructionLength() | |
index += 1 | |
break | |
# if label in trialSymbols and False: | |
# addr = doc.getAddressForName(label) | |
# print('found:', label, addr, type(addr)) | |
# for xref in seg.getReferencesOfAddress(addr): | |
# # xref_seg = doc.getSegmentAtAddress(xref) | |
# print('xref to fount:', xref) | |
# # existing_inline_comment = xref_seg.getInlineCommentAtAddress(xref) | |
# # if existing_inline_comment is None or existing_inline_comment.startswith("0x"): | |
# # cstr_data = str(read_data(None, cstr_ptr, cstr_len)) | |
# # doc.log("Set inline comment at 0x%x: %s"%(xref, repr(cstr_data))) | |
# # xref_seg.setInlineCommentAtAddress(xref, "@" + repr(cstr_data)) | |
# i = seg.getInstructionAtAddress(xref) | |
# print('instruction:', i.getInstructionString()) | |
# # for x in range(0, len(bytes)): | |
# # seg.writeByte(adr + x, bytes[x]) | |
# # if not printed: | |
# # print_exported_class(xref.__class__) | |
# # printed = True | |
# # if not printed2: | |
# # print_exported_class(i.__class__) | |
# # printed2 = True | |
for patchKlass in patchesForCSP: | |
# print( 'Starting patch: %s' % patchKlass.PatchDescription ) | |
print( '%s' % patchKlass.PatchDescription ) | |
matchResult, patchContext = patchKlass.findPatternToPatch( doc ) | |
# print( '\tfind patch pattern: %s' % matchResult ) | |
if matchResult is False: | |
print( 'can\'t findPatternToPatch, script need to be update!' ) | |
# raise SystemError() | |
# print( '\ttry applyPath at: 0x%09x' % patchContext.addr ) | |
patchResult = patchKlass.applyPatch( patchContext ) | |
if patchResult is False: | |
print( 'failed applyPatch(), script need to be update!' ) | |
# raise SystemError() | |
print( '\tSuccess!' ) | |
print( 'Patch Completed.' ) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment