使用命令行参数将任意二进制数据从 C# 应用程序传递到另一个应用程序

Passing arbitrary binary data from C# application to another application using command line arguments

出于学术目的,我想尝试通过传递一些包含特定二进制数据(原始字节)的任意长字符串,使用 C# 利用 strcpy 函数和 buffer overflow attack

我正在尝试类似于此 C# 代码的操作,但这显然不起作用:

static void Main(string[] args)
{
    string cPath = @"C:\Debug";
    var strCmdText =
        "0xCA" + "0xCA" + + "0xCA" + "0xCA" + "0xCA" + ...;
    string filename = Path.Combine(cPath, "Buffer.exe");
    var proc = System.Diagnostics.Process.Start(filename, strCmdText);
}

我们假设目标应用程序使用 single-byte characters as its argv。所以...

1. 测试应用程序

我们的测试应用程序名为 Buffer.exe,其源代码为:

void print_str(char* str)
{
    size_t length = strlen(str);
    printf("Line: '%s'\n", str);
    printf("Len : '%d'\n", length);
    printf("Hex :", length);

    for (size_t i = 0; i < length; i++)
    {
        printf("\t0x%02x", str[i]);
    }

    printf("\n");
}


int main(int argc, char* argv[])
{
    for (int i = 1; i < argc; i++)
    {
        char* str = argv[i];
        printf("Argument #%d:\n", i);
        print_str(str);
    }

    printf("Press enter to exit\n");
    getchar();
}

它只是将传递的参数打印为字符串和十六进制值,因此对于参数 "a1" "b2" 它将打印

Argument #1:
Line: 'a1'
Len : '2'
Hex :   0x61    0x31
Argument #2:
Line: 'b2'
Len : '2'
Hex :   0x62    0x32
Press enter to exit

2.主要"ingredients"

我们需要的是:

  1. 一种将字节转换为类似 "single byte characters" 的方法(实际上它们仍然是 2 字节 UTF-16 chars on the C# side, but [OS should pass them to our receiver]/[Buffer.exe should interpret] as single byte characters with the same binary value we started on the C# side) - for that we need Encoding.Default (as corrected by @Tom Blodget) property and its Encoding.GetString 方法。
  2. 一种确保我们的参数行被正确转义的方法(这样 0x20-Space 就不会将我们的大参数分成多个,其他特性也不会影响命令行)- 为简单起见我们将用引号转义一整行,但对于 正确的解决方案 (至少在 Win32 上)请参见 https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/.

3. 实施

我们创建应用程序的参数如下:

public static String BytesToCommandLineArgument(Byte[] array)
{            
    var ascii = Encoding.Default.GetString(array);
    // "Escape" it here. Disclaimer - it is actually a wrong way to escape a command line argument.
    // See https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/ 
    // for a way to do it correctly at least on Win32
    return String.Format("\"{0}\"", ascii); 
}

public static  void Main()
{
    try
    {
        var bytes = new Byte[] { 0x10, 0x31, 0x13, 0x61, 0x20 };

        using (var process = Process.Start(
            fileName: "Buffer.exe",
            arguments: BytesToCommandLineArgument(bytes)))
        {
            process.WaitForExit();
        }
    }
    catch (Exception exc)
    {
        Console.WriteLine(exc);
    }
    Console.WriteLine("Press any key...");
    Console.ReadKey(true);
}

4. 测试

如您所见,我们的测试字节数组包含空格和换行符,因此我们至少可以确保我们的解决方案不会去除它们(尽管正如我所说的那样,最后的引号会破坏它) .

Argument #1:
Line: '►1‼a '
Len : '5'
Hex :   0x10    0x31    0x13    0x61    0x20
Press enter to exit

P.S.1: 不要忘记此解决方案错误地转义命令行 - https://blogs.msdn.microsoft.com/twistylittlepassagesallalike/2011/04/23/everyone-quotes-command-line-arguments-the-wrong-way/!它可能不会对可能的数据空间中的大多数数据造成任何问题,但它肯定会对某些数据造成影响。

P.S.2: 如果您需要动态输入数据,How do you convert Byte Array to Hexadecimal String, and vice versa? 可能对您有用。