Skip to content
This repository has been archived by the owner on Feb 1, 2024. It is now read-only.

Commit

Permalink
Issue #1 - Replicate VERSIONINFO and timestomp target DLL
Browse files Browse the repository at this point in the history
  • Loading branch information
sadreck committed Mar 9, 2023
1 parent 4040fbb commit 526bc13
Show file tree
Hide file tree
Showing 8 changed files with 375 additions and 1 deletion.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
# Spartacus Changelog

## v1.2.0

* `[New]` Implement replication of `VERSIONINFO` and timestomping to match source file during solution compilation. (Issue #1)

## v1.1.1

* `[Fix]` Allow digits/symbols in --only-proxy command
Expand Down
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,8 @@ Create a proxy only for a specific export function.
--generate-proxy --ghidra C:\ghidra\support\analyzeHeadless.bat --dll C:\Windows\System32\userenv.dll --output-dir C:\Projects\spartacus-wtsapi32 --verbose --only-proxy "ExpandEnvironmentStringsForUserW"
```

**Note**: When generating proxies for export functions, the solution that is created also replicates `VERSIONINFO` and timestomps the target DLL to match the date of the source one (using PowerShell).

## Proxy DLL Template

Below is the template that is used when generating proxy DLLs, the generated `#pragma` statements are inserted by replacing the `%_PRAGMA_COMMENTS_%` string.
Expand Down
49 changes: 49 additions & 0 deletions Spartacus/Properties/Resources.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

127 changes: 127 additions & 0 deletions Spartacus/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,106 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved)
}
return TRUE;
}</value>
</data>
<data name="proxy.rc" xml:space="preserve">
<value>// Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#include "winres.h"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS

/////////////////////////////////////////////////////////////////////////////
// English (United Kingdom) resources

#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENG)
LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_UK

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE
BEGIN
"resource.h\0"
END

2 TEXTINCLUDE
BEGIN
"#include ""winres.h""\r\n"
"\0"
END

3 TEXTINCLUDE
BEGIN
"\r\n"
"\0"
END

#endif // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// Version
//

VS_VERSION_INFO VERSIONINFO
FILEVERSION %FILEVERSION_MAJOR%,%FILEVERSION_MINOR%,%FILEVERSION_REVISION%,%FILEVERSION_BUILD%
PRODUCTVERSION %PRODUCTVERSION_MAJOR%,%PRODUCTVERSION_MINOR%,%PRODUCTVERSION_REVISION%,%PRODUCTVERSION_BUILD%
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
#else
FILEFLAGS 0x0L
#endif
FILEOS 0x40004L
FILETYPE 0x2L
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "080904b0"
BEGIN
VALUE "CompanyName", "%COMPANYNAME%"
VALUE "FileDescription", "%FILEDESCRIPTION%"
VALUE "FileVersion", "%FILEVERSION%"
VALUE "InternalName", "%INTERNALNAME%"
VALUE "LegalCopyright", "%LEGALCOPYRIGHT%"
VALUE "OriginalFilename", "%ORIGINALNAME%"
VALUE "ProductName", "%PRODUCTNAME%"
VALUE "ProductVersion", "%PRODUCTVERSION%"
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x809, 1200
END
END

#endif // English (United Kingdom) resources
/////////////////////////////////////////////////////////////////////////////



