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


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,

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 F11 until 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 <-- Patch to NOP has no effect, 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 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! 
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. 

NB - Okay I messed this up, apologies from CrackZ, contact Frienship 
by e-mail.

; 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.

Key Generators Return to Main Index

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