UGFLEX
modified flexlm by UNIGRAPHICS
student
Not Assigned
15.11.1999
by macilaci
Courtesy of Fravia's page of reverse engineering
slightly edited
by tsehp
There is a crack, a crack in everything That's how the light gets in
Rating
(X)Beginner (X)Intermediate ( )Advanced ( )Expert

YES. Flexlm for newbies. Presented by UNIGRAPHICS.
UGFLEX
modified flexlm by UNIGRAPHICS
Written by macilaci


Introduction
When you are interested in CAD software you may noticed, that UNIGRAPHICS company released 
a free software named SolidEdgeOrigin. This well programmed software uses the latest parasolid engine. 
However the UGs added some nonfunctionality to this program. You will create a model - all ok.
You can save  it to disk /yeah..you think../, but when you create a drawing from the model.... 
You will be unable to save the drawing- UG starts asking for money. And this makes the soft unusable. 
Why create the model when you are unable to make drawings from that? The answer is the marketing strategy. 
AutoCad users should learn a new approach... Do you guess it now? 
Anyway, you will come to a point when you decide whether to buy the license for SolidedgeOrigin3D or not.  



Tools required
Softice or any other win32 debugger, Wdasm or IDA 3.75 brain and essays on flexlm /*S+H,pillgrim,etc.*/

Target's URL/FTP
http://www.ugsolutions.com, http://www.solid-edge.com /*ask for your free CD*/

Program History
flexlm.../*globetrotter*/

Essay
Part One 

Our target uses the Globetrotter's flexlm protection. When you have the 
license key for SolidEdgeOrigin create 
a license file using SolidEdge registration wizard. The license file looks 
like this: 


FEATURE solidedgeorigin uglmd 7.0 permanent uncounted XXXXXXXXXXXX \ 
HOSTID=ANY 

The XXXXXXXXXXX is your CD key /*hexadecimal numbers*/. 

Let's load the ugflex.dll to Wdasm and look at the exports: FLEX__enter is 
the most near to the lc_init in noticed essays. Put a breakpoint on the entry 
to this fuction. /* Tip for newbies - use the addr command after application start*/ 
Get your feature names. On the FLEX__enter dd eax and voila... 
Create a fake license file: /* Selicense.dat*/ 

FEATURE solidedgeorigin uglmd 7.0 permanent uncounted 123456789123 \ 
HOSTID=ANY 

FEATURE solidedgeorigin3d uglmd 7.0 permanent uncounted 123456789123 \ 
HOSTID=ANY 

FEATURE solidedgeboxset uglmd 7.0 permanent uncounted 123456789123 \ 
       HOSTID=ANY 

FEATURE solidedgeclassic uglmd 7.0 permanent uncounted 123456789123 \ 
       HOSTID=ANY 

FEATURE solidedgeassembly uglmd 7.0 permanent uncounted 123456789123 \ 
       HOSTID=ANY 

FEATURE solidedgesheetmetal uglmd 7.0 permanent uncounted 123456789123 \ 
       HOSTID=ANY 

FEATURE solidedgexpresroute uglmd 7.0 permanent uncounted 123456789123 \ 
       HOSTID=ANY 

FEATURE solidedgefeaturereco uglmd 7.0 permanent uncounted 123456789123 \ 
       HOSTID=ANY 


Part Two 

After this run again the target. I used the part.exe file. You will get a 
message -8,130 - error. And another one that you don't have any valid license. 
Run it again this time with bpx on FLEX__enter. 
Press F12 until you get to part.exe module. 

10001568                 mov     edx, [esp+24h+var_20] 
1000156C                 push    edx 
1000156D                 call    j_JUTIL_1101 
10001572                 test    eax, eax ; our landing point 
10001574                 jl      short loc_100015BE ;jump 
. 
. 
. 
100015BE                 lea     ecx, [esp+28h+var_24] 
100015C2                 push    ecx 
100015C3                 call    j_JUTIL_700 
100015C8                 add     esp, 4 
100015CB                 test    eax, eax 
100015CD                 jnz     short loc_100015DD ;jump 
100015CF                 test    esi, esi 
100015D1                 jz      short loc_100015DD ;jump 
100015D3                 mov     eax, 1 ;load dll's and run it 
100015D8                 pop     esi 
100015D9                 add     esp, 20h 
100015DC                 retn 
100015DD                 xor     eax, eax ;bad user - no license 
100015DF                 pop     esi 


