繁体   English   中英

Python Linux读取进程内存 - int太大而无法转换为C long

[英]Python Linux read process memory - int too large to convert to C long

我有这个片段在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()具有相同的结果和错误。

编辑:我忘了说的是我在“x64”系统上遇到的错误。

问题是你有地址0xffffffffff600000L (带符号)C long只能保存-0x80000000000000000x7fffffffffffffff值。 因此,这个地址确实“太大而无法转换为C long”。

如果您查看源代码 ,您可以看到问题很可能是由于某种原因,当在非工作发行版上配置Python时,它无法检测到fseekooff_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实际上被转换为C层内部的一些无符号64位类型,这意味着它正如你所希望的那样寻求0xffffffffff600000L


您也可以通过使用mmap映射所需的页面而不是seekread来解决这个问题。


如果最坏的情况发生,您可以使用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它,并处理错误。 seekread可能会失败的原因还有其他原因 - 例如,如果您正在查看的进程在您到达之前取消映射某个区域,或者退出 - 您宁愿跳过错误并继续操作而不是退出,正确?

所以:

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")
    # ...

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM