SetConsoleActiveScreenBuffer does not display screen buffer - c#

I am currently trying to write a console application in C# with two screen buffers, which should be swapped back and forth (much like VSync on a modern GPU). Since the System.Console class does not provide a way to switch buffers, I had to P/Invoke several methods from kernel32.dll.
This is my current code, grossly simplified:
static void Main(string[] args)
{
IntPtr oldBuffer = GetStdHandle(-11); //Gets the handle for the default console buffer
IntPtr newBuffer = CreateConsoleScreenBuffer(0, 0x00000001, IntPtr.Zero, 1, 0); //Creates a new console buffer
/* Write data to newBuffer */
SetConsoleActiveScreenBuffer(newBuffer);
}
The following things occured:
The screen remains empty, even though it should be displaying newBuffer
When written to oldBuffer instead of newBuffer, the data appears immediately. Thus, my way of writing into the buffer should be correct.
Upon calling SetConsoleActiveScreenBuffer(newBuffer), the error code is now 6, which means invalid handle. This is strange, as the handle is not -1, which the documentation discribes as invalid.
I should note that I very rarely worked with the Win32 API directly and have very little understanding of common Win32-related problems. I would appreciate any sort of help.

As IInspectable points out in the comments, you're setting dwDesiredAccess to zero. That gives you a handle with no access permissions. There are some edge cases where such a handle is useful, but this isn't one of them.
The only slight oddity is that you're getting "invalid handle" rather than "access denied". I'm guessing you're running Windows 7, so the handle is a user-mode object (a "pseudohandle") rather than a kernel handle.
At any rate, you need to set dwDesiredAccess to GENERIC_READ | GENERIC_WRITE as shown in the sample code.
Also, as Hans pointed out in the comments, the declaration on pinvoke.net was incorrect, specifying the last argument as a four-byte integer rather than a pointer-sized integer. I believe the correct declaration is
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr CreateConsoleScreenBuffer(
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwFlags,
IntPtr lpScreenBufferData
);

Related

Whats the difference between open and native handle in c#

I am looking for the difference between
IntPtr handle_1 = process.Handle;
Gets the native handle of the associated process.
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr OpenProcess(
uint processAccess,
bool bInheritHandle,
uint processId
);
IntPtr handle_2 = OpenProcess(0x0010,false,process.Id);
If the function succeeds, the return value is an open handle to the specified process.
Both got different values. But i can still read the memory with those. I would like to understand the difference between those two, to prevent making mistakes.
I am using them in the context:
ReadProcessMemory(handle_x, addr, data, data.Length, IntPtr.Zero);
Both are process handles, and as such can be used in the same manner.
A Process object contains a process handle through its Handle property. When you call Dispose on that object, you close that handle.
When you call OpenProcess on the process' ID, you get a different handle (so it has a different value) that refers to the same process. You must separately close that handle when you're done with it (using the Win32 function CloseHandle): disposing the Process object won't magically close the handle you got from OpenProcess.
So why would you call OpenProcess when you already have a perfectly functional handle in Process? Well, access rights, really. The handle obtained by Process has PROCESS_ALL_ACCESS (i.e. full access rights). If you want an handle with fewer rights, you can use OpenProcess for that.
But really, for most purposes, there isn't really a need to mess around with native APIs when you need a process handle.

Can Keylogger apps able to see the messages sent via SendMessage()?

I am creating a c# app to send a message in a notepad using the SendMessage() function. I have successfuly passed the strings to notepad. The strings are very important and i was wondering if a keylogger program can see this message?
If yes, do you have any other ideas on how i can send the strings securely?
Below is a sample code i used.
[DllImport("user32.dll", EntryPoint = "FindWindowEx")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
[DllImport("User32.dll")]
public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, string lParam);
Process[] notepads = Process.GetProcessesByName("notepad");
if (notepads.Length == 0) return;
if (notepads[0] != null)
{
IntPtr child = FindWindowEx(notepads[0].MainWindowHandle, new IntPtr(0), "Edit", null);
SendMessage(child, 0x000C, 0, TextBox1.Text);
}
What you're doing is not secure; there are multiple ways a SendMessage call can be spied on by anyone who wants to do so.
SetWindowsHookEx with WH_CALLWNDPROC or WH_CALLWNDPROCRET will let an attacker monitor all messages being sent to a given thread, or they can monitor all messages across the system and just filter out the ones headed to your SendMessage target.
Alternately, an attacker can inject themselves into your recipient process, using WriteProcessMemory to write a DLL name into the recipient process, then CreateRemoteThread and LoadLibrary to load the DLL into the target process. After that, monitoring the process's messages should be fairly trivial.
To avoid using a DLL, an attacker could also use WriteProcessMemory to write code directly into the target process's memory space, then CreateRemoteThread to call it.
All three of these monitoring methods are documented in this CodeProject article. It's admittedly a little old, but the methods should still be relevant, particularly the SetWindowsHookEx one.
An attacker could also hook various Windows APIs directly; it's difficult and somewhat risky, but depending on the sensitivity of your data an attacker might find it a worthwhile approach.
Trying to protect your data will be very difficult, honestly. You can look at how KeePass keeps passwords secure; it's got a setting (at least in the 1.x branch; KeePass 2.x is an entirely different app) to "allow pasting only once and protect against clipboard spies", which might be of some benefit to you. Taking another cue from KeePass, you can also look into Windows' Data Protection API.
As a side note, you may want to replace
SendMessage(child, 0x000C, 0, TextBox1.Text);
with
SendMessage(child, WM_SETTEXT, 0, TextBox1.Text);
for readability. Not many people will recognize 0x000C by itself, although it's possible to guess what the message is based on context.