Run it with your valid license number obtained from UGs. You will see the difference... 
Run the Part.exe with your fake license number. But what, when you bpx on the 100015CB in the part.exe 
some strange thing happen. Yes I speak about this page fault. Let's clear the bpx and run it. 
All is OK. You will get the -8,130 message. Do you feel the CRC check? Yes I guessed it too. Do the bpx 100015CB 
again but this time with bpm 100015CB. 

10001501                 mov     edx, eax 
10001503                 xor     ebx, ebx 
10001505                 mov     bl, [ecx]                  ; you land here before the page fault 
10001507                 and     edx, 0FFh 
1000150D                 xor     edx, ebx 
1000150F                 shr     eax, 8 
10001512                 mov     edx, dword_10006054[edx*4] 
10001519                 xor     eax, edx 
1000151B                 inc     ecx 
1000151C                 dec     esi 
1000151D                 jnz     short loc_10001501 
1000151F                 pop     ebx 
10001520                 not     eax 
10001522                 pop     esi 
10001523                 retn 

Get one level up with F12. You see: 

10001715                 mov     edx, dword_10006C78 
1000171B                 mov     eax, dword_10006C74 
10001720                 push    edx 
10001721                 push    eax 
10001722                 call    sub_100014F0 ;our call 
10001727                 mov     ecx, dword_10006C7C         ;load the correct CRC 
1000172D                 add     esp, 8 
10001730                 cmp     eax, ecx ;compare 
10001732                 jz      loc_10001819 ;jump if OK 
. 
. 
1000174E                 push    offset aCrcBuffer_8xCo       ;bad boy 
10001753                 push    eax 
10001754                 call    ds:sprintf 
1000175A                 add     esp, 14h 
1000175D                 lea     ecx, [esp+540h+var_20C] 
10001764                 push    ecx 
10001765                 call    ds:OutputDebugStringA 

Another exples:  Bpx in Jutil.dll module. The CRC check is done right 
before the our part.exe CRC check: 

100016C6                 push    3BF0h 
100016CB                 push    eax 
100016CC                 call    sub_100014F0 
100016D1                 add     esp, 8 
100016D4                 cmp     eax, 464E4B2Eh        ;looks like CRC 
100016D9                 jnz     loc_1000176B ;jump if bad 
100016DF                 lea     ecx, [esi+1350h] 
100016E5                 push    130h 
100016EA                 push    ecx 
100016EB                 call    sub_100014F0 
100016F0                 add     esp, 8 
100016F3                 cmp     eax, 1A78AC1Ch         ;this too 
100016F8                 jnz     short loc_1000176B 
100016FA                 add     esi, 3A1F0h 
10001700                 push    0D8h 
10001705                 push    esi 
10001706                 call    sub_100014F0 
1000170B                 add     esp, 8 
1000170E                 cmp     eax, 4D03231Ah         ;oops 
10001713                 jnz     short loc_1000176B 

To keep our debugging session comfortable modify the jumps. 

Let's continue with our BPX 100015CB. 

1000156C                 push    edx 
1000156D                 call    j_JUTIL_1101 
10001572                 test    eax, eax ; our old landing point 
10001574                 jl      short loc_100015BE ;jump if bad 
. 
. 
. 
100015BE                 lea     ecx, [esp+28h+var_24] 
100015C2                 push    ecx 
100015C3                 call    j_JUTIL_700 
100015C8                 add     esp, 4 
100015CB                 test    eax, eax 
100015CD                 jnz     short loc_100015DD ;jump if bad 
100015CF                 test    esi, esi 
100015D1                 jz      short loc_100015DD ;jump if bad 

Examine the JUTIL_700 call - you will see that this is just playing with 
numbers. The real deal is the JUTIL_1101. 
Bpx there and step in... 

