Zikagames - Início Ir para conteúdo
keyboard_arrow_down
account_circle Entrar

Entrar



  • Não recomendado para computadores públicos


  • Esqueceu sua senha?

person_add Cadastre-se
theskytalos

Acessando a memória de processos externos - Endereço Dinâmico

Posts Recomendados

Postado (editado)

Pra começar minha atividade no fórum, resolvi começar com o primeiro tópico de C/C++.

 Lembrando que este tutorial é válido apenas para Windows utilizando a Win32 API. Algo parecido pode ser feito no Linux através das system calls utilizando as funções read e write (veja).

 Um outro ponto importante a ser recordado é que este tutorial se restringe SOMENTE a PROCESSOS EXTERNOS, o que NÃO inclui DLLs injetadas no processo, afinal, injetar uma DLL nada mais é do que você manualmente carregar um módulo executável novo no processo, desta forma, você acaba sendo parte do processo, podendo ter acesso direto à memória do processo sem a necessidade da Win32 API como intermediadora.

As funções de manipulação de memória requerem Permissões de Administrador, portanto, quando for rodar o programa que acessa a memória de uma "vítima", rode-o como Administrador. Se estiver utilizando Visual Studio, rode a própria IDE em Modo Administrador.

Neste tutorial, será abordada somente o acesso à um endereço direto, DINÂMICO, acessar a partir de endereços bases somando offsets fica para uma outra hora.

É extremamente recomendado que você saiba C/C++ e tenha noções de PONTEIROS, pois eu simplesmente os uso, inclusive nas chamadas das funções, e não os explico, pois já assumo que vocês os conheça e saiba usá-los.

Começaremos com o programa que será "invadido", muito simples:

#include <iostream>
#include <Windows.h> // Apenas incluí a API para ter acesso à constante TRUE, a função Sleep e a função SetConsoleTitle.

int main()
{
  	SetConsoleTitle(L"Memory Victim"); // Muda o nome da janela para 'Memory Victim'.
  
	int VictimVar = 64; // Variável que será mudada.

	while (TRUE) // Loop infinito.
	{
      	// Printa a variável a cada 1 segundo.
		std::cout << VictimVar << std::endl;
		Sleep(1000);
	}
}

Note que usei majoritariamente recursos da Win32 API (Windows.h), mas por opção própria, a memória de QUALQUER processo em modo usuário pode ser acessada.

Documentação: SetConsoleTitle, Sleep.

Uma vez escrito o programa "alvo", podemos escrever e aprofundar com detalhes o programa "invasor".
 

#include <iostream>
#include <Windows.h>

int main()
{
	DWORD Address = 0x00EFF990; // Endereço que será lido e escrito no programa alvo.
	DWORD ValueRead = 0x0, NewValue = 0x0;

	DWORD PID;
	
	// Retornará um handle para a janela caso suceda, e nulo caso não encontre.
	 HWND hWindow = FindWindow(NULL, L"Memory Victim");

	// Verifica o sucesso da chamada FindWindow
	if (hWindow == NULL)
	{
		std::cout << "Não foi possível encontrar a janela.";
		exit(EXIT_FAILURE);
	}

	// Pega o PID do processo que criou a thread da Janela através do handle da janela.
	GetWindowThreadProcessId(hWindow, &PID);

	HANDLE pHandle = OpenProcess(PROCESS_ALL_ACCESS, 0, PID);

	// Verifica o sucesso da chamada OpenProcess
	if (pHandle == NULL)
	{
		std::cout << "Não foi possível pegar o handle do processo.";
		exit(EXIT_FAILURE);
	}

	// Lê o endereço presente na variável Address e guarda na variável ValueRead. 
	ReadProcessMemory(pHandle, (void*)Address, &ValueRead, sizeof(ValueRead), 0);

	std::cout << "Valor Lido: " << ValueRead << std::endl;

	NewValue = ValueRead * 2;

	// Duplica o valor que estava no endereço de memória.
	WriteProcessMemory(pHandle, (void*)Address, &NewValue, sizeof(NewValue), 0);

	// Re-lê o a posição de memória para verificar se realmente mudou o valor.
	ReadProcessMemory(pHandle, (void*)Address, &ValueRead, sizeof(ValueRead), 0);

	std::cout << "Novo Valor Lido: " << ValueRead << std::endl;

	system("PAUSE");

	return EXIT_SUCCESS;
}

Aqui a coisa complica um pouco mais complicado, mas vamos lá:
 

  1. Precisamos ler e escrever no processo desejado, para tal, precisamos de um identificador deste processo, que é o PID, obtido pela função GetWindowThreadProcessId . Para utilizar esta função necessita-se de um handler da janela, um jeito comum é pegá-lo através da função FindWindowW (Expandida por FindWindow), procurando pelo título da janela.
  2. Uma vez com o PID em mãos, abrimos o processo utilizando a função OpenProcess com a flag PROCESS_ALL_ACCESS (leia), que nos dará permissão de escrita e leitura na memória virtual do processo.
  3. A partir daí, basta simplesmente ler e/ou escrever na memória do processo, utilizando as funções ReadProcessMemory e WriteProcessMemory.

Rodando o programa "vítima", temos:

image.png.1e484bfccc6e8c6c7b049142a645b559.png

E, rodando o programa "invasor":

image.png.10a9648fcdd7571a5c0aa90283664f94.png

O programa "vítima" após ser "invadido":

image.png.cebb3bf5a980c7f932c1a70deacaef15.png

E é isso, maiores detalhes sobre os argumentos das funções e etc se encontram na documentação da Win32 API que deixei linkadas no artigo.

Editado por theskytalos
Completar o artigo
  • Curti! 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ótimo tópico @theskytalos, parabéns! Amanhã vai ficar mais completo ainda!
Curtido!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Post muito bom, muito completo, parabéns!
Abraços!

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar Agora

  • FIQUE POR DENTRO!
    -Fique por dentro das regras da nossa comunidade! Para mais informações clique aqui!

    - CONFIRA NOSSOS EVENTOS: Premiações em acessórios gamers e gift cards. Para mais informações clique aqui!  
  • Acompanhe o TZN SHOW!





×