I seem to be failing to find the correct answer to what I am trying to do here.
In my C# code, I would like to extract resources from another executable that would be passed by user prompt. The other executable would be a native PE file.
As an example, I need to pull the KDATA\106 resource from this PE file (sample.exe). This is what it looks like in ResourceHacker.

I seem to be only able to find info on how to extract from my program, or parsing from another project.
I ended up marshalling the code and handling this as if it was C++.
One important thing to note about FindResource() is that it expects the lpName to be prepended with # if you pass it a string instead of an integer. MSDN Page
If the first character of the string is a pound sign (#), the remaining characters represent a decimal number that specifies the integer identifier of the resource's name or type. For example, the string "#258" represents the integer identifier 258.
First I marshal out all of the important functions from kernel32.dll in a separate class, then call the resource by name and type. (I grabbed most of this class from a blog that I cannot find again, will link if I locate it again.) Note that I have marshaled the parameters of FindResource as strings and not integers, for simplicity in C# (no need for hacks with MAKEINTRESOURCE).
ResourceManager.cs
class ResourceManager
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
[DllImport("Kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr LoadLibrary(string lpFileName);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr FindResource(IntPtr hModule, string lpName, string lpType);
// public static extern IntPtr FindResource(IntPtr hModule, int lpName, uint lpType);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr LockResource(IntPtr hResData);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool EnumResourceNames(IntPtr hModule, string lpType, IntPtr lpEnumFunc, IntPtr lParam);
public static byte[] GetResourceFromExecutable(string lpFileName, string lpName, string lpType)
{
IntPtr hModule = LoadLibrary(lpFileName);
if (hModule != IntPtr.Zero)
{
IntPtr hResource = FindResource(hModule, lpName, lpType);
if (hResource != IntPtr.Zero)
{
uint resSize = SizeofResource(hModule, hResource);
IntPtr resData = LoadResource(hModule, hResource);
if (resData != IntPtr.Zero)
{
byte[] uiBytes = new byte[resSize];
IntPtr ipMemorySource = LockResource(resData);
Marshal.Copy(ipMemorySource, uiBytes, 0, (int)resSize);
return uiBytes;
}
}
}
return null;
}
}
Main.cs
public Main(){
string path = @"C:\sample.exe";
// Get the raw bytes of the resource
byte[] resource = ResourceManager.GetResourceFromExecutable(path, "#106", "KDATA");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With