Winamp "real practice" tutorial
Part of Crashtest's tutorial #1

Click here to jump back to the main file.


0 ) Introduction

1 ) A patching serial approach
1.1 ) Raw dump
1.2 ) Analyzed dump

2 ) The key generator approach


0 ) Introduction

Winamp is surely one of the most famous MP3 player. but most people ignore what the protection is for.
I don't either. It's just a financial support , I guess. No actual protection.

I'm dealing with Winamp 2.091. but the protection is the same since Winamp 2.00
The program expects an integer as a serial.
There is no "Wrong serial" message box, so we can't break on that.
The other basic solution is to break on serial reading.
That's what we'll do.

1 ) A patching serial approach

Run Winamp. Click on "Enter Registration Info"
Type your name. Mine will be "Crashtest [tNO '99]"

Well. it's obvious that the prog is checking your serial everytime you type something.
So. let's put a breakpoint.
start typing some number.
Here, '6734'
Then fire Softice (ctrl+d, for instance)
type bpx hmemcpy and go back to winamp window. (F5)
type '1'
You are now in the winamp program. but it has called the user.dll...

1.1 ) Raw dump

Here is exactly what happened. directly dumped from Softice by the symbol loader.
Non newbies will automatically understand. but if you need comments, scroll down to 1.2 )

Break due to BPX KERNEL!HMEMCPY  (ET=612.80 milliseconds)
KERNEL!HMEMCPY
1787:1D5C  PUSH    DWORD PTR [SI+20]
1787:37B0  OR      AX,AX
1787:3A18  OR      AX,AX
Break due to BPX KERNEL!HMEMCPY  (ET=2.70 microseconds)
1787:0B45  PUSH    WORD PTR [DI]
1787:27B9  SUB     DX,DX
1787:0C0D  POP     DS
17BF:82E7  POP     EDI
17B7:4BC0  RET
1797:2A05  JMP     2A16                                              (JUMP )
1797:4697  POP     CX
0187:0028  JMP     014F:BFF72964
014F:0040260B  PUSH    00
:u cs:eip
014F:0040260B  PUSH    00
014F:0040260D  PUSH    00
014F:0040260F  PUSH    EBX
014F:00402610  PUSH    EDI
014F:00402611  CALL    [USER32!GetDlgItemInt]
014F:00402617  MOV     ESI,EAX
014F:00402619  LEA     EAX,[EBP-80]
014F:0040261C  PUSH    EAX
:bl
00)   BPX KERNEL!HMEMCPY
:bd 0
:bl
00) * BPX KERNEL!HMEMCPY
014F:0040260D  PUSH    00
014F:0040260F  PUSH    EBX
014F:00402610  PUSH    EDI
014F:00402611  CALL    [USER32!GetDlgItemInt]
014F:00402617  MOV     ESI,EAX
:? eax
0001070D  0000067341  ""
014F:00402619  LEA     EAX,[EBP-80]
014F:0040261C  PUSH    EAX
:u cs:eip
014F:0040261C  PUSH    EAX
014F:0040261D  CALL    0041F6A6
014F:00402622  CMP     EAX,ESI
014F:00402624  POP     ECX
014F:00402625  JNZ     00402631
014F:00402627  CMP     BYTE PTR [EBP-80],00
014F:0040262B  JZ      00402631
014F:0040262D  PUSH    01
:d eax
0157:006CE748 43 72 61 73 68 74 65 73-74 20 5B 74 4E 4F 20 27  Crashtest [tNO '
0157:006CE758 39 39 5D 00 00 00 00 00-8F 36 98 77 57 01 20 77  99]......6.wW. w
0157:006CE768 07 02 A0 76 07 02 50 3C-A7 03 50 BB 07 02 00 00  ...v..P<..P.....
0157:006CE778 99 28 F9 BF 79 1A 39 45-00 00 00 00 00 00 4F 03  .(..y.9E......O.
0157:006CE788 EF 45 00 00 00 40 00 00-00 00 01 02 31 00 00 00  .E...@......1...
0157:006CE798 FF FF FF 40 FF FF FF FF-40 06 00 00 00 00 00 00  ...@....@.......
0157:006CE7A8 5F 20 EF 05 4E 78 DD 32-8F 04 39 BD 07 02 50 BB  _ ..Nx.2..9...P.
0157:006CE7B8 07 02 00 01 F2 77 FF 40-00 00 00 00 0A 78 FF 40  .....w.@.....x.@
014F:0040261D  CALL    0041F6A6
014F:00402622  CMP     EAX,ESI
:? esi
0001070D  0000067341  ""
:? eax
05BDB139  0096317753  "½±9"
014F:00402624  POP     ECX
014F:00402625  JNZ     00402631                                      (JUMP )

1.2 ) Analyzed dump

Now, the 'analyzed' version.
of coz, I disabled the code and the data window, to show what's happening.
sometimes, I pressed F10, or function keys, but It's not shown here.
so I'll write it in square brackets ([])


Break due to BPX KERNEL!HMEMCPY  (ET=612.80 milliseconds)
[softice broke here. but I'm not in Winamp. so I press F12 until I'm in]

KERNEL!HMEMCPY
1787:1D5C  PUSH    DWORD PTR [SI+20]
[F12 Pressed]
1787:37B0  OR      AX,AX
[F12 Pressed]
1787:3A18  OR      AX,AX
[F12 Pressed]
Break due to BPX KERNEL!HMEMCPY  (ET=2.70 microseconds)
[F12 Pressed]
1787:0B45  PUSH    WORD PTR [DI]
[F12 Pressed]
1787:27B9  SUB     DX,DX
[F12 Pressed]
1787:0C0D  POP     DS
[F12 Pressed]
17BF:82E7  POP     EDI
[F12 Pressed]
17B7:4BC0  RET
[F12 Pressed]
1797:2A05  JMP     2A16                                              (JUMP )
[F12 Pressed]
1797:4697  POP     CX
[F12 Pressed]
0187:0028  JMP     014F:BFF72964
[F12 Pressed]
[So I pressed F12 12 times]
014F:0040260B  PUSH    00
[now, the winice windows shows I'm in winamp, because    ]
[I can see WINAMP!.text+1609 in the middle of the window ]


:u cs:eip					] U = unassembles functions.
						] cs=code segment.
						] eip = extended instruction pointer
						] so cs:eip = the adress of current instruction.
[I want to see what's happening now. so I ask winice to show me the code]
014F:0040260B  PUSH    00			] look at that.
014F:0040260D  PUSH    00			] it's exactly what I spoke about in 3.1.2 ) .
014F:0040260F  PUSH    EBX			] Push is used for passing parameters.
014F:00402610  PUSH    EDI			] 
014F:00402611  CALL    [USER32!GetDlgItemInt]	] then the call is made.
014F:00402617  MOV     ESI,EAX			] and the result seems received in EAX.
014F:00402619  LEA     EAX,[EBP-80]		]
014F:0040261C  PUSH    EAX			]


[U can see here that getwindowtexta won't work. that's why it's better to directly use
HMEMCPY as a breakpoint
:bl						] bl = breakpoint list	
00)   BPX KERNEL!HMEMCPY
:bd 0						] bd = disable breakpoint
:bl
00) * BPX KERNEL!HMEMCPY
[Now, I disable the breakpoint on hmemcpy, because I know that GETDLGITEMINT
will call it. all GET... will call it. and I don't want it to happen. I want
to have the control, now]
[F10 pressed]
014F:0040260D  PUSH    00
[F10 pressed]
014F:0040260F  PUSH    EBX
[F10 pressed]
014F:00402610  PUSH    EDI
[F10 pressed]
014F:00402611  CALL    [USER32!GetDlgItemInt]
[F10 pressed]
014F:00402617  MOV     ESI,EAX
:? eax
0001070D  0000067341  ""
[Surprise. My serial is exactly stored in EAX.]

[F10 pressed]
014F:00402619  LEA     EAX,[EBP-80]
[F10 pressed]
014F:0040261C  PUSH    EAX
:u cs:eip
[I want to see what will happen]
014F:0040261C  PUSH    EAX			] we can see here another push/call
014F:0040261D  CALL    0041F6A6			] structure.
014F:00402622  CMP     EAX,ESI			] and some comparison is made after.
014F:00402624  POP     ECX			] 
014F:00402625  JNZ     00402631			] 
014F:00402627  CMP     BYTE PTR [EBP-80],00	]
014F:0040262B  JZ      00402631			]
014F:0040262D  PUSH    01			]
:d eax
0157:006CE748 43 72 61 73 68 74 65 73-74 20 5B 74 4E 4F 20 27  Crashtest [tNO '
0157:006CE758 39 39 5D 00 00 00 00 00-8F 36 98 77 57 01 20 77  99]......6.wW. w
...
[well. here, my name is used directly]

[F10 pressed]
014F:0040261D  CALL    0041F6A6
[F10 pressed]
014F:00402622  CMP     EAX,ESI
:? esi
0001070D  0000067341  ""			] here is the serial I entered.
:? eax
05BDB139  0096317753  "½±9"			] here is the compared value.
[F10 pressed]
014F:00402624  POP     ECX
[F10 pressed]
014F:00402625  JNZ     00402631                                      (JUMP )
well. of course, I hope you understood that the value 96317753 is the correct serial for "Crashtest [tNO '99]"
See : the serial I entered is stored in esi. and the winamp generates in the cs:41F6A6 call a number stored in eax, and compare them. If you still don't understand, even if you read here, then forget cracking.

so, as I wrote in 3.1.2 ), if you just want your serial, u have it this way.
if you want to make a patch, just delete the jnz. if you want to make a keymaker,
analyse the call, starting at cs:41F6A6

2 ) The key generator approach

Sorry, but so far, I wrote about 1000 lines for this tut. and I wonder if it worthes going on.
I'm not lazy. I will go on if people ask me (politely !), but nobody has written more than 1000 lines for nothing, I think.

So in other words, gimme feedbacks !

Crashtest [tNO '99]