Guitar Pro v2.2 Demo
[Reversing essay]

Subject: Cracking
Target: Guitar Pro v2.2
Author: BlackB
Date: 2000-06-05
Tools used: SoftICE, w32dasm (or IDA)
Difficulty (scale 1-5): 3.5

Before starting!
This essay is for knowledge purposes only!!
Software developers spend much time in making their programs. They live from the money we give them!
Please buy good software!!
I. Introduction

Hi there! Welcome to this tutorial. I never thought I 'd ever write a tutorial on this bitch of a program. Well, the program is not a bitch, but its protection is. To be honest: this is my toughest target I _ever_ did, and I had many moments I wanted to give up. However, pausing for a couple of hours, doing some other stuff but computer and playing much guitar (*g*) gave me the courage to go on.
I've worked more then 12 hours on this program and with this tutorial it'll probably be 14 hours. Why do I keep doing this? :)
CD_Knight, this tutorial is for you pall ;-)
Please notice that this is only a short summary on what I did to reverse / crack this program!!

II. About the protection
Nag - 30 day trial - CRC - three important limits: Only 24 measures saving, evaluation string on printouts, 50-note limit on ASCII and MIDI importation - "mislead cracker" code
III. Cracking it

Looks quite tough huh? Well it was. Of course, if you read this tutorial, this all won't look that hard because I almost immediately will tell you what path to follow to crack a certain item. But please keep in mind, that if you start cracking this program without any help, you don't know what the best approach will be. Just trying trying and trying different methods leads to a solution!

I started with the easiest part: disabling the nag and time trial: run the program and you'll see it appear. The continue button will appear after a few seconds. For this nag I took the same approach as with the The Bat! nagscreen (see The Bat v1.44 tutorial on my homepage), because it was a similar nagscreen (a TPanel). You can find out with a program named Windowse.
Get the handle of that button (type without quotes 'hwnd gpro' in SoftICE and search for the button handle) and type: bmsg <handle> wm_lbuttonup. This breakpoint will break when you clicked the button. Do so! :)
The goal is that we get out of the call that draws the nag, so we can scroll up in the code and look for a conditional "jump-to-nag-or-not-jump". Press F12 to fasten the process in SoftICE and keep pressing (quite a lot) until you see this when scrolling up:

Start partial code

:004CC614 53                      push ebx
:004CC615 8BD8                    mov ebx, eax
:004CC617 80BBE202000000          cmp byte ptr [ebx+000002E2], 00 (1.)
:004CC61E 7439                    je 004CC659
:004CC620 E817DDF3FF              call 0040A33C (2.)
:004CC625 DCA3D8020000            fsub qword ptr [ebx+000002D8]
:004CC62B DB2DF0C64C00            fld tbyte ptr [004CC6F0]

End partial code

(1.) If ebx+2e2 == 0 then the program is 'registered' and it doesn't need to draw the nag
(2.) This call draws our nag and also contains the evaluation period check. ;-)

To make our patch work for sure, we change the code into:
mov byte ptr [ebx+000002E2], 00
jmp 004CC659

Okay, here ends the easy part of this essay :-P Let's move on to the real stuff!

Let's start with the save-limit. The demo version of Guitar Pro has a 24-measure save limit. This limit, cost me the most time to crack and gave me a terrible headache and a profound feeling of frustration. Let's go.......
Make a new partiture and add more then 24 measures. Save it: File - Save as ......*boom*, we get a messagebox that says that it's a trial version that can't save more then 24 measures. So we set a 'bpx messageboxa'.....File - Save as.......and ......? Damn, SoftICE doesn't break, so it isn't a messagebox. It doesn't break on MessageBox either. I deceided to work with the 'OK' button handle again: bmsg <buttonhandle> wm_lbuttonup. Then again a lot a lot of F12's until you see the messagebox disappear. Then be careful with how many times your press F12. At a certain moment you come across some more 'normal looking' code at a code location 54xxxx. When you scroll up (same method as with nagscreen), you can see the check:

Start partial code

:0054D8DC A128765500              mov eax, dword ptr [00557628]
:0054D8E1 83B8E002000018          cmp dword ptr [eax+000002E0], 00000018 (1.)
:0054D8E8 7E5E                    jle 0054D948
:0054D8EA 66A134DB5400            mov ax, word ptr [0054DB34]
:0054D8F0 50                      push eax
:0054D8F1 6A02                    push 00000002
:0054D8F3 6A00                    push 00000000
:0054D8F5 8D55F0                  lea edx, dword ptr [ebp-10]

