Program: Nitrus Crackme -- Serial & Sound Nag (VB6)
cracker: r!sc :)

layout: Ripping a Key, Finding the Keygen Routine, Patching the Sound Nag

When: 11th July '99

IMPORTANT: Make sure you have exports for VB6 loaded into SoftICE, if not,
load Symbol Loader click 'File/Load Exports' and select MSVBVM60.DLL,
otherwise, you wont get any breakpoints to work.. :-(


+++++++++++++++++
+Ripping a Key..+
+++++++++++++++++

its programed in visual basic, so i/we try the normal bpx for serial fishing

:bpx __vbastrcmp

then i enter my name & fake serial 'Name:R!SC' / 'Serial:12121212'
click on the missing register button..

Break due to BPX MSVBVM60!__vbaStrCmp

:dd esp l 10     <-- show me the last values push onto the stack
0167:0066F2F8 00402B33  004404F0  00440524  0066F41C      3+@...D.$.D...f.
 RVA of esp   ret addr  lpstring  lpstring  not ours

okay, the fisrt DD is the return address, automatically pushed onto the stack
when a call is executen, then the next two are pointers to the two strings to
compare, so lets take a look at these..

:d 4404f0 l 20
0167:004404F0 00460035  00360037  00350038  00420037      5.F.7.6.8.5.7.B.
0167:00440500 00360034  00340036  00380032  00350036      4.6.6.4.2.8.6.5.
:d 440524 l 20
0167:00440524 00650053  00690072  006C0061  0031003A      S.e.r.i.a.l.:.1.
0167:00440534 00310032  00310032  00310032  00000032      2.1.2.1.2.1.2...

hehe, one looks like our serial, the other one looks like our fake serial, but
with the text 'Serial:' accidentally included.. damn.. so i exit softice, and
delete 'Name:' & 'Serial:' and try again.. WHAT? it doesnt break..hmm
i change my name, to 'R!SC iSD' and try again, hehe, it works, must be a
length check.. further experimenting, the name has to be 5 or more letters...

Break due to BPX MSVBVM60!__vbaStrCmp
Break due to BPX MSVBVM60!__vbaStrCmp
:d esp l 10
0167:0066F2F8 00402B33  004404F0  004404CC  0066F41C      3+@...D...D...f.
                ret     string#1  string#2

:d 4404f0 l 20
0167:004404F0 00300037  00440032  00320037  00430035      7.0.2.D.7.2.5.C.
0167:00440500 00430032  00300039  00320037  00440035      2.C.9.0.7.2.5.D.
:d 4404cc l 20
0167:004404CC 00320031  00320031  00320031  00320031      1.2.1.2.1.2.1.2.
0167:004404DC 00430000  00300039  00000000  A0000034      ..C.9.0.....4...

okay, we got a code? try it..name 'R!SC iSD' serial '702D725C2C90725D'....
hehe, it works.. Registered.. cool..

experiment with some other names, seems the bigger the name, the bigger the
serial, lets dig deeper and see how it makes our serial ?


++++++++++++++++++++++++++++++
+Finding the Keygen Routine..+
++++++++++++++++++++++++++++++

okay, still with bpx __vbastrcmp, click register..hit F11 for return to caller,
see where abouts we are in the 'exe...

Break due to G
:u eip l 10
015F:00402B33  8BF0                MOV     ESI,EAX
015F:00402B35  8D4DD4              LEA     ECX,[EBP-2C]
015F:00402B38  F7DE                NEG     ESI
015F:00402B3A  1BF6                SBB     ESI,ESI
015F:00402B3C  46                  INC     ESI
015F:00402B3D  F7DE                NEG     ESI
015F:00402B3F  FF15CC104000        CALL    [MSVBVM60!__vbaFreeStr]

blah blah blah, lets wdasm it and take a look at this address...scroll up, lets
look at the code before the compare routine, see what we can bpx on to make it
break a bit earlier...

you should find this code..

* Reference To: MSVBVM60.rtcMidCharBstr, Ord:0277h
                                  |
:0040293E FF1548104000            Call dword ptr [00401048]
:00402944 8BD0                    mov edx, eax
:00402946 8D4DD0                  lea ecx, dword ptr [ebp-30]
:00402949 FFD3                    call ebx
:0040294B 50                      push eax

* Reference To: MSVBVM60.rtcAnsiValueBstr, Ord:0204h
                                  |
:0040294C FF1520104000            Call dword ptr [00401020]
:00402952 666BC00B                imul ax, 000B
:00402956 8B55CC                  mov edx, dword ptr [ebp-34]
:00402959 0F80E2020000            jo 00402C41
:0040295F 52                      push edx
:00402960 0FBFF0                  movsx esi, ax

* Reference To: MSVBVM60.__vbaLenBstr, Ord:0000h
                                  |
:00402963 FF150C104000            Call dword ptr [0040100C]
:00402969 8BC8                    mov ecx, eax
:0040296B 8BC6                    mov eax, esi
:0040296D 99                      cdq
:0040296E F7F9                    idiv ecx
:00402970 8D559C                  lea edx, dword ptr [ebp-64]
:00402973 C7459C03000000          mov [ebp-64], 00000003
:0040297A 52                      push edx
:0040297B 8945A4                  mov dword ptr [ebp-5C], eax
:0040297E 8D458C                  lea eax, dword ptr [ebp-74]
:00402981 50                      push eax

* Reference To: MSVBVM60.rtcHexVarFromVar, Ord:023Dh
                                  |
:00402982 FF1598104000            Call dword ptr [00401098]

through another project i'm doing, reversing VB for Dummies, i know about a few
of these procedures

rtcMidCharBstr --  gets a letter from a string
rtcAnsiValueBstr - returns in EAX the value of this letter
__vbaLenBstr ----- returns in EAX the length of a string

hehe, pretty normal serial gen routines.. lets set a bpx on rtcMidCharBstr &
trace from there with F10..

:bpx rtcmidcharbstr
Break due to BPX MSVBVM60!rtcMidCharBstr    (then hit F11)
Break due to G
:d eax l 10
0167:00540FEC 00000052  00000000  00000000  00540FE4      R.............T.

the first letter from the name?
trace over 'rtcAnsiValueBstr'

:?eax
00000052  0000000082  "R"

got the ascii value of the letter in EAX now..
next instruction is 'imul ax, 000B' eax=eax*11

:?eax
00000386  0000000902  ""

keep tracing, '__vbaLenBstr' returns 8 in eax, 'R!SC iSD' is 8 characters...

:?eax
00000008  0000000008  ""

it then moves the length into ecx, gets the letter*11 back into eax..
and then 'idiv ecx' , letter*11/len ?

:?eax
00000070  0000000112  "p"

70 happens to be the first value in my serial...
hit F5, then trace again, see if it gets the right answer for the next letter

Break due to BPX MSVBVM60!rtcMidCharBstr
Break due to G
:d eax l 10
0167:00540FEC 00000021  00000000  00000000  00540FE4      !.............T.
:?eax
00000021  0000000033  "!"   <--rtcAnsiValueBstr
:?eax
0000016B  0000000363  "k"  <-- imul eax,0B
:?eax
0000002D  0000000045  "-"   <-- idiv ecx

yep, looks right, 702D....


* Reference To: MSVBVM60.rtcMidCharBstr, Ord:0277h
                                  |
:0040293E FF1548104000            Call dword ptr [00401048]     <-- gets a char from our name
:00402944 8BD0                    mov edx, eax
:00402946 8D4DD0                  lea ecx, dword ptr [ebp-30]
:00402949 FFD3                    call ebx
:0040294B 50                      push eax

* Reference To: MSVBVM60.rtcAnsiValueBstr, Ord:0204h
                                  |
:0040294C FF1520104000            Call dword ptr [00401020]     <-- returns ascii value in EAX
:00402952 666BC00B                imul ax, 000B                 <-- multiply it with 11 decimal
:00402956 8B55CC                  mov edx, dword ptr [ebp-34]
:00402959 0F80E2020000            jo 00402C41                   <-- jo to overflow routine.. ignore
:0040295F 52                      push edx
:00402960 0FBFF0                  movsx esi, ax                 <-- save letter*11 in si

* Reference To: MSVBVM60.__vbaLenBstr, Ord:0000h
                                  |
:00402963 FF150C104000            Call dword ptr [0040100C]     <-- get length in eax
:00402969 8BC8                    mov ecx, eax                  <-- move length into eax
:0040296B 8BC6                    mov eax, esi                  <-- copy letter*11 back to EAX
:0040296D 99                      cdq                           <-- convert double to quad (clears edx..)
:0040296E F7F9                    idiv ecx                      <-- divide eax by whatever
:00402970 8D559C                  lea edx, dword ptr [ebp-64]
:00402973 C7459C03000000          mov [ebp-64], 00000003
:0040297A 52                      push edx
:0040297B 8945A4                  mov dword ptr [ebp-5C], eax
:0040297E 8D458C                  lea eax, dword ptr [ebp-74]
:00402981 50                      push eax

* Reference To: MSVBVM60.rtcHexVarFromVar, Ord:023Dh            <-- convert our answer to ASCii ?
                                  |
:00402982 FF1598104000            Call dword ptr [00401098]


okay, we have the maths.. goes something like this..

for (i=0;i<length[name];i++) {
x=name[i];
x=x*11;
x=x/length[name];
serial[i]=x;
};

i can only code in asm, so i have included serial gen routine in asm only,
seperate file..


++++++++++++++++++++++++
+Patching the Sound Nag+
++++++++++++++++++++++++

Okay, i was kinda lucky.. i thought, sound==*.wav, so i search the exe for
ascii text, find where the WAV file is, and corrupt the header.. as you know,
corrupt headers can seriously screw up anything, Zip files, Jpeg's, Exe's..

00005780 52 49 46 46 32 D0 02 00 57 41 56 45 66 6D 74 20 RIFF2...WAVEfmt 

i changed it to all spaces, like this

00005780 20 20 20 20 20 D0 02 00 20 20 20 20 20 20 20 20      ...        

ran the crackme, and sure enough, no sound nag!! and luck was on my side,
as there was no crash aswell.. further experimenting, i found out i just had
to change one single letter in the header..

00005780 52 49 46 46 32 D0 02 00 57 41 56 45 66 6D 74 20 RIFF2...WAVEfmt 
                                                         ^^^^^   ^^^^^^^
                                                         
edit any single one of the marked letters, and the sound nag goes away.. :)


okay, hope this was helpful to you, and you know know not to be scared of VB
(well, most VB, some VB is scary, but, its still fun to reverse..)

laters, love R!SC


