0

我有这个片段,它在 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”系统上遇到的错误。

4

1 回答 1

2

问题是你有地址0xffffffffff600000L。A(有符号)C long 只能保存从-0x8000000000000000到 的值0x7fffffffffffffff。所以,这个地址确实“太大而无法转换为 C long”。

如果您查看源代码,您会发现问题很可能是由于某种原因,当 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)

你也可以试试这个可怕的 hack:

if start >= 1<<63L:
    start -= 1<<64L

这会将你的to0xffffffffff600000L转换-0xa00000成一个long...long0xffffffffff600000L


您也可以通过使用mmap来映射您想要的页面,而不是seekand来解决这个问题read


如果最坏的情况变得最糟,您可以使用ctypescffi或任何您喜欢的方式)fseeko直接调用您的文件句柄。


最后,确保您确实想要阅读该区域。我可能错了,但我似乎记得linux为映射到用户空间的内核页面保留了上层区域。如果我是对的,你要找的字符串不会在这里,所以你可以跳过它们……</p>

要跳过处理区域,您可以在 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")
    # ...
于 2013-05-12T13:04:23.187 回答