Split byte array on delimiter

I have a problem, and other questions here did not help me.

I am a security student and I am trying to write crypto for a project. For those who do not know what it is, you can read it here. http://www.gamekiller.net/tutorials-guides/17187-tut-making-crypter-vb6-using-rc4.html

In any case, a quick explanation, crypters are programs designed to bypass antivirus programs by encrypting the program and then attaching a โ€œstubโ€, which is a program that decrypts it on the front panel. I have a very nasty problem with splitting my file.

The big annoyance is that I have to put the encrypted executable in an array of bytes, since strings kill certain characters in my encrypted executable, making it unenforceable. To aggravate the situation, I still have to "split" exe, and this is where the problem begins.

The main idea of โ€‹โ€‹the stub is as follows:

  • Get current exe path
  • Read all bytes through File.ReadAllytes
  • Separate the file on the separator, "EVILDELIMITER"
  • Get the last field (since it is an encrypted EXE)
  • Decrypt it using RC4
  • Starting using RunPE.

Everything works for me, except for the part of the splitting, which is the most annoying. How to split byte array into delimiter? Is there an easier way to do this?

Here is the code for the stub I have.

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

Thanks for any help.

+7
source share
6 answers
 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; } 
+6
source

I know that I'm really very late for the party, but ... Of course, you can change this to return the list if necessary. I left comments / entries in case this would be useful ... This may not be the most optimal / optimized code, but works well for my specific use case, and I thought I wanted to share it.

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

There are a number of drawbacks to your approach - you read the entire byte [] in memory, but decryption is a smooth-access process, so you are wasting memory. Secondly, you cannot โ€œsplitโ€ an array (or string, for that matter) in the CLR. When you break a CLR String, it creates copies that lose memory.

Try the following:

 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 } 

There is no messy byte [] of arrays :)

0
source

Here is mine. It only makes a split at least once. I did not try to make him performing.

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

checked (partially):

 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 
0
source

For people who want to use bytes in place, instead of copying them to new arrays, you can use ArraySegment for this purpose.

Here is the implementation:

 private static List<ArraySegment<byte>> Split(byte[] arr, byte[] delimiter) { var result = new List<ArraySegment<byte>>(); 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<byte>(arr, segStart, segLen)); segStart = i + 1; j = 0; } if (segStart < arr.Length) result.Add(new ArraySegment<byte>(arr, segStart, arr.Length - segStart)); return result; } 
0
source

Here is the general version

  public static IList<ArraySegment<T>> Split<T>(this T[] arr, params T[] delimiter) { var result = new List<ArraySegment<T>>(); var segStart = 0; for (int i = 0, j = 0; i < arr.Length; i++) { //If is match if (arr.Skip(i).Take(delimiter.Length).SequenceEqual(delimiter)) { //Skip first empty segment if (i > 0) { result.Add(new ArraySegment<T>(arr, segStart, i - segStart)); } //Reset segStart = i; } } //Add last item if (segStart < arr.Length) { result.Add(new ArraySegment<T>(arr, segStart, arr.Length - segStart)); } return result; } 
0
source

Source: https://habr.com/ru/post/911013/


All Articles