父子进程和匿名管道通信的问题

woyaomoney 2007-01-09 03:31:47
父进程使用createprocessAsUser启动c:\windows\system32\tracert.exe,冲定向子进程的标准输出到管道,但是为什么父进程里得不到子进程的输出呢?


using System;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Security.Permissions;
using System.Text;
using System.Threading;
using System.IO;
using Microsoft.Win32.SafeHandles;

//using System.Windows.Forms;

[assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, UnmanagedCode = true)]
[assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name = "FullTrust")]
public class ImpersonationDemo
{
[DllImport("advapi32.dll", SetLastError = true)]
public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword,
int dwLogonType, int dwLogonProvider, ref IntPtr phToken);

//[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
//private unsafe static extern int FormatMessage(int dwFlags, ref IntPtr lpSource,
// int dwMessageId, int dwLanguageId, ref String lpBuffer, int nSize, IntPtr* Arguments);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public extern static bool CloseHandle(IntPtr handle);

[DllImport("advapi32.dll", EntryPoint = "CreateProcessAsUser", SetLastError = true, CharSet = CharSet.Ansi, CallingConvention = CallingConvention.StdCall)]
public extern static bool CreateProcessAsUser(IntPtr hToken, String lpApplicationName, String lpCommandLine, ref SECURITY_ATTRIBUTES lpProcessAttributes,
ref SECURITY_ATTRIBUTES lpThreadAttributes, bool bInheritHandle, int dwCreationFlags, IntPtr lpEnvironment,
String lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation);

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public extern static bool DuplicateToken(IntPtr ExistingTokenHandle,
int SECURITY_IMPERSONATION_LEVEL, ref IntPtr DuplicateTokenHandle);

[DllImport("advapi32.dll", EntryPoint = "DuplicateTokenEx")]
public extern static bool DuplicateTokenEx(IntPtr ExistingTokenHandle, uint dwDesiredAccess,
ref SECURITY_ATTRIBUTES lpThreadAttributes, int TokenType,
int ImpersonationLevel, ref IntPtr DuplicateTokenHandle);

[DllImport("Kernel32.dll", SetLastError = true)]
public static extern bool CreatePipe(out IntPtr readHandle, out IntPtr writeHandle, ref SECURITY_ATTRIBUTES sa, int nSize);

[DllImport("kernel32", SetLastError = true, ExactSpelling = true)]
public static extern Int32 WaitForSingleObject(IntPtr handle, uint milliseconds);

[DllImport("Kernel32.dll", SetLastError = true)]
public static extern unsafe Int32 PeekNamedPipe(
IntPtr hNamedPipe,
void* lpBuffer,
uint nBufferSize,
int* lpBytesRead,
int* lpTotalBytesAvail,
int* lpBytesLeftThisMessage
);

[DllImport("kernel32", SetLastError = true)]
static extern unsafe bool ReadFile(
IntPtr hFile, // handle to file
void* pBuffer, // data buffer
int NumberOfBytesToRead, // number of bytes to read
int* pNumberOfBytesRead, // number of bytes read
int Overlapped // overlapped buffer
);

[DllImport("kernel32", SetLastError = true)]
static extern unsafe bool WriteFile(
IntPtr hFile, // handle to file
void* pBuffer, // data buffer
int nNumberOfBytesToWrite, // number of bytes to read
int* lpNumberOfBytesWritten, // number of bytes read
int Overlapped // overlapped buffer
);

[DllImport("Kernel32.dll", SetLastError = true)]
static extern IntPtr GetStdHandle(
int nStdHandle
);

[DllImport("Kernel32.dll", SetLastError = true)]
static extern bool SetStdHandle(
int nStdHandle,
IntPtr hHandle
);


[DllImport("Kernel32.dll", SetLastError = true)]
static extern void GetStartupInfo(
ref STARTUPINFO lpStartupInfo
);


public struct SECURITY_ATTRIBUTES
{
public long nLength;
public IntPtr lpSecurityDescriptor;
public bool bInheritHandle;
}

public struct PROCESS_INFORMATION
{
public IntPtr hProcess;
public IntPtr hThread;
public long dwProcessId;
public long dwThreadId;
}

