我有这个片段在Linux中读取进程内存并搜索字符串,在某些发行版上运行正常,但在其他发行版上只有这个错误:
maps_file = open("/proc/%s/maps"%pid, 'r')
mem_file = open("/proc/%s/mem"%pid, 'r')
for line in maps_file.readlines(): # for each mapped region
m = re.match(r'([0-9A-Fa-f]+)', line)
if m.group(3) == 'r': # if this is a readable region
start = int(m.group(1), 16)
end = int(m.group(2), 16)
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region contents
#print chunk, # dump contents to standard output
mem_dump = open(working_dir+"/%s.bin"%pid, "ab")
mem_dump.write(chunk,)
mem_dump.close()
maps_file.close()
mem_file.close()
错误:
scan process: 491
Traceback (most recent call last):
File "./dump.py", line 106, in <module>
MainDump(pid)
File "./dump.py", line 79, in MainDump
mem_file.seek(start) # seek to region start
OverflowError: Python int too large to convert to C long
问题在于:
start = int(m.group(1), 16)
和
mem_file.seek(start)
我应该声明为float
吗?有什么想法吗?
还尝试了long()
相同的结果和错误。
答案 0 :(得分:2)
问题是你有地址0xffffffffff600000L
。 (签名)C long只能保存从-0x8000000000000000
到0x7fffffffffffffff
的值。所以,这个地址确实“太大而无法转换为C long”。
如果你看一下the source,你会发现问题最有可能是因为某些原因,当在非工作发行版上配置Python时,它无法检测到fseeko
和off_t
存在。但除非您想重建Python,否则无法帮助您。
那么,你怎么解决这个问题呢?有几件事要尝试。
第一种可能性是从头而不是开始寻求。
mem_len = os.fstat(mem_file.fileno()).st_size
if start >= 1<<63L:
mem_file.seek(mem_len - start, os.SEEK_END)
else:
mem_file.seek(start)
你也可以试试这个可怕的黑客:
if start >= 1<<63L:
start -= 1<<64L
这会将您的0xffffffffff600000L
转换为-0xa00000
,这恰好适用于long
...然后希望long
实际上被转换为某些无符号的64-在C层内部的位类型,意味着它按照您的希望寻找0xffffffffff600000L
。
您也可以使用mmap
映射所需的网页,而不是seek
和read
来解决此问题。
如果最糟糕的情况发生,您可以使用ctypes
(或cffi
或您喜欢的任何内容)直接在文件句柄上调用fseeko
。
最后,请确保您确实想要阅读此区域。我可能错了,但我似乎记得linux保留了映射到用户空间的内核页面的上部区域。如果我是对的,你正在寻找的字符串不会在这里,所以你可以跳过它们......
要跳过处理区域,您可以在if:
中移动处理start = int(m.group(1), 16)
end = int(m.group(2), 16)
if start <= sys.maxint:
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region contents
# ...
...或使用continue
语句跳到循环的下一次迭代:
start = int(m.group(1), 16)
end = int(m.group(2), 16)
if start > sys.maxint:
continue
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region contents
# ...
如果您知道区域始终按排序顺序排列,则可以使用break
代替continue
(因为其余区域也将超出范围)。
但我认为最好的解决方案就是try
它,并处理错误。此seek
和read
可能会失败的其他原因 - 例如,如果您正在查看的流程在您到达之前取消映射某个区域,或者退出 - 而您宁愿跳过该错误并继续,而不仅仅是退出,对吗?
所以:
if m.group(3) == 'r': # if this is a readable region
start = int(m.group(1), 16)
end = int(m.group(2), 16)
try:
mem_file.seek(start) # seek to region start
chunk = mem_file.read(end - start) # read region co
except Exception as e:
print('Skipping region {:#018x} because of error {}'.format(start, e))
continue
mem_dump = open(working_dir+"/%s.bin"%pid, "ab")
# ...