Girish Jain
2009-04-29 15:44:37 UTC
Hello All,
In order to protect my application from piracy, I am taking the following approach:
1. Write some encrypted data to app executable file header at the time of application installation.
2. The logic for generating this data has to consider machine specific details (I am yet to select upon the data values)
3. The app executable would also have the same logic for generating machine specific data. On startup, it would generate the unique data and compare it with the data from its own header, (of course after decrypting!!)
4. If the data values match, application will proceed, otherwise not.
This would ensure that merely copying the application exe from one machine to another would not work.
For this purpose, I need to add some data to PE file and then later retrieve the same using C#. I am using the following ImgHelp APIs for the purpose :
ImageAddCertificate
ImageGetCertificateData
I am able to add data to PE file and ImageAddCertificate function call succeeds. While calling ImageGetCertificateData to retrieve the data, I am getting errors. It gives the following error:
A call to PInvoke function 'PESignature!PESignature.WinSDK::ImageGetCertificateData' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
I am struggling with using PInvoke to call ImageGetCertificateData function. The functions have been defined as follows.
static class WinSDK
{
[DllImport("Imagehlp.dll", SetLastError=true)]
static public extern bool ImageAddCertificate(SafeFileHandle HANDLE, ref WINCERTIFICATE certData, out long index);
[DllImport("Imagehlp.dll", SetLastError = true)]
static public extern bool ImageGetCertificateData(SafeFileHandle FileHandle, long CertificateIndex, out IntPtr CertData, out long RequiredLength);
}
struct WINCERTIFICATE
{
public UInt32 dwLength;
public int wRevision;
public int wCertificateType;
public byte[] bCertificate;
}
Unmanaged counterpart
--------------------------------------------------------
BOOL
IMAGEAPI
ImageGetCertificateData(
IN HANDLE FileHandle,
IN DWORD CertificateIndex,
OUT LPWIN_CERTIFICATE Certificate,
IN OUT PDWORD RequiredLength
);
typedef struct _WIN_CERTIFICATE
{
DWORD dwLength;
WORD wRevision;
WORD wCertificateType; // WIN_CERT_TYPE_xxx
BYTE bCertificate[ANYSIZE_ARRAY];
} WIN_CERTIFICATE, *LPWIN_CERTIFICATE;
--------------------------------------------------------
Following is the button click event handler code (in test project) which attempts to retrieves data from the PE file…
private unsafe void lblGetSignatureData_Click(object sender, EventArgs e)
{
FileStream fs = null;
IntPtr certPtr;
unsafe
{
try
{
fs = File.Open(this._FilePath, FileMode.Open, FileAccess.Read);
// Now retrieve cert data
WINCERTIFICATE certSelect = new WINCERTIFICATE();
long ReqLength = 55;
certPtr = Marshal.AllocHGlobal(Marshal.SizeOf(certSelect));
Marshal.StructureToPtr(certSelect, certPtr, false);
WinSDK.ImageGetCertificateData(fs.SafeFileHandle, 5, out certPtr, out ReqLength);
MessageBox.Show(Encoding.ASCII.GetString(certSelect.bCertificate));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
fs.Close();
fs.Dispose();
fs = null;
}
}
}
The data which I had initially written to the PE file was of length 55 i.e. byte array length 55. The SDK function expects the data structure to be pre-initialized with the required buffer. Also, I am trying to retrieve the data added at the index position 5 (while testing I could successfully add several data values).
I am not very sure about how to handle such API calls where we need to pass structure pointer as parameter.
Questions:
1. Could you please suggest the error in my approach for calling ImageGetCertificateData function. Request you to validate the following:
a. Method declaration in Win SDK class
b. WINCERTIFICATE struct definition
c. Code for initializing the unmanaged memory for data structure and passing it as input parameter to function call
2. The current approach for safeguarding the application would require that I safeguard my application setup (MSI) file more than anything else. Could you please suggest some other approach to prevent piracy wherein I need not even protect MSI file and can freely distribute the same?
Would highly appreciate your suggestions/ideas. Thanks in advance.
MSDN Link for function http://msdn.microsoft.com/en-us/library/ms680154(VS.85).aspx
-Girish Jain
P.S. Due to certain issues you can expect delay in response from my side
_________________________________________________________________
Windows Live Messenger. Multitasking at its finest.
http://www.microsoft.com/india/windows/windowslive/messenger.aspx
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
In order to protect my application from piracy, I am taking the following approach:
1. Write some encrypted data to app executable file header at the time of application installation.
2. The logic for generating this data has to consider machine specific details (I am yet to select upon the data values)
3. The app executable would also have the same logic for generating machine specific data. On startup, it would generate the unique data and compare it with the data from its own header, (of course after decrypting!!)
4. If the data values match, application will proceed, otherwise not.
This would ensure that merely copying the application exe from one machine to another would not work.
For this purpose, I need to add some data to PE file and then later retrieve the same using C#. I am using the following ImgHelp APIs for the purpose :
ImageAddCertificate
ImageGetCertificateData
I am able to add data to PE file and ImageAddCertificate function call succeeds. While calling ImageGetCertificateData to retrieve the data, I am getting errors. It gives the following error:
A call to PInvoke function 'PESignature!PESignature.WinSDK::ImageGetCertificateData' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.
I am struggling with using PInvoke to call ImageGetCertificateData function. The functions have been defined as follows.
static class WinSDK
{
[DllImport("Imagehlp.dll", SetLastError=true)]
static public extern bool ImageAddCertificate(SafeFileHandle HANDLE, ref WINCERTIFICATE certData, out long index);
[DllImport("Imagehlp.dll", SetLastError = true)]
static public extern bool ImageGetCertificateData(SafeFileHandle FileHandle, long CertificateIndex, out IntPtr CertData, out long RequiredLength);
}
struct WINCERTIFICATE
{
public UInt32 dwLength;
public int wRevision;
public int wCertificateType;
public byte[] bCertificate;
}
Unmanaged counterpart
--------------------------------------------------------
BOOL
IMAGEAPI
ImageGetCertificateData(
IN HANDLE FileHandle,
IN DWORD CertificateIndex,
OUT LPWIN_CERTIFICATE Certificate,
IN OUT PDWORD RequiredLength
);
typedef struct _WIN_CERTIFICATE
{
DWORD dwLength;
WORD wRevision;
WORD wCertificateType; // WIN_CERT_TYPE_xxx
BYTE bCertificate[ANYSIZE_ARRAY];
} WIN_CERTIFICATE, *LPWIN_CERTIFICATE;
--------------------------------------------------------
Following is the button click event handler code (in test project) which attempts to retrieves data from the PE file…
private unsafe void lblGetSignatureData_Click(object sender, EventArgs e)
{
FileStream fs = null;
IntPtr certPtr;
unsafe
{
try
{
fs = File.Open(this._FilePath, FileMode.Open, FileAccess.Read);
// Now retrieve cert data
WINCERTIFICATE certSelect = new WINCERTIFICATE();
long ReqLength = 55;
certPtr = Marshal.AllocHGlobal(Marshal.SizeOf(certSelect));
Marshal.StructureToPtr(certSelect, certPtr, false);
WinSDK.ImageGetCertificateData(fs.SafeFileHandle, 5, out certPtr, out ReqLength);
MessageBox.Show(Encoding.ASCII.GetString(certSelect.bCertificate));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
fs.Close();
fs.Dispose();
fs = null;
}
}
}
The data which I had initially written to the PE file was of length 55 i.e. byte array length 55. The SDK function expects the data structure to be pre-initialized with the required buffer. Also, I am trying to retrieve the data added at the index position 5 (while testing I could successfully add several data values).
I am not very sure about how to handle such API calls where we need to pass structure pointer as parameter.
Questions:
1. Could you please suggest the error in my approach for calling ImageGetCertificateData function. Request you to validate the following:
a. Method declaration in Win SDK class
b. WINCERTIFICATE struct definition
c. Code for initializing the unmanaged memory for data structure and passing it as input parameter to function call
2. The current approach for safeguarding the application would require that I safeguard my application setup (MSI) file more than anything else. Could you please suggest some other approach to prevent piracy wherein I need not even protect MSI file and can freely distribute the same?
Would highly appreciate your suggestions/ideas. Thanks in advance.
MSDN Link for function http://msdn.microsoft.com/en-us/library/ms680154(VS.85).aspx
-Girish Jain
P.S. Due to certain issues you can expect delay in response from my side
_________________________________________________________________
Windows Live Messenger. Multitasking at its finest.
http://www.microsoft.com/india/windows/windowslive/messenger.aspx
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives