Giter Site home page Giter Site logo

jamesmenetrey / memorysharp Goto Github PK

View Code? Open in Web Editor NEW
624.0 624.0 134.0 4.87 MB

A C# based memory editing library targeting Windows applications, offering various functions to extract and inject data and codes into remote processes to allow interoperability.

License: Other

C# 100.00%

memorysharp's People

Contributors

cooloppo avatar jamesmenetrey avatar xeropresence avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

memorysharp's Issues

equivalent to ReadProcessMemory

I've been trying to achieve this code with MemorySharp read with address and pointer but without success,

`byte[] object_pointer = new byte[4];

int bytesRead;

var objAddress = Base + 0x4C5F4C;

ReadProcessMemory(App.GameProcess.Process.Handle, objAddress, object_pointer, 4, out bytesRead);`

but i get The relative address cannot be greater than the main module size.

I tried this
IntPtr objectPointer = sharp.Read<IntPtr>(Base + 0x4C5F4C);

The problem is there's a pointer stored on memory address i want to read that pointer from the address, the code above works but i have to write more code to change from byte[] to IntPtr to use it again on assembly transaction.

AssemblyFactory.Execute is terribly slow

I tried using MemorySharp to replace some dirty code I was using to Execute assembly from the memory.

First allocates the memory like this :

// First allocate the memory
RemoteAllocation getflagfunmem = safeHandle.Memory.Allocate(0x8000);

string[] asm =
{
    "mov eax, 0x" + (getflagfunmem.BaseAddress + 0x400).ToString("X"),
    "mov eax, [eax]",
    "push eax",
    "call 0x" + Pointers.GET_EVENT_FLAG.ToString("X"),
    "ret"
};

safeHandle.Assembly.Inject(asm, getflagfunmem.BaseAddress);

And then call it later on like this :

safeHandle.Write(getflagfunmem.BaseAddress + 0x400, eventID, false);
int flags = safeHandle.Assembly.Execute<int>(getflagfunmem.BaseAddress);
return (flags >> 7) == 1;

But I found that the Execute is terribly slow compared to my previous code, showed here :

// Note that the asm code used is a tiny bit different. Since I can't 
// automatically read the result with I can with Execute, the asm code
// writes the result in getflagfunmem.BaseAddress + 0x404 instead
safeHandle.Write(getflagfunmem.BaseAddress + 0x400, eventID, false);

IntPtr newThreadHook = (IntPtr)CreateRemoteThread(safeHandle.Handle, 0, 0, (int)getflagfunmem.BaseAddress, 0, 0, 0);
WaitForSingleObject(newThreadHook, 0xFFFFFFFFU);
CloseHandle(newThreadHook);

int flags = safeHandle.Read<int>(getflagfunmem.BaseAddress + 0x404, false);

And as you can see from the Execution times (in ms), the Execute code :

Flags function called 709 times, average duration : 5.46240267983074
Flags function called 709 times, average duration : 5.70936375176305

Is much slower than my own code, using Kernel calls :

Flags function called 709 times, average duration : 0.186416502115656
Flags function called 709 times, average duration : 0.187183215796897

MemoryCore.Query unsigned 32-bit address overflow

Environment

Windows11 64bit os

Target process

32bit process
my process is 32bit process.

Problem

I am trying to query and read the space of 0xFF3F0000.
However, this must be accessed as unsigned.

image

public IEnumerable<RemoteRegion> Regions => from page in MemoryCore.Query(addressTo: new IntPtr(int.MaxValue), processHandle: MemorySharp.Handle, addressFrom: IntPtr.Zero)
                                            select new RemoteRegion(MemorySharp, page.BaseAddress);

int.MaxValue is 0x7FFFFFFF, but i scan address is 0xFFFF****

If you enter a larger value, an overflow error window will appear.

Exception occurred: 'System.OverflowException' (mscorlib.dll)
An unhandled exception of type 'System.OverflowException' occurred in mscorlib.dll.
An arithmetic operation caused an overflow.

I think there should be no overflow and the maximum value should be 0xFFFFFFFF or SYSTEM_INFO maximumApplicationAddress (GetSystemInfo) and there should be no overflow.

