2012-03-18 22 views
6

Tengo un problema y las otras preguntas aquí no me sirvieron de mucho.Dividir una matriz de bytes en un delimitador

Soy un estudiante de seguridad y estoy tratando de escribir un crypter para un proyecto. Para aquellos que no saben de qué se trata, pueden leer aquí. http://www.gamekiller.net/tutorials-guides/17187-tut-making-crypter-vb6-using-rc4.html

De todas formas, una explicación rápida, cifrados son programas destinados a eludir los antivirus mediante el cifrado de un programa y luego la colocación de un "trozo", que es un programa que lo descifra, en la parte frontal. Tengo un problema muy molesto con la división de mi archivo.

La gran molestia es que tengo que poner el ejecutable encriptado en una matriz de bytes, ya que las cadenas matan ciertos caracteres en mi ejecutable cifrado, por lo que es inexequible. Para empeorar las cosas, todavía tengo que "dividir" el exe y aquí es donde comienza el problema.

La idea básica del talón es:

  • obtener la ruta exe actual
  • Leer todos los bytes a través File.ReadAllytes
  • dividir el archivo en el delimitador "" EVILDELIMITER
  • Obtener el último campo (Dado que es el EXE cifrado)
  • Descifrarlo utilizando RC4
  • Ejecutar utilizando RunPE.

Tengo todo funcionando, excepto la parte de división, que es la más molesta. ¿Cómo puedo dividir una matriz de bytes en el delimitador? ¿Hay alguna forma más fácil de hacer esto?

Aquí está el código del talón que tengo hasta ahora.

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

Gracias por cualquier ayuda.

+1

La codificación de UTF8 no es ideal. Puede obtener puntos de código Unicode no válidos. Debería intentar iterar a través de la matriz de bytes. – Polynomial

+0

¿Cómo cambio mi cadena a una matriz de bytes? Necesito cambiar mi delimitador antes de poder buscarlo, a menos que conozca una función que me permita buscar a través de una matriz de bytes con un valor de cadena. También arreglé el código. Accidentalmente usé una versión antigua que tenía. – redcodefinal

+0

@Roger Me arroja un montón de errores :(Dice que la cadena no tiene un método ToArray () – redcodefinal

Respuesta

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

Su implementación parece muy sólida pero, ¿por qué Seperate devuelve un byte [] [] y no un byte común? []? Solo necesito el último campo, ya que solo hay un separador. – redcodefinal

+0

use Separate (..). Last() –

+0

Bien, gracias, déjenme probar esto muy rápido: D – redcodefinal

0

Su enfoque tiene una serie de defectos - que está leyendo todo un byte [] en la memoria, pero es un proceso de descifrado en flujo continuo, por lo que estamos perdiendo innecesariamente la memoria. En segundo lugar, no puede "dividir" una matriz (o una cadena, para el caso) en el CLR. Cuando divide una Cadena CLR crea copias, lo que desperdicia memoria.

Prueba esto:

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 
} 

No, no hay ningún byte desordenado [] matrices :)

+0

No estoy seguro de cómo implementarlo. Nunca lo utilicé d BianryReader antes. Tampoco me importa perder memoria, ya que no está haciendo mucho trabajo, solo descifrar el exe y ejecutarlo antes de terminarlo. – redcodefinal

1

Sé que soy muy, muy tarde a la fiesta, pero ... Por supuesto, puede modificar esto para devolver una lista fácilmente si se prefiere. Dejé comments/writelines en caso de que fuera útil ... Puede que este no sea el código más óptimo/optimizado, pero funciona bien para mi caso de uso específico y pensé que lo compartiría.

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