我又测试了下,就算我不主动调用gc,Frida.heapSize
获取的内存占用最多也才10多M。间隔性调用gc,一直保持在2M左右,但这获取的并不是APP的内存占用。
在 ceserver.py
的 handler
函数 CECMD.CMD_READPROCESSMEMORY
分支内,我尝试不执行 ReadProcessMemory
函数,APP内存占用没有任何变化。
elif (command == CECMD.CMD_READPROCESSMEMORY):
handle = reader.ReadUInt32()
address = reader.ReadUInt64()
size = reader.ReadUInt32()
compress = reader.ReadInt8()
# ret = API.ReadProcessMemory(address, size)
# if (compress == 0):
# if ret != False:
# writer.WriteInt32(len(ret))
# ns.sendall(ret)
# else:
# writer.WriteInt32(0)
# else:
# if ret != False:
# compress_data = zlib.compress(ret, level=compress)
# writer.WriteInt32(len(ret))
# writer.WriteInt32(len(compress_data))
# ns.sendall(compress_data)
# else:
# writer.WriteInt32(0)
# writer.WriteInt32(0)
writer.WriteInt32(0)
而执行 ReadProcessMemory
函数,内存就会暴涨。
elif (command == CECMD.CMD_READPROCESSMEMORY):
handle = reader.ReadUInt32()
address = reader.ReadUInt64()
size = reader.ReadUInt32()
compress = reader.ReadInt8()
ret = API.ReadProcessMemory(address, size)
# if (compress == 0):
# if ret != False:
# writer.WriteInt32(len(ret))
# ns.sendall(ret)
# else:
# writer.WriteInt32(0)
# else:
# if ret != False:
# compress_data = zlib.compress(ret, level=compress)
# writer.WriteInt32(len(ret))
# writer.WriteInt32(len(compress_data))
# ns.sendall(compress_data)
# else:
# writer.WriteInt32(0)
# writer.WriteInt32(0)
writer.WriteInt32(0)
ReadProcessMemory
函数:
readprocessmemory: function (address, size) {
try {
if (ptr(address).isNull() == false) {
return Memory.readByteArray(ptr(address), size);
} else {
return false;
}
} catch (e) {
return false;
}
},
获取占用的内存:
+ (double)usedMemory
{
task_basic_info_data_t taskInfo;
mach_msg_type_number_t infoCount = TASK_BASIC_INFO_COUNT;
kern_return_t kernReturn = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&taskInfo, &infoCount);
if (kernReturn != KERN_SUCCESS) {
return NSNotFound;
}
return taskInfo.resident_size / 1024.0 / 1024.0;
}
获取APP剩余可用内存:
+ (double)availableMemory
{
if (@available(iOS 13.0, *)) {
return os_proc_available_memory() / 1024.0 / 1024.0;
}
vm_statistics_data_t vmStats;
mach_msg_type_number_t infoCount = HOST_VM_INFO_COUNT;
kern_return_t kernReturn = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vmStats, &infoCount);
if (kernReturn != KERN_SUCCESS) {
return NSNotFound;
}
return (vm_page_size *vmStats.free_count) / 1024.0 / 1024.0;
}
当APP剩余可用内存被占用完,APP就会被系统杀死进程。
在 Cheat Engine 扫描内存过程中,会不断发送 CMD_READPROCESSMEMORY
指令,脚本收到指令后频繁调用 Memory.readByteArray
函数,最终通过 socket 把读取到的内存数据发送给 Cheat Engine。
我测试了不读取内存,只收发数据是不会出现内存波动,只有读取内存后才会持续占用APP内存。
我的测试过程
改回原代码后,在我开始测试前,usedMemory
获取的内存占用为600M左右,availableMemory
获取的可用内存为1000M左右。
Cheat Engine 开始扫描内存,指定搜索范围 0x105000000
- 0x110000000
。usedMemory
获取的内存占用持续增加到1300M,availableMemory
获取的可用内存慢慢减少到800M。
然后测试扫描指针,基址范围也设置 0x105000000
- 0x110000000
。usedMemory
获取的内存占用持续增加到1500M左右,又慢慢降低到700M左右。availableMemory
获取的可用内存慢慢减少到200M。
这个时候我要再扫描一次内存,或者扫描指针,APP必定闪退。
在这个过程中,Frida.heapSize
获取的内存占用一直都是在2M左右,我有主动调用gc,就算没有最多也就10多M。但APP的内存波动太大,并且 availableMemory
获取的可用内存不会恢复。
我按照你的方式,单独遍历APP内存,调用 Memory.readByteArray
函数并不会让APP内存增加。这就有点迷惑了。