L ZZZZZZ RRRRR SSSSS L Z R R S L aaa Z aaa R R u u S L a Z a RRRRR u u SSSSS XX L aaaa Z aaaa R R u u S XXXX L a a Z a a R R u u S XXXXXX LLLLLLL aaaaa ZZZZZZZ aaaaa R R uuuuu SSSSSS XXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX XXXXXX XXXXXX XXXX proudly presents his 23.Cracking Tutorial (06.07.1999) XX Cracking VB5 progs with W32Dasm I. Introduction II. The essay III. BTW IV. All Tutorials by LaZaRuS I. Welcome to my 23st cracking tutorial. Yep, I know: There's a handy little tool call Smartcheck. I tried to download it once, but I got a corrupted RAR file. D/l it again? Nah, not with my "turtle"-connection. I already have a disassembler and a debugger: W32Dasm and SICE. Actually there are some guys that say the only thing you get for VB progs in W32Dasm is garbage. *Completely* wrong. It's just a matter of interpretation. A VB5 prog in W32Dasm does (generally) look like a W32Asm prog without string references. The main difference is that VB progs are *easier* to crack. It seems obvious that VB coders use the predefined functions for the comparison of the good/bad serial. (and btw: razzia didn't have Smartcheck for his famous VB essay, too :P) As examples I take two CrackMe's of BuLLeT (1.75 and 2.75). I.1 W32Dasm 8.9 BuLLeT's CrackMe 1.75 BuLLeT's CrackMe 2.75 Audio List Maker 1.52.1016 II. The essay Let's start with the first CrackMe. When you disassemble it you will nothing but the functions that are called MSVBVM50.DLL. Import Module 001: MSVBVM50.DLL Addr:0F0399BC hint(0000) Name: _CIcos Addr:0F0E7F94 hint(0000) Name: _adj_fptan Addr:0F0E7855 hint(0000) Name: _adj_fdiv_m64 Addr:0F0E7EDC hint(0000) Name: _adj_fprem1 Addr:0F02B4EB hint(0000) Name: __vbaHresultCheckObj Addr:0F0E7809 hint(0000) Name: _adj_fdiv_m32 Addr:0F01E2F2 hint(0000) Name: __vbaObjSet Addr:0F0E78A1 hint(0000) Name: _adj_fdiv_m16i Addr:0F0E79A1 hint(0000) Name: _adj_fdivr_m16i Addr:0F0399B2 hint(0000) Name: _CIsin Addr:0F01F90B hint(0000) Name: __vbaChkstk Addr:0F02299D hint(0000) Name: EVENT_SINK_AddRef Addr:0F01F8F6 hint(0000) Name: __vbaStrCmp Addr:0F0E7F91 hint(0000) Name: _adj_fpatan Addr:0F037FD1 hint(0000) Name: EVENT_SINK_Release Addr:0F0342BF hint(0000) Name: _CIsqrt Addr:0F03634A hint(0000) Name: EVENT_SINK_QueryInterface Addr:0F022B59 hint(0000) Name: __vbaExceptHandler Addr:0F0E7C24 hint(0000) Name: _adj_fprem Addr:0F0E7955 hint(0000) Name: _adj_fdivr_m64 Addr:0F10A1A4 hint(0000) Name: __vbaFPException Addr:0F0342B5 hint(0000) Name: _CIlog Addr:0F0E78D5 hint(0000) Name: _adj_fdiv_m32i Addr:0F0E79D5 hint(0000) Name: _adj_fdivr_m32i Addr:0F0E7909 hint(0000) Name: _adj_fdivr_m32 Addr:0F0E7344 hint(0000) Name: _adj_fdiv_r Addr:0F00A1BF hint(0064) Name: ThunRTMain Addr:0F0342AB hint(0000) Name: _CIatan Addr:0F0EA765 hint(0000) Name: _allmul Addr:0F0EA75B hint(0000) Name: _CItan Addr:0F01F2DD hint(0000) Name: _CIexp Addr:0F01F878 hint(0000) Name: __vbaFreeStr Addr:0F01DC7F hint(0000) Name: __vbaFreeObj Some of the names are selfexplaining, some of them are cryptic, but some of them have an interesting name: At least __vbaStrCmp - Doesn't it sound like StringCompare? Let's search for appearances in the deadlisting. The first one is obviously not the one that compares the good serial with the one you entered (Look at it and you'll see). The second (and last) one looks more interesting. * Referenced by a (U)nconditional or (C)onditional Jump at Address: |:004106D3(C) | :004106E6 FF75E8 push [ebp-18] :004106E9 6850014100 push 00410150 * Reference To: MSVBVM50.__vbaStrCmp, Ord:0000h | :004106EE E8C509FFFF Call 004010B8 :004106F3 8BD8 mov ebx, eax :004106F5 8D4DE8 lea ecx, dword ptr [ebp-18] :004106F8 F7DB neg ebx :004106FA 1BDB sbb ebx, ebx :004106FC 43 inc ebx :004106FD F7DB neg ebx Enter the debug mode of W32Dasm and set a breakpoint on :004106E9. Then trace into the next call. Tracing little further, you'll come to this: __vbaStrCmp() :0F01F8F6 push [esp+08] :0F01F8FA push [esp+08] :0F01F8FE push 00000000 :0F01F900 call MSVBVM50.__vbaStrComp :0F01F905 movsx eax, ax :0F01F908 ret 0008 MSVBVM50.__vbaStrComp? It's getting interesting, isn't it? Trace into this one, too. __vbaStrComp() :0F003563 push ebp :0F003564 mov ebp, esp :0F003566 push ebx :0F003567 push esi :0F003568 push edi :0F003569 cmp dword ptr [ebp+10], 00000000 // [ebp+10] points to the first string :0F00356D mov esi, 00000000 :0F003572 je 0F00357A // if first string = "", then jump :0F003574 mov eax, dword ptr [ebp+10] //Here is the first string that is compared :0F003577 mov esi, dword ptr [eax-04] //ESI = Length(first string)*2 :0F00357A cmp dword ptr [ebp+0C], 00000000 //[ebp+0C] points to the second string :0F00357E mov edi, 00000000 :0F003583 je 0F00358B :0F003585 mov ecx, dword ptr [ebp+0C] // ECX = second string that is compared :0F003588 mov edi, dword ptr [ecx-04] // EDI = Length(second string)*2 :0F00358B cmp edi, esi // compare stringlength of both strings :0F00358D mov ebx, edi // save lenght of second string in EBX :0F00358F jnb 0F0035B6 // if string two has less chars, then string one, then jump :0F003591 cmp dword ptr [ebp+08], 00000000 :0F003595 jne 0F0035CD :0F003597 test ebx, ebx :0F003599 je 0F0035C3 :0F00359B mov eax, ebx :0F00359D shr eax, 1 :0F00359F push eax :0F0035A0 push [ebp+0C] // points to second string :0F0035A3 push [ebp+10] // points to first string :0F0035A6 call MSVBVM50.0F00D9EA // this one compares them "really" and sets flag :0F0035AB test eax, eax // if they are the same :0F0035AD je 0F0035BA // then jump :0F0035AF pop edi // else return from call with "Not same" flag :0F0035B0 pop esi :0F0035B1 pop ebx :0F0035B2 pop ebp :0F0035B3 ret 000C :0F0035B6 mov ebx, esi :0F0035B8 jmp MSVBVM50.0F003591 Here is the call at :F0035A6 that compares the two strings really. :0F00D9EA push esi // save esi :0F00D9EB push edi // save edi :0F00D9EC mov edi, dword ptr [esp+10] // edi = first string :0F00D9F0 mov esi, dword ptr [esp+0C] // esi = second string :0F00D9F4 mov ecx, dword ptr [esp+14] // ecx = length of both strings :0F00D9F8 xor eax, eax // erase eax :0F00D9FA repz // this one :0F00D9FB cmpsw // compares them :0F00D9FD je 0F00DA04 // if they are equal, then jump :0F00D9FF sbb eax, eax // else :0F00DA01 sbb eax, FFFFFFFF // set "not equal" flag :0F00DA04 pop edi // restore edi :0F00DA05 pop esi // restore esi :0F00DA06 ret 000C // return from call What do I want to show you? Just that every standard comparison of two strings must pass this lines of code. So breakpointing with SICE at :0F00D9F4 would easily reveal which strings are compared. Another example: BuLLeT's CrackMe 2.75: In this CrackMe we have no __vbaStrCmp :( - The important call is __vbaVarTstEq. The second appearance is the correct here, too. After some tracing (enter every callyou come - Yeah guess where you come. You will come to __vbaStrComp() again and then to the passage described above where the two strings are compared. :0F00D9EC mov edi, dword ptr [esp+10] // edi = real serial :0F00D9F0 mov esi, dword ptr [esp+0C] // esi = serial, you entered Just as I said: No matter which method of comparison is used by the programmer, this part of code will always be executed. One string will always be in esi, the other one will always be in edi. btw: I nearly forgot The serial for the first CrackMe is 2hard4u2crackm8 The serial for the second CrackMe is 2rK4HJ4-7n8RgT09IW6a7kSlg33 Attention: Remember that strings in VB are stored in "Wide char" format like this: [edi+00000000] - 00720032 2.r. [edi+00000004] - 0034004b K.4. [edi+00000008] - 004a0048 H.J. [edi+0000000C] - 002d0034 4.-. [edi+00000010] - 006e0037 7.n. [edi+00000014] - 00520038 8.R. [edi+00000018] - 00540067 g.T. [edi+0000001C] - 00390030 0.9. [edi+00000020] - 00570049 I.W. [edi+00000024] - 00610036 6.a. [edi+00000028] - 006b0037 7.k. [edi+0000002C] - 006c0053 S.l. [edi+00000030] - 00330067 g.3. [edi+00000034] - 00000033 3... Just get rid of every 00h and you will get the serial. Farthermore the wide char format is the reason, that not the "real" length of the strings is compared, but length*2. Eh, do I still hear doubts in your voice? Just CrackMes? Small deadlisting? I had luck? May a crack for a "real" program convince you? OK, here it comes. The target is Audio List Maker 1.52.1016. The EXE file is 355 KB big, the deadlisting is 6445KB. I hope that satisfies you. There are quite many __vbaStrCmp in the listing, but that shouldn't frighten us. With some *zen* we can easily eliminate most. When you enter a wrong serial, a messagebox appears. I believe that there's a messagebox when you enter a correct serial, too. Now it's only speculation, but we will later see, that it is indeed so. So look at the __vbaStrCmp calls and you will soon find this one: :0044877B 8B55E4 mov edx, dword ptr [ebp-1C] ;; point to real serial :0044877E 8B45D8 mov eax, dword ptr [ebp-28] ;; point to entered serial :00448781 52 push edx ;; save real serial to stack :00448782 50 push eax ;; save entered serial to stack * Reference To: MSVBVM50.__vbaStrCmp, Ord:0000h | :00448783 FF1540824500 Call dword ptr [00458240] ;; compare them and set flag :00448789 85C0 test eax, eax ;; test flag :0044878B 0F85B6050000 jne 00448D47 ;; if not set, then jump to "beggar off" I strongly believed that this one is "our" __vbaStrCmp, as there is a conditioned jump right after the call that jumps to a MessageBox (MSVBVM50.rtcMsgBox). If the jump is not taken, a messagebox will appear, too. Read the real serial out at :0044877B. For LaZaRuS it is ALM4-3111-7951-9X2K where the "-" mustn't be entered in the program as there are only 16 chars allowed. Alright, I know what you are saying. When the serials are pushed in front of the __vbaStrCmp why did we trace into the call in the two CrackMes??? Imagine that there are some ways to hide the __vbaStrCmp in the deadlisting (for example: call edi - the indirect call through a register). In a deadlisting there won't be much chances to find that, but if you put a breakpoint on the correct place inside the __vbaStrComp() function you can easily find the addresses that call the __vbaStrCmp with the help of SICE. III. BTW Greets to: tKC, Ed!son, Moral Insanity, +Sandman, Fravia+ and everyone at #cracking4newbies, +Sandman's forum and Fravia+'s forum. IV. All tutorials by LaZaRuS