C
C#13mo ago
Bambino

✅ FileStream is not reading entire file?

client.exe (3,563,520 bytes) fs.Length (896,000 bytes)
var path = Core.FindDataFile("client.exe", false);

using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);

// VS_VERSION_INFO (unicode)
Span<byte> vsVersionInfo = stackalloc byte[]
{
0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00,
0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00,
0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00,
0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00
};

for (var i = 0; i < buffer.Length - 30; i++)
{
if (vsVersionInfo.SequenceEqual(buffer.AsSpan(i, 30)))
{
var offset = i + 30 + 12;

var minorPart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset));
var majorPart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset + 2));
var privatePart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset + 4));
var buildPart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset + 6));

return new ClientVersion(majorPart, minorPart, buildPart, privatePart);
}
}
}
var path = Core.FindDataFile("client.exe", false);

using (FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var buffer = new byte[fs.Length];
fs.Read(buffer, 0, buffer.Length);

// VS_VERSION_INFO (unicode)
Span<byte> vsVersionInfo = stackalloc byte[]
{
0x56, 0x00, 0x53, 0x00, 0x5F, 0x00, 0x56, 0x00,
0x45, 0x00, 0x52, 0x00, 0x53, 0x00, 0x49, 0x00,
0x4F, 0x00, 0x4E, 0x00, 0x5F, 0x00, 0x49, 0x00,
0x4E, 0x00, 0x46, 0x00, 0x4F, 0x00
};

for (var i = 0; i < buffer.Length - 30; i++)
{
if (vsVersionInfo.SequenceEqual(buffer.AsSpan(i, 30)))
{
var offset = i + 30 + 12;

var minorPart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset));
var majorPart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset + 2));
var privatePart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset + 4));
var buildPart = BinaryPrimitives.ReadUInt16LittleEndian(buffer.AsSpan(offset + 6));

return new ClientVersion(majorPart, minorPart, buildPart, privatePart);
}
}
}
11 Replies
reflectronic
reflectronic13mo ago
firstly, your Read is incorrect Read does not have to read buffer.Length bytes, it can read any amount less than that you want fs.ReadExactly(buffer) but, also, i'm not sure what you mean about fs.Length. it doesn't lie, if it's 896,000 then that's the length of the file
Bambino
Bambino13mo ago
The length of the file is the file size? Is it not?
Bambino
Bambino13mo ago
Bambino
Bambino13mo ago
it is, nvm, that part is covered. I had a major brain fart looking at the wrong client in the wrong directory. However, I need to figure out what exact you meant by Read & ReadExactly
reflectronic
reflectronic13mo ago
look at the value returned by Read
The total number of bytes read into the buffer. This can be less than the number of bytes allocated in the buffer if that many bytes are not currently available, or zero (0) if the end of the stream has been reached.
it does not have to fill the entire array by default. you are expecting buffer to have the entire file but it may not. Read might only write a single byte to buffer if it would like really, it would be easiest for you to just do var buffer = File.ReadAllBytes(path); in this situation also, you know that there are APIs to read the version info, right. you do not need to scan for it yourself
Bambino
Bambino13mo ago
I was using FileVersionInfo info = FileVersionInfo.GetVersionInfo(path); However, this is an older file from the 90s. I'll see if any other APIs use a different method that may work as well. Interesting. Also, the one linked is a c++ library, I'm using c#
reflectronic
reflectronic13mo ago
ah. well, if FileVersionInfo doesn't work, then neither will GetFileVersionInfoW, since it just uses that
Bambino
Bambino13mo ago
Anyhow, I will have to figure out the address & offsets with IDA to determine the version in this case. Which is a whole other animal I am learning todo. You got me squared away with my issue here. Thanks for the assistance and helping me understand what 'exactly' was being read into the buffer.
cap5lut
cap5lut13mo ago
parsing the data afterwards can be a bit tricky (depending on how the data is structured) if u use a plain buffer, dotnet has a fancy helper class/system for that: https://learn.microsoft.com/en-us/dotnet/standard/io/pipelines wanted to show it to u incase it will be useful
Accord
Accord13mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.