Modifying binary file with Python

17,016

Solution 1

You only need to use seek and write. Use seek to jump to the position and write to overrwite the existing data.

with file('patch1.bin', 'rb') as fh:
    patch1 = fh.read()

with file('patch2.bin', 'rb') as fh:
    patch2 = fh.read()

with file('file.bin', 'r+b') as fh:
    # apply patch1
    fh.seek(0xc0010)
    fh.write(patch1)
    fh.seek(0x7c0010)
    fh.write(patch1)
    # apply patch2
    fh.seek(0x040000)
    fh.write(patch2)

Solution 2

1.txt:

asdf

a.py:

with open('1.txt','r+b') as f:
    f.seek(2)
    f.write('D')

1.txt:

asDf

This should give you a clue.

Solution 3

You need to use the r+b mode for editing the target file. wb is the mode for writing without updating and will truncate an existing file. Check out http://docs.python.org/2/library/functions.html#open or your OS' man page for fopen to get details on the different file modes.

Share:
17,016
james28909
Author by

james28909

Updated on June 23, 2022

Comments

  • james28909
    james28909 almost 2 years

    i am trying to patch a hex file. i have two patch files (hex) named "patch 1" and "patch 2"

    the file to be patched is a 16 MB file named "file.bin".

    i have tried many different way for the past 6 or 7 hours to figure out how to do it. I can write a string to a file all day long, but i am trying to do the following:

    open patch1.bin with read bytes open patch2.bin with read bytes open file.bin with write bytes

    i want to seek to positions 0xc0010, and 0x7c0010, and apply patch1.bin then i want to seek to 0x040000 and apply patch2.bin

    so all in all i will have 3 patches applied, then close the "file.bin"

    if someone cold give me an example i would very much appreciate it :)

    i tried this first:

    patch1 = open("patch1", "r");
    patch2 = open("patch2", "r");
    main = open("file.bin", "w");
    
    main.seek(0xC0010);
    main.write(patch1);
    main.seek(0x7C0010);
    main.write(patch1);
    main.seek(0x40000);
    main.write(patch2);
    main.close();
    

    but was informed i was was trying to write a string to a file, when indeed its not what i wanted, lol then i tried this:

    infile1 = open("patch1.bin", "rb") 
    new_pos1 = int("0x00", 16)
    infile1.seek(new_pos1, 0)
    infile2 = open('file.bin', 'wb')
    new_pos2 = int('0xc0010', 16)
    infile2.seek(new_pos2, 0xc0010)
    chunk1 = int("6FFFE0", 16)         #this is how long patch1 file is
    data1 = infile1.read(chunk1)
    with open("file.bin", "a") as outfile:
        outfile.write(data1)
    

    but it did not work either, as no matter what i tried, i could not get it to write the data at he correct offset.

    I did manage a few times to write the patch1 to file.bin, but it did not patch at the right offset, as a matter of fact it deleted the file.bin and just copied patch1 in its place. which ofcourse is wrong.

    i must remind you i am new to python and programming, but i am really trying to dig my feet into it and learn, so any good examples will be examined and hopefully will be a good learning lesson for me :)

    thanks guys and gals for helping me figure out what i was doing wrong :)

  • james28909
    james28909 about 11 years
    ok i figured out what it was, with file('file.bin', 'w') needed to be 'r+'.... after i changed that the code works flawless. thank you very much :)
  • Simon Callan
    Simon Callan about 11 years
    When opening the patch files, you should open them in binary mode - open("<fn>", "rb"), while the file to be patched should be opened in "r+b" mode.
  • james28909
    james28909 about 11 years
    yes, and i now know what i was doing worng ;) thanks for schooling a noob lol
  • Antony Hatchkins
    Antony Hatchkins about 11 years
    w+b truncates the file. Use r+b in this case.
  • Antony Hatchkins
    Antony Hatchkins about 11 years
    w mode truncates the file. Use r+b for patching existing file.
  • james28909
    james28909 about 11 years
    well, i tested the files byte for byte, and when i run the script, it is different than when i manually patch the file, i tested with HxD and use file compare function. is there a way to make it more accurate?
  • james28909
    james28909 about 11 years
    nvm, i figured it out. while i was screwing things up, i managed to delete all the data in one of my patch files, lol. i recopied it and all is well and the files are identical. thanks everyone :)
  • bikeshedder
    bikeshedder about 11 years
    Whops. Fixed the code example. Sorry, I only tested it against an empty file created usind dd if=/dev/zero of=file.bin count=50000 and everything seamed to be ok.
  • youfu
    youfu about 8 years
    When dealing with large files, maybe you should consider using mmap instead of file.read etc.