C# p/invoke, Reading data from an Owner Drawn List Box

I have an Owner Drawn List Box in an external application (America Online) that I need to get data out of for building a component to assist people with its usability. (the utility will be making access of certain things more simple, etc).
Notice
My knowledge of C++ is very poor. I am a C# programmer.
I have the hWnd to the List Box in question, but it appears to be owner drawn. Using LB_GETTEXT returns bad data, I just get junk (it renders in my debugger as a bunch of chinese characters) and going through LB_GETITEMDATA returns much the same.
I believe this is because the owner drawn list box has graphics on it. Doing a lot of digging, I have discovered others in the past with this problem. I have unearthed the following code that is supposed to remedy this issue. However it does not. The code is posted below, and the issues beneath it.
void GetListItemData( HWND hListWnd, long index, char *outputResult )
{
int result;
DWORD processID;
HANDLE hProcess;
char *itemData;
char sDataRead[5];
DWORD bytes;
DWORD lListItemHold, lListItemDataHold;
*outputResult=0;
if( hListWnd )
{
GetWindowThreadProcessId( hListWnd, &processID );
hProcess=OpenProcess( 0x10|0xf0000|PROCESS_VM_READ, 0, processID );
if( hProcess )
{
lListItemHold=(DWORD)SendMessage( hListWnd, LB_GETITEMDATA, index-1, 0 );
lListItemHold=lListItemHold+24;
result=ReadProcessMemory( hProcess, (void *)lListItemHold, &sDataRead, 4, &bytes );
if( !result )
{
RaiseWinErr();
}
memcpy( &lListItemDataHold, &sDataRead, 4 );
lListItemDataHold=lListItemDataHold+6;
ReadProcessMemory( hProcess, (void *)lListItemDataHold, outputResult, 16, &bytes );
CloseHandle( hProcess );
}
}
}
My understanding, limited as it is, is that lListItemHold=lListItemHold+24 tries to account for whatever 'structure' is in the ListBox and pass through the first 24 bytes of it, and return what remains. However this does not seem to be working for me.
Can anyone shed some light on things I could try? I know I am grasping at straws as it is. I am coding this in C#, so this function is used using p/invoke such as follows;
[DllImport("GetListItemData.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void RetrieveListItem(
System.IntPtr hWnd,
System.Int32 index,
[MarshalAs(UnmanagedType.LPArray)]byte[] buffer
);
[DllImport("GetListItemData.dll", CallingConvention = CallingConvention.Cdecl)]
internal static extern void RetrieveListItem(
System.IntPtr hWnd,
System.Int32 index,
[MarshalAs(UnmanagedType.LPTStr)]System.Text.StringBuilder buffer
);
I have two blog posts on the topic
http://taylorza.blogspot.com/2009/08/archive-hacking-my-way-across-process.html
http://taylorza.blogspot.com/2010/06/crossing-process-boundary-with-net.html
These however are for a ListView control, but you might want to take a look at the code. The second post is using P/Invoke to achieve this in .NET.
1- Why are you adding 24 to lListItemHold?
2- Are you sure lListItemhold is a pointer to a string, it might be some internal structure of the application.

Call a function from an injected DLL

First off I would like to say, that I am not trying to hack a game. I am actually employed by the company whose process I am trying to inject. :)
I would like to know how to call a function from an already injected DLL.
So, I have successfully injected and loaded my DLL in the target using CreateRemoteThread(). Below you can see a snippet of the injection:
private static bool Inject(Process pToBeInjected, string sDllPath,out string sError, out IntPtr hwnd, out IntPtr hLibModule)
{
IntPtr zeroPtr = (IntPtr)0;
hLibModule = zeroPtr;
IntPtr hProcess = NativeUtils.OpenProcess(
(0x2 | 0x8 | 0x10 | 0x20 | 0x400), //create thread, query info, operation ,write, and read
1,
(uint)pToBeInjected.Id);
hwnd = hProcess;
IntPtr loadLibH = NativeUtils.GetProcAddress( NativeUtils.GetModuleHandle("kernel32.dll"),"LoadLibraryA");
IntPtr dllAddress = NativeUtils.VirtualAllocEx(
hProcess,
(IntPtr)null,
(IntPtr)sDllPath.Length, //520 bytes should be enough
(uint)NativeUtils.AllocationType.Commit |
(uint)NativeUtils.AllocationType.Reserve,
(uint)NativeUtils.MemoryProtection.ExecuteReadWrite);
byte[] bytes = CalcBytes(sDllPath);
IntPtr ipTmp = IntPtr.Zero;
NativeUtils.WriteProcessMemory(
hProcess,
dllAddress,
bytes,
(uint)bytes.Length,
out ipTmp);
IntPtr hThread = NativeUtils.CreateRemoteThread(
hProcess,
(IntPtr)null,
(IntPtr)0,
loadLibH, //handle to LoabLibrary function
dllAddress,//Address of the dll in remote process
0,
(IntPtr)null);
uint retV= NativeUtils.WaitForSingleObject(hThread, NativeUtils.INFINITE_WAIT);
bool exitR = NativeUtils.GetExitCodeThread(hThread, out hLibModule);
return true;
}
Note: Error checking and freeing resources were removed for brevity, but rest assured I check all the pointers and free my resources.
After the function above exits, I have a non-zero module handle to my DLL returned by LoadLibrary through hLibModule, meaning that the DLL was loaded correctly.
My DLL is a C# class library meant to show a message box (for testing). I have tried testing the function and the message box pops up. It looks like this:
public class Class1
{
public static void ThreadFunc(IntPtr param )
{
IntPtr libPtr = LoadLibrary("user32.dll");
MessageBox(IntPtr.Zero, "I'm ALIVE!!!!", "InjectedDll", 0);
}
[DllImport("kernel32", SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern int MessageBox(IntPtr hWnd, String text, String caption, int options);
}
I compile it from Visual Studio and the DLL appears in the Debug folder. I then pass the full path of my DLL to the injector.
After injection into the target process, I don't know how to call my ThreadFunc from the injected DLL, so it never executes.
I cannot use GetProcAddress(hLibModule,"ThreadFunc") since I am out of process, so the answer must lie into calling CreateRemoteThread() somehow. Also, I have read that DllMain is no longer allowed for .NET DLLs, so I cannot get any free execution that way either.
Does anyone have any idea how to call a function from an injected DLL?
Thank you in advance.
Well, you already got a thread running inside that process. You make it do something boring, it only loads a DLL. This works completely by accident, LoadLibrary just happens to have to correct function signature.
It can do much more. That however better be unmanaged code, just like LoadLibrary(), you cannot count on any managed code running properly. That takes a heckofalot more work, you have to load and initialize the CLR and tell it to load and execute the assembly you want to run. And no, you cannot load the CLR in DllMain().
Keywords to look for are CorBindToRuntimeEx() and ICLRRuntimeHost::ExecuteInAppDomain(). This is gritty stuff to get going but I've seen it done. COM and C++ skills and generous helpings of luck required.

C# string to long pointer

I am working with an application in C# that need to send a message to a C++ application.
I imported
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(
int hWnd, // handle to destination window
uint Msg, // message
IntPtr wParam, // first message parameter
IntPtr lParam // second message parameter
);
but now, my problem is that I need to passe string to wParam and lParam. I tried unsafe code, but it seems string just doesnt work like the rest of variables. How can I achieve that? Thanks.
The declaration is wrong, the wParam and lParam arguments are IntPtr, not long.
There is a complication because you are trying to send strings. What matters if the target window is Unicode enabled or not. There are two versions of SendMessage, SendMessageA() and SendMessageW(). The former needs to be used if the program is dated and uses 8-bit character strings rather than UTF-16 encoded strings.
You can find out by using Spy++. Use the finder tool to select the window of the application. In the General property tab, you'll see "Window proc". It will say (Unicode) if the window is Unicode enabled. If you don't see it then the strings have to be translated to 8-bit characters.
To generate the string pointers you need to pass, you can use Marshal.StringToHGlobalAnsi or StringToHGlobalUni (respectively 8-bit and Unicode). You can however play a trick to let the P/Invoke marshaller translate the string for you. Saves you the hassle of having to free the strings after the call. For the Ansi version, you can declare the API function like this:
[DllImport("user32.dll", CharSet = CharSet.Ansi, EntryPoint = "SendMessageA", ExactSpelling = true)]
private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
And the Unicode version like this:
[DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW", ExactSpelling = true)]
private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
One final note: this will not work as-is if the window belongs to another application, you'll crash it. The pointer values you pass are only valid in your own process, not in the C++ process. To work around that, you have to allocate memory in the target process so that the pointer is valid. That requires OpenProcess to get a handle to the process, VirtualAllocEx() to allocate memory in the target process, big enough to store the string, WriteProcessMemory to write the string. Now you can call SendMessage(), use a version that is declared with IntPtr for the wParam and lParam arguments, pass the value you got from VirtualAllocEx. Next use VirtualFreeEx() to release the memory and CloseHandle to clean up. Or keep the memory around for the next time if you do this often.
Quite a lot of P/Invoke to get wrong there. Not to mention security issues, WriteProcessMemory requires admin privileges, UAC elevation is required.
Passing the address of the string would involve unsafe code,
since Win32 API calls expect addresses (in a C/C++ native envrion). What windows message are you sending that requires a string in wParam or lParam?
We ended up using "WmCpyDta_d.dll" to deal with all that.

Categories

Resources