* Possible StringData Ref from Code Obj ->"Gene-VersionEvaluation24Mesures"
:0054D8F8 B840DB5400              mov eax, 0054DB40
:0054D8FD E8C6C9FBFF              call 0050A2C8
:0054D902 FF75F0                  push [ebp-10]
:0054D905 6868DB5400              push 0054DB68
:0054D90A 6868DB5400              push 0054DB68
:0054D90F 8D55EC                  lea edx, dword ptr [ebp-14]

* Possible StringData Ref from Code Obj ->"Gene-MerciDeVousEnreg"

End partial code

(1.) If the number of measures is lower then 24 (=18h), then jump. Patch this jle to a jmp.

Now you may ask yourself: Why not searching for these strings (Gene-VersionEvaluation24Mesures) in w32dasm to find the check? Well, because there are really a lot of these strings on different places with the same checkcode, but they are never executed! A first "annoy cracker" code.

A second "annoy cracker" code, in which I put a lot of time are the strings with "Gene-MerciDeVousEnreg" which is French for "ThankYouForRegistering". So I thought it was possible to register the demo (however, there's no option in the program itself for it). I did some further research and found a gpro220.ini file in c:\windows with two 'important looking' strings: V220USER and V220KEY. So I filled in my name and a bogus serial, set a breakpoint on GetPrivateProfileStringA etc..... . To make this short: the user and serial are read but they are never processed! In my opinion it's just a waste of time to find out a method to register the program. It's a real demo!

Anyway, we just patched the save limit. So, let's try it! Open an existing .gtp file provided with the program with more then 24 measures and save it under another filename. Cool :) No more messages. Now open the file you just saved and......baha, did you really think it would be _that_ easy? It doesn't work. Well, let me tell you: the jump we patched is just a jump that only avoids or shows a messagebox, but it isn't the real "Save" check.
As you can see in the code I pasted above, the number of measures is stored in a memory location: [eax+000002E0]. Save your file again with a breakpoint on 0054D8E1, when SoftICE pops, set a 'bpm eax+2e0' and continue. When Guitar Pro saves the file it will break! It looks like this:

Start partial code

:004F5905 A128765500              mov eax, dword ptr [00557628]
:004F590A 83B8E002000018          cmp dword ptr [eax+000002E0], 00000018 (1.)
:004F5911 7E09                    jle 004F591C
:004F5913 C745D018000000          mov [ebp-30], 00000018 (2.)
:004F591A EB0E                    jmp 004F592A

End partial code

(1.) Check again if number of measures and jumps if it's less than 24 (18h).
(2.) Now this is actually interesting: if you have, take 30 measures, GPro stores the max. number of measures in ebp-30.
I won't explain why yet, but it is interesting.

Again, patch this jle to a jmp. Open again an existing .gtp file and save it under another filename. Try to open it. Now Guitar Pro gives an error message: "Already at end of file", but in French, and everything kinda crashes.
Hmmm. At this point I started to become a little bit frustrated. (God may have known how much more I got frustrated). I deceided to compare the filesizes of both original .gtp file and the one I saved under another filename. It was quite obvious: the file I saved was not bigger then 3.677 bytes. I found out that that was the exact size of files with 24 measures. In other words: we didn't patch the real save-limit!
Now what the heck did we patch then? Well, I did some profound reversing on the .gtp files (which I won't explain here) and I found out that the number of measures is stored at location 20Bh of every .gtp file.
Now let me get back to what I said about the mov [ebp-30], 00000018 being interesting: at location ebp-30, the number of measures get stored, to get written at location 20Bh in your .gtp file afterwards. That immediately explains our error message we get when we try to open our saved file. Follow me:

1. Program checks number of measures and shows messagebox if more then 24 measures
2. Program checks number of measures to store at 20Bh in the .gtp file.
3. Program starts writing to .gtp file and as we patched nr. 2, it writes a number greater then 24 measures. (take 30)
4. While writing the program checks how many measures that already have been written (this is the real check). Once 24 measures are written, it stops.
5. We open our saved file......
6. Program reads at location 20Bh that there are 30 measures.
7. Program reads the measures in the file until it's at the end of our .gtp file with the measure counter on 24....but.....location 20Bh told the program that there were 30!

As a concequence, Windows gives a "EOF error" and Guitar Pro crashes. We have to find the real check made in nr. 4.
But how? Well my dear reader, that's the part that sux most of all. I did not know what to do. Because the translation of the notes to hex codes in a .gtp file and the writing to that file is complex to reverse if you only have the asm source of SoftICE!
Anyway, I had no choice and set a breakpoint on Writefile, opened an already existing file (with always more then 24 measures) and saved it under another filename. *Boom* SoftICE breaks. Press F12 three times to get back to the real saving code. Now start tracing (F10) and notice the same portion of code keeps coming back:

Start partial code

:004F577E 6A00                    push 00000000 (1.)
:004F5780 8B1528765500            mov edx, dword ptr [00557628]
:004F5786 B965000000              mov ecx, 00000065
:004F578B 8D8558FEFFFF            lea eax, dword ptr [ebp+FFFFFE58]
:004F5791 E80207F1FF              call 00405E98
:004F5796 E831D0F0FF              call 004027CC (2.)

End partial code

(1.) This and next parameters are pointers to what to save
(2.) This call writes to our file.

Just keep tracing and notice this keeps coming back. Keep tracing and don't forget to get out of loops by setting breakpoints just after them. After a while (not too fast tho) you see this.....and it made me (oh man!) very happy :-)

Start partial code

:004F7075 FF45E8                  inc [ebp-18]
:004F7078 83C304                  add ebx, 00000004
:004F707B 837DE819                cmp dword ptr [ebp-18], 00000019
:004F707F 0F853BEBFFFF            jne 004F5BC0

End partial code

This portion of code is the REAL check ! EBP-18 is the counter of the number of measures. Once the number of measures equals 25, the program jumps out of the saving routine. To patch this, change the 'jne' into 'jmp'. "Yea, that f##king save limit disabled", I thought. And happy I was, I saved a file and reopened it to look if no error messages or faults were displayed......and my god, then frustration really got out of controle and I had to stop for several hours.

As you may have guessed, it didn't work. I thought another check wouldn't be realistic anymore. After some time of thinking, I decided I better knew for sure and I set a breakpoint on 4F707B, saved a file again and when SoftICE broke, I set a 'bpm ebp-18' to check out if the counter was checked somewhere else. And indeed....another nifty, filthy check, that checks if the number of measures exceeds 27! (not 24, probably used to trick us crackers).

Start partial code

:004F5BCB 3B45E8                  cmp eax, dword ptr [ebp-18]
:004F5BCE 0F8CB1140000            jl 004F7085
:004F5BD4 6A00                    push 00000000

End partial code

To patch, nop out the 'jl'.
Now, try to save a file again, reopen it and you'll see that everything will work fine!!

Hehe, that's limit one of three. Two to go :P No, the next two weren't as difficult.

I thought about enabling the import functions first. So I clicked File - Import - Midi. *kaboom* "Access violation at.....". My first thought was that all the patching I previously did, caused the crash. But as I couldn't find any mistake I started thinking about a CRC check.
To be sure, I took the original .exe and changed one little stringbyte on a random place, that had no importance at all. I tried to import and I got the same crash. When I undid the little change I made, it ran fine again. So, obviously a CRC!
Maybe you didn't know, but if a program checks its CRC, it has to open itself with an API like CreateFileA or OpenFile. Therefore many CRC's are easy to find. Set a breakpoint on CreateFileA and click Import - Midi again. SoftICE breaks. Press F12 and trace through the code until you see this suspicious code (I immediately felt it was supicious):

Start partial code

:004A27E4 8BC3                    mov eax, ebx
:004A27E6 E811010000              call 004A28FC (1.)
:004A27EB 3B0598665500            cmp eax, dword ptr [00556698](2.)
:004A27F1 7430                    je 004A2823
:004A27F3 66837B2E00              cmp word ptr [ebx+2E], 0000
:004A27F8 740A                    je 004A2804
:004A27FA 8BD3                    mov edx, ebx
:004A27FC 8B4330                  mov eax, dword ptr [ebx+30]
:004A27FF FF532C                  call [ebx+2C]
:004A2802 EB1F                    jmp 004A2823

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
:004A2804 6A10                    push 00000010

* Possible StringData Ref from Code Obj ->"Program error"
:004A2806 6888284A00              push 004A2888

* Possible StringData Ref from Code Obj ->"This program has been modified "
                                        ->"either by a virus or by a transfer "
                                        ->"problem. It will terminate now."

End partial code

The string "This program has been modified...." never gets displayed btw.
(1.) This call calculates our CRC
(2.) If the program is not modified, the conditional "je" jumps.

To patch, change the 'je' into 'jmp'.
Now try to import and now it works :-). Now we can concentrate on enabling the 50-note importation (MIDI) limit.
I worked a lot on this one too and actually wasted a lot of time: it is very very very hard to locate the check because: is it located when you load the midi file? or when you get the option menu? or when you have clicked 'OK' in the option menu, etc... . There are tons of unimportant code for that import function. I tried with readfile, createfilea, hmemcpy, all sort of success and a big problem.
Then an old w32dasm trick came up in my mind: What if I tried to search in the dead listing for the hex value of 50 (50 notes you know). Hex value is 32h. So I searched for '00000032' and noted all occcurences which looked important......until I found this

Start partial code

* Referenced by a (U)nconditional or (C)onditional Jump at Address:
:0050090A 83FF32                  cmp edi, 00000032
:0050090D 7E38                    jle 00500947
:0050090F 8B15EC735500            mov edx, dword ptr [005573EC]
:00500915 691217070000            imul edx, dword ptr [edx], 00000717

End partial code

EDI contains the number of notes read. It's obvious that you should patch the 'jle' to 'jmp'. ;-)
Now try importing a midi file.....and it works perfectly :))

