Taisam zālītes paši – keygen

Pirms kāda laiciņa uzrakstīju nelielu rakstu par “zālīšu pagatavošanu” mājas apstākļos. Interese un atsaucība bija diezgan liela. Atsaucās arī daudzi zālīšu pagatavošanas lietpratēji, tāpēc pamazām tiek domāts arī par Latvijas crackme lapas izveidi. Ja kāds grib iesaistīties, tad sūtam vēstules uz oollee at datuve.lv.

[b]Vecais_Dumais_Laacis[/b] ir iesūtījis savu versiju par keygen izveidi programmai LatHack Audio Tag Editor. Lasam un priecājamies. Ar šīm zināšanām jau vajadzētu pietikt, lai tiktu galā ar vienkāršām aizsardzībām.

Tātad. Kā izveidot keygen’u LatHack Audio Tag Editor’am?
No iepriekšējā raksta par tuvu tēmu ‘Taisam zālītes paši‘ mēs jau zinām dažas lietas:
* Kā izsaukt reģistrācijas logu
* Lietotāja vārdam ir jābūt vismaz 5iem simboliem.
* Funkcijas, kura pārbauda koda pareizību, adresi – 0040C76C

Lietas, kuras būs nepieciešamas:
* Pati programma 😉
* OllyDbg 1.10
* Noderētu arī kāds C kompilētājs/IDE (MS Visual Studio / DevC++)
* Nedaudz laika un pacietības
* Kaut nelielas zināšanas par C/ASM

Nu aš sāksim nu 😉

1) Palaižam programmu un tiekam līdz reģistrācijas pieprasījumam

2) Palaižam OllyDbg un ‘attačojamies’ procesam (File – Attach)

3) Ieliekam ‘breikpointu’ lai programmas izpilde apstaatos uz paarbaudes. Plugins-Command Line-Command Line
Liekam ‘breikpointu’ – ierakstām ‘bp 0040C76C’

Braši nospiežam Enter taustiņu un Breakpoints logā vajadzētu parādīties jaunam ierakstam

4) Turpinām programas izpildi, kura tika apstādināta brīdī, kad tika veikts ‘attach to process’, ar Debug-Run.
Ierakstām lietotāja vārdu (pietiekoši garu) un kautkādu kodu.

Nospiežam register un caps ollydbg apstaadina programmu tieshi uz paarbaudes funkcijas saakumu

5) Te nu naaksies mazlietiņ padomāt 😉

Tas, kas uzreiz krīt acīs, ir:
* sprintf ar “ID3TEDT-%X”
* strcmp

Ar strcmp viss daudz maz skaidrs salīdzinam stringus un pasakām sakrīt vai nē.
Ar sprintf ir mazlietiņ tā, ka jāpadomā 😉
No dotajiem datiem varam spriest, ka kods ir jaaievada dotajaa formaa (“ID3TEDT-%X”, kur %X apzīmē heksdecimālo skaitli ar lielajiem burtiem)

Vēl var nojaust, ka šis skaitlis tiek ģenerēts šajā vietā:

Tātad lecam bedrē, lecam bedrē.. tfu. Liekam breikpointu uz 0040C74D.

Laižaim programmu tālāk – Debug-Run

6) Apstājamies pie tikko ieliktā breikpointa.

Redzam savu ievadīto lietotāja vārdu un strlen funkciju.
Šeit var arī redzēt, ka tiek izsaukt vēl viena funkcija (0040C6D9), kurai tiek kā parametri padoti:
* lietotāja vārda garums (PUSH EAX, kas ir strlen rezultāts)
* pats lietotāja vārds (PUSH DWORD PTR SS:[ESP+8] )
* 0?

Šīs funkcijas (0040C6D9) atgrieztais rezultāts tiek ‘xorēts’ (XOR EAX, DEADBEEF)

Ejam tālāk liekam breikpointu uz 0040C6D9 un turpinām izpildi.

7) Atkal apstājamies

Sadalīsim visu 2ās daļās
No 0040C6D9 līdz 0040C713 (neieskaitot)
No 0040C713 līdz 0040C74C