5A00F870                 sub     esp, 20h 
5A00F873                 lea     eax, [esp+20h+var_20] 
5A00F877                 mov     [esp+20h+var_1C], offset loc_5A00C690 
;create jump table 
5A00F87F                 push    eax 
5A00F880                 mov     [esp+24h+var_18], offset loc_5A00CDB0 ;create jump table 
5A00F888                 mov     [esp+24h+var_14], offset loc_5A00D4D0 ;create jump table 
5A00F890                 mov     [esp+24h+var_10], offset loc_5A00DBF0 ;create jump table 
5A00F898                 mov     [esp+24h+var_C], offset loc_5A00E310 ;create jump table 
5A00F8A0                 mov     [esp+24h+var_8], offset loc_5A00EA30 ;create jump table 
5A00F8A8                 mov     [esp+24h+var_4], offset loc_5A00F150 ;create jump table 
5A00F8B0                 call    ds:time                              ;get random value 
5A00F8B6                 mov     eax, [esp+24h+var_20] 
5A00F8BA                 mov     ecx, 7 
5A00F8BF                 cdq 
5A00F8C0                 idiv    ecx 
5A00F8C2                 mov     eax, [esp+24h+arg_0]                 ;reduced to 7 cases 
5A00F8C6                 push    eax 
5A00F8C7                 call    [esp+edx*4+28h+var_1C]               ;jump 
5A00F8CB                 add     esp, 28h 
5A00F8CE                 retn    4 

As you see the the code at different locations is the same. What does this 
mean ? Answer: To gather newbies getting informations about this target. 
You can set the edx value to zero. 

Step in the 5A00C690. 
5A00C8FA loc_5A00C8FA:                  ; CODE XREF: .text:5A00CA8B_j 
5A00C8FA               mov     ecx, [esp+3Ch] 
5A00C8FE                add     ecx, edi 
5A00C900                cmp     [ecx+10h], ebx 
5A00C903                 jz      loc_FFFFF000_5A00CA78 ;jump if nofeature 
. 
. 
5A00CA78                 mov     edi, [esp+10h] 
5A00CA7C                 mov     ecx, [esp+40h] 
5A00CA80                 inc     ebp 
5A00CA81                 add     edi, 14h 
5A00CA84                 dec     ecx 
5A00CA85                 mov     [esp+10h], edi 
5A00CA89                 cmp     ebp, ecx ;all licenses checked? 
5A00CA8B                 jle     loc_5A00C8FA ;jump if not 

And inside this cycle  /*if the name of  feature was found*/: 


5A00C987                 push    eax 
5A00C988                 push    ecx 
5A00C989                 call    sub_5A010480 ;check license 
5A00C98E                 add     esp, 2Ch 
5A00C991                 test    eax, eax ;it's OK? 
5A00C993                 jz      short loc_5A00C9DE ;jump if not 
5A00C995                 mov     edx, [esp+40h] 
5A00C999                 lea     esi, [ebp+1] 
5A00C99C                 dec     edx 
5A00C99D                 cmp     esi, edx 
5A00C99F                 jg      loc_5A00CA78 

You can set the jump to nops at 5A00C993 but the license is still not 
available. So step into the 5A010480 call. 


5A010508                 mov     ecx, dword_5A03CBB4 
5A01050E                 push    eax 
5A01050F                 call    sub_5A026660 ; compare license 
5A010514                 mov     ebx, eax 
5A010516                 lea     ecx, [esp+9Ch+var_5C] 
5A01051A                mov     byte ptr [esp+9Ch+var_4], 4 
5A010522                 call    ??1GUserText@@QAE@XZ 

Look at the eax poiter - our feature names, step into 5A026660. 

5A026691                 mov     ecx, [esp+2Ch+arg_4] 
5A026695                 push    ecx 
5A026696                 push    edx 
5A026697                 call    j_FLEX__set_product_version 
5A02669C                 lea     eax, [esp+34h+var_20] 
5A0266A0                 push    1 
5A0266A2                 push    eax 
5A0266A3                 call    j_FLEX__enter ;we started here 
5A0266A8                 add     esp, 10h 
5A0266AB                 mov     ecx, ebx 
5A0266AD                 mov     esi, eax 
5A0266AF                 call    sub_5A026D50 
5A0266B4                 mov     ecx, [esp+2Ch+arg_8] 
5A0266B8                 test    esi, esi 
5A0266BA                 mov     [ecx], eax 
5A0266BC                 jnz     short loc_5A0266DA 
5A0266BE                 lea     edx, [esp+2Ch+var_20]                ; license ok, continue 

