138 lines
4.4 KiB
Plaintext
138 lines
4.4 KiB
Plaintext
#####################################
|
|
## Created by briandeheus ##
|
|
## https://github.com/briandeheus ##
|
|
## Implementation and changes ##
|
|
## LoafyLemon ##
|
|
#####################################
|
|
init python:
|
|
import binascii
|
|
import struct
|
|
|
|
class ImagePayload(object):
|
|
|
|
_END_CHUNK_TYPE = 'IEND'
|
|
_PUNK_CHUNK_TYPE = 'wtSi'
|
|
_MAX_BYTES = 2147483647
|
|
_chunks = dict()
|
|
|
|
def __init__(self):
|
|
self._mode = None
|
|
self._file = None
|
|
self._output = None
|
|
self._bytes_to_hide = None
|
|
|
|
self._bytes_read = 0
|
|
|
|
def decode(self, input_file):
|
|
self.__init__()
|
|
self._mode = 'decode'
|
|
self._file = open("{}/outfits/{}".format(config.gamedir, input_file), 'rb+')
|
|
#self._output = open(config.basedir+'/game/'+output_file+'.txt', 'wb+')
|
|
|
|
# First move cursor past the signature
|
|
self._read_bytes(8)
|
|
|
|
# Start reading chunks
|
|
self._read_next_chunk()
|
|
return self._output
|
|
|
|
def encode(self, input_file, bytes_to_hide):
|
|
self.__init__()
|
|
self._mode = 'encode'
|
|
self._file = open("{}/outfits/{}.png".format(config.gamedir, input_file), 'rb+')
|
|
self._bytes_to_hide = bytes_to_hide.encode('utf-8')
|
|
|
|
# First move cursor past the signature
|
|
self._read_bytes(8)
|
|
|
|
# Start reading chunks
|
|
self._read_next_chunk()
|
|
|
|
def _read_bytes_as_hex(self, position):
|
|
return self._read_bytes(position).encode('hex')
|
|
|
|
def _read_bytes_as_ascii(self, position):
|
|
return self._read_bytes(position).encode('ascii')
|
|
|
|
def _read_bytes_as_int(self, position):
|
|
return int(self._read_bytes_as_hex(position), 16)
|
|
|
|
def _read_bytes(self, byte_count):
|
|
self._bytes_read += byte_count
|
|
return self._file.read(byte_count)
|
|
|
|
def _rewind_bytes(self, byte_count):
|
|
self._bytes_read -= byte_count
|
|
self._file.seek(self._bytes_read)
|
|
|
|
def _inject_punk_chunk(self):
|
|
# Move back 8 bytes.
|
|
self._rewind_bytes(8)
|
|
|
|
chunk_size = len(self._bytes_to_hide)
|
|
print 'Hiding', (chunk_size / 1024), 'kB (', chunk_size, 'bytes)'
|
|
|
|
# Create a temporary byte array for the CRC check.
|
|
tmp_bytes = bytearray()
|
|
|
|
# First write the chunk type
|
|
tmp_bytes.extend(bytearray(self._PUNK_CHUNK_TYPE))
|
|
|
|
# Now write the bytes of whatever we're trying to hide
|
|
tmp_bytes.extend(self._bytes_to_hide)
|
|
|
|
#print 'Injecting punk chunk'
|
|
|
|
# Write the chunk size
|
|
self._file.write(bytearray(struct.pack('!i', chunk_size)))
|
|
|
|
# And the type
|
|
self._file.write(bytearray(self._PUNK_CHUNK_TYPE))
|
|
|
|
self._file.write(self._bytes_to_hide)
|
|
|
|
crc = binascii.crc32(tmp_bytes)
|
|
self._file.write(bytearray(struct.pack('!i', crc)))
|
|
|
|
# Write the end chunk. Start with the size.
|
|
self._file.write(bytearray(struct.pack('!i', 0)))
|
|
# Then the chunk type.
|
|
self._file.write(bytearray(self._END_CHUNK_TYPE))
|
|
|
|
crc = binascii.crc32(bytearray(self._END_CHUNK_TYPE))
|
|
self._file.write(bytearray(struct.pack('!i', crc)))
|
|
|
|
#print 'Punk chunk injected'
|
|
|
|
def _read_next_chunk(self):
|
|
chunk_size = self._read_bytes_as_int(4)
|
|
print 'Chunk size:', chunk_size
|
|
|
|
chunk_type = self._read_bytes_as_ascii(4)
|
|
print 'Chunk type:', chunk_type
|
|
|
|
if self._mode == 'encode' and chunk_type == self._END_CHUNK_TYPE:
|
|
self._inject_punk_chunk()
|
|
|
|
#print 'Reached EOF'
|
|
self._file.close()
|
|
return
|
|
|
|
content = self._read_bytes(chunk_size)
|
|
|
|
crc = self._read_bytes_as_hex(4)
|
|
print 'CRC:', crc
|
|
|
|
if self._mode == 'decode' and chunk_type == self._PUNK_CHUNK_TYPE:
|
|
print "Found a chunk data", len(content), "bytes. Importing.."
|
|
#self._output.write(bytearray(content))
|
|
#self._output.close()
|
|
self._output = content.decode('utf-8')
|
|
self._file.close()
|
|
print "Done."
|
|
return True
|
|
|
|
self._read_next_chunk()
|
|
|
|
image_payload = ImagePayload()
|