Pirmajā daļā tiek aizpildīts masīvs ar ģenerētiem skaitļiem (to gan es sapratu tikai rakstot rakstu 😉

Otrajā daļā tiek ņemti burti no lietotāja vārda un izmantojot iepriekš ģenerēto masīvu tiek ģenerēts maģiskais skaitlis, kuru beigās izmanto koda ģenerācijā.

Ņemot vērā to, ka es vēljoprojām neesmu iedziļinājies masīva ģenerēšanas algoritmā, pirmo daļu attiecīgi nevarēšu aprakstīt.

Par otro daļu:

0040C713 |> 8B4C24 14 MOV ECX,DWORD PTR SS:[ESP+14]
[b]Ievietojam ECX reģistrā lietotāja vārda garumu (padots kā parametrs)[/b]
0040C717 |. 8B4424 0C MOV EAX,DWORD PTR SS:[ESP+C]
[b]Ievietojam EAX reģistrā trešo parametru 0[/b]
0040C71B |. 8BD1 MOV EDX,ECX
[b]Kopējam ECX reģistra saturu (lietotāja vārda garums) uz EDX reģistru[/b]
0040C71D |. 49 DEC ECX
[b]Samazinām par vienu ECX reģistra vērtību[/b]
0040C71E |. 85D2 TEST EDX,EDX
[b]Salīdzinām EDX ar EDX[/b]
0040C720 |. F7D0 NOT EAX
[b]Invertējam EAX reģistru (iegūstam 0xFFFFFFFF, jo rindā 0040C717 ieguvām 0)[/b]
0040C722 |. 76 24 JBE SHORT id3tedt.0040C748
[b]Lecam projām, ja lietotāja vārda garums ir 0?[/b]
0040C724 |. 8D51 01 LEA EDX,DWORD PTR DS:[ECX+1]
[b]Ielādējam EDX reģistrā 9???[/b]
0040C727 |. 8B4C24 10 MOV ECX,DWORD PTR SS:[ESP+10]
[b]EAX reģistrā ieliekam lietotāja vārda adresi atmiņā[/b]
[b]Šeit ir redzams cikls[/b]
0040C72B |> 0FB639 /MOVZX EDI,BYTE PTR DS:[ECX]
[b]Ievietojam EDI reģistrā ECX reģistrā esošo vērtību (sākumā šī vērtība ir 4C, kas atbilst ‘L’, jeb pirmajam burtam dotajā gadījumā)[/b]
0040C72E |. 8BF0 |MOV ESI,EAX
[b]Kopējam uz ESI reģistru EAX reģistra vērtību (pirmajā reizē 0xFFFFFFFF)[/b]
0040C730 |. 81E6 FF000000 |AND ESI,0FF
[b]Izveicam bināro operāciju AND ar ESI reģistru un 0xFF (rezultātu saglabājas ESI reģistrā)[/b]
0040C736 |. 33F7 |XOR ESI,EDI
[b]Izveicam bināro operāciju XOR ar ESI un EDI reģistriem (rezultātu saglabājas ESI reģistrā)[/b]
0040C738 |. C1E8 08 |SHR EAX,8
[b]Izveicam bināro operāciju SHR – faktiski izdalām EAX ar 256[/b]
0040C73B |. 8B34B5 C0D9420>|MOV ESI,DWORD PTR DS:[ESI*4+42D9C0]
[b]Izmantojot maģisko iepriekš ģenerēto tabulu kopējam vērtību no tabulas uz ESI reģistru. (ESI=Table[ESI])[/b]
0040C742 |. 33C6 |XOR EAX,ESI
[b]Izveicam bināro operāciju XOR ar EAX un ESI reģistriem (rezultātu saglabājas EAX reģistrā)[/b]
0040C744 |. 41 |INC ECX
[b]Palielinam ECX reģistru (tur glabājas pointeris uz lietotāja vārdu. Pēc šīs operācijas ECX norāda uz nākošo burtu)[/b]
0040C745 |. 4A |DEC EDX
[b]Samazinām EDX reģistru – EDX bija vārda garums, kurš tiek samazināts līdz visi burti ir izmantoti)[/b]
0040C746 |.^75 E3 \JNZ SHORT id3tedt.0040C72B
[b]Ja visi burti navizmantoti (EDX!=0), tad atkārtojam ciklu[/b]
0040C748 |> 5F POP EDI
0040C749 |. 5E POP ESI
[b]Atjaunojam no steka iepriekšējās EDI un ESI vērtības[/b]
0040C74A |. F7D0 NOT EAX
[b]Invertējam EAX reģistru[/b]
0040C74C \. C3 RETN
[b]Atgriežamies pie izsaucēja funkcijas[/b]

Uff. Pārvēršot šo visu c kodā sanāk apmēram šādi.

DWORD GetSerial2(int len, char *Username){
	DWORD esi;
	DWORD eax=-1;//0040C720 

	for(int s=0;s> 8;//0040C738
		esi=table[esi];//0040C73B
		eax=eax ^ esi;//0040C742
	}
	eax=-eax-1;//0040C74A	
	return eax;
}
Par tabulu mazliet vēlāk.

8) Atceroties 6o daļu

void GetSerial(char *Username, char *code){
	int l=strlen(Username);
	DWORD l2=GetSerial2(l, Username);//oriģināli šī funkcija tiek izsaukt
ar 0?, bet ja jau mēs to zinām tad ievietojam to jau pašā funkcijā
	l2=l2 ^ 0xDEADBEEF;//0040C766
	//atceroties 4o daļu un sprintf'u
	sprintf(code, "ID3TEDT-%X", l2);
}

9) Gandrīz viss kārtībā 😉

Izņemot tabulu. Šeit es mazliet pašmaucos un nokopēju datus no atmiņas failā un startējot keygenu ielasu vērtības no tā, bet kāds jau var pameklēt algoritmu pēc kāda šī tabula tika izveidota 😉

Tas arī praktiski viss.

Izmantojot funkciju GetSerial (padodot lietotāja vārdu un masīvu, kurā ievietot kodu), iegūstam kodu no lietotāja vārda.

Executable un Source

Share on facebook
Share on twitter
Share on linkedin
Share on whatsapp

Atbildēt

Jūsu e-pasta adrese netiks publicēta. Obligātie lauki ir atzīmēti kā *

Datuve.lv – IT un Tehnoloģiju ziņas || Copyright © 2004-2020 || Kontaktinformācija: info@datuve.lv  || Contact Us