我们假设'QH'这个字符串在内存中的地址是a,'LJQ'在内存中的地址是b
you='QH'#让you变量指向a地址
me=you #让me变量和you变量一样指向a地址
you='LJQ' #修改you变量,让它指向到b地址
print you#可想而知you指向的是b地址,所以它的值为'LJQ'
print me#me指向的是a地址,所以它的值为'QH'
输出:
LJQ
QH
可以使用ID来加强对python的赋值机制的理解
>>>a = 'asdf'
>>>id(a)
872552384
>>>b = a
>>>id(b)
872552384
>>>a = 'haha'
>>>id(a)
872552672
>>>id(b)
872552384
>>>a
'haha'
>>>b
'asdf'
c=a 这样的操作属于浅复制,a和c的值其实指向的是同一个内存地址,改变其中任何一个变量的值,都会造成另外的变量的值也显示为一样的改变。
用id函数可看出a 和 c 其实指向的是同一个内存地址。
如果想深复制,也就是值不指向同一个内存地址,可以用 c=a[:]
使用ctypes模块调用WriteProcessMemory函数,在创建程序进程后,就可以修改该程序指定内存地址。WriteProcessMemory的函数原型如下所示。
BOOL WriteProcessMemory(
HANDLE hProcess,
LPVOID lpBaseAddress,
LPCVOID lpBuffer,
SIZE_T nSize,
SIZE_T* lpNumberOfBytesWritten
)
其参数含义如下。
· hProcess:要写内存的进程句柄。
· lpBaseAddress:要写的内存起始地址。
· lpBuffer:写入值的地址。
· nSize:写入值的大小。
· lpNumberOfBytesWritten :实际写入的大小。
python代码示例如下:
from ctypes import *# 定义_PROCESS_INFORMATION结构体
class _PROCESS_INFORMATION(Structure):
_fields_ = [('hProcess', c_void_p),
('hThread', c_void_p),
('dwProcessId', c_ulong),
('dwThreadId', c_ulong)]
# 定义_STARTUPINFO结构体
class _STARTUPINFO(Structure):
_fields_ = [('cb',c_ulong),
('lpReserved', c_char_p),
('lpDesktop', c_char_p),
('lpTitle', c_char_p),
('dwX', c_ulong),
('dwY', c_ulong),
('dwXSize', c_ulong),
('dwYSize', c_ulong),
('dwXCountChars', c_ulong),
('dwYCountChars', c_ulong),
('dwFillAttribute', c_ulong),
('dwFlags', c_ulong),
('wShowWindow', c_ushort),
('cbReserved2', c_ushort),
('lpReserved2', c_char_p),
('hStdInput', c_ulong),
('hStdOutput', c_ulong),
('hStdError', c_ulong)]
NORMAL_PRIORITY_CLASS = 0x00000020 # 定义NORMAL_PRIORITY_CLASS
kernel32 = windll.LoadLibrary("kernel32.dll") # 加载kernel32.dll
CreateProcess = kernel32.CreateProcessA # 获得CreateProcess函数地址
ReadProcessMemory = kernel32.ReadProcessMemory # 获得ReadProcessMemory函数地址
WriteProcessMemory = kernel32.WriteProcessMemory # 获得WriteProcessMemory函数地址
TerminateProcess = kernel32.TerminateProcess
# 声明结构体
ProcessInfo = _PROCESS_INFORMATION()
StartupInfo = _STARTUPINFO()
file = 'ModifyMe.exe' # 要进行修改的文件
address = 0x0040103c # 要修改的内存地址
buffer = c_char_p("_") # 缓冲区地址
bytesRead = c_ulong(0) # 读入的字节数
bufferSize = len(buffer.value) # 缓冲区大小
# 创建进程
if CreateProcess(file, 0, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0, byref(StartupInfo), byref(ProcessInfo)):
# 读取要修改的内存地址,以判断是否是要修改的文件
if ReadProcessMemory(ProcessInfo.hProcess, address, buffer, bufferSize, byref(bytesRead)):
if buffer.value == '\x74':
buffer.value = '\x75' # 修改缓冲区内的值,将其写入内存
# 修改内存
if WriteProcessMemory(ProcessInfo.hProcess, address, buffer, bufferSize, byref(bytesRead)):
print '成功改写内存!'
else:
print '写内存错误!'
else:
print '打开了错误的文件!'
TerminateProcess(ProcessInfo.hProcess,0) # 如果不是要修改的文件,则终止进程
else:
print '读内存错误!'
else:
print '不能创建进程!'