FOR THE +HCU: ACADEMY OF REVERSE ENGINEERING


  Oct. 2001
"PowerZip v5.01.1366"
Win32 Program
Win32 Code Reversing
                      
by Bengaly
           
 
Code Reversing For Beginners 
       Msg For +Tshep
Program Details:
Program Name:PowerZip v5.01 
Program Type: Compression Utile 
Program Location: [ here ]
Program Size: 2+MB 

 

Tools Required:
W32Dasm  - Win'95/98 Dissasembler
Softice V4.X -  DeBugger 
Level
Easy ( X+ )  Medium (   )  Hard (   )  Pro (   )
"It's Up to you now Young Cracker"


 Cracking A Compression Utility
('Most Stupid Protection')
Written by Bengaly


Introduction

 
 PowerZip is a complete file compression solution for Windows. Supporting a large number of compressed formats, PowerZip enables  you to compress and extract files quickly and easily. PowerZip combines a simple and easy to use user interface with great flexibility  and advanced features so whether you are a novice or a power user, PowerZip is the right software to use.
                                                           About this protection

This program is registered by selecting the 'Help' button, 'About' button And than Registration# Button.

Name/Company:
Number Of Copies Bought:
Registration Number:

On Successful Registration, PowerZip will make a 'PowerZip.reg' file in it's Dir. with this information:

[Reg]
RegNum=-715191246  (Notice this number is diff from the real one, cuz it's transformed, notice in winice )
Copies=1
Name=Bengaly

if you want to use this software please Buy it, This  program is very good, please support it!


The Essay

Hello and welcome to my 32'th Tutorial.

Again, with no internet I had to dig inside my RCE CD , and lucky me I found this app in a
German magazine web page ripped in the cd :-) , it was some  sort of a project needed to,
Be cracked, so I took it ,  at least something than nothing :-)
This Application does not use any special Protection, only but the regular win Protection:

Call xxx
Test eax,eax
Jnz xxx

Never changed doeasn't it ? :-)
Of course cracking it wont be any trouble at all, even serial fishing will be too much easy,
Although I can say the Algo is very nice (little tricky and very very annoying), also coded in VC++,
Too much junk, when ppl will learn that ASM is the best ? ohh yeah blame m$ :-( .
Any way, let's start the cracking mission
Load up PowerZip, go to the registration Dialog, enter some information :

Name: Bengaly
Copies: 1 (this Bastard is kind tricky to make keygen, you'll see why ;-)
Registration Number: 12121212 (Good old teacher :-)

Press the OK Button and should get a Messagebox saying : "The registration number is invalid."
Hmm, no Problem, let's Disassemble the PowerZip...
Take nearly a 10 seconds to disassemble this file (200k), anyway Open up the String-Ref and search
For the string,....hm...Where is it?...hm... :-/
Seems PowerZip does not use the string...that's weird (it could happen) but can't be
In our case..hm...I know what we need...alittle ZEN :-) yeah, this will probably help when you're stuck,
Ok but first put some Axel-Rudi-pell CD (Great German heavy rock guitar player, even Talisman will do)
But don't put Really heavy screaming metal ugly music, that's not ZEN that's Headeck :-)
Anyway back to our proggy, since we know that the string is not in the app's EXE, we must seek something
Else, hm...think, it's a Compression program, and also 200kbytes for the EXE, that's weird,
Also this program uses allot of compression's (CAB,ZIP,HA,ARJ,Self ZIP eXTRACTION...),
I must tell that 200k program can't handle such amount of work :-)
So there must be some Help Files, a DLLS yeah that's must be, That's why we couldn't find the
String, PowerZip.exe is just an Dialog with Imported/Exported functions from outside DLLs.
Ok, let's make the DLLs visible, on  Win98 :-( View->Forlder Options->View->Show all files
Now you should see 9 different DLLS, just as i mentioned each dll correspond to his function.
Now, how can we know which DLLs is the one we need?
No problem, first look at the Dll's names, all uses the Libs (zip,ace,rar,zsfx...) but on 1 has a weird name,
More to say, Look at his Files Size 492 kbytes :-) and our PowerZip.exe is only 204kbytes, so we
Used alittle brain (not much, but we did) to find the suspicious file,
Now Lets disassemble it, and viola we have String-Ref, and more, scroll down and you will see:

