Native C++ makine koduna derlenir ve derlenmiş kodun korunmuş kod olduğuna inanmak caziptir. Öyle değildir. Tek bir if ile biten bir lisans kontrolü, çalışan bir crack'e yalnızca tek bir koşullu atlama yaması uzaklıktadır. Yazılım kıranlar da kaynak kodunuzu nadiren okur: debugger bağlar, fonksiyonları hook'lar, ağ trafiğini izler ve bellekteki komutlara yama yaparlar. Lisanslı yazılımlarda C++ kimlik doğrulama, bunların hepsinin yaşandığını varsaymak zorundadır.
Bu rehberde bu varsayım üzerine kurulmuş bir lisanslama akışını adım adım anlatıyoruz: oturumun nasıl kurulduğunu, lisans kararının neden sunucuda verilmesi gerektiğini, bütünlük kontrollerinin neleri yakaladığını ve tüm bunları qPapel Auth ile bir C++ uygulamasına nasıl bağlayacağınızı. İlkeler, hangi lisanslama sistemini kullanırsanız kullanın geçerlidir.
C++ kimlik doğrulama nelere karşı savunma yapmalı?
İşe yarar her tasarım bir tehdit modeliyle başlar. Masaüstü yazılımlar için dürüst tehdit modeli ise açıktır: Makine saldırgana aittir. Elinde binary'niz, yönetici yetkileri, herkese açık tüm tersine mühendislik araçları ve istediği kadar zaman vardır. Bu model içinde beş tür saldırının başarısız olması gerekir.
| Saldırı | Tipik araçlar | Onu ne durdurmalı? |
|---|---|---|
| Statik analiz | IDA, Ghidra, Binary Ninja | Bulunmaya değer sır veya karar mantığının olmaması |
| Dinamik analiz | x64dbg, WinDbg | Debugger tespiti ve çalışma zamanı analizi |
| Trafiğin ele geçirilmesi | Fiddler, Wireshark, mitmproxy | Oturum başına anahtarlarla şifreli, imzalı trafik |
| Bellek manipülasyonu | Cheat Engine, ReClass | Bellek bütünlüğü kontrolleri ve anti-dumping |
| Binary yamalama | Hex editörler, yama script'leri | Sunucu tarafı kararlar ve kod bütünlüğü kontrolleri |
Hiçbir kontrol beşini birden kapsamaz. Ciddi C++ lisanslamasının bir zincir olarak kurulmasının nedeni budur: Bir halkayı aşmak, saldırganın elinde yine de çalışan bir ürün bırakmaz. Rehberin geri kalanı bu zinciri ilk paketten son bütünlük kontrolüne kadar izliyor.
Güvenli bir C++ lisanslama oturumu nasıl işler?
Korumalı bir oturumun beş aşaması vardır. Her aşama, bir öncekinin açık bıraktığı bir boşluğu kapatır ve sıra önemlidir: Sunucu kararını vermeden uygulamaya değerli hiçbir şey ulaşmaz.
01Anahtar değişimi
Yeni oturum anahtarları, hiçbiri binary'de saklanmaz
02İmzalı el sıkışma yanıtı
Sahte bir sunucu bunu üretemez
03Lisans anahtarı + HWID
Aktarım sırasında şifreli ve imzalı
04Lisans kararı
Süre sonu, yasaklar ve HWID burada kontrol edilir
05String ve dosya isteği
Yalnızca olumlu karardan sonra
06Sunucu tarafı veriler
Belleğe gönderilir, asla derlemede yer almaz
1. Anahtar değişimi
Uygulama başladığında istemci ve sunucu, bir anahtar değişimiyle yeni oturum anahtarları üzerinde anlaşır. Modern tasarımlar genellikle X25519 gibi geçici (ephemeral) eliptik eğri Diffie-Hellman kullanır; böylece anahtarlar çalışma zamanında türetilir ve hiçbir zaman binary'de saklanmaz. Çalıştırılabilir dosyanızın her baytını çıkaran bir saldırgan bile bu anahtarlara sahip olmaz. Kaydedilmiş bir oturum da daha sonra tekrar oynatılamaz, çünkü bir sonraki oturum farklı anahtarlar kullanır.
qPapel Auth her oturumu bir anahtar değişimiyle açar ve AES-256 oturum anahtarlarını her oturumda yeniler. Bu adım başarısız olursa SDK, Banned Computer ya da Unverified Build gibi hatalardan ayrı olarak özel bir Key Exchange veya Handshake Error bildirir; böylece başarısız bir el sıkışmayı bir lisans sorunundan ayırt edebilirsiniz.
2. Şifreli ve imzalı trafik
El sıkışmadan sonraki her istek ve yanıt şifrelenir ve imzalanır. Şifreleme, içeriği Fiddler veya mitmproxy gibi proxy'lerden gizler. İmza ise daha da önemlidir, çünkü istemcinin gerçek bir sunucu yanıtını sahtesinden ayırmasını sağlar. İmza olmadan saldırgan, her isteğe "lisans geçerli" diye cevap veren sahte bir sunucu kurabilir; bu da bilinen en eski crack yöntemlerinden biridir.
3. Sunucu tarafında lisans ve HWID kontrolü
İstemci, lisans anahtarını ve bir donanım parmak izini korumalı kanal üzerinden gönderir ve bekler. Lisansın geçerli olup olmadığını hiçbir zaman kendisi hesaplamaz. Sunucu; anahtarın var olduğunu, süresinin dolmadığını, yasaklanmadığını ve bu makinenin donanım kimliğine (HWID) bağlı olduğunu kontrol eder. Bu mantığın hiçbir parçası binary'de yer almadığı için yerelde "evet" dedirtmek üzere yama yapılabilecek bir şey de yoktur.
4. Sunucu tarafı string'ler ve dosyalar
Lisanslamayı gerçek bir korumaya dönüştüren adım budur. Olumlu karardan sonra sunucu, uygulamanın çalışmak için gerçekten ihtiyaç duyduğu şeyleri gönderir: yapılandırma değerleri, uç noktalar, offset'ler, sabitler ve dosyaların tamamı. qPapel Auth'ta bunlar sunucu tarafı string'ler ve sunucu tarafı dosyalar olarak adlandırılır; kimliği doğrulanmış oturuma aktarılır ve dağıttığınız derlemenin dışında tutulur. Lisans kontrolü yamayla devre dışı bırakılmış bir derleme bunları hiçbir zaman almaz.
5. Tek seferlik bir kontrol değil, süregelen bir oturum
Yalnızca açılışta yapılan bir kontrol, process bu kontrolü geçtikten sonra yama yapılarak aşılabilir. qPapel Auth her çalıştırmayı, sürekli yenilenen oturum anahtarlarıyla bir sunucu oturumuna bağlar. Uzaktan ayarlardaki Session Token Enforcement ile azami aktif oturum süresini belirleyebilir ve oturumları bir IP adresine kilitleyebilirsiniz. Panelde bir anahtarın süresini sonlandırdığınızda ya da onu yasakladığınızda uygulama yeni durumu bir sonraki kontrolde alır.
Lisans kararı neden sunucuda kalmalı?
C++ kimlik doğrulamadaki en önemli kural kısadır: İstemci raporlar, sunucu karar verir. Tamamen process'inizin içinde çalışan her kontrol bulunabilir ve değiştirilebilir. Klasik crack, bir koşullu atlamayı JE'den JMP'ye çevirir ya da bir çağrının üzerine NOP komutları yazar; uygulama da lisans geçerliymiş gibi çalışmaya devam eder.
Kararı sunucuya taşımak, bir yamanın elde edebileceği sonucu değiştirir. Saldırgan yerel if'inizi yine atlayabilir, ama bunu atlamak geçerli bir oturum yaratmaz; geçerli bir oturum olmadan da sunucu hiçbir şey göndermez. Aynı düşünce, binary'deki değerli diğer her şey için de geçerlidir.
| Varlık | Binary'de dağıtılırsa risk | Olması gereken yer |
|---|---|---|
| Lisans kararı | Her zaman başarılı olacak şekilde yamalanır | İmzalı kanal üzerinden sunucu kararı |
| Doğrulama algoritması | Bir anahtar üreticiye (keygen) kopyalanır | Yalnızca sunucuda |
| API anahtarları ve token'lar | Basit bir string taramasıyla çıkarılır | Kendi backend'iniz ya da sunucu tarafı bir string |
| Yapılandırma, offset'ler, sabitler | Davranışı değiştirmek için düzenlenir | Girişten sonra sunucu tarafı string'ler |
| Premium modüller ve DLL'ler | Lisanssız olarak kopyalanıp yeniden kullanılır | Sunucu tarafı dosyalar ya da bellekte yükleme |
Native kodun son satır için bir seçeneği daha var. qPapel Auth, korumalı bir modülü diskte dağıtmak yerine şifreli DLL'leri diske yazmadan belleğe aktarabilir; Map Files özelliği de dosyalarınızı bir PE yükleyicisine benzer şekilde belleğe eşler. DLL'leri bellekte yükleyerek koruma yazısı bunun nasıl çalıştığını ve ne zaman zahmetine değdiğini anlatıyor.
Bütünlük kontrolleri: yamalı kodu ve belleği yakalamak
Sunucu tarafı kararlar yamaları daha az işe yarar hâle getirir. Bütünlük kontrolleri ise onları görünür kılar. Çalışan bir C++ process'inde iki tür kurcalama önemlidir.
- Kodun kendisindeki değişiklikler. Saldırgan, bir kontrolü atlamak ya da bir sonucu değiştirmek için çalıştırılabilir dosyadaki ya da dosya yüklendikten sonra kod bölümündeki komutları düzenler.
- Çalışma zamanında bellekteki değişiklikler. Bir debugger ya da bellek düzenleyici, canlı process'e yazarak bir komuta ya da değere tam gerektiği anda yama yapar.
qPapel Auth ikisini de kendi kodunuza yerleştirdiğiniz çağrılar olarak sunar. auth.CheckTextIntegrity() CRC kontrolleri, oturum tabanlı kontroller ve JMP ile NOP yamalarına yönelik kontroller yapar. auth.CheckMemoryIntegrity(), JMP ve NOP değişiklikleri gibi komut yamaları dahil, programın belleğinin çalışma zamanında değiştirilip değiştirilmediğini kontrol eder. Bunların üzerine Uzaktan ayarlarda açılıp kapatılabilen Integrity Check ve CRC32 Check korumaları bulunur; Build kontrolü de dosyanızın yetkisiz araçlarla değiştirilmesini, yamalanmasını ya da açılmasını engeller.
// Illustrative: where qPapel Auth integrity checks fit in a C++ app.
// CheckTextIntegrity and CheckMemoryIntegrity are real SDK names.
// StartLicensedSession, RunMainLoop and ExportProject are your own code.
int main()
{
if (!StartLicensedSession()) // key exchange, license and HWID check
return 1; // fail closed: no session, no app
auth.CheckTextIntegrity(); // CRC, session and JMP/NOP checks
auth.CheckMemoryIntegrity(); // runtime memory modification
RunMainLoop();
}
void OnExportClicked()
{
auth.CheckMemoryIntegrity(); // check again before valuable work
ExportProject();
}qPapel Auth bir C++ uygulamasına nasıl entegre edilir?
Entegrasyon, hassas herhangi bir kod çalışmadan önce, uygulamanın açılış akışında yer alır. Adımlar sırasıyla aşağıda; ilk entegrasyonlarda en sık hata yapılan noktaları da belirttik.
- 01
Güncel SDK dosyalarını alın
En güncel Lib ve Include dosyalarını resmi Example projesinden,
qPapelAuth64.dlldosyasını da PapelShip panelinizdeki İndirmeler sayfasından alın. Güvenlik ve şifreleme katmanları değiştiğinde eski kütüphaneler çalışmayı bırakır; bu yüzden her zaman güncel sürümle derleyin. - 02
Default Library ile EasyAuth arasında seçim yapın
Default Library hâlâ tam olarak destekleniyor. EasyAuth ise C++'ın yanında C# desteği, daha iyi hata yönetimi ve güvenlik politikası tanılamaları sunan yeni kütüphanedir. PapelShip, EasyAuth olgunlaştıkça projelerin kademeli olarak ona taşınmasını öneriyor.
- 03
Değerli hiçbir şey çalışmadan kimlik doğrulayın
Oturumu, ana pencereniz açılmadan ya da yapılandırmanız yüklenmeden önce,
mainfonksiyonunun en başında başlatın. Korunmaya değer hiçbir şey, kimliği doğrulanmamış bir oturumda çalışmamalıdır. - 04
İhtiyacınız olanı sunucudan yükleyin
Yapılandırmayı, uç noktaları ve hassas sabitleri sunucu tarafı string'lere, premium varlıkları da sunucu tarafı dosyalara taşıyın. Bunları girişten sonra okuyun ve yalnızca ihtiyaç duyduğunuz süre kadar bellekte tutun.
- 05
Bütünlük kontrollerini ekleyin, korumaları açın
auth.CheckTextIntegrity()veauth.CheckMemoryIntegrity()çağrılarını açılışa ve değerli işlemlerin öncesine yerleştirin; ardından Uzaktan ayarlarda Anti-VM'i, debugger tespit edildiğinde yasaklamayı, oturum sistemini ve HWID kilidini etkinleştirin. - 06
Hata durumunda kapanın
Sunucuya ulaşılamaması, hatalı bir yanıt ya da başarısız bir kontrol, uygulamanın kapanması demektir. Ürünün tamamını çalıştıran bir çevrimdışı yedek mod bir arka kapıdır; çevrimdışı kullanımı desteklemeniz gerekiyorsa süre ve kapsam açısından sıkı biçimde sınırlayın.
EasyAuth, bir oturumun neden sona erdiğini de kullanıcıya bildirir. Bir güvenlik politikası uygulamayı kapattığında “Security Policy Closing..” mesajını, nedene dair ek bilgilerle birlikte gösterir. Bu da yanlışlıkla bir kurala takılan gerçek müşterilerle destek görüşmelerini kısa tutar. Ürün ayrıntıları ve planlar qPapel Auth sayfasında.
Native kod için anti-debug, anti-VM ve çalışma zamanı tespiti
Lisanslama, yazılımınızı kimin çalıştırabileceğine karar verir. Çalışma zamanı koruması ise çalıştığı ortama güvenilip güvenilemeyeceğine. Native koda karşı kullanılan başlıca araç debugger'lardır; onları bellek düzenleyiciler ve sanal makineler izler. Sanal makineler, saldırganın bir oturumun anlık görüntüsünü alıp onu istediği kadar geri sarmasına olanak tanır.
qPapel Auth'un Uzaktan ayarları; pencere başlıklarını, sınıf adlarını, process'leri ve debug araçlarını engellemenizi, sanal makineleri tespit etmenizi ve bir debugger bağlandığında lisansı yasaklamanızı sağlar; hem de yeni bir derleme almadan. Anti-dumping rutinleri, bellek koruması ve kurcalamaya karşı sağlamlaştırma ise bu ayarlardan bağımsız olarak binary'yi korur. Politika uzaktan iletildiği için yeni bir araç ortaya çıktığında korumayı yeniden derlemeden güncelleyebilirsiniz.
Kara listeler yalnızca zaten bildiğiniz araçları yakalar. Adı değiştirilmiş ya da yeniden derlenmiş bir debugger, process adlarından oluşan bir listeden kolayca geçer. Bu yüzden qPAnalyzer bunun yerine arayüz yerleşim kalıplarına, pencere handle'larına ve bellek imzalarına bakar; işaretlenen pencerenin ekran görüntüsünü alır ve eşiklerini sizin belirlediğiniz uyarı, kısıtlama, kapatma ve yasaklama aşamalarına sahip bir risk puanına katkıda bulunur. Statik kara listelerin ötesinde tersine mühendislik koruması yazısı bu yaklaşımı ayrıntılı olarak anlatıyor.
Lisans ve HWID
Kim, hangi bilgisayarda çalıştırabilir?
Korumalı oturum
Anahtar değişimi, şifreli ve imzalı trafik
Sunucu tarafı veriler
String'ler ve dosyalar yalnızca girişten sonra
Bütünlük kontrolleri
Yamalı kod ve bellek tespit edilir
Çalışma zamanı tespiti
Kara listeler, anti-VM ve qPAnalyzer
C++ lisans kontrollerinde sık yapılan hatalar
Kırılan C++ ürünlerinin çoğu zekice bir yöntemle kırılmadı. Bir avuç tasarım kestirmesinden biri yüzünden kırıldı.
- Her şeyi tek bir boolean koruyor. Tek bir
isLicensedbayrağı, saldırganın ilk aradığı şeydir. Özellikleri bir bayrağa değil, sunucu verisine bağlayın. - String literal'lerde sırlar. Binary'deki API anahtarları, şifreleme anahtarları ve indirme URL'leri, string taraması yapan herkes tarafından görülebilir. Bunları karartmak yalnızca bellekte çözüldükleri anı erteler.
- Yerel saate güvenmek. Sistem saatine göre hesaplanan süre sonu, tarihi değiştirerek aşılabilir. Bir lisansın süresinin dolup dolmadığına sunucu karar versin.
- Yalnızca açılışta bir kez kontrol etmek. Açılıştan sonra bağlanmak ve oturumun ortasında yama yapmak tek seferlik kontrolleri etkisiz bırakır. Oturumu canlı tutun ve değerli işlerden önce yeniden kontrol edin.
- Cömert çevrimdışı yedek modlar. Sunucuya ulaşılamadığında uygulama tam olarak çalışıyorsa sunucuyu engellemek, crack'in ta kendisidir.
- Eskimiş SDK'lar. Eski kütüphaneler protokol ve koruma güncellemelerini kaçırır. SDK değiştiğinde aylar sonra değil, hemen yeniden derleyin.
Aynı hatalar yönetilen (managed) kodda da görülür, ama orada fazladan bir sorun vardır: .NET assembly'leri okunabilir kaynak koda geri decompile edilebilir. Bu tarafı koda gömülü sırlar olmadan C# lisanslama yazısında ele alıyoruz.
Sıkça sorulan sorular
Kırıldığında bile güvenli biçimde başarısız olan C++ yazılımları geliştirin
Güvenli C++ kimlik doğrulama, tek bir zekice kontrol değildir. Korumalı bir oturum, sunucuda verilen bir karar, ancak bu karardan sonra gelen veriler, yamaları fark eden bütünlük kontrolleri ve bunların arkasındaki araçları fark eden çalışma zamanı tespitidir. Her katman tek başına sıradandır. Birlikte ise herhangi birini aşmanın saldırganın elinde çalışmayan bir derleme bırakması anlamına gelir.
Sunucu tarafı karar ve sunucu tarafı verilerle başlayın, çünkü yazılım kırmanın ekonomisini en çok onlar değiştirir. Ardından bütünlük kontrollerini ve çalışma zamanı tespitini ekleyin; SDK'yı da güncel tutun ki hiçbir şeyi yeniden yazmadan koruma gelişmeye devam etsin.
qPapel Security Team
Lisanslama ve yazılım koruması