mIRC v5.5 - Tutorial by friendship

"Well a really nice first tutorial by friendship which I'm proud to be hosting. I enjoy seeing how reversers are moving away from just cracking and are actually reversing a scheme, I like also this trend towards web-ready programming languages, surely it will not be long before we have on-line key generators written in Java/PERL etc. Go now and download for yourselves a copy of mIRC (available all over the web), then reverse the hell out of it before paying the deserving author if you use it. This is a great 1st tutorial by any new reverser". "Edited by CrackZ".

United Kingdom - http://www.mirc.co.uk
United States of America - http://www.mirc.com
OS : Windows 95/98
Tools Used : SoftICE v3.24

Introduction

Hello there!, this is my first tutorial. Any comments are welcome. I'm short of comments, because I am not good at English. Firstly a quick description, of mIRC, you surely know it as the program that connects you to other people all over the world through the internet. Like chatting but, but typing from the keyboard. Internet Relay Chat Client.

Protection System

Registration is via selecting the 'Help' menu option then choosing the 'Register' option. Here you will be asked to enter:

Full Name         :
Registration Code :
The registration code is evidently based on what you type in for your name/handle.

1. Deep within your System Registry it uses the following branch to store it's program settings and User Registration.

HKEY_CURRENT_USER\Software\mIRC\Code ---> Code registration with complicated encryption
HKEY_CURRENT_USER\Software\mIRC\Date ---> Code date of installation
HKEY_CURRENT_USER\Software\mIRC\Name ---> Name of registered user, unencrypted

2. It's a 30 day, time limited program that will 'expire' after 30 days of being installed.

The Essay

Run mIRC - click on Help - Select Register - fill out the entries in the registration screen with your name and your favourite key. Let's use these keys :

Full Name         : abcdefgh
Registration Code : 1234-567890
Then press "Register!", it pops up a window with comments that shows you an unmatched registration code and at the end it says Thanks!, a polite program, eh?. Press 'OK' to go back to the register dialog again. Now, let's use SoftICE :

Ctrl+D (enter into SoftICE)
:bpx GetDlgItem         --> break into Dialog Item
                        --> Use Quick View to see the Command of API32 that mIRC uses.
:lines 43               --> display 43 lines in window of Softice
:wc 19                  --> make 19 lines of unassembly
:code on                --> display include code machine / instruction byte
:wd 7                   --> make 7 lines of dump code in byte
:wr                     --> display register window or press F2

Now back to Window,
:    --> press F5
Again fill out the entries, and press Register! it breaks into SoftICE.
:   --> press F11 twice (in my computer, I close all the running application before cracking it)
    --> until you see the "CRIMINAL!.text+00034CD9, in the middle lower of screen, in a line.
Here is where SoftICE breaks (I must tell you that the Code Segment (CS) = 0177 is not permanent). It depends on application and memory used in Windows, so disregard it.
0177:00435CD9  CALL    USER32!SendDlgItemMessageA
0177:00435CDE PUSH 004D5F23 <-- mIRC breaks here 0177:00435CE3 PUSH 000003E7 <-- press F8 0177:00435CE8 PUSH 0D <-- press F8 0177:00435CEA PUSH 00000082 <-- press F8 0177:00435CEF MOV EDX,[EBP+08] <-- press F8 0177:00435CF2 PUSH EDX <-- press F8 0177:00435CF3 CALL USER32!SendDlgItemMessageA <-- press F10. Then press F11 until back here. 0177:00435CF8 PUSH 004D5F23 <-- keys registration code is store here 0177:00435CFD PUSH 004D5B3C <-- keys fullname code is store here 0177:00435D02 CALL 00492278 <-- analyze the registration and Fullname code 0177:00435D07 TEST EAX,EAX <-- if EAX=0 unmatch. Else, MATCH. 0177:00435D09 JZ 00435DAA <-- if Match no jump, else jump <-- Patch to NOP is no effect when start running again, <-- it still shows unregistered. 0177:00435D0F PUSH 004CCF7C
Now trace it with F8, single step tracing.

To see the code of registration and fullname, type :

:d ds:4D5F23   display dump memory store the Regsitration Code
:d ds:4D5D3C   display dump memory store the Full Name
Now, we enter into subcall CS:00492278, by pressing F8. Here is the code :
0177:00492278  PUSH    EBP
0177:00492279  MOV     EBP,ESP
0177:0049227B  PUSH    EBX
0177:0049227C  PUSH    ESI
0177:0049227D  PUSH    EDI
0177:0049227E  MOV     ESI,[EBP+0C]
0177:00492281  MOV     EBX,[EBP+08]
0177:00492284  PUSH    EBX
0177:00492285  CALL    004BAEB4     <-- check length string of FullName code
0177:0049228A  POP     ECX
0177:0049228B  CMP     EAX,05       <-- is string equal or greater than 5 characters
0177:0049228E  JAE     00492294     <-- Yes, and proceed to analyze
0177:00492290  XOR     EAX,EAX      <-- No. False.
0177:00492292  JMP     004922F0     <-- Exit !

