I am busy rewriting a piece of code from C++ in to C#
Currently I am stuck at the following
pCommBuf = new BYTE[nSize+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE+SB_OEM_CHK_SUM_SIZE];
nReceivedBytes = comm_recv( pCommBuf, nSize+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE+SB_OEM_CHK_SUM_SIZE, gCommTimeOut );
if( nReceivedBytes != nSize+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE+SB_OEM_CHK_SUM_SIZE )
{
if(pCommBuf)
delete pCommBuf;
return PKT_COMM_ERR;
}
memcpy(Buf, pCommBuf, SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE);
memcpy(pBuf, pCommBuf+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE, nSize);
wReceivedChkSum = *(WORD*)(pCommBuf+nSize+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE);
I have the code working up to this point
//memcpy(Buf, pCommBuf, SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE);
Marshal.Copy(pCommBuf, Buf, 0, (int)(SB_OEM_HEADER_SIZE + SB_OEM_DEV_ID_SIZE)); // This works
//memcpy(pBuf, pCommBuf+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE, nSize);
I am not sure how to do pCommBuf+SB_OEM_HEADER_SIZE+SB_OEM_DEV_ID_SIZE in C#, pCommBuff is a IntPtr and in C++ Byte*
You simply need to change the start offset for the 2nd copy :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;
namespace ConsoleApplication1
{
class Program
{
const int SB_OEM_HEADER_SIZE = 10;
const int SB_OEM_DEV_ID_SIZE = 10;
const int SB_OEM_CHK_SUM_SIZE = 10;
static void Main(string[] args)
{
int nSize = 1024;
byte[] nBuf = new byte[nSize];
byte[] Buf = new byte[SB_OEM_HEADER_SIZE + SB_OEM_DEV_ID_SIZE];
IntPtr pCommBuf = Marshal.AllocHGlobal(nSize + SB_OEM_HEADER_SIZE + SB_OEM_DEV_ID_SIZE + SB_OEM_CHK_SUM_SIZE);
Marshal.Copy(nBuf, 0, pCommBuf, nSize);
Marshal.Copy(pCommBuf + nSize , Buf, 0, (int)(SB_OEM_HEADER_SIZE + SB_OEM_DEV_ID_SIZE));
}
}
}
Related
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;
namespace BaseAddress
{
class Program`enter code here`
{
[DllImport("kernel32.dll")]
public static extern bool WriteProcessMemory(int hProcess, Int64 lpBaseAddress, byte[] lpBuffer,
int nSize, ref int lpNumberOfBytesWritten);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
public static extern bool ReadProcessMemory(int hProcess,
Int64 lpBaseAddress, byte[] lpBuffer, int dwSize, ref int lpNumberOfBytesRead);
const int PROCESS_WM_ALL = 0xFFFF;
static void Main(string[] args)
{
Process[] process = Process.GetProcessesByName("Notepad");
Console.WriteLine(GetBase("Notepad"));
Console.WriteLine(GetAdd("Notepad",FromHex("59-00-6F-00-59-00"));
}
public static long GetAdd(string app, byte[] findthis)
{
byte[] buffer = new byte[findthis.Length];
int bytesRead = 0;
long foundAddr = 0;
Process[] processes = Process.GetProcessesByName(app);
Process process = processes[0];
IntPtr procHandle = OpenProcess(PROCESS_WM_ALL, false, process.Id);
long addr = 13188986418;
Console.WriteLine(addr);
Console.WriteLine("Starting address 0x{0}", (addr).ToString("X"));
bool ret2 = ReadProcessMemory((int)procHandle, addr, buffer, buffer.Length, ref bytesRead);
string p = BitConverter.ToString(buffer,0);
string tmp = BitConverter.ToString(findthis, 0);
Console.WriteLine(p);
Console.WriteLine(tmp);
if (p == tmp)
{
foundAddr = addr;
Console.WriteLine("Found it at 0x{0}", foundAddr.ToString("X"));
} else
{
Console.WriteLine("NO");
}
return foundAddr;
}
static long GetBase(string app)
{
long add = 0;
using (Process proc = new Process())
{
Process[] processes = Process.GetProcessesByName(app);
ProcessModule pm;
ProcessModuleCollection pmc = processes[0].Modules;
for (int i = 0; i < pmc.Count; i++)
{
pm = pmc[i];
if(pm.ModuleName.Replace(".exe","") == processes[0].ProcessName)
{
add = pm.BaseAddress.ToInt64();
}
}
}
return add;
}
public static byte[] FromHex(string hex)
{
hex = hex.Replace("-", "");
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return raw;
}
So what I'm trying to do is create a function that I can provide the process name ("Notepad" in this example) and a byte array (in hex) and then the program scans the process in memory, finds the first instance of the matching array, and provides the address of it.
This works for finding a byte array BUT i have to hard code the starting point
what i don't understand is how the base address is 140696861212672 (dec)
yet the address where the code actually is is 13188986418 (dec)
This is the console output:
140696861212672
13188986418
Starting address 0x3121FF632
59-00-6F-00-59-00
59-00-6F-00-59-00
Found it at 0x3121FF632
13188986418
Any idea how i can get this to start at the start of the memory, skip empty zones in memory and loop a chunk of byte array until the array is found?
Hope that makes sense. Any help is welcome.
I am new to C# and I am experiencing an issue when trying to display the value of a memory address.
This is the pointer and offset I am trying to get working:
Link to Cheat Engine Image
When I read the address "0x005040E8" with no offset I receive the correct value in the console:
Console result below:
Last Error: 0
Memory address 0x5040E8
Memory value 13828056
When I add an offset I receive a 16 length address which naturally has no value.
Console result below:
Last Error: 0
Memory address 0xCA0FE800D41E70
Memory value 0
Here is my code attempting to find the value of 0x005040E8 with an offset of 0x00011E98:
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ConsoleApp3
{
using memoryTest;
class Program
{
static unsafe void Main(string[] args)
{
Process proc = Process.GetProcessesByName("testApp")[0];
var hProc = memapi.OpenProcess(memapi.ProcessAccessFlags.All, false, proc.Id);
var modBase = memapi.GetModuleBaseAddress(proc, "testApp");
//var modBase2 = memapi.GetModuleBaseAddress(proc.Id, "testApp");
var memoryAddr = memapi.FindDMAAddy(hProc, (IntPtr)(0x005040E8), new int[] { 0x00011E98 });
System.Console.WriteLine("Last Error: " + Marshal.GetLastWin32Error());
Console.WriteLine("Memory address " + "0x" + memoryAddr.ToString("X"));
var buffer = new byte[IntPtr.Size];
memapi.ReadProcessMemory(hProc, memoryAddr, buffer, buffer.Length, out var read);
Console.WriteLine("Memory value " + BitConverter.ToInt32(buffer, 0));
Console.ReadKey();
}
}
}
Here are the relevant functions:
public static extern bool ReadProcessMemory(
IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, Int32 nSize, out IntPtr lpNumberOfBytesRead);
public static IntPtr GetModuleBaseAddress(int procId, string modName)
{
IntPtr modBaseAddr = IntPtr.Zero;
IntPtr hSnap = CreateToolhelp32Snapshot(SnapshotFlags.Module | SnapshotFlags.Module32, procId);
if (hSnap.ToInt64() != INVALID_HANDLE_VALUE)
{
MODULEENTRY32 modEntry = new MODULEENTRY32();
modEntry.dwSize = (uint)Marshal.SizeOf(typeof(MODULEENTRY32));
if (Module32First(hSnap, ref modEntry))
{
do
{
if (modEntry.szModule.Equals(modName))
{
modBaseAddr = modEntry.modBaseAddr;
break;
}
} while (Module32Next(hSnap, ref modEntry));
}
}
CloseHandle(hSnap);
return modBaseAddr;
}
public static IntPtr FindDMAAddy(IntPtr hProc, IntPtr ptr, int[] offsets)
{
var buffer = new byte[IntPtr.Size];
foreach (int i in offsets)
{
ReadProcessMemory(hProc, ptr, buffer, buffer.Length, out
var read);
ptr = (IntPtr.Size == 4) ? IntPtr.Add(new IntPtr(BitConverter.ToInt32(buffer, 0)), i) : ptr = IntPtr.Add(new IntPtr(BitConverter.ToInt64(buffer, 0)), i);
}
return ptr;
}
I do not believe using a base address is needed, I have tried FindDMAAddy(hProc, (IntPtr)(modebase + 0x005040E8), new int[] { 0x00011E98 }); but it still failed. Any help would be greatly appreciated.
This is the code in Form1:
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 System.Diagnostics;
using System.Runtime.InteropServices;
namespace MemoryScanner
{
public partial class Form1 : Form
{
[DllImport("kernel32.dll")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress,
[In, Out] byte[] buffer, UInt32 size, out IntPtr lpNumberOfBytesRead);
public static byte[] ReadBytes(IntPtr Handle, Int64 Address, uint BytesToRead)
{
IntPtr ptrBytesRead;
// ptrBytesRead = (IntPtr)30;
byte[] buffer = new byte[BytesToRead];
ReadProcessMemory(Handle, new IntPtr(Address), buffer, BytesToRead, out ptrBytesRead);
Array.Resize<byte>(ref buffer, ptrBytesRead.ToInt32());
return buffer;
}
public static int ReadInt32(long Address, uint length = 4, IntPtr? Handle = null)
{
return BitConverter.ToInt32(ReadBytes((IntPtr)Handle, Address, length), 0);
}
public static string ReadString(long Address, uint length = 32, IntPtr? Handle = null)
{
string temp3 = ASCIIEncoding.Default.GetString(ReadBytes((IntPtr)Handle, Address, length));
string[] temp3str = temp3.Split('\0');
return temp3str[0];
}
public Form1()
{
InitializeComponent();
Process p = null;
UInt32 Address = 00002688;
// get process
Process[] Processes = Process.GetProcesses();
List<Process> flash_processes = new List<Process>();
for (int i = 0; i < Processes.Length; i++)
{
//IntPtr f = Test[i].MainModule.BaseAddress;// Are you sure you want the flag process ?
p = Processes[i];
if (p.ProcessName.StartsWith("FlashPlugin") == true)
flash_processes.Add(p);
}
Process Test = flash_processes[1]; // take the second flash process .. are you sure about that? we need the second process ?
p = Candy;
UInt32 proc_base_addr = (UInt32)p.MainModule.BaseAddress.ToInt32();//+00000+1835008+100000;
uint proc_mem_sz = (uint)p.MainModule.ModuleMemorySize;
// byte[] arr = ReadBytes(p.Handle, proc_base_addr, proc_mem_sz);
byte[] arr = ReadBytes(p.Handle, proc_base_addr, proc_mem_sz);//5 * 1024 * 1024);
The project is under Admin.
The size i'm getting arr is: 1888256 also the variable proc_mem_sz contain: 1888256
When i'm using the windows Task Manager i see two processes one it's memory size: 78.1MB
The second one is: 3.1MB
The problem is that i can't get the specific process memory size.
I need it to read all the memory of a specific process.
ModuleMemorySize indicates the amount of memory that is required to load the module. It includes only the size of the static code and data in the module file, but no additional allocations made from the module after it's been loaded.
To get detailed information about the memory usage of a process you should look at GetProcessMemoryInfo. You can find an example here.
You can retrieve information about the current working set (the amount of memory physically mapped to its process context) with QueryWorkingSet \ QueryWorkingSetEx. More info here.
this is the code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
[DllImport("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, out int lpdwProcessId);
[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
public static extern Int32 ReadProcessMemory(IntPtr hProcess, int lpBaseAddress, out string buffer, int size, out int lpNumberOfBytesRead);
public List<int> Search(string ProcessName, int _Length, int Value)
{
Process[] P = Process.GetProcessesByName(ProcessName);
List<int> tmp = new List<int>();
if (P.Length < 0) return tmp;
try
{
if (P[0].HasExited)
return tmp;
}
catch { return tmp; }
byte[] buff = new byte[4];
int Address = P[0].MainModule.BaseAddress.ToInt32();
for (int i = 0; i < _Length; i++)
{
ReadProcessMemory(P[0].Handle, Address + i, buff, 4, 0);
if (BitConverter.ToInt32(buff, 0) == Value)
{
tmp.Add(Address + i);
}
}
return tmp;
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
listBox1.DataSource = Search("plugin-container", 0x100, 15035990);
}
}
}
the problem:
ReadProcessMemory(P[0].Handle, Address + i, buff, 4, 0);
That line is wrong
He marks it with a red line
Does anyone have any idea why he does not recognize this line?
Sorry about my bad English
Your P/Invoke definitions are not quite right. While lpBuffer is annotated as an __out parameter, this does not translate to the .Net P/Invoke meaning of out. If you notice it is an LPVOID, which if this was truly a .Net out it should be LPVOID* (pointer to a pointer).
Instead:
[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
public static extern bool ReadProcessMemory(
IntPtr hProcess, // <-- Pointers should be IntPtr
IntPtr lpBaseAddress,
byte[] buffer, // <-- Using byte[], also IntPtr could be used
uint size, // <-- SIZE_T is unsigned
out uint lpNumberOfBytesRead);
Used like so:
uint bytesRead;
byte[] buffer = new byte[4];
IntPtr baseAddress = P[0].MainModule.BaseAddress;
for (int i = 0; i < _Length; i++)
{
IntPtr nextAddress = IntPtr.Add(baseAddress, i);
if (ReadProcessMemory(
P[0].Handle,
nextAddress,
buffer,
(uint)buffer.Length,
out bytesRead))
{
if (bytesRead == buffer.Length
&& BitConverter.ToInt32(buffer, 0) == Value)
{
tmp.Add(nextAddress);
}
else if (bytesRead != buffer.Length)
{
throw new InvalidOperationException(String.Format(
#"Read {0} bytes (expecting {1}) at {2:X}",
bytesRead,
buffer.Length,
nextAddress.ToInt64()));
}
}
else
{
throw new InvalidOperationException(String.Format(
#"Could not read {0} bytes at {1:X}",
buffer.Length,
nextAddress.ToInt64()));
}
}
return tmp;
This is my first time using C#, so I'm very much out of my element. But I have faith that the wonderful people here at Stack Overflow can help me out! I've come up with the following code (below) based on some other pieces of code I found floating around on the internet. What I am trying to do is to look up all the "text" DNS records (TXT) of a given domain. I've started out simple, with a Console Application in Visual C# 2008 Express looking up the records for google.com. I'll worry about customizing the domain based on command line parameters later; for now I'd just like to get this working. Any DNS lookup tools can tell you that google.com has this DNS text record in their DNS:
v=spf1 include:_netblocks.google.com ip4:216.73.93.70/31 ip4:216.73.93.72/31 ~all
But unfortunately that's not what I'm getting. Here's my code:
namespace DnsUtils
{
using System;
using System.Collections;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Text;
public class DnsTxt
{
[DllImport("dnsapi", EntryPoint = "DnsQuery_W", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
private static extern int DnsQuery([MarshalAs(UnmanagedType.VBByRefStr)]ref string pszName, QueryTypes wType, QueryOptions options, int aipServers, ref IntPtr ppQueryResults, int pReserved);
[DllImport("dnsapi", CharSet = CharSet.Auto, SetLastError = true)]
private static extern void DnsRecordListFree(IntPtr pRecordList, int FreeType);
public static string[] GetTXTRecords(string domain)
{
IntPtr ptr1 = IntPtr.Zero;
IntPtr ptr2 = IntPtr.Zero;
TXTRecord recTxt;
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
throw new NotSupportedException();
}
ArrayList list1 = new ArrayList();
UnicodeEncoding encoding = new UnicodeEncoding();
int num1 = DnsTxt.DnsQuery(ref domain, QueryTypes.DNS_TYPE_TEXT, QueryOptions.DNS_QUERY_BYPASS_CACHE, 0, ref ptr1, 0);
if (num1 != 0)
{
throw new Win32Exception(num1);
}
for (ptr2 = ptr1; !ptr2.Equals(IntPtr.Zero); ptr2 = recTxt.pNext)
{
recTxt = (TXTRecord)Marshal.PtrToStructure(ptr2, typeof(TXTRecord));
if (recTxt.wType == 16)
{
IntPtr pointerToAddressStringArray = Marshal.AllocHGlobal(IntPtr.Size);
IntPtr addressStringArray = Marshal.ReadIntPtr(pointerToAddressStringArray);
for (int i = 0; i < recTxt.dwStringCount; i++)
{
IntPtr addressCharArray = Marshal.ReadIntPtr(recTxt.pStringArray, i * 4);
int offset = 0;
ArrayList bytesList = new ArrayList();
byte newByte = Marshal.ReadByte(addressCharArray, offset++);
while (newByte != 0)
{
bytesList.Add(newByte);
newByte = Marshal.ReadByte(addressCharArray, offset++);
}
byte[] bytesArray = new byte[offset];
bytesList.CopyTo(bytesArray);
string textValue = encoding.GetString(bytesArray);
list1.Add(textValue);
}
Marshal.FreeHGlobal(pointerToAddressStringArray);
}
}
DnsTxt.DnsRecordListFree(ptr2, 0);
return (string[])list1.ToArray(typeof(string));
}
private enum QueryOptions
{
DNS_QUERY_ACCEPT_TRUNCATED_RESPONSE = 1,
DNS_QUERY_BYPASS_CACHE = 8,
DNS_QUERY_DONT_RESET_TTL_VALUES = 0x100000,
DNS_QUERY_NO_HOSTS_FILE = 0x40,
DNS_QUERY_NO_LOCAL_NAME = 0x20,
DNS_QUERY_NO_NETBT = 0x80,
DNS_QUERY_NO_RECURSION = 4,
DNS_QUERY_NO_WIRE_QUERY = 0x10,
DNS_QUERY_RESERVED = -16777216,
DNS_QUERY_RETURN_MESSAGE = 0x200,
DNS_QUERY_STANDARD = 0,
DNS_QUERY_TREAT_AS_FQDN = 0x1000,
DNS_QUERY_USE_TCP_ONLY = 2,
DNS_QUERY_WIRE_ONLY = 0x100
}
private enum QueryTypes
{
DNS_TYPE_TEXT = 16
}
[StructLayout(LayoutKind.Sequential)]
private struct TXTRecord
{
public IntPtr pNext;
public string pName;
public short wType;
public short wDataLength;
public int flags;
public int dwTtl;
public int dwReserved;
public int dwStringCount;
public IntPtr pStringArray;
}
static void Main(string[] args)
{
try
{
string[] s = DnsUtils.DnsTxt.GetTXTRecords("google.com");
foreach (string st in s)
{
Console.WriteLine("Value: {0}", st);
}
}
catch (Win32Exception e)
{
Console.WriteLine(e.Message);
}
Console.ReadLine();
}
}
}
When I run this code, it prints Value: ?. Now I'm hoping that this means it actually did the DNS query and got the results as expected, but I just screwed something up in the part where it tries to convert an IntPtr to an array of strings (because I'm guessing it's harder to debug the former). Anyways, have any suggestions? Can anyone see where I went awry? Thanks in advance.
This line looks a bit off to me:
IntPtr addressCharArray = Marshal.ReadIntPtr(recTxt.pStringArray, i * 4);
It looks like you'd be reading the first 4 bytes of the first string entry of the TXT record as an IntPtr. I think something like:
string s = Marshal.PtrToStringAuto(recTxt.pStringArray);
would get you the first entry. After that, I think something like:
IntPtr p = new IntPtr(recTxt.pStringArray.ToInt32() + sizeof(uint) * i);
string s = Marshal.PtrToStringAuto(p);
would get the remainders.
As a simpler alternative you could avoid dealing with all the COM interop by creating a new nslookup process and parsing the StandardOuput to grab what you need.
using System;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var startInfo = new ProcessStartInfo("nslookup");
startInfo.Arguments = "-type=TXT google.com";
startInfo.RedirectStandardOutput = true;
startInfo.UseShellExecute = false;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
using (var cmd = Process.Start(startInfo))
{
// This is where you grab the output from nslookup.
Console.WriteLine(cmd.StandardOutput.ReadToEnd());
}
Console.Read();
}
}
}