I am trying to get the symbol information from an address but I am getting error 87 (0x57) ERROR_INVALID_PARAMETER, I have also found the same question here https://social.msdn.microsoft.com/Forums/en-US/bd3e1c89-83c7-41c3-9d5d-a41069da2555/retrieving-symbol-information-by-address-in-c?forum=netfxtoolsdev but the answer does not work for me or at least it is not clear. There is some related questions in SO like: SymFromAddr using C# but it seems there is no clues to solve this.
Note: DbgHelpNative class is a wrapper of the DbgHelp.dll for C#.
This is my code:
static IntPtr GetThreadStartAddress(int threadId)
{
var hThread = OpenThread(ThreadAccess.QueryInformation, false, threadId);
if (hThread == IntPtr.Zero) {
throw new Win32Exception();
}
var buf = Marshal.AllocHGlobal(IntPtr.Size);
try {
var result = NtQueryInformationThread(hThread,ThreadInfoClass.ThreadQuerySetWin32StartAddress,buf, IntPtr.Size, IntPtr.Zero);
if (result != 0) {
throw new Win32Exception(string.Format("NtQueryInformationThread failed; NTSTATUS = {0:X8}", result));
}
IntPtr threadAddress = Marshal.ReadIntPtr(buf);
if (DbgHelpNative.SymInitialize(IntPtr.Zero, null, false)) {
int bufferSize = Marshal.SizeOf(typeof(DbgHelpNative.SYMBOL_INFO)) + ((2000 - 2) * 2);
var buffer = Marshal.AllocHGlobal(bufferSize);
DbgHelpNative.SYMBOL_INFO symbolInfo = new DbgHelpNative.SYMBOL_INFO();
ulong displacement = 0;
Marshal.PtrToStructure(buffer, typeof(DbgHelpNative.SYMBOL_INFO));
symbolInfo.SizeOfStruct = (uint)Marshal.SizeOf(typeof(DbgHelpNative.SYMBOL_INFO));
symbolInfo.MaxNameLen = 2000;
if (DbgHelpNative.SymFromAddr(hThread, (ulong)threadAddress, out displacement, ref symbolInfo)) {
MessageBox.Show("Success");
} else {
var error = Marshal.GetLastWin32Error();
MessageBox.Show(error.ToString());
}
}
return threadAddress;
}
finally {
CloseHandle(hThread);
Marshal.FreeHGlobal(buf);
}
}
The correct code is:
static IntPtr GetThreadStartAddress(IntPtr hProc, int threadId)
{
IntPtr hThread = IntPtr.Zero;
GCHandle handle = default(GCHandle);
try
{
hThread = OpenThread(ThreadAccess.QueryInformation, false, threadId);
if (hThread == IntPtr.Zero)
{
throw new Win32Exception("OpenThread failed");
}
var threadAddress = new IntPtr[1];
handle = GCHandle.Alloc(threadAddress, GCHandleType.Pinned);
var result = NtQueryInformationThread(hThread, ThreadInfoClass.ThreadQuerySetWin32StartAddress, handle.AddrOfPinnedObject(), IntPtr.Size, IntPtr.Zero);
if (result != 0)
{
throw new Win32Exception(string.Format("NtQueryInformationThread failed; NTSTATUS = {0:X8}", result));
}
DbgHelpNative.SymSetOptions(DbgHelpNative.Options.SYMOPT_UNDNAME | DbgHelpNative.Options.SYMOPT_DEFERRED_LOADS);
if (!DbgHelpNative.SymInitialize(hProc, null, true))
{
throw new Win32Exception("SymInitialize failed");
}
DbgHelpNative.SYMBOL_INFO symbolInfo = new DbgHelpNative.SYMBOL_INFO();
// Look at your DbgHelpNative.SYMBOL_INFO.Name definition, there should be a SizeConst.
// Change the 1024 to the SizeConst
// If using Unicode, change 1024 to 1024 * 2
// In the end SizeOfStruct should be 88, both at 32 and 64 bits, both Ansi and Unicode
symbolInfo.SizeOfStruct = (uint)Marshal.SizeOf(typeof(DbgHelpNative.SYMBOL_INFO)) - 1024;
// Change the 1024 to the SizeConst (both for Ansi and Unicode)
symbolInfo.MaxNameLen = 1024;
ulong displacement;
if (!DbgHelpNative.SymFromAddr(hProc, (ulong)threadAddress[0], out displacement, ref symbolInfo))
{
throw new Win32Exception("SymFromAddr failed");
}
Console.WriteLine("Success");
return threadAddress[0];
}
finally
{
if (hThread != IntPtr.Zero)
{
CloseHandle(hThread);
}
if (handle.IsAllocated)
{
handle.Free();
}
}
}
**you'll have to do a small correction in the symbolInfo.SizeOfStruct and symbolInfo.MaxNameLen lines!
Note that you need both a hProc (a handle to the process) AND a threadId
For current process you can use this:
var proc = Process.GetCurrentProcess();
int id = proc.Threads[0].Id;
IntPtr addr = GetThreadStartAddress(proc.Handle, id);
Note that, if you are using this for the DbgHelpNative, I consider any PInvoke that uses Ansi instead of Unicode to be defective. Another (small, non-) problem is that the SizeConst in that library is set to 1024, but in the MSDN examples they use MAX_SYM_NAME, that is 2000... I haven't ever seen a 2000 character symbol, but...)
Related
I am having trouble fixing a memory leak causes by SCardConnect function in winscard.dll library wrapper. Are there a way to fix the memory by winscard.dll
Summary: When the SCardConnect successfully returns 0, which means that there is a card presents on the reader, the memory goes off the roof.
Details:
I found out that the SCardEstablishContext also create memory leak so I tried to minimize the use of that function as much as possible.
I also tried to use SCardStatusChange function but it also creates memory leak and the logic is complicated.
Wrapper Card.cs:
[DllImport("winscard.dll")]
public static extern int SCardConnect(int hContext, string szReaderName, int dwShareMode, int dwPrefProtocol, ref int phCard, ref int ActiveProtocol);
Main Code:(omitted some global variables)
public Form1()
{
InitializeComponent();
do
{
if (this.Connect())
{
}
else
{
}
}
while (true);
}
public bool Connect()
{
if(string.IsNullOrEmpty(readername))
try
{
readername = this.GetReadersList()[0];
}
catch(Exception e) { }
retCode = Card.SCardConnect(hContext, readername, Card.SCARD_SHARE_SHARED,
Card.SCARD_PROTOCOL_T0 | Card.SCARD_PROTOCOL_T1, ref hCard, ref Protocol);
if (retCode != Card.SCARD_S_SUCCESS)
{
return false;
}
else
{
return true;
}
}
public List<string> GetReadersList()
{
string ReaderList = "" + Convert.ToChar(0);
int indx;
int pcchReaders = 0;
string rName = "";
List<string> lstReaders = new List<string>();
//Establish Context
retCode = Card.SCardEstablishContext(Card.SCARD_SCOPE_USER, 0, 0, ref hContext);
// 2. List PC/SC card readers installed in the system
retCode = Card.SCardListReaders(this.hContext, null, null, ref pcchReaders);
if (retCode != Card.SCARD_S_SUCCESS)
{
throw new Exception("Error SCardListReaders");
}
byte[] ReadersList = new byte[pcchReaders];
// Fill reader list
retCode = Card.SCardListReaders(this.hContext, null, ReadersList, ref pcchReaders);
if (retCode != Card.SCARD_S_SUCCESS)
{
throw new Exception("Error SCardListReaders");
}
rName = "";
indx = 0;
while (ReadersList[indx] != 0)
{
while (ReadersList[indx] != 0)
{
rName += (char)ReadersList[indx];
indx++;
}
lstReaders.Add(rName);
rName = "";
indx++;
}
return lstReaders;
}
Memory diagnostic:
enter image description here.
All the memory up-ramps are at the time of card holding on the reader.
PS: I have tried this in Window Form, Console, and Window Service platforms.
My C# program needs to call C++ functions located in an external DLL.
I found that it works fine under single thread, but error under multithread.
C++ code:
enum ProgramExitType:int {
ET_ERROR,
ET_SUCCEED,
ET_TLE,
ET_MLE
};
enum ProgramErrorType :int {
PE_UNKNOWN,
PE_INPUT,
PE_OUTPUT,
PE_ERRPUT,
PE_CREATEPROCESS,
PE_WAIT,
};
struct ProgramExitInfo {
ProgramExitType type;
ProgramErrorType err_type;
long long memory_usage;
int time;
unsigned int exit_code;
};
#define ___RR_COMBINE_(x,y) x##y
#define __RR_COMBINE(x,y) ___RR_COMBINE_(x,y)
#define UNIQUESYM __RR_COMBINE(__RRLibrary__unique_symbol_,__COUNTER__)
#define AUTOCLOSE(h) AutoClose UNIQUESYM(h)
#define AUTOCLOSEREF(h) AutoCloseRef UNIQUESYM(h)
class AutoClose {
HANDLE h;
public:
AutoClose(HANDLE h) :h(h) {}
~AutoClose() { CloseHandle(h);/* LOGW(L"AutoClose\n"); */ }
};
class AutoCloseRef {
HANDLE* h;
public:
AutoCloseRef(HANDLE* h) :h(h) {}
~AutoCloseRef() { CloseHandle(*h); /* LOGW(L"AutoCloseRef\n");*/ }
};
ProgramExitInfo RunProgram(PCWSTR path, PCWSTR param, PCWSTR input, PCWSTR output, PCWSTR errput, int time_limit, long long memory_limit) {
//MessageBox(0, L"RunProgram Start", L"", MB_ICONINFORMATION);
ProgramExitInfo ret;
ZeroMemory(&ret, sizeof(ProgramExitInfo));
HANDLE hin = INVALID_HANDLE_VALUE, hout = INVALID_HANDLE_VALUE, herr = INVALID_HANDLE_VALUE;
AUTOCLOSEREF(&hin); AUTOCLOSEREF(&hout); AUTOCLOSEREF(&herr);
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.lpSecurityDescriptor = NULL;
sa.bInheritHandle = TRUE;
if (input != NULL && *input != 0) {
//MessageBox(0, input, L"Load Input", MB_ICONINFORMATION);
hin = CreateFile(input, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hin == 0 || hin == INVALID_HANDLE_VALUE) {
ret.type = ET_ERROR;
ret.err_type = PE_INPUT;
return ret;
}
}
if (output != NULL && *output != 0) {
//MessageBox(0, input, L"Load Output", MB_ICONINFORMATION);
hout = CreateFile(output, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (hout == 0 || hout == INVALID_HANDLE_VALUE) {
ret.type = ET_ERROR;
ret.err_type = PE_OUTPUT;
return ret;
}
}
if (errput != NULL && *errput != 0) {
//MessageBox(0, input, L"Load Errput", MB_ICONINFORMATION);
herr = CreateFile(errput, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
if (herr == 0 || herr == INVALID_HANDLE_VALUE) {
ret.type = ET_ERROR;
ret.err_type = PE_ERRPUT;
return ret;
}
}
STARTUPINFO si = { sizeof(si) };
si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
si.wShowWindow = SW_HIDE;
si.hStdOutput = hout;
si.hStdError = herr;
si.hStdInput = hin;
PROCESS_INFORMATION pi = { 0 };
wchar_t* param_buff = 0;
if (param != NULL) {
param_buff = new wchar_t[lstrlenW(param) + 1];
lstrcpyW(param_buff, param);
}
BOOL b = CreateProcess(path, NULL,
NULL,
NULL,
TRUE,
NULL,
NULL,
NULL,
&si, &pi);
if (param_buff != 0)
delete[] param_buff;
AUTOCLOSE(pi.hProcess); AUTOCLOSE(pi.hThread);
if (b == FALSE) {
ret.type = ET_ERROR;
ret.err_type = PE_CREATEPROCESS;
return ret;
}
int ti = GetTickCount();
DWORD dw = WaitForSingleObject(pi.hProcess, time_limit);
ret.time = GetTickCount() - ti;
if (dw != WAIT_OBJECT_0)
TerminateProcess(pi.hProcess, -1);
GetExitCodeProcess(pi.hProcess, (LPDWORD)&ret.exit_code);
switch (dw) {
case WAIT_OBJECT_0: {
break;
}
case WAIT_TIMEOUT: {
ret.type = ET_TLE;
break;
}
default: {
ret.type = ET_ERROR;
ret.err_type = PE_WAIT;
return ret;
}
}
PROCESS_MEMORY_COUNTERS pmc = { 0 };
GetProcessMemoryInfo(pi.hProcess, &pmc, sizeof(pmc));
ret.memory_usage = (long long)pmc.PeakWorkingSetSize + pmc.PeakPagefileUsage;
if (ret.memory_usage > memory_limit) {
ret.type = ET_MLE;
return ret;
}
ret.type = ET_SUCCEED;
return ret;
}
C# code:
[DllImport("ProgramRunningHelper.dll", CallingConvention = CallingConvention.Cdecl)]
public static extern ProgramExitInfo RunProgram([MarshalAs(UnmanagedType.LPWStr)]string path, [MarshalAs(UnmanagedType.LPWStr)]string param, [MarshalAs(UnmanagedType.LPWStr)]string input, [MarshalAs(UnmanagedType.LPWStr)]string output, [MarshalAs(UnmanagedType.LPWStr)]string errput, int time_limit, long memory_limit);
I use RunProgram runs different .exe file with different in/output redirections in different thread.
But the function returns PE_INPUTorPE_OUTPUT which means it cannot create an in/output file.
I called FindLastError() and get 32 "Another program is using this file and the process cannot access it."
But if there is only one thread, no any errors.
So I think this may be because the parameters passed by different threads are confused( For example, there are two threads passing parameters 'a' and 'b' respectively, but CLR considers that both of them passed 'a'. ). Is it possible?
How can I solve it?
Any help would be much appreciated !
I'm trying to hook the winsock connect function and route the TCP connection through socks5 proxy /w auth.
This works if the socket is a blocking socket, but while using firefox ( nonblocking sockets ) I get a lot of 10035, 10022 winsock Errors.
How can i determine if it's a nonblocking / blocking socket?
I would really appreciate any hints or ideas to achieve the functionality to hook the wsock connect function and route tcp traffic through a socks5 server.
I can put the demo application on github if anybody wants to test it. ( Works with any version of firefox )
Edit1: https://github.com/duketwo/WinsockConnectHookSocks5/
( You have to edit the proxy information in WSockConnectHook/HookManager.cs and the path of firefox in Injector/MainForm.cs )
Edit2: It's easyhook which is causing the trouble, anything after the original function call doesn't work properly.
Edit3: Seems like i got it working with many flaws, in fact it is required differentiate between nonblocking sockets and blocking sockets. Any ideas how to achieve this?
Edit4: Windows doesn't offer any method to retrieve the blocking-attribute of a socket, so I might have to hook the ioctlsocket function to keep track of the blocking status of the sockets.
Thanks
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using EasyHook;
using System.IO;
using System.Windows.Forms;
namespace WSockConnectHook
{
public class WinSockConnectController : IDisposable, IHook
{
[UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet = CharSet.Ansi, SetLastError = true)]
private delegate int WinsockConnectDelegate(IntPtr s, IntPtr addr, int addrsize);
[DllImport("WS2_32.dll", SetLastError = true)]
public static extern int connect(IntPtr s, IntPtr addr, int addrsize);
[StructLayout(LayoutKind.Sequential, Size = 16)]
public struct sockaddr_in
{
public const int Size = 16;
public short sin_family;
public ushort sin_port;
public struct in_addr
{
public uint S_addr;
public struct _S_un_b
{
public byte s_b1, s_b2, s_b3, s_b4;
}
public _S_un_b S_un_b;
public struct _S_un_w
{
public ushort s_w1, s_w2;
}
public _S_un_w S_un_w;
}
public in_addr sin_addr;
}
[DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern int WSAGetLastError();
[DllImport("ws2_32.dll", CharSet = CharSet.Auto, SetLastError = true)]
static extern void WSASetLastError(int set);
[DllImport("Ws2_32.dll", CharSet = CharSet.Ansi)]
public static extern uint inet_addr(string cp);
[DllImport("Ws2_32.dll")]
public static extern ushort htons(ushort hostshort);
[DllImport("ws2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr socket(short af, short socket_type, int protocol);
[DllImport("Ws2_32.dll")]
public static extern int send(IntPtr s, IntPtr buf, int len, int flags);
[DllImport("Ws2_32.dll")]
public static extern int recv(IntPtr s, IntPtr buf, int len, int flags);
[DllImport("ws2_32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
public static extern int closesocket(IntPtr s);
[DllImport("Ws2_32.dll")]
public static extern ushort ntohs(ushort netshort);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern void SetLastError(int errorCode);
private string _name;
private LocalHook _hook;
public bool Error { get; set; }
public string Name { get; set; }
private string proxyIp, proxyPort, proxyUser, proxyPass;
public WinSockConnectController(IntPtr address, string proxyIp, string proxyPort, string proxyUser, string proxyPass)
{
this.Name = typeof(WinSockConnectController).Name;
this.proxyIp = proxyIp;
this.proxyPort = proxyPort;
this.proxyUser = proxyUser;
this.proxyPass = proxyPass;
try
{
_name = string.Format("WinsockHook_{0:X}", address.ToInt32());
_hook = LocalHook.Create(address, new WinsockConnectDelegate(WinsockConnectDetour), this);
_hook.ThreadACL.SetExclusiveACL(new Int32[] { 1 });
}
catch (Exception)
{
this.Error = true;
}
}
private object wSockLock = new object();
private int WinsockConnectDetour(IntPtr s, IntPtr addr, int addrsize)
{
lock (wSockLock)
{
// retrieve remote ip
sockaddr_in structure = (sockaddr_in)Marshal.PtrToStructure(addr, typeof(sockaddr_in));
string remoteIp = new System.Net.IPAddress(structure.sin_addr.S_addr).ToString();
ushort remotePort = ntohs(structure.sin_port);
HookManager.Log("Ip: " + remoteIp + " Port: " + remotePort.ToString() + " Addrsize: " + addrsize);
if (!proxyIp.Equals(""))
//if (!proxyIp.Equals(""))
{
// connect to socks5 server
SetAddr(s, addr, proxyIp, proxyPort);
var result = Connect(s, addr, addrsize);
if (result == -1)
return -1;
// send socks 5 request
IntPtr socksProtocolRequest = SetUpSocks5Request();
result = send(s, socksProtocolRequest, 4, 0);
if (result == -1)
return -1;
// retrieve server repsonse
var response = Recieve(s, 2);
if (response == IntPtr.Zero)
return -1;
byte[] recvBytes = new byte[2] { Marshal.ReadByte(response), Marshal.ReadByte(response, 1) };
if (recvBytes[1] == 255)
{
HookManager.Log("No authentication method was accepted by the proxy server");
return -1;
}
if (recvBytes[0] != 5)
{
HookManager.Log("No SOCKS5 proxy");
return -1;
}
// if auth request response, send authenicate request
if (recvBytes[1] == 2)
{
int length = 0;
var authenticateRequest = SetUpAuthenticateRequest(proxyUser, proxyPass, out length);
result = Send(s, authenticateRequest, length);
response = Recieve(s, 2);
if (response == IntPtr.Zero)
return -1;
recvBytes = new byte[2] { Marshal.ReadByte(response), Marshal.ReadByte(response, 1) };
if (recvBytes[1] != 0)
{
HookManager.Log("Proxy: incorrect username/password");
return -1;
}
}
// request bind with server
var bindRequest = SetUpBindWithRemoteHost(remoteIp, remotePort);
result = Send(s, bindRequest, 10);
if (result == -1)
return -1;
// response
response = Recieve(s, 10);
if (response == IntPtr.Zero)
return -1;
if (!VerifyBindResponse(response))
return -1;
// success
WSASetLastError(0);
SetLastError(0);
// clean memory
foreach (var ptr in allocatedMemory)
Marshal.FreeHGlobal(ptr);
allocatedMemory.Clear();
return 0;
}
else
{
var result = connect(s, addr, addrsize);
return result;
}
}
}
private int Connect(IntPtr socket, IntPtr addr, int addrsize)
{
var result = connect(socket, addr, addrsize);
while (result == -1)
{
var errorcode = WSAGetLastError();
HookManager.Log("Error: " + errorcode);
if (errorcode == 10056)
break;
if (errorcode == 10037)
break;
if (errorcode != 10035 && errorcode != 10037)
return -1;
//flag = 1;
result = connect(socket, addr, addrsize);
}
return result;
}
private int Send(IntPtr socket, IntPtr buf, int len)
{
var result = send(socket, buf, len, 0);
while (result == -1)
{
var errorcode = WSAGetLastError();
HookManager.Log("Error: " + errorcode);
if (errorcode == 10056)
break;
if (errorcode == 10037)
break;
if (errorcode != 10035 && errorcode != 10037)
return -1;
result = send(socket, buf, 4, 0);
}
return result;
}
private List<IntPtr> allocatedMemory = new List<IntPtr>();
private IntPtr Recieve(IntPtr socket, int len)
{
var buffer = Marshal.AllocHGlobal(len);
allocatedMemory.Add(buffer);
var result = recv(socket, buffer, len, 0);
if (result == -1)
{
HookManager.Log("Error2: " + WSAGetLastError());
return IntPtr.Zero;
}
return buffer;
}
private IntPtr RecieveAuth(IntPtr socket, int len)
{
var buffer = Marshal.AllocHGlobal(len);
allocatedMemory.Add(buffer);
var result = recv(socket, buffer, len, 0);
if (result == -1)
{
HookManager.Log("Error3: " + WSAGetLastError());
return IntPtr.Zero; ;
}
if (result == 0)
return buffer;
if (result != 2)
{
HookManager.Log("Proxy: Bad response from server");
return IntPtr.Zero;
}
return buffer;
}
private IntPtr RecieveBind(IntPtr socket, int len)
{
var buffer = Marshal.AllocHGlobal(len);
allocatedMemory.Add(buffer);
var result = recv(socket, buffer, len, 0);
if (result == -1)
{
HookManager.Log("Error3: " + WSAGetLastError());
return IntPtr.Zero; ;
}
if (result == 0)
return buffer;
if (result != 10)
{
HookManager.Log("Proxy: Bad response from server");
return IntPtr.Zero;
}
return buffer;
}
private void SetAddr(IntPtr socket, IntPtr addr, string ip, string port)
{
sockaddr_in structure = (sockaddr_in)Marshal.PtrToStructure(addr, typeof(sockaddr_in));
string originalip = new System.Net.IPAddress(structure.sin_addr.S_addr).ToString();
ushort originalport = ntohs(structure.sin_port);
structure.sin_addr.S_addr = inet_addr(ip);
structure.sin_port = htons(Convert.ToUInt16(port));
Marshal.StructureToPtr(structure, addr, true);
structure = (sockaddr_in)Marshal.PtrToStructure(addr, typeof(sockaddr_in));
}
private IntPtr SetUpSocks5Request()
{
var initialRequest = Marshal.AllocHGlobal(4);
Marshal.WriteByte(initialRequest, Convert.ToByte(5));
Marshal.WriteByte(initialRequest + 1, Convert.ToByte(2));
Marshal.WriteByte(initialRequest + 2, Convert.ToByte(0));
Marshal.WriteByte(initialRequest + 3, Convert.ToByte(2));
return initialRequest;
}
private IntPtr SetUpAuthenticateRequest(string username, string password, out int index)
{
index = 0;
var size = 3 + Encoding.Default.GetBytes(username).Length + Encoding.Default.GetBytes(password).Length;
var authenticateBuffer = Marshal.AllocHGlobal(size);
Marshal.WriteByte(authenticateBuffer + index++, Convert.ToByte(1));
Marshal.WriteByte(authenticateBuffer + index++, Convert.ToByte(username.Length));
byte[] rawBytes;
if (username.Length > 0)
{
rawBytes = Encoding.Default.GetBytes(username);
for (int i = 0; i < rawBytes.Length; i++)
{
Marshal.WriteByte(authenticateBuffer + index++, rawBytes[i]);
}
}
Marshal.WriteByte(authenticateBuffer + index++, Convert.ToByte(password.Length));
if (password.Length > 0)
{
rawBytes = Encoding.Default.GetBytes(password);
for (int i = 0; i < rawBytes.Length; i++)
{
Marshal.WriteByte(authenticateBuffer + index++, rawBytes[i]);
}
}
return authenticateBuffer;
}
private IntPtr SetUpBindWithRemoteHost(string eveIP, ushort evePort)
{
var bindWithEveBuffer = Marshal.AllocHGlobal(10);
var iplist = eveIP.Split('.').ToList();
byte[] portbyte = BitConverter.GetBytes(evePort).Reverse().ToArray();
byte[] newbyte = new byte[2];
int indexy = 0;
foreach (var byty in portbyte)
{
newbyte[indexy] = byty;
indexy++;
}
// bind with remote server
Marshal.WriteByte(bindWithEveBuffer, Convert.ToByte(5));
Marshal.WriteByte(bindWithEveBuffer + 1, Convert.ToByte(1));
Marshal.WriteByte(bindWithEveBuffer + 2, Convert.ToByte(0));
Marshal.WriteByte(bindWithEveBuffer + 3, Convert.ToByte(1));
Marshal.WriteByte(bindWithEveBuffer + 4, Convert.ToByte(iplist[0]));
Marshal.WriteByte(bindWithEveBuffer + 5, Convert.ToByte(iplist[1]));
Marshal.WriteByte(bindWithEveBuffer + 6, Convert.ToByte(iplist[2]));
Marshal.WriteByte(bindWithEveBuffer + 7, Convert.ToByte(iplist[3]));
Marshal.WriteByte(bindWithEveBuffer + 8, newbyte[0]);
Marshal.WriteByte(bindWithEveBuffer + 9, newbyte[1]);
return bindWithEveBuffer;
}
private bool VerifyBindResponse(IntPtr buffer)
{
var recvBytes = new byte[10] { Marshal.ReadByte(buffer), Marshal.ReadByte(buffer, 1), Marshal.ReadByte(buffer, 2), Marshal.ReadByte(buffer, 3), Marshal.ReadByte(buffer, 4), Marshal.ReadByte(buffer, 5), Marshal.ReadByte(buffer, 6), Marshal.ReadByte(buffer, 7), Marshal.ReadByte(buffer, 8), Marshal.ReadByte(buffer, 9) };
if (recvBytes[1] != 0)
{
if (recvBytes[1] == 1)
HookManager.Log("General failure");
if (recvBytes[1] == 2)
HookManager.Log("connection not allowed by ruleset");
if (recvBytes[1] == 3)
HookManager.Log("network unreachable");
if (recvBytes[1] == 4)
HookManager.Log("host unreachable");
if (recvBytes[1] == 5)
HookManager.Log("connection refused by destination host");
if (recvBytes[1] == 6)
HookManager.Log("TTL expired");
if (recvBytes[1] == 7)
HookManager.Log("command not supported / protocol error");
if (recvBytes[1] == 8)
HookManager.Log("address type not supported");
HookManager.Log("Proxy: Connection error binding eve server");
return false;
}
return true;
}
public void Dispose()
{
if (_hook == null)
return;
_hook.Dispose();
_hook = null;
}
}
}
I'm trying to find the vendor id and the product id of a USB card. For this purpose, I use setupapi.dll. When I closed my program I have 0x80131623 (2146232797) appears. I don't know how I can fix it.
My code is :
result = HidD_GetHidGuid(ref HidGuid);
DeviceInfoSet = SetupDiGetClassDevs(ref HidGuid, IntPtr.Zero, IntPtr.Zero, 18);
do
{
SP_DEVICE_INTERFACE_DATA MyDeviceInterfaceData = new SP_DEVICE_INTERFACE_DATA();
MyDeviceInterfaceData.cbSize = 28;
result = SetupDiEnumDeviceInterfaces(DeviceInfoSet, IntPtr.Zero, ref HidGuid, MemberIndex, ref MyDeviceInterfaceData);
//int lastError = Marshal.GetLastWin32Error();
if (result != 0)
{
//SP_DEVINFO_DATA MyDeviceInfoData = new SP_DEVINFO_DATA();
//MyDeviceInfoData.cbSize = Marshal.SizeOf(MyDeviceInfoData);
//Premier appel pour obtenir la taille du buffer
result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, ref MyDeviceInterfaceData, IntPtr.Zero, 0, out neededSize, IntPtr.Zero);
//int lastError = Marshal.GetLastWin32Error();
int requiredSize = (int)neededSize;
SP_DEVICE_INTERFACE_DETAIL_DATA MyDeviceInterfaceDetailData = new SP_DEVICE_INTERFACE_DETAIL_DATA();
if (IntPtr.Size == 8) // for 64 bit operating systems
MyDeviceInterfaceDetailData.cbSize = 8;
else
MyDeviceInterfaceDetailData.cbSize = 4 + Marshal.SystemDefaultCharSize; // for 32 bit systems
IntPtr detailDataBuffer = Marshal.AllocHGlobal(requiredSize);
Marshal.StructureToPtr(MyDeviceInterfaceDetailData, detailDataBuffer, true);
result = SetupDiGetDeviceInterfaceDetail(DeviceInfoSet, ref MyDeviceInterfaceData, detailDataBuffer, requiredSize, out neededSize, IntPtr.Zero);
int lastError = Marshal.GetLastWin32Error();
//string instanceID = Marshal.PtrToStringAuto(detailDataBuffer);
Marshal.PtrToStructure(detailDataBuffer, MyDeviceInterfaceDetailData);
if (MyDeviceInterfaceDetailData.DevicePath.IndexOf("vid_04fa&pid_9123") != -1)
{
Marshal.FreeHGlobal(detailDataBuffer);
Marshal.FreeHGlobal(DeviceInfoSet);
return true;
}
MemberIndex++;
Marshal.FreeHGlobal(detailDataBuffer);
}
else
{
//int lastError = Marshal.GetLastWin32Error();
}
if (MemberIndex>=16) { lastDevice = true; }
} while (lastDevice == false);
Marshal.FreeHGlobal(DeviceInfoSet);
return false;
}
I think the problem is caused by Marshaling.
Here's some C# source code which implements an unmanaged DLL (advapi32).
public void AddPrivileges(string account, string privilege)
{
IntPtr pSid = GetSIDInformation(account);
LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1];
privileges[0] = InitLsaString(privilege);
uint ret = Win32Sec.LsaAddAccountRights(lsaHandle, pSid, privileges, 1);
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
int error = Win32Sec.LsaNtStatusToWinError((int)ret);
throw new Win32Exception(error);
}
The variable values at runtime are as follows:
privilege: "SeServiceLogonRight"
account: "named"
ret: 3221225485 (STATUS_INVALID_PARAMETER)
error: 87
When caught, the message within the Win32Exception is: "The parameter is incorrect"
The code is running on Windows Web Server 2008. I can verify that the account does exist, and this code works fine on another server... I'm not sure if this could have been caused by Windows 2008 SP2. I'm thinking that I've forgotten to install something, but I can't think what...
The code is from: http://weblogs.asp.net/avnerk/archive/2007/05/10/granting-user-rights-in-c.aspx
Following the provided link through to the code at http://www.hightechtalks.com/csharp/lsa-functions-276626.html
IntPtr GetSIDInformation(string account)
{
LSA_UNICODE_STRING[] names = new LSA_UNICODE_STRING[1];
LSA_TRANSLATED_SID2 lts;
IntPtr tsids = IntPtr.Zero;
IntPtr tdom = IntPtr.Zero;
names[0] = InitLsaString(account);
lts.Sid = IntPtr.Zero;
Console.WriteLine("String account: {0}", names[0].Length);
int ret = Win32Sec.LsaLookupNames2(lsaHandle, 0, 1, names, ref tdom, ref tsids);
if (ret != 0)
{
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError(ret));
}
lts = (LSA_TRANSLATED_SID2) Marshal.PtrToStructure(tsids,
typeof(LSA_TRANSLATED_SID2));
Win32Sec.LsaFreeMemory(tsids);
Win32Sec.LsaFreeMemory(tdom);
return lts.Sid;
}
lts (an LSA_TRANSLATED_SID2 struct) contains a pointer that points at memory that is freed by the call to Win32Sec.LsaFreeMemory. Using the pointer after the memory is freed is bad practice and will have unpredictable results -- it might even "work".
Tweaking the code at the link by using the SecurityIdentifier class (.Net 2 and above) along a little cleanup of unneeded code avoids the memory problem.
using System;
namespace Willys.LsaSecurity
{
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Principal;
using LSA_HANDLE = IntPtr;
[StructLayout(LayoutKind.Sequential)]
struct LSA_OBJECT_ATTRIBUTES
{
internal int Length;
internal IntPtr RootDirectory;
internal IntPtr ObjectName;
internal int Attributes;
internal IntPtr SecurityDescriptor;
internal IntPtr SecurityQualityOfService;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct LSA_UNICODE_STRING
{
internal ushort Length;
internal ushort MaximumLength;
[MarshalAs(UnmanagedType.LPWStr)]
internal string Buffer;
}
sealed class Win32Sec
{
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
internal static extern uint LsaOpenPolicy(
LSA_UNICODE_STRING[] SystemName,
ref LSA_OBJECT_ATTRIBUTES ObjectAttributes,
int AccessMask,
out IntPtr PolicyHandle
);
[DllImport("advapi32", CharSet = CharSet.Unicode, SetLastError = true), SuppressUnmanagedCodeSecurityAttribute]
internal static extern uint LsaAddAccountRights(
LSA_HANDLE PolicyHandle,
IntPtr pSID,
LSA_UNICODE_STRING[] UserRights,
int CountOfRights
);
[DllImport("advapi32")]
internal static extern int LsaNtStatusToWinError(int NTSTATUS);
[DllImport("advapi32")]
internal static extern int LsaClose(IntPtr PolicyHandle);
}
sealed class Sid : IDisposable
{
public IntPtr pSid = IntPtr.Zero;
public SecurityIdentifier sid = null;
public Sid(string account)
{
sid = (SecurityIdentifier) (new NTAccount(account)).Translate(typeof(SecurityIdentifier));
Byte[] buffer = new Byte[sid.BinaryLength];
sid.GetBinaryForm(buffer, 0);
pSid = Marshal.AllocHGlobal(sid.BinaryLength);
Marshal.Copy(buffer, 0, pSid, sid.BinaryLength);
}
public void Dispose()
{
if (pSid != IntPtr.Zero)
{
Marshal.FreeHGlobal(pSid);
pSid = IntPtr.Zero;
}
GC.SuppressFinalize(this);
}
~Sid()
{
Dispose();
}
}
public sealed class LsaWrapper : IDisposable
{
enum Access : int
{
POLICY_READ = 0x20006,
POLICY_ALL_ACCESS = 0x00F0FFF,
POLICY_EXECUTE = 0X20801,
POLICY_WRITE = 0X207F8
}
const uint STATUS_ACCESS_DENIED = 0xc0000022;
const uint STATUS_INSUFFICIENT_RESOURCES = 0xc000009a;
const uint STATUS_NO_MEMORY = 0xc0000017;
IntPtr lsaHandle;
public LsaWrapper()
: this(null)
{ }
// // local system if systemName is null
public LsaWrapper(string systemName)
{
LSA_OBJECT_ATTRIBUTES lsaAttr;
lsaAttr.RootDirectory = IntPtr.Zero;
lsaAttr.ObjectName = IntPtr.Zero;
lsaAttr.Attributes = 0;
lsaAttr.SecurityDescriptor = IntPtr.Zero;
lsaAttr.SecurityQualityOfService = IntPtr.Zero;
lsaAttr.Length = Marshal.SizeOf(typeof(LSA_OBJECT_ATTRIBUTES));
lsaHandle = IntPtr.Zero;
LSA_UNICODE_STRING[] system = null;
if (systemName != null)
{
system = new LSA_UNICODE_STRING[1];
system[0] = InitLsaString(systemName);
}
uint ret = Win32Sec.LsaOpenPolicy(system, ref lsaAttr,
(int) Access.POLICY_ALL_ACCESS, out lsaHandle);
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int) ret));
}
public void AddPrivileges(string account, string privilege)
{
uint ret = 0;
using (Sid sid = new Sid(account))
{
LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1];
privileges[0] = InitLsaString(privilege);
ret = Win32Sec.LsaAddAccountRights(lsaHandle, sid.pSid, privileges, 1);
}
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int) ret));
}
public void Dispose()
{
if (lsaHandle != IntPtr.Zero)
{
Win32Sec.LsaClose(lsaHandle);
lsaHandle = IntPtr.Zero;
}
GC.SuppressFinalize(this);
}
~LsaWrapper()
{
Dispose();
}
// helper functions
static LSA_UNICODE_STRING InitLsaString(string s)
{
// Unicode strings max. 32KB
if (s.Length > 0x7ffe)
throw new ArgumentException("String too long");
LSA_UNICODE_STRING lus = new LSA_UNICODE_STRING();
lus.Buffer = s;
lus.Length = (ushort) (s.Length * sizeof(char));
lus.MaximumLength = (ushort) (lus.Length + sizeof(char));
return lus;
}
}
}
I couldn't get this to work, so instead I used the source code from the CodeProject project, LSA Functions - Privileges and Impersonation which works nicely.
lts.Sid is freed before returning in GetSIDInformation.
Moving the codes of GetSIDInformation out. It worked fine for .Net 4.5.
public void AddPrivileges(string account, string privilege)
{
LSA_UNICODE_STRING[] names = new LSA_UNICODE_STRING[1];
LSA_TRANSLATED_SID2 lts;
IntPtr tsids = IntPtr.Zero;
IntPtr tdom = IntPtr.Zero;
names[0] = InitLsaString(account);
lts.Sid = IntPtr.Zero;
Console.WriteLine("String account: {0}", names[0].Length);
int ret1 = Win32Sec.LsaLookupNames2(lsaHandle, 0, 1, names, ref tdom, ref tsids);
if (ret1 != 0)
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError(ret1));
lts = (LSA_TRANSLATED_SID2)Marshal.PtrToStructure(tsids, typeof(LSA_TRANSLATED_SID2));
IntPtr pSid = lts.Sid;
//IntPtr pSid = GetSIDInformation(account);
LSA_UNICODE_STRING[] privileges = new LSA_UNICODE_STRING[1];
privileges[0] = InitLsaString(privilege);
uint ret = Win32Sec.LsaAddAccountRights(lsaHandle, pSid, privileges, 1);
Win32Sec.LsaFreeMemory(tsids);
Win32Sec.LsaFreeMemory(tdom);
if (ret == 0)
return;
if (ret == STATUS_ACCESS_DENIED)
{
throw new UnauthorizedAccessException();
}
if ((ret == STATUS_INSUFFICIENT_RESOURCES) || (ret == STATUS_NO_MEMORY))
{
throw new OutOfMemoryException();
}
throw new Win32Exception(Win32Sec.LsaNtStatusToWinError((int)ret));
}
I came across the same error when calling LsaAddAccountRights and I found out I was using sizeof(char) instead of sizeof(wchar) when initializing LSA_UNICODE_STRING.
I checked the code at http://www.codeproject.com/KB/cs/lsadotnet.aspx and found similar issue:
static LSA_UNICODE_STRING InitLsaString(string s)
{
// Unicode strings max. 32KB
if (s.Length > 0x7ffe)
throw new ArgumentException("String too long");
LSA_UNICODE_STRING lus = new LSA_UNICODE_STRING();
lus.Buffer = s;
lus.Length = (ushort)(s.Length * sizeof(char));
lus.MaximumLength = (ushort)(lus.Length + sizeof(char));
return lus;
}
Should be something like:
lus.Length = (ushort)(s.Length * UnicodeEncoding.CharSize);
lus.MaximumLength = (ushort)(lus.Length + UnicodeEncoding.CharSize);
I was able to get this working on one box but then on another box it failed with the error you received:
System.ComponentModel.Win32Exception: The parameter is incorrect
I discovered that the root cause of this issue for me had to do with architecture of the process that was running the code. I was running a msbuild 32-bit process which worked fine, but when I used the 64-bit msbuild.exe to run this it failed with this error.
I hope that helps!
Regards,
Brandon
I found this problem is related to .NET 4.0. Downgrade your project to .NET 3.5 and it will work.