#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif // not APSTUDIO_INVOKED</value>
</data>
<data name="proxy.sln" xml:space="preserve">
<value>Microsoft Visual Studio Solution File, Format Version 12.00
Expand Down Expand Up @@ -404,16 +504,43 @@ EndGlobal</value>
&lt;EnableUAC&gt;false&lt;/EnableUAC&gt;
&lt;ModuleDefinitionFile&gt;proxy.def&lt;/ModuleDefinitionFile&gt;
&lt;/Link&gt;
&lt;PostBuildEvent&gt;
&lt;Command&gt;powershell.exe -c (Get-ChildItem "$(TargetPath)").LastWriteTime = (Get-ChildItem "%SOURCEDLL%").LastWriteTime
powershell.exe -c (Get-ChildItem "$(TargetPath)").CreationTime = (Get-ChildItem "%SOURCEDLL%").CreationTime&lt;/Command&gt;
&lt;/PostBuildEvent&gt;
&lt;/ItemDefinitionGroup&gt;
&lt;ItemGroup&gt;
&lt;ClCompile Include="dllmain.cpp" /&gt;
&lt;/ItemGroup&gt;
&lt;ItemGroup&gt;
&lt;None Include="proxy.def" /&gt;
&lt;/ItemGroup&gt;
&lt;ItemGroup&gt;
&lt;ClInclude Include="resource.h" /&gt;
&lt;/ItemGroup&gt;
&lt;ItemGroup&gt;
&lt;ResourceCompile Include="proxy.rc" /&gt;
&lt;/ItemGroup&gt;
&lt;Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /&gt;
&lt;ImportGroup Label="ExtensionTargets"&gt;
&lt;/ImportGroup&gt;
&lt;/Project&gt;</value>
</data>
<data name="resource.h" xml:space="preserve">
<value>//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by proxy.rc

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 101
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1001
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
</value>
</data>
</root>
72 changes: 71 additions & 1 deletion Spartacus/Spartacus/ProxyDLLGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using static Spartacus.Spartacus.Models.FunctionSignature;
Expand Down Expand Up @@ -209,7 +210,22 @@ private bool GenerateSolution(string dllPath, Dictionary<string, FunctionSignatu
string proxySln = Resources.ResourceManager.GetString("proxy.sln");

Logger.Info("Generating proxy.vcxproj");
string proxyVCXProj = Resources.ResourceManager.GetString("proxy.vcxproj").Replace("%_NAME_%", projectName);
string proxyVCXProj = Resources.ResourceManager.GetString("proxy.vcxproj")
.Replace("%_NAME_%", projectName)
.Replace("%SOURCEDLL%", dllPath);

Logger.Info("Generating proxy.rc");
string proxyRC = "";
try
{
proxyRC = GenerateProxyRC(dllPath);
} catch (Exception e)
{
Logger.Error("Could not get file version information: " + e.Message);
}

Logger.Info("Generating resource.h");
string resourceH = Resources.ResourceManager.GetString("resource.h");

Logger.Info("Saving proxy.def...");
File.WriteAllText(Path.Combine(outputDirectory, "proxy.def"), proxyDefinitions);
Expand All @@ -223,9 +239,63 @@ private bool GenerateSolution(string dllPath, Dictionary<string, FunctionSignatu
Logger.Info("Saving proxy.vcxproj");
File.WriteAllText(Path.Combine(outputDirectory, "proxy.vcxproj"), proxyVCXProj);

Logger.Info("Saving resource.h");
File.WriteAllText(Path.Combine(outputDirectory, "resource.h"), resourceH);

Logger.Info("Saving proxy.rc");
// We are writing the data to this file as Unicode (UTF16 LE BOM), otherwise characters like the copyright symbol won't display correctly.
using (var f = File.Create(Path.Combine(outputDirectory, "proxy.rc")))
{
using (StreamWriter sw = new StreamWriter(f, Encoding.Unicode))
{
sw.Write(proxyRC);
}
}

return true;
}

private string GenerateProxyRC(string dllPath)
{
FileVersionInfo versionInfo = FileVersionInfo.GetVersionInfo(dllPath);

string proxyRC = Resources.ResourceManager.GetString("proxy.rc")
.Replace("%COMPANYNAME%", versionInfo.CompanyName)
.Replace("%FILEDESCRIPTION%", versionInfo.FileDescription)
.Replace("%INTERNALNAME%", versionInfo.InternalName)
.Replace("%LEGALCOPYRIGHT%", versionInfo.LegalCopyright)
.Replace("%ORIGINALNAME%", versionInfo.OriginalFilename)
.Replace("%PRODUCTNAME%", versionInfo.ProductName)
.Replace("%PRODUCTVERSION%", versionInfo.ProductVersion)
.Replace("%PRODUCTVERSION_MAJOR%", versionInfo.ProductMajorPart.ToString())
.Replace("%PRODUCTVERSION_MINOR%", versionInfo.ProductMinorPart.ToString())
.Replace("%PRODUCTVERSION_BUILD%", versionInfo.ProductBuildPart.ToString())
.Replace("%PRODUCTVERSION_REVISION%", versionInfo.ProductPrivatePart.ToString());

string fileVersion = versionInfo.FileVersion.Split(' ')[0];
proxyRC = proxyRC.Replace("%FILEVERSION%", fileVersion);

// For some reason FileVersion doesn't always match what is displayed when you view the file's properties.
string[] fileVersionParts = fileVersion.Split('.');

if (fileVersionParts.Length != 4)
{
fileVersionParts = new string[4];
fileVersionParts[0] = versionInfo.ProductMajorPart.ToString();
fileVersionParts[1] = versionInfo.ProductMinorPart.ToString();
fileVersionParts[2] = versionInfo.ProductBuildPart.ToString();
fileVersionParts[3] = versionInfo.ProductPrivatePart.ToString();
}

proxyRC = proxyRC
.Replace("%FILEVERSION_MAJOR%", fileVersionParts[0])
.Replace("%FILEVERSION_MINOR%", fileVersionParts[1])
.Replace("%FILEVERSION_BUILD%", fileVersionParts[2])
.Replace("%FILEVERSION_REVISION%", fileVersionParts[3]);

return proxyRC;
}

private void RunGhidra(string headlessAnalyserPath, string projectPath, string scriptPath, string dllPath)
{
Process p = new Process();
Expand Down
Loading

0 comments on commit 526bc13

Please sign in to comment.