public struct STARTUPINFO
{
public long cb; //Size of the structure, in bytes.
public string lpReserved; //Reserved. Set this member to NULL before passing the structure to CreateProcess.
public string lpDesktop; //Pointer to a null-terminated string that specifies either the name of the desktop, or the name of both the desktop and window station for this process. A backslash in the string indicates that the string includes both the desktop and window station names.
public string lpTitle; //For console processes, this is the title displayed in the title bar if a new console window is created. If NULL, the name of the executable file is used as the window title instead. This parameter must be NULL for GUI or console processes that do not create a new console window.
public long dwX; //
public long dwY;
public long dwXSize;
public long dwYSize;
public long dwXCountChars;
public long dwYCountChars;
public long dwFillAttribute;
public long dwFlags;
public long wShowWindow;
public long cbReserved2;
public byte lpReserved2;
public IntPtr hStdInput;
public IntPtr hStdOutput;
public IntPtr hStdError;
}



public static uint INFINITE = 0xFFFFFFFF;

const uint STARTF_USESHOWWINDOW=0x00000001;
const uint STARTF_USESIZE=0x00000002;
const uint STARTF_USEPOSITION=0x00000004;
const uint STARTF_USECOUNTCHARS=0x00000008;
const uint STARTF_USEFILLATTRIBUTE= 0x00000010;
const uint STARTF_RUNFULLSCREEN=0x00000020 ; // ignored for non-x86 platforms
const uint STARTF_FORCEONFEEDBACK=0x00000040;
const uint STARTF_FORCEOFFFEEDBACK=0x00000080;
const uint STARTF_USESTDHANDLES=0x00000100;

const uint SW_HIDE=0;
const uint SW_SHOWNORMAL=1;
const uint SW_NORMAL=1;
const uint SW_SHOWMINIMIZED=2;
const uint SW_SHOWMAXIMIZED=3;
const uint SW_MAXIMIZE=3;
const uint SW_SHOWNOACTIVATE=4;
const uint SW_SHOW=5;
const uint SW_MINIMIZE=6;
const uint SW_SHOWMINNOACTIVE=7;
const uint SW_SHOWNA=8;
const uint SW_RESTORE=9;
const uint SW_SHOWDEFAULT=10;
const uint SW_FORCEMINIMIZE=11;
const uint SW_MAX = 11;

const int STD_INPUT_HANDLE=-10;
const int STD_OUTPUT_HANDLE=-11;
const int STD_ERROR_HANDLE = -12;


public static unsafe int Read(IntPtr handle, byte[] buffer, int index, int count)
{
int n = 0;
fixed (byte* p = buffer)
{
if (!ReadFile(handle, p + index, count, &n, 0))
return 0;
}
return n;
}
...全文
726 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
woyaomoney 2007-01-10
  • 打赏
  • 举报
回复
up
heartdevil 2007-01-09
  • 打赏
  • 举报
回复
顶下
wshuangminlg 2007-01-09
  • 打赏
  • 举报
回复
帮LZ顶
woyaomoney 2007-01-09
  • 打赏
  • 举报
回复
up
GXY2005 2007-01-09
  • 打赏
  • 举报
回复
我看错了,高人总是让我混淆,因为他们都有个相同的名字:高人
woyaomoney 2007-01-09
  • 打赏
  • 举报
回复
Knight94(愚翁) ( )

不是在一个user下面的,不过我试了用同一个account也不行
GXY2005 2007-01-09
  • 打赏
  • 举报
回复

Knight94(愚翁) 高手,刚才看到有个帖子给你100分让你去接分!真的
Knight94 2007-01-09
  • 打赏
  • 举报
回复
父进程和子进程是否在同一个用户下运行
cherry_j 2007-01-09
  • 打赏
  • 举报
回复
好长,头好晕

帮你顶下
woyaomoney 2007-01-09
  • 打赏
  • 举报
回复
sorry,太长了,还有一半



