Cracking
Audio Notes Recorder v3.4
******** by Soldat ********
August 2002
GENERAL
This tutorial will try to explain some basic tehniques for cracking ,so it is recommended to beginners ,of course everyone can read it
TOOLS Used :
OS Win 98
SOFT-ICE 4.05
IDA 4.21
Hiew 6.81 ( or another hex editor )
Warning : you can use IDA 4.20 if don’t have 4.21 I don’t know is there carck for it ,if you have trouble with this mail me
(soldatsoldat@hotmail.com ) I’ll send you the crack
ABOUT PROGRAM
Audio Notes Recorder is easy to use voice notes application. It works in systray, has two operating modes (Analog and Digital), three microphone modes (Normal, Spy, Voice Operated Recording), export to WAV/MP3/EXE option, direct message sending as email attachment, and of course - very posh design with various skins.
There are several protections that limit using demo version of this program
1. Time limitation ( the first and most important)
2. In digital mode you can save just 3 messages per cassette
3. In digital mode you can save just 30 second of your voice per message
4. In Analog mode you can save onlly one minute of sound per cassette
CRACKING
PART 1
Fire IDA and chose ANR.exe (Audio Notes Recorder v3.4) , waite for several minutes and when disassembling is over open
string window (SHIFT+F12) , look for a while and you will see 4 very useful words like this:
Unregistered
Unregistered
…….
Unregistered
Select first ,double click on it and you will see something like this:
:0052B857 aUnregistered db 'Unregistered',0 ; DATA XREF: sub_430508+742
double click on sub_430508+742 and you will find yourself in following part of the code :
.text:00430C1E add esp, 0Ch
.text:00430C21 test al, al
.text:00430C23 jz short loc_430C41
.text:00430C25 mov ecx, [ebp+arg_0]
.text:00430C28 mov byte ptr [ecx+624h], 1
.text:00430C2F lea edx, [ebp+var_48]
.text:00430C32 mov eax, [ebp+arg_0]
.text:00430C35 add eax, 5F8h
.text:00430C3A call @System@AnsiString@$basg$qqrrx17System@AnsiString System::AnsiString::operator=(System::AnsiString &)
.text:00430C3F jmp short loc_430C8A
.text:00430C41 ; ---------------------------------------------------------------------------
.text:00430C41
.text:00430C41 loc_430C41: ; CODE XREF: sub_430508+71Bj
.text:00430C41 mov [ebp+var_D4], 164h
.text:00430C4A mov edx, offset aUnregistered ; "Unregistered"
.text:00430C4F lea eax, [ebp+var_74]
.text:00430C52 call sub_5263B4
.text:00430C57 inc [ebp+var_C8]
.text:00430C5D lea edx, [ebp+var_74]
.text:00430C60 mov eax, [ebp+arg_0] (doesn’t matter)
.text:00430C63 add eax, 5F8h
We will put two nop ( 90h ) on 00430C23 it means that program in no case jump to Unregistered
fire Hiew select our program select our code 00430C23 ( F5 and input data ,enter ) then F3 , F2 input nop once ,enter ,nop again enter ,Esc then F9 ,F10 and this jump is killed
Now back in IDA select second Unregistrered ,repeat like in previous and you‘ll get something like this:
:00431132 add esp, 0Ch
.text:00431135 test al, al
.text:00431137 jz short loc_431155
.text:00431139 lea edx, [ebp+var_7C]
.text:0043113C mov eax, [ebp+arg_0]
.text:0043113F add eax, 5F8h
.text:00431144 call @System@AnsiString@$basg$qqrrx17System@AnsiString ; System::AnsiString::operator=(System::AnsiString &)
.text:00431149 mov ecx, [ebp+arg_0]
.text:0043114C mov byte ptr [ecx+624h], 1
.text:00431153 jmp short loc_43119D
.text:00431155 ; ---------------------------------------------------------------------------
.text:00431155
.text:00431155 loc_431155: ; CODE XREF: sub_430508+C2Fj
.text:00431155 mov [ebp+var_D4], 248h
.text:0043115E mov edx, offset aUnregistered_0 ; "Unregistered"
.text:00431163 lea eax, [ebp+var_C0]
.text:00431169 call sub_5263B4
( doesn’t matter )
We need to put again two nop on 00431137 to avoid jump on Unregistered
do like in previous case with Hiew
Now select 3rd Unregistred you will get following :
mov eax, [ecx]
.text:00441431 cmp dword ptr [eax+34h], 78h
.text:00441435 jnz short loc_441459
.text:00441437 mov edx, 5Eh
.text:0044143C mov eax, [ebx+2D4h]
.text:00441442 call @Controls@TControl@SetHeight$qqri ; Controls::TControl::SetHeight(int)
.text:00441447 mov edx, 58h
.text:0044144C mov eax, [ebx+2D4h]
.text:00441452 call @Controls@TControl@SetWidth$qqri ; Controls::TControl::SetWidth(int)
.text:00441457 jmp short loc_441479
.text:00441459 ; ---------------------------------------------------------------------------
.text:00441459
.text:00441459 loc_441459: ; CODE XREF: _TAboutForm_FormShow+3Dj
.text:00441459 mov edx, 5Ch
.text:0044145E mov eax, [ebx+2D4h]
.text:00441464 call @Controls@TControl@SetHeight$qqri ; Controls::TControl::SetHeight(int)
.text:00441469 mov edx, 56h
.text:0044146E mov eax, [ebx+2D4h]
.text:00441474 call @Controls@TControl@SetWidth$qqri ; Controls::TControl::SetWidth(int)
.text:00441479
.text:00441479 loc_441479: ; CODE XREF: _TAboutForm_FormShow+5Fj
.text:00441479 mov [ebp+var_1C], 8
.text:0044147F mov edx, offset aUnregistered_1 ; "Unregistered"
.text:00441484 lea eax, [ebp+var_4]
.text:00441487 call sub_5263B4
Now
we have to change 00441435 to jump
because if we put nop it will go on Unregistered ,we don’t want this so put
jump instead
jnz ,procedure similar with Hiew
Select 4 th Unregistered ,looks like this :
.text:00443B06 call @System@AnsiString@$bdtr$qqrv ; System::AnsiString::~AnsiString(void)
.text:00443B0B pop ecx
.text:00443B0C test cl, cl
.text:00443B0E jz loc_443BD8
.text:00443B14 mov [ebp+var_4C], 74h
.text:00443B1A xor eax, eax
.text:00443B1C mov [ebp+var_30], eax
.text:00443B1F lea edx, [ebp+var_30]
.text:00443B22 inc [ebp+var_40]
.text:00443B25 mov ecx, [ebp+var_60]
.text:00443B28 mov eax, [ecx+2D0h]
.text:00443B2E call @TControl@GetText$qqrv ; TControl::GetText(void)
.text:00443B33 lea edx, [ebp+var_30]
.text:00443B36 mov ecx, off_551ABC
.text:00443B3C mov eax, [ecx]
.text:00443B3E add eax, 5F8h
.text:00443B43 call @System@AnsiString@$basg$qqrrx17System@AnsiString ; System::AnsiString::operator=(System::AnsiString &)
.text:00443B48 dec [ebp+var_40]
.text:00443B4B lea eax, [ebp+var_30]
.text:00443B4E mov edx, 2
.text:00443B53 call @System@AnsiString@$bdtr$qqrv ; System::AnsiString::~AnsiString(void)
.text:00443B58 mov ecx, off_551ABC
.text:00443B5E mov eax, [ecx]
.text:00443B60 mov byte ptr [eax+624h], 1
.text:00443B67 mov edx, [ebp+var_60]
.text:00443B6A mov eax, [edx+2D0h]
.text:00443B70 xor edx, edx
.text:00443B72 mov ecx, [eax]
.text:00443B74 call dword ptr [ecx+5Ch]
.text:00443B77 mov eax, off_551AD4
.text:00443B7C mov edx, [eax]
.text:00443B7E mov eax, [edx+330h]
.text:00443B84 mov dl, 1
.text:00443B86 mov ecx, [eax]
.text:00443B88 call dword ptr [ecx+5Ch]
.text:00443B8B mov eax, off_551AD4
.text:00443B90 mov edx, [eax]
.text:00443B92 mov eax, [edx+338h]
.text:00443B98 mov dl, 1
.text:00443B9A mov ecx, [eax]
.text:00443B9C call dword ptr [ecx+5Ch]
.text:00443B9F mov eax, off_551AD4
.text:00443BA4 mov edx, [eax]
.text:00443BA6 mov eax, [edx+334h]
.text:00443BAC mov dl, 1
.text:00443BAE mov ecx, [eax]
.text:00443BB0 call dword ptr [ecx+5Ch]
.text:00443BB3 mov eax, [ebp+var_60]
.text:00443BB6 mov eax, [eax+2D4h]
.text:00443BBC xor edx, edx
.text:00443BBE mov ecx, [eax]
.text:00443BC0 call dword ptr [ecx+5Ch]
.text:00443BC3 mov eax, [ebp+var_60]
.text:00443BC6 mov dl, 1
.text:00443BC8 mov eax, [eax+2E8h]
.text:00443BCE call unknown_libname_429
.text:00443BD3 jmp loc_443C8A
.text:00443BD8 ; ---------------------------------------------------------------------------
.text:00443BD8
.text:00443BD8 loc_443BD8: ; CODE XREF: _TRegisterForm_RegButtonClick+26Aj
.text:00443BD8 mov [ebp+var_4C], 80h
.text:00443BDE mov edx, offset aUnregistered_2 ; "Unregistered"
.text:00443BE3 lea eax, [ebp+var_34]
.text:00443BE6 call sub_5263B4
.text:00443BEB inc [ebp+var_40]
.text:00443BEE mov eax, off_551ABC
.text:00443BF3 lea edx, [ebp+var_34]
(doesn’t matter)
We have to change 00443B0E to nop to avoid jum on Unregistered ( put 6 nop because this is six byte instruction ) .Do this with Hiew of course
There is one more thing in the third Unregistered you will se one Registered to : ( after double clicking on Unregistered ) select this and you will find somethig like this
.text:004414B0 call @System@AnsiString@$bdtr$qqrv ; System::AnsiString::~AnsiString(void)
.text:004414B5 pop ecx
.text:004414B6 test cl, cl
.text:004414B8 jz short loc_4414D6
.text:004414BA xor edx, edx
.text:004414BC mov eax, [ebx+2F4h]
.text:004414C2 call @Controls@TControl@SetVisible$qqro ; Controls::TControl::SetVisible(bool)
.text:004414C7 mov dl, 1
.text:004414C9 mov eax, [ebx+2F0h]
.text:004414CF call @Controls@TControl@SetVisible$qqro ; Controls::TControl::SetVisible(bool)
.text:004414D4 jmp short loc_441538
.text:004414D6 ; ---------------------------------------------------------------------------
.text:004414D6
.text:004414D6 loc_4414D6: ; CODE XREF: _TAboutForm_FormShow+C0j
.text:004414D6 mov [ebp+var_1C], 14h
.text:004414DC xor ecx, ecx
.text:004414DE mov eax, off_551ABC
.text:004414E3 mov [ebp+var_8], ecx
.text:004414E6 lea ecx, [ebp+var_8]
.text:004414E9 inc [ebp+var_10]
.text:004414EC mov edx, [eax]
.text:004414EE mov eax, offset aRegisteredTo ; "Registered to "
.text:004414F3 add edx, 5F8h
.text:004414F9 call @System@$badd$qqrpxcrx17System@AnsiString ; System::operator+(char *,System::AnsiString &)
.text:004414FE lea edx, [ebp+var_8]
.text:00441501 mov eax, [ebx+2F4h]
( doesn’t matter )
In this case we need to chage jz on address 004414B8 to jump because we want to jump on Registered
This last thing is for every case , this will work without this but because ‘about’ in program to have clear situation ( if one looks in our program he can’t say it is not registered )
OK now you can run our sweet program and you will see that time limitation is broken but still there is limitation under 2. 3. 4.
Now it goes harder part of cracking.
Close IDA we don’t need it anymore we’re gonna use now SOFT-ICE and intuition
When 30 seconds passes window pops-up to warn us we are not pleasant anymore , OK press CTR+D and SOFT-ICE will pop-up.
Put breakpoint on Showwindow (bpx Showwindow) exit SOFT-ICE and try to save your 3 rd message in digital mode . SOFT-ICE will break ,we hit API Showwindow (Because program wants to say us :get out of here ) press F12 until you reach the code of our program .
Now let’s think for a while , this API is called because program wants to pop-up message , so it is to assume that whenever
program wanna show something ( i.e at the beginning ) he calls the same procedure but with different parameters (that is the sense of calls), so we have to find where is the beginning of our procedure responsible for message about limitation ,because if we change something in general procedure for showing window we will screw up something and program will not work
OK when we reached the code with F12 after pop-up trace for a while with F10 in SOFT-ICE .You will see that every time you reach ret from current call the next ret is not so far ,so go on untill you reach the code where is departure from this .You will see something like this :
.text:004DA6F6 mov
fs:[edx], esp
.text:004DA6F9 mov
eax, [ebp+var_4]
.text:004DA6FC call
unknown_libname_770
.text:004DA701 xor edx, edx land here
.text:004DA703 push ebp
.text:004DA704 push
offset loc_4DA7BB
.text:004DA709 push dword ptr fs:[edx]
trace F10 for a while and you will find yourself in the loop :
.text:004DA731 mov eax, [ebx]
.text:004DA733
call (some call)
.text:004DA738 mov
eax, [ebx]
.text:004DA73A cmp
byte ptr [eax+8Ch], 0
.text:004DA741 jz
short loc_4DA752
.text:004DA743 mov
eax, [ebp+var_4]
.text:004DA746 mov
dword ptr [eax+234h], 2
.text:004DA750
jmp short loc_4DA766
.text:004DA752 mov
eax, [ebp+var_4]
.text:004DA755 cmp
dword ptr [eax+234h], 0
.text:004DA75C jz
short loc_4DA766
.text:004DA75E mov
eax, [ebp+var_4]
.text:004DA761 call (some call)
.text:004DA766 mov
eax, [ebp+var_4]
.text:004DA769 mov
eax, [eax+234h]
.text:004DA76F test eax,
eax
.text:004DA771 jz short loc_4DA731
If you continue with tracing you will see how program draws letters so it means we are on the right place ,this call is our call ,scroll-up until you reach the beginning of it something like this :
.text:004DA5EC
push ebp
This is the beginning of our
call
.text:004DA5ED mov
ebp, esp
.text:004DA5EF add
esp, 0FFFFFFE0h
.text:004DA5F2 push ebx
.text:004DA5F3 push esi
.text:004DA5F4 xor
edx, edx
.text:004DA5F6 mov
[ebp+var_20], edx
.text:004DA5F9 mov
[ebp+var_4], eax
.text:004DA5FC mov
ebx, offset dword_5524B0
.text:004DA601 xor eax, eax
The end of this call is something like :
.text:004DA7A2
mov [ebp+hWnd], eax
.text:004DA7A5
xor eax, eax
.text:004DA7A7 pop edx
.text:004DA7A8 pop ecx
.text:004DA7A9 pop ecx
.text:004DA7AA mov
fs:[eax], edx
.text:004DA7AD push
offset loc_4DA7C2
.text:004DA7B2 mov
eax, [ebp+var_4]
.text:004DA7B5 call
sub_4DA534
.text:004DA7BA retn
The end of our call
Put breakpoint on ret on our call 004DA7BA ,why this ,because we want to see what part of the program code is responsible for this message about limitation
OK press now F5 in SOFT-ICE ,message is here but calm ,nothing happens ,what is with our bpx on the end of our call ,did we make mistake ,no we didn’t
Close message window ,and SOFT-ICE will pop up ,it means that we have the following situation
start of call
Waiting for us to close the window
and cotinue with execution
end of call
So we needn’t anymore bpx on API Showwindow because we know this call ,so clear it ,but put the bpx on the beginning (004DA5EC) of the call
just to se how is going all stuff .Trace for a while after ret following the logic from the beginning until you reach next :
.text:0041584D mov
edx, [eax]
.text:0041584F call
dword ptr [edx+0D8h]
.text:00415855 cmp byte ptr [edi+2F4h], 1 land here
.text:0041585C jnz
short loc_41586B
.text:0041585E mov dl,
1
.text:00415860 mov eax, [ebx+4B8h]
Scroll-up little untill you reach something like this :
.text:00415764 cmp
dword ptr [ebx+5B8h], 1
.text:0041576B jnz
loc_415989
.text:00415771 test al,
al
.text:00415773 jz loc_415989
.text:00415779 mov
byte ptr [ebx+59Ah], 1
.text:00415780 mov word ptr [esi+10h], 1D0h
(overrides critical call)
You see, jz on 00415773 will override the call we just returned ,if it is active ,so put bpx on it, put new cassette in our recorder and you will see that this jz is active first tree times and after that it is inactive ,yes that’s it ,we just have to rename it in jmp and there is no limitation in numbers of messages per cassete anymore ,do it with Hiew
There is still time limitation per message wait for 30 second ,after that time SOFT-ICE will pop-up ,because we left the bpx on the beginning of critical call ,OK do F5 ,window with message is here ,close it and as in previous SOFT-ICE pops-up,trace for a while until you reach following
.text:00409214 mov
edx, [eax]
.text:00409216 call
dword ptr [edx+0D8h]
.text:0040921C cmp byte ptr [edi+2F4h], 1 land here
.text:00409223 jnz
short loc_409232
.text:00409225 mov dl,
1
.text:00409227 mov eax, [ebx+4B8h]
Scroll up for a while until you reach next :
.text:0040912A test al,
al
.text:0040912C jz loc_4092F8
.text:00409132 mov
edx, ebx
.text:00409134 mov eax, ebx
(overrides critical call)
See when this jz is active it overrides our critical section we returned ,you can put bpx on it ,start recording and watch what is going on
but SOFT-ICE will break again and again ,if you look at secondes on the recorder’s display you will see that they’re counted up ,and this jz is active until counter reachs 30 and then he becomes inactive (jz) and goes on critical call ,then on our call etc…
yes that’s it put jmp instead jz on 0040912C and say bye ,bye to the time limitation for digital mode .
But there is still limitation for analog mode ,let’s kill it .
You remember our bpx on critical call stays , now you put analog cassette and wait for SOFT-ICE’s break ,after it close window and trace for a while until you reach next :
.text:00408FDE mov
eax, edi
.text:00408FE0 mov
edx, [eax]
.text:00408FE2 call
dword ptr [edx+0D8h]
.text:00408FE8 cmp byte ptr [edi+2F4h], 1 lend here
.text:00408FEF jnz short loc_408FFE
Scroll-up and you will see the next :
.text:00408EF6 test al,
al
.text:00408EF8 jz loc_4090C4
.text:00408EFE mov
edx, ebx
.text:00408F00 mov eax, ebx
(overrides crirical call)
Again jz (00408EF8) is active in first 60 second after that becomes inactive ,please put jmp instead jz and that’s it.We broke the last limitation enjoy
If you have any trouble with this mail me ,I hope this was useful to one who read above.Best wishes in cracking and keep cracking