-
Notifications
You must be signed in to change notification settings - Fork 127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
How to update some text content in StringTable? #219
Comments
Hi, unfortunately That being said, it is possible to edit a string manually. AsmResolver follows this structure as well. So what you can do, is follow this path in the win32 resource directory down to the data entry of the string block you want to edit, manually swap the contents, then update the PE file with a new Example code// Read raw PE file.
var file = PEFile.FromFile("basebrd.dll.mui");
// Open as image.
var image = PEImage.FromFile(file);
// Look up string entry.
var stringTables = (IResourceDirectory) image.Resources.Entries.First(e => e.Id == (int) ResourceType.String);
var stringEntry = (IResourceDirectory) stringTables.Entries.First(e => e.Id == 251); // ID
var dataEntry = (IResourceData) stringEntry.Entries.First(e => e.Id == 1033); // Lang ID
// Build up new string contents
const string newString = " Preview-Version";
using var stream = new MemoryStream();
var writer = new BinaryStreamWriter(stream);
writer.WriteUInt16((ushort) newString.Length);
writer.WriteBytes(Encoding.Unicode.GetBytes(newString));
writer.Align(4);
// Swap old data with new data (NOTE: in this example it erases any other string in this block as well, so in your
// implementation you might want to change this slightly).
dataEntry.Contents = new DataSegment(stream.ToArray());
// Swap contents of original .rsrc section with new resource directory buffer.
var rsrc = file.Sections.First(s => s.Name == ".rsrc");
var newContents = new ResourceDirectoryBuffer();
newContents.AddDirectory(image.Resources);
rsrc.Contents = newContents;
// Update data directory in optional header.
file.AlignSections();
file.OptionalHeader.DataDirectories[(int) DataDirectoryIndex.ResourceDirectory] =
new DataDirectory(newContents.DirectoryTable.Rva, newContents.DirectoryTable.GetPhysicalSize());
// Save.
file.Write("basebrd.dll.mui.patched"); See the following docs for more info on these classes: |
Thanks @Washi1337, it's a great library. I've seen a similar project(https://github.com/kohoutech/Resourcery) where able to list detailed resource information. Unfortunately it doesn't have to save the modified resource function. |
I am not familiar with Resourcery, but it seems like it is a program with the sole purpose of viewing/editing resources of a PE file. Both projects probably have pros and cons and it depends on what you need on whether you want to go with AsmResolver or a project such as Resourcery. The rich feature set of AsmResolver may make "simple" tasks (such as editing a single string entry) a bit more complicated than just calling a single function as other libraries might provide. On the other hand, the goal of AsmResolver is not to be just a resources editor, but an entire PE editor, giving you more freedom in what you can do and cannot do. |
Thanks very much. now I can search for byte arrays and replace them. var stringTables = (IResourceDirectory)image.Resources.Entries.First(e => e.Id == (int)ResourceType.String);
var stringEntry = (IResourceDirectory)stringTables.Entries.First(e => e.Id == 251); // ID
var dataEntry = (IResourceData)stringEntry.Entries.First(e => e.Id == 1033); // Lang ID
byte[] content = ((AsmResolver.DataSegment)dataEntry.Contents).Data;
List<string> stringlist = GetStringResource(251, content); private List<string> GetStringResource(int name, byte[] bytesIn)
{
List<string> result = new List<string>();
MemoryStream ms = new MemoryStream();
if (bytesIn.Length > 0)
{
BinaryWriter writer = new BinaryWriter(ms);
char[] OldBinary = Encoding.Unicode.GetString(bytesIn).ToCharArray();
int offset = 0;
for (int index = 0; index <= 15; index++)
{
if (Convert.ToInt32(OldBinary[offset]) != 0)
{
int length = OldBinary[offset];
offset += 1;
if (length > 0)
{
int stringID = (name - 1) * 16 + index;
writer.Write(stringID);
writer.Write(length);
int inner = offset;
while (inner < offset + length)
{
writer.Write(OldBinary[inner]);
inner += 1;
}
}
offset += length;
}
else
{
offset += 1;
}
}
ms.Position = 0;
}
if (ms != null && ms.Length > 0)
{
BinaryReader reader = new BinaryReader(ms);
while (ms.Position < ms.Length)
{
int stringID = reader.ReadInt32();
int length = reader.ReadInt32();
char[] buff = reader.ReadChars(length);
Console.WriteLine(stringID.ToString() + ":" + new string(buff));
result.Add(new string(buff));
}
}
return result;
} |
Nice, does that mean your issue has been resolved ? |
yes, thank you very much! |
private byte[] WriteStringResource(int name, byte[] bytesIn, Dictionary<string, string> UpdateString)
{
MemoryStream ms = new MemoryStream();
if (bytesIn.Length > 0)
{
BinaryWriter writer = new BinaryWriter(ms, Encoding.Unicode);
char[] OldBinary = Encoding.Unicode.GetString(bytesIn).ToCharArray();
int oldOffset = 0;
int newOffset = 0;
for (int index = 0; index <= 15; index++)
{
try
{
if (Convert.ToInt32(OldBinary[oldOffset]) != 0)
{
int length = OldBinary[oldOffset];
oldOffset += 1;
newOffset += 1;
if (length > 0)
{
int stringID = (name - 1) * 16 + index;
if (UpdateString.ContainsKey(stringID.ToString()))
{
writer.Write((short)(UpdateString[stringID].Length));
writer.Write(Encoding.Unicode.GetBytes(UpdateString[stringID]));
newOffset += UpdateString[stringID].Length;
}
else
{
writer.Write((short)length);
int inner = oldOffset;
while (inner < oldOffset + length)
{
writer.Write(OldBinary[inner]);
inner += 1;
}
}
oldOffset += length;
}
}
else
{
writer.Write(new byte[] {0, 0});
oldOffset += 1;
newOffset += 1;
}
}
catch (Exception ex)
{
}
}
ms.Position = 0;
}
return ms.ToArray();
} Dictionary<string, string> UpdateString = new Dictionary<string, string>() |
For example, this file: C:\Windows\Branding\Basebrd\en-US\basebrd.dll.mui, I want change the 251 resourceId content to "Preview-Version":
The text was updated successfully, but these errors were encountered: