C# 混凝土浇筑时字符串溢出
我试图制作一个程序打包器,但我总是失败,因为当我将三个字符串(一个包含源代码的前缀,一个包含可执行内容,另一个包含源代码的后缀)转换为后缀时,内容溢出。代码:C# 混凝土浇筑时字符串溢出,c#,C#,我试图制作一个程序打包器,但我总是失败,因为当我将三个字符串(一个包含源代码的前缀,一个包含可执行内容,另一个包含源代码的后缀)转换为后缀时,内容溢出。代码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.W
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.IO;
using System.IO.Compression;
namespace ProgramPacker
{
public partial class Form1 : Form
{
static string prefix = @"using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace ProgramPacker
{
class Program
{
static string inside = @" + "\"";
static string suffix = "\";\n" + @"static void Main(string[] args)
{
string temp = Path.GetRandomFileName() +" + "\"" + @".exe" + "\"" + @";
BinaryWriter sw = new BinaryWriter(new FileStream(temp, FileMode.Create));
sw.Write(inside);
sw.Flush();
sw.Close();
System.Diagnostics.Process.Start(temp);
}
}
}";
public string code = "";
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
openFileDialog1.ShowDialog();
BinaryReader br = new BinaryReader(new FileStream(openFileDialog1.FileName, FileMode.Open));
byte[] data = new byte[br.BaseStream.Length];
br.Read(data, 0, (int)br.BaseStream.Length);
br.Close();
string inside = Encoding.UTF7.GetString(data);
code = string.Concat(prefix, string.Concat(inside, suffix));
}
private void button2_Click(object sender, EventArgs e)
{
Console.Write(code);
CSharpCodeProvider cs = new CSharpCodeProvider();
ICodeCompiler compile = cs.CreateCompiler();
CompilerParameters param = new CompilerParameters();
param.GenerateInMemory = false;
param.ReferencedAssemblies.Add("mscorlib.dll");
param.ReferencedAssemblies.Add("System.dll");
param.ReferencedAssemblies.Add("System.Core.dll");
param.GenerateExecutable = true;
param.OutputAssembly = Environment.CurrentDirectory + "/a.exe";
param.WarningLevel = 4;
CompilerResults comp = compile.CompileAssemblyFromSource(param, code);
foreach (CompilerError error in comp.Errors)
{
MessageBox.Show(error.Line + " " + error.Column + " " + error.ErrorText);
}
MessageBox.Show(comp.PathToAssembly);
MessageBox.Show("Finish!");
}
}
}
它输出:
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
namespace ProgramPacker
{
class Program
{
static string inside = @"?ãÎoüoy±ôãøÿ?ÿQÔh¦Rt!?^ÿyóë=G:Fÿ»??¿Ç/}òKÿ?úõßû3õMù?c·?Äûòëoª?À_Û>LÖïá^öÿ·õ©üüòcÊ?ª??÷Ô?î:^ȯÏäG¶?ù ?ñË?oñëy:ôã7??ò@ÚyN?w¿=?ëÆ÷ëÛßTëºÓ»yßüø]áå{ö/àïªêL©Oÿ;ú5rù% ä¸?1)Ï?¥?y®ÿ]0QL8û×ÖGòów±?øÿèü[?ª~éá¿ÿó£üüJ~ܹ
Êw¡h??/?úçeñÈ_?¿?ü½L^ywü7?,ùÅû¿ß£ó÷w?É~Ç????ê?ÿQÌyç¿??¹Cö×vZ__>?? ûïx?_ü"õ!ì; ;ùõåÇ?ú3*¿ @ÿV?èÿ¿Ë??/½P¶y?â¡??ùñÿÑæä/A¶_ò?v??ÿ?ÿQtÄx÷w?O'N?u$ÿk÷U«yÆò?£.Y?ùw(?ßÔ6ÿ]2ÿeUÆò¿?ضö·ßO~ü#*y£Jæ·Ä w yóYëï´
õ}y¡ä¨ù÷YPdú?Z©Óé¼R?æg?ÀSyà쬽ÉÿûÁ?ym>ut?ÿA??>?¿[ôçF ê´)9ß9xÿ£¿?
åùïyí ÁTlù
-ùñ?Òÿ·!·
E?£üO5÷]çºy?7Áè¿?Zô?(å§
#ü¥úõ®?o«âû]0Èßä7¿à??¿õ?d?ѵ;Jü_K?úAMìT>Àü1mR0sâ¿ê¨õ{äö×ó??¿.úÿõ½Eä?ÔïÿÎÿ±³v'ÿûìw ?»oÃø1±WtB
É¡wì&øuå£Îÿ?Éw?|úWÿ=ö÷_ÿ·?y®YWöwû¿ßß?Öe'û?%?yß/×Àî-yÿ.?8åóù?ûÇÚ6ÿÂßøï?Áàï?{8Zy?¿Å5yø ÇpÏ9=ó»üÑ>Õ?Èÿ?Y¿,?ëÿ?Êçÿì_}E?÷Ûú|î$ò÷ø}Jÿ^Êtò¿?@á|ò{Ø`<ªÿQ?QLæ½õo)¿ü&¿áÂÿ¼ó¿_÷7yMå8)¿Ùo'¿õ±üü=~#LÚ¿ó§¢Ë÷üO?Æ?å÷WJÍ$¾¸øW?A?Òÿ(09Áÿà³_ëÿù3l?SWYµßô÷¤~?ÀG¿ñ
??Às%ÍyÑ;Ò¸!ÿ?_Iÿ¼¼í/Ôrö
?T´ôÑùyǹßE~üV?ñ¿C~VßùuÿG X8|._¼Å_:Æü-?îü:?øì?|W ¤ÃÓW01?$å×?Û#ùIÿû·1:4û½ü._y^òÙNó?º1?ßIÍ?ÿ¿ß_~|ÖùX?@?në_B?¡µ~_×ãÿhãèïØÏßì¡yïôk_y;HÿÛyÿàâ/sÀ??? $ìw0Jüßü«@?ûo?¿îËX
´úÏ?Æ?Y>øçÿFpyÅÿèËöyK¡²Ì`}ù½Ò¿íÿÀñn"?Í?ëOëi»ò¹Î~çÿ?_òüîÿh£ôáêDøÏÿ¶?ç·fy ÄúçÿÖÿ?yÿ?¿?ã0ÿ¿Ë÷åå?ÿQ|ü/ü9¿?÷×Hè×ÉÏ#õ??æ?ÿâ?x?ß?5µ}~Øy¾ß^øè{¿
y{íü;Òÿ¿óú7¤¡î?» yû?ÀÓøiP?ÿÀ_ôK?Gëªíá@??ú%íwS×ñ¿¨#Û¦ÿÿÛªy\]¼÷Z~yR~ü¶ÿ£hû???ÇãÿQVèÿ©?÷{O?Gë¬ ??¡ø\«L` æcëí¿ ½?»?ü?oë¼Ätÿ>ò÷£_¯ÖiÄ?¯ÿÓ¿÷Ï?(c¦äàéûèó?ü£´çÕè4üy_
r?qÆ¿ø'?KÿÀ_ó×xùkÔ¿FõkÌ~õ¯1y5Ú_ã'??n~âר~å¯ñkü»¿Æø×رÿÿ5~?_ã7ø5~Í_ã?Z4ÔrñkL~ò׸?5Òßûÿ??ñïñnQ¦?yYÕò³vÇ;¥ùrZÍ?åÅg}õæÙöÁGiÓfËYVVËü³®óæ£ßãè7NgM?/&åuJrustInfo>
</assembly>
;
}
}
}
使用系统;
使用System.Collections.Generic;
使用系统文本;
使用System.IO;
名称空间程序打包器
{
班级计划
{
本月5月月日,该名名名名为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为为本月的维维维维维维维维维维维托托托托卡内内为为为为为为为为为为为为为为为为为为本月5 5月月日日,为为为为为为为为为为为为为为为为为为本月月月日日日,为为为为为为为为为为为为本月月月日日,为为为为为为为为为为其他其他其他其他其他其他其他为为为为为为为本月月日,为为为为为为为为为本月日,而而而为为为为为为为为为为为为为为该该名名名名名名为为为为为为为为为尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅:尼奥涅[?ª~ÿÿóüJ~Ü
“w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w·w政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政政ÿVÿQtÄx÷wÿNÿk÷u«yÆyòyùw(?223; 6ÿ2ÿeUòOèO#yæwÿyÿ
你认为是什么?
åùyíTlù
-ùñ?Òÿ·!·
EèO5÷]yè7ÁèZè?(229;§
#
“w”维维维托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托托更好地使用CodeCompileUnit从C程序生成C代码:
您还可以使用它将生成的ATS编译成assembley
或者从文件中解析模板部分。这将使代码更具可读性。不要使用裸UTF7或UTF8字符串,而是使用Base64编码
// given: byte[] data = new byte[...]
string inside = System.Convert.ToBase64String(data);
code = string.Concat(prefix, string.Concat(inside, suffix));
// in your target code
sw.Write(System.Convert.FromBase64String(inside));
你不能只将可执行二进制代码表示为C字符串而不进行转义。至少你需要用两个双引号字符序列替换出现的双引号字符(“
)
请注意,字符串可能包含导致屏幕以乱码方式显示字符串的控制字符,但这不一定会导致包含该字符串的代码编译不正确。例如,如果您有一个包含退格的逐字字符串(“stac{backspace}koverflow”
,例如),退格后的字符将覆盖退格前的字符,因此在屏幕上查看字符串将给出其内容的不准确表示(“stakoverflow”
)。编译器可能会看到完整的14个字符的字符串,包括退格。您遇到了表示问题,您不太可能按原样用代码修复该问题
但是,您可以选择遵循类似的方法,只需稍作修改(实际上根本不会对程序进行太多压缩)
将@
从内部的字符串定义中删除。这是问题的原因之一
您不能只在字符串中插入贝尔字符或NUL字符,而是写出它们的unicode转义序列:
string inside = String.Concat(
data.Select(b => String.Format(@"\u{0:X4}", b)));
现在,在后缀
代码中,将内部的字符串重新解释为您转换为字节的字符:
sw.Write(inside.Select(c => (byte)c).ToArray()); // hardly efficient
我能够使用这些修改并成功地“打包”并执行以下操作:
C:\temp>type hello.cs
using System;
class M {
static void Main(string[] args) {
System.IO.File.Create("hello.world");
}
}
C:\temp>csc hello.cs
Microsoft (R) Visual C# 2010 Compiler version 4.0.30319.1
Copyright (C) Microsoft Corporation. All rights reserved.
C:\temp>pack.exe hello.exe
3584 bytes
C:\temp>a.exe
C:\temp>dir *.world
Volume in drive C is OSDisk
Volume Serial Number is AABD-D663
Directory of C:\temp
03/22/2012 16:36 0 hello.world
1 File(s) 0 bytes
0 Dir(s) 279,351,762,944 bytes free
这个列表应该是一个示例输出?您正在使用的“内部”示例是什么?可能引号没有正确转义?顺便说一句,这个应用程序感觉有点可疑,将一个内部exe写入一个临时文件,然后执行它?试图对某些东西进行特洛伊木马攻击,是吗?如果您没有要转换的字符串,则不是。Encoding.UTF7.GetBytes()
仅当您将字符串从一种编码转换为另一种编码时才有效;它不会神奇地将非字符串数据转换为字符串。(您不能将食用色素添加到鸡汤中,并让它神奇地停留在面包片之间。)我们在这里不是要讨论这个问题的可疑性。他的问题中没有恶意,打包代码或编写不断发展的代码是一种在某些情况下使用的技术。请注意,打包代码不会覆盖任何安全边界,它实际上取决于允许他将其保存到某个系统的系统安全性d是否可以越界执行(如NX位).所以,我看不出有什么理由我们应该摆脱他的问题。只有他链接的可执行文件可以是一个边缘案例,请不要在没有彻底检查的情况下运行它…好吧,这里的问题是,当我浓缩三个字符串时,它溢出了。但是好的建议,我可能会使用它们。我尝试了payo的代码,该代码可以转义引号,但仍然不起作用。@user1286744正如我所说,如果有,我会感到惊讶。我给答案添加了一些想法。@user1286744:这比我的简单多了,我来谈谈隧道视觉!你不需要用Base64编码的数据逃避任何事情。我会在任何一天(周日两次)接管我的。根据规范,任何unicode字符都可以包含在逐字字符串中(当然,“
,它总是由”
)表示除外)。因此,这不应该包括BELL和NUL吗?@phoog:我没有成功地编译它们。