如何在python 2.x中读取后用HEX写入转储文件



根据标题,我需要帮助写入转储文件中的特定字节。到目前为止,我可以用以下代码读取512字节:

sectorcount = 0;
bytecount= 0;
with open('a2.dump', 'rb') as f:
    for chunk in iter(lambda: f.read(16), b''):
        #16 bytes per chunk aka 32 characters
        item = chunk.encode('hex')
        #to filter display output so it shows 2 character per array element
        filtered_item= [item[i:i+2] for i in range(0, len(item), 2)]
        #to display in "hex" form
        #filtered_item[0] = "E5"

        print ' '.join(filtered_item)
        sectorcount = sectorcount +1
        #to display 1 sector use the value 32. adjust accordingly"
        if sectorcount ==32:
            break

结果显示

00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 77 8a 1c 22 00 00 00 21
03 00 83 37 ee fb 00 08 00 00 00 b8 3d 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa

正如你所看到的,我需要帮助编辑结果中的一个值(例如,将"77"的值更改为"E1")

我尝试以with open('a2.dump', 'wb') as f:的身份打开该文件,但我的转储文件被清空了。我认为我需要对文件使用写操作,但不确定如何在Python中以十六进制或二进制形式执行。

感谢您提前提供的帮助!谢谢

编辑:根据James Sebastian的请求,我创建了一个.dump文件,并在HexEdit中对其进行了编辑,结果如上所示。

然后我执行代码print repr(open('input.dump', 'rb').read())结果如下:

'x00wx8ax1c"x00'

相应的预期输出(替换后的结果):

'x00xe1x8ax1c"x00'

这里有一个做十六进制搜索的简短演示&替换为二进制文件。我摘录了你的32字节数据;这是它的十六进制转储(在Linux上使用hd生成)。

00000000  00 00 00 00 00 00 00 00  77 8a 1c 22 00 00 00 21  |........w.."...!|
00000010  03 00 83 37 ee fb 00 08  00 00 00 b8 3d 00 00 00  |...7........=...|
00000020

这是代码:

fname = 'qdata'
with open(fname, 'r+b') as f:
    #save position of the start of the data block
    fprev = f.tell()
    stringdata = f.read(32)
    print stringdata.encode('hex')
    #replace the first occurence of x77x8a with xe1x8a
    newdata = stringdata.replace('x77x8a', 'xe1x8a')
    print newdata.encode('hex')
    #rewind file to the start of the data block
    f.seek(fprev)
    f.write(newdata)

请注意,文件模式为'r+b'。这使我们可以读取文件并对其进行修改。如果您使用w模式打开文件,则文件将被截断,即其以前的内容将被擦除,并且文件大小将重置为零。如果在a模式下打开它,则文件指针位于文件的末尾,以允许附加数据。

以下是上面代码打印的输出:

0000000000000000778a1c220000002103008337eefb0008000000b83d000000
0000000000000000e18a1c220000002103008337eefb0008000000b83d000000

我们不需要来执行.encode('hex')print步骤,它们纯粹是信息性的,所以我们可以看到程序在做什么。

这是修改后的文件的六进制转储:

00000000  00 00 00 00 00 00 00 00  e1 8a 1c 22 00 00 00 21  |..........."...!|
00000010  03 00 83 37 ee fb 00 08  00 00 00 b8 3d 00 00 00  |...7........=...|
00000020

在上面的代码中,我将整个文件内容读入RAM;这当然没有必要,你可以一块一块地扫描,或者你认为合适的方式。但是您必须在文件.read().write()操作之间执行文件.seek()调用。

此外,要非常小心,确保定位正确。并且不要意外地写入错误的数据长度。它不会改变文件长度,但如果你的替换数据不是你认为的长度,它仍然会把你的文件弄得一团糟。


这里有一个函数,可以在给定的偏移量处修改文件数据。由于其操作具有潜在的危险性,该函数会提示用户确保覆盖了正确的数据。在测试代码中,我使用与以前相同的32字节文件,覆盖偏移量为0x12的3字节'x83x37xee'

def binedit(fname, offset, newdata):
    with open(fname, 'r+b') as f:
        #Show current contents
        f.seek(offset)
        stringdata = f.read(len(newdata))
        print 'Current data:'
        print '%08X: %sn' % (offset, stringdata.encode('hex'))
        prompt = 'Replace with %s ? (y/N) ' % newdata.encode('hex')
        s = raw_input(prompt)
        if s != 'y':
            print 'Aborting'
            return
        #Replace data at offset with newdata
        f.seek(offset)
        f.write(newdata)

fname = 'qdata'
offset = 0x12
newdata = 'dead42'.decode('hex')
binedit(fname, offset, newdata)

输出

Current data:
00000012: 8337ee
Replace with dead42 ? (y/N) y

"之前"one_answers"之后"十六进制转储:

00000000  00 00 00 00 00 00 00 00  77 8a 1c 22 00 00 00 21  |........w.."...!|
00000010  03 00 83 37 ee fb 00 08  00 00 00 b8 3d 00 00 00  |...7........=...|
00000020
00000000  00 00 00 00 00 00 00 00  77 8a 1c 22 00 00 00 21  |........w.."...!|
00000010  03 00 de ad 42 fb 00 08  00 00 00 b8 3d 00 00 00  |....B.......=...|
00000020

免责声明:如果你使用此代码销毁有价值的数据,那不是我的错!

要替换二进制文件中的字节,不需要十六进制转储,例如用b'xE1':替换b'x77'

#!/usr/bin/env python
import mmap
from contextlib import closing
with open('a2.dump', 'r+b') as file, 
     closing(mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_WRITE)) as s:
    i = -1
    while 1:
        i = s.find(b'x77', i+1)
        if i < 0: # not found
            break
        s[i] = b'xE1'[0] # replace

它就地执行替换。它适用于任意大的文件。

例如,如果输入文件是使用创建的

open('a2.dump','wb').write(b'x00wx8ax1c"x00')

则输出(在77 -> E1替换之后)为:

print(repr(open('a2.dump','rb').read()))
# -> b'x00xe1x8ax1c"x00'

请注意,0x77字节已替换为0xE1

请参阅Python-如何更改文件中的字节。

最新更新