Execute return wrong values on x64bit

realreturn
the function return value = 0x0166DCB00900

execute function return value =0xDCB00900

as you can see there are missing bytes .
bad return
the problem in GetExitCodeThread function return , I don't know how to fix that.
bad return code

var keyAddress = sharp.Assembly.Execute<IntPtr>(gameFunc, CallingConventions.MicrosoftX64, new dynamic[] { ecx });
@JamesMenetrey

Execute?

hi .
I've using your lib to do something fun.
thanks a lot!
but I have a question.
Is AssemblyFactory.Execute() can call a injected funtion too?
when I injected my test dll to another game process and get successful.
I dont know how to call my funtions.
please answer me.
thank you!

@JamesMenetrey

System.ApplicationException

I'm trying to write an external hack, but can't seem to make it work.
Here's the error message:
System.ApplicationException: Couldn't get the information from the process, error code '-1073741820'. in Binarysharp.MemoryManagement.Memory.MemoryCore.NtQueryInformationProcess(SafeMemoryHandle processHandle) in Binarysharp.MemoryManagement.MemorySharp..ctor(Process process) in Invoker.Program.Main(String[] args) in source\repos\Invoker\Invoker\Program.cs:row 18

And here's the code

Bugs report!

1.window.Mouse.MoveTo(0, 0);
If the "window" is a child control, mouse can not move correctly!

2.If an application has 2+ top level windows, WindowFactory.RemoteWindows can not collect all!
Maybe should support "TopLevelWindows" property, and "MainWindow" is just the first visible one in collections.

3.Why don't support a "Parent" property in RemoteWindow?

public string ReadString(IntPtr address, Encoding encoding, bool isRelative = true, int maxLength = 0x200)
{
string str = encoding.GetString(this.ReadBytes(address, maxLength, isRelative));
int index = str.IndexOf('\0');
return str.Substring(0, index);

==>

return index==-1?str:str.Substring(0,index);//If don't find "\0" in maxLength, just return it.
}

var sharp = new MemorySharp(Process.GetCurrentProcess());
sharp["kernel32"]["MessageBoxW"].Execute(0, "Hey", "Title", 0);
this code contains so many errors
(1) kernel32 => user32
(2)sharp["user32"]["MessageBoxW"].Execute(0, "Hey", "Title", 0);
will throw an exception.
should: sharp["user32"]["MessageBoxW"].Execute(CallingConventions.Stdcall,0, "Hey", "Title", 0);
(3)MessageBoxW can not work normally, MessageBoxA can.
(4)sharp["user32"]["MessageBoxA"].Execute(CallingConventions.Stdcall,0, "汉字", "Title", 0);
If the string contains non-latin character, such as Chinese, this code can not work correctly.
I must do it like this:

//my process
(1).sharp["user32"]["MessageBoxA"].Execute(CallingConventions.Stdcall, 0, Marshal.StringToHGlobalAnsi("汉字"), "Title", 0);
(2).sharp["user32"]["MessageBoxW"].Execute(CallingConventions.Stdcall, 0, Marshal.StringToHGlobalUni("汉字"), Marshal.StringToHGlobalUni("Title"), 0);

//remote process
(3).
var bytes = Encoding.GetEncoding("gb2312").GetBytes("汉字");
Array.Resize(ref bytes, bytes.Length + 1);
RemoteAllocation ra = ms.Memory.Allocate(bytes.Length);
ra.Write(bytes);
sharp["user32"]["MessageBoxA"].Execute(CallingConventions.Stdcall, 0, ra.BaseAddress, "Title", 1);

I think MemorySharp should support:
RemoteAllocation/Inptr Write/WriteString (data)
{
}
not need pass in address as paramter and the method will alloc proper size and return the address.(like Marshal.StringToHGlobalAnsi)

Wrong value returned when using the Fasm32Assembler without pointer

When using the Fasm32Assembler you will get 2 different byte arrays when using the Assemble method.

Below I've provided a quick example:
The following string is used: "jmp 4259840"
byte[] asm = assembler.Assemble(asmString); // Returns 233,251,255,64,0
byte[] asm = assembler.Assemble(asmString, _addressToPatch.BaseAddress); // returns 233,231,251,64,255

