I've got a super simple program. My intention is to copy standard input to standard output. Here's the source code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
namespace LALA
{
class LALA
{
static void Main()
{
int bufferSize = 40;
Console.OpenStandardInput().CopyTo(Console.OpenStandardOutput(), bufferSize);
}
}
}
If I set bufferSize to 40, then for any input I just see 'C o n', 'C o n s', or 'C o n s o l e' etc.
If I set bufferSize to 41, then everything is fine.
My question is am I doing something wrong, and by accident values above 41 work?
To clarify, this is the output when I type asd:
c:\some_path>ConsoleApplication2.exe
asd
C o n
Surprise! This appears to be internal buffer overflow and I'll share what I found, though it's not yet a real proof it makes sense to me.
The code for CopyTo method of the Stream class is: (taken with reflector)
public void CopyTo(Stream destination, int bufferSize)
{
//bunch of non relevant validations...
this.InternalCopyTo(destination, bufferSize);
}
Now the code for InternalCopyTo is:
private void InternalCopyTo(Stream destination, int bufferSize)
{
byte[] array = new byte[bufferSize];
int count;
while ((count = this.Read(array, 0, array.Length)) != 0)
{
destination.Write(array, 0, count);
}
}
The console stream instance is of type __ConsoleStream (sealed internal class in System.IO) and its Read method code:
public override int Read([In] [Out] byte[] buffer, int offset, int count)
{
//bunch of non relevant validations...
int errorCode = 0;
int num = __ConsoleStream.ReadFileNative(this._handle, buffer, offset, count, 0, out errorCode);
if (num == -1)
{
__Error.WinIOError(errorCode, string.Empty);
}
return num;
}
And finally ReadFileNative code of __ConsoleStream:
private unsafe static int ReadFileNative(SafeFileHandle hFile, byte[] bytes, int offset, int count, int mustBeZero, out int errorCode)
{
if (bytes.Length - offset < count)
{
throw new IndexOutOfRangeException(Environment.GetResourceString("IndexOutOfRange_IORaceCondition"));
}
if (bytes.Length == 0)
{
errorCode = 0;
return 0;
}
__ConsoleStream.WaitForAvailableConsoleInput(hFile);
int result;
int num;
fixed (byte* ptr = bytes)
{
num = __ConsoleStream.ReadFile(hFile, ptr + (IntPtr)offset / 1, count, out result, Win32Native.NULL);
}
if (num != 0)
{
errorCode = 0;
return result;
}
errorCode = Marshal.GetLastWin32Error();
if (errorCode == 109)
{
return 0;
}
return -1;
}
The ReadFile method is low level call:
[DllImport("kernel32.dll", SetLastError = true)]
private unsafe static extern int ReadFile(SafeFileHandle handle, byte* bytes, int numBytesToRead, out int numBytesRead, IntPtr mustBeZero);
My assumption at this point is that behind the scenes, 40 bytes are "reserved" somewhere to internal data so if the buffer is not more than that, you will see that reserved data which in this case of console application is the process name.
I will keep investigating this when I'll have more time and try to reproduce, this case is quite special since both streams point to the same "file" so you can write to it while reading it.
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.
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;
I'm writing a Binary file converter in which I need to convert 1-6 byte arrays into int (short-long) values. At the moment I'm using following three functions, I want to know is there anyway to improve the performance?
private string byteToShortParse(byte[] recordData, int offset, int length)
{
byte[] workingSet = new byte[2];
Buffer.BlockCopy(recordData, offset, workingSet, 0, length);
return (BitConverter.ToInt16(workingSet, 0).ToString());
}
private string byteToIntParse(byte[] recordData, int offset, int length)
{
byte[] workingSet = new byte[4];
Buffer.BlockCopy(recordData, offset, workingSet, 0, length);
return (BitConverter.ToInt32(workingSet, 0).ToString());
}
private string byteToLongParse(byte[] recordData, int offset, int length)
{
byte[] workingSet = new byte[8];
Buffer.BlockCopy(recordData, offset, workingSet, 0, length);
return (BitConverter.ToInt32(workingSet, 0).ToString());
}
Edit2:
I suppose if the number of bytes you need to convert to int is variable length (which does seem strange), I suggest doing it this way:
private string bytesToIntParse(byte[] recordData, int offset, int length)
{
long result = 0;
for (int i = 0; i < length; ++i)
{
result |= ((long)recordData[i + offset]) << (i * 8);
}
return result.ToString();
}
Now you have one function, no Buffer.BlockCopy and it supports any length.
Edit1:
You could use unsafe code such as:
// I don't think you need to specify a length parameter, since int32 is always 4 bytes
private string byteToIntParse(byte[] recordData, int offset, int length)
{
unsafe
{
fixed (byte* p = &recordData[offset])
{
// This result will differ on little and big endian architectures.
return (*(int*)p).ToString();
}
}
}
But this is what BitConverter does internally, so I don't think you will gain any performance
Why are you copying the bytes into workingSet? You could just:
return BitConverter.ToInt32(recordData, offset).ToString()
I guess that yields a performance boost since you don't have to call Buffer.BlockCopy every time :P
Yes, optimal variant would be
private string byteToShortParse(byte[] recordData, int offset, int length)
{
if (length == 2)
{
short i = (recordData[offset + 1] << 8) | recordData[offset];
return i.ToString;
} else return "";
}
The same applies to 4-byte and 8-byte values (just more shifts are needed).
I've successfully read a PE header from an unmanaged module loaded into memory by another process. What I'd like to do now is read the names of this module's exports. Basically, this is what I have so far (I've left out a majority of the PE parsing code, because I already know it works):
Extensions
public static IntPtr Increment(this IntPtr ptr, int amount)
{
return new IntPtr(ptr.ToInt64() + amount);
}
public static T ToStruct<T>(this byte[] data)
{
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
T result = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T));
handle.Free();
return result;
}
public static byte[] ReadBytes(this Process process, IntPtr baseAddress, int size)
{
int bytesRead;
byte[] bytes = new byte[size];
Native.ReadProcessMemory(process.Handle, baseAddress, bytes, size, out bytesRead);
return bytes;
}
public static T ReadStruct<T>(this Process process, IntPtr baseAddress)
{
byte[] bytes = ReadBytes(process, baseAddress, Marshal.SizeOf(typeof(T)));
return bytes.ToStruct<T>();
}
public static string ReadString(this Process process, IntPtr baseAddress, int size)
{
byte[] bytes = ReadBytes(process, baseAddress, size);
return Encoding.ASCII.GetString(bytes);
}
GetExports()
Native.IMAGE_DATA_DIRECTORY dataDirectory =
NtHeaders.OptionalHeader.DataDirectory[Native.IMAGE_DIRECTORY_ENTRY_EXPORT];
if (dataDirectory.VirtualAddress > 0 && dataDirectory.Size > 0)
{
Native.IMAGE_EXPORT_DIRECTORY exportDirectory =
_process.ReadStruct<Native.IMAGE_EXPORT_DIRECTORY>(
_baseAddress.Increment((int)dataDirectory.VirtualAddress));
IntPtr namesAddress = _baseAddress.Increment((int)exportDirectory.AddressOfNames);
IntPtr nameOrdinalsAddress = _baseAddress.Increment((int)exportDirectory.AddressOfNameOrdinals);
IntPtr functionsAddress = _baseAddress.Increment((int)exportDirectory.AddressOfFunctions);
for (int i = 0; i < exportDirectory.NumberOfFunctions; i++)
{
Console.WriteLine(_process.ReadString(namesAddress.Increment(i * 4), 64));
}
}
When I run this, all I get is a pattern of double question marks, then completely random characters. I know the header is being read correctly, because the signatures are correct. The problem has to lie in the way that I'm iterating over the function list.
The code at this link seems to suggest that the names and ordinals form a matched pair of arrays, counted up to NumberOfNames, and that the functions are separate. So your loop may be iterating the wrong number of times, but that doesn't explain why you're seeing bad strings from the very beginning.
For just printing names, I'm having success with a loop like the one shown below. I think the call to ImageRvaToVa may be what you need to get the correct strings? However I don't know whether that function will work unless you've actually loaded the image by calling MapAndLoad -- that's what the documentation requests, and the mapping did not seem to work in some quick experiments I did using LoadLibrary instead.
Here's the pInvoke declaration:
[DllImport("DbgHelp.dll", CallingConvention = CallingConvention.StdCall), SuppressUnmanagedCodeSecurity]
public static extern IntPtr ImageRvaToVa(
IntPtr NtHeaders,
IntPtr Base,
uint Rva,
IntPtr LastRvaSection);
and here's my main loop:
LOADED_IMAGE loadedImage = ...; // populated with MapAndLoad
IMAGE_EXPORT_DIRECTORY* pIID = ...; // populated with ImageDirectoryEntryToData
uint* pFuncNames = (uint*)
ImageRvaToVa(
loadedImage.FileHeader,
loadedImage.MappedAddress,
pIID->AddressOfNames,
IntPtr.Zero);
for (uint i = 0; i < pIID->NumberOfNames; i++ )
{
uint funcNameRVA = pFuncNames[i];
if (funcNameRVA != 0)
{
char* funcName =
(char*) (ImageRvaToVa(loadedImage.FileHeader,
loadedImage.MappedAddress,
funcNameRVA,
IntPtr.Zero));
var name = Marshal.PtrToStringAnsi((IntPtr) funcName);
Console.WriteLine(" funcName: {0}", name);
}
}
What is the easiest way to get a PID that listens on a given port in C#?
Basically, I want to make sure that my service is running and listens on a port I have provided it.
If there is an easier way than parsing netstat output it will be great.
from win XP SP2 onwards you can P/Invoke to GetExtendedTcpTable
Using This person's kind work to flesh out the signature (the PInvoke.net spec is incomplete) here is a (rough and poor at error checking) example
using System;
using System.Runtime.InteropServices;
public enum TCP_TABLE_CLASS : int
{
TCP_TABLE_BASIC_LISTENER,
TCP_TABLE_BASIC_CONNECTIONS,
TCP_TABLE_BASIC_ALL,
TCP_TABLE_OWNER_PID_LISTENER,
TCP_TABLE_OWNER_PID_CONNECTIONS,
TCP_TABLE_OWNER_PID_ALL,
TCP_TABLE_OWNER_MODULE_LISTENER,
TCP_TABLE_OWNER_MODULE_CONNECTIONS,
TCP_TABLE_OWNER_MODULE_ALL
}
[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCPROW_OWNER_PID
{
public uint state;
public uint localAddr;
public byte localPort1;
public byte localPort2;
public byte localPort3;
public byte localPort4;
public uint remoteAddr;
public byte remotePort1;
public byte remotePort2;
public byte remotePort3;
public byte remotePort4;
public int owningPid;
public ushort LocalPort
{
get
{
return BitConverter.ToUInt16(
new byte[2] { localPort2, localPort1}, 0);
}
}
public ushort RemotePort
{
get
{
return BitConverter.ToUInt16(
new byte[2] { remotePort2, remotePort1}, 0);
}
}
}
[StructLayout(LayoutKind.Sequential)]
public struct MIB_TCPTABLE_OWNER_PID
{
public uint dwNumEntries;
MIB_TCPROW_OWNER_PID table;
}
[DllImport("iphlpapi.dll", SetLastError=true)]
static extern uint GetExtendedTcpTable(IntPtr pTcpTable,
ref int dwOutBufLen,
bool sort,
int ipVersion,
TCP_TABLE_CLASS tblClass,
int reserved);
public static MIB_TCPROW_OWNER_PID[] GetAllTcpConnections()
{
MIB_TCPROW_OWNER_PID[] tTable;
int AF_INET = 2; // IP_v4
int buffSize = 0;
// how much memory do we need?
uint ret = GetExtendedTcpTable(IntPtr.Zero,
ref buffSize,
true,
AF_INET,
TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL,
0);
if (ret != 0 && ret != 122) // 122 insufficient buffer size
throw new Exception("bad ret on check " + ret);
IntPtr buffTable = Marshal.AllocHGlobal(buffSize);
try
{
ret = GetExtendedTcpTable(buffTable,
ref buffSize,
true,
AF_INET,
TCP_TABLE_CLASS.TCP_TABLE_OWNER_PID_ALL,
0);
if (ret != 0)
throw new Exception("bad ret "+ ret);
// get the number of entries in the table
MIB_TCPTABLE_OWNER_PID tab =
(MIB_TCPTABLE_OWNER_PID)Marshal.PtrToStructure(
buffTable,
typeof(MIB_TCPTABLE_OWNER_PID));
IntPtr rowPtr = (IntPtr)((long)buffTable +
Marshal.SizeOf(tab.dwNumEntries));
tTable = new MIB_TCPROW_OWNER_PID[tab.dwNumEntries];
for (int i = 0; i < tab.dwNumEntries; i++)
{
MIB_TCPROW_OWNER_PID tcpRow = (MIB_TCPROW_OWNER_PID)Marshal
.PtrToStructure(rowPtr, typeof(MIB_TCPROW_OWNER_PID));
tTable[i] = tcpRow;
// next entry
rowPtr = (IntPtr)((long)rowPtr + Marshal.SizeOf(tcpRow));
}
}
finally
{
// Free the Memory
Marshal.FreeHGlobal(buffTable);
}
return tTable;
}
check out this project:
http://www.codeproject.com/KB/IP/iphlpapi.aspx
It uses Interop in C# to get to the underlying GetTcpTable Win API function. And therefore can give you the process id you are looking for.
hope that helps,
Alex