Pergunta

Gostaria de saber se Perl, Python ou Ruby pode ser usado para escrever um programa para que ele irá procurar 0x12345678 na memória de outro processo (provavelmente o montão, tanto para dados de dados e código) e, em seguida, se ele for encontrado , alterá-lo para 0x00000000? É algo semelhante ao Cheat Engine , o que pode fazer algo assim no Windows.

Outras dicas

É possível fazê-lo se tiver ligado o seu programa como um depurador para o processo, que deve ser possível nesses idiomas se existem wrappers para as APIs apropriadas, ou acessando diretamente as funções do Windows através de algo como ctypes (para Pitão). No entanto, pode ser mais fácil de fazer em uma linguagem mais baixo nível, uma vez que em aqueles de nível mais alto você vai ter que se preocupar com a forma de traduzir tipos de dados de alto nível para reduzir as etc.

Comece chamando OpenProcess sobre o processo a depuração, com o acesso adequado solicitado (você precisa ser um administrador na máquina / tem bastante elevados privilégios de acesso ganho). Você deve então ser capaz de chamar funções como ReadProcessMemory e WriteProcessMemory para ler e escrever para que de processo memória.

[Edit] Aqui está uma prova python rápida do conceito de uma função que lê com sucesso a memória do espaço de endereço de outro processo:

import ctypes
import ctypes.wintypes
kernel32 = ctypes.wintypes.windll.kernel32

# Various access flag definitions:
class Access:
    DELETE      = 0x00010000
    READ_CONTROL= 0x00020000
    SYNCHRONIZE = 0x00100000
    WRITE_DAC   = 0x00040000
    WRITE_OWNER = 0x00080000
    PROCESS_VM_WRITE = 0x0020
    PROCESS_VM_READ = 0x0010
    PROCESS_VM_OPERATION = 0x0008
    PROCESS_TERMINATE = 0x0001
    PROCESS_SUSPEND_RESUME = 0x0800
    PROCESS_SET_QUOTA = 0x0100
    PROCESS_SET_INFORMATION = 0x0200
    PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
    PROCESS_QUERY_INFORMATION = 0x0400
    PROCESS_DUP_HANDLE = 0x0040
    PROCESS_CREATE_THREAD = 0x0002
    PROCESS_CREATE_PROCESS = 0x0080

def read_process_mem(pid, address, size):
    """Read memory of the specified process ID."""
    buf = ctypes.create_string_buffer(size)
    gotBytes = ctypes.c_ulong(0)
    h = kernel32.OpenProcess(Access.PROCESS_VM_READ, False, pid)
    try:
        if kernel32.ReadProcessMemory(h, address, buf, size, ctypes.byref(gotBytes)):
            return buf
        else:
            # TODO: report appropriate error GetLastError
            raise Exception("Failed to access process memory.")
    finally:
        kernel32.CloseHandle(h)

Note que você vai precisar para determinar onde na memória para olhar para as coisas - a maior parte desse espaço de endereço vai ser não mapeada, pensava há alguns offsets padrão para olhar para coisas como o código do programa, dlls etc

Bem, a parte divertida é obter acesso à memória do outro processo. CheatEngine faz isso executando todo o seu sistema operacional em uma máquina virtual que permite a proteção de memória para ser derrotado. Há também o modelo de 'execução em um depurador', o que significa geralmente iniciar a aplicação alvo como um processo filho do pedido de modificao, com privilégios elevados. Veja a Win32 API para muitas coisas divertidas sobre isso.

Em Perl, uma vez que você teve o acesso necessário, você provavelmente quer interagir com ele usando Win32 :: Segurança :: Raw .

Existem maneiras de fazer isso injeção Processo usando, atraso biblioteca de carregamento etc.

Eu não vê-lo fazendo isso a partir das ferramentas que você tenha listado. Esta é C e assembler país e começando a chegar em território vírus escrito. Depois de conseguir isso para trabalhar, todos os pacotes anti-vírus irá vetá-lo correr e tentar isolá-lo. Então é melhor você realmente quer fazer isso.

"Com o poder vem muito ...."

Boa sorte

É possível implementar todo o processo em um dos idiomas listados, mas uma linguagem compilada seria melhor para a digitalização de memória (considerações de velocidade, se nada mais). Há uma dll (com fonte) chamou SigScan disponíveis que, embora adaptado para um jogo específico, provavelmente poderia ser modificado de acordo com as suas necessidades com o mínimo esforço.

Com base na resposta correta de Brian aqui está um exemplo rápido e sujo de usar uma dll para obter seu endereço de dentro python. Isto é, claro, específico para a implementação DLLs. "Nome do módulo" geralmente seria o nome dll como exibido no cheat engine "Enumerar DLLs e símbolos" de diálogo.

Com o exemplo de Brian como uma diretriz e MSDN você poderia facilmente estender isso com seu próprio método WriteProcessMemory.

import win32defines
import win32process
import win32gui
from ctypes import *
SigScan = cdll.SigScan
kernel32 = windll.kernel32
addresses = {"Value1" : {"sigArg1" : "b0015ec390518b4c24088d4424005068", 
                          "sigArg2" : 36, 
                          "address" : None,
                          "size"    : 32
                         },
            "Value2" :{"sigArg1" : "3b05XXXXXXXX741285c0",
                          "sigArg2" : None, 
                          "address" : None,
                          "size"    : 32
                        }
        }

def read_process_mem(pid, address, size):
    """Read memory of the specified process ID."""
    buf = create_string_buffer(size)
    gotBytes = c_ulong(0)
    h = kernel32.OpenProcess(win32defines.PROCESS_VM_READ, False, pid)
    try:
        if kernel32.ReadProcessMemory(h, address, buf, size, byref(gotBytes)):
            return buf
        else:
            # TODO: report appropriate error GetLastError
            raise Exception("Failed to access process memory.")
    finally:
        kernel32.CloseHandle(h)
if __name__ == "__main__":
    pid, id = None, None
    ## HWND 
    hwnd = win32gui.FindWindowEx(0, 0, 0, "Window Name here")
    ## pid
    pid = win32process.GetWindowThreadProcessId(hwnd)[-1]
    ## Initialize the sigscan dll
    SigScan.InitializeSigScan(pid, "Module Name")
    ## Find all the addresses registered
    for key in addresses.keys():
        addresses[key]["address"] = SigScan.SigScan(addresses[key]["sigArg1"],
            addresses[key]["sigArg2"])
    ## Allow the scanner to clean up
    SigScan.FinalizeSigScan()
    for key in addresses.keys():
        if addresses[key]["address"] != None:
            print repr(read_process_mem(pid, addresses[key]["address"],
                            addresses[key]["size"]).raw)

Eu escrevi Proc :: Memória e sua biblioteca subjacente libvas para esta finalidade. Ele apenas chama {Read,Write}ProcessMemory sob o capô no Windows, mas ele também suporta outras plataformas. Exemplo:

my $mem = Proc::Memory->new(pid => $$); 
$mem->poke(0x12345678, 'L') = 12;
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top