Setup – Custom Action Type

Add Comment | Sep 18, 2008

I was modifying old setups lately, by directly editing them with Orca. It’s not such a great experience, but I really didn’t want to go through Dark for such simple modifications.

In the process, I found that one of the worst parts of the format is decoding the Type column in the CustomAction table. Because of that, I have coded a very simple application that tells me which options are selected when I input the number in the column. I hope you find it useful, it’s uploaded here: http://www.codeproject.com/KB/install/customactiondecoder.aspx

Recycle Bin

Add Comment | Aug 31, 2008

There’s something that we developers don’t seem to get about the users, and it’s that the file system is a quite complex beast to use. It provides order, yes, but at the expense of users getting lost on where their files are. And it gets worst, as there’s no easy way to solve this. In Windows, there’s only one key that will move your files to a well known location in a single key press: the Delete key. You probably know how it works: select a few files, hit Delete, and go find the selected files in the Recycle Bin.

My mother, on noticing this, started using the Recycle Bin as the place to store her information. She will find a file after minutes or hours of looking around, hit Delete and automatically know where the file will be next time she needs it. Also, the Recycle Bin is easily accessible from the desktop. That is, until one of my brothers gets a hold of her computer, notices that the Recycle Bin hasn’t been emptied in a long time, and wipe it out. There’s no coming back from that one…

Windows tried to fix this by introducing My Documents, and it failed. Most users will simply store everything in the desktop, and the reason for that is that it’s easy. My Documents sounds childish, and My Pictures, My Videos, etc really shouldn’t be contained in it. I mean, My Pictures are not a part of My Documents. My Documents are mostly Word and PDF files. My Pictures are images from friends and family. There’s no correlation between both kinds of files. Vista does a much better job of this, with the new Document structure. This structure actually makes sense and it’s easy to access from Windows Explorer at any time. It’s ordered, and it works.

That’s why I thought of my first shell extension, and I coded it over the weekend. With this extension, pressing F12 will redirect the selected documents to where they make sense: audio files go to Music, videos go to Videos, pictures go to Pictures, the rest go to Documents. This way I cover the glitch: I have a single key press separating my disorder from order. Plus, it’s not as dangerous as storing everything in the Recycle Bin.

I coded it as a Vista-specific dll, as the directory structure from Windows XP (and earlier) doesn’t make much sense to me, and I’m going to publish source and binaries as soon as I find a good place for them (probably CodeProject). It was a great learning experience (I’m not really used to native code), and I hope people will like it when I post it.

Update: Uploaded here if it survives moderation.

Setup - Patching

One Comment | Aug 29, 2008

In case you didn’t know, Windows XP SP2 provides a very cool update feature. It works like this: you have a main product, and the Quick Fixes / Service Packs that are applied to it. When you repair your setup for the main product, all the updates are also applied. When you remove, the cleanup is done for all. And it also looks cool on the Add/Remove Programs screen:

image

You’ve probably seen it before in Vista, and thought that that was a Microsoft only thing. I really prefer the way it looks in XP. It looks like this in Vista:

image

The good news is that you can do the same for your software, and it’s actually easy! The trick is to know the MSP format (same as MSI, but for Patches instead of Installers). MSP is a format you’ve probably never heard about, but you use it all the time. Each time you get an update from Windows Update, or a download from Microsoft KB, you are downloading MSP files (within a bootstrapper, but I’ll get to that later). Also, if you have installed any Service Pack provided by Microsoft, you’re also using MSP files. This covers both cases: KB articles are Quick Fixes, Service Packs are Service Packs.

So what’s an MSP file? It’s just the difference between 2 MSI files. For the files to be comparable, their Product Code (Id attribute in Wix’s Product element) must match. They must also have Comments in the Package element and UpgradeCodes on the Product element. The rest is pretty much free, and will count as “differences”, but you shouldn’t alter the Feature tree too much if you want a logical upgrade. Also, it’s recommended that you change the Version number (changing build for Quick Fixes, and minor for Service Packs). You should consider forcing a remove/reinstall for Major Upgrades. Changing version numbers is not mandatory, but it is recommended.

To create your MSP file, then, you need 2 MSI files:

1) The setup that your client has installed in his computer and that you want to upgrade.

2) The setup you would have provided if you could, with fixes to the previous setup.

Both MSI files must have the same name, so to keep them apart you have to place them in different directories. For the directory names, I use “installed” for the first setup, and “upgrade” for the second setup.

The cool thing about this is that you can publish an upgrade for pre-installed products in MSP format, and an install for customers that don’t have the previous version in MSI format.

To create the patch, you need both MSI files to use uncompressed files (compressed=”no” in the Wix file for both). This is not something you’ll normally do, but there is a very practical workaround: extracting both files to their own directories. To do this, you’ll do:

msiexec /a installed\myproduct.msi TARGETDIR=c:\myproduct\installed

msiexec /a upgrade\myproduct.msi TARGETDIR=c:\myproduct\upgrade

This will extract all the files in the setup and new MSI files that are not compressed in each directory. The only gotcha here is that you can’t have any feature with level 0. If the level is 0, the files will not get extracted. In this case, you can safely open the setup with Orca and change the level to 1, or whatever. This change will not render the upgrade incompatible with the previous setup. If the files are not uncompressed where they should, the upgrade will not work.

