Discussion:
PInvoke + Prevent Piracy
Girish Jain
2009-04-29 15:44:37 UTC
Permalink
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
Girish Jain
2009-04-29 15:57:28 UTC
Permalink
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

===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
Adam Tuliper
2009-04-29 15:55:51 UTC
Permalink
Just to ask.. why go through the troubles of preventing only copying by
modifying a file (which a virus scanner may prevent as suspiscious activity
anyways depending on how you do it of course) - rather than an easier but
probably as effective technique others already use.. such as hidden registry
values.. etc. Im assuming your app isn't signed otherwise you're changing
checksum (although ways around that) unless you are dealing with native
code.

Either way you are dealing with probably a one byte patch on your executable
in the validation routines return code by anyone with any reverse
engineering experience. So the argument is to protect against most users -
in that case why not just use hidden data in registry (or hidden file) that
is based on machine specific data. Even if those values/files are copied to
other machines they won't work because of your validation function and
you've saved yourself the headaches with modifying your own executables at
runtime.. and both techniques have similiar success and downfalls, but one
way you don't worry about that extra code.
Post by Girish Jain
Hello All,
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
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
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.
1. Could you please suggest the error in my approach for calling
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
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
Girish Jain
2009-05-03 15:59:56 UTC
Permalink
I am currently using the approach of using hidden registry values (with plain text hard coded values) and thought that it would be easy to crack... and therefore, was looking for another approach which would be more difficult to break and would make my life easy in distributing my application....

Although, as you pointed out, both the approaches have similar plus and minus points... I am yet to figure out a solution which would make my life easy with respect to distributing my application.

Any pointers would be of great help...


Cheers,
Girish Jain

----------------------------------------
Date: Wed, 29 Apr 2009 11:55:51 -0400
Subject: Re: [ADVANCED-DOTNET] PInvoke + Prevent Piracy
Just to ask.. why go through the troubles of preventing only copying by
modifying a file (which a virus scanner may prevent as suspiscious activity
anyways depending on how you do it of course) - rather than an easier but
probably as effective technique others already use.. such as hidden registry
values.. etc. Im assuming your app isn't signed otherwise you're changing
checksum (although ways around that) unless you are dealing with native
code.
Either way you are dealing with probably a one byte patch on your executable
in the validation routines return code by anyone with any reverse
engineering experience. So the argument is to protect against most users -
in that case why not just use hidden data in registry (or hidden file) that
is based on machine specific data. Even if those values/files are copied to
other machines they won't work because of your validation function and
you've saved yourself the headaches with modifying your own executables at
runtime.. and both techniques have similiar success and downfalls, but one
way you don't worry about that extra code.
Post by Girish Jain
Hello All,
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
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
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.
1. Could you please suggest the error in my approach for calling
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
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
_________________________________________________________________
Drag n’ drop—Get easy photo sharing with Windows Live™ Photos.