The complete code i'm using is this:
Fasm32Assembler assembler = new Fasm32Assembler();
string asmString = String.Join("\n", newAsm.ToArray());
// There is a bug currently in the Assembler.Assemble method.
// We are forced to pass in an address otherwise it will return a wrong byte array.
byte[] asm = assembler.Assemble(asmString);
asm = assembler.Assemble(asmString, _addressToPatch.BaseAddress);
PatchBytes(asm);

So I'm always forced to pass a pointer with the asm string otherwise the wrong values are returned.
The place where the different values return from are:
/// <summary>
/// Assemble the specified assembly code at a base address.
/// </summary>
/// <param name="asm">The assembly code.</param>
/// <param name="baseAddress">The address where the code is rebased.</param>
/// <returns>An array of bytes containing the assembly code.</returns>
public byte[] Assemble(string asm, IntPtr baseAddress)
{
// Rebase the code
asm = String.Format("use32\norg 0x{0:X8}\n", baseAddress.ToInt64()) + asm;
// Assemble and return the code
return FasmNet.Assemble(asm);
}

Located in Binarysharp.MemoryManagement.Assembly.Assembler.Fasm32Assembler.

Enhance the string encoding interoperability.

Background

Currently, strings are read and written using dedicated methods (ReadString/WriteString). While those functions enable the develop to specify the encoding, this is not the case for the Execute methods. Indeed, those methods can be called with arbitrary .NET parameters but there is no way to specify an encoding.

This enhancement addresses this issue by adding a layer of abstraction on .NET strings. A new class, possibly EncodedString, describes a string and an encoding. The dedicated methods for strings will be removed and replaced by the traditional Read/Write methods. Extension methods will helps the developer to encode properly a string.

API DEMO

Before:
s.WriteString(address, text); // UTF8 by default
s.WriteString(address, text, Encoding.Ansi);
p.Execute(callingConvention, text); // Only in UTF8

After:
s.Write(address, text); // UTF8 by default
s.Write(address, text.EncodeAsAnsi());
p.Execute(callingConvention, text.EncodeAsAnsi()); // Handle any encoding

Question about mixing Fasm.net and P/Invoke method

Hi, i manage to use your library to get the CPU id with the following code :

 public static class Asm
    {
        [SuppressUnmanagedCodeSecurity] // disable security checks for better performance
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)] // cdecl - let caller (.NET) clean the stack
        private delegate IntPtr AssemblyReadRegistersFunction();
        [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
        private delegate CpuIdResult CpuIDDelegate(int level);

        [StructLayout(LayoutKind.Sequential, Size = 16)]
        public struct CpuIdResult
        {
            public int Eax;
            public int Ebx;
            public int Ecx;
            public int Edx;
        }
        internal static string CPUIdAsm()
        {
            using (var currentProcess = new ProcessSharp(System.Diagnostics.Process.GetCurrentProcess(), MemoryType.Local))
            {
                FasmNet fasmNet = new FasmNet();
                fasmNet.AddLine("use32"); //Tell FASM.Net to use x86 (32bit) mode
                fasmNet.AddLine("PUSH EBX");
                fasmNet.AddLine("PUSH EDI");
                fasmNet.AddLine("MOV EDI, EAX");
                fasmNet.AddLine("MOV EAX, 1");
                fasmNet.AddLine("DW $A20F");
                fasmNet.AddLine("STOSD");
                fasmNet.AddLine("MOV EAX, EBX");
                fasmNet.AddLine("STOSD");
                fasmNet.AddLine("MOV EAX, ECX");
                fasmNet.AddLine("STOSD");
                fasmNet.AddLine("MOV EAX, EDX");
                fasmNet.AddLine("STOSD");
                fasmNet.AddLine("POP EDI");
                fasmNet.AddLine("POP EBX");
                fasmNet.AddLine("RET");  // in cdecl calling convention, return value is stored in EAX; so this will return both params added up
                byte[] assembledCode = fasmNet.Assemble();

                var allocatedCodeMemory = currentProcess.MemoryFactory.Allocate(
                    name: "Example3", // only used for debugging; not really needed
                    size: assembledCode.Length,
                    protection: MemoryProtectionFlags.ExecuteReadWrite /* It is important to mark the memory as executeable or we will get exceptions from DEP */
                );
                allocatedCodeMemory.Write(0, assembledCode);
                var myAssemblyFunction = Marshal.GetDelegateForFunctionPointer<CpuIDDelegate>(allocatedCodeMemory.BaseAddress);

                CpuIdResult result = myAssemblyFunction(1);

                var returnValue = result;
                // Warning: Potential memory leak!
                // Do not forget to dispose the allocated code memory after usage. 
                allocatedCodeMemory.Dispose();               
                int cpuid1 = returnValue.Eax;
                int cpuidpluscomplement = cpuid1 & 0x0FFF7FFF;
                string converted = cpuidpluscomplement.ToString("X8");                
                return converted;
            }

        }
    }