I also managed to enable the ASCII import function, which is a lot more difficult. As I don't know exactly how the checks work I won't explain it here, but I'll just give you the location where you can find the checks (there are 4 of them in the direct environment of the location I'll give you). They are like cmp [ebp-28], 32 and cmp [ebp-28], 33. Location is: 4D454D

Only one (!!) limit to go: the print string. It's not very difficult, but we'll use some (sloppy?) alternative approach for this. I tried to find a conditional jump that avoids or jumpes to the "PrintEvalString" but I wasn't able to find it. Because it's a demo version, I don't think there actually is a conditional jump to print the string or not.
Alternatively, I did a memory search in SoftICE for the eval string: "s 0 lfffffff 'Evaluation' . Search for next occurences until you see this: Gene-GuitarProVersionEvaluation=Guitar Pro - Evaluation version. If you replace the "Guitar Pro - Evaluation version" with blank spaces, and you do a print preview, or really print, the eval string won't be visible no more. I tried to find out the function that put that message there, but I noticed that it was a procedure used to display all strings in Guitar Pro.
As a method of last resort, I searched for the "Gene-GuitarPro......" string in HIEW and spaced it out.
When printing, or print previewing, another message appeared: "Internal error: Translation not found". Search for that string too in HIEW and space it out. You'll now see that you can print everything like it would be the full version.

Okay, admitted: this is somewhat sloppy, but I didn't see any other method to do so. Besides.....if you don't tamper with the program, this error string isn't needed for anything else!

Third and last limit enabled!!! And I'm finished! Hope you learned something again......and now, I think, it's time for a beer. CHEERS!

IV. In the end

I hate Guitar Pro kinda now :) I ran it soooo many many times that I'm tired of looking at it. But if you just crack this with this tutorial or use a crack.....I'm sure you 'll find it a very good and usefull program (at least if you're into music, like I am).
Personal greets goto CD_Knight (enjoyed it? hehe), Magic Mike and Kayaker (who could give useful info on the registration possibilities of the demo version).

I guess this is the one and only tutorial on Guitar Pro v(anyversion) Demo (until 05-06-2000) and there's also no crack available for it yet. I guess this proves that many crackers are or: 1. not skilled enough to crack this, but more 2. too lazy to crack this or to write a tutorial on it. Get up and reverse, write guys!
Well.....'till next time.....tata!


The Blackbird
Please report bugs in this essay to

Essay written by The Blackbird © 1999-2000
This essay can be freely distributed/ published/ printed etc... as long as no modifications are made.