Code Monkey home page Code Monkey logo

memory-scanner's Introduction

Memory Scanner

This program is an x86/x64-based memory scanner. It can search for and modify bytes, integers, and strings. It is essentially a clone of Cheat Engine. This scanner allows the user to search memory addresses for values, and then save those values.

Once a memory value is saved, you can change its data type, add a description, change its address, and more. To run the program, navigate to the proper release folder for your target binary (x86/x64), then download Memory-Scanner.exe, then open it. Upon opening the scanner, it will prompt you for administrative privileges -- which is required for the memory scanning functions to work properly.

Release folders

Technologies used

  • Visual C++
  • .NET Framework 4.8
  • WinForms
  • Windows API

Video demonstration

Memory-Scanner-Demonstration.mp4

Read memory functions

These functions read memory values using the ReadProcessMemory() function from the Windows API. They return the result as a managed string, but this can easily be changed to return as a number type. A couple things to note is that when reading memory from an .exe, you must factor in the module base address. You must also pass in the process handle, which can be done with:

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, NULL, dwProcessId);

All you need is the process ID, and the Windows header, which can be included by using the #include <Windows.h> preprocessor directive. For the string value function, you can modify MAX_STRING_LENGTH to your desired string length. The extra byte added to the string size is to account for the null terminator. For a failed read, you can use GetLastError(), to get the numeric error code.

Read BYTE value

String^ ReadByteFromMemory(HANDLE hProcess, BYTE* cbAddress)
{
	BYTE bValue = 0;

	if (!ReadProcessMemory(hProcess, reinterpret_cast<LPVOID>(cbAddress), &bValue, sizeof(bValue), nullptr))
	{
		return "???";
	}

	return bValue.ToString();
}

Read UInt16 value

String^ ReadUInt16FromMemory(HANDLE hProcess, BYTE* cbAddress)
{
	uint16_t u16Value = 0;

	if (!ReadProcessMemory(hProcess, reinterpret_cast<LPVOID>(cbAddress), &u16Value, sizeof(u16Value), nullptr))
	{
		return "???";
	}

	return u16Value.ToString();
}

Read DWORD value

String^ ReadDWORDFromMemory(HANDLE hProcess, BYTE* cbAddress)
{
	DWORD dwValue = 0;

	if (!ReadProcessMemory(hProcess, reinterpret_cast<LPVOID>(cbAddress), &dwValue, sizeof(dwValue), nullptr))
	{
		return "???";
	}

	return dwValue.ToString();
}

Read UInt64 value

String^ ReadUInt64FromMemory(HANDLE hProcess, BYTE* cbAddress)
{
	uint64_t u64Value = 0;

	if (!ReadProcessMemory(hProcess, reinterpret_cast<LPVOID>(cbAddress), &u64Value, sizeof(u64Value), nullptr))
	{
		return "???";
	}

	return u64Value.ToString();
}

Read String value

String^ ReadStringFromMemory(HANDLE hProcess, BYTE* cbAddress)
{
	const int MAX_STRING_LENGTH = 32;

	array<BYTE>^ cbBufferArray = gcnew array<BYTE>(MAX_STRING_LENGTH);
	pin_ptr<BYTE> cbptrBuffer = &cbBufferArray[0];

	if (ReadProcessMemory(hProcess, (LPCVOID)cbAddress, cbptrBuffer, MAX_STRING_LENGTH, nullptr))
	{
		// Convert the bytes in the buffer to a string using UTF-8 encoding
		System::Text::Encoding^ encoding = System::Text::Encoding::UTF8;
		String^ strValue = encoding->GetString(cbBufferArray);

		// Remove any null characters and trim the string
		int iNullTerminatorIndex = strValue->IndexOf('\0');
		if (iNullTerminatorIndex >= 0)
		{
			strValue = strValue->Substring(0, iNullTerminatorIndex);
		}

		return strValue;
	}

	return "???";
}

Write memory functions

These functions write to memory using the WriteProcessMemory() function from the Windows API. Similar to the read functions, you must also declare the process handle in order to pass it into the function. However, for writing to strings, the declaration is slightly different:

HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);

You also need to factor in the module base address when passing in the address. Also, note that you can easily change the encoding from UTF-8 to UTF-16. Since these functions are written for Visual C++ WinForms, a failed write will launch a message box that will specify the error code. This format can be easily changed to work on a CLI-based application.

Write BYTE value

void WriteByteToMemory(HANDLE hProcess, BYTE* cbAddress, BYTE bValue)
{
	if (!WriteProcessMemory(hProcess, (BYTE*)cbAddress, &bValue, sizeof(bValue), NULL))
	{
		DWORD dwError = GetLastError();

		MessageBox::Show("Failed to write to address, error code: " + dwError.ToString(), "Error",
			MessageBoxButtons::OK, MessageBoxIcon::Error);
	}
}

Write UInt16 value

void WriteUInt16ToMemory(HANDLE hProcess, BYTE* cbAddress, uint16_t u16Value)
{
	if (!WriteProcessMemory(hProcess, (BYTE*)cbAddress, &u16Value, sizeof(u16Value), NULL))
	{
		DWORD dwError = GetLastError();

		MessageBox::Show("Failed to write to address, error code: " + dwError.ToString(), "Error",
			MessageBoxButtons::OK, MessageBoxIcon::Error);
	}
}

Write DWORD value

void WriteDWORDToMemory(HANDLE hProcess, BYTE* cbAddress, DWORD dwValue)
{
	if (!WriteProcessMemory(hProcess, (BYTE*)cbAddress, &dwValue, sizeof(dwValue), NULL))
	{
		DWORD dwError = GetLastError();

		MessageBox::Show("Failed to write to address, error code: " + dwError.ToString(), "Error",
			MessageBoxButtons::OK, MessageBoxIcon::Error);
	}
}

Write UInt64 value

void WriteUInt64ToMemory(HANDLE hProcess, BYTE* cbAddress, uint64_t u64Value)
{
	if (!WriteProcessMemory(hProcess, (BYTE*)cbAddress, &u64Value, sizeof(u64Value), NULL))
	{
		DWORD dwError = GetLastError();

		MessageBox::Show("Failed to write to address, error code: " + dwError.ToString(), "Error",
			MessageBoxButtons::OK, MessageBoxIcon::Error);
	}
}

Write String value

void WriteStringToMemory(HANDLE hProcess, BYTE* cbAddress, const char* cNewString)
{
	// Calculate the size of the string, including the null terminator
	size_t uDataSize = strlen(cNewString) + 1;

	if (!WriteProcessMemory(hProcess, (LPVOID)cbAddress, cNewString, uDataSize, 0))
	{
		DWORD dwError = GetLastError();

		MessageBox::Show("Failed to write to address, error code: " + dwError.ToString(), "Error",
			MessageBoxButtons::OK, MessageBoxIcon::Error);
	}
}

Sources

memory-scanner's People

Contributors

julianozelrose avatar

Stargazers

 avatar

Watchers

 avatar

Forkers

mortonfs

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.