Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python3 reading a binary file, 4 bytes at a time and xor it with a 4 byte long key

Tags:

python

byte

I want to read a binary file, get the content four bytes by four bytes and perform int operations on these packets.

Using a dummy binary file, opened this way:

with open('MEM_10001000_0000B000.mem', 'br') as f:
    for byte in f.read():
            print (hex(byte))

I want to perform an encryption with a 4 byte long key, 0x9485A347 for example.

Is there a simple way I can read my files 4 bytes at a time and get them as int or do I need to put them in a temporary result using a counter?

My original idea is the following:

        current_tmp = []
        for byte in data:
            current_tmp.append(int(byte))
            if (len(current_tmp) == 4):
                    print (current_tmp)
                    # but current_tmp is an array not a single int
                    current_tmp = []

In my example, instead of having [132, 4, 240, 215] I would rather have 0x8404f0d7

like image 214
aze Avatar asked Nov 30 '16 14:11

aze


1 Answers

Just use the "amount" parameter of read to read 4 bytes at a time, and the "from_bytes" constructor of Python's 3 int to get it going:

with open('MEM_10001000_0000B000.mem', 'br') as f:
    data = f.read(4)
    while data:
        number = int.from_bytes(data, "big")
        ...
        data = f.read(4)

If you are not using Python 3 yet for some reason, int won't feature a from_bytes method - then you could resort to use the struct module:

import struct
...
    number = struct.unpack(">i", data)[0]
    ...

These methods however are good for a couple interations, and could get slow for a large file - Python offers a way for you to simply fill an array of 4-byte integer numbers directly in memory from an openfile - which is more likely what you should be using:

import array, os
numbers = array.array("i")
with open('MEM_10001000_0000B000.mem', 'br') as f:
    numbers.fromfile(f, os.stat('MEM_10001000_0000B000.mem').st_size // numbers.itemsize)
numbers.byteswap()

Once you have the array, you can xor it with something like

from functools import reduce #not needed in Python2.7
result = reduce(lambda result, input: result ^ input, numbers, key)

will give you a numbers sequence with all numbers in your file read-in as 4 byte, big endian, signed ints.

If you file is not a multiple of 4 bytes, the first two methods might need some adjustment - fixing the while condition will be enough.

like image 193
jsbueno Avatar answered Dec 09 '22 01:12

jsbueno