A página de manual do Linuxproc(5)
diz que /proc/$pid/mem
"pode ser usado para acessar as páginas da memória de um processo". Mas uma tentativa direta de usá-lo só me dá
$ cat /proc/$$/mem /proc/self/mem
cat: /proc/3065/mem: No such process
cat: /proc/self/mem: Input/output error
Por que não é cat
possível imprimir sua própria memória ( /proc/self/mem
)? E qual é esse erro estranho de "não existe esse processo" quando tento imprimir a memória do shell ( /proc/$$/mem
obviamente o processo existe)? Como posso ler /proc/$pid/mem
, então?
Respostas:
/proc/$pid/maps
/proc/$pid/mem
mostra o conteúdo da memória do $ pid mapeado da mesma maneira que no processo, ou seja, o byte no deslocamento x no pseudo-arquivo é o mesmo que o byte no endereço x no processo. Se um endereço não estiver mapeado no processo, a leitura do deslocamento correspondente no arquivo retornaráEIO
(erro de entrada / saída). Por exemplo, como a primeira página de um processo nunca é mapeada (para que o cancelamento de referência de umNULL
ponteiro falhe de maneira limpa em vez de acessar a memória real sem intenção), a leitura do primeiro byte/proc/$pid/mem
sempre gera um erro de E / S.A maneira de descobrir quais partes da memória do processo são mapeadas é ler
/proc/$pid/maps
. Este arquivo contém uma linha por região mapeada, assim:Os dois primeiros números são os limites da região (endereços do primeiro byte e o byte depois do último, em hexa). A próxima coluna contém as permissões, e há algumas informações sobre o arquivo (deslocamento, dispositivo, inode e nome) se este for um mapeamento de arquivo. Consulte a
proc(5)
página do manual ou Noções básicas sobre Linux / proc / id / maps para obter mais informações.Aqui está um script de prova de conceito que despeja o conteúdo de sua própria memória.
/proc/$pid/mem
Se você tentar ler o
mem
pseudo-arquivo de outro processo, ele não funcionará: você receberá umESRCH
erro (sem esse processo).As permissões em
/proc/$pid/mem
(r--------
) são mais liberais do que deveria ser o caso. Por exemplo, você não deve conseguir ler a memória de um processo setuid. Além disso, tentar ler a memória de um processo enquanto o processo está modificando pode dar ao leitor uma visão inconsistente da memória e, pior ainda, havia condições de corrida que poderiam rastrear versões mais antigas do kernel Linux (de acordo com este segmento lkml , embora eu não conheço os detalhes). Portanto, são necessárias verificações adicionais:/proc/$pid/mem
deve ser anexado ao processo usandoptrace
com oPTRACE_ATTACH
sinalizador. É isso que os depuradores fazem quando começam a depurar um processo; é também ostrace
que as chamadas de sistema de um processo fazem. Depois que o leitor terminar de ler/proc/$pid/mem
, ele deve se desconectar chamandoptrace
com oPTRACE_DETACH
sinalizador.ptrace(PTRACE_ATTACH, …)
interrompe o processo de destino (envia umSTOP
sinal), mas há uma condição de corrida (a entrega do sinal é assíncrona), portanto o rastreador deve chamarwait
(conforme documentado emptrace(2)
).Um processo em execução como root pode ler a memória de qualquer processo, sem precisar chamar
ptrace
, mas o processo observado deve ser parado ou a leitura ainda retornaráESRCH
.Na fonte do kernel Linux, o código que fornece entradas por processo
/proc
está emfs/proc/base.c
, e a função para ler/proc/$pid/mem
émem_read
. A verificação adicional é realizada porcheck_mem_permission
.Aqui está um exemplo de código C para anexar a um processo e ler um pedaço do
mem
arquivo (verificação de erro omitida):Já publiquei um script de prova de conceito para despejo
/proc/$pid/mem
em outro segmento .fonte
/proc/$pid/mem
diretamente (seja comcat
ou comdd
qualquer outra coisa) não funciona. Leia minha resposta./proc/self/mem
. Um processo pode ler seu próprio espaço de memória muito bem, está lendo o espaço de memória de outro processo que requerPTRACE_ATTACH
.process_vm_readv()
chamada do sistema (Linux 3.2).ESRCH
erro neste cenário.Este comando (do gdb) despeja a memória de forma confiável:
Os despejos podem ser grandes, use
-o outfile
se o diretório atual não tiver espaço suficiente.fonte
Quando você executa,
cat /proc/$$/mem
a variável$$
é avaliada pelo bash, que insere seu próprio pid. Em seguida, ele executacat
um pid diferente. Você acabacat
tentando ler a memória debash
seu processo pai. Como processos não privilegiados podem apenas ler seu próprio espaço de memória, isso é negado pelo kernel.Aqui está um exemplo:
Observe que é
$$
avaliado como 17823. Vamos ver qual processo é esse.É o meu shell atual.
Aqui, novamente,
$$
avalio para 17823, que é meu shell.cat
não consigo ler o espaço de memória do meu shell.fonte
$pid
seja. Como explico na minha resposta, a leitura da memória de um processo diferente exige que você a rastreie.$$
quando escreve (e lê)$pid
?$$
e colocando$pid
no final. Transpus na minha cabeça sem perceber. Minha resposta inteira deve se referir$$
, não$pid
.Aqui está um pequeno programa que escrevi em C:
Uso:
O programa usa / proc / $ pid / maps para encontrar todas as regiões de memória mapeadas do processo e, em seguida, lê essas regiões em / proc / $ pid / mem, uma página de cada vez. essas páginas são gravadas no stdout ou no endereço IP e na porta TCP que você especificou.
Código (testado no Android, requer permissões de superusuário):
fonte
write to stdout
imediatamente acimafwrite(..., stdout)
. Veja programmers.stackexchange.com/questions/119600/…