// Test harness.
// If you incorporate this code into a DLL, be sure to demand FullTrust.
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public static void Main(string[] args)
{
IntPtr tokenHandle = new IntPtr(0);
IntPtr dupeTokenHandle = new IntPtr(0);
IntPtr writeHandle = new IntPtr(0);
IntPtr readHandle = new IntPtr(0);


try
{
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.bInheritHandle = true ;
sa.lpSecurityDescriptor = (IntPtr)0;
sa.nLength = System.Runtime.InteropServices.Marshal.SizeOf(sa);


string userName, domainName;
// Get the user token for the specified user, domain, and password using the
// unmanaged LogonUser method.
// The local machine name can be used for the domain name to impersonate a user on this machine.

Console.Write("Enter the name of the domain on which to log on: ");
domainName = Console.ReadLine();

Console.Write("Enter the login of a user on {0} that you wish to impersonate: ", domainName);
userName = Console.ReadLine();

Console.Write("Enter the password for {0}: ", userName);

const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;

tokenHandle = IntPtr.Zero;

// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser(userName, domainName, Console.ReadLine(),
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);


if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("LogonUser failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

const uint GENERIC_ALL = 0x10000000;
const int SecurityImpersonation = 2;
const int TokenType = 1;
Console.WriteLine("LogonUser called.");

if (!DuplicateTokenEx(tokenHandle, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref dupeTokenHandle))
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("DuplicateTokenEx failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}


Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
Console.WriteLine("Value of Windows NT token: " + tokenHandle);



if (!CreatePipe(out readHandle, out writeHandle, ref sa, 0))
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("CreatePipe failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

IntPtr std = GetStdHandle(STD_OUTPUT_HANDLE);
SetStdHandle(STD_OUTPUT_HANDLE, writeHandle);

PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

STARTUPINFO si = new STARTUPINFO();
//si.lpDesktop = string.Empty;
//si.cb = System.Runtime.InteropServices.Marshal.SizeOf(si);
//si.dwFlags = STARTF_USESTDHANDLES ;
//si.wShowWindow = SW_HIDE;
////si.hStdInput = writeHandle;
//si.hStdOutput = writeHandle;

GetStartupInfo(ref si);
si.dwFlags= STARTF_USESTDHANDLES ;
si.hStdOutput = writeHandle;

bool r = CreateProcessAsUser(dupeTokenHandle, null, @"c:\windows\system32\tracert.exe", ref sa, ref sa,true, 0, (IntPtr)0, @"c:\", ref si, out pi);
if (r)
{
if (1==WaitForSingleObject(pi.hProcess, INFINITE))
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("WaitForSingleObject failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

if (!CloseHandle(pi.hProcess))
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("CloseHandle failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

if (!CloseHandle(pi.hThread))
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("CloseHandle failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

}
else
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("CreateProcessAsUser failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

SetStdHandle(STD_OUTPUT_HANDLE, std);

//CloseHandle(writeHandle);

System.Text.ASCIIEncoding Encoding = new System.Text.ASCIIEncoding();
string hello="hello";
byte[] wbuffer=Encoding.GetBytes(hello);
unsafe
{
//int count = 5;
//int n;
//fixed (byte* p = wbuffer)
//{
// WriteFile(writeHandle ,p , count, &n, 0);
//}
byte[] buffer = new byte[40];
int read, total, left;
fixed (byte* p = buffer)
{
if (PeekNamedPipe(readHandle, p, (uint)buffer.Length, &read, &total, &left) > 0)
{
if (total > 0)
{
int bytesRead;
do
{
bytesRead = Read(readHandle, buffer, 0, buffer.Length);
string content = Encoding.GetString(buffer, 0, bytesRead);
Console.Write("{0}", content);
}
while (bytesRead > 0);
}
}
else
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("PeekNamedPipe failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);

}
}
}

// Free the tokens.

if (readHandle != IntPtr.Zero)
CloseHandle(readHandle);

if (writeHandle != IntPtr.Zero)
CloseHandle(writeHandle);

if (tokenHandle != IntPtr.Zero)
CloseHandle(tokenHandle);

Console.Read();


}
catch (Exception ex)
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("CreateProcessAsUser failed with error code : {0}", ret);
Console.WriteLine(new System.ComponentModel.Win32Exception(ret));

Console.WriteLine("Exception occurred. " + ex.Message);
Console.Read();
}

}
}


woyaomoney 2007-01-09
  • 打赏
  • 举报
回复
sorry,太长了,还有一半



// Test harness.
// If you incorporate this code into a DLL, be sure to demand FullTrust.
[PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")]
public static void Main(string[] args)
{
IntPtr tokenHandle = new IntPtr(0);
IntPtr dupeTokenHandle = new IntPtr(0);
IntPtr writeHandle = new IntPtr(0);
IntPtr readHandle = new IntPtr(0);


try
{
SECURITY_ATTRIBUTES sa = new SECURITY_ATTRIBUTES();
sa.bInheritHandle = true ;
sa.lpSecurityDescriptor = (IntPtr)0;
sa.nLength = System.Runtime.InteropServices.Marshal.SizeOf(sa);


string userName, domainName;
// Get the user token for the specified user, domain, and password using the
// unmanaged LogonUser method.
// The local machine name can be used for the domain name to impersonate a user on this machine.

Console.Write("Enter the name of the domain on which to log on: ");
domainName = Console.ReadLine();

Console.Write("Enter the login of a user on {0} that you wish to impersonate: ", domainName);
userName = Console.ReadLine();

Console.Write("Enter the password for {0}: ", userName);

const int LOGON32_PROVIDER_DEFAULT = 0;
//This parameter causes LogonUser to create a primary token.
const int LOGON32_LOGON_INTERACTIVE = 2;

tokenHandle = IntPtr.Zero;

// Call LogonUser to obtain a handle to an access token.
bool returnValue = LogonUser(userName, domainName, Console.ReadLine(),
LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT,
ref tokenHandle);


if (false == returnValue)
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("LogonUser failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

const uint GENERIC_ALL = 0x10000000;
const int SecurityImpersonation = 2;
const int TokenType = 1;
Console.WriteLine("LogonUser called.");

if (!DuplicateTokenEx(tokenHandle, GENERIC_ALL, ref sa, SecurityImpersonation, TokenType, ref dupeTokenHandle))
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("DuplicateTokenEx failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}


Console.WriteLine("Did LogonUser Succeed? " + (returnValue ? "Yes" : "No"));
Console.WriteLine("Value of Windows NT token: " + tokenHandle);



if (!CreatePipe(out readHandle, out writeHandle, ref sa, 0))
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("CreatePipe failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

IntPtr std = GetStdHandle(STD_OUTPUT_HANDLE);
SetStdHandle(STD_OUTPUT_HANDLE, writeHandle);

PROCESS_INFORMATION pi = new PROCESS_INFORMATION();

STARTUPINFO si = new STARTUPINFO();
//si.lpDesktop = string.Empty;
//si.cb = System.Runtime.InteropServices.Marshal.SizeOf(si);
//si.dwFlags = STARTF_USESTDHANDLES ;
//si.wShowWindow = SW_HIDE;
////si.hStdInput = writeHandle;
//si.hStdOutput = writeHandle;

GetStartupInfo(ref si);
si.dwFlags= STARTF_USESTDHANDLES ;
si.hStdOutput = writeHandle;

bool r = CreateProcessAsUser(dupeTokenHandle, null, @"c:\windows\system32\tracert.exe", ref sa, ref sa,true, 0, (IntPtr)0, @"c:\", ref si, out pi);
if (r)
{
if (1==WaitForSingleObject(pi.hProcess, INFINITE))
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("WaitForSingleObject failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

if (!CloseHandle(pi.hProcess))
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("CloseHandle failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

if (!CloseHandle(pi.hThread))
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("CloseHandle failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

}
else
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("CreateProcessAsUser failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);
}

SetStdHandle(STD_OUTPUT_HANDLE, std);

//CloseHandle(writeHandle);

System.Text.ASCIIEncoding Encoding = new System.Text.ASCIIEncoding();
string hello="hello";
byte[] wbuffer=Encoding.GetBytes(hello);
unsafe
{
//int count = 5;
//int n;
//fixed (byte* p = wbuffer)
//{
// WriteFile(writeHandle ,p , count, &n, 0);
//}
byte[] buffer = new byte[40];
int read, total, left;
fixed (byte* p = buffer)
{
if (PeekNamedPipe(readHandle, p, (uint)buffer.Length, &read, &total, &left) > 0)
{
if (total > 0)
{
int bytesRead;
do
{
bytesRead = Read(readHandle, buffer, 0, buffer.Length);
string content = Encoding.GetString(buffer, 0, bytesRead);
Console.Write("{0}", content);
}
while (bytesRead > 0);
}
}
else
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("PeekNamedPipe failed with error code : {0}", ret);
throw new System.ComponentModel.Win32Exception(ret);

}
}
}

// Free the tokens.

if (readHandle != IntPtr.Zero)
CloseHandle(readHandle);

if (writeHandle != IntPtr.Zero)
CloseHandle(writeHandle);

if (tokenHandle != IntPtr.Zero)
CloseHandle(tokenHandle);

Console.Read();


}
catch (Exception ex)
{
int ret = Marshal.GetLastWin32Error();
Console.WriteLine("CreateProcessAsUser failed with error code : {0}", ret);
Console.WriteLine(new System.ComponentModel.Win32Exception(ret));

Console.WriteLine("Exception occurred. " + ex.Message);
Console.Read();
}

}
}


110,535

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