我尝试运行一个简单的命令转义但没有响应,没有输出缓冲区,但如果我删除" $"符号效果很好。我该怎么办?
public class Executor
{
private Process proc;
public Executor ()
{
this.proc = new Process();
this.proc.StartInfo.UseShellExecute = false;
this.proc.StartInfo.RedirectStandardError = true;
this.proc.StartInfo.RedirectStandardInput = true;
this.proc.StartInfo.RedirectStandardOutput = true;
}
public String call(String command){
this.proc.StartInfo.FileName = "/bin/bash";
this.proc.StartInfo.Arguments = "-c $'" + stringToHexEscape(command) + "'";
this.proc.Start();
String result = this.proc.StandardOutput.ReadToEnd ();
this.proc.WaitForExit();
this.proc.Close ();
return result;
}
public String stringToHexEscape(String buffer){
byte[] ba = Encoding.Default.GetBytes(buffer);
String hexString = BitConverter.ToString(ba);
if (String.IsNullOrEmpty (hexString))
return "";
return ("\\x" + hexString.Replace("-", "\\x")).Trim();
}
}
在命令中尝试:
Executor executor = new Executor ();
String result = this.executor.call (
"[ -f ~/.ssh/id_rsa.pub ] && echo \"Found\" || echo \"Not found\""
);
Console.WriteLine("stdout: {0}", result);
但结果是空字符串。从bash工作正常:
me@Unknow:~$ /bin/bash -c $'echo \x61'
a
答案 0 :(得分:0)
针对已修改的问题进行了更新:
手头的核心问题是子进程I / O std / err重定向到父进程。如果您将其设置为true,则可以通过UseShellExecute
查看:
Process.StartInfo.UseShellExecute = true;
你将能够想要你正在尝试'执行',但实际上你正在使用内置函数进行bash评估。当然,在这种情况下你不能使用shell重定向,因为Process
类是不可能的。创建一个使用UseShellExecute = true
但没有重定向的控制台测试应用程序,您将看到您的评估按预期工作,现在您只需捕获该输出。
有很多方法,很多人使用BASHISM
技术,例如使用coproc
和/或其他子进程输出重定向(即使用exec
创建另一个输出并重定向子输出。)哪种方式更好? ...如果你在你的应用程序中不断地这样做,有些人会说使用posix shell,它不像dash
那样进行子进程替换...但是再次,个人偏好。
这是我多次使用的pipe
技术,因为我不必更改(破解)我的bash评估字符串,只是重定向我感兴趣捕获的一些(或全部)输出
injections
,具有进程权限的任何人都可以strace
任何系统调用,包括这些调用,从而观察您的shell / bash调用,并通过gdb
对这些进程进行代码注入...
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace consoleEcho
{
class MainClass
{
[DllImport ("libc")]
private static extern int system (string exec);
public static void Main (string[] args)
{
Process.Start ("mkfifo", "/tmp/fifo");
system (" [ -f ~/.ssh/id_rsa.pub ] && echo 'Found' >/tmp/foobar || echo 'Not found' >/tmp/foobar ");
var proc = new Process ();
proc.StartInfo.FileName = "cat";
proc.StartInfo.Arguments = "/tmp/foobar";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
String result = proc.StandardOutput.ReadToEnd ();
proc.WaitForExit();
proc.Close ();
Console.WriteLine(result);
Process.Start ("rm", "/tmp/fifo");
}
}
}
外壳输出:
Not found
(我的ssh文件不在标准位置......)
问题更新前的原文:
当你已经进入一个时,你正在开始一个新的bash / shell解释器,即:
bash -c echo -e '\x61'
或
bash -c echo $'\x61'
从bash的CLI运行时,两者都返回一个空字符串。
跳过第二个解释器并直接调用echo:
proc.StartInfo.FileName = "echo";
proc.StartInfo.Arguments = " '\x61' ";
剪切/粘贴示例:
using System;
using System.Diagnostics;
namespace consoleEcho
{
class MainClass
{
public static void Main (string[] args)
{
Process proc = new Process();
proc.StartInfo.FileName = "echo";
proc.StartInfo.Arguments = " '\x61' ";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardError = true;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
var output = proc.StandardOutput.ReadToEnd ();
Console.WriteLine("stdout: {0}", output);
}
}
}