mem内存库

读写内存需要以系统管理员权限登陆操作系统.
内存读写错误有可能影响程序的稳定性.尤其是要慎用写入内存的功能.。

一、打开要读写的目标进程内存

在读写其他进程以前,一定要调用mem.open()打开进程.
读写完成以后,一定要调用mem.close()关闭进程.

hp = mem.open()
在「fap模拟程序」中打开前面一个「模拟区块」的进程,
成功返回线程句柄,失败返回nil空值。

hp = mem.open(filename)
指定应用程序名字,打开进程,成功返回线程句柄,失败返回nil空值。

例:

--打开calc.exe进程
win.exec("calc.exe")

if( mem.open("calc.exe") ) then
    n = mem.readInt(0x00E81D68,2);
    --0x00E81D6指定要读写的内存地址,2为要读写的字节大小
    --0x00E81D6是十六进制值,在LAScript中0x前缀指定一个十六进制
    --当然你也可以使用十进制值.
    mem.close(); -- 一定要关闭打开的进程
end;

hp = mem.openHWND(hwnd)
打开一个进程,参数hwnd为目标窗体句柄.
成功返回线程句柄,失败返回nil空值。

hwnd = win.find("SciCalc",nil);
if( mem.openHWND(hwnd) ) then
    n = mem.readInt(0x00E81D68,2);
    mem.close();
end;

hp = mem.open(pid)
根据进程ID打开一个进程,
成功返回线程句柄,失败返回nil空值。

二、关闭目标进程内存

mem.close()
读写完成以后,一定要调用mem.close()关闭进程.

三、读写内存

使用读写内存要谨慎,读写之前应清楚的了解读写以后的效果。

str = mem.read(addr,size)
addr指定内存地址,size指定要读取的长度。
返回值为二进制的字符串数据。

mem.write(addr,str)
addr指定内存地址,size指定要读取的长度。
写入二进制的字符串数据。

int = mem.readInt(addr,size)
读取内存整数值。
addr参数指定内存基址,size为要读取的字节大小.
8位为一个字节,一个节字指定为1,两个字节指定为2.
常用的是32位数指定字节大小为4即可.


例:

num = mem.readInt(0x00E81D68,4);
即读取内存地址0x00E81D68处4个字节的值.


mem.readFloat(addr)
读取四个字节大小的浮点数,addr参数指定内存地址.

mem.readDouble(addr)
读取八个字节大小的浮点数,addr参数指定内存地址.

mem.writeInt(addr,value,size)
写入内存数字值。
参数与mem.readInt(addr,size)其本相同,addr指定内存地址,
size指定要写入的字节,value参数指定要写入的值

mem.writeFloat(addr,value)
写入内存浮点数字值。
addr指定内存地址,最后一个参数指定要写入的四个字节的单精度浮点值

mem.writeDouble(addr,value)

写入内存浮点数字值。
addr指定内存地址,最后一个参数指定要写入的八个字节的双精度浮点值

四、搜索内存

size,base,protect,type = mem.query(base,protect,type);

功能:
mem.query从内存的低地址向高地址搜索有效的符合指定参数的内存,并返回相关信息

参数:
base指定基址,可省略,protect指定页面属性可省略,type指定类型(可省略)

返回值:
size(内存块大小),base(基址),protect(页面属性),type(类型)

--type 内存类型
_MEM_MAPPED 0x40000
_MEM_PRIVATE 0x20000
_MEM_MAPPED 0x40000

--protect 页面属性
_PAGE_NOACCESS = 0x01
_PAGE_READONLY = 0x02
_PAGE_READWRITE = 0x04
_PAGE_WRITECOPY = 0x08
_PAGE_EXECUTE = 0x10
_PAGE_EXECUTE_READ = 0x20
_PAGE_EXECUTE_READWRITE = 0x40
_PAGE_EXECUTE_WRITECOPY = 0x80
_PAGE_GUARD = 0x100
_PAGE_NOCACHE = 0x200
_PAGE_WRITECOMBINE = 0x400

内存搜索QQ号完整示例

--type 内存类型
_MEM_MAPPED = 0x40000
_MEM_PRIVATE = 0x20000
_MEM_MAPPED = 0x40000
 
--protect 页面属性
_PAGE_NOACCESS = 0x01
_PAGE_READONLY = 0x02
_PAGE_READWRITE = 0x04
_PAGE_WRITECOPY = 0x08
_PAGE_EXECUTE = 0x10
_PAGE_EXECUTE_READ = 0x20
_PAGE_EXECUTE_READWRITE = 0x40
_PAGE_EXECUTE_WRITECOPY = 0x80
_PAGE_GUARD = 0x100
_PAGE_NOCACHE = 0x200
_PAGE_WRITECOMBINE = 0x400
 
--上面的定义也可以使用 import("std"); 自动导入
 
win.consoleOpen();
print("请在搜索,可能需要几分钟,请耐心等待");
 
if( mem.open("qq.exe") )then
    local i,j,i2,j2; -- 在循环外部声明变量较好
    local size,base,protect,type = mem.query(); --找出第一个有效内存地址
   
    if( size )then
   
        while( win.doEvents() )do --循环查找, win.doEvents()响应用户停止热键等
       
            size,base,protect,type = mem.query(base + size,_PAGE_READWRITE,_MEM_PRIVATE);
            if(not size)then break end;--找不到size返回nil值
           
            str = mem.read(base,size ); --读取字符串,
            i,j = string.find( str,"\\%d+\\MsgEx.db" );
            if(i)then
                for qq in string.gfind(str,"\\(%d+)\\MsgEx.db") do
                    print("内存找到一个登录的QQ号码",qq);
                end;
            end;
               
           
        end;
       
    end;
   
    mem.close();
   
end;
 
print("搜索完成!")
delay(0)