Now that you have this, all you need is a PCP file. This is a file with information on what you want to upgrade. There is a good sample of this on the Wix Tutorial (http://www.tramontana.co.hu/wix/lesson4.php#4.2), by far the best resource on Wix available. There most important element in your wix file will be UpgradeImage. It contains an UpgradeFile element where you can tell the MSP which files you need to upgrade. The MSP file will contain the delta between the two files by default (making it very small in size), but you can tell it to use the whole file if you want.

Finally, you must run the mspmsi tool. This tool is part of the MSI SDK, and it comes installed with Visual Studio 2008. You can find it at C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin. If your PCP file is called upgrade.pcp, the following line will create your MSP file:

"C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\msimsp.exe" -s upgrade.pcp -p upgrade.msp -l log.txt

If everything worked ok, you’ll have a new msp file. If it didn’t, you’ll get an entry in the log (log.txt) with a very cryptic error. Most common reasons for an MSP not working are:

1) Putting the wrong path for the MSI files, or not having run msiexec /a. In this case, you’ll actually get an error that makes sense.

2) Not having Comments on either MSI file, or having an apostrophe within the product name or the comments. This is illegal, and should be modified.

3) Non-matching signatures in the MSI files (that is, different Product Codes).

4) MSI files with non-matching file names.

If it worked, you can now open the msp file in Orca to see if the information is correct. To do that, you first open the installed MSI, and then go to Transform –> View Patch and open the MSP file. You’ll get something like this:

image

Where the green line to the left of the table names means that there are differences between the original and the patch, and the square green box means that the table is new. The Patch file in the screenshot is the most important difference. When the patch run, a PatchFiles action will be run in the Execute Sequence. This action will apply patches for every file in the Patch table. If it is empty, the setup will run but your files will not be patched. When the files in the UpgradeFile elements are not found in the directories where you have uncompressed your setup (with msiexec /a), the table will be empty.

And now you can run the setup! Simply double click the upgrade, and it will be handled by msiexec. If the previous version of the product is installed, you’ll see the Change/Repair/Remove dialog (if available). Clicking on Repair will run your patch. Notice that the setup is running all the actions that a Repair will normally run. There is a PATCH property you can use to know when the setup is being patched, and add or remove custom actions from the patch.

After you install the patch, Repair on any patch or the original MSI will result in your patch being applied. Remove in the patch will only remove the patch (and dependent patches if any). Remove in the MSI will remove all.

The Change/Repair/Remove interface may not be clean enough for your needs, though. You may need the patch to simply show a progress bar and be done with it. You can get this behavior by running:

msiexec /p upgrade.msp /passive

There is a tool called IExpress that’s used to create bootstraps for your setups. If you run IExpress from the command prompt, you’ll see it.The tool is pretty self explanatory. The only thing that you need to know is that you have to input the line I just mentioned in the “Install Program to Launch” step. When IExpress is finished, you’ll have an exe file that will get the correct behavior for you.

So go ahead, and happy patching!

If you need more information, or you want a second opinion, there’s a step-by-step here: http://trentm.com/blog/archives/2007/05/29/wix-and-msp/

You can also use the Wix Tutorial: http://www.tramontana.co.hu/wix

Finally, there’s more info (although somewhat misleading) of IExpress here: http://www.microsoft.com/technet/prodtechnol/ie/ieak/techinfo/deploy/60/en/iexpress.mspx?mfr=true

Setup - Elevation

Add Comment | Aug 15, 2008

It is very common on Vista (with UAC activated) to have a setup run through with no error, but to end up not installing anything. This happens when you try to write to protected resources (such as some parts of the file system, registry, etc). It’s easy to get past this on custom actions (using impersonate=”no” and Execute=”deferred”), but finding out how to do it on the “standard” components is not that easy. Luckily, it’s a one-liner. Just add the InstalledPrivileges attribute to your package, like this:

<Package Id='????????-????-????-????-????????????' Description='My Software' Manufacturer='MyCompany' InstallerVersion='250' InstallPrivileges='elevated'></Package>

And now your package will ask for elevation as soon as the execute sequence starts, resulting in all the actions/components being installed with elevated privileges.

Custom Action – Copying a Property to another Property

One Comment | Aug 06, 2008

