在分隔符处拆分字节数组

我有一个问题,这里的其他问题对我没什么帮助。

我是一名安全学生,我正在尝试为项目编写一个加密器。 对于那些不知道它是什么的人,你可以在这里阅读。 http://www.gamekiller.net/tutorials-guides/17187-tut-making-crypter-vb6-using-rc4.html

无论如何,一个快速的解释,加密器是通过加密程序然后在前面粘贴“存根”(一个解密它的程序)来绕过防病毒的程序。 我分割文件时遇到了一个非常烦人的问题。

最大的烦恼是我必须将加密的可执行文件放入一个字节数组中,因为字符串会杀死我的加密可执行文件中的某些字符,使其无法执行。 更糟糕的是,我仍然必须“拆分”exe,这就是麻烦开始的地方。

存根的基本思想是:

  • 获取当前的exe路径
  • 通过File.ReadAllytes读取所有字节
  • 在分隔符“EVILDELIMITER”处拆分文件
  • 获取最后一个字段(因为那是加密的EXE)
  • 使用RC4解密它
  • 使用RunPE运行。

我有一切工作,除了分裂部分,这是最烦人的。 如何在分隔符处拆分字节数组? 有更简单的方法吗?

这是我到目前为止存根的代码。

public void main() { string outpath = RandomString(8) + ".exe"; byte[] key = { 33, 44, 55, 66, 77 }; string apppath = Assembly.GetEntryAssembly(); byte[] exe = File.ReadAllBytes(apppath); string strseperate = "EVILSEPERATOREVIL"; System.Text.UTF8Encoding encoding = new System.Text.UTF8Encoding(); byte[] seperator = encoding.GetBytes(strseperate); //Split code should go here exe = Decrypt(key, encrypted); Process.Start(outpath); } 

谢谢你的帮助。

 byte[] SeparateAndGetLast(byte[] source, byte[] separator) { for (var i = 0; i < source.Length; ++i) { if(Equals(source, separator, i)) { var index = i + separator.Length; var part = new byte[source.Length - index]; Array.Copy(source, index, part, 0, part.Length); return part; } } throw new Exception("not found"); } public static byte[][] Separate(byte[] source, byte[] separator) { var Parts = new List(); var Index = 0; byte[] Part; for (var I = 0; I < source.Length; ++I) { if (Equals(source, separator, I)) { Part = new byte[I - Index]; Array.Copy(source, Index, Part, 0, Part.Length); Parts.Add(Part); Index = I + separator.Length; I += separator.Length - 1; } } Part = new byte[source.Length - Index]; Array.Copy(source, Index, Part, 0, Part.Length); Parts.Add(Part); return Parts.ToArray(); } bool Equals(byte[] source, byte[] separator, int index) { for (int i = 0; i < separator.Length; ++i) if (index + i >= source.Length || source[index + i] != separator[i]) return false; return true; } 

我知道我真的,非常迟到了派对,但是……如果愿意的话,你当然可以修改它以便轻松返回List。 我留下了评论/ writelines,以防它有用…这可能不是最优/优化的代码,但适用于我的特定用例,我想我会分享。

  public static byte[][] SplitBytesByDelimiter(byte[] data, byte delimiter) { if (data == null) throw new ArgumentNullException(nameof(data)); if (data.Length < 1) return null; List retList = new List(); int start = 0; int pos = 0; byte[] remainder = null; // in case data found at end without terminating delimiter while (true) { // Console.WriteLine("pos " + pos + " start " + start); if (pos >= data.Length) break; if (data[pos] == delimiter) { // Console.WriteLine("delimiter found at pos " + pos + " start " + start); // separator found if (pos == start) { // Console.WriteLine("first char is delimiter, skipping"); // skip if first character is delimiter pos++; start++; if (pos >= data.Length) { // last character is a delimiter, yay! remainder = null; break; } else { // remainder exists remainder = new byte[data.Length - start]; Buffer.BlockCopy(data, start, remainder, 0, (data.Length - start)); continue; } } else { // Console.WriteLine("creating new byte[] at pos " + pos + " start " + start); byte[] ba = new byte[(pos - start)]; Buffer.BlockCopy(data, start, ba, 0, (pos - start)); retList.Add(ba); start = pos + 1; pos = start; if (pos >= data.Length) { // last character is a delimiter, yay! remainder = null; break; } else { // remainder exists remainder = new byte[data.Length - start]; Buffer.BlockCopy(data, start, remainder, 0, (data.Length - start)); } } } else { // payload character, continue; pos++; } } if (remainder != null) { // Console.WriteLine("adding remainder"); retList.Add(remainder); } return retList.ToArray(); } 

你的方法有很多缺陷 – 你正在将整个Byte []读入内存,但解密是一个可流动的过程,所以你不必要地浪费内存。 其次,你不能在CLR中“拆分”一个数组(或者一个字符串)。 拆分CLR字符串时,它会创建副本,这会浪费内存。

试试这个:

 public static void Main(String[] args) { using(FileStream fs = new FileStream( @"path\to\fileName.exe", FileMode.Read)) { BinaryReader rdr = new BinaryReader( fs ); SeekToEndOfDelimiter( rdr ); // Use an implementation of RC4 decryption that accepts Streams as arguments, then pass fs directly as an argument: using(FileStream output = new FileStream( @"path\to\out.exe", FileMode.Write)) { // Providing the key arguments is an exercise for the reader MyRc4Implementation.DecryptStream( fs, output, key ); } } } private static void SeekToEndOfDelimiter(BinaryReader rdr) { // Implementing this code is an exercise left up to the reader. // But just iterate through each byte (assuming ASCII-compatible encoding) until you encounter the end of the delimiter } 

在那里,没有凌乱的byte []数组:)

这是我的。 它只进行了一次分割。 我没有试图让它变得高效。

 public static byte[][] Split(this byte[] composite, byte[] seperator) { bool found = false; int i = 0; for (; i < composite.Length - seperator.Length; i++) { var compositeView = new byte[seperator.Length]; Array.Copy(composite, i, compositeView, 0, seperator.Length); found = compositeView.SequenceEqual(seperator); if (found) break; } if(found == false) { return null; } var component1Length = i; var component1 = new byte[component1Length]; var component2Length = composite.Length - seperator.Length - component1Length; var component2 = new byte[component2Length]; var component2Index = i + seperator.Length; Array.Copy(composite, 0, component1, 0, component1Length); Array.Copy(composite, component2Index, component2, 0, component2Length); return new byte[][] { component1, component2 }; } 

测试(部分):

 byte[] b1 = new byte[] { 1, 2, 3, 4, 1, 1, 5 }; byte[] b2 = new byte[] { 1, 1 }; var parts1 = b1.Split(b2); // [1,2,3,4],[5] byte[] b3 = new byte[] { 1, 1, 3, 4, 4, 1, 5 }; byte[] b4 = new byte[] { 1, 1 }; var parts2 = b3.Split(b4); // [],[3,4,4,1,5] byte[] b5 = new byte[] { 0, 0, 3, 4, 4, 1, 1 }; byte[] b6 = new byte[] { 1, 1 }; var parts3 = b5.Split(b6); // [0,0,3,4,4],[] byte[] b7 = new byte[] { 1, 2, 3, 4, 5 }; byte[] b8 = new byte[] { 1, 2, 3, 4 }; var parts4 = b7.Split(b8); // [],[5] byte[] b9 = new byte[] { 1, 2, 3, 4, 5 }; byte[] b0 = new byte[] { 2, 3, 4, 5 }; var parts5 = b9.Split(b0); // [1],[] byte[] c1 = new byte[] { 1, 2, 3, 4, 5 }; byte[] c2 = new byte[] { 6 }; var parts6 = c1.Split(c2); // null 

对于想要就地使用字节的人而不是将它们复制到新数组,可以使用ArraySegment来实现此目的。

这是一个实现:

 private static List> Split(byte[] arr, byte[] delimiter) { var result = new List>(); var segStart = 0; for (int i = 0, j = 0; i < arr.Length; i++) { if (arr[i] != delimiter[j]) continue; if (j++ != delimiter.Length - 1) continue; var segLen = i - segStart - (delimiter.Length - 1); if (segLen > 0) result.Add(new ArraySegment(arr, segStart, segLen)); segStart = i + 1; j = 0; } if (segStart < arr.Length) result.Add(new ArraySegment(arr, segStart, arr.Length - segStart)); return result; }