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

时间:2015-11-15 01:32:21

标签: python python-2.7 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中使用Hex也称为二进制形式。

提前感谢任何帮助!谢谢 !

编辑: 根据James Sebastian的要求,我创建了一个.dump文件,并在HexEdit中编辑它们,结果如上所示。

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

'\x00w\x8a\x1c"\x00'

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

'\x00\xe1\x8a\x1c"\x00'

2 个答案:

答案 0 :(得分:1)

这是一个做十六进制搜索的简短演示&替换为二进制文件。我拿了一个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 \x77\x8a with \xe1\x8a
    newdata = stringdata.replace('\x77\x8a', '\xe1\x8a')
    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步骤,他们完全是信息性的,所以我们可以看到该计划的内容&#39这样做。

这里是修改后文件的hexdump:

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;当然没有必要,你可以逐块扫描,或者你认为合适。但您必须在文件.seek().read()操作之间进行文件.write()调用。

此外,非常小心,您可以正确定位。并且不要意外地写错了数据长度。它不会改变文件长度,但是如果您的替换数据不是您认为的长度,它仍然会使您的文件变得混乱。

这是一个修改给定偏移量的文件数据的函数。由于其操作具有潜在危险,因此该功能会提示用户确保正在覆盖正确的数据。在测试代​​码中,我使用与以前相同的32字节文件,覆盖偏移量为0x12的3个字节'\x83\x37\xee'

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: %s\n' % (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

&#34;之前&#34; &#34;&#34;&#34;&#34;十六进制转储:

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

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

答案 1 :(得分:-1)

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

#!/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'\x00w\x8a\x1c"\x00')

然后输出(在77 -> E1替换之后)是:

print(repr(open('a2.dump','rb').read()))
# -> b'\x00\xe1\x8a\x1c"\x00'

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

请参阅Python - How can I change bytes in a file