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

Commit

Permalink
Update documentation for v2.1.3, including minor optimisations for PE…
Browse files Browse the repository at this point in the history
…FileExports
  • Loading branch information
sadreck committed Jul 16, 2023
1 parent 0b01448 commit eb642ed
Show file tree
Hide file tree
Showing 4 changed files with 18 additions and 30 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Spartacus Changelog

## v2.1.3

* `[Update]` Proxy `--action exports` now supports wildcard DLL paths like `--dll C:\Windows\System32\*.dll` and also displays forwarded functions.
* `[Fix]` Rewrite PE file exporter from scratch.

## v2.1.2

* `[New]` Added `--action exports` to `--mode proxy` that lists a file's exports, functionality similar to `dumpbin.exe /exports`.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ To use this feature, simply run Spartacus with `--detect`.
| `dll`, `com` | `--existing` | Switch to indicate that Spartacus should process an existing ProcMon event log file (PML). To indicate the event log file use --pml, useful when you have been running ProcMon for hours or used it in Boot Logging. |
| `dll` | `--all` | By default any DLLs in the Windows or Program Files directories will be skipped. Use this to include those directories in the output. |
| `proxy` | `--ghidra` | Path to Ghidra's 'analyzeHeadless.bat' file. Used when you want to proxy specific functions rather than just `DllMain`. |
| `proxy` | `--dll` | Path to the DLL you want to proxy, and can include multiple instances of this argument. |
| `proxy` | `--dll` | Path to the DLL you want to proxy, and can include multiple instances of this argument. In addition, can also contain wildcards like `C:\Windows\System32\*.dll` - however all paths have to end in `*.dll`. |
| `proxy` | `--overwrite` | If the `--solution` path already exists, use this flag to overwrite it. |
| `proxy` | `--only` | Generate proxy functions only for functions defined in this variable. Values are comma separated like `'WTSFreeMemory,WTSFreeMemoryExA,WTSSetUserConfigA'`. |
| `proxy` | `--action` | Default action is to generate a VS solution. `--action prototypes`, takes as input a Windows SDK folder and parses *.h files in order to generate a database of function prototypes. `--action exports` displays a DLL's export functions and when complimented with `--prototypes` it will display if the function definition has been pre-generated. |
Expand Down
4 changes: 2 additions & 2 deletions Spartacus/Properties/AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("2.1.2.0")]
[assembly: AssemblyFileVersion("2.1.2.0")]
[assembly: AssemblyVersion("2.1.3.0")]
[assembly: AssemblyFileVersion("2.1.3.0")]
37 changes: 10 additions & 27 deletions Spartacus/Utils/PEFileExports.cs
Original file line number Diff line number Diff line change
Expand Up @@ -213,11 +213,7 @@ public List<FileExport> Extract(string dllFile)

private List<FileExport> GenerateResult(uint[] ordinals, string[] functions, string[] forwards)
{
if (ordinals == null || functions == null || forwards == null)
{
return new();
}
else if (ordinals.Length == 0 || functions.Length == 0 || forwards.Length == 0)
if (ordinals.Length == 0 || functions.Length == 0 || forwards.Length == 0)
{
return new();
}
Expand All @@ -241,7 +237,8 @@ private string[] ExtractTable(EXPORT_DIRECTORY_TABLE exportTable, uint sectionBa
output[i] = "";
// If the index[i] is within the boundaries of the export table (virtual address + size), extract the string. Otherwise
// it's a reference to a function offset rather than a forward.
if (index[i] > 0 && index[i] >= exportDataTable.VirtualAddress && index[i] <= (exportDataTable.VirtualAddress + exportDataTable.Size))
bool betweenBounds = index[i] >= exportDataTable.VirtualAddress && index[i] <= (exportDataTable.VirtualAddress + exportDataTable.Size);
if (index[i] > 0 && betweenBounds)
{
output[i] = ReadString(index[i] - sectionBaseOffset);
}
Expand All @@ -266,37 +263,25 @@ private string ReadString(uint offset)
List<byte> output = new();
do
{
byte c = reader.ReadByte();
if (c == 0x00)
{
break;
}
output.Add(c);
} while (true);

output.Add(reader.ReadByte());
} while (output.Last() != 0x00);
output.RemoveAt(output.Count - 1); // Last added byte was 0x00, remove it.

return Encoding.ASCII.GetString(output.ToArray());
}

private uint[] ExtractTableIndex(uint offset, uint size)
{
uint[] output = new uint[size];
stream.Seek(offset, SeekOrigin.Begin);
for (int i = 0; i < size; i++)
{
output[i] = reader.ReadUInt32();
}
return output;
return output.Select(o => reader.ReadUInt32()).ToArray();
}

private uint[] ExtractOrdinals(EXPORT_DIRECTORY_TABLE exportTable, uint sectionBaseOffset)
{
uint[] output = new uint[exportTable.NumberOfNamePointers];
stream.Seek(exportTable.OrdinalTableRVA - sectionBaseOffset, SeekOrigin.Begin);
for (int i = 0; i < output.Length; i++)
{
output[i] = reader.ReadUInt16() + exportTable.OrdinalBase;
}
return output;
return output.Select(o => reader.ReadUInt16() + exportTable.OrdinalBase).ToArray();
}

private EXPORT_DIRECTORY_TABLE GetExportDirectoryTable(uint offset)
Expand Down Expand Up @@ -345,15 +330,13 @@ private bool IsPEPlus()

private IMAGE_FILE_HEADER GetImageFileHeader()
{
IMAGE_FILE_HEADER header = new();

// Get the PE location - https://learn.microsoft.com/en-us/windows/win32/debug/pe-format#signature-image-only
stream.Seek(SIZEOF_IMAGE_DOS_HEADER, SeekOrigin.Begin);
uint executableHeaderOffset = reader.ReadUInt32() + 4; // +4 as the first 4 bytes are PE\0\0

// Navigate to that offset.
stream.Seek(executableHeaderOffset, SeekOrigin.Begin);
return BytesToStructure<IMAGE_FILE_HEADER>(reader.ReadBytes(Marshal.SizeOf(header)));
return ReadStructFromStream<IMAGE_FILE_HEADER>();
}

private T ReadStructFromStream<T>()
Expand Down

0 comments on commit eb642ed

Please sign in to comment.