ok we re in reg check calc after copying serial we do this 00402F2E 8B

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
ok we're in reg check/calc
after copying serial we do this
00402F2E |. 8B40 F4 MOV EAX,DWORD PTR DS:[EAX-0xC] ; mov length of serial into eax
00402F31 |. 6BC0 05 IMUL EAX,EAX,0x5 ; 10 * 5 = 50 (hex)
00402F34 |. 83C0 07 ADD EAX,0x7
00402F37 |. 99 CDQ
00402F38 |. 83E2 07 AND EDX,0x7 ; sign extended so just incase we get a funky number?
00402F3B |. 03C2 ADD EAX,EDX
00402F3D |. 8BF0 MOV ESI,EAX
00402F3F |. C1FE 03 SAR ESI,0x3 ; shift right by 3 is like a div by 8
eax = 57, esi = 0a (57 / 8)
004033C0 |. E8 57FBFFFF CALL DMY.00402F1C ; does some math on serial?
eax = 0a
004033C5 |. 59 POP ECX ; 001A8C18 (get the serial off the stack)
do some useless shit?
004033DF |. E8 7EE1FFFF CALL DMY.00401562 ; copy serial again?
004033E4 |. C645 FC 03 MOV BYTE PTR SS:[EBP-0x4],0x3
004033E8 |. C645 FC 01 MOV BYTE PTR SS:[EBP-0x4],0x1
004033EC |. E8 DBFCFFFF CALL DMY.004030CC ; convert from base 36 to 10 original bytes
inside the start of something, hopefully, maybe ....
004030F6 |. 6BC0 05 IMUL EAX,EAX,0x5
004030F9 |. 50 PUSH EAX
004030FA |. 8D4D F0 LEA ECX,DWORD PTR SS:[EBP-0x10]
004030FD |. 8945 E8 MOV DWORD PTR SS:[EBP-0x18],EAX
00403100 |. E8 16F8FFFF CALL DMY.0040291B ; allocate more space on heap, length * 5?
this extracts 5 bytes representing 5 bits for each character in serial
00403112 |. 83C6 02 ADD ESI,0x2 ; esi = target buffer, add 2 since our math starts with -2
00403115 |> 57 /PUSH EDI
00403116 |. 8D4D 08 |LEA ECX,DWORD PTR SS:[EBP+0x8]
00403119 |. E8 FEFCFFFF |CALL DMY.00402E1C ; get character from serial
0040311E |. 0FB7C0 |MOVZX EAX,AX ; clear everything before ax
00403121 |. 8D48 D0 |LEA ECX,DWORD PTR DS:[EAX-0x30] ; sub 30h from character (0 - 9) check
00403124 |. 66:83F9 09 |CMP CX,0x9
00403128 |. 77 08 |JA SHORT DMY.00403132
0040312A |. 0FB7C0 |MOVZX EAX,AX ; if its a number then get the number
0040312D |. 83E8 30 |SUB EAX,0x30
00403130 |. EB 13 |JMP SHORT DMY.00403145
00403132 |> 8D48 BF |LEA ECX,DWORD PTR DS:[EAX-0x41] ; check if its a letter 41 = A
00403135 |. 66:83F9 19 |CMP CX,0x19
00403139 |. 0F87 9D000000 |JA DMY.004031DC
0040313F |. 0FB7C0 |MOVZX EAX,AX
00403142 |. 83E8 37 |SUB EAX,0x37 ; if its a letter sub 37h from it
00403145 |> 8AC8 |MOV CL,AL ; if its a number land here and use the number 0 - 9
00403147 |. 80E1 01 |AND CL,0x1
0040314A |. 884E FE |MOV BYTE PTR DS:[ESI-0x2],CL ; store first bit
0040314D |. 8BC8 |MOV ECX,EAX
0040314F |. D1F9 |SAR ECX,1
00403151 |. 80E1 01 |AND CL,0x1
00403154 |. 884E FF |MOV BYTE PTR DS:[ESI-0x1],CL ; store second bit
00403157 |. 8BC8 |MOV ECX,EAX
00403159 |. C1F9 02 |SAR ECX,0x2
0040315C |. 80E1 01 |AND CL,0x1
0040315F |. 880E |MOV BYTE PTR DS:[ESI],CL
00403161 |. 8BC8 |MOV ECX,EAX
00403163 |. C1F9 03 |SAR ECX,0x3
00403166 |. C1F8 04 |SAR EAX,0x4
00403169 |. 80E1 01 |AND CL,0x1
0040316C |. 24 01 |AND AL,0x1
0040316E |. 884E 01 |MOV BYTE PTR DS:[ESI+0x1],CL
00403171 |. 8846 02 |MOV BYTE PTR DS:[ESI+0x2],AL ; store 5th bit
00403174 |. 8B45 08 |MOV EAX,DWORD PTR SS:[EBP+0x8]
00403177 |. 47 |INC EDI
00403178 |. 83C6 05 |ADD ESI,0x5 ; each byte turns into 5 new bytes ?
0040317B |. 3B78 F4 |CMP EDI,DWORD PTR DS:[EAX-0xC] ; length check, have we stored each bit for the serial?
0040317E |.^7C 95 \JL SHORT DMY.00403115
00403180 |> 8B45 E8 MOV EAX,DWORD PTR SS:[EBP-0x18] ; eax will = 50h
00403183 |. 83C0 07 ADD EAX,0x7
00403186 |. 99 CDQ
00403187 |. 83E2 07 AND EDX,0x7
0040318A |. 03C2 ADD EAX,EDX
0040318C |. 8BC8 MOV ECX,EAX
0040318E |. C1F9 03 SAR ECX,0x3 ; shift right 57h = 0a
00403191 |. 33C0 XOR EAX,EAX
00403193 |. 3BCB CMP ECX,EBX ; check if sar ecx is zero
00403195 |. 894D E4 MOV DWORD PTR SS:[EBP-0x1C],ECX
00403198 |. 7E 3A JLE SHORT DMY.004031D4
0040319A |. 33FF XOR EDI,EDI
0040319C |> 8B4D 0C /MOV ECX,DWORD PTR SS:[EBP+0xC]
0040319F |. 8D1408 |LEA EDX,DWORD PTR DS:[EAX+ECX]
004031A2 |. 881A |MOV BYTE PTR DS:[EDX],BL
004031A4 |. 33F6 |XOR ESI,ESI
004031A6 |. 897D EC |MOV DWORD PTR SS:[EBP-0x14],EDI ; store our counter, will be cmp'd to 8 at the end
004031A9 |> 8B4D EC |/MOV ECX,DWORD PTR SS:[EBP-0x14]
004031AC |. 3B4D E8 ||CMP ECX,DWORD PTR SS:[EBP-0x18] ; cmp our counter to 50h
004031AF |. 7D 18 ||JGE SHORT DMY.004031C9 ; exit when we hit the last extracted bit
004031B1 |. 8B5D F0 ||MOV EBX,DWORD PTR SS:[EBP-0x10] ; ebx will = address of bit extraction result
004031B4 |. 8D0C37 ||LEA ECX,DWORD PTR DS:[EDI+ESI]
004031B7 |. 8A1C19 ||MOV BL,BYTE PTR DS:[ECX+EBX] ; bl = byte/bit to process
004031BA |. 8BCE ||MOV ECX,ESI
004031BC |. D2E3 ||SHL BL,CL ; shift bit left by position
004031BE |. 081A ||OR BYTE PTR DS:[EDX],BL ; edx = target buffer and OR by bl ...
004031C0 |. 46 ||INC ESI
004031C1 |. FF45 EC ||INC DWORD PTR SS:[EBP-0x14]
004031C4 |. 83FE 08 ||CMP ESI,0x8 ; process 8 bits at a time?
004031C7 |.^7C E0 |\JL SHORT DMY.004031A9
004031C9 |> 40 |INC EAX
004031CA |. 83C7 08 |ADD EDI,0x8
004031CD |. 33DB |XOR EBX,EBX
004031CF |. 3B45 E4 |CMP EAX,DWORD PTR SS:[EBP-0x1C]
004031D2 |.^7C C8 \JL SHORT DMY.0040319C
ok all that shit was some fucking base 36 conversion
result of turning extracted bits into 10 new bytes?
003D7FE0 41 0C 52 CC 41 09 A8 C5 9A 7B A.RÌA.¨Åš{
then we xor the second half of 5 bytes by the first 5 bytes
00403455 |> 8B45 08 /MOV EAX,DWORD PTR SS:[EBP+0x8]
00403458 |. 99 |CDQ
00403459 |. 6A 05 |PUSH 0x5
0040345B |. 5B |POP EBX
0040345C |. F7FB |IDIV EBX
0040345E |. 03D1 |ADD EDX,ECX
00403460 |. 8D043A |LEA EAX,DWORD PTR DS:[EDX+EDI]
00403463 |. 8B55 08 |MOV EDX,DWORD PTR SS:[EBP+0x8]
00403466 |. 8A143A |MOV DL,BYTE PTR DS:[EDX+EDI]
00403469 |. 3010 |XOR BYTE PTR DS:[EAX],DL ; possibly xor'ing first half by second half ? 0a = 05 * 2
0040346B |. FF45 08 |INC DWORD PTR SS:[EBP+0x8]
0040346E |. 394D 08 |CMP DWORD PTR SS:[EBP+0x8],ECX ; yup we're only xoring second half by the first half
00403471 |.^7C E2 \JL SHORT DMY.00403455
result of xor shit
003D7FE0 41 0C 52 CC 41 48 A4 97 56 3A A.RÌAH¤—V:
now we call a method with
pointer to original 5
length 05
pointer next 5 bytes (xor'd bytes)
some unknown address in ecx
0012EAB8 003D7FE5 |Arg1 = 003D7FE5 -> second half of xor result
0012EABC 00000005 |Arg2 = 00000005 -> length of input data
0012EAC0 003D8058 \Arg3 = 003D8058 -> wtf? oh this is the buffer for the result
00434C12 |. E8 ACF9FFFF CALL DMY.004345C3 ; md4init
00434C17 |. FF75 0C PUSH DWORD PTR SS:[EBP+0xC]
00434C1A |. 8B5D 08 MOV EBX,DWORD PTR SS:[EBP+0x8]
00434C1D |. 8D45 A8 LEA EAX,DWORD PTR SS:[EBP-0x58]
00434C20 |. 53 PUSH EBX
00434C21 |. 50 PUSH EAX
00434C22 |. E8 72FEFFFF CALL DMY.00434A99 ; md4update
00434C27 |. 8B7D 10 MOV EDI,DWORD PTR SS:[EBP+0x10]
00434C2A |. 8D45 A8 LEA EAX,DWORD PTR SS:[EBP-0x58]
00434C2D |. 50 PUSH EAX
00434C2E |. 57 PUSH EDI
00434C2F |. E8 00FFFFFF CALL DMY.00434B34 ; md4finalize
00434C34 |. 33C0 XOR EAX,EAX
00434C36 |. 40 INC EAX
00434C37 |. 83C4 18 ADD ESP,0x18
00434C3A |. 3946 10 CMP DWORD PTR DS:[ESI+0x10],EAX
00434C3D |. 8945 08 MOV DWORD PTR SS:[EBP+0x8],EAX
00434C40 |. 7E 4E JLE SHORT DMY.00434C90
00434C42 |> 8D45 A8 /LEA EAX,DWORD PTR SS:[EBP-0x58]
00434C45 |. 50 |PUSH EAX
00434C46 |. E8 78F9FFFF |CALL DMY.004345C3 ; md4init
00434C4B |. 807E 18 00 |CMP BYTE PTR DS:[ESI+0x18],0x0
00434C4F |. 59 |POP ECX
00434C50 |. 74 19 |JE SHORT DMY.00434C6B
00434C52 |. 33C9 |XOR ECX,ECX
00434C54 |. 394E 14 |CMP DWORD PTR DS:[ESI+0x14],ECX ; length check
00434C57 |. 7E 12 |JLE SHORT DMY.00434C6B
00434C59 |> 8BC1 |/MOV EAX,ECX
00434C5B |. 99 ||CDQ
00434C5C |. F77D 0C ||IDIV DWORD PTR SS:[EBP+0xC] ; make sure we only use the first 5 from xor result
00434C5F |. 8A041A ||MOV AL,BYTE PTR DS:[EDX+EBX] ; mov byte from xor result starting at 0 to al
00434C62 |. 300439 ||XOR BYTE PTR DS:[ECX+EDI],AL ; xor md4 hash byte with serial byte
00434C65 |. 41 ||INC ECX
00434C66 |. 3B4E 14 ||CMP ECX,DWORD PTR DS:[ESI+0x14]
00434C69 |.^7C EE |\JL SHORT DMY.00434C59
00434C6B |> FF76 14 |PUSH DWORD PTR DS:[ESI+0x14] ; length
00434C6E |. 8D45 A8 |LEA EAX,DWORD PTR SS:[EBP-0x58]
00434C71 |. 57 |PUSH EDI ; source data = xor'd md4 hash
00434C72 |. 50 |PUSH EAX ; destination
00434C73 |. E8 21FEFFFF |CALL DMY.00434A99 ; md4update
00434C78 |. 8D45 A8 |LEA EAX,DWORD PTR SS:[EBP-0x58]
00434C7B |. 50 |PUSH EAX ; source md4 hash of previous xor'd hash
00434C7C |. 57 |PUSH EDI ; destination
00434C7D |. E8 B2FEFFFF |CALL DMY.00434B34 ; md4finalize
00434C82 |. 83C4 14 |ADD ESP,0x14
00434C85 |. FF45 08 |INC DWORD PTR SS:[EBP+0x8]
00434C88 |. 8B45 08 |MOV EAX,DWORD PTR SS:[EBP+0x8]
00434C8B |. 3B46 10 |CMP EAX,DWORD PTR DS:[ESI+0x10] ; 1F4? looks like we hash/xor 500 times and then bail out
00434C8E |.^7C B2 \JL SHORT DMY.00434C42
003D8058 40 81 3D 00 41 5B FB CE EC 5A 30 48 BD 20 72 B6 @=.A[ûÎìZ0H½ r¶
MD4 hash of second 5 bytes
0012EA58 2E 65 26 F2 EC 5C 22 0D 31 A3 DB 44 A3 7C 20 6A .e&òì\".1£ÛD£| j
xor md4 hash with second half of xor result, wash rinse repeat 500 times
final hash of xor'd hashes
003D8058 28 F6 B4 F5 20 1A 9B 97 5E 64 0B 49 3E 14 D9 33 (ö´õ ›—^d I>Ù3
we've returned from our hash exercise and .....
00434CD8 |. 8B07 MOV EAX,DWORD PTR DS:[EDI] ; first 4 bytes of xor'd md4 hash as dword
00434CDA |. 99 CDQ
00434CDB |. F73E IDIV DWORD PTR DS:[ESI] ; 3e8 is it hardcoded? yup = 1000
00434CDD |. 52 PUSH EDX ; /Arg1
00434CDE |. E8 B8FF0100 CALL DMY.00454C9B ; \turn a negative into a positive
00434CE3 |. 59 POP ECX
take first 4 bytes of that hash, divide them by 1000 or 3e8h (dword mod 3e8)
use edx = remainder/mod value
FFFFFC90
turn mod value from negative into positive
370
00434CED |> 0FAFC8 /IMUL ECX,EAX ; multiply result from mod/hashes by 5
00434CF0 |. 034E 08 |ADD ECX,DWORD PTR DS:[ESI+0x8] ; add the base address of that really big table to imul result
00434CF3 |. 8A0C11 |MOV CL,BYTE PTR DS:[ECX+EDX] ; get a byte from way off in the middle of no where
00434CF6 |. 880C1A |MOV BYTE PTR DS:[EDX+EBX],CL ; store byte
00434CF9 |. 8B4E 04 |MOV ECX,DWORD PTR DS:[ESI+0x4]
00434CFC |. 42 |INC EDX
00434CFD |. 3BD1 |CMP EDX,ECX ; check if we've gotten 5 bytes from that table
00434CFF |.^7C EC \JL SHORT DMY.00434CED ; get 5 weird bytes?
result of byte lookup
003D8140 EA 24 C2 01 8B ê$‹
so the second half of the serial bytes represents the offset to the lookup table
the value it looks up is the first 5 bytes of returned by the next operations
perform the hash/xor operation on the first 5 bytes
the first 5 in this are compared to the 5 from the byte lookup
003D8058 AB 33 21 27 41 5B FB CE EC 5A 30 48 BD 20 72 B6 «3!'A[ûÎìZ0H½ r¶
if they match the serial was good
00434D20 |> 8A1401 /MOV DL,BYTE PTR DS:[ECX+EAX] ; bytes from previous lookup
00434D23 |. 3A10 |CMP DL,BYTE PTR DS:[EAX] ; bytes from last processing loop @ 00434d0a
00434D25 |. 75 0B |JNZ SHORT DMY.00434D32 ; doesn't match so its a bad key
00434D27 |. FF45 0C |INC DWORD PTR SS:[EBP+0xC]
00434D2A |. 40 |INC EAX
00434D2B |. 3975 0C |CMP DWORD PTR SS:[EBP+0xC],ESI
00434D2E |.^7C F0 \JL SHORT DMY.00434D20
00434D30 |. EB 04 JMP SHORT DMY.00434D36 ; good key jump
00434D32 C645 FF 00 MOV BYTE PTR SS:[EBP-0x1],0x0 ; hrmm bad key so set to 0
OK RECAP TIME
base 36 decode serial
xor second 5 bytes by first five bytes
41 0C 52 CC 41 48 A4 97 56 3A
first check bytes come from
md4/xor operation on 48 A4 97 56 3A (second half of xor'd bytes)
first 4 bytes from that hash
28 F6 B4 F5 turn this into a dword F5B4F628 mod 3E8 (1000) take result and grab only int
370h
use that as an offset into the big ass table and extract 5 bytes from there
EA 24 C2 01 8B <--- first magic number?
ok now take these 5 bytes aka first half of serial/xor result
41 0C 52 CC 41
md4/xor operation on them and grab the first 5 bytes of that final hash
AB 33 21 27 41 <--- second magic number?
magic 01 and magic 02 must match
SO TO GENERATE A VALID SERIAL
find a set of 5 bytes that when md4/xor hashed the first 5 bytes of the hash exist in the lookup table
find a second set of 5 bytes that when md4/xor hashed the first 4 bytes of the hash point to the offset in the lookup table
4 bytes = dword ptr [hash]
magic dword / 1000 ...
grab int from remainder of division (negative numbers will have their sign removed)
offset of lookuptable + (remainder int * 5) = fucking pointer ... multiply by 5 cause each entry is 5 bytes long
take the second 5 bytes and xor by the first 5 bytes
take those final 10 bytes and convert to base36
base36 result = serial which will be 16 characters long
since the registration check strips - and spaces we can format our serial like so
XXXX-XXXX-XXXX-XXXX or XXXXXXXX-XXXXXXXX
PROBLEM 1 ... finding hashed bytes that exist in the lookup table, this part requires bruteforcing and it could be slow
PROBLEM 2 ... finding second hashed bytes also requires bruteforcing but the odds are much better
serial bit extraction result (this is part of the base36 conversion)
003DF720 01 00 00 00 00 00 01 00 00 00 01 01 00 00 00 00 ............
003DF730 00 01 00 00 01 00 01 00 00 00 01 01 00 00 01 01 .........
003DF740 01 00 00 00 00 00 01 00 01 00 00 01 00 00 00 00 ............
003DF750 00 00 00 01 00 01 00 01 01 00 01 00 00 00 01 01 .........
003DF760 00 01 00 01 01 00 00 01 01 01 00 01 01 01 01 00 ......
really big table used in some shit
(lookup table storing all the valid serial hash codes) 1000 hash codes 5 bytes for each code 5k of bullshit
003D8708 CA 95 CA 35 BB 4B 41 8D 2E 06 17 22 44 34 04 A8 Ê•Ê5»KA."D4¨
003D8718 EF 91 6F 6F 70 A1 EA B7 0F 7C 4F 30 49 57 4E 3D ï‘oop¡ê·|O0IWN=
003D8728 6E C7 43 EC F5 B2 6D FF B5 85 CF 16 48 1A FE 57 nÇCìõ²mÿµ…ÏHþW
003D8738 CF BA A5 87 60 8D 97 5B 4A 6C B1 36 70 19 CA 51 Ϻ¥‡`—[Jl±6pÊQ
003D8748 09 60 E6 C8 6D 10 AB B6 A5 51 FB 1D 13 B3 0A 60 .`æÈm«¶¥Qû³.`
.......
thats a lookup table thats 5000 bytes long ... wooo damn