From 18464bacff870f1c432cc67b63c347a9fb6cfab6 Mon Sep 17 00:00:00 2001 From: Natalia Portillo Date: Sat, 3 Mar 2018 06:01:35 +0000 Subject: [PATCH] Add decoding RT_STRING resources from NE (Windows and OS/2), and appropriate GUI. --- exeinfogui/NE/PanelNeStrings.xeto | 8 +++ exeinfogui/NE/PanelNeStrings.xeto.cs | 54 ++++++++++++++++ exeinfogui/NE/TabNeResources.xeto.cs | 6 ++ libexeinfo/NE/GetStrings.cs | 96 ++++++++++++++++++++++++++++ libexeinfo/NE/NE.cs | 45 ++++++++----- libexeinfo/libexeinfo.csproj | 1 + 6 files changed, 193 insertions(+), 17 deletions(-) create mode 100644 exeinfogui/NE/PanelNeStrings.xeto create mode 100644 exeinfogui/NE/PanelNeStrings.xeto.cs create mode 100644 libexeinfo/NE/GetStrings.cs diff --git a/exeinfogui/NE/PanelNeStrings.xeto b/exeinfogui/NE/PanelNeStrings.xeto new file mode 100644 index 0000000..f113ff0 --- /dev/null +++ b/exeinfogui/NE/PanelNeStrings.xeto @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/exeinfogui/NE/PanelNeStrings.xeto.cs b/exeinfogui/NE/PanelNeStrings.xeto.cs new file mode 100644 index 0000000..29cabf8 --- /dev/null +++ b/exeinfogui/NE/PanelNeStrings.xeto.cs @@ -0,0 +1,54 @@ +// +// PanelNeStrings.xeto.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2017 Copyright © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using Eto.Forms; +using Eto.Serialization.Xaml; + +namespace exeinfogui.NE +{ + public class PanelNeStrings : Panel + { + GridView treeStrings; + + public PanelNeStrings() + { + XamlReader.Load(this); + + treeStrings.Columns.Add(new GridColumn + { + DataCell = new TextBoxCell {Binding = Binding.Property(r => r)}, + HeaderText = "String" + }); + } + + public void Update(byte[] data, libexeinfo.NE.TargetOS targetOs) + { + treeStrings.DataStore = targetOs == libexeinfo.NE.TargetOS.OS2 + ? libexeinfo.NE.GetOs2Strings(data) + : libexeinfo.NE.GetWindowsStrings(data); + } + } +} \ No newline at end of file diff --git a/exeinfogui/NE/TabNeResources.xeto.cs b/exeinfogui/NE/TabNeResources.xeto.cs index 016d77e..f7c5949 100644 --- a/exeinfogui/NE/TabNeResources.xeto.cs +++ b/exeinfogui/NE/TabNeResources.xeto.cs @@ -39,6 +39,7 @@ namespace exeinfogui.NE TreeGridItemCollection treeData; TreeGridView treeResources; PanelWin16Version panelWin16Version; + PanelNeStrings panelNeStrings; public TabNeResources() { @@ -52,6 +53,7 @@ namespace exeinfogui.NE treeResources.SelectionChanged += TreeResourcesOnSelectionChanged; panelWin16Version = new PanelWin16Version(); + panelNeStrings = new PanelNeStrings(); } public void Update(IEnumerable resourceTypes, libexeinfo.NE.TargetOS os) @@ -98,6 +100,10 @@ namespace exeinfogui.NE pnlResource.Content = panelWin16Version; panelWin16Version.Update(data); break; + case "RT_STRING": + pnlResource.Content = panelNeStrings; + panelNeStrings.Update(data, (libexeinfo.NE.TargetOS)((TreeGridItem)treeResources.SelectedItem).Values[4]); + break; default: pnlResource.Content = null; break; diff --git a/libexeinfo/NE/GetStrings.cs b/libexeinfo/NE/GetStrings.cs new file mode 100644 index 0000000..0ef4d26 --- /dev/null +++ b/libexeinfo/NE/GetStrings.cs @@ -0,0 +1,96 @@ +// +// GetStrings.cs +// +// Author: +// Natalia Portillo +// +// Copyright (c) 2017 Copyright © Claunia.com +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +using System; +using System.Collections.Generic; +using System.Text; + +namespace libexeinfo +{ + public partial class NE + { + public static IEnumerable GetWindowsStrings(ResourceType resource) + { + List strings = new List(); + + foreach(Resource r in resource.resources) strings.AddRange(GetWindowsStrings(r.data)); + + return strings; + } + + public static IEnumerable GetWindowsStrings(byte[] data) + { + List strings = new List(); + + int pos = 0; + while(pos < data.Length) + { + byte len = data[pos++]; + + if(len == 0) break; + + byte[] buffer = new byte[len]; + Array.Copy(data, pos, buffer, 0, len); + string str = Encoding.Default.GetString(buffer); + if(!string.IsNullOrWhiteSpace(str)) strings.Add(str); + pos += len; + } + + return strings; + } + + public static IEnumerable GetOs2Strings(ResourceType resource) + { + List strings = new List(); + + foreach(Resource r in resource.resources) strings.AddRange(GetOs2Strings(r.data)); + + return strings; + } + + public static IEnumerable GetOs2Strings(byte[] data) + { + List strings = new List(); + + // Skip resource header + int pos = 2; + while(pos < data.Length) + { + byte len = data[pos++]; + + if(len == 0) break; + + byte[] buffer = new byte[len]; + Array.Copy(data, pos, buffer, 0, len); + string str = StringHandlers.CToString(buffer, Encoding.Default); + if(!string.IsNullOrWhiteSpace(str)) strings.Add(str); + pos += len; + } + + return strings; + } + } +} \ No newline at end of file diff --git a/libexeinfo/NE/NE.cs b/libexeinfo/NE/NE.cs index 59929a2..fbf1398 100644 --- a/libexeinfo/NE/NE.cs +++ b/libexeinfo/NE/NE.cs @@ -95,9 +95,9 @@ namespace libexeinfo ? Architecture.I286 : Architecture.I86 }; - public OperatingSystem RequiredOperatingSystem { get; private set; } - public IEnumerable Strings { get; private set; } - public IEnumerable Segments { get; private set; } + public OperatingSystem RequiredOperatingSystem { get; private set; } + public IEnumerable Strings { get; private set; } + public IEnumerable Segments { get; private set; } void Initialize() { @@ -119,8 +119,8 @@ namespace libexeinfo Marshal.FreeHGlobal(hdrPtr); if(Header.signature != SIGNATURE) return; - Recognized = true; - Type = "New Executable (NE)"; + Recognized = true; + Type = "New Executable (NE)"; List strings = new List(); OperatingSystem reqOs = new OperatingSystem(); @@ -219,7 +219,8 @@ namespace libexeinfo Header.imported_names_offset <= resourceUpperLimit) resourceUpperLimit = Header.imported_names_offset; if(Header.resource_table_offset < resourceUpperLimit && Header.resource_table_offset != 0) - if(Header.target_os == TargetOS.Windows || Header.target_os == TargetOS.Win32) + if(Header.target_os == TargetOS.Windows || Header.target_os == TargetOS.Win32 || + Header.target_os == TargetOS.Unknown) { Resources = GetResources(BaseStream, BaseExecutable.Header.new_offset, Header.resource_table_offset, resourceUpperLimit); @@ -232,6 +233,13 @@ namespace libexeinfo Versions = GetVersions().ToArray(); strings.AddRange(from v in Versions from s in v.StringsByLanguage from k in s.Value select k.Value); + + foreach(ResourceType rtype in Resources.types) + { + if(rtype.name != "RT_STRING") continue; + + strings.AddRange(GetWindowsStrings(rtype)); + } } else if(Header.target_os == TargetOS.OS2 && segments != null && Header.resource_entries > 0) { @@ -298,6 +306,13 @@ namespace libexeinfo Resources.types[counter].resources = kvp.Value.OrderBy(r => r.id).ToArray(); counter++; } + + foreach(ResourceType rtype in Resources.types) + { + if(rtype.name != "RT_STRING") continue; + + strings.AddRange(GetOs2Strings(rtype)); + } } } @@ -393,14 +408,11 @@ namespace libexeinfo } } - if(!string.IsNullOrEmpty(ModuleName)) - strings.Add(ModuleName); - if(!string.IsNullOrEmpty(ModuleDescription)) - strings.Add(ModuleDescription); + if(!string.IsNullOrEmpty(ModuleName)) strings.Add(ModuleName); + if(!string.IsNullOrEmpty(ModuleDescription)) strings.Add(ModuleDescription); + + if(strings.Count > 0) Strings = strings.Distinct().OrderBy(s => s); - if(strings.Count > 0) - Strings = strings.Distinct().OrderBy(s => s); - if(segments == null) return; List libsegs = new List(); @@ -408,16 +420,15 @@ namespace libexeinfo { Segment libseg = new Segment { - Flags = $"{(SegmentFlags)(seg.dwFlags & SEGMENT_FLAGS_MASK)}", - Name = - ((SegmentType)(seg.dwFlags & SEGMENT_TYPE_MASK)) == SegmentType.Code ? ".text" : ".data", + Flags = $"{(SegmentFlags)(seg.dwFlags & SEGMENT_FLAGS_MASK)}", + Name = (SegmentType)(seg.dwFlags & SEGMENT_TYPE_MASK) == SegmentType.Code ? ".text" : ".data", Offset = seg.dwLogicalSectorOffset * 16, Size = seg.dwSegmentLength }; if(Header.target_os == TargetOS.OS2 && (seg.dwFlags & (int)SegmentFlags.Huge) == (int)SegmentFlags.Huge) libseg.Size *= 16; - + libsegs.Add(libseg); } diff --git a/libexeinfo/libexeinfo.csproj b/libexeinfo/libexeinfo.csproj index 754c682..4c9f932 100644 --- a/libexeinfo/libexeinfo.csproj +++ b/libexeinfo/libexeinfo.csproj @@ -56,6 +56,7 @@ +