this work like a charm but only if i execute it "alone".
If i first call

 string driveletter = Path.GetPathRoot(Environment.GetFolderPath(Environment.SpecialFolder.System));
            if (driveletter != "")
            {
                uint serialNumber = VolumeSerialNumber(driveletter);
                machineDesc.Append(serialNumber.ToString("X8"));
            }

where
VolumeSerialNumber is

 private static uint VolumeSerialNumber(string driveLetter)
        {
            StringBuilder volname = new StringBuilder(261);
            StringBuilder fsname = new StringBuilder(261);
            uint sernum, maxlen;
            FileSystemFeature flags;
            GetVolumeInformation(driveLetter, volname, volname.Capacity, out sernum, out maxlen, out flags, fsname, fsname.Capacity);            
            return sernum;
        }

        #region DllImport
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rootPathName"></param>
        /// <param name="volumeNameBuffer"></param>
        /// <param name="volumeNameSize"></param>
        /// <param name="volumeSerialNumber"></param>
        /// <param name="maximumComponentLength"></param>
        /// <param name="fileSystemFlags"></param>
        /// <param name="fileSystemNameBuffer"></param>
        /// <param name="nFileSystemNameSize"></param>
        /// <returns></returns>
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal extern static bool GetVolumeInformation(string rootPathName, StringBuilder volumeNameBuffer, int volumeNameSize, out uint volumeSerialNumber, out uint maximumComponentLength, out FileSystemFeature fileSystemFlags, StringBuilder fileSystemNameBuffer, int nFileSystemNameSize);

        #endregion

the Asm.CPUIdAsm() method return 0 for all value in the struct

[StructLayout(LayoutKind.Sequential, Size = 16)]
        public struct CpuIdResult
        {
            public int Eax;
            public int Ebx;
            public int Ecx;
            public int Edx;
        }

i put a sample test in attachment.

I hope you can help me
ConsoleApp1.zip

Keyboard press and write does not work.

It seems like the Keyboard press and write does not work. I tried this with both Notepad and Notepad++. Does anyone know of a fix for this? Thanks!

Using Version 1.2 of MemorySharp.
Windows 10 x64
VS2017

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Binarysharp.MemoryManagement;
using System.Diagnostics;

namespace memsharp_test_1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

    private void Form1_Load(object sender, EventArgs e)
    {
        var sharp = new MemorySharp(Process.GetCurrentProcess());

        var tlsPtr = sharp.Threads.MainThread.Teb.Tls;

        Console.WriteLine(tlsPtr.ToString());

        var wh = sharp.Windows.GetWindowsByTitleContains("Notepad").FirstOrDefault();

        Console.WriteLine(wh.ToString());

        wh.Keyboard.Press(Binarysharp.MemoryManagement.Native.Keys.A); // does nothing
        wh.Keyboard.PressRelease(Binarysharp.MemoryManagement.Native.Keys.A); // does nothing

        wh.Width = 800; // works
        wh.Height = 600; // works

        wh.Keyboard.Write("test 123"); // does nothing

    }
}

}

Question about mixing MemorySharp and P/Invoke method

    HI, sorry for having posting on the wrong repo.

I modify my code to use MemorySharp instead.
Here is the code:

