Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Reversing the code
#1
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.
.py   DeobfuscateGameBootstrap.py (Size: 2.69 KB / Downloads: 50)

--------------------
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()
    
Larz60+ write Feb-12-2024, 11:02 PM:
Please don't attach code, instead please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
Reply
#2
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.
Gribouillis write Feb-23-2024, 05:46 AM:
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020