2021年3月30日 星期二

[程式碼] Python修改程式記憶體

 #-*-coding:utf-8 -*-
import io, sys
try:
  sys.stdout=io.TextIOWrapper(sys.stdout.buffer,encoding='utf8')
except:
  pass
import win32api, win32gui, win32con, win32process, win32security
from ctypes import *
from ctypes import wintypes
liAddr = []

# https://www.programcreek.com/python/example/114361/win32security.AdjustTokenPrivileges
def AcquirePrivilege(privilege):
    process = win32process.GetCurrentProcess()
    token = win32security.OpenProcessToken(
        process,
        win32security.TOKEN_ADJUST_PRIVILEGES | win32security.TOKEN_QUERY)
    priv_luid = win32security.LookupPrivilegeValue(None, privilege)
    privilege_enable = [(priv_luid, win32security.SE_PRIVILEGE_ENABLED)]
    #privilege_disable = [(priv_luid, win32security.SE_PRIVILEGE_REMOVED)]
    win32security.AdjustTokenPrivileges(token, False, privilege_enable)

#https://yiyibooks.cn/__trs__/meikunyuan6/pywin32/pywin32/PyWin32/win32api__GetSystemInfo_meth.html
'''
wProcessorArchitecture
dwPageSize
lpMinimumApplicationAddress
lpMaximumApplicationAddress
dwActiveProcessorMask
dwNumberOfProcessors
dwProcessorType
dwAllocationGranularity
'''
# http://www.rohitab.com/discuss/topic/39525-process-memory-scannerpy/
# https://forums.codeguru.com/showthread.php?560337-Windows-Python-Memory-Scanner
# https://mpxd.net/code/jan/mem_edit/commit/5c75da31d5a7ec1e43f9ab542c1f8b4eea01f44a?lang=ja-JP
class MEMORY_BASIC_INFORMATION32(Structure):
    _fields_ = [
            ('BaseAddress', wintypes.DWORD),
            ('AllocationBase', wintypes.DWORD),
            ('AllocationProtect', wintypes.DWORD),
            ('RegionSize', wintypes.DWORD),
            ('State', wintypes.DWORD),
            ('Protect', wintypes.DWORD),
            ('Type', wintypes.DWORD),
            ]
class MEMORY_BASIC_INFORMATION64(Structure):
    _fields_ = [
            ('BaseAddress', c_ulonglong),
            ('AllocationBase', c_ulonglong),
            ('AllocationProtect', wintypes.DWORD),
            ('RegionSize', c_ulonglong),
            ('State', wintypes.DWORD),
            ('Protect', wintypes.DWORD),
            ('Type', wintypes.DWORD),
            ]

def ScanMemStep0(hProcess, nSize, nValue):  # 從頭開始尋找記憶體並記錄匹配位址
    li = win32api.GetSystemInfo()
    BaseAddr = li[2]
    MaxAddr = li[3]
    global liAddr
    liAddr = []
    windll.kernel32.VirtualQueryEx.argtypes = [wintypes.HANDLE, 
        wintypes.LPCVOID,
        c_void_p,
        c_size_t]
    while BaseAddr < MaxAddr:
        PTR_SIZE = sizeof(c_void_p)
        if PTR_SIZE == 8:       # 64-bit python
            MEMORY_BASIC_INFORMATION = MEMORY_BASIC_INFORMATION64
        elif PTR_SIZE == 4:     # 32-bit python
            MEMORY_BASIC_INFORMATION = MEMORY_BASIC_INFORMATION32
        MBI = MEMORY_BASIC_INFORMATION()
        MBI_pointer = byref (MBI)
        size = sizeof (MBI)
        windll.kernel32.VirtualQueryEx(
        hProcess,
        BaseAddr,
        MBI_pointer,
        size)
        if MBI.Protect == win32con.PAGE_READWRITE and \
            MBI.State == win32con.MEM_COMMIT:
            for i in range(0, MBI.RegionSize, nSize):
                data = win32process.ReadProcessMemory(hProcess, MBI.BaseAddress+i, nSize)
                if int.from_bytes(data, byteorder='little') == nValue:
                    liAddr.append(MBI.BaseAddress+i)
        BaseAddr += MBI.RegionSize

def ScanMemStep1(hProcess, nSize, nValue):  # 接續尋找變更資料後的記憶體
    global liAddr
    for i in range(len(liAddr)-1, -1, -1):
        data = win32process.ReadProcessMemory(hProcess, liAddr[i], nSize)
        if int.from_bytes(data, byteorder='little', signed=True) != nValue:
            liAddr.pop(i)

def WriteMem(hProcess, nSize, nValue):  # 修改記憶體內容
    global liAddr
    if len(liAddr) != 1:
        return
    # 使用此方式異常
    # buffer = nValue.to_bytes(nSize, byteorder="little", signed=True)
    # win32process.WriteProcessMemory(hProcess, liAddr[0], buffer)
    windll.kernel32.WriteProcessMemory.argtypes = [c_void_p, c_void_p, c_void_p, c_int, c_void_p]
    lpNumberOfBytesWritten = c_size_t(0)
    windll.kernel32.WriteProcessMemory(hProcess, 
        c_char_p(liAddr[0]), # lpBaseAddress
        addressof(c_longlong(nValue)),  # lpBuffer
        nSize,
        byref(lpNumberOfBytesWritten))

if __name__ == "__main__":
    AcquirePrivilege("SeTimeZonePrivilege")
    hWnd = win32gui.FindWindow(None, "維京碼農")
    if hWnd != 0:
        tid, pid = win32process.GetWindowThreadProcessId(hWnd)
        '''
        hProcess = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION |
            win32con.PROCESS_VM_READ | 
            win32con.PROCESS_VM_WRITE,
            False,
            pid)
        '''
        hProcess = windll.kernel32.OpenProcess(win32con.PROCESS_QUERY_INFORMATION |
            win32con.PROCESS_VM_READ | 
            win32con.PROCESS_VM_WRITE,
            False,
            pid)
        while True:
            str = input("Input Scan Step、Size And Value: ")
            liStr = str.split(" ")
            if liStr[0] == "0":
                ScanMemStep0(hProcess, int(liStr[1]), int(liStr[2]))
                print("Count Of liAddr = %d\n" % len(liAddr))
            elif liStr[0] == "1":
                ScanMemStep1(hProcess, int(liStr[1]), int(liStr[2]))
                print("Count Of liAddr = %d\n" % len(liAddr))
                if len(liAddr) == 1:
                    print("Addr Of Value = %x\n" % liAddr[0])
            elif liStr[0] == "w":
                WriteMem(hProcess, int(liStr[1]), int(liStr[2]))
            elif liStr[0] == "q":
                print("Bye Bye")
    else:
        print("App Not Found")
    input("Press Any Key...")

0 意見:

張貼留言

 
Design by Free WordPress Themes | Bloggerized by Lasantha - Premium Blogger Themes | Blogger Templates