Pergunta

Então, tudo que eu quero fazer é criar um programa Ruby que leia alguns valores de endereços de memória conhecidos na memória virtual de outro processo.Através de minha pesquisa e conhecimento básico de edição hexadecimal de um assembly x86 de um processo em execução na memória, encontrei o endereço base e os deslocamentos para os valores na memória que desejo.Não quero mudá-los;Eu só quero lê-los.Perguntei a um desenvolvedor de um editor de memória como abordar esse resumo da linguagem assumindo uma plataforma Windows.Ele me disse que as chamadas Win32API para OpenProcess, CreateProcess, ReadProcessMemory e WriteProcessMemory eram a melhor opção usando C ou C++.Acho que o caminho a seguir seria apenas usar a classe Win32API e mapear duas instâncias dela;Uma para OpenProcess ou CreateProcess, dependendo se o usuário já tem o processo em execução ou não, e outra instância será mapeada para ReadProcessMemory.Provavelmente ainda preciso encontrar a função para obter a lista de processos em execução para saber qual processo em execução é o que desejo, caso já esteja em execução.

Isso daria algum trabalho para juntar tudo, mas acho que não seria tão ruim codificar.É apenas uma nova área de programação para mim, já que nunca trabalhei nesse nível baixo em uma linguagem de alto nível (bem, de qualquer maneira, em um nível mais alto que C).Estou apenas me perguntando como abordar isso.Eu poderia apenas usar um monte de chamadas Win32API, mas isso significa ter que lidar com um monte de pacotes de strings e arrays e descompactar que depende do sistema. Quero eventualmente fazer com que isso funcione em várias plataformas, já que o processo que estou lendo é produzido a partir de um executável que possui múltiplas compilações de plataforma (eu sei que o endereço de memória muda de sistema para sistema.A ideia é ter um arquivo simples que contenha todos os mapeamentos de memória para que o programa Ruby possa combinar o ambiente da plataforma atual com o mapeamento de memória correspondente.) mas pelo que parece, terei que criar uma classe que envolva o que quer que seja as chamadas de função relacionadas à memória da biblioteca compartilhada do sistema da plataforma atual.

Pelo que sei, já poderia existir uma joia Ruby que cuida de tudo isso para mim e que simplesmente não estou encontrando.Eu também poderia tentar editar os executáveis ​​de cada compilação para que sempre que os valores de memória que desejo ler sejam gravados pelo processo, ele também grave uma cópia do novo valor em um espaço na memória compartilhada que de alguma forma tenho Ruby cria uma instância de uma classe que é um ponteiro oculto para aquele endereço de memória compartilhada e de alguma forma sinaliza ao programa Ruby que o valor foi atualizado e deve ser recarregado.Basicamente, um sistema baseado em interrupções seria bom, mas como o propósito de ler esses valores é apenas enviar para um placar transmitido de um servidor central, eu poderia simplesmente me ater a um sistema baseado em polling que envia atualizações em intervalos de tempo fixos.Eu também poderia abandonar Ruby completamente e optar por C ou C++, mas não os conheço tão bem.Na verdade, conheço mais x86 do que C++ e só conheço C até ANSI C independente do sistema e nunca lidei com bibliotecas de sistema compartilhadas antes.

Então, existe uma jóia ou módulo menos conhecido disponível que já fez isso?Caso contrário, qualquer informação adicional sobre como fazer isso seria boa.Eu acho que, resumindo a história, como faço tudo isso?

Desde já, obrigado, Grg

PS:Também seria bom uma confirmação de que essas chamadas Win32API deveriam ser direcionadas à biblioteca kernel32.dll.

Foi útil?

Solução

Dê uma olhada win32utils.Estou pensando que isso deveria pelo menos ajudá-lo a se levantar e dar exemplos de como se aprofundar na própria API se as joias em si não funcionarem para você.Talvez você precise se arriscar e escrever um módulo em C.

Outras dicas

Utilize Ruby-FFI:

Se você conhece C e a API Win32, talvez seja mais fácil de usar Ruby-FFI gema. Ruby-FFI envolve funções C de forma transparente, permitindo que você use qualquer função Win32.

Para memória compartilhada nomeada, o Win32 fornece CreateFileMapping( ) e MapViewOfFile( ).

Estes têm os cabeçalhos

# WINBASEAPI HANDLE WINAPI CreateFileMappingA(HANDLE,LPSECURITY_ATTRIBUTES,DWORD,DWORD,DWORD,LPCSTR);
# WINBASEAPI PVOID WINAPI MapViewOfFile(HANDLE,DWORD,DWORD,DWORD,DWORD);

Passando um identificador de arquivo inválido 0xFFFFFFFF em CreateFileMapping, você pode evitar lidar com arquivos e simplesmente definir sua memória compartilhada usando arrays e ponteiros.

Abaixo está um exemplo simplificado que lê da memória compartilhada.(Uma versão com qualidade de produção usaria semáforos no leitor e no gravador, e um buffer circular, para permitir que ambos os processos prosseguissem de forma assíncrona, garantindo ao mesmo tempo que o gravador não sobrescrevesse um buffer até que o leitor terminasse de lê-lo.)

Exemplo de Ruby simplificado:

require 'ffi'

module Win32
   extend FFI::Library
   ffi_lib 'kernel32'  # see winbase.h
   attach_function :CreateFileMapping, 
            :CreateFileMappingA,[ :uint, :pointer, :long, :long, :long, :pointer ], :pointer   
            # suffix A indicates the ASCII version
   attach_function :MapViewOfFile, 
            :MapViewOfFile,[ :pointer, :long, :long, :long, :long ], :pointer  
end

memoryName = "Share Memory Name"
sz_buf = 1000  # bytes  (250 ints, 4 bytes each)
num_ints = sz_buf / 4

# Windows constants
PAGE_READWRITE = 0x0004
FILE_MAP_WRITE = 2

# Get handle to shared memory
hMemory = Win32.CreateFileMapping(0xFFFFFFFF, nil, PAGE_READWRITE, 0, sz_buf, memoryName)

# Create pointer into shared memory in the reader's memory space 
pMemory = FFI::MemoryPointer.new(:int, num_ints )
pMemory = Win32.MapViewOfFile(hMemory, FILE_MAP_WRITE, 0, 0, sz_buf)

# Read from shared memory buffer
puts pMemory.read_array_of_int(sz_buf).join(" ")  

Algumas informações úteis:

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top