Don't modify the jump - it doesn't make any sense, just step into a 
FLEX_enter. 

04E514EE                 push    esi 
04E514EF                 mov     esi, [esp+4+arg_0] 
04E514F3                 push    esi 
04E514F4                 push    offset aEnteringModule ; entering module 
04E514F9                 call    FLEX__note 
04E514FE                 mov     eax, dword_4E81DA8 
04E51503                 push    4000h 
04E51508                 push    offset unk_4E7C130 
04E5150D                 push    0 
04E5150F                 push    1 
04E51511                 push    offset a15_0 
04E51516                 push    esi 
04E51517                 push    eax 
04E51518                 mov     dword_4E80410, 1 
04E51522                 call    sub_4E53481 ;yep , this call - step in 
04E51527                 mov     esi, eax 
04E51529                 add     esp, 24h 
04E5152C                 test    esi, esi 
04E5152E                 jge     short loc_4E51552 
04E51530                 cmp     [esp+4+arg_4], 1 
04E51535                 jnz     short loc_4E51540 
04E51537                 push    esi 
04E51538                 call    sub_4E519E0 ; ugflexlmerror 

04E53481... 
. 
. 
. 
04E534F5                 mov     dword_4E80948, offset 04E53669 
04E534FF                 or      byte ptr [esi+17Ch], 40h 
04E53506                 push    esi 
04E53507                 call    dword_4E80948 ;step in 

An indirect call - this might be... 

04E53669... 
. 
. 
. 
04E53827                 push    edi 
04E53828                 push    esi 
04E53829                 call    sub_4E53E77 
04E5382E                 add     esp, 0Ch 
04E53831                 test    eax, eax        ; eax should not be 
zero 
04E53833                 jz      loc_4E53726 ; jump if bad boy 
04E53839                 cmp     dword ptr [ebp+18h], 3 
04E5383D                 jz      loc_FFFFF000_4E53924 
04E53843                 push    edi ;license OK -continue 

When you patch the jump at 04e53831 you will get the right license for our 
fake license file. And how to get this? 
I've just compared the jumps with the valid SolidEdgeOrigin key /*remember, it's for free*/. 
Here is the jump at location -compare table: 
SolidEdgeOrigin Our feature with fake key 
     04E536A1       04E536A1 
     04E536D7       04E536D7 
     04E5371E       04E5371E 
     04E53749       04E53749 
     04E5377F       04E5377F 
     04E537A2       04E537A2 
     04E537F3       04E537F3 
                    04E53833 
     etc.                       etc. 

You see - nothing special. 


Part three - let's patch it 


Patch the location in ugflex at 04E53833 to some nops. And of course keep 
the fake license file in the directory. The part.exe you can overwrite with original version. 
To prevent lamers from detecting which file was changed /*the about box - 
setup info- */ change some bytes in partDcx.dll at 075B77FA to nops. 
You will get the complete copy of  SolidEdge 7.0 -YES all modules!!! 


Final Notes
This is a nice example to show the commercial stupidity  - how to license a feature or how to make more money with less effort. 
Poor programmers...  Dear programmers if you are reading this, you should improve your product and sell it at nice price. 
Then more people will buy it  /*The effect of scale- ask marketers - they should know it and if not, there's a problem*/.   



Ob Duh
I wont even bother explaining you that you should BUY this target program if you intend to use it for a longer period than the allowed one. Should you want to STEAL this software instead, you don't need to crack its protection scheme at all: you'll find it on most Warez sites, complete and already regged, farewell, don't come back.

You are deep inside Fravia's page of reverse engineering, choose your way out:


redhomepage redlinks redsearch_forms red+ORC redhow to protect redacademy database
redreality cracking redhow to search redjavascript wars
redtools redanonymity academy redcocktails redantismut CGI-scripts redmail_Fravia+
redIs reverse engineering legal?