| Author | Falcon |
| Target | PhoX crackme 7 |
| Public Release | Sunday,16 of July,2000 |
| Author Contact | falcon_geno@mail.ru |
| Dedication | Irwin Shaw |
| Difficulty Level (1..7) | 3 (MEDIUM) |
| Tools Required | SoftIce 3.xx.;WinDasm;HIEW |
Disclaimer: Please
note, the information herein is copyright to Hellforge. No portion of this
text may be duplicated. Furthermore, damage or problems arising after reading
this text is left to the users disposal. Neither Hellforge, nor its members
can be held responsible for any direct or indirect result of following
this text. The full liability of following this text is on the reader (YOU).
The information is provided for educational purposes, misuse of this information
is strictly prohibited. If you do not agree with this agreement, then please
hit the "back" button on your browser, and go to hell. - Mercution.
|
|
Today I wanted to share with one
of the methods that I used for cracking this nice program from Phox. Although,
he was saying about 2 methods I could find only one of available. The interesting
thing in this program is that it has a some aspects of REVERSING
(It deals with proper functioning of the programs), as I said it, in this
tutorial will be some stuff I did not talk in my previous tutorials about.
The program requires patching, in fact we need to change 2 bytes. In this
tutorial, you're going to understand how to make PATCHERs
(Programs that change initial code to make it work as WE want) and how
to make BRUTE FORCERs (A program made
by a cracker to calculate a number or a sequence of chars (word), later
you will know all the rules about it.)
|
|
- Execute the program
and activate Soft-Ice
- Enter anything
as your Serial
- Set these breakpoints
and Press 'OK' button, and you will break at GetWindowTextA
- Press F11 and
let's examine the code carefully, you'll see...
*Referance To: User32.GetWindowTextA, ord:0000h
004011E4 CALL 0040131E
004011E9 PUSH
DWORD PTR [00402044]
004011EF CALL 0040126F
004011F4 CMP EAX, 00000001
004011F7 JNE 00401217
004011F9 PUSH
00000030
*Possible
StringData Ref from Data Obj -> "*BEATEN*"
004011FB PUSH
0040208A
*Possible
StringData Ref from Data Obj -> "*mumble*"
00401200 PUSH 00402093
Comments:
This piece of
code was taken after DisAssembling this CrackMe using WinDasm... Examining this code, we can conclude
that the main program code, where all calculations and comparing routines
will take place in the CALL at 004011EF address, because after it goes
a Compare operation after which the program Jumps (or does not Jump) depending
on the value of EAX. So, the first
thing that I did it was Tracing Into (F8) the CALL at 004011EF, so let's
do it. YOU we see... Note: I will explain how to make this program say
that we crack it from the very beginning, showing how to analyze the program
code...
*Referenced
by a Call at Address:
:004011EF
0040126F C8000000 enter 0000,00
00401273 53 push ebx
00401274 52 push edx
00401275 FF354C204000 push dword ptr [0040204C]
*Reference To: User32.GetWindowTextLengthA, Ord:0000h
0040127B E8AA000000 Call 0040132A {See below comments about this CALL}
00401280 8BC8 mov ecx, eax
00401282 33C0 xor eax, eax
00401284 B89C204000 mov eax, 0040209C
00401289 803800 cmp byte ptr
[eax], 00
0040128C 746A je 004012F8
0040128E 33DB xor ebx, ebx
00401290 33D2 xor edx, edx
Comments:
You may
be thinking now- Why did that Falcon stopped just before the main Calculation
Routine starts? I did it because this was the piece
of code where I confused. You see, this API (GetWindowTextLengthA) takes
the length of the serial that you specified in that EditBox of the form,
but something strange happened when you traced through this line: 0040127B
E8AA000000
Call 0040132A As you, probably,
know: When you trace this CALL, the EAX register should indicate the length
or your Serial, and if you did Enter something it must show the length,
but IT DOES NOT...The author did it unendingly, for confusing crackers
from their primary objective (Serial), but let's not panic and do something...
Let's deactivate current breakpoint and ser another one.
- Type bc *
- Set bpx GetWindowTextLengthA
- Press again
the 'OK' button =>Soft-Ice breaks
- Press F11 and
you will be seeing...
004011C5 FF35502040000 push dword ptr [00402050]
*Reference TO: User32.GetWindowTextLengthA
004011CB E85A0100000 Call
0040132A {Length of the Serial goes to
EAX}
004011D0 83F800 cmp eax, 00000000 {CoMPares if EAX is equal to Zero}
004011D3 7460 je 00401235 {Jump to 'Bad' message if Equal}
004011D5 33C0 xor eax, eax {EAX is equal to Zero after operation}
004011D7 6A28 push 00000028 {Stores in the stack this number (28h) }
Comments:
Was not it strange, that this time in EAX, was the correct Serial
length? The reason to this is that BEFORE
Soft-Ice breaks; A number, that is located at 00402050, is stored in the
stack. Considering this number Program gets the right Serial length, so
let's think a little bit and... We can conclude
that in previous piece of code (Where I get confused), there was another
number. Let's compare these two:
1) 00401275 FF354C204000
push dword ptr [0040204C]
{This
goes from confused code}
2) 004011C5 FF3550204000 push
dword ptr [00402050]
{This
is right code}
So, what do we do?
Now, we are going to patch this
Confused code, so that program takes GOOD Serial length.
- Firstly, we
have to find offset, where Bad code is located. For reaching this goal
we are going to use WinDasm
- Open this CrackMe
with Wdasm and goto Address 00401275,
- You have to
memorize this offset
- Open with CrackMe
with HIEW, Press F5 and write this offset (It must be...875)
- Press Enter
and you are in the right place, now press F3 and change 4C to 50,
- Press F9 for
updating the program with changes, and that's all...(Or not???)
- Set bpx GetWindowTextLengthA
again and press once F5 and then F11 and you will see...
00401275 FF354C204000 push dword ptr ([0040204C] will become) [00402050]
*Reference To: User32.GetWindowTextLengthA, Ord:0000h
0040127B E8AA000000 Call 0040132A
{And after this CALL, EAX takes real Serial length, so we did good
job reaching second interesting part.}
00401280 8BC8 mov ecx, eax
{MOVes length of Serial
to ECX}
00401282 33C0 xor eax, eax
{XORes EAX with EAX, so EAX=0}
00401284 B89C204000 mov eax, 0040209C
{Here is interesting point, see below}
00401289 803800 cmp byte ptr [eax], 00
{It check current char
code with 00}
0040128C 746A je 004012F8
{It will Jump if it's equal to 00.Without any additional preparation
for getting to Calculations of Serial you will always Jump to the BAD routine,
so
let's see}
0040128E 33DB xor ebx, ebx
00401290 33D2 xor edx, edx
Look again at the line at 00401284
address! It seems to me
that to EAX register must be MOVed address where you Serial is located,
BUT... when you type d 00402084, can you
see your Serial? I guess not, so author made again the trick.
- Let's examine
the program code again.
- Deactivate current
breakpoint and set another one (bpx GetWindowTextA) {This API is used for
storing information that you enter in the EditBox at address, so we have
to point our attention to this brealpoint}
- Press 'OK' button
and you see...
004011D9 689C204000 push 0040209C
004011DE FF354C204000 push dword ptr [0040204C]
*Referance To: User32.GetWindowTextA, ord:0000h
004011E4 CALL
0040131E {See below comments about this CALL}
004011E9 PUSH
DWORD PTR [00402044]
004011EF CALL 0040126F
004011F4 CMP EAX, 00000001
004011F7 JNE 00401217
004011F9 PUSH
00000030
Comments:
Firstly, I wanted to say something about line at 004011D9. The program
PUSHes into the stack this address, because that's location of our Serial,
but when you trace this line : 004011E4 CALL
0040131E and when you type: d 0040209c
you do not see the Serial that you entered, but we can fix this. Author
uses the same trick...004011DE FF354C204000
push dword ptr [0040204C] Does
this line reminds you something? Yeah, that's right! I remember that we
had to change 4C to 50...Do it here also, use the same steps that I gave
you for changing it... As, you did it,
(Offset must be 7DE), set again bpx GetWindowTextA and when you got to
Soft-Ice type: d 0040209C and you will see the
Serial....WE HAVE ACCOMPLISHED THE PREPARATION PART, let's move to Serial
Calculations. But before doing this let me show you how to make a PATCHER
(for more convenience).
PATCHER:
{This patcher
was made in PASCAL, and I am quite sure you will understand what it does...}
Uses Crt;
Const
A: Array[1..2] of Record
A : Longint;
B : Byte;
End =
((A:$877;B:$50),(A:$7e0;B:$50));
Var
Ch:Char;
I:Byte;
F:File;
Begin
ClrScr;
Writeln('Falcon''s
Patch');
writeln('Crack
for Phox''s Crackme#7.0');
Assign(F,'crackme7.EXE');
{$I-}
Reset(F,1); {$I+}
If IOResult
<> 0 then
begin
Writeln;
writeln('File not found!');
writeln('Make sure that
this patcher is located with CrackMe in same folder!');
Readln;
halt(1);
end
Else
Begin
For i:=1 to 2 Do
Begin
Seek(F,a[i].a);
{This command move the cursor to the following offset}
Ch:=Char(a[i].b);
Blockwrite(F,Ch,1);
{Here we change byte to 50h}
End;
Writeln('File
successfully patched!');
Write('Press
Enter to terminate the program.');
Readln;
End;
End.
Let's figure out how to find the Serial for this CrackMe:
0040126F C8000000 enter 0000,00
00401273 53 push ebx
00401274 52 push edx
00401275 FF354C204000 push dword ptr [00402050]
*Reference To: User32.GetWindowTextLengthA, Ord:0000h
0040127B E8AA000000 Call 0040132A
{Moves the length of Serial to EAX}
00401280 8BC8 mov ecx, eax
{Value of EAX is MOVed to
ECX}
00401282
33C0 xor eax, eax
{EAX xor EAX makes finally Zero}
00401284
B89C204000 mov
eax,
0040209C
{MOVes address where Serial is to
EAX}
00401289
803800 cmp byte ptr [eax],
00
{CoMPares first char code with
0}
0040128C
746A je 004012F8
{Jump if Equal}
0040128E
33DB xor ebx, ebx
{EBX xor EBX makes finally Zero}
00401290
33D2 xor edx, edx
{EDX xor EDX makes finally Zero}
*Referenced by (U)nconditional
or (C)onditional Jump at Address
:004012A5
00401292 MOV
BL, BYTE PTR [EAX] {MOVes current char code to BL register}
00401294 PUSH
ECX {Value of ECX is stored in Stack}
00401295 XOR CL, BL
{Now, ECX takes new value after CL=CL xor BL}
00401297 ROR EBX, CL {Rotates Operand (EBX) Right by CL units}
00401299 ROL ECX, 03
{Rotates Operand (ECX) Left by 3 units}
0040129C SHL EBX, CL
{SHifts operand Left
by CL units, in fact EBX=EBC*2^CL}
0040129E POP ECX
{Restores value, that was pushed, in ECX }
0040129F ADD EDX, EBX {ADDition of 2 operands,
EDX=EDX+EBX}
004012A1 INC EAX {shifts to the next char}
004012A2 CMP
BYTE PTR [EAX], 00 {CoMPare char code with 0}
004012A5 JNE 00401292 {Jump to the start of the LOOP if Not Equal to 0}
Comments:
Actually,
there is nothing much to say. All the operations are known for you, and
considering the fact that WE do not know the Serial itself and the Serial
length is also unknown, we have to create a Brute Forcer. When you pass
this piece of code-the final value will be in EDX register and now, the
only thing we need from Soft-Ice is to know what must be the chars after
passing all these commands...
- Let's see...
004012A7 PUSH
EDX
004012A8 PUSH
00402058
004012AD PUSH
004020B5
{As I said before the address that is pushed to stack before API that
I described before will be the address where the final sum, (from EDX register
) will appear as String}
004012B2 CALL
USER!wsprintA {This
procedure will store the final resul that is in EDX register by the address
from which it will take all the numbers one by one for comparing, you will
see it right away...}
004012B7 XOR
EBX,EBX
004012B9 MOV
EBX, 004020B5
{Loads
the addres,where the SUM is located, to EBX Register. Now, it will compare
numbers...Here, you will see that your sum is a string, the author made
it being so, for comparing all chars of this string with 'GOOD' ones}
004012BE CMP
BYTE PTR [EBX], 44
{CoMpare first char of the SUM with 'D' }
004012C1 JNZ 004012F8
{Jump to 'Bad cracker'
if they are not equal }
004012C3 CMP
BYTE PTR [EBX+1], 33
{CoMpare second char of the SUM with '3' }
004012C7 JNZ 004012F8
{Jump to 'Bad cracker' if they are not equal }
004012C9 CMP
BYTE PTR [EBX+2], 46
{CoMpare second char of the SUM with 'F'}
004012CD JNZ 004012F8
{Jump to 'Bad cracker' if they are not equal }
004012CF CMP
BYTE PTR [EBX+3], 38
{CoMpare second char of the SUM with '8' }
004012D3 JNZ 004012F8
{Jump to 'Bad cracker' if they are not equal }
004012D5 CMP
BYTE PTR [EBX+4], 42
{ CoMpare second char of the SUM with 'B'}
004012D9 JNZ
004012F8
{Jump to 'Bad cracker' if they are not equal }
004012DB CMP
BYTE PTR [EBX+5], 31
{CoMpare second char of the SUM with '1' }
004012DF JNZ 004012F8
{Jump to 'Bad cracker' if they are not equal }
004012E1 CMP
BYTE PTR [EBX+6], 30
{CoMpare second char of the SUM with '0' }
004012E5 JNZ
004012F8
{Jump to 'Bad cracker' if they are not equal }
004012E7 CMP
BYTE PTR [EBX+7], 43
{CoMpare second char of the SUM with 'C' }
004012EB JNZ
004012F8
{Jump to 'Bad cracker'
if they are not equal }
004012ED MOV
EAX, 00000001
{If you pass all these compares then EAX takes value of 1..}
004012F2 POP
EDX
{ Restores last info, that was pushed, from stack to EDX }
004012F3 POP
EBX
{ Restores pre-last info, that was pushed, from stack to EDX }
004012F4 LEAVE
{Almost Abandoned the CALL }
004012F5 RET
{RETurn from CALL to main program }
004011F4 CMP
EAX, 01
{ If EAX =1 then jump to good message }
004011F7 JNZ 004011D1
{ If EAX is not equal to 1 then jump to 'BAD' }
Calculation
of the Serial:
Before we prepare a Brute Forcer,
let me explain what it is. A bit of theory will be just good...
BRUTE FORCER
-is
a program that was prepared by a cracker for finding the final result using
the power of his/her Personal Computer. Usually it is prepared when the
Serial is HardCoded and when the Serial is Encrypted.
a) If the final goal is a Number
then the principle is like this:
- Coder declares
a COUNTER, that will undergo all the calculations that are necessary for
reaching the final value. Usually, the initial value is COUNTER=0, but
it can be changed depending on the calculations in the program, but this
can be decided only by experienced cracker.
- As it passed
all the calculations, the counter is compared with final value and if it
is not equal to it then the counter is increased by one, and cracker must
start all the calculations from the beginning, and it will last until computer
find a Real Serial (Number)
b) If the final goal is a Word (Like
in this CrackMe) the principle is a little bit different:
- Firstly, cracker
should know the length of the Serial, otherwise it will be very hard to
get the right Serial (btw: here we also do not know what's the length of
Serial), and depending on the length of Serial he/she will construct the
proper code
- Cracker constructs
as many loops as is the length of the Serial, but these loops must be one
in another (you will see it soon), and the calculations on chars of the
word are in the final loop.
- Comparison with
Final Word is also in the final loop, and if it's not equal, just counter
of this loop increases not begins from the beginning, so let's see, huh?
BRUTE FORCER:
It was prepared in Delphi, almost the same as PASCAL, so I think also will
be understandable, also here is a piece in inline ASM, that will be for
sure not a problem!
procedure TForm1.Button1Click(Sender:
TObject);
const
n=6; {Number of loops}
Comp_Number:cardinal=$d3f8b10c;
var
UserName:string[20];
F:File;
Serial:string;
Main_Number:cardinal;
a,b,c,d,e:byte;
aa:byte;
ar:array [1..n] of byte;
t:byte; {counter for array}
Begin
Serial:='';
UserName:=Form1.Edit1.Text;
AssignFile(F,'Result.txt');
ReWrite(F,30);
For a:=65 to
122 Do
Begin
For
b:=65 to 122 Do
Begin
For c:=48 to 122 Do
Begin
For d:=48 to 122 Do
Begin
For e:=48 to 122 Do
Begin
For aa:=48 to 122 Do
Begin
ar[1]:=a;
ar[2]:=b;
ar[3]:=c;
ar[4]:=d;
ar[5]:=e;
ar[6]:=aa;
asm
mov esi,edi
xor ecx,ecx
add esi,n
mov byte ptr [esi+n],00h
mov cl,n
xor ebx,ebx
xor edx,edx
mov eax,esi
@1: mov bl,byte ptr [eax]
push ecx
xor cl,bl
ror ebx,cl
rol ecx,03h
shl ebx,cl
pop ecx
add edx,ebx
inc eax
cmp byte ptr [eax],00
jnz @1
Mov Main_Number,edx
end;
Serial:='';
If Main_Number=Comp_Number Then
Begin
For t:=1 to n Do
Serial:=Serial+chr(ar[t]);
{ Here you could add one more command, as
you reached this point you can jump out of the program to terminate it
using GOTO command, in fact that would be better to do, 'coz until the
program finishes your PC can explode }
BlockWrite(F,Serial[1],1);
End;
End;
End;
End;
End;
End;
End;
end;
Comments:
You may ask me, how did I know that the length of Serial will be 6, in
the beginning I did not know it!
I had to check
what should that be?! I thought that there is no name for a parfume with
less than 4 chars in it, so my Brute Forcer consisted, firstly, from 5
loops. I failed to find the Serial, so I changed it to 6, and I was RIGHT!
Serial: 2XDrvB
If I was wrong
somewhere or if you like this tut, or you have any complains just mail
me, I will think about your suggesting.
|
|
|
|
All members from Genocide Crew http://www.genocidecrew.cjb.net/
All members
from Hellforge
http://www.hellforge.org
Enormous thanks
goes and Mercution {his design of this tut} for providing HellForge with
glorious LOGOs
To every one
who makes tutorials
Cool coders:
Terminal Cilla, AntiXrist, Chafe, The+Q, LaZaRuS, defiler, Lucifer48, Fatboy
Joe
CzDrillard { he is great in making good Math algos}
Crackers
:
SiFLyiNG, mIST, C_DKnight, TSCube (my special greetings to you, friend),
and everybody I forgot to add...
Special greetings:
Eternal Bliss and ID people
|
|