http://www.premia.com - Webpage (cw32v51b.exe - (8.23Mb)).
Welcome to another tutorial. Firstly, a small digression, with most software vendors now having a web presence, 30-day downloadable trial versions of applications are fairly common, in fact most will tend to provide on-line registration, serial #'s, keys etc. to further cut their costs. Those of you in the software business will realise quite how time consuming it can be to actually implement a real time-crippled application that cannot be unlocked in some way, however Premia Codewright is one such example.
There's quite a few things to dislike about this time-limited program, the initial start-up evaluation screen quoting the amount of time left, the actual time-trial itself and the About Box 'FREE DEMO COPY' string, so lets systematically remove each of these protectionist features.
In my experience, the best way to do this is in most cases to reboot your PC and move the BIOS date temporarily forward thus giving the system the impression that the date has moved on. After you have moved the BIOS time forward attempt to launch Codewright, you should get this message box after clicking O.K at the first screen.
The Premia programmers were not clever here, with SoftICE you can bpx on anyone of 3 API functions, (GetLocalTime, GetSystemTime, GetTimeZoneInformation), and trace your way to the compare routine. Alternatively you can just work backwards from the nag box with bpx MessageBoxA. The real time check is controlled by this code, use any of the aforementioned breakpoints to reach it, (and note that we are inside cwdll32.dll).
:10187F37 PUSH EDX <-- Note that DX = 1Eh (30).
:10187F38 AND ECX, 0000FFFF <-- Prepares CX.
:10187F3E PUSH EAX <-- AX = 8h (the month).
:10187F3F PUSH ECX <-- CX = 7CEh (the year).
:10187F40 CALL 10189C90 <-- Manipulate pushes to make the real compare less obvious.
:10187F5B RET <-- Return function.
:1011E105 MOV EAX, [EBP-04] <-- Time_limit_magic_number.
:1011E108 CMP EAX, [EBP-08] <-- Check it.
:1011E10B JLE 1011E1A0 <-- Jump_good.
So here's what happens, the first part of CALL 10189C90 checks the year for between 1980 and 2038 by subtracting 1900 from the current year. We then generate using some arithmetic and the date what I've termed as our magic number, its returned in EAX at the end of the function. This magic number will then be compared with 35E7366Fh (which I assume must always be the same). This type of compare does avoid the CMP ExX, 1E instruction which many reversers might be used too. However its still a simple patch to force the JLE to JMP.
:1011E10B OF 8E 8F 00 00 00 <-- JLE 1011E1A0.
:1011E10B E9 90 00 00 00 90 <-- JMP 1011E1A0 + NOP.
With the time-trial now rendered ineffective the next task is to remove the welcoming box, which pops up immediately after the splash screen. It looks very much like a standard windows dialog box, so using some fairly crude trial and error tactics you'll find that >bpx DialogBoxParamA triggers SoftICE.
:1011E0F5 CALL [USER32!DialogBoxParamA] <-- Display
I believed fixing this dialog box would be fairly simple, just by NOP-ping it away and correcting the stack pointer, however when I performed the necessary HEX editing and launched Codewright the program refused to start. There are probably a few ways to actually get around this, but the disassembly provided me with my first solution, note this code just before the welcoming box.
:1011E0DD CMP DWORD PTR [EBP-0C], 00000000
:1011E0E1 JNZ 1011E0FB <-- Note this jump.
This conditional jump literally jumps over just the pushed parameters for DialogBoxParamA and the call itself, its certainly a change worth trying, so lets force the JNZ to a JMP and watch as this seems to work.
The final change to make is rather cosmetic. Launch the program and all is well, no welcoming screen or time restriction, however the Help/About is not very a very pretty sight, "FREE DEMO COPY". The first thing I did was perform a HEX search through the Codewright directory looking for this string but I was unable to find it. Although judging from the location of our previous protections I was fairly sure that cwdll32.dll was responsible.
You'll find by setting a bpx on DialogBoxParamA that our about box is displayed at address 10146D0D. Its possible to work back from here just by setting breakpoints. this code. However you might like to take a look at this code.
:1014977B CALL [CWDLL32.MsgData] <-- Nice function,
check contents of ECX.
:10149780 TEST EAX, EAX <-- Does our string exist (check for length).
:10149782 JLE 1014982F <-- Jump_it_doesn't.
:10149788 CMP DWORD PTR [EBP-04], 00000000 <-- Check contents.
:1014978C JZ 1014982F <-- Jump_no_contents
Well, neither the JLE or the JZ actually jumped here which is hardly surprising because our string was contained in ECX, the net result of these not jumping was a call to wsprintfA at address 1014980E, you'll note the S/N string reference at address 10149805 which is added just before. So we can fool the program into actually thinking that our string 'FREE DEMO COPY' in ECX doesn't exist by forcing either of the above 2 conditional jumps (they both go to the same address), the result is a S/N: of V5.1b in the About Box.
:10149782 0F 8E A7 00 00 00 <-- JLE 1014982F.
:10149782 E9 A8 00 00 00 90 <-- JMP 1014982F + NOP.