Re: PInvoke + Prevent Piracy

Adam Tuliper <[email protected]> Wed, 29 Apr 2009 11:55:51 -0400
Newsgroups gmane.comp.windows.devel.dotnet.advanced
Message-ID <[email protected]>
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.







On Wed, Apr 29, 2009 at 11:44 AM, Girish Jain <[email protected]>wrote:

> 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