Description Barudan Punchant I believe is software to control knitting & sewing machines, functionally useless for most of us I think.
Protection Type TimeHASP-4, other tricks :-).
Size 15Mb Installation Files.
Target Name Barudan Punchant v6.0G (Tajima DGML v6.0, Wilcom ES-65 Designer).

I'll start out in one of my new style tutorials firstly with a little history (the longer you reverse the more important this becomes). My battle against these programs started around 2 years ago when I ran into a very similar product to this one called Wilcom ES-65 Designer. In early 1997 it was one of the first good TimeHASP protections I had seen, lots of Service 2 response codes too :-), it gave me back then a serious headache with its little tricks which have been repeated, albeit slightly differently, in this example.

TimeHASP-4 is a more expensive flavour of HASP dongle and has 496-bytes of memory as well as a real-time clock. Finding our HASP routine is simple enough, disassembling bp.exe finds you a trademark 'cmp bh, 32' at 00402DD6, below this you can easily find the JMP HASPDOSDRV. We will be adding our emulation routine in the usual fashion (see CasMate's tutorial if you don't know how to do this) - change the E9 at raw offs. 18FA68 to E8 and start your emulation routine at raw offs. 182CAA.

Our first problem will be finding which dongle to use with this program, after faking a IsHasp() check you'll find there are 4 sets of passwords used with HaspCode (34A7/3268, 50ED/5017, 1F97/68E0 & 3C39/2047). To this day I've never discovered which is the correct one, I can only assume different HASP's control the various programs from this company. This will however prove no problem as the first set will work with ALL 3 programs I have. All programs call 4 main HASP services, I'll discuss them briefly. IsHasp as you might expect will prove trivial. The HaspCode checks however are very good, the program initially looks up 8 random seed codes in a table and then uses the index to get at the desired responses, when I first broke this in 1997 I coded a basic routine which hooked the table, retrieved the index off the stack and got at the returns that way.

Needless to say I have long since emulated HaspCode() generically so this is not longer an issue. Service 4E or HaspID() is also trivial to emulate (choose your serial number at will :-) ). Our main problems will be with Service 3 & 49 (ReadWord() & GetDate()). Normally I'd have patched in a hard-wired date for GetDate() but Barudan Punchant verifies the returns in a routine which would be no fun to patch, the days you have left are also validated using words from the dongle (at the end you'll see how to fix this). Getting therefore the current date is our first dilemma, yet we have the answer sat in front of our very eyes, we'll just use GetLocalTime() which is imported by bp.exe already.

VOID GetLocalTime(

LPSYSTEMTIME lpSystemTime // address of system time structure

typedef struct _SYSTEMTIME { // st
WORD wYear; <-- Return Par 4.
WORD wMonth; <-- Return Par 2.
WORD wDayOfWeek;
WORD wDay; <-- Return Par 1.
WORD wHour;
WORD wMinute;
WORD wSecond;
WORD wMilliseconds;

Here's how this could translate into assembly (as your smart you wouldn't be doing this for real) :-

CMP BH, 49 <-- GetDate().
JNZ $+x <-- Do next service.
PUSHAD <-- Save registers.
LEA EDI, [EBP+offset] <-- Struct of 10h dup(0).
PUSH EDI <-- lpSystemTime.
CALL GetLocalTime()
SUB ESP, 4 <-- Correct stack.
POP EDI <-- Restore EDI.
POPAD <-- Restore registers.
LEA ECX, [EBP+offset] <-- Our struct.
MOVZX EBX, WORD PTR [ECX+2] <-- Month.
SUB DX, 76Ch <-- Sub 1900 decimal.
XOR ECX, ECX <-- Clear status as required.
RET <-- Return from emulator.

Its always quite satisfying to use the facilities the program provides for us :-). Service 3 works as follows. All words from 0 - F7 are read by the program and summed, as EDI holds the word being read you can use a conditional breakpoint to skip past most of this. Positions F6 & F7 act as checksums and are then verified, I advise you NOP these checks and come back to fix them at the very end (004FF048 & 004FF062). From here on in you need only concern yourself with words 0 - 3D. Most of these work simply as option toggles, i.e. read the word, hook a table with its index, XOR it with corresponding table entry and compare result with FFFFh (being good).

However, the programs all have the exceptions which required lots of research on my part. Firstly, I advise you fix word 1C, it acts as a validity toggle, fix this and you should be able to start the program without the "Invalid Product" error. Words 1A & 1B are the date toggle, they are XOR'd with table entries and then manipulated to give a DWORD of form below.