http://www.microsoft.com/india/windows/windowslive/photos.aspx
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
Sébastien Lorion
2009-05-03 16:03:37 UTC
Permalink
It's a losing battle .. even dongles get cracked. It just annoys your real
customers.
Sébastien
Post by Girish Jain
I am currently using the approach of using hidden registry values (with
plain text hard coded values) and thought that it would be easy to crack...
and therefore, was looking for another approach which would be more
difficult to break and would make my life easy in distributing my
application....
Although, as you pointed out, both the approaches have similar plus and
minus points... I am yet to figure out a solution which would make my life
easy with respect to distributing my application.
Any pointers would be of great help...
Cheers,
Girish Jain
----------------------------------------
Date: Wed, 29 Apr 2009 11:55:51 -0400
Subject: Re: [ADVANCED-DOTNET] PInvoke + Prevent Piracy
Just to ask.. why go through the troubles of preventing only copying by
modifying a file (which a virus scanner may prevent as suspiscious
activity
anyways depending on how you do it of course) - rather than an easier but
probably as effective technique others already use.. such as hidden
registry
values.. etc. Im assuming your app isn't signed otherwise you're changing
checksum (although ways around that) unless you are dealing with native
code.
Either way you are dealing with probably a one byte patch on your
executable
in the validation routines return code by anyone with any reverse
engineering experience. So the argument is to protect against most users
-
in that case why not just use hidden data in registry (or hidden file)
that
is based on machine specific data. Even if those values/files are copied
to
other machines they won't work because of your validation function and
you've saved yourself the headaches with modifying your own executables
at
runtime.. and both techniques have similiar success and downfalls, but
one
way you don't worry about that extra code.
Post by Girish Jain
Hello All,
In order to protect my application from piracy, I am taking the
following
Post by Girish Jain
1. Write some encrypted data to app executable file header at the time
of
Post by Girish Jain
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
Post by Girish Jain
specific data. On startup, it would generate the unique data and compare
it
Post by Girish Jain
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
Post by Girish Jain
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
Post by Girish Jain
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
Post by Girish Jain
A call to PInvoke function
'PESignature!PESignature.WinSDK::ImageGetCertificateData' has unbalanced
the
Post by Girish Jain
stack. This is likely because the managed PInvoke signature does not
match
Post by Girish Jain
the unmanaged target signature. Check that the calling convention and
parameters of the PInvoke signature match the target unmanaged
signature.
Post by Girish Jain
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.
Post by Girish Jain
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
Post by Girish Jain
data added at the index position 5 (while testing I could successfully
add
Post by Girish Jain
several data values).
I am not very sure about how to handle such API calls where we need to
pass
Post by Girish Jain
structure pointer as parameter.
1. Could you please suggest the error in my approach for calling
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
Post by Girish Jain
I safeguard my application setup (MSI) file more than anything else.
Could
Post by Girish Jain
you please suggest some other approach to prevent piracy wherein I need
not
Post by Girish Jain
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
===================================
View archives and manage your subscription(s) at
http://peach.ease.lsoft.com/archives
_________________________________________________________________
Drag n’ drop—Get easy photo sharing with Windows Live™ Photos.
http://www.microsoft.com/india/windows/windowslive/photos.aspx
===================================
View archives and manage your subscription(s) at
http://peach.ease.lsoft.com/archives
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
Sébastien Lorion
2009-05-04 11:35:29 UTC
Permalink
It's a losing battle .. even dongles get cracked. It just annoys your real
customers.
Sébastien
Post by Girish Jain
I am currently using the approach of using hidden registry values (with
plain text hard coded values) and thought that it would be easy to crack..
and therefore, was looking for another approach which would be more
difficult to break and would make my life easy in distributing my
application....
Although, as you pointed out, both the approaches have similar plus and
minus points... I am yet to figure out a solution which would make my life
easy with respect to distributing my application.
Any pointers would be of great help...
Cheers,
Girish Jain
----------------------------------------
Date: Wed, 29 Apr 2009 11:55:51 -0400
Subject: Re: [ADVANCED-DOTNET] PInvoke + Prevent Piracy
Just to ask.. why go through the troubles of preventing only copying by
modifying a file (which a virus scanner may prevent as suspiscious
activity
anyways depending on how you do it of course) - rather than an easier but
probably as effective technique others already use.. such as hidden
registry
values.. etc. Im assuming your app isn't signed otherwise you're changing
checksum (although ways around that) unless you are dealing with native
code.
Either way you are dealing with probably a one byte patch on your
executable
in the validation routines return code by anyone with any reverse
engineering experience. So the argument is to protect against most users
-
in that case why not just use hidden data in registry (or hidden file)
that
is based on machine specific data. Even if those values/files are copied
to
other machines they won't work because of your validation function and
you've saved yourself the headaches with modifying your own executables
at
runtime.. and both techniques have similiar success and downfalls, but
one
way you don't worry about that extra code.
Post by Girish Jain
Hello All,
In order to protect my application from piracy, I am taking the
following
Post by Girish Jain
1. Write some encrypted data to app executable file header at the time
of
Post by Girish Jain
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
Post by Girish Jain
specific data. On startup, it would generate the unique data and compare
it
Post by Girish Jain
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
Post by Girish Jain
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
Post by Girish Jain
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
Post by Girish Jain
A call to PInvoke function
'PESignature!PESignature.WinSDK::ImageGetCertificateData' has unbalanced
the
Post by Girish Jain
stack. This is likely because the managed PInvoke signature does not
match
Post by Girish Jain
the unmanaged target signature. Check that the calling convention and
parameters of the PInvoke signature match the target unmanaged
signature.
Post by Girish Jain
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.
Post by Girish Jain
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
Post by Girish Jain
data added at the index position 5 (while testing I could successfully
add
Post by Girish Jain
several data values).
I am not very sure about how to handle such API calls where we need to
pass
Post by Girish Jain
structure pointer as parameter.
1. Could you please suggest the error in my approach for calling
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
Post by Girish Jain
I safeguard my application setup (MSI) file more than anything else.
Could
Post by Girish Jain
you please suggest some other approach to prevent piracy wherein I need
not
Post by Girish Jain
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
===================================
View archives and manage your subscription(s) at
http://peach.ease.lsoft.com/archives
_________________________________________________________________
Drag n’ drop—Get easy photo sharing with Windows Live™ Photos.
http://www.microsoft.com/india/windows/windowslive/photos.aspx
===================================
View archives and manage your subscription(s) at
http://peach.ease.lsoft.com/archives
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives

===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
Girish Jain
2009-05-04 11:35:21 UTC
Permalink
I am currently using the approach of using hidden registry values (with plain text hard coded values) and thought that it would be easy to crack... and therefore, was looking for another approach which would be more difficult to break and would make my life easy in distributing my application....

Although, as you pointed out, both the approaches have similar plus and minus points... I am yet to figure out a solution which would make my life easy with respect to distributing my application.

Any pointers would be of great help...


Cheers,
Girish Jain

----------------------------------------
Date: Wed, 29 Apr 2009 11:55:51 -0400
Subject: Re: [ADVANCED-DOTNET] PInvoke + Prevent Piracy
Just to ask.. why go through the troubles of preventing only copying by
modifying a file (which a virus scanner may prevent as suspiscious activity
anyways depending on how you do it of course) - rather than an easier but
probably as effective technique others already use.. such as hidden registry
values.. etc. Im assuming your app isn't signed otherwise you're changing
checksum (although ways around that) unless you are dealing with native
code.
Either way you are dealing with probably a one byte patch on your executable
in the validation routines return code by anyone with any reverse
engineering experience. So the argument is to protect against most users -
in that case why not just use hidden data in registry (or hidden file) that
is based on machine specific data. Even if those values/files are copied to
other machines they won't work because of your validation function and
you've saved yourself the headaches with modifying your own executables at
runtime.. and both techniques have similiar success and downfalls, but one
way you don't worry about that extra code.
Post by Girish Jain
Hello All,
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
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
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 ie.
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.
1. Could you please suggest the error in my approach for calling
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
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
_________________________________________________________________
Drag n’ drop—Get easy photo sharing with Windows Live™ Photos.

http://www.microsoft.com/india/windows/windowslive/photos.aspx
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives

===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
Benjamin Schwehn
2009-04-29 18:58:23 UTC
Permalink
Post by Girish Jain
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;
Shot in the dark:

shouldn't pdword pinvoked be UInt32 or IntPtr, not long?

A quick test with the P/Invoke interop assistent[1] converts this:

BOOL
PVOID
ImageGetCertificateData(
IN HANDLE FileHandle,
IN DWORD CertificateIndex,
OUT PVOID Certificate,
IN OUT PDWORD RequiredLength
);


to this:

[System.Runtime.InteropServices.DllImportAttribute("<Unknown>",
EntryPoint="ImageGetCertificateData")]
public static extern System.IntPtr
ImageGetCertificateData(System.IntPtr FileHandle, uint CertificateIndex,
System.IntPtr Certificate, ref uint RequiredLength) ;

Same with WIN_CERTIFICATE, WORD -> ushort:


public struct WIN_CERTIFICATE {

/// DWORD->unsigned int
public uint dwLength;

/// WORD->unsigned short
public ushort wRevision;

/// WORD->unsigned short
public ushort wCertificateType;

/// BYTE[1]

[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst=1, ArraySubType=System.Runtime.InteropServices.UnmanagedType.I1)]
public byte[] bCertificate;
}


Apart from that I agree with Adam, seems to be too much trouble for an
easily bypassed protection.


Ben

[1]http://www.codeplex.com/clrinterop/Release/ProjectReleases.aspx?ReleaseId=14120

===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
Girish Jain
2009-05-03 16:06:43 UTC
Permalink
Hi Ben,

Your shot has hit the right target... You are correct. I have modified the signature and is able to call the method correctly and the method call succeeds. Now, the next issue I am facing is with retrieving the returned data.

The method populates the structure. When I try to convert the structure pointer back to a managed type instance using Marshal.PtrToStructure, it does not succeed and rather gives me some FatalEngineExecution exception. I dont have experience with COM programming and therefore, having issues with COM Interop with .NET.

I am writing this mail from home and dont have the latest working code as of now. I shall post the latest code at the first possible opportunity.

Thanks a lot


Cheers,
Girish Jain

----------------------------------------
Date: Wed, 29 Apr 2009 20:58:23 +0200
Subject: Re: [ADVANCED-DOTNET] PInvoke + Prevent Piracy
Post by Girish Jain
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;
shouldn't pdword pinvoked be UInt32 or IntPtr, not long?
BOOL
PVOID
ImageGetCertificateData(
IN HANDLE FileHandle,
IN DWORD CertificateIndex,
OUT PVOID Certificate,
IN OUT PDWORD RequiredLength
);
[System.Runtime.InteropServices.DllImportAttribute("",
EntryPoint="ImageGetCertificateData")]
public static extern System.IntPtr
ImageGetCertificateData(System.IntPtr FileHandle, uint CertificateIndex,
System.IntPtr Certificate, ref uint RequiredLength) ;
public struct WIN_CERTIFICATE {
/// DWORD->unsigned int
public uint dwLength;
/// WORD->unsigned short
public ushort wRevision;
/// WORD->unsigned short
public ushort wCertificateType;
/// BYTE[1]
[System.Runtime.InteropServices.MarshalAsAttribute(System.Runtime.InteropServices.UnmanagedType.ByValArray,
SizeConst=1, ArraySubType=System.Runtime.InteropServices.UnmanagedType.I1)]
public byte[] bCertificate;
}
Apart from that I agree with Adam, seems to be too much trouble for an
easily bypassed protection.
Ben
[1]http://www.codeplex.com/clrinterop/Release/ProjectReleases.aspx?ReleaseId=14120
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
_________________________________________________________________
Live Search extreme As India feels the heat of poll season, get all the info you need on the MSN News Aggregator
http://news.in.msn.com/National/indiaelections2009/aggregator/default.aspx
===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
Benjamin Schwehn
2009-05-03 17:36:48 UTC
Permalink
Post by Girish Jain
The method populates the structure. When I try to convert the
structure pointer back to a managed type instance using
Marshal.PtrToStructure,
If your problem is related to marshaling the certificate data,
have you tried using Marshal.Copy(IntPtr, byte[], Int32, Int32) on the
bCertificate IntPtr into a managed byte[dwLength]? Or do you not succeed
getting a WINCERTIFICATE struct from OUT LPWIN_CERTIFICATE Certificate?

Ben

===================================
View archives and manage your subscription(s) at http://peach.ease.lsoft.com/archives
Loading...