user10043815
user10043815

Reputation:

C# - Reading Sequence of Hex Bytes in Binary

So I've been googling & googling for this, but I can't find a solution for my case. I could find things about byte arrays. but I hope there's also a simpler solution for my case. Maybe it's just me using the wrong search terms, don't know.

Anyways, I already have a kinda working code which is:

    static void Main(string[] args)
    {
        // Open the file to search in
        BinaryReader br = new BinaryReader(File.OpenRead("D:/Users/Joey/Desktop/prod"));
        for (int i = 0; i <= br.BaseStream.Length; i++)
        {
            // Search the file for the given byte
            if (br.BaseStream.ReadByte() == (byte)0xC0)
            {
                Console.WriteLine("Found the byte at offset " + i); //write to the console on which offset it has been found
            }
        }
    }

This example works. However, I need it to be able to search for more than just one byte. For example: C0035FD6

I feel like I'm missing something so simple, but I just can't seem to figure it out.

If anyone has gotten a solution for me, that would be great :D

Upvotes: 2

Views: 1119

Answers (2)

Xiaoy312
Xiaoy312

Reputation: 14477

You can use this extension to search for AOB:

public static class StreamExtensions
{
    public static IEnumerable<long> ScanAOB(this Stream stream, params byte[] aob)
    {
        long position;
        byte[] buffer = new byte[aob.Length - 1];

        while ((position = stream.Position) < stream.Length)
        {
            if (stream.ReadByte() != aob[0]) continue;
            if (stream.Read(buffer, 0, aob.Length - 1) == 0) continue;

            if (buffer.SequenceEqual(aob.Skip(1)))
            {
                yield return position;
            }
        }
    }

    public static IEnumerable<long> ScanAOB(this Stream stream, params byte?[] aob)
    {
        long position;
        byte[] buffer = new byte[aob.Length - 1];

        while ((position = stream.Position) < stream.Length)
        {
            if (stream.ReadByte() != aob[0]) continue;
            if (stream.Read(buffer, 0, aob.Length - 1) == 0) continue;

            if (buffer.Cast<byte?>().SequenceEqual(aob.Skip(1), new AobComparer()))
            {
                yield return position;
            }
        }
    }

    private class AobComparer : IEqualityComparer<byte?>
    {
        public bool Equals(byte? x, byte? y) => x == null || y == null || x == y;
        public int GetHashCode(byte? obj) => obj?.GetHashCode() ?? 0;
    }
}

Example:

void Main()
{
    using (var stream = new MemoryStream(FakeData().ToArray()))
    {
        stream.ScanAOB(0x1, 0x2).Dump("Addresses of: 01 02");
        stream.Position = 0;
        stream.ScanAOB(0x03, 0x12).Dump("Addresses of: 03 12");
        stream.Position = 0;
        stream.ScanAOB(0x04, null, 0x06).Dump("Addresses of: 04 ?? 06");
    }
}

// Define other methods and classes here
IEnumerable<byte> FakeData()
{
    return Enumerable.Range(0, 2)
        .SelectMany(_ => Enumerable.Range(0, 255))
        .Select(x => (byte)x);
}

Upvotes: 1

mjw
mjw

Reputation: 1206

Give this a shot. You will need to verify the arrays are correct. In a binary stream, a byte array is just a collection of bytes starting at offset with count bytes as its size.

//here is where you initialize your array. you may need to tweak the values to match your byte range (array)
byte[] dataArray = new byte[9] { 0x93, 0x0E, 0x40, 0xF9, 0x53, 0x00, 0x00, 0xB5, 0xDE };

//here is where you initialize the NEW array you want to write where your matching array lives
byte[] newArray = new byte[9] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };

// Open the file to search in
BinaryReader br = new BinaryReader(File.OpenRead("D:/Users/Joey/Desktop/prod"));
for (int i = 0; i <= br.BaseStream.Length; i++)
{
    // Search the file for the STARTING byte of my match
    if (br.BaseStream.ReadByte() == (byte)0x93)
    {
        Console.WriteLine("Found the starting byte at offset " + i); //write to the console on which offset it has been found
        byte[] tempArray = new byte[9];
        tempArray = br.ReadBytes(9);
        //now compare the arrays to see if you have a full match:
        int matched = 0;
        for (int j=0; j<tempArray.Length; j++)
        {
            if(tempArray[j] == dataArray[j])
            {
                 matched++;
            }
        }

        //if the arrays match, write your new values:
        if(matched == tempArray.Length-1)
        {
            br.BaseStream.Write(newArray, i, 9);
            break; //exit the loop when finished                    
        }                    
    }
}

Upvotes: 0

Related Questions