"StorePath"
"Tar Archives (*.Tar)|*.Tar|"
"Tar"
"TGZ"
"tgz"
"Thank you for registering PowerZip!"
"The registration number is invalid."
"Toolbar"
"TSEW"
"TSPZ.Document"
"Type"
"u "

Ahah you say, i did it, i beat the night :-) , Still there more to be done,
Double click on The registration number is invalid and  you will be here:
 
* Reference To: MFC42.Ordinal:0217, Ord:0217h
                                  |
:150228C0 E8950B0100              Call 1503345A
* Reference To: DTUtil.?DT_IsValidRegNo@@YGHVCString@@II@Z
                                  |
:150228C5 E8661DFFFF    call 15014630 - Algo :-)
:150228CA 85C0                    test eax, eax
:150228CC 7512                   jne 150228E0 
:150228CE 50                         push eax
:150228CF 6A10                    push 00000010

* Possible StringData Ref from Data Obj ->"The registration number is invalid."
                                  |
:150228D1 68F4E40415              push 1504E4F4

Can you believe it ?
I think it's the Most stupid protection ever, look: :-)

DT_IsValidRegNo@@YGHVCString@@II@Z
       ^^^^^^^^^^^^
Yeah this is Stupid, also I can tell you, that this program made in VC++,
And so it calls IsValidRegNo() function that you see above :-) none to say, it's Stupid
Stupid Protection, but weird Algo :-) .

Ok, from what I see, Patch on the JNE wont work, it will only show the Good message but wont
Make it registered, this is because it save a reg file, and read it from it, so of you will patch it
It fill it with fake stuff, but still when it will read it, it wont accept it.
So we need to enter the call at 15014630this where we are interested in, follow the call and we are here:
 
* Referenced by a CALL at Addresses:
|:150148FC , :150228C5                            ;We called from those.
|

Exported fn(): ?DT_IsValidRegNo@@YGHVCString@@II@Z - Ord:00C1h
:15014630 64A100000000            mov eax, dword ptr fs:[00000000]

* Possible Reference to Dialog: DialogID_3A9E, CONTROL_ID:00FF, ""
                                  |
:15014636 6AFF                         push FFFFFFFF
:15014638 68D86D0315           push 15036DD8
:1501463D 50                              push eax
:1501463E B888130000            mov eax, 00001388
:15014643 64892500000000    mov dword ptr fs:[00000000], esp
:1501464A E861F70100           call 15033DB0
:1501464F 56                              push esi
:15014650 57                              push edi
:15014651 A0F0E80415           mov al, byte ptr [1504E8F0]
:15014656 B9E1040000           mov ecx, 000004E1
:1501465B 88442408                mov byte ptr [esp+08], al
:1501465F 33C0                         xor eax, eax
:15014661 8D7C2409                lea edi, dword ptr [esp+09]
:15014665 33F6                          xor esi, esi
:15014667 F3                              repz
:15014668 AB                             stosd
:15014669 66AB                        stosw
:1501466B AA                            stosb
:1501466C 8B8424A4130000    mov eax, dword ptr [esp+000013A4]
:15014673 89B42498130000     mov dword ptr [esp+00001398], esi
:1501467A 3BC6                          cmp eax, esi
:1501467C 0F86FD000000        jbe 1501477F
:15014682 8B8C24A0130000   mov ecx, dword ptr [esp+000013A0]
:15014689 8B49F8                      mov ecx, dword ptr [ecx-08]
:1501468C 83F901                      cmp ecx, 00000001
:1501468F 0F8EEA000000       jle 1501477F
:15014695 53                               push ebx
:15014696 8D54240C                lea edx, dword ptr [esp+0C]
:1501469A 6A05                        push 00000005  ; Magic number to div with
:1501469C 52                              push edx
:1501469D 50                              push eax

* Reference To: MSVCRT._itoa, Ord:0134h    ;ahh VC++ :-) Convert Integer To String
                                  |
