tr-demoscene
the scene => coding => pc => Konuyu başlatan: 2ka - 05.06.2007 13:22:35
-
efenim oldskool copy protection rutinleri ile ilgili konu$alim diyorum netekim bazıları platform yüzünden obsolote olsada bu tarz şeyler yaklaşım açısından oldukça vizyon açıcı olaylardır diye düşünmekteyim.
hep beraber birkac tanesini yazalim :)
disasembler $a$irtmaca (bogus instruction)
instructionlar arasinda bogus data basip onlarin uzerinden atlamak suretiyle yapilir , disasembler in instruction u yanli$ dekode etmesiyle sonuclanir.
normal kod:
mov ah,09h
mov dx,120h
int 21
ret
modifiye kod:
mov ah,09h
db 0ebh,02 ; jmp +2
db 0f0h,0a0h
mov dx,105h
db 0ebh,02 ; jmp +2
db 0f0h,?
int 21
ret
disasembler sonucu :
-u 100
16A9:0100 B409 MOV AH,09
16A9:0102 EB02 JMP 0106
16A9:0104 F0 LOCK
16A9:0105 00BA0501 ADD [BP+SI+0105],BH
16A9:0109 EB02 JMP 010D
16A9:010B F0 LOCK
16A9:010C A0CD21 MOV AL,[21CD]
16A9:010F C3 RET
int u 3 (debuggerin hook ettigi breakpoint interruptu) kullanarak runtime kod dekode etme
normal ko$ullarda int 3 debugger tarafindan hook edilir . ancak biz bu interrupt i decoder rutini olarak kullanirsak o interrupt debug amacli hook edildiginde kod cali$maz hale gelir.
ornek (bogus instruction kombosuyla)
db 0ebh,02h
db 0f0h,0a0h?
int 3
db 0c8h,0bh ; xor ax,ax
disasembler sonucu :
16A9:0100 EB02 JMP 0104
16A9:0102 F0 LOCK
16A9:0103 A0CCC8 MOV AL,[C8CC]
16A9:0106 0B05 OR AX,[DI]
**basit bir int 3 handler i
Int_3_Handler:
db 0ebh,02h
db 0fh,0FFh
push ax
push bx
push dx
add sp,6
pop bx
pop ax
push ax
push bx
sub sp,6
push ds
mov ds,ax
db 0ebh,02h
db 0fh,0FFh
mov dx,word ptr ds:[bx+2]
xor [bx],dx
POP DS
pop dx
pop bx
pop ax
iret
-
Birinci yöntem 6510 ASM'de BIT ve benzeri komutlarla oyun firmaları tarafından zamanında sık sık kullanmıştır. Öyle ki 80li 90lı yıllarda crackerlar zaman zaman kafaları allak bullak olduğu için tracerlar yazmak zorunda kalmışlardır.
Int 3'ü ise ilk kez duydum. Yöntem güzel. Aklıma hemen şu soru geldi, int 3 interruptıyla yukardaki tricki kullanan bir kod modifiye etmeden debug edilebilir mi? Daha doğrusu alternatif debugging metodları var mı yoksa gerçekten debug edilmesine karşı sağlam bir önlem midir bu?
-
cpu cache trick
cogu i$lemci kodu çalıştırmadan önce bir kısmını cachelediği için yakın bölgede yapacaginiz değişikliklerin çalisan kod uzerinde etkisi olmaz. Ancak birisi kodunuzu debug ediyorsa durum değişir . bu durumu kullanarak trace edilen kodla debugsız çalışan kodun farklı olmasını sağlayabilirsiniz
örnek bi senaryo :
push si
push cs
pop ds
call zop
zop:
pop si
add si,8
mov byte ptr[si],01eh ; burda bi sonraki jump ın adresini deiştiriyoruz (kodun herhangi bi yerindeki başka bir instruction da olabilir)
db 0ebh,0a0h ; debug esnasinda deistirilen jump , normal runtime da ise orjinal jump calisiyor.
-
hatta eskiden code icine int 3 serpistirirlerdi, debugger icinde run edince durup dururken debug ekranina donerdi..
softice'i device driver olarak yuklediginde saglam bir yontem degildir..
Int 3'ü ise ilk kez duydum. Yöntem güzel. Aklıma hemen şu soru geldi, int 3 interruptıyla yukardaki tricki kullanan bir kod modifiye etmeden debug edilebilir mi? Daha doğrusu alternatif debugging metodları var mı yoksa gerçekten debug edilmesine karşı sağlam bir önlem midir bu?
-
eski copy protection yontemlerinden gordugum en absurd yontem, bir turk eczane programindaydi.. disketin sonlarinda bariz igne ile delinmis bir delik vardi, program icinde bu bolumu kontrol ediyordu..
icerigi bir baska diskete kopyalayip, ayni yere igne ile bir delik acarsan, code uzerinde degisiklik yapmana gerek kalmiyordu.. :D
-
@2ka: evet bu cache olayını deneme/yanılmayla bulmuştum ben. c64'den alışkanlık olarak self modifying code yazmaya çalıştığımda PC'de garip yavaşlamalar sezinledim. sonradan araştırdım öğrendim ki bu olay cache'i devre dışı bırakıyor, hatta yanılmıyorsam yeniden cachelenmesi için tetikliyormuş. o zaman anlamıştım zaten PC'ye geçişin uzuuuun yıllar alacağını. öyle de oldu netekim.
@gnos: abi ne kadar "absurd" de olsa bence çok yaratıcı bir fikirmiş. tebrik ediyorum yöntemi ilk düşüneni.
-
elbette bunlarin cogu modern i$letim sistemlerinde (edit: ve modern debugger'larda) gecersiz. prefetch instruction cache'i atlatmak kolay, meric (fatalica) benim yazdigim bir rutini ilk sefer yiyip, "hmm" deyip ikincide gecmi$ti. (bkz: genlock).
bu konuda gecmi$te en saygi duydugum anti-debugging trick'lerden biri turklere aittir. ankara'da guven bilgisayar diye bir firmanin hyper-lock isminde bir yazilimi vardi. decryption'i int 1 uzerinden yapiyordu.
int 1, enable edildiginde her instruction execute edildikten sonra cali$an bir interrupt. dolayisiyla her instruction decode edildiginde bir sonraki instruction'i decode eden kod cali$iyordu. bu da kolayca uzerinden gecmeyi cok zorla$tiriyordu. debugger'lar step by step trace icin instruction devamina int 3 koyduklarindan bu kod degi$tiginden decryption'i bozuyor step-by-step trace'i de engelliyordu. kod encrypted oldugundan ilerde bir yerlere de breakpoint koyamiyordunuz.
ssg
-
bunlarin yani sira cevresel aletlerden (mesela keyboard veya mouse) durum bilgisi alarak ve hatta durum bilgisini var sayarak yapilan işlemlerde söz konusu. normalde 100 ms de programin açıldığını var sayarsak bu süre içerisinde debug esnasında kullanımda olabilecek spesifik bir arabirimi özel bir duruma geçirip daha sonra ordan gelen veriyi kullanabiliriz.
örnek senaryo
init:
...
mov al,0adh ; Keyboard ı kitle
out 64h,al ;
add al,049h ; Keyboard bufferı resetle
out 60h,al ; Bu durumda artık port 64 bize 16 return edecek
...
daha sonra herhangi bir mekanizmanin icerisinden bu porttan gelen 16 sayisini kontrol etmeksizin kullanabiliriz , bu decryption rutininin çarpanlarından biri veya bir far jump olabilir. keyboard in kitli olmasi durumuda cabasi :)
initializasyon bittiğinde keyboard ı eski duruma getirmeyi de unutmamak gerek