Custom Action type 50 has a very useful behavior. This custom action copies a value to a property. The cool thing about it is that you can copy any formatted string. That is, if you use [], you can get the value of another property. and you can also use environment variables (with a % prefix), file paths (with a # prefix) and directory paths (with a $ prefix). So, to copy a property to another property, simply do this:

<CustomAction Id="CopyProperty" Property="TargetProperty" Value="[SourceProperty]" />

And then you’ll have two properties with the same value!

Custom Action – Status Bar

Add Comment | Aug 06, 2008

If you’ve made your own setup using Wix and Custom Actions, you probably got to the end of your setup to see the progress bar still running with an empty status message. It’s specially notorious if your action takes a long time to run. Gladly, there’s an easy solution to that. Simply open your UI.wxs (or add a <UI> tag in your Product, or in a Fragment) and add the following line:

<ProgressText Action="MyAction">Configuring my Custom Action</ProgressText>

Where MyAction is the Id of your action and that’s it, you now have a proper message on long-running custom actions.

Product Keys and Setup – Custom Action

4 Comments | Jul 27, 2008

The question from my previous post was: how do I validate a Product Key from a Wix Setup? The answer has many components.

First, you have to create a dialog for your product key in Wix. This dialog should have some sort of formatted input (say, a repetition of six 4-letter groups). It should also have some sort of validation.

Next, you need to have a custom action that will validate the key. It’s very important for this custom action not to be obvious to crack. Wix is very easy to modify as is, if you’re going to use the same code to validate the key in your product, let them bypass the control in the setup; it will be much harder to bypass in the product.

So first things first, let’s start with Wix. It’s actually very easy.

If you’re using WixMondo, you have most of the work cut out for you. You only need to add a new dialog to the dialogs directory. This dialog should include a MakedEdit control, which is where your key will be displayed.

The mask for the MaskedEdit is somewhat complex, and the documentation isn’t good. But for this exercise, the result is actually pretty simple. A mask of & will recognize any single character or number, and the – will display a separator. My mask in this example is a property named PIDTemplate (which is a standard variable name for the product key’s mask) declared like this:

  <Property Id="PIDTemplate">
    <![CDATA[&&&&-&&&&-&&&&-&&&&-&&&&-&&&&]]>
  </Property>
The key is associated to the Control via the Text property, like this:

    <Control Id="Key" Type="MaskedEdit" Height="15" Width="330" X="32" Y="148" Text="[PIDTemplate]"  Property="KEY" />
I think that you can paste the key directly into the attribute instead of using the property, but that really didn’t work for me.

Finally, you have to provide validation via the DoAction event in the Publish section for the Next button:

<Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17"     Default="yes" Text="$(loc.WixUINext)">
  <Publish Event="DoAction" Value="MSIKey">1</Publish>
  <Publish Event="NewDialog" Value="[WixUI_ProdKeyDlg_Next]">VALIDATEKEY =  "1"</Publish>
  <Publish Event="SpawnDialog" Value="BadKeyDlg"><![CDATA[VALIDATEKEY <> "1"]]></Publish>
</Control>
Notice that the events will run in order. That is, your MSIKey will run first (setting the VALIDATEKEY property in the process), followed by the NewDialog if VALIDATEKEY equals 1 and the SpawnDialog if the VALIDATEKEY doesn’t. NewDialog will replace your current step with the following step (defined in UI.wxs) and SpawnDialog will show a new smaller dialog with an error, that you must also define.

The full code for the dialog will then be (sorry for the formatting, the whole point is to give you a good copy paste point):

<Include>
  <Property Id="PIDTemplate">
    <![CDATA[&&&&-&&&&-&&&&-&&&&-&&&&-&&&&]]>
  </Property>

  <Dialog Id="ProductKeyDlg" Width="370" Height="270" Title="$(loc.ProdKeyDlg_Title)">
    <Control Id="Key" Type="MaskedEdit" Height="15" Width="330" X="32" Y="148" 
          Text="[PIDTemplate]"  Property="KEY" />
    <Control Id="Back" Type="PushButton" X="180" Y="243" Width="56" Height="17" 
          Text="$(loc.WixUIBack)">
       <Publish Event="NewDialog" Value="[WixUI_ProdKeyDlg_Back]">1</Publish>
    </Control>
    <Control Id="Next" Type="PushButton" X="236" Y="243" Width="56" Height="17" Default="yes" 
           Text="$(loc.WixUINext)">
       <Publish Event="DoAction" Value="ValidateKey">1</Publish>
       <Publish Event="NewDialog" Value="[WixUI_ProdKeyDlg_Next]">VALIDATEKEY = "1"</Publish>
       <Publish Event="SpawnDialog" Value="BadKeyDlg"><![CDATA[VALIDATEKEY <> "1"]]></Publish>
    </Control>
    <Control Id="Cancel" Type="PushButton" X="304" Y="243" Width="56" Height="17" Cancel="yes" 
           Text="$(loc.WixUICancel)">
       <Publish Event="SpawnDialog" Value="CancelDlg">1</Publish>
    </Control>
    <Control Id="BannerBitmap" Type="Bitmap" X="0" Y="0" Width="370" Height="44" TabSkip="no" 
           Text="$(loc.ProdKeyDlgBannerBitmap)" />
    <Control Id="BannerLine" Type="Line" X="0" Y="44" Width="370" Height="0" />
    <Control Id="BottomLine" Type="Line" X="0" Y="234" Width="370" Height="0" />
    <Control Id="Description" Type="Text" X="25" Y="23" Width="280" Height="15" Transparent="yes" 
           NoPrefix="yes" Text="$(loc.ProdKeyDlgDescription)" />
    <Control Id="Title" Type="Text" X="15" Y="6" Width="200" Height="15" Transparent="yes" 
           NoPrefix="yes" Text="$(loc.ProdKeyDlgTitle)" />
    <Control Id="EnterKey" Type="Text" Height="20" Width="154" X="25" Y="116" 
           Text="$(loc.ProdKeyDlgEnterKey)" />
  </Dialog>
</Include>

I will spare you the code for the error dialog. If you need one, just copy Cancel.wxi or OutOfDisk.wxi and change the name and description. Add it in the includes section of UI.wxs, and you’re good to go.

Next comes the Custom Action, which is actually the hardest part. In MSI, you can create a Custom Action in several ways. The most common for this kind of thing are JScript/VBScript, Managed (as in, C#) and Native. My reasons for using native, following:

1. Nobody in their right mind should right a piece of JScript code and think that it’s safe. Period. You can easily extract the JScript from the MSI, and then your product will not be safe because you have given any potential attacker your key validation code. Also, JScript is somewhat harder to debug than the other two options. JScript can’t be used from your product’s code (most of the time), so you’ll have to duplicate your logic and your code to call it if needed.

2. Managed is a little harder to exploit, but just a little. The real drawback here is that you can’t really use Managed code in the DoAction event of a Control. If you really want to, you can refer to a post in Pablo’s blog that tells you how to do it. It’s a very hard and very manual process you’ll have to do every time you compile your assembly which basically fools the MSI executable into thinking that your code is native when in fact it isn’t. Managed can be used from you code easily from your product if your product is also written in the same managed code. I don’t think you can use Java for a custom action in MSI, but I really didn’t check into it.

3. Native is the hardest to exploit, but also the hardest to write, especially if you’re not used to it. Also, it’s the recommended choice for any custom action run from an MSI. Finally, a native dll may be imported in almost any language that you are using for your product.

There’s also another option you have available for the custom action: wether the dll containing it will be stored in binary form somewhere in the database, or if you want to store it in the file system before running it. I’m going to show how to use it from binary, but you’ll usually store it in the disk if you want to use it from your product too. Either way, Wix configuration is almost the same:

<Binary Id="ProductKeyCode" SourceFile="Binary\ProductKeyCode.dll" />
<CustomAction Id="MSIKey" 
     BinaryKey="ProductKeyCode" DllEntry="MSIValidateKey" />

The only difference between this and using the deployed version is that you will have a FileKey instead of the BinaryKey, and the dll as part of your regular directory structure.

And finally for the complex part, here’s how you create the dll. I’m not a native developer by trade, so the following may have huge conceptual errors. Please forgive me for them and help me correct them using the comments.

First, you have to create a Win32 application in Visual Studio, and select the type as Static Library in the wizard. Don’t include MFC or Precompiled Headers. The wizard will create a .cpp and a .h file for you to edit. It will also include a set of std files.

Open the stdafx.h file, and add the following:

#include <msi.h>
#include <msiquery.h>
#include <stdlib.h>
#pragma comment(lib, "msi.lib")

#include <comutil.h>
#include <string>
#include <tchar.h>

The msi.h and msi.lib are important, the others are being used only for this sample. You may not have the msi.h, msiquery.h or msi.lib available in your computer. If you don’t, you’ll need to install the Windows Installer SDK to get them. Also, you may need to add the folder where the msi files are to your includes and libs directories, or copy the files to the actual include and lib directories.

The actual code (in your cpp file) should look like this:

#include "stdafx.h"
#include "ProductKeyCode.h"

int __stdcall GetItemFromKey(TCHAR* szValueBuf, int iPos)
{
    std::basic_string<TCHAR> str = szValueBuf;
    wchar_t ptrKey [5] = TEXT("****");
    str.copy(ptrKey, 4, (iPos - 1) * 5);

    int iRet = wcstol(ptrKey, (wchar_t**)NULL, 16);

    str.~basic_string();

    return iRet;
}

BOOL __stdcall KeyValidationMain(TCHAR* szValueBuf)
{
    int key0 = GetNumberFromKey(szValueBuf, 1);
    int key1 = GetNumberFromKey(szValueBuf, 2);
    int key2 = GetNumberFromKey(szValueBuf, 3);
    int key3 = GetNumberFromKey(szValueBuf, 4);
    int key4 = GetNumberFromKey(szValueBuf, 5);
    int key5 = GetNumberFromKey(szValueBuf, 6);
        
// Your validation goes here. 
    return TRUE;
}

UINT __stdcall MSIKeyValidation(MSIHANDLE hInstall)
{
//    MessageBox(NULL, TEXT("Debug"), TEXT("Debug"), 0);
    TCHAR* szValueBuf = NULL;
    DWORD cchValueBuf = 0;
    UINT uiStat =  MsiGetProperty(hInstall, TEXT("KEY"), TEXT(""),
                                     &cchValueBuf);
    if (ERROR_MORE_DATA == uiStat)
    {
        ++cchValueBuf; // does not include terminating null, so add 1
        szValueBuf = new TCHAR[cchValueBuf];
        if (szValueBuf)
        {
            uiStat = MsiGetProperty(hInstall, TEXT("KEY"), szValueBuf
                    , &cchValueBuf);
        }
    }
    if (ERROR_SUCCESS != uiStat)
    {
        if (szValueBuf != NULL) 
        delete [] szValueBuf;
        return ERROR_INSTALL_FAILURE;
    }

    if (ValidationKeyMain(szValueBuf) == TRUE)
    {
        MsiSetProperty(hInstall, TEXT("VALIDATEKEY"), TEXT("1"));
    }
    else
    {
        MsiSetProperty(hInstall, TEXT("VALIDATEKEY"), TEXT("0"));
    }

    delete [] szValueBuf;    

    return ERROR_SUCCESS;
}

There are two exported methods here: MsiKeyValidation and KeyValidationMain. GetItemFromKey is a private helper method that may be declared elsewhere. Notice that the actual validation occurs in KeyValidationMain. This method will run your validation algorithm (a cryptographic thing, mostly) and return TRUE if the key is valid or FALSE otherwise. My convention is that, in case of error, I return false. MsiKeyValidation is a simple wrapper to integrate with MSI.

The commented MessageBox at the beginning of MSIKeyValidation is important, I’ll get back to that in a second. MSIKeyValidation will get the KEY property from the Msi database. It will always look the same: “    -    -    -    -    -    “, with whatever the user writes in the spaces or spaces if the users doesn’t write anything. This makes it very safe to cut in the GetItemFromKey method. In this last method, I return a base 16 number for each part of the key (I use hex in this sample), but you’ll generally use it directly as text.

Finally, to make the exported files visible, you have to include a .def file, with the following contents:

LIBRARY    "ProductKeyCode"
EXPORTS
    MSIKeyValidation
    KeyValidationMain

This library should compile as is. If you open it with depends, you should be able to see the functions in the exports section. A setup constructed this way will work on most computers, but I found out that sometimes, it doesn’t work. If you’re finding that your dll isn’t running (and you go to the %temp% directory, and you don’t see it appearing there, and you can’t attach to it), then go to Project Properties, find C/C++ –> Code Generation and select Multi-Threaded Debug in the Runtime Library option. I really don’t know why, but it will fix it.

With this done, you’re ready to deploy with a product key. If you want to debug the dll, you’ll have to reenable the message box. Run the setup and wait for the message box to appear (it will appear when you click Next on the Product Key dialog). At this point, attach Visual Studio to the newest msiexec process, and you should be able to debug. The executable for Msi opens a new process for each Custom Action. In any case (script, managed or native) the correct way to attach a debugger is the same.

As an added bonus, if you want to call your validation from managed code, you should write the following code:

[DllImport("ProductKeyCode.dll", CallingConvention = 
CallingConvention.StdCall, EntryPoint="KeyValidationMain")]
static extern bool KeyValidationMain(
[MarshalAs(UnmanagedType.LPTStr)]string szKey);

And that’s it! Now you can access the same algorithm from managed code.

Product Keys and Setup – Random Thoughts

2 Comments | Jul 26, 2008

I was commissioned recently on making a Product Key system for a shrink wrap piece of software. And my first thought was: there must be some sort of best practice or pattern language for this. I mean, many people sell shrink wrap software every day, and inventing the procedure each time is just to costly and error probe. Turns out, I was wrong. There is no pattern or best practice for product keys (at least none that I could find in the internet, forums or books). It makes sense, though, for several reasons. First, the market for enterprise software is way bigger than the market for shrink wrap, and there’s where all the advise is directed to. Next, because product keys are something best kept secret. As we know, security by obscurity was never a great idea, so let me share what I have come up with.

Before I start, let me tell you Joel has it right, twice: he says that product keys aren’t a good measure of security (at least I think it was him, I can’t find the link right now). Crackers will crack them anyway sooner or later. Or they can end up in public or not so public forums in a very short time. Next, he says you should raise up your prices and he’s also right. Both pieces of advise go together: you don’t put a public key in place to make your software impossible to copy. You put it in there to clearly state that making such a copy is illegal. Normal customers, users, will get a pirated copy of your software if they want to. It’s not hard and as of today it's not dangerous. But the corporations can’t do that, because they have codes of ethics to attend to. Also, their bottom line is not as affected by you as a regular user’s is. So my comment on this is: use a product key, so a customer will get your software from wherever he finds it, adopt it, and tell his boss about it so he can buy it. You may even get someone so into your software that he’ll buy it from you right after getting an illegal copy of it.

One very valid solution is to avoid the whole product key affair, and publish a free version of your software with a reduced set of features in it, and a full version on purchase. Of course, the rules of the game will remain the same. Pirate copies of your software will be unprotected. Remember: seeing your software in the pirate circles means your software is successful. If a cracker took the time to work on it, it probably means it’s worth it. This fact will not get you any money now, but it sure will make you money in the long run.

My general advice is:

1. Make your key easy to code. Not as easy as to make your key laughing stock from the cracking community, not as hard as to lose valuable time (your time) over it. Crackers will probably bypass your code instead of trying to solve your algorithm if it’s too hard.

2. Always use some sort of non-managed code for the key algorithm. Managed is just to easy to read, even when obfuscated. I mean, this guys debug your code in assembly to crack it, scrambled names will not be enough to stop them. Also, if you’re a Managed developer, remember that a signed assembly cannot be tampered with, but it can be read.

3. Validating your key in the setup is cool for usability, but it has nothing to do with security. MSI is a simple database and it can be very easily modified. Most software providers actually validate the key in an exe before the msi even starts up (that’s one of the reason that most software ships with setup.exe and setup.msi). I find that doing that is not really necessary if you do 4.

4. Always validate your key on startup of your product. If the key is invalid, you can load with a reduced set of features, or not load at all.

5. If you want to provide a time bomb (that is, trial software that will eventually expire), hide the expiration date (or something that you can convert to the expiration date) somewhere in the key.

6. Eliminating keys you find on the internet is an impossible race. There’s many more of them than there are of you. New keys will resurface within hours.

A good product key is like a good encryption algorithm. In this context, that means two things:

7. If you change a single bit of your product key, the rest of the key should change to accommodate your checksum. All the “digits” must change.

8. There should be a minimum (say, 10%) of valid product keys per bit. That is, if your product key is 32 bits (it won’t be), only 2 or 3 keys should be valid.

I created the key on a very simple algorithm I will not disclose, using Wix and a C++ dll. I’m planning on giving the details of the procedure on the next few posts.

Mathcing Braces with Regex

Add Comment | Jul 24, 2008

3 years ago, I wrote this post: http://regexlib.com/REDetails.aspx?regexp_id=1135.

It contained a .Net regular expression that would match the highest level of matching braces, something that is needed more often than not when parsing languages. It will also return null if no matching braces are found. Finally, as an added bonus, it will ignore braces that are escaped with a backslash.

Soon after I posted it, someone commented on it being impossible, because Finite Automatas can’t count. I didn’t want to fight it (and I didn’t know better), so I simply made a wrong statement that would divert the discussion. I simply knew that it worked back then. I’m wiser now, and I know the answer.

FAs are used to parse regular languages and as such, they can’t count. That’s absolutely true. That means that you can’t keep track of what you’ve seen by using a FA. So, if you need to match a symmetrical phrase (aabbccbbaa), you can’t. That’s what Push-down automatas are used for.

Problem is, .Net regular expressions don’t work as a regular language. When you start using backtracking and lookahead, you’re automatically out of the regular language domain. And then, Finite Automatas can’t be used anymore.

So, if you need to count, you can always use a backtrack. You can use them to search for a palindrome (http://aspn.activestate.com/ASPN/Cookbook/Rx/Recipe/326097) and you can use them to search for matching braces.

As an added bonus, here’s how you do different braces with the regex:

Curly ({}): (?<!\\)\{(\\\{|\\\}|[^\{\}]|(?<!\\)\{.*(?<!\\)\})*(?<!\\)\}

Parenthesis (()): (?<!\\)\((\\\(|\\\)|[^\(\)]|(?<!\\)\(.*(?<!\\)\))*(?<!\\)\)

Square ([]): (?<!\\)\[(\\\[|\\\]|[^\[\]]|(?<!\\)\[.*(?<!\\)\])*(?<!\\)\]

Chevrons (<>): (?<!\\)\<(\\\<|\\\>|[^\<\>]|(?<!\\)\<.*(?<!\\)\>)*(?<!\\)\>

Hope you find it useful!

Alive again

Add Comment | Jul 22, 2008
It has been a long time. I really didn't feel the need to blog back then. But now I have a few things I'd like to share, and some peers recommended me to blog, so here I am.

First, let me tell you that the experiment with Asterisk and the Linksys router didn't end up well. I mean, it worked and it worked ok. The problem was that the router couldn't cope with the processing required for Asterisk to work. When Asterisk was active, my poor little router restarted every 15 minutes or so. I always suspected it was a heat issue, and mounting a cooling fan on it would probably had helped. I'm a software hacker, though, not a hardware guy. Even the smallest hardware change is really hard for me. So, long story short, I found a service that actually work and I use a Gramphone VOIP thingy now, which works on zero configuration and it's fully supported both by the provider and by Gramphone. Hacking into de Linksys sure was fun, but not profitable. Sorry if somebody was expecting me to tell you how it worked. If someone wants to try with the cooler, I have the configuration files lying around somewhere. And now that Mitnick is phreaking again (seriously, man, phreaking is so '70) it may actually be useful.

Anyway, I'm hoping I'll last longer this time...

Got VOIP!! On how to integrate a WRT54G with Asterisk - Errr... just a sec!

Add Comment | Dec 17, 2005
I've been having problems and I'm looking for a solution. I'm hoping to be posting the second and third parts soon. Sorry, if anyone was following this!

Got VOIP!! On how to integrate a WRT54G with Asterisk - Part 1

6 Comments | Nov 13, 2005

Everything started a few months ago. I live in a country where you cannot choose the
phone company you'll get, and you're stuck with the single company that covers your area.

This of course smells of corruption, but that's not the point here.
The problem was I spent about an year calling the phone company so they'll repair my
line, which was absolutely dead. And they'll send someone, and it'll work for a few days,
and then the problems started again. I spent half last year without even having a phone.

So I told myself: why not go to IP?

For those unfamiliar with VoIP I'll clear some of the vocabulary out right away. A VoIP
(Voice over IP) phone is a phone (known as an ATA) that connects to a provider (VoIP
provider) using one of several protocols (h.323 and SIP being the two most popular). You
can have an incoming phone number (called a DID) that looks exactly like any regular
phone number in your area. The people calling you can never know you're on VoIP (except
for a little delay in the voice). You also don't want that huge downloads interfere with
your voice experience, and you have QoS (Quality of Service) for that. It is a system
where you either limit the bandwith of a certain port/computer/etc or that dynamically
limits and increases the bandwith of a service.

So I cancel the line with the telco company (which they ended up not doing pecause they
lost my form and they where forcing me to pay an extra month I didn't use), and I start
searching for VoIP providers carrying DID's in my area. When you have VoIP, you can have
a provider anywhere in the world. The cost of the calls is generally the same. But if you
want an incoming line, it has to be in your area, or people'll have to call international
rates to get to you.

I found several VoIP providers (which was amazing, I thought that there where none), and
I sent mails to all of them asking them what their costs where, etc, etc. I finally chose
Altocontacto.com, and I must say I'm very satisfied with them. I wasn't satisfied with
the whole VoIP thing at first, but they have excellent customer support, and they helped
me through every issue they could.

Second step was to find a good ATA. I live with my non-computer savy girlfriend (and I
love her) and I wanted this phone to resemble a phone as much as it could. The solution
for that is a VoIP router, which routes internet calls to a regular phone line. I saw
several, and finally I had to choose between PAP2 or RT31P2 from linksys. I love linksys,
all my routing hardware is linksys, but I must tell you: never buy VoIP products from
them. Linksys has over the last few years associated with the major VoIP providers in the
US (Vonage being the number one). They usually sell hardware locked to those companies.
You can find unlocked hardware outside the US (which is completely legal) or unlock your
linksys hardware (which, I think, is not so legal). The problem is that if you buy
unlocked hardware from linksys, they will absolutely not give you any support.
Furthermore, they'll try to find out how you got the hardware in the first place, and
they'll demand that you be a VoIP provider authorized by them before giving you the most
simple and mundane piece of data.

Anyway, I had these choice to make. RT31P2 seemed like stronger hardware, with QoS
capabilities so I chose that. It was, of course, the wrong choice. RT31P2 may have better
hardware than the PAP2, but the PAP2 has a way better firmware. There's configuration you
simply can't do with the RT31P2. And the QoS system it has is lame. But at first,
everything went ok. I was making the calls, I had to choose amongst several voice
protocols and I found one where the calls will actually sound ok. I was jolly,
altoncontacto was helping me with all of this. They didn't have the RT31P2 in their
knowledge base, so I had to configure it myself, but everything was ok. My configuration
at this point was:

Internet provider <-> WRT54G <-> RT31P2 <-> Regular phone

With some wireless computers connected to the WRT54G router and some wired computers
connected to the RT31P2. Then, my friends started complaining that they could never call
me, and I started doing some tests. Apparently, the VoIP provider was ditching my
connection after some time of inactivity. I could connect perfectly, but I'll get
silently disconnected after some time. Nobody uses DID's in Argentina, so this company
has a lot of outgoing calls and almost no incoming calls. To increase the concurrency of
the system, they kill connections after a fair timeout (which is about 2 minutes). I
couldn't really blame them, the configuration they had was optimum for their needs. They
tell me "just set the register expires parameter in yout ATA to 120 seconds, and
everything'll be fine". But my ATA (the RT31P2) doesn't carry that setting... so I
couldn't do that. Another problem I had, which was more like a slight nuisance than a
problem, was that using VoIP you're technically nowhere. So when you want to call your
next door neighbor you have to dial the 00 + international code + local code + number.
This wasn't a big problem, but it sure was annoying.

So at first I try configuring this RT31P2 thing in every conceivable way, and then I
contact linksys for support, and they wouldn't even tell me if the parameter was there or
not. Finally, this really cool guy from linksys (they're forbidden to do it, which
doesn't mean they're bad people) tells me "if you can't find the configuration parameter,
it probably isn't there". So I thank him and start going through alternative paths. First
path was trying to replace the RT31P2 with a PAP2, which does have the parameter. But
that was a no-no, my equipment was used and really difficult to sell. Then, other things:
connecting a modem to the additional phone line and opening the port and closing it every
120 seconds (I don't even think that would work anyway), sending the SIP request with a
spoofed IP address from a wired PC (but I generally don't have any on 24x7). And finally,
changing the firmware of one of the routers to acommodate my needs.

Linksys may create good hardware, but the firmware's are generally pretty bad. Also, they
used to opensource some of their firmwares. Those two items combined made people (several
people, in fact) create firmwares for their hardware. RT31P2 firmwares are obviously
nowhere to be found, those are locked... but WRT54G firmwares come in all sort of
packages and colors. You simply have to choose which one's best for you and go with it.
WRT54G seems also to be a popular choice where I work, so I went around asking people
which firmware they use. One of them suggested OpenWRT. You can schedule tasks in
OpenWRT, so I could spoof the SIP request from there. Others suggested Sveasoft's
firmwares, but I really don't think I want to get into that war. So I went with OpenWRT,
and I started investigating. Checking things out, I found out that there was an Asterisk
port for OpenWRT, so I started finding stuff out about that too. Now, don't get me wrong.
Before this, I didn't even know what an Asterisk was. I'm a developer, not an
administrator. This kind of things are simply out of my scope. So let me explain:

In the telephony world, there's a piece of hardware called a PBX. What a PBX does is it
receives incoming phone lines, and it routes them to the extensions in your
house/company. A software PBX does almost the same thing: It gets VoIP phone lines and it
routes them to VoIP extensions, or other software/hardware PBX's that'll route the calls
to regular phone extensions. It provides routing mechanisms and protocol conversions (if
you want, for instance, to communicate a SIP-enabled phone with an h323-enabled VoIP
provider). The OpenWRT-Asterisk combination allowed me to make local calls without
international prefixes (given that I configured an appropiate rule) and best of all, it
carried the Register Expires configuration item!

My first step was then to flash the firmware in the linksys router. (Disclaimer: this is
what I did, and it voided my warranty... kids, don't do this at home!). They tell you
that your WAN (Internet) connection must be set to static before flashing the firmware,
so I went into linksys' web admin and changed that. That left me with no internet, so I
made sure to havve everything I needed (Including linksys' V2.02.7 firmware just in case)
before starting. The best procedure for flashing the router from a Windows box (I had a
Linux box, but I wanted to use the windows), is to start pinging the router with

ping 192.168.1.1 -t

where the router will always be 192.168.1.1, no matter what you configure it to be. You
then have to have this line:

tftp -i 192.168.1.1 PUT firmware.bin

ready in a separate command prompt. You disconnect power from the linksys router count to
60 and reconnect it. As soon as the ping starts responding again, hit return in the tftp
line. That'll upload the firmware (in about 10 seconds), and you're ready to go!
So at this point, I had a WRT54G with an OpenWRT firmware, a RT31P2 connecting with my
VoIP provider, and a wired computer connected to the RT31P2. Next step was to make the
internet work...

To get into the WRT54G, I couldn't use the web interface anymore, since it was no longer
there. I had to telnet into it instead. Now, telneting into a box is the most unsecure
thing you can do. Issuing a passwd command, I set a password for root (a strong one,
also, with letters and numbers and strange symbols). OpenWRT also comes with SSH, so I
tried connecting to it with putty. It asked me for a user login (root) and a password
(the one I just set). So I went ahead and deleted telnet from the WRT. After that, I had
to make the internet work. My girlfriend was about to wake up, and if Internet didn't
work... I wouldn't be able to work on this anymore. All your settings remain when you
flash the firmware, so the only thing I had to do is to set the WAN to dhcp again (I had
set it to static before flashing the firmware). The parameter's name is wan_proto, and
the setting should be dhcp. I issued these commands:

nvram set wan_proto=dhcp
nvram commit

And everything was working again! This is just how easy it is to flash a WRT54G and get
whichever firmware you want. Even the wireless interface was working again. (BTW, at this
point I used nvram show a lot to find what the names of the parameters where). So next step was to get the Asterisk up and running. I'll continue with that in a few days... if you want a preview, go to http://lestblood.imagodirt.net/archives/106-Asterisk-on-OpenWRT-part-2.html. I'll try to post all the relevant links tomorrow, I'm so thankful to so many people...

Visual C# Express 2005

2 Comments | Oct 25, 2005
I finally did it. I mean, I know I should have done this a long time ago, but last week I finally did it. I went to microsoft's page, downloaded Visual C# Express and installed it.

I must say, my first impression was absolutely positive.

As a windows geek, the first thing I did was to create a new empty Windows Forms project. And just to see what was on it, I compiled it and disassembled it on ILDASM.

There where two things that I found unusual and beautiful. First thing was inside ILDASM, and second thing was outside it.
Let me explain:

The first thing I saw, was that there where two classes in my main Namespace: Form1 and Program. Form1 I already knew, Program I didn't know. So I went into Program, to see what that was about. And I liked it, I really did!
In a blank C# Windows Forms project, Program has the void main() function, working as a startup. Traditionally this was the job of the very first form you added to the project (added by default in Visual Studio). The thing I love about the new approach is that I never liked the way it used to work, but I didn't think about it until I saw the new way. First thing I thought is "someone is taking the job of anticipating my thoughts for me".
The advantages of this approach are obvious: if you have to delete the first form for some reason, the void main() remains in the project. If you need to hide that form (as in a spash window), you'll have to either take the main function to a new class, or have a resident form for the duration of the application. But that's not what I like about Visual C# Express providing it for me. What I like is that someone thought it'll be a cool feature, and he added it though it didn't look like the great thing...

So I went to the form class to see what it looked like, and I found the second great thing: Partial Classes.

Partial classes are to me another of the "removing little inconveniences" new features. They don't add much, but then again, they do.
Anyway, what I saw was that the InitializeComponents was nowhere to be seen. So I opened the little branch coming from Form1.cs in the Solution Explorer, and there I saw two new objects: Form1.Designer.cs and Form1.resx. Form1.resx I knew; that was the resources file. It wasn't there in previous versions (explicitly at least), but it was pretty obvious that was it. The other one looked like code, so I went and double-clicked it. And there it was, InitializeComponents in a different part of the code, but in the same form.
For those who don't know what Partial Classes are, a really simple explanation: they are the new way of defining a single class in multiple parts of the code. You simply add a "partial" keyword to any class definition, and you write some more code to it. There are quite a few restrictions, but it's still a great thing. To understand the restrictions, you must understand that Partial Classes are just Regions on steroids. You can't redefine an existing method, you can't change the scope of the class. You can define new internal members, new properties, new methods, new events... whatever you like as long as you don't alter anything defined elsewhere. Partial classes are not ment to provide new functionality. On the contrary, they are ment to separate functionality. For instance, all the stuff that the Form Designer adds for you ends up in the Form1.Designer.cs module, as part of Form1.

So why is this a great thing? Same reason as the new Program class is a great thing: neatness. In previous versions, the things the Form Designer did where mixed with your code. And you could end up accidentally changing it. Or worst, it was almost completely hidden from you (as when creating a typed dataset). Everything is now shown and everything is now separated.

Once again, it doesn't add much. But I really do like it. I like it so much, I think I'll be blogging about it again!