07CF 0C1D
^^^^ ^^^^
 1A   1B

This should be self-explanatory, 07CF being the year, 0C the month, 1D the day). This DWORD is fed into a routine which calculates the days left using the current date read with Service 49 (assumed to be correct). Its therefore quite easy to give yourself a 10 or 20 year trial of this software or better still XOR them both to FFFFh and the expiry will never be checked. Word 1E controls some sort of version information and must XOR to 32 (its checked right at the end of the service 3 product loop).

I'll list for you here the words that control options, i.e. you can XOR them safely to FFFFh, the best thing I can advise you to do is dump the XOR table and write a small program to do the tedious work for you.

Safe to XOR to FFFFh :- 2-D (inclusive), F, 10, 11, 14, 15, 18, 19, 1F, 23, 2B, 2C, 2E-3B (inclusive), 3D.

All these programs have a further 2 main tricks, the first involves a 2-part disabling of certain functions (the second part of this on a timer will prove tricky to find). The second trick disables the startup options. We'll deal with the second trick first, the startup options disable pretty quickly and quits with a message box which can be bpx'd easily, 2 pushes of F12 and you'll find the counters easily enough, they are controlled using word 20 read from the dongle which will be XOR'd with its table entry (9D08h) and then divided by 3E8h, the 3 programs I have here require different results of this division, in Barudan Punchant its 3, so XOR word 20 to BB8h in this case.

2 other dongle words, 24 & 3C disable the save and print options so don't XOR them to FFFFh even though they are checked in the same fashion as the others. The final part I had the most trouble with involves a timer which disables various menu options (the save being one), this is the really clever bit of this protection. I tried firstly following how word 24 & 3C disabled the save and after about 15 lines of notes which copied the XOR result many times I gave up. Well what about the timer and menu enabling/disabling API's?, the timer API's I tried broke too much and the menu API's led only to loops inside mfc42.dll, it wasn't going to work.

The way I found the code was eventually quite easy and annoyed me somewhat (because I should have gone there first). I started out by setting a bpx for CreateFileA and clicking my currently enabled save, I then unwound the stack until I reached the menu ID handling procedure which takes the ID parameter via EBX, it turns out the ID for Save is 8127h. Of course bp.exe has no menu resources which is why I didn't find this immediately, instead they are in a file called bpres.dll (yes with a name like that I bet you are all wondering how I missed it :-) ). You'll get here also 8125h as the Save As ID. Lets search for 8127 in W32Dasm and see what we find :-

:0041E102 MOV [ESP+0C], 00008127 <-- HERE.
:0041E646 PUSH 00008127 <-- HERE (dual routine).
:00473213 PUSH 00008127 <-- Search the CALLs.

A quick inspection reveals that the reference at 00473213 is an enabling routine (you can verify that its only reached when word 24 doesn't XOR to FFFFh). The 0041E646 reference is very similar to the one at 0041E102 with ID processing functions following each. I put a bpx on both locations but only 0041E102 hit, my best guess is either that 0041E646 triggers under another set of circumstances (which I couldn't find) or perhaps acts as a dual routine reflecting the disabling back to the screen controls handler. 0041E102 traces back to CALL 0041E090 which is then not referenced any further, in fact its reached via the CALL [EAX+4] at 0041F71B, this is another clever touch.

The CALL [EAX+4] takes a variable base pointer to .rdata (obtained via [ESI]) and then by adding 4 hooks into an array of DWORD's containing the real function addresses. By using a HEX editor we'll also be able to find a reference to CALL 0041E3F0 (our mysterious 2nd reference fished above). How does this help actually us?, well we know from our work thus far that tracing this function higher would not be an option so we'll indulge in some redirection reversing and maybe some more research.

One possible solution would be to change the 2 DWORD's in the .rdata section to point to our own routine, all it would probably need to consist of is a RET and maybe some stack correcting (else we could patch the routine directly to bypass the disabling routines or change the ID pushes to 0). We could also hunt for the 00539F50 base address in the disassembly, as it turns out there is only 1 such reference, a MOV DWORD PTR [ESI], 00539F50 which might or might not be interesting (depending on whether you really want to do a lot more work).

Thats really all there is to see here, the other 2 programs work just like this, Tajima disables a few more options and is a little trickier, Wilcom slightly easier. If you are interested in examining any of these 3 targets for didactical purposes then drop me an e-mail and I'll make the files available. As I have some respect for the authors of this protection you will find no ready-made cracks here, go figure.

  Dongles Return to Main Index

© 1998, 1999, 2000 CrackZ. 28th December 1999.