Esenlikler;
s3rh47 KeygenMe ile bugün yeni bir keygenning dersini yapacağız. KeygenMe’yi (ve keygeni ile kaynak kodlarını da) yazımızın en altındaki bağlantıdan ya da decompile.us‘daki konu başlığından indirebilirsiniz.
1. KeygenMe’yi ExeInfo ile açalım:
Gördüğünüz gibi herhangi bir paketleme kullanılmamış.
2. IDA Pro ile önce dosyayı disassemble etmek ve kurcalamak istiyorum:
Resimde sol tarafta keygenme içerisindeki yordamları (fonksiyon) görüyorsunuz. Pembe olanlar dışarıdan çağrılan fonksiyonlar. Start, DialogFunc, sub_4010DE ve sub_40110F ise s3rh47’in yazdığı yordamlar ;) Biz bu 4 dört yordamı inceleyeceğiz. Eğer assembly yazılarımı okuduysanız, Start yordamı henüz ekrana bir pencere basılmadan önce yapılan hazırlıkları barındırıyor. s3rh47 Start yordamı içerisinde DialogBoxParam apisini çağırıyor ; bu yordam bir taslak(template) kullanarak pencere (modal dialog olarak geçer) yaratıyor. Ama bu kadar değil; API pencere yaratmak için bir de yordama ihtiyacı var: DialogFunc.
3. Şimdi de sol taraftaki mönüden DialogFunc’a çift tıklayarak bu yordamın(IDA Pro bunları subroutine olarak adlandırıyor ben yordam demeye devam edeceğim) içine girelim(Kod satırlarına noktalı virgüllerden son eklemeler yaptım onları da okuyalım):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
40102E. PUSH EBP 40102F. MOV EBP,ESP 401031. MOV EAX,DWORD PTR SS:[EBP+0xC] 401034. CMP EAX,0x110 401039. JNZ SHORT 00401077 ; s3rh47_K.00401077 40103B. PUSH 0x1388 ; /RsrcName = 5000. 401040. PUSH DWORD PTR DS:[0x4030F0] ; |hInst = NULL 401046. CALL 00401358 ; \LoadBitmapA 40104B. PUSH 0x1389 ; /RsrcName = 5001. 401050. PUSH DWORD PTR DS:[0x4030F0] ; |hInst = NULL 401056. CALL 0040135E ; \LoadIconA 40105B. MOV DWORD PTR DS:[0x4030F4],EAX 401060. PUSH DWORD PTR DS:[0x4030F4] ; /lParam = 0x0 401066. PUSH 0x0 ; |wParam = 0x0 401068. PUSH 0x80 ; |Message = WM_SETICON 40106D. PUSH DWORD PTR SS:[EBP+0x8] ; |hWnd 401070. CALL 0040136A ; \SendMessageA 401075. JMP SHORT 004010D5 ; s3rh47_K.004010D5 401077> CMP EAX,0x111 40107C. JNZ SHORT 004010BB ; s3rh47_K.004010BB 40107E. MOV EAX,DWORD PTR SS:[EBP+0x10] 401081. MOV EDX,DWORD PTR SS:[EBP+0x10] 401084. SHR EDX,0x10 401087. CMP EAX,0x3EE 40108C. JNZ SHORT 0040109A ; s3rh47_K.0040109A 40108E. PUSH DWORD PTR SS:[EBP+0x8] 401091. CALL 0040110F ; s3rh47_K.0040110F---->Kayit Et butonuna tiklaninca bu çağrılıyor 401096. LEAVE 401097. RETN 0x10 40109A> CMP EAX,0x3EF 40109F. JNZ SHORT 004010D5 ; s3rh47_K.004010D5 4010A1. PUSH 0x0 ; /Style = MB_OK|MB_APPLMODAL 4010A3. PUSH 0x4030A2 ; |Title = "Hakkinda" 4010A8. PUSH 0x4030AB ; |Text = "s3rh47 # KeygenMe 18.05.2018 www.decompile.us" 4010AD. PUSH DWORD PTR SS:[EBP+0x8] ; |hOwner 4010B0. CALL 00401364 ; \MessageBoxA 4010B5. LEAVE 4010B6. RETN 0x10 4010B9. JMP SHORT 004010D5 ; s3rh47_K.004010D5 4010BB> CMP EAX,0x10 4010BE. JNZ SHORT 004010CC ; s3rh47_K.004010CC 4010C0. PUSH 0x0 ; /Result = 0x0 4010C2. PUSH DWORD PTR SS:[EBP+0x8] ; |hWnd 4010C5. CALL 0040134C ; \EndDialog 4010CA. JMP SHORT 004010D5 ; s3rh47_K.004010D5 4010CC> MOV EAX,0x0 4010D1. LEAVE 4010D2. RETN 0x10 4010D5> MOV EAX,0x1 4010DA. LEAVE 4010DB. RETN 0x10 |
Yukarıda da gördüğünüz gibi DialogFunc s3rh47’in penceresinin ikonunu dialoga ekliyor, “Hakkinda” butonuna basılırsa mesaj kutusunu açıyor ve eğer “Kayit Et” butonuna basarsa da “401091. CALL 0040110F” satırında görüleceği gibi kayıt etme algoritmasının bulunduğu yordam çağrılıyor.
4. Şimdi keygenmemizi ollydbg ile açalım ve 40110F adresine kesme noktamızı(breakpoint) F2 ile koyalım, sonra F9 ile çalıştıralım. KeygenMe dialogu ekrana gelince ben
Name: bluedevil
Serial: 1122334455667788
girdim. Kayit Et butonuna basalım ve aşağıdaki kodda duralım:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 |
40110F/$ PUSH EBP 401110|. MOV EBP,ESP 401112|. PUSH EBX 401113|. PUSH EDI 401114|. PUSH ESI ;RtlZeroMemory ile s3rh47 5 tane değişkeni "0" sıfırlıyor: 401115|. PUSH 0x410 ; /Length = 410 (1040.) 40111A|. PUSH 0x404548 ; |Destination = s3rh47_K.00404548;; Uzgunum bayim yanlis serial yazilacak yer 40111F|. CALL 00401340 ; \RtlZeroMemory 401124|. PUSH 0x410 ; /Length = 410 (1040.) 401129|. PUSH 0x404958 ; |Destination = s3rh47_K.00404958 40112E|. CALL 00401340 ; \RtlZeroMemory 401133|. PUSH 0x410 ; /Length = 410 (1040.) 401138|. PUSH 0x403918 ; |Destination = s3rh47_K.00403918 40113D|. CALL 00401340 ; \RtlZeroMemory 401142|. PUSH 0x410 ; /Length = 410 (1040.) 401147|. PUSH 0x403D28 ; |Destination = s3rh47_K.00403D28; girdigimiz serialin tutulacagi yer 40114C|. CALL 00401340 ; \RtlZeroMemory 401151|. PUSH 0x410 ; /Length = 410 (1040.) 401156|. PUSH 0x404138 ; |Destination = s3rh47_K.00404138 40115B|. CALL 00401340 ; \RtlZeroMemory 401160|. LEA ESI,DWORD PTR DS:[0x4030DC];Address=004030DC, (ASCII "s3rh47&DECOMPILE") 401166|. LEA EDI,DWORD PTR DS:[0x403918];Address=00403918 adresin içi boş 40116C|> /LODS DWORD PTR DS:[ESI] ;\esi'deki dizinin ilk 4 baytındaki değeri al ve EAX'e yaz 40116D|. |OR EAX,EAX ;|bu OR işleminin amacı dizi sonunun tespiti için 40116F|. |JE SHORT 00401177 ;|tüm karakterler işlendiyse dallan 401171|. |STOS DWORD PTR ES:[EDI] ;|eax'deki değeri EDI'deki adrese yaz 401172|. |MOV ECX,0x2 ;|ECX = 2 401177|>^\LOOPD SHORT 0040116C ;/döngü şartı sağlanıyorsa yukarı dallan 401179|. MOV AL,0x0 ; AL=0 40117B|. STOS BYTE PTR ES:[EDI] ; EDI'deki adrese 0 atıyor olurda dizi sonuna "NULL" gelmezse diye 40117C|. PUSH 0x410 ; /Count = 410 (1040.) 401181|. PUSH 0x4030F8 ; |Buffer = s3rh47_K.004030F8 401186|. PUSH 0x3EA ; |ControlID = 3EA (1002.) 40118B|. PUSH DWORD PTR SS:[EBP+0x8] ; |hWnd 40118E|. CALL 00401352 ; \GetDlgItemTextA APIsi 4030F8 adresine bizim "Name" yazıyor 401193|. OR EAX,EAX ; API sorunsuz çalışırsa EAX'e aldığı dizinin uzunluğunu döndürür 401195|. JE SHORT 0040119C ; isim girilmediyse 40119C adresine dallan "hata mesajı" 401197|. CMP EAX,0x4 40119A|. JNB SHORT 004011B7 ; isim girilip 4 karakterden büyükse 4011B7 adresine dallan ve "Hata mesajına girme" 40119C|> PUSH 0x0 ; /Style = MB_OK|MB_APPLMODAL 40119E|. PUSH 0x403000 ; |Title = "HATA!" 4011A3|. PUSH 0x403006 ; |Text = "Isim Girmediniz ve en az 4 Karakter Girmelisiniz!" 4011A8|. PUSH DWORD PTR SS:[EBP+0x8] ; |hOwner 4011AB|. CALL 00401364 ; \MessageBoxA 4011B0|. POP ESI 4011B1|. POP EDI 4011B2|. POP EBX 4011B3|. LEAVE 4011B4|. RETN 0x4 4011B7|> PUSH 0x410 ; /Count = 410 (1040.) 4011BC|. PUSH 0x403508 ; |Buffer = s3rh47_K.00403508 4011C1|. PUSH 0x3EB ; |ControlID = 3EB (1003.) 4011C6|. PUSH DWORD PTR SS:[EBP+0x8] ; |hWnd 4011C9|. CALL 00401352 ; \GetDlgItemTextA APIsi 403508 adresine serialimizi yazıyor. 4011CE|. OR EAX,EAX ; hatırlayın EAX'de serialin uzunluğu olması gerekiyor eğer 0 ise demekki kullanıcı serial girmemiş 4011D0|. JNZ SHORT 004011ED ; s3rh47_K.004011ED 4011D2|. PUSH 0x0 ; /Style = MB_OK|MB_APPLMODAL 4011D4|. PUSH 0x403000 ; |Title = "HATA!" 4011D9|. PUSH 0x403038 ; |Text = "Serial Girmediniz!" 4011DE|. PUSH DWORD PTR SS:[EBP+0x8] ; |hOwner 4011E1|. CALL 00401364 ; \MessageBoxA 4011E6|. POP ESI 4011E7|. POP EDI 4011E8|. POP EBX 4011E9|. LEAVE 4011EA|. RETN 0x4 4011ED|> LEA ESI,DWORD PTR DS:[0x403508];ESI = serialimizin adresi 4011F3|. LEA EDI,DWORD PTR DS:[0x403D28];EDI = içi boş adres değeri 4011F9|. XOR EBX,EBX ;EBX = 0 4011FB|> /LODS BYTE PTR DS:[ESI] ;serialin ilk baytını al ve AL yazmacına yaz 4011FC|. |OR AL,AL ; AL = NULL mu? 4011FE|. |JE SHORT 0040120C ; s3rh47_K.0040120C;AL = NULL ise döngü sonuna git 401200|. |CMP AL,0x2D ; AL = 2D = "-" mi? 401202|. |JNZ SHORT 00401206 ; s3rh47_K.00401206 2D değilse dallan 401204|. |LODS BYTE PTR DS:[ESI] 401205|. |INC EBX ; '-' tire sayacı,seriale girilen tireleri sayıyor 401206|> |STOS BYTE PTR ES:[EDI] ; AL'deki değeri EDI'ye yaz 401207|. |MOV ECX,0x2 ; ECX = 2 40120C|>^\LOOPD SHORT 004011FB ; s3rh47_K.004011FB 40120E|. MOV AL,0x0 401210|. STOS BYTE PTR ES:[EDI] 401211|. PUSH EBX ;daha sonra kullanılmak üzere tire sayısını yığına atıyor. 401212|. LEA ESI,DWORD PTR DS:[0x403D28]; girdiğimiz serial var(eğer tire girdiysek tireleri çıkartılmış serial var) 401218|. LEA EDI,DWORD PTR DS:[0x404138]; 404138 adresi boş 40121E|. XOR EBX,EBX ; EBX = 0 401220|. MOV EDX,0x1 ; EDX = 1 |
Aşağıdaki döngü girdiğimiz serialdeki değeri sanki bir onaltılık sayı yazmışız gibi belleğe atıyor ama tam olarak değil. Yani 11111111 girdiysen belleğe 31313131 olarak değil yine 11111111 olarak alıyor. Ayrıca algoritma 8 karakter alıp alıp işlem yapıyor EDX yazmacının 8 ile kontrolünün nedeni o. Mesela 12345678AB girdiniz seriale AB önemsenmiyor çünkü döngü başlarken AL yazmacının 0 olup olmamasını kontrol ediyor. Durum böyle olunca en çok 32 karakterlik bir serial girmemiz gerekiyor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
401225|> /LODS BYTE PTR DS:[ESI] ; ESInin sakladığı adresin ilk baytını AL'ye yaz 401226|. |OR AL,AL ; Switch (cases 0..46) 401228|. |JE SHORT 00401258 ; s3rh47_K.00401258 40122A|. |CMP AL,0x46 ; AL == 0x46h == 'F' ? F'den büyük karakter girdiysen yanlis serial hata mesajına dallanıyor 40122C|. |JA SHORT 00401232 ; s3rh47_K.00401232 ;Küçükse dallan 40122E|. |CMP AL,0x30 ; AL == 0x30h = BOŞLUK ? 401230|. |JNB SHORT 00401237 ; s3rh47_K.00401237; Altında değilse dallan 401232|> |JMP 004012F4 ; s3rh47_K.004012F4; Default case of switch 00401226 401237|> |CMP AL,0x41 ; AL == 0x41h == 'A' ? 401239|. |JNB SHORT 0040123F ; s3rh47_K.0040123F; Altında değilse dallan 40123B|. |SUB AL,0x30 ; AL = AL -0x30h 40123D|. |JMP SHORT 00401241 ; s3rh47_K.00401241 40123F|> |SUB AL,0x37 ; Cases 41 ('A'),42 ('B'),43 ('C'),44 ('D'),45 ('E'),46 ('F') of switch 00401226 401241|> |ADD BL,AL ; Cases 30 ('0'),31 ('1'),32 ('2'),33 ('3'),34 ('4'),35 ('5'),36 ('6'),37 ('7'),38 ('8'),39 ('9'),3A (':'),3B (';'),3C ('<'),3D ('='),3E ('>'),3F ('?'),40 ('@') of switch 00401226 401243|. |CMP EDX,0x8 401246|. |JNZ SHORT 0040124F ; s3rh47_K.0040124F 401248|. |MOV EAX,EBX 40124A|. |BSWAP EAX ; EAX'deki değeri ters çevir 40124C|. |STOS DWORD PTR ES:[EDI] ; EAX'deki değeri EDI'ye yaz 40124D|. |XOR EDX,EDX ; EDX = 0 40124F|> |SHL EBX,0x4 ; EBX'deki değeri 4 bit sola kaydır 401252|. |INC EDX ; EDX 401253|. |MOV ECX,0x2 ; ECX = 2 401258|>^\LOOPD SHORT 00401225 ; s3rh47_K.00401225; Case 0 of switch 00401226 40125A|. MOV AL,0x0 40125C|. STOS BYTE PTR ES:[EDI] 40125D|. LEA ESI,DWORD PTR DS:[0x4030F8];ESI = Name adresi 401263|. XOR EBX,EBX ; EBX = 0 401265|> /MOVZX EAX,BYTE PTR DS:[ESI] ; Name ile bayt EAX'e atanıyor 401268|. |OR EAX,EAX ; Name'den NULL gelirse burada kontrol edip döngüden çıkılacak 40126A|. |JE SHORT 00401292 ; s3rh47_K.00401292 40126C|. |MOV ECX,EAX ; ECX = EAX; Name'in bir karakteri kendi sayısal değeri kadar aşağıdaki küçük dönyüye sokulacak 40126E|> |/LEA EAX,DWORD PTR DS:[EAX+EAX*4];EAX = EAX + (EAX * 4) 401271|. ||DEC ECX 401272|. ||OR ECX,ECX 401274|.^|\JNZ SHORT 0040126E ; s3rh47_K.0040126E 401276|. |CMP EBX,0x10 ; EBX 0x10h yani 16 ile kontrol ediliyor çünkü her seferinde 4 bayt yazılıyor böylece 4x4=16dan toplam 16 bayt yazılmasını kontrol ediyor. ;Diyelimki 16 bayt yazdı ama hala Name var karakterleri bitmedi, başa dönülmesi gerekiyor. ;İşte kontrolü yapıyor bir kere dallanıyor; dallanmadan sonra EBX'e yine 4 atıyor. Bu sayede baştan yazmaya devam ediyor: 401279|. |JE SHORT 00401286 ; s3rh47_K.00401286 40127B|. |ADD EBX,0x4 40127E|. |ADD DWORD PTR DS:[EBX+0x403914],EAX;burada s3rh47&DECOMPILE var ve ilk 4 baytı ile bizim az önce ürettiğimiz sayı toplanıp üzerine yazılıyor 401284|. |JMP SHORT 00401291 ; s3rh47_K.00401291 401286|> |MOV EBX,0x4 40128B|. |ADD DWORD PTR DS:[EBX+0x403914],EAX 401291|> |INC ESI 401292|> |OR EAX,EAX 401294|.^\JNZ SHORT 00401265 ; s3rh47_K.00401265 401296|. MOV ECX,0x4 ; Döngü bittiğinde 0x403918 adresinde serialimiz kısmen hazır 40129B|. LEA ESI,DWORD PTR DS:[0x404138];ESI =Serialimizin bellekteki adresi(dialogdan girilen) 4012A1|. PUSH 0x403918 ; name'den üretilen serial 4012A6|. XOR EBX,EBX ; ebx = 0 4012A8|> /LODS DWORD PTR DS:[ESI] ; girilen serialin 4 baytı eax'e yazılıyor 4012A9|. |MOV EDI,DWORD PTR SS:[ESP] ; Name kullanılarak üretilen değer burada EDI'ye aktarılıyor. 4012AC|. |XOR DWORD PTR DS:[EDI],EAX ; Serialin ilk 4 baytı ve ya sekiz karakteri burada gerçek serial ile XOR işlemine tabi tutuluyor. Eğer biz gerçek seriali girebilmiş olsaydık o zaman sonuç 0 olacaktı. 4012AE|. |ADD DWORD PTR DS:[ESP],0x4 ;sonraki 4 bayt için stack pointerı 4 artır 4012B3|. |ADD EBX,DWORD PTR DS:[EDI] ;Doğru serial girilince EDI'nin gösterdiği yer xorlanarak sıfırlanmış olacak ve ebx'te 0 olduğu için toplamı da sıfır olacak 4012B5|. |DEC ECX ; ecx -= 1 4012B6|.^\JNZ SHORT 004012A8 ; s3rh47_K.004012A8 4012B8|. POP EDX 4012B9|. POP EDX ; EDX = serialdeki tire sayısı 4012BA|. OR EBX,EBX ; EBX = NULL mu? Eğer NULL ise doğru serial girilmiş demektir. 4012BC|. JNZ SHORT 004012F4 ; s3rh47_K.004012F4 4012BE|. PUSH EDX ; EDX deki tire sayısını yığına atıyor 4012BF|. PUSH 0x404548 ; boş tampon alan şifreli mesaj buraya çözülecek 4012C4|. PUSH 0x40304B ; ASCII "Wfaqjhofq"#Pfm#av#jpjm#fkojpjm#9*#" Şifreli İYİ ÇOCUK mesajı 4012C9|. CALL 004010DE ; s3rh47_K.004010DE; bu çağrı içinde şifre çözülüyor 4012CE|. PUSH EDX 4012CF|. PUSH 0x404958 4012D4|. PUSH 0x40306E ; ASCII "Wfaqjhofq"""" 4012D9|. CALL 004010DE ; s3rh47_K.004010DE 4012DE|. PUSH 0x0 ; /Style = MB_OK|MB_APPLMODAL 4012E0|. PUSH 0x404958 ; |Title = "" 4012E5|. PUSH 0x404548 ; |Text = "" 4012EA|. PUSH DWORD PTR SS:[EBP+0x8] ; |hOwner 4012ED|. CALL 00401364 ; \MessageBoxA 4012F2|. JMP SHORT 0040132D ; s3rh47_K.0040132D 4012F4|> MOV EDX,0x0 ; EDX = 0 4012F9|. PUSH EDX 4012FA|. PUSH 0x404548 4012FF|. PUSH 0x40307B ; ASCII "Þxeþlþo"@c{ko"."[clnkq"Qgpkcn"8*"" Şifreli KÖTÜ ÇOCUK mesajı 401304|. CALL 004010DE ; s3rh47_K.004010DE 401309|. PUSH EDX 40130A|. PUSH 0x404958 40130F|. PUSH 0x40309D ; ASCII "Jcvc" 401314|. CALL 004010DE ; s3rh47_K.004010DE 401319|. PUSH 0x0 ; /Style = MB_OK|MB_APPLMODAL 40131B|. PUSH 0x404958 ; |Title = "" 401320|. PUSH 0x404548 ; |Text = "" 401325|. PUSH DWORD PTR SS:[EBP+0x8] ; |hOwner 401328|. CALL 00401364 ; \MessageBoxA 40132D|> POP ESI 40132E|. POP EDI 40132F|. POP EBX 401330|. LEAVE 401331\. RETN 0x4 |
401304 adresindeki “CALL 004010DE” çağrısı bizim hata ve başarma mesajlarımızı çözen fonksiyon:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
4010DE/$ PUSH EBP 4010DF|. MOV EBP,ESP 4010E1|. MOV ESI,DWORD PTR SS:[EBP+0x8]; ESI = ASCII "Wfaqjhofq"#Pfm#av#jpjm#fkojpjm#9*#" 4010E4|. MOV EDI,DWORD PTR SS:[EBP+0xC]; EDI = tampon 4010E7|. XOR EAX,EAX ; EAX = 0 4010E9|. CMP DWORD PTR SS:[EBP+0x10],0x0; '-' tire sayısı 0 mı? 4010ED|. JNZ SHORT 004010F6 ; 0 değilse dallan 4010EF|. MOV EBX,0x2 4010F4|. JMP SHORT 004010F9 ; s3rh47_K.004010F9 4010F6|> MOV EBX,DWORD PTR SS:[EBP+0x10];tire sayısını EBX'e kopyala 4010F9|> /LODS BYTE PTR DS:[ESI] ; Şifreli mesajın ilk baytını al 4010FA|. |OR EAX,EAX ; Şifreli mesajın sonuna ulaşıldı mı? 4010FC|. |JE SHORT 00401106 ; s3rh47_K.00401106 4010FE|. |XOR EAX,EBX ; EAX = EAX XOR EBX şifreli mesajın her baytını tire sayısı ile XORlayarak doğru mesajı üretiyor ; doğru mesaj üretmek için 3 tireye gerek var 401100|. |STOS BYTE PTR ES:[EDI] ; EAX = EDI'deki adresin gösterdiği yer, yani temiz mesajı tampona yaz 401101|. |MOV ECX,0x2 ; ECX = 2 401106|>^\LOOPD SHORT 004010F9 ; s3rh47_K.004010F9 401108|. MOV AL,0x0 40110A|. STOS BYTE PTR ES:[EDI] 40110B|. LEAVE 40110C\. RETN 0xC |
s3rh47 iyi çocuk ve kötü çocuk mesajlarını 3 ile XORlayarak şifrelemiş. Seriali GetDlgItemTextA APIsi ile çekip tek tek karakterlerini kontrol ediyor ve ‘-‘ tire varsa kaç tane tire olduğunu sayıp yığına(stack) gönderiyor. Eğer doğru serial girilmişse iyi çocuk mesajını bu tire sayısından gelen 3 ile tekrar xorlayıp MessageBox APIsi ile ekrana bastırıyor.
401296 adresine geldiğimizde, memory dump ekranına tıklayıp Ctrl+G yapıp 0x403918 adresini çokan kutucuğa yazıp git dersek orada içerisinde tireler olmayan doğru serialimizi göreceğiz. Buna 3 tane de tire eklersek geçerli bir serialimiz olur:
name: bluedevil
serial:55D8479A-C992A463-64739734-A6B7CDD3
Ama s3rh47 bir tire kontrolü yapmamış.
55D8479-A-C992A46364739734A6B7CDD-3
55D8479A-C992A463-64739734A6-B7CDD3
5-5-D-8479AC992A46364739734A6B7CDD3
Örneğin bu üçü de geçerli serial oluyor. Sadece tireler yan yana gelmemesi gerek yoksa 4011FB adresindeki tire sayacı döngüsü ard arda gelen tirelerden ikincisini sanki bir onaltılık değermiş gibi memory’e atıyor ve saymıyor. Bu da serialin hatalı olmasına neden oluyor.
Ayırdına vardıysanız s3rh47 kullanıcının girdiği kullanıcı adını kullanarak zaten doğru seriali keygenme içerisinde kullanıyor. Ben de kodun burasını kopyala yapıştır ile alıp kendi assemly kodumun içerisime gömüp keygenimi yazacağım.
[dm]163[/dm]
Comments of this post
byclone
21 August 2018
Sayın Blue DeviL,
Örnek aldığım nadir kişilerdensiniz.Tutorial’i zevkle okudum.Tebrik ederim güzel bir anlatım olmuş.
Tutorial’e vesile olduğu ve keygenme için s3rh47’a da ayrıca teşekkür ederim.
Tire kontrolü olmadığından gözümden kaçırarak tiresiz key verdiğim keygenmedir.
BlueDeviL
01 September 2018
Çok teşekkürler, amacımız kaliteli Türkçe içerik üretmek. Beğenildiyse, işe yarıyorsa ne mutlu bize. Senin dll keygenme’ne de bakıyordum ama evde çalışamayınca çözüm üretmek, tutorial yazmak maalesef olmuyor. Zaman gerekiyor güzel bir yazı yazabilmek için.