0177:00492294  PUSH    ESI
0177:00492295  PUSH    EBX
0177:00492296  CALL    00492198     <-- Here! Analyze both fullname and registration code.

0177:0049229B  TEST    EAX,EAX      <-- here the test, if EAX=1 then MATCH
0177:0049229D  JZ      004922A6     <-- if EAX=0, not match.
                                    <-- Until here it can be forced to match everything
                                    <-- by changing the hex 74 (jz) to hex EB (jmp)
                                    <-- I think is not too smooth or ethical, besides
                                    <-- I hate to do it.
0177:0049229F  MOV     EAX,00000001 <-- MATCH! EAX > 0
0177:004922A4  JMP     004922F0     <-- Exit !
Now, lets examine a deeper subcall CS:00492198, by pressing F8. Here is that code :
0177:00492198  EBP
0177:00492199  MOV     EBP,ESP
0177:0049219B  ADD     ESP,-0C
0177:0049219E  PUSH    EBX
0177:0049219F  PUSH    ESI
0177:004921A0  PUSH    EDI
0177:004921A1  MOV     ESI,[EBP+0C]
0177:004921A4  PUSH    2D
0177:004921A6  PUSH    ESI

0177:004921A7  CALL    004BAE14      <-- Check length string of registration code
0177:004921AC  ADD     ESP,08
0177:004921AF  MOV     EBX,EAX       <-- save it and test if null
0177:004921B1  TEST    EBX,EBX
0177:004921B3  JNZ     004921BC      <-- if not, analyze code
0177:004921B5  XOR     EAX,EAX       <-- Not equal
0177:004921B7  JMP     0049226E      <-- if yes, exit

0177:004921BC  MOV     BYTE PTR [EBX],00  <-- change '-' to 00 in order to easy analyze
0177:004921BF  PUSH    ESI
0177:004921C0  CALL    004C2C44      <-- Now, calculate it and add it.
Here the explanation of registration code : 1234-567890 (is represented by x variable).

x1 x2 x3 x4 - x5 x6 x7 x8 x9 x10

In mathematical formula (dec numbers used) :

[EBP-04] = 10^3 (x1 - 48) + 10^2 (x2 - 48) + 10^1 (x3 - 48) + 10^0 (x4 - 48)
So, 1 is 49 in ASCII code, 2 is 50 in ASCII code and so on. What the formula says is "get the first four digits and store it in [EBP-04]". So, memory [EBP-04] is 1234.

0177:004921C5  POP     ECX
0177:004921C6  MOV     [EBP-04],EAX  <-- Save '1234' in memory [EBP-04]

0177:004921C9  MOV     BYTE PTR [EBX],2D  <-- move back the minus sign
0177:004921CC  INC     EBX                <-- the next, x5 x6 ... xn
0177:004921CD  CMP     BYTE PTR [EBX],00
0177:004921D0  JNZ     004921D9           <-- now, analyze the x5..xn code

0177:004921D2  XOR     EAX,EAX
0177:004921D4  JMP     0049226E
0177:004921D9  PUSH    EBX
0177:004921DA  CALL    004C2C44      <-- get the x5..xn code. Same as the
                                     <-- explanation above.
0177:004921DF  POP     ECX
0177:004921E0  MOV     [EBP-08],EAX  <-- save '567890' in [EBP-08].

0177:004921E3  MOV     EDX,[EBP+08]  <-- Now, analyze the FullName code.
0177:004921E6  PUSH    EDX
0177:004921E7  CALL    004BAEB4      <-- Check length of FullName code.
0177:004921EC  POP     ECX

Analyzing...

0177:004921ED  MOV     [EBP-0C],EAX  <-- length of code
0177:004921F0  XOR     EAX,EAX
0177:004921F2  XOR     EBX,EBX
0177:004921F4  MOV     EDX,00000003
0177:004921F9  MOV     ECX,[EBP+08]
0177:004921FC  ADD     ECX,03        <-- get the 4th index in code
0177:004921FF  CMP     EDX,[EBP-0C]
0177:00492202  JGE     00492220

0177:00492204  MOVZX   ESI,BYTE PTR [ECX]
0177:00492207  IMUL    ESI,[EAX*4+004D0160]  <-- multiple with standard mIRC data
0177:0049220F  ADD     EBX,ESI               <-- add it
0177:00492211  INC     EAX                   <-- next data mIRC
0177:00492212  CMP     EAX,26                <-- max length of code (= 38)
0177:00492215  JLE     00492219              <-- this code is effective when starting mIRC
0177:00492217  XOR     EAX,EAX
0177:00492219  INC     EDX                   <-- next index of code
0177:0049221A  INC     ECX                   <-- next index of code in memory dump
0177:0049221B  CMP     EDX,[EBP-0C]
0177:0049221E  JL      00492304
Here the explanation of the above codes : abcdefgh (is represented by Y variable) Y1 Y2 Y3 Y4 Y5 Y6 Y7 Y8. The formula is : (n is start from 4th to the end of the FullName code), Sum Yn * [004D0160 + (n-4)*4].

So the formula says : Get the 4rth of code, multiple with the mIRC standard data, and add repeatedly with the next one until the end of code.

0177:00492220  CMP     EBX,[EBP-04]   <-- Then the result compare with [EBP-04]
0177:00492223  JZ      00492229       <-- if equal, match!
                                      <-- Until here, it can be forced to Match everything.
                                          by changing the hex 74 (jz) to hex EB (jmp)
                                          But it taste not delecious. Besides, I don't want to.
0177:00492225  XOR     EAX,EAX        <-- if not equal, exit!
0177:00492227  JMP     0049226E

Analyzing...
0177:00492229  XOR     EAX,EAX
0177:0049222B  XOR     EBX,EBX
0177:0049222D  MOV     EDX,00000003   <-- the 4th index of code
0177:00492232  MOV     ECX,[EBP+08]
0177:00492235  ADD     ECX,03
0177:00492238  CMP     EDX,[EBP-0C]
0177:0049223B  JGE     00492260
0177:0049223D  MOVZX   ESI,BYTE PTR [ECX]   <-- Yn
0177:00492240  MOVZX   EDI,BYTE PTR [ECX-01]   <-- Yn-1
0177:00492244  IMUL    ESI,EDI                 <-- Yn * Yn-1
0177:00492247  IMUL    ESI,[EAX*4+004D0160]    <-- Yn * Yn-1 * standard Data mIRC
0177:0049224F  ADD     EBX,ESI                 <-- save and add to next
0177:00492251  INC     EAX
0177:00492252  CMP     EAX,26         <-- is achieved to 38th index of code?
0177:00492255  JLE     00492259       <-- no, keep analyzing
0177:00492257  XOR     EAX,EAX
0177:00492259  INC     EDX
0177:0049225A  INC     ECX
0177:0049225B  CMP     EDX,[EBP-0C]   <-- is achieved at end of code?
0177:0049225E  JL      0049233D       <-- no, back again
Here again the formula : (n is start from 4th to the end of the FullName code), Sum Yn * Yn-1 * [004D0160 + (n-4)*4]

The formula says : Get the 4rth code, multiple with the code before, multiple with the mIRC standard data, and continue with the next one until the end of code.

0177:00492260  CMP     EBX,[EBP-08]   <-- Then the result compare with [EBP-08]
0177:00492263  JZ      00492269       <-- if equal, match!
                                      <-- Until here, it can be forced to Match
                                          by changing the hex 74 (jz) to hex EB (jmp)
                                          But, I don't want to do it.
0177:00492265  XOR     EAX,EAX        <-- not match
0177:00492267  JMP     0049226E       <-- exit!
If this matchs it displays Registered in a pop up window, then the code is saved to the registry using an encryption method. The FullName and Registration code is randomized 19 times. The 1st times and the 2nd times use dec 39 ($27) and dec 30 ($1E) to random. Then adding with standard mIRC (in memory 004CB0B4). Switching between Y1 <--> Y2, Y1 <--> Yn and so on. After that it is still encrypted 3 times again.

You'll see the encryption is finished when there is a compare instruction between [004DC050] and [004DC044]. After that, the program works as per the explanation above. You'll see that subcall CS:004BAEB4 is used to cut and count the code length.

When the program starts, it performs the decrypt in reverse. I think it is a very complicated encryption and a protectionist program. If you want to see the manner of the encryption, you could bpx for you run the program.

Here are the steps to see the decryption scheme :

1. CTRL+D to enter SoftICE
2. set BPX RegQueryValueA
3. CTRL - D back to Windows
4. Now, run the program
5. It break, press F11 until you entered to the program.
6. Then trace single step using F8. If you reach a API32 subcall, use F10 and F11 to back.
I advise you it is better to leave it alone, you'll get a headache.:)

PERL Key Generator

Here are the steps to run it :

1. Copy and paste it in a text file, name it --> mirc.pl
2. perl mirc.pl
3. enter your name (should be 4 or greater characters) then press enter
4. it generates the registration code for you.

-----------Listing of the program in PERL Languange-------------

#! /perl/bin/perl.exe    <-- This is the first line

# The first line points to the PERL.exe main program FOLDER
# If you installed PERL.exe in other folder, you should change it.
#
# Created by friendship
# Program : Key Generator for mIRC version 4 above.

@data = qw(11  6 17 12 12 14  5 12
           16 10 11  6 14 14  4 11
            6 14 14  4 11  9 12 11
           10  8 10 10 16  8  4  6
           10 12 16  8 10  4 16  0);

print "Input Full Name : ";
$_ = ; chop($_);

$j = 0;
$len = length($_);
for ($i = 3; $i<$len; ++$i) {
   $v1 = ord(substr($_, $i, 1));
   $v2 = ord(substr($_, $i-1, 1));
   $p1 += $v1 * $data[$j];
   $p2 += $v1 * $v2 * $data[$j];
   ++$j
}

print "Registration Code is : $p1\-$p2\n";

--------------------End of Listing of the program --------------
To erase the registration you can enter the registry window, find the key (HKEY_CURRENT_USER\Software\mIRC) and erase it.

That all's.

PS: Many thanks to +ORC and this wonderful website.


Return to Main Index, Key Generators.

© 1999 friendship, Hosted by CrackZ. 6th May 1999.