Reversing the code - Printable Version +- Python Forum (https://python-forum.io) +-- Forum: Python Coding (https://python-forum.io/forum-7.html) +--- Forum: Game Development (https://python-forum.io/forum-11.html) +--- Thread: Reversing the code (/thread-41586.html) |
Reversing the code - chocolatedisco - Feb-12-2024 Hello,I'm new to python and I'm starting to study it,but I have this code that it's been used to unpack a certain compressed file. This file needs to be compressed back If I want to apply my changes to a game,so I'm trying to understand how I can make it so that instead of decompress,it does the opposite. Is it possible to revert this code? If someone can help me through this I would be very grateful,thanks. Code is attached.[attachment=2743] -------------------- import sys def DeObfuscate(pInput, pOutput): inpOffset = 0 outOffset = 0 # Loop and deobfuscate. blockId = pInput[inpOffset] inpOffset += 1 if blockId == 0: pass if blockId >= 2: print("block id: 0x%x" % blockId) while blockId != 0: pBlockPtr = inpOffset + 1 while blockId >= 2: if (blockId & 1) == 1: pOutput[outOffset] = pInput[inpOffset] blockId = blockId >> 1 inpOffset = pBlockPtr pBlockPtr += 1 outOffset += 1 else: a = pInput[inpOffset] b = pInput[pBlockPtr] c = (a << 8) | b d = c & 0x7FF e = c >> 11 if d == 0: d = 0x800 pCopyPtr = outOffset - d d = e & 0x1F if d == 0: d = 0x20 inpOffset = pBlockPtr + 1 blockId = blockId >> 1 pBlockPtr += 2 for i in range(d): if outOffset >= len(pOutput) or pCopyPtr >= len(pOutput): print("%d (%d) | %d (%d) | %d (%d)" % (outOffset, len(pOutput), pCopyPtr, len(pOutput), i, d)) pOutput[outOffset] = pOutput[pCopyPtr] pCopyPtr += 1 outOffset += 1 blockId = pInput[inpOffset] inpOffset = pBlockPtr print("block id: 0x%x" % blockId) print("bytes copied: %d" % outOffset) return outOffset def main(): # Open the input file and read the file into memory. f = open(sys.argv[1], 'rb') unk = f.read(4) inputData = f.read() f.close() # Deobfuscate the input buffer. outputData = bytearray(len(inputData) * 4) length = DeObfuscate(inputData, outputData) # Write the deobfuscated data to file. f = open(sys.argv[1] + "_dec", 'wb') f.write(outputData[0:length]) f.close() if __name__ == '__main__': main() RE: Reversing the code - Baroscope - Feb-23-2024 To revert this code, you need to do the following steps: • Define a function called Obfuscate, which takes two parameters: pInput and pOutput. This function will do the opposite of DeObfuscate, that is, it will compress the input data and write it to the output buffer. • In the Obfuscate function, initialize two variables: inpOffset and outOffset, both set to 0. These variables will keep track of the current positions in the input and output buffers, respectively. • In the Obfuscate function, create a loop that iterates over the input data until inpOffset reaches the end of the input buffer. In each iteration, do the following: • Find the longest match between the current input position and the previous data in the sliding window. You can use a function like FindLongestMatch, which takes three parameters: pInput, inpOffset, and windowSize, and returns a tuple of two values: matchOffset and matchLength. The matchOffset is the distance from the current input position to the start of the match, and the matchLength is the size of the match. If no match is found, the matchLength is set to 0. • If the matchLength is greater than or equal to a minimum threshold (such as 3), then encode the match as a reference. To do this, write a 0 bit to the output buffer, followed by the encoded matchOffset and matchLength. You can use a function like EncodeReference, which takes four parameters: pOutput, outOffset, matchOffset, and matchLength, and returns the updated outOffset. The EncodeReference function should write the matchOffset and matchLength using variable-length bit fields, depending on the size of the sliding window and the maximum match length. For example, if the sliding window is 2048 bytes and the maximum match length is 32 bytes, then the matchOffset should be encoded using 11 bits and the matchLength should be encoded using 5 bits. • If the matchLength is less than the minimum threshold, then encode the current input byte as a literal. To do this, write a 1 bit to the output buffer, followed by the input byte. You can use a function like EncodeLiteral, which takes three parameters: pOutput, outOffset, and inpByte, and returns the updated outOffset. The EncodeLiteral function should write the inpByte using 8 bits. • Update the inpOffset by adding the matchLength (if it is a reference) or 1 (if it is a literal) to it. • After the loop, write a final 0 bit to the output buffer, followed by a zero offset and length, to indicate the end of the compressed data. You can use the EncodeReference function for this, passing 0 as the matchOffset and matchLength. • Return the final value of outOffset, which is the length of the compressed data. geometry dash • Define a main function, which will take the input file name as a command-line argument, read the file into memory, call the Obfuscate function to compress the data, and write the compressed data to a new file with a different extension (such as "_enc"). • Call the main function if the script is run as the main module. Here is a possible code that implements these steps: import sys def FindLongestMatch(pInput, inpOffset, windowSize): # Initialize the match offset and length to zero matchOffset = 0 matchLength = 0 # Loop over the previous data in the sliding window for i in range(max(0, inpOffset - windowSize), inpOffset): # Initialize the current offset and length to zero curOffset = i curLength = 0 # Loop over the input data until a mismatch is found or the end is reached while inpOffset + curLength < len(pInput) and pInput[inpOffset + curLength] == pInput[curOffset + curLength]: # Increment the current length curLength += 1 # If the current length is greater than the match length, update the match offset and length if curLength > matchLength: matchOffset = inpOffset - curOffset matchLength = curLength # Return the match offset and length as a tuple return (matchOffset, matchLength) def EncodeReference(pOutput, outOffset, matchOffset, matchLength): # Write a 0 bit to indicate a reference pOutput[outOffset // 8] &= ~(1 << (7 - (outOffset % 8))) outOffset += 1 # Write the match offset using 11 bits pOutput[outOffset // 8] |= (matchOffset >> 3) & 0xFF outOffset += 8 pOutput[outOffset // 8] &= ~(0x1F << (3 - (outOffset % 8))) pOutput[outOffset // 8] |= (matchOffset & 0x07) << (3 - (outOffset % 8)) outOffset += 3 # Write the match length using 5 bits pOutput[outOffset // 8] &= ~(0x1F << (7 - (outOffset % 8))) pOutput[outOffset // 8] |= (matchLength & 0x1F) << (7 - (outOffset % 8)) outOffset += 5 # Return the updated output offset return outOffset def EncodeLiteral(pOutput, outOffset, inpByte): # Write a 1 bit to indicate a literal pOutput[outOffset // 8] |= 1 << (7 - (outOffset % 8)) outOffset += 1 # Write the input byte using 8 bits pOutput[outOffset // 8] = inpByte outOffset += 8 # Return the updated output offset return outOffset def Obfuscate(pInput, pOutput): # Initialize the input and output offsets to zero inpOffset = 0 outOffset = 0 # Loop over the input data until the end is reached while inpOffset < len(pInput): # Find the longest match in the sliding window matchOffset, matchLength = FindLongestMatch(pInput, inpOffset, 2048) # If the match length is greater than or equal to 3, encode it as a reference if matchLength >= 3: outOffset = EncodeReference(pOutput, outOffset, matchOffset, matchLength) # Otherwise, encode the current input byte as a literal else: outOffset = EncodeLiteral(pOutput, outOffset, pInput[inpOffset]) matchLength = 1 # Update the input offset by adding the match length inpOffset += matchLength # Write a final 0 bit, followed by a zero offset and length, to indicate the end of the compressed data outOffset = EncodeReference(pOutput, outOffset, 0, 0) # Return the length of the compressed data return outOffset def main(): # Open the input file and read the file into memory f = open(sys.argv[1], 'rb') inputData = f.read() f.close() # Obfuscate the input buffer outputData = bytearray(len(inputData) * 2) length = Obfuscate(inputData, outputData) # Write the obfuscated data to file f = open(sys.argv[1] + "_enc", 'wb') f.write(outputData[0:length]) f.close() if __name__ == '__main__': main()I hope this code helps you understand how to compress the file back using the LZSS algorithm. |