internal static string CPUIIDMemorySharp()
        {
            var sharp = new MemorySharp(System.Diagnostics.Process.GetCurrentProcess());

            using (var memory = sharp.Memory.Allocate(24))
            {
                AssemblyTransaction fasmNet;
                using (fasmNet = sharp.Assembly.BeginTransaction(memory.BaseAddress))
                {
                    fasmNet.AddLine("use32"); //Tell FASM.Net to use x86 (32bit) mode
                    fasmNet.AddLine("PUSH EBX"); //{Save affected register}
                    fasmNet.AddLine("PUSH EDI");
                    fasmNet.AddLine("MOV EDI, EAX"); //{@Resukt}
                    fasmNet.AddLine("MOV EAX, 1");
                    fasmNet.AddLine("DW $A20F"); //CPUID Command}
                    fasmNet.AddLine("STOSD");  //{ CPUID[1]}
                    fasmNet.AddLine("MOV EAX, EBX");
                    fasmNet.AddLine("STOSD"); //{CPUID[2]}
                    fasmNet.AddLine("MOV EAX, ECX");
                    fasmNet.AddLine("STOSD"); //{CPUID[3]}
                    fasmNet.AddLine("MOV EAX, EDX");
                    fasmNet.AddLine("STOSD"); //{CPUID[4]}
                    fasmNet.AddLine("POP EDI"); //{Restore registers}
                    fasmNet.AddLine("POP EBX");
                    fasmNet.AddLine("RETN");  // in cdecl calling convention, return value is stored in EAX; so this will return both params added up
                }

                var myAssemblyFunction = Marshal.GetDelegateForFunctionPointer<CpuIDDelegate>(memory.BaseAddress);
                CpuIdResult result = myAssemblyFunction(1);              
                int cpuid1 = result.Eax;
                int cpuidpluscomplement = cpuid1 & 0x0FFF7FFF;
                string converted = cpuidpluscomplement.ToString("X8");
                return converted;
            }

I end with the same problem, if i execute this code first, i have a value in

CpuIdResult result = myAssemblyFunction(1);  
int cpuid1 = result.Eax;

If i made a call to a P/Invoke method first, the struct CpuIdResult has all this properties to 0.
When i first call MemorySharp
image

When i call a P/Invoke method before calling MemorySharp:
image

Here is the modified example /repro project.
ConsoleApp1.zip

I'm pretty sure i'm missing something but what...
I hope you will have the time to take a look, and maybe a lead for me

Originally posted by @smardine in #26 (comment)

Calling a thiscall function?

How do you call a thiscall function? I know the function's address and the 'this' pointer but when I call it like 'sharp.Assembly.Execute((IntPtr)0x0123, CallingConventions.Thiscall, (IntPtr)0x0123);', the program crashes.

Pattern Mechanisms?

Hi,

I assume Pattern Mechanisms are going to be things such as: Byte Search and Replace, Byte Search to return a memory address, etc, correct?

System.ComponentModel.Win32Exception (299): Couldn't read 12 byte(s) from 0x5662FFCC.

Hello, not sure if this is an error or i did a mistake. But im trying to call a function from a running process externally.
The function is: double __thiscall sub_2A1E7C(_DWORD *this, float a2, float a3)

 static public void Walk()
        {
            var swed = new Swed("Game");
            var moduleBase = swed.GetModuleBase("Game.exe");

            Process game = Mem.GetRagWindow("Game");
            var address = moduleBase + 0x29CE50; // function address
            MemorySharp sharp = new MemorySharp(game);

            // Execute code and get the return value as a Vector3 structure
            Vector3 vector = sharp[address].Execute<Vector3>(Binarysharp.MemoryManagement.Assembly.CallingConvention.CallingConventions.Thiscall, 17.50, -77.50);
            Console.WriteLine(vector);
        }

And im getting error: System.ComponentModel.Win32Exception (299): Couldn't read 12 byte(s) from 0x5662FFCC.

v1.1.1.0 is not available on nuget.org

The package on nuget.org contains a DLL marked v1,1,0.0. I can't get this DLL to work. I get runtime exception:

{"Couldn't get the information from the process, error code '-1073741820'."}

But if I use v1.1.1.0 manually, without nuget, then it works fine.

Can you piblish 1.1.1.0 to nuget? Thanks!

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.