:1501469E FF1504970315     Call dword ptr [15039704]     ; First Part Of The Algo 
:150146A4 8D7C2418              lea edi, dword ptr [esp+18]
:150146A8 83C9FF                  or ecx, FFFFFFFF
:150146AB 33C0                      xor eax, eax
:150146AD 83C40C                add esp, 0000000C
:150146B0 F2                           repnz
:150146B1 AE                          scasb
:150146B2 F7D1                      not ecx
:150146B4 49                           dec ecx
:150146B5 8D7C0C0C          lea edi, dword ptr [esp+ecx+0C]
:150146B9 8D8C24A4130000          lea ecx, dword ptr [esp+000013A4]

-----------------Snip--------------------

* Reference To: zlib.adler32, Ord:0001h
                                  |
:15014750 E8AB050100                              Call 15024D00 ; Second Part Of The Algo
:15014755 5B                                                  pop ebx
:15014756 8B8C24A8130000                      mov ecx, dword ptr [esp+000013A8]
:1501475D C7842498130000FFFFFFFF  mov dword ptr [esp+00001398], FFFFFFFF
:15014768 3BC8                                            cmp ecx, eax ; yeah it's Magic time :-)
:1501476A 8D8C24A0130000                     lea ecx, dword ptr [esp+000013A0]
:15014771 751E                                              jne 15014791

 

Argh, it's long, Damm Vc++ code makes everything UnClear an messy :-(
Any way We can understand what's going on there by Debugging, But i already did,
In the Program there are 2 part of the Algo:

1. For the Number Of copies.
2. For the name + table.

Let see what's going on in Part 1 of the algo :
 
0177:7800294B  JMP       7800291E 
0177:7800294D  PUSH      EBP 
0177:7800294E  MOV       EBP,ESP 
0177:78002950  CMP       DWORD PTR [EBP+10],0A     ; over 10 ? 
0177:78002954  JNZ         78002960 
0177:78002956  CMP       DWORD PTR [EBP+08],00     ; no copies ? 
0177:7800295A  JL           7801327A 
0177:78002960  PUSH      00 
0177:78002962  PUSH      DWORD PTR [EBP+10]      ; Point to number 5 
0177:78002965  PUSH      DWORD PTR [EBP+0C]     ; ?? (Sice shows: 75D5ACh) 
0177:78002968  PUSH      DWORD PTR [EBP+08]      ; Number of copies we bought 
0177:7800296B  CALL      78002978               <-----------+ 
0177:78002970  MOV       EAX,[EBP+0C]                      | 
0177:78002973  ADD        ESP,10                                 | 
0177:78002976  POP        EBP                                     | 
0177:78002977  RET                                                    | 
0177:78002978  PUSH      EBP                      <------------+ 
0177:78002979  MOV       EBP,ESP 
0177:7800297B  CMP       DWORD PTR [EBP+14],00   ; ?? compare some with 0, uselss from my point 
0177:7800297F  MOV       ECX,[EBP+0C]                     ; ECX = 75D5AC (mabye number of copies as well) 
0177:78002982  PUSH      EBX                                    ; stack save 
0177:78002983  PUSH      ESI                                     ; stack save 
0177:78002984  PUSH      EDI                                     ; stack save 
0177:78002985  JNZ       78013283                               ; Jump not equal to stack save esi ;-/ (junk?) 
0177:7800298B  MOV       ESI,[EBP+08]                      ; ESI = 1 (we choose 1 copy remember?) 
0177:7800298E  MOV       EDI,ECX                              ; EDI = 75D5AC (pointer to 1?) 
0177:78002990  MOV       EAX,ESI                              ; EAX = 1 
0177:78002992  XOR       EDX,EDX                              ; EDX = 0 
0177:78002994  DIV       DWORD PTR [EBP+10]          ; Devide by 5 
0177:78002997  MOV       EAX,ESI                              ; EAX = ESI 
0177:78002999  MOV       EBX,EDX                             ; EBX = 1 (EDX does not affect ebx, junk C++) 
0177:7800299B  XOR       EDX,EDX                              ; Xor again :-/ (VC++ junk :-) 
0177:7800299D  DIV       DWORD PTR [EBP+10]          ; Devide by 5 (VC++ junk :-) 
0177:780029A0  CMP       EBX,09                                ; EBX=9? (this may cuz after 9(copies) it does diff calcs) 
0177:780029A3  MOV       ESI,EAX                              ; ESI = 0 
0177:780029A5  JA        78013291                               ; If there were more than 9 copies ? (i think so) 
0177:780029AB  ADD       BL,30                                  ; EBX = 1 + 30 = 31 ('1') 
0177:780029AE  MOV       [ECX],BL                            ; Move it to the adress of ECX 
0177:780029B0  INC       ECX                                      ; ECX increased (address) -> 75D5AD 
0177:780029B1  TEST      ESI,ESI                               ; Is There remaining calculations ? 
0177:780029B3  JA        78002990                               ; Yup we haven't finished yet, jump 
0177:780029B5  AND       BYTE PTR [ECX],00              ; AND address with 00   (More junk) 
0177:780029B8  DEC       ECX                                     ; ECX goes down to 75D5AC 
0177:780029B9  MOV       DL,[EDI]                              ; EDX = 31  ('1')  (DL=30) 
0177:780029BB  MOV       AL,[ECX]                             ; EAX = 31 ('1')   (AL = 30) 
0177:780029BD  MOV       [ECX],DL                             ; save (more junk ahead) 
0177:780029BF  MOV       [EDI],AL                              ; save  (yeah kill CPU time) 
0177:780029C1  DEC       ECX                                     ; ECX = 75D5AB 
0177:780029C2  INC       EDI                                        ; EDI = 75D5AC 
0177:780029C3  CMP       EDI,ECX                               ; Make Comparison (ECX = 1's magic number, write it) 
0177:780029C5  JB        780029B9                                ; below? than  jump to junk 
0177:780029C7  POP       EDI                                       ; original stack 
0177:780029C8  POP       ESI                                       ; origianl.. 
0177:780029C9  POP       EBX                                      ; original... 
0177:780029CA  POP       EBP                                     ; original... 
0177:780029CB  RET                                                   ; Finished abuse you CPU, exit :-)

