使用命令行参数将任意二进制数据从 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"
我们需要的是:
- 一种将字节转换为类似 "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 方法。
- 一种确保我们的参数行被正确转义的方法(这样 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? 可能对您有用。
出于学术目的,我想尝试通过传递一些包含特定二进制数据(原始字节)的任意长字符串,使用 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"
我们需要的是:
- 一种将字节转换为类似 "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 方法。
- 一种确保我们的参数行被正确转义的方法(这样 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? 可能对您有用。