What can I say, Total mess, this is what happened when you code in VC++ ;-)
Any way, let me originize some Air to breeth and tell you what's going on, it is very weird
Becasue it's is coded in C and there is too much junk, explanation:

1. takes the number of copies you shoose in HEX (i choosed 1)
2. divide it with magic num 5 (EAX = 1/5 = 0, without reminder)
3. check to see if there is more number to divide in eax
4. add 30h to the number we entered (1h+30h => 31h =>'1')
5. save it for the second part of the algo.

But this is easy as it's 1 number, try to put big num and you get Headeck, example:
I choosed 400 copies :-), it's more than 9 so:
190h / 5h = 50h
50h / 5h = 10h
10h / 5h = 3h
3h / 5h = 0
And than do something weird here with adding 30h and if esi below ecx, it will keep
Move in 30h very weird.
from the above example the magic number is 100Dec ( and it's not a sum)

*Hope someone can give me a hint on that ? :-) plz contact me.

anyway i got magic number 1 from this weird calculation for the number of copies 1, dont worry
It does give other numbers :-) , well this goes for the First part,

Second part Of algo:

There is no actually code for this second part, but only created in memory ,
I will Explain the main idea of how to make a valid serial:

Magic Number + Name (uppercase) + table
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
All those togethere with some code makes a valid number, now you can't find it in win32dasm ro so,
so you need to rip it from softICE,  here is an example to my valid serial from my name:
 
 
Here ot does the same as below only start from the first char of the built table
------------------------Snip--------------------------
0177:026810D3  MOV       DL,[ESI-02]  ; move char 
0177:026810D6  ADD       EDI,ECX      ; char + ecx 
0177:026810D8  ADD       ECX,EDX    ; ecx + edx 
0177:026810DA  XOR       EDX,EDX   ; make room for another char 
0177:026810DC  MOV       DL,[ESI-01]     ;last char 
0177:026810DF  ADD       EDI,ECX          ;.... 
0177:026810E1  ADD       ECX,EDX        ;... 
0177:026810E3  ADD       EDI,ECX          ;... 
0177:026810E5  DEC       EBP 
0177:026810E6  JNZ        02681050 
0177:026810EC  TEST      EAX,EAX 
0177:026810EE  JZ          026810FC 
0177:026810F0  XOR       EDX,EDX 
0177:026810F2  MOV       DL,[ESI] 
0177:026810F4  ADD       ECX,EDX 
0177:026810F6  INC         ESI 
0177:026810F7  ADD       EDI,ECX 
0177:026810F9  DEC       EAX 
0177:026810FA  JNZ        026810F0 
0177:026810FC  MOV       EAX,ECX 
0177:026810FE  XOR       EDX,EDX 
0177:02681100  MOV       ECX,0000FFF1 
0177:02681105  DIV         ECX 
0177:02681107  MOV       EAX,EDI 
0177:02681109  MOV       EDI,0000FFF1 
0177:0268110E  MOV       ECX,EDX 
0177:02681110  XOR       EDX,EDX 
0177:02681112  DIV         EDI 
0177:02681114  TEST      EBX,EBX 
0177:02681116  MOV       EDI,EDX 
0177:02681118  JA           02681031 
0177:0268111E  POP       EBP 
0177:0268111F  MOV       EAX,EDI 
0177:02681121  POP       EBX 
0177:02681122  SHL        EAX,10 
0177:02681125  POP       EDI 
0177:02681126  OR         EAX,ECX        ; Built Serial Here  
0177:02681128  POP       ESI 
0177:02681129  RET       000C 

It's not hard to to understand this piece of code, it builds up a Table from algo1+string+algo2
Mine was: 1BENGALYPowerZip

Here's how Everythings Work:

1 . Calculated magic number from the first algo. (copies related)
2. Convert name to uppercase (Bengaly -> BENGALY)
3. add the string table 'PowerZip 5, Standard Edition' before the second algo
4. get lenght  = 36 dec
5. cut down the   5, Standard Edition String.
6. get every char from table (1BENGALYPowerZip) and sum the values
7. alittle more calculations here :-)
8. eax OR ecx Builds the final serial

For me I  got :

name: Bengaly(BENGALY)
Copies: 1
Serial: 3579776050

If you wish to built an keygen, it's posible as long as you figure out the part 1 of the algo,
Please send me solution for part 1 algo :-) as i was too lazy to understznd it.
Work Well and cya Next time.


Btw:
Heya +Tsehp, what you think on the little pics i did at beginning ? :-)
 
Oh And..

Do I really have to remind you all that by buying and NOT stealing the software you use will ensure that these software houses will continue to produce even *better* software for us to use and more importantly, to continue offering even more challenges to breaking their often weak protection systems.

If your looking for cracks or serial numbers then your wasting your time, try searching elsewhere on the Web under Warez, Cracks and etc.
 
Greetings

I would like to say thank you to all who has supported me, and helped me through my cracking days:

First Thanks goes to all who made Reveres-Engineering Possible:

In no specific order:
+ORC, reverser+, +RGC, +greythorne, +ReZiDeNt, +Xoanon , SiuL+Hacky,
The+Q (Home Made), +Spath, +Mammon_, Frog's print, +gthorne, +daQ,
razzia, +MaLaTTiA, Quine, +Alt-F4, +DataPimp, The+Chineese, +Hackmore,
+Indian_Trail, bajunny, +Sandman, +Aesculapius, Shaman, +Aitor,
Dr Fuhrball, MaD, TWD, +SNikKkEL, +Sync, Flipper, +Spalj, +Tsehp,
A+heist, The Undertaker, Civetta, +Zer0, +drlan, +PopJack.
all the HCUkers out there, we'll never forget you,
And to those who has past away from this world we'll remember you as well.

Thank for my Cracking Skills (Whatever they are)  Goes To To:
 
CoDe_InSiDe, fusS, _Nordic_, Muad'D1b, gogamoga,
ManKind, PGC & +HCU Academy Support.

And Thanx to my real friends as well (even if some don't know what I do) :-)

Work Well And Have Fun.
                                               Bengaly