BadUSB nedir? Ne yapar? Tehlikesi nedir?

Uzun zamandır fırsat bulup yazamadığım bloğuma baktığım zaman benden epey geride kaldığını gördüm. Ufak da olsa birşeyler yazmak isteğine bugün artık karşı koyamadım 🙂
Bu yazıda BadUSB ‘den ve alınabilecek önlemlerden bahsedeceğim. Daha çok son kullanıcıdaki farkındalığı artırmak amaçlı bir yazı olacağından çok fazla teknik detaya girmeden herkesin anlayabileceği seviyede tutmaya çalışacağım. Bir sonraki yazımda muhtemelen kendi BadUSB mizi yapacağız. Bu sefer proof of consept (POC) tadında, mümkün olduğunca teknik,  meraklısına özel bir yazı olacak. Takipte kalın 🙂

Giriş

Günlük hayatımızda bize çok zararsız görünen USB bellekleri çıktı almak için, veri paylaşmak için vs  sıkça kullanıyoruz. Bazen bir zararlı yazılımla enfekte olmuş bilgisayar USB belleğimizin içeriğini gizliyor (birçoğumuz sildiğini sanıyoruz). Bu durum can sıkıcı olsa da çoğu zaman önemsemiyoruz. Başkalarından aldığımız, yolda bulduğumuz USB bellekleri bilgisayarımıza takıp dosya kopyalıyor, kopyaladığımız dosyaları açmadığımız sürece içinde zararlı yazılım olsa dahi birşey olmaz güvendeyiz diye düşünüyoruz. USB belleği tarayan anti-malware yazılımları nasıl olsa yakalar diye düşünebiliyoruz.
Bilgisayarınıza bir başkasının hakimiyetinde olan bir klavyeyi bağlar mıydınız?
Peki ya size o taktığınız USB belleğin aslında bir klavye olabileceğini söylesem?
Aklınızda iki soru belirmiş olmalı:
1-Nasıl yani? bildiğimiz flash bellek? Klavye olması mümkün mü? (olsa görürdüm tuşu hani nerede 🙂 )
2- Diyelim mümküm ne olacak ki?
USB arayüzüyle bağladığımız (fan led vs gibi sadece güç için bağlananlar masumlar  hariç) cihazlar  bilgisayarınıza kim olduğunu ne iş yaptığını ve nasıl çalıştığını bilgisayarınıza bildirmek durumundadırlar. USB bellek örneği üzerinden gidersek bilgisayarınıza bellek olduğunu , depolama işi yaptığını ve çalışma şeklini anlatır. Böylece siz de cihazınızı bu bilgiler ışığında bilgisayarınızın size sunduğu imkanlarla (cihaz driverı aracılığıyla) sorunsuz kullanırsınız. Bu işi yapan kısıma firmware (donanım yazılımı,bellenim) denir. Diğer bir ifadeyle firmware, “sayısal veri işleme yeteneği bulunan her tür donanımın kendisinden beklenen işlevleri yerine getirebilmesi için kullandığı yazılımlara verilen addır.” (wikipedia) . Bu yazılım cihaza gömülü olarak (halihazırda yüklü)  gelir. Bu durum USB bellekler ve klavyeler içinde dolayısıyla geçerlidir. İşte tam burada şöyle bir soru aklımıza gelmeli: Peki bu firmware in doğru söylediğini, örneğin bir USB belleğin bilgisayarımıza kendini USB bellek gibi mi yoksa başka bir cihaz (mesela klavye) gibi  mi tanıttığını kim kontrol ediyor? Bildiğim kadarıyla bunu kontrol eden bir mekanizma (en azından standart bir işletim sistemi parçası olarak ) mevcut değil. O zaman donanım yazılımı (firmware) değiştirilmiş bir cihaz bilgisayarımıza yalan söyleyerek kendisini başka bir cihaz olarak tanıtabilir ve hatta hiç beklemediğimiz şeyler yapabilir. USB bellek olarak gördüğünüz bir cihaz klavye olarak hareket edip bilgisayarınızda sanki siz birşeyler  yazıyormuşsunuz gibi davranabilir, kod çalıştırabilir. Normalde gerçekten USB bellek olarak kullanıldığını bildiğiniz (örneğin kingston, toshiba, sandisk vs bellekleri) cihazların bunu yapabilmesi için donanım yazılımının (firmware) özellikle değiştirilmiş ve klavye gibi davranmaya ayarlanmış olması gerekir. Teoride ilk sorumuzun cevabının olumlu olduğuna  gelmeye çalıştığımı anlamışsınızdır. Pratikte ise bunun mümkün olduğu  2014’te Karsten NOHL ve Jakob LELL adındaki iki araştırmacı tarafından Black Hat konferansında dünyaya duyuruldu ve kanıtladı. Bu tarih öncesinde bu durumun istihbarat teşkilatları tarafından bilinip kullanıldığı tartışmaları konumuz olmadığı için girmiyorum.

Peki BadUSB nedir?
BadUSB için görüntüsünün oluşturduğu beklentiden farklı şekilde çalışması için donanım yazılımı (firmware) özellikle değiştirileren veya doğrudan bu şekilde kodlanan USB cihazlardır diyebiliriz.
BadUSB için, görüntüdeki cihaz türünü USB bellekle sınırlamak doğru olmadığı gibi yaptığı işi klavye gibi davranmak olarak belirtmek de doğru olmaz. Bilgisayarınıza bağladığınızda sizden gizli klavye gibi çalışan ama sizi USB bellek görüntüsüyle aldatan bir cihaz, BadUSB’ ye güzel bir örnek olabilir (tanım değil). Piyasada bu işi yapan cihazlar USB Rubber duck olarak satılmakta. Takılan bilgisayarda istediğiniz işlemleri (veri çalmak,zaralı yazılım yüklemek vs vs işleri) yapabilecek scriptleri (kod parçalarını)
yazmanıza imkan tanıyan programlar internette bulunmakta.

USB Rubber Duck

Bu noktada BadUSB nin ne yapabileceğine dair bir örneği de vermiş olduk aslında: kod çalıştırmak.
Aşağıdaki videoda kendi oluşturduğum bir BadUSB’nin içine yerleştirdiğim firmware sayesinde klavye gibi davranarak internetteki bir sunucudan takıldığı bilgisayara zararlı yazılım indirdiğini ve çalıştırdığını görebilirsiniz. İşlem tamamlandığında bilgisayar saldırganın (ki bu örnekte ben oluyorum) kontrolüne geçmekte.

Dipnot: burada cihaz tarafından yapılan işlemin görülmesi, görülmeye ayarlanması ile ilgili. Gerçekte siz hiç birşeyin farkına varmadan da bu işlemler yapılabilirdi.

P_20160303_032041

Yazdığı kodlar (yaklaşık olarak) (Klavye yerleşimini değiştirdiğim için payload bozuk biraz)

Bu tehlikeli ve kötücül cihazlar nereden gelebilir?
Bu tür cihazlar (BadUSB) hedef noktaya yakın yerlere atılmak suretiyle bilinsiz kişilerce hedefe takılması amaçlanabilir. (bakınız önlem 3)
Aslında cevap her yerden olmalı çünkü; elinizdeki normal bir USB cihazı taktığınızda bir bilgisayarın (vs) bu işlemleri otomatik gerçekleştirip siz farketmeden cihazınızı aleyhinize çalışacak bir silah haline getirmesi mümkün(bakınız önlem 2 ve 4 ve 5)

Sonuç

Bu yazıda bir USB cihazın görüntüsünün sizi aldatabileceğini, farketmeden hoşlanmayacağınız şeyler yapabileceğini anlatmaya, farkına vardırmaya çalıştım.

Önlemler

Hitap etmeye çalıştığım kitle açısından yazının en önemli kısmına gelirsek:

1-Gerektiğinde kendinize ait USB cihazları kullanmalısınız.

2-USB cihazlarnızı güvenmediğiniz yerlere takmamalısınız.
3-Yalnızca güvenilen cihazları bilgisayarınıza bağlamalısınız. Yolda sağda solda bulduğunuz cihazları bağlamamalısınız.
4-Her USB cihaza güvenmemeli, güvendikleriniz de dahil olmak üzere takmadan önce önlem almalısınız.
5-Cihazların özellikle donanım yazılımında ve depolama içeriğinde zararlı yazılım taraması yaptırmalısınız.

6-Firmware güncellemelerinde kod imzalaması (code signing) kullanmalısınız.

7-Firmware güncellemelerini engelleyebilirsiniz.

8-Kullandığınız bilgisayarın (vs) kritiklik derecesine, sakladığı bilgilerin önemine göre USB portlarını tamamen kullanılamaz hale getirmeyi değerlendirebilirsiniz.

9-USB cihazı takıldığında doğrudan sanal bir bilgisayara bağlanacak şekilde ayarlayıp oradan kullanmayı düşünebilirsiniz.

Kötücül bir cihazın büyük ihtimalle bir klavye gibi davranacağını düşünürsek yukarıdakilere ek olarak :

  • (şüpheli) USB cihazı kullanmadan önce bilgisayarınızın ekranını kilitleyip cihazı takmak ve bir süre bekledikten sonra (ne kadar uzun o kadar iyi) kilidi açıp kullanmak,
  • (şüpheli) USB cihazı takmadan önce klavye düzeninizi (keyboard layout) normalde kullandığınız dilden ve ingilizceden başka alakasız bir dile değiştirmek
  • İnternetten yazılım indirmesi olasılığına karşı (şüpheli) cihazı kullanmadan önce interneti kesmek ve cihazı çıkarana kadar bağlamamak

önlemlerinin de faydalı olabileceğini düşünüyorum.

Umarım faydalı bir yazı olmuştur. Olumlu – olumsuz eleştirilerinizi yorum olarak yazmaktan çekinmeyin.

 

 

8086 mimarisi ve assembly dili ile bellekteki karakter dizisinin uzunluğunu bulma

Belleğin 0x1300 adresinden başlayan bir karakter dizisi olsun. Dizinin bittiğini sonundaki  00 değerleri belirtiyor olsun. Biz de bu bilgiden yaralanarak dizinin uzunluğunu bulalım ve bunu belleğe kaydedelim.

—————

org 1000

;heksadecimal 42h sayısı B harfini ifade eder. 43h C harfini ve bu şekilde devam etmektedir. örneğin: 4243h BC olarak düşünülebilir.

;Aşağıdaki komutlarla belleğe bir karakter dizisi yazdırdık.

mov cx,4243h                 ;
mov [0x1300],cx             ;

mov cx,4445h                 ;
mov [0x1302],cx             ;

mov cx,4647h                 ;
mov [0x1304],cx             ;

mov cx,4849h                 ;
mov [0x1306],cx             ;

Mov [0x1308], 0x00h     ; string sonu belleğe kopyalandı

;Uzunluğu bulma
mov bx, 0000h       ; karakter dizisinin uzunluğunu tutacağımız bx ‘i sıfırladık.

mov si, 0x1300       ;bellek adreslerini si ‘da tutacağız.

dongu:                    ; buraya dongu adlı etiket(label) kondu

mov dh, [si]    ;si ‘ın gösterdiği adresteki 2 karakter dh içerisine taşındı.

inc si               ;si ‘ın tuttuğu bellek adresi 1 artırıldı

inc bx              ;bx 1 artırıldı.

cmp dh,00h     ;dh içerisindeki karakterler ile 00 (hekzadesimal) karşılaştırıldı

jnz dongu         ;eğer bir önceki komutta eşleşme olmazsa dongunun başına, olursa aşağı geçilecek

dec bx              ;bx ‘teki 1 fazla değer atıldı.

mov [0x1002],bx   ;bx te tutulan dizi uzunluğu 0x1002 adresine kopyalandı

hlt   ;program sonlandırıldı

——————–

Aşağıdaki resimde örnek bir çalışma anını görebilirsiniz.

assembly123

8086 mimarisi ve assembly dili ile toplama, çarpma, bölme,çıkarma

Hafızada(memory) iki adet sayı olsun. hekzadesimal 6553h sayısı  0x00B00 adresinde, hekzadesimal 1287h sayısı 0x00B02 adresinde bulunuyor olsun. Bu iki sayının toplamını,farkını,çarpımını,bölümünü 0x00B10 adresinden başlayarak belleğe sırası ile yazalım.

—————————

org 1000

;Not: kodlar intel syntaxına uygun olarak yazılmıştır.

;sayıları bellek alanlarından yazmaçlara (register) kopyalayalım.

MOV ax, [0x00B00]                 ; 6553h sayısını ax yazmacına kopyaladık.

MOV bx, [0x00B02]                ; 1287h sayısını bx yazmacına kopyaladık.

;TOPLAMA

ADD ax,bx                              ; bu komutla iki sayı toplandı ve ax yazmacına yerleştirildi.

MOV [0x00B10], ax               ;  toplamı ax yazmacından belirtilen bellek adresine kopyaladık.

MOV ax, [0x00B00]               ; 6553h sayısını ax yazmacına tekrar kopyaladık , çünkü biraz önce toplam yazılmıştı. (bx’teki sayı ;değişmedi)

;ÇIKARMA

SUB ax, bx                            ;  bu komutla 6553h sayısından 1287h sayısı çıkarıldı ve ax yazmacına kopyalandı.

MOV [0x00B12], ax              ; farkı ax yazmacından belirtilen bellek adresine kopyaladık.

;ÇARPMA

;Çarpma komutu olan MUL tek operand alır. Diğer operand MUL komutunun aldığı operandın (bit olarak) boyutuna göre ah ;ya da ax ten otomatik olarak alınır (konumuz olmayan sonraki işlemcilerde eax ten de alınabilir.).

;İşlem sonucu eğer 8 bit ise ax yazmacına, 16 bit ise yüksek anlamlı kısmı dx ‘e düşük anlamlı kısmı ax ‘e olmak üzere dx:ax ‘e kaydedilir.

MOV ax, [0x00B00]       ; 6553h sayısını ax yazmacına tekrar kopyaladık , çünkü biraz önce fark yazılmıştı.

;bx yazmacında halen 1287h sayısı var ancak örneğin açıklığı açısından yeniden kopyalayalım.

MOV bx, [0x00B02]      ; 1287h sayısını bx yazmacına kopyaladık.

;MUL komutu aldığı operandın 16 bit veya 8 bit oluşuna göre değişik davranış gösterir

MUL bx                          ; bu komut bx’ teki sayı ile ax’ ten aldığı sayıyı çarptı ve dx:ax’ e yazdı. bx 16 bit olduğu için ax’ in ;doğrudan alındığına dikkat edin.Eğer bx yerine bl (veya 8 bitlik başka birşey) yazsaydık sonuç sadece ax’e kaydedilecekti.

;burada kullandığımız MUL işaretsiz çarpma yapar. İşaretli için IMUL kullanılmalıdır.

;sonuç olan 32 bitlik 075544C5h sayısı dx:ax ‘e kaydedildi.

MOV [0x00B14] , dx      ; sonucun 16 bitini belirtilen bellek adresine kopyaladık.

MOV [0x00B16] , ax      ; sonucun diğer 16 bitini belirtilen bellek adresine kopyaladık.

;BÖLME

; Bölme komutu olan DIV tek operand alır, bu bölendir. Diğer operand 8 bitlik bölmede ax’ten 16 bitlik bölmede dx:ax’ ten

;otomatik olarak alınır. Yani bölünenin uzunluğunu DIV komutunun aldığı operand olan bölen belirler.

; 8 bitlik bölmede al bölüm, ah kalan ;16 bitlik bölmede ax bölüm dx kalanı tutar.

MOV ax, [0x00B00]    ; 6553h sayısını ax yazmacına tekrar kopyaladık.

MOV bx, [0x00B02]    ; 1287h sayısını bx yazmacına kopyaladık (bx te zaten bu değer vardı, örneğin açıklığı açısından yeniden ;kopyaladık)

;BÖLME

;DIV komutu aldığı operandın 16 bit veya 8 bit oluşuna göre değişik davranış gösterir.

DIV bx                         ; bx yazmacındaki değer bölen olarak alındı ve ax’ teki  değeri böldü. Bölüm (05h) ax’ e  , kalan ;(08b0h) dx’ e kaydedildi. Eğer bx yerine 8 bit bir operand verseydik bu sefer bölüm al’ye kalan ah’a kaydedilecekti.

;burada kullandığımız DIV işaretsiz bölme yapar. İşaretli için IDIV kullanılmalıdır.

MOV [0x00B18] , ax   ; sonucu belirtilen bellek adresine kopyaladık.

hlt                                ;programı sonlandırdık

——————

Format makinesi ayağınıza geldi. (Programsız Windows kurulum USB ‘si hazırlama)

  • Giriş

Aslında bu yazı biraz konu dışı olacak. Ancak hepimizin bildiği bir gerçek(!) var: bilgisayar mühendisi format atar! . Şaka bir yana herkesin ucundan da olsa teknolojiyle iç içe olduğu bu zamanda birçoğumuzun en azından nasıl yapıldığını bilmesi gereken bazı şeyler var. Format atmak da bunlardan biri. Ne yazıkki bilgisayar mühendisliği okuyan arkadaşlarımdan bile  bu taleple gelenler olunca bu yazıyı yazıp bloğumda var diyebilmek şart oldu. (yanlış anlaşılmasın sizi seviyorum sayın arkadaşlar 🙂 ancak bazı şeyleri öğrenmelisiniz, böyle bir şeyi sürekli yapmak angarya haline dönüşüp can sıkıcı olabiliyor.).

  •  Kurulum Ortamı Hazırlama

harddiskinizdeki verileri yedeklemenizi şiddetle öneririm. Aksi halde sorumluluk kabul etmem 🙂

Bu yazı temiz kurulum yapacaklar içindir. Bilgisayarınızla bir windows yüklü geldiyse kurtarmanın nasıl yapılacağını araştırın. Temiz kurulum ürün anahtarınızı silip sizi cracklere ya da yeni windows almaya mahkum edebilir.

Hangi windows sürümü kullanmanız gerektiği konusunda şuraya https://support.microsoft.com/tr-tr/kb/827218 başvurabilirsiniz. Destekleniyorsa 64 bit kullanın.

kurulum için 2 seçeneğiniz var a) dvd ile kurulum b) USB ile kurulum

a) ilk seçenek için bir şekilde elde ettiğiniz .iso uzantılı windows dosyasını -ki bu aslında bir disk kalıbı- itina ile DVD’ye yazıyorsunuz. Nasıl yapıldığına şuradan bakabilirsiniz. Ardından doğrudan kuruluma geçebilirsiniz. DVD ile kurulum hem zahmetsiz hem de yeniden kullanılabilir olacaktır.

b) Bir adet minimum 8 gb’lık flash bellek bulunur. İçinde önemli veri varsa yedeklenir.

XP üzeri bir işletim sistemine ihtiyacınız var. Zira tüm sürümlerde işlemlerin birçoğunu yapabilseniz de USB belleği NTFS olarak biçimlendiremezsiniz.

adım1) windows (alt tuşunun solundaki) ve R tuşlarına birlikte basıyorsunuz ve gelen ekrandaki alana cmd yazıp enter a basıyorsunuz.

cmd

adım2) gelen komut satırı penceresinde diskpart yazıyorsunuz ve enter a basıyorsunuz. Yeni bir komut satırı penceresi açılıyor. Artık işimiz onunla.

adım3) Yeni pencerede list disk yazıyorsunuz. Bilgisayarınızın diskleri listelenecek. Buradan boyutlara bakarak usb belleğin hangisi olduğunu bulmalısınız. Bende 60 gb lık bir harddisk ve altında da usb belleğim var.yani benim usb belleğim disk 1. Burada dikkatli olup doğru numarayı bulmalısınız yoksa veri kaybı yaşarsınız sorumluluk kabul etmem 🙂

list disk

adım4) doğru diski seçtikten sonra

select disk  X

komutunu vereceksiniz. Burada X bir önceki adımda belirlediğiniz disk numaranız. Benimki 1 olduğu için 1 yazdım. Aman siz doğrusunu yazın.

adım5) clean komutunu verin.

select clean

adım6) create partition primary komutunu verin.

ardından select partition 1 komutunu verin. Burada herkes 1 yazacak 🙂

sonra sırasıyla active ve assign komutlarını verin.

eğer buraya kadar bir hata almadıysanız işimiz bitti sayılır.

active assign

adım7)Açtığımız komut satırı pencerelerini (siyah pencereler) kapatın. Sizden diski biçimlendirmenizi isteyen pencere gelecektir. diski biçimlendire tıklayın. Yeni açılan pencerede dosya sistemi olarak NTFS seçip başlata tıklayın (gelene tamam diyin)

biçimle

biçimlendirme tamamlandığında artık belleğe windows dosyalarını atmak kalıyor. .iso uzantılı dosyadan dosyaları atmak için windows 8 / 8.1 / 10 kullanıyorsanız çift tıklamanız ve açılan penceredekileri belleğe kopyalamanız yeterli. Windows7 kullaıyorsanız Daemon tools isimli aracı kurup onunla açabilir ve kopyalayabilirsiniz. Kullanım için şu linkten http://hakanbudakk.blogspot.com.tr/2012/02/daemon-tools-kurulum-kullanm-resimli.html veya bu linkten http://video.tamindir.com/daemon-tools-ile-iso-dosyasi-nasil-acilir/ yararlanabilirsiniz. Olmadı Google dostunuz.

Usb biraz zahmetli görünüyor olabilir ancak bir kez bu işlemi uyguladıktan sonra windows kurulum dosyalarını usb bellekten silebilir lazım olduğunda dosyaları yeniden belleğe atıp üsttekileri tekrar yapmadan kullanabilir, kurulum yapabilirsiniz.

Üzgünüm kurulumu anlatmayacağım. Birçok kaynak internette mevcut.

Ornek olarak buraya bakabilirsiniz.

http://windows.microsoft.com/tr-tr/windows-8/clean-install

Kurulum yapacağınız yerden bilgisayarı başlatmak için biosunuzu kurcalamanız ve başlatmada (boot) ilk sıraya dvd  usb koymanız lazım. Malesef standart bir yolu yok. Bios için buralardan yardım alabilirsiniz:

http://www.enpedi.com/2010/02/bios-onyukleme-boot-onceligini.html

http://wiki.ubuntu-tr.net/index.php?title=Bilgisayar%C4%B1_CD/DVD_ya_da_USB_bellekten_ba%C5%9Flatmak

Kurulumda (boyutuna bakarak) doğru disk alanını da  seçerseniz sizden alası yok (yanlışı seçerseniz diskiniz silinir).

Kolay gelsin.

Kubuntu – Ubuntu üzerinde DNSCrypt kullanımı

  • DNS trafiğini şifrelemenin avantajlarından birkaçı

Normal şartlarda DNS trafiği şifrelenmez ve açık metin şeklinde akar. Dolayısıyla resimde göreceğiniz gibi ağı dinleyen bir kişi nereyegidiyorum.com için bir sorgu yapıldığını görecektir.

nereyegidiyorumwireshark

İnternet bulutunda hangi sunuculara ulaştığınız bilgisini kolayca ortaya çıkarabilecektir. Sunucular ile aranızdaki trafiğin http ya da https kullanılarak akması bu durumu değiştirmiyor. Dolayısıyla (https kullanırken) internette ne yaptığınız üçüncü bir gözden (trafiği dinleyenler, aradaki kişiler adamlar, kadınlar, atlardan) gizlense de nerede yaptığınız DNS sorgularınız aracılığıyla açıkça anlaşılabilir. Belirtmekte fayda var ki sadece bir web sitesini ziyaret ederken değil; mail gönderirken, anlık mesajlaşma uygulamalarını kullanırken (vs.) de DNS sorguları kullanılır. Bu noktada DNS trafiğini şifrelemek gizlilik açısından mantıklı olur. DNS bazlı kısıtlamalardan kurtulmak için de trafiği şifrelemek faydalıdır.

  • DNS Trafiği Nasıl Şifrelenir?

Bu iş için DNSCrypt istemcisi olan DNSCrypt-proxy kuracağız ve kullanacağız. DNSCrypt-proxy kurmadan önce kodunu derlemek için gereken tek bağımlılık olan libsodium kütüphanesini kuracağız.

  • libsodium Kurulumu

https://download.libsodium.org/libsodium/releases/ adresinden son sürümü (LATEST.tar.gz) indiriyoruz ve arşivden çıkarıyoruz. Çıkarılan dizine geçtikten sonra ilk olarak sırasıyla

./configure

make && make check

komutlarını veriyoruz. Hata almazsak şuna benzer bir çıktı göreceğiz.

makecheck

sudo make install

komutunu çalıştırıyoruz ve kurulum tamamlanıyor. Eğer kütüphanenin önceden derlenmiş halini kullanmayıp (bizim yaptığımız gibi) kaynak koddan derleyerek bir kütüphane kurarsanız;

ldconfig

komutunu çalıştırmanız gerekmekte.

  • DNSCrypt-proxy kurulumu

Eğer şanslıysanız depolarda dnscypt-proxy’yi bulabilirsiniz ve

sudo apt-get install dnscrypt-proxy

komutuyla kurulumu yapıp bu kısmı atlayabilirsiniz. Aksi takdirde aşağıdan devam edin.

http://download.dnscrypt.org/dnscrypt-proxy/ adresinden son sürümü (LATEST.tar.gz) indirip arşivden çıkarıyoruz. Çıkardığımız dizinde sırasıyla;

./configure

make

sudo make install

komutlarıyla kurulumu yapıyoruz.

  • DNSCrypt-proxy Kullanımı

sudo dnscrypt-proxy –resolver-name=<çözümleyici-ismi>

komutuyla yerel sunucumuzu başlatıyoruz. Varsayılan olarak sunucu 127.0.0.1 adresinde 53 numaralı port üzerinde dinlemede olacaktır.

Örneğin;

sudo dnscrypt-proxy –resolver-name=dnscrypt.org-fr –daemonize

komutuyla varsayılan adreste, dnscrypt.org sunucusunu kullanmak üzere, (–daemonize ile) arka planda  çalıştırdık.

Ağ arayüzümüzü dnscrypt-proxy adresi olarak ayarlamamız gerekiyor (varsayılan 127.0.0.1:53). Ardından network hizmetini yeiden başlatmalıyız.

Temel kullanımı bu şekilde belirttikten sonra birkaç noktaya değinmekte fayda var.

Dinleme adresinin 127.0.0.1 yerine 127.0.0.2 gibi aynı bloktaki başka bir adreste dinlemek üzere ayarlanmasın çakışma olmaması açısından faydalı olacağını düşünüyorum.

Eğer ortamda bir güvenlik duvarı (firewall) varsa 443 numaralı port kullanılması trafiğin birçok güvenlik duvarından rahat geçmesini sağlar.

IPV6 da desteklenmekte. IPv6 ayarlarını da yapmayı unutmamak gerekiyor.

Sisteminizi kapatıp açtığınızda dnscrypt-proxy’yi yeniden başlatmanız gerekiyor.

Aynı anda, farklı ayarlar ile birden fazla dnscrypt-proxy çalıştırabilirsiniz.

Son olarak DNSCrypt-proxy yi yetkisiz bir kullanıcı ile kullanmak güvenliğiniz açısından tavsiye edilir.

Komut satırından ek ayarları şu parametrelerle yapabilirsiniz:

–ephemeral-keys: Her sorguda bir geçici (ephemeral) açık (public) anahtar kullanılarak gizliliğin artırılmasını sağlar. Kendi sunucunuzu kullanmıyorsanız tavsiye edilir.

–local-address=<ip>[:port] Yerel olarak bağlanılacak adresi belirtir. Varsayılan 127.0.0.1:53’tür.

–logfile=<dosya>  Özel bir dosyaya kayıt (log) tutmak için kullanılır. Varsayılan olarak kayıtlar, işlem eğer önplanda (foreground) çalışıyorsa stdout’a ; arkaplanda (background) çalışıyorsa syslog’a gönderilir.

–max-active-requests=<sayı> Maksimum aktif istek sayısını belirtmeye yarar. Varsayılan değer 250 dir. Hizmetin devamı için bazı durumlarda sınırlanması gerekebilir.

–pidfile=<dosya>  işlem tanım değerini (PID) değerini bir dosyaya depolak için kullanılabilir.

–resolvers-list=<dosya>  Çözümleyici listesini ve kullanılacak parametreleri içeren (CSV) dosyayı belirtmekte kullanılır.

–test Sunucu tarafının doğru yapılandırılmış ve geçerli bir sertifikanın kullanılabileceğini kontrol etmek için kullanılır.Kendi dnscrypt proxy’nizi izlemek (monitor etmek) için kullanabilirsiniz.

  • Sonuç

crypted

Evet artık DNS sorgularımız şifreli. 3. gözler sorgularımızı dinlese bile kimin IP adresini istediğimizi göremeyecekler. Peki yeterince gizlilik sağladık mı? Bunun cevabı size kalmış.

DNS’in çalışma mantığına geri dönersek (kabaca) siz bir siteyi tarayıcınıza yazarsınız ve enter’a basarsınız, o sitenin IP adresi DNS sunucuya sorulur. Buraya kadar sızıntı sağlamıyoruz. DNS sunucudan bize IP adresi döndüğünde biz o adrese bir HTTP isteği yollarız, işte burada başka bir sızıntı var. Basitçe bir ters sorgulama (reverse lookup) ile 3. kişiler hala nereye gittiğinizi anlayabilir. Buna engel olmak için VPN ya da proxy kullanmalısınız.

A NFA EXAMPLE TO CATCH STRINGS THAT ENDS WITH WEB or EBAY

In our privious article, we had shown how can be achieved with a DFA. This article we will introduce the same problem with a NFA which is relatively hard to implement than DFA. You can obtain all codes from here. Let’s start with state diagram. PS:For those who check over the DFA example the state equations is like this : a=>1    b=>1,2   c= >1,3,5  d=>1,4,6    e=>1,5    f=>1,6  g=>1,7  h=>1,8 nfa state diyagramHere, “” symbol  is stands for the input set which is all printable ASCII characters including w,e,b,a,y . As you know,a rule of NFA’s, we can be in several states at one particular time. Let me explain with example. Suppose we had given “awebay” word. We start at state 1 because it’s our initial state. Then character “a” comes. We return to state 1. We can express this event via transition function like δ(1,a)=1 . So we have {1} state set which we are in. Next we have the character “w” .  If “w” comes while we are in state 1 we can now be in states 1 or 2. Videlicet δ(1,w)={1,2}. Next,  character is “e”. We must evaluate the output of transition function for each state that we are in. Therefor we say δ(1,e)={1,5} , δ(2,e)={3} and the output of transition function is {1,5,3}. Our word is continue with “bay”. If we evaluate them in order, for b: δ(1,b)={1}  δ(3,b)={4} δ(5,b)={6}  and {4}U{1}U{6}={1,4,6} and for a: δ({1,4,6},a)={1,7} . Pay attention that while we are in state 4, If any character comes, output of function is null set. Lastly from {1,7} where we in,If  “y” comes  we take output δ({1,7},y)={1,8}. In this manner we finish our word. Because of output state set {1,8} includes accepted state 8, the word aswebay is accepted by this automata. Now time to think about code. Conclusion of the example above, we can be in several state. To provide this feature, we will use a character array and keep the states in it. For each element of the states set(array), we must evaluate (via transition function) the next state or states for the input character. By doing this, we achieve the next states set that we are in. The keystone char * transition(char states[10],char input ) function can be implemented like this : trrrra Function get 2 parameter. First one is the states array. Second one is a character of our given string. For each member of the char array the process will be: decide what state it is, decide what input it is, decide where to go next and append it to new reached_states (If it is empty set, then delete old state), delete evaluated old state, And move on to next array member. New state is appended to reached_states via appendToArray function. Then old state is deleted via deleteFromArray. Eventually reached_states is copied into states via arrayCopy function and it is returned by transition function. So the task of transition function is over. For convenience transition function takes one character instead of a string at a time. Construct a brige between, we use void send (string str) function. sendfunction send function takes one string (str) and send its characters to transition function one by one. It does this in printarray function. This function, as you guess, takes an array and prints it on the screen with some helpfull information. Wherein the use, takes the result that returned by transition function and prints it. Pay attention that the states[0] is initiated with 1. because it is our start state. void printarray(char *arr) is implemented like this: (not much to explain I guess) print void arrayCopy(char a[10], char[10]) function copies the second parameter array ( b[10] ) into the first one ( a[10] ) . arraycopy char * deleteFromArray (char orginal[10] , char ap) function deletes the parameter character ap from parameter array orginal[10]. Fills that area with last member of the array. Then it assigns NULL to the last position. As result returns the array back. delete Char * appendToArray (char [10], char ap) function tries to append the second parameter (character) to the first parameter which is an array (orginal[]). If it ‘s already in the array returns back without doing anything. append Our last function void didAccepted() checks ıf the given string is accepted by automata or not. To do this, it looks for the reached_states has at least one accepted states. didaccept We can put aour functions in a class called automata. reached_states must be a member variable of this class. ps:If there is no access modifier to a member of class , then tis member is threated as private by default. automata class in main function we take a string(stri) from user. Then we call the send function for this string. Lastly, to see the result, call didAccepted function to know if it is accepted or not. main an example output of our program : Ekran Alıntısı We describe our arrays with length 10 to simplfy the codes and focus on key points. In this example we have 8 state. Even if we present all states (in this case even this is not possible) this arrays is enough for us. You can use dynamic array lengths if you wish. After pointing out this link to obtain all of codes  again, I stop here.  Happy codes 🙂 .

A DFA example that catch strings ending with web/ebay

If you have ever used Linux ,you probably meet with the grep command. For who doesn’t know it, shortly, we can say it is a command is used to catch a given string. So how grep command can be implemented? How can a search engine compare words to find the closer results for your queries? This topic can help you with start understanding.

We will introduce how you can implement a DFA which controls a given string if it ends with ebay/web (as regex (all printable ASCII characters)*web or (all printable ASCII characters)*ebay ) or not.

As you know, as a rule of DFA, We can be in just one state at a time. We are going to keep this information (which state we are in) in a character variable. Another characteristic of DFA s, it is clear which state to jump which we are present, for a particular input character . We are going to control the this pass with if-else blocks.

The diagram of our automata will be like this

DFA diyagramı

Here, “” symbol  is stands for the input set which is all printable ASCII characters includes w,e,b,a,y .

0 is our initial state.It means we have nothing that we like.

state 1 tells we have “w”

state 2 tells we have “w” followed by “e” (we)

state 3 tells we have “web” .This state is an accepted state.

state 4 tells we have “e”

state 5 tells we have “eb”

state 6 tells we have “eba”

state 7 tells we have “ebay”. This is also an accepted state.

Let’s get to coding.We are going to explain codes part by part. You can obtain whole code from here

Transition between states will be controlled via private: char transition(char) function.

Untitled

ps:i hasn’t got any mission

This function gets just a char variable which will be handled for that call. For example; if we enter “aw”, firstly we handle the “a” character. First if block will be evaluated and because of “a” is not equal “w” , state variable will be set as “0”. Then the similar process will go on with character “w”. Eventually the state variable will be returned as 1. Because we have “w” character.

dx

The task of public: void send (string) function is to call transition function for ever single character in a given string. Because Transition function can handle just one character at a time.

dm

Function public: int didAccepted () , is responsible for controll whether the given string has accepted or not. It can achieve this by checking the state variable is whether equal to 3 or 7 or not.

dh

Our functions will be in a class named automata. Private class variable state is already initiated with 0 because our initial state is 0.

dy

Lastly we have the main function like above. We create an automata object. Then send (via send function) the string that is entered by user. Eventualy we check  if it is accepted by automaton via didAccepted function.

End of story 🙂 I hope this helped you with some understanding. You can view the NFA automata implementation via this link.

Sonu web veya ebay ile biten kelimeleri yakalayan sonlu otomata (NFA) örneği

Bir önceki yazıda DFA örneğini koda dökmüştük. Bu yazıda ise koda dökülmesi nisbeten biraz daha zor olan NFA örneğini yapacağız. Kodlara topluca bu linkten erişebilirsiniz.

Öncelikle state diyagramı ile başlayalım.

DFA örneğini inceleyenler için buradaki statelerin karşılığının a=>1    b=>1,2   c= >1,3,5  d=>1,4,6    e=>1,5    f=>1,6  g=>1,7  h=>1,8  olduğunu belirtelim.

 

nfa state diyagram∑ sembolü yazdırılabilir (w,e,b,a,y) dahil tüm ASCII karakter kümesini temsil ediyor. Bu küme bizim input kümemiz. Bildiğiniz gibi NFA ların özelliği bir anda birden fazla state de bulunulabilmesidir. Bir örnekle açıklayalım. İnput string olarak ‘awebay’ kelimesini ele alalım. Başlangıç state imiz 1 olduğu için buradayız. a karakteri geliyor. Sonuçta 1 state i elimizde kalıyor. Transition fonksiyonu olarak ifade edersek δ(1,a)=1 oluyor. Dolayısıyla bulunduğumuz state hala 1 state i. Sırada w karakteri var. 1 state inde iken w gelirse artık 1 ve /veya 2 statelerinde bulunabiliriz yani δ(1,w)={1,2} . Sıradaki karakterimiz e. Bu karakteri bulunduğumuz her state (küme) için değerlendirmeliyiz. Bu yüzden δ(1,e)={1,5} ve δ(2,e)={3} çıktılarının bileşimi artık bizim bulunduğumuz state kümesi olacak ki bu da {1,5,3} state lerinden oluşan küme. İnput stringimizin devamında bay var. Sırasıyla yine karakterleri değerlendirmeye alırsak b için δ(1,b)={1}  δ(3,b)={4} δ(5,b)={6} olduğundan {4}U{1}U{6}={1,4,6} sonucunu alırız. a için δ({1,4,6},a)={1,7} sonucunu alıyoruz. Burada 4 state inde iken bir input geldiğinde boş kümeye düşüldüğüne dikkat edin. Son olarak bulunduğumuz {1,7} kümesinde iken y geldiğinde  δ({1,7},y)={1,8} sonucunu alıyoruz. Bulunduğumuz kümede kabul edilen 8 state i bulunduğu için girilen aswebay string i kabul ediliyor.

Şimdi kodu düşünelim. Bir anda birden fazla durumda bulunabileceğimizden bunu bir karakter dizisinde tutacağız. Bu kümedeki her eleman (state) için yeni gelen karakteri bir transition fonksiyonu ile değerlendirip bulunduğumuz yeni state kümesini elde edeceğiz ve bu kümeyi de yine bir dizide tutacağız. Yazımızın kilit noktası char * transition(char states[10],char input ) fonksiyonumuzun  kodları şu şekilde :

transition

Fonksiyon iki parametre alıyor. States dizisi o anda bulunulan stateleri tutuyor. input ise değerlendirilecek karakter.  Bulunulan her state için (states dizisinin her bir elemanı için ) while döngüsü içindeki if else blokları ile önce bulunulan değerlendirilen state e sonra da gelen input a göre geçilecek state e  karar veriliyor. Geçilen state appendToArray fonksiyonu ile reached_states adlı diziye eklendikten sonra states deleteFromArray fonksiyonu ile dizisinden siliniyor. Son olarak bu karakter için (o anki tüm stateler ile) tüm değerlendirmeleri yaptıktan sonra ulaştığımız stateleri tutan reached_states dizisi arrayCopy fonksiyonu ile states dizisine kopyalanıp states dizisi sonuç olarak döndürülüyor. Böylece transition fonksiyonu görevini yapmış oluyor.

Basitlik açısından transition fonksiyonu tek karakter için (char input) çağrılıyor. Biz ise kullanıcıdan bir karakter dizisi alıyoruz. Aradaki köprüyü sağlamak için void send (string str) fonksiyonunu kullanıyoruz.

send

send fonksiyonu bir string (str) alıyor ve karakterlerini tek tek transition fonksiyonuna gönderiyor. Bunu printarray isimli fonksiyon içinden yapıyor. tahmin edeceğiniz gibi print array bir diziyi ekrana basan fonksiyon. Transition fonksiyonumuzun dönderdiği diziyi (states) alıyor ve bunu biraz ek bilgi ile ekrana basıyor. kodları şu şekilde:

printarray

void arrayCopy(char a[10], char[10]) fonksiyonu aldığı ikinci( b[10] ) diziyi ilk diziye( a[10] ) kopyalıyor.

arraycopy

char * deleteFromArray (char orginal[10] , char ap) fonksiyonu aldığı diziden (orjinal [10]) karakteri (ap) siliyor. Sildiği yere son elemanı koyuyor. Son karaktere NULL atıyor. Sonuçta da kalan diziyi dönderiyor.

deletefromarray

Char * appendToArray (char [10], char ap) fonksiyonu aldığı diziye (orginal[]) aldığı karakteri (ap) eğer yoksa ekliyor. Zaten bulunuyorsa aldığı diziyi doğrudan dönderiyor.

appendtoarray

son fonksiyonumuz void didAccepted() ile girdimizin otomata tarafından kabul edilip edilmediğini öğreniyoruz. Fonksiyon bunu reached_states içinde kabul edilen 4 ve 8 statelerinden birinin bulunup bulunmadığını kontrol ederek yapıyor.

didaccepted

Fonksiyonlarımızı automata isimli bir sınıf içine yazıyoruz.  reached_states dizimiz bu sınıfın private bir değişkeni. Bu arada başına erişim tanımlayıcı (public,private vs) yazmadığımız fonksiyonlar da varsayılan olarak private olarak değerlendiriliyor. Sınıfımızın genel görünümünü ve main fonksiyonunu verip yazımızı sonlandıralım.

automata class

Main fonksiyonunda kullanıcıdan stri isimli bir string alıyoruz, send fonksiyonuna gönderiyoruz. Son olarak didAccepted fonksiyonunu çağırarak inputun kabul edilip edilmediğini öğreniyoruz.

automata main

Programımızın örnek çıktısı :

output

Dizi boyutlarını 10 olarak sabit şekilde tanımadık. Çünkü bizim örneğimizde sadece 8 state imiz var ve hepsinde aynı anda bulunsak bile (ki örneğimizde bu bile mümkün değil) bu dizi bize yetecektir. Kodu basit tutup gerekli noktalara odaklanmak açısından diziyi sabit boyutlu tanımlamış olsak da dinamik olarak boyutu ayarlayanabilir. Kodların tamamını topluca bu linkten bulabileceğinizi tekrar belirterek yazımızı noktalıyoruz. Herkese kolay gelsin.

Sonu web veya ebay ile biten kelimeleri yakalayan sonlu otomata (DFA) örneği

Linux kullandıysanız mutlaka grep komutu ile de bir yerlerde karşılaşmışsınızdır. Bilmeyenler için kısaca bunun verilen bir stringi yakalamaya yarayan bir komut olduğunu belirtirek uzatmadan geçelim. Peki bu komut nasıl koda dökülmüştür? Bir arama motoru istediğiniz metni ararken metin karşılaştırmalarını nasıl yapar ve sizi yakın sonuçlara götürür? Bu yazımız kafanızda birşeyler oluşması sağlayabilir.

Bu yazıda sonunda web veya ebay (regex olarak ifade edersek (ASCII karakter kümesi)*web ya da (ASCII karakter kümesi)*ebay ) kelimeleri geçen stringleri yakalayan sonlu otomata örneğinin c++ ile nasıl koda döküleceğini örnekleyeceğiz. Bu iş için DFA (Deterministic Finite Automata) kullanacağız.

Bildiğiniz gibi DFA da herhangi bir anda sadece bir state de bulunabiliriz. Bu state in hangisi olduğunu bir karakter değişkeni içerisinde saklayacağız. DFA ların bir başka özelliği ise input alfabesindeki herhangi bir inputa karşılık o anda bulunulan stateden hangi state e geçileceğinin net bir şekilde belli olmasıdır. Biz geçişleri if else blokları ile kontrol edeceğiz. İstenirse switch case yapısı da kullanılabilir.

Otomatamızın state diyagramı gördüğünüz gibi olacaktır.

DFA diyagramıBurada “” input alfabemizin kümesi olan yazdırılabilir  tüm (w,e,b,a,y dahil) ASCII karakterlerini temsil ediyor.

0: başlangıç state imiz. Elimizde herhangi istediğimiz bir karakter dizisi bulunmadığını niteliyor.

1: elimizde ‘w’ bulunduğu durum.

2:elimizde ‘we’ bulunduğu durumu belirtiyor.

3:elimizde ‘web’ bulunduğu durumu belirtiyor. Bu kabul edilen bir state. Kelimemizin sonunda web olduğunu haber veriyor.

4:elimizde ‘e’ bulunduğu durumu belirtiyor.

5:elimizde ‘eb’ bulunduğu durumu belirtiyor.

6:elimizde ‘eba’ bulunduğu durumu belirtiyor.

7:elimizde ‘ebay’ bulunduğu durumu belirtiyor. Bu kabul edilen bir state. Kelimemizin sonunda ebay geçtiğini bize anlatıyor.

Gelelim kodlamaya. Kodları bölüm bölüm açıklayacağız. Tamamını şuradan alabilirsiniz.

State ler arasındaki geçişi private: char transition(char) fonksiyonu ile sağlayacağız.

Untitled

Bu fonksiyon bir adet char değişkeni alıyor. Bu bizim o çağrıda değerlendireceğimiz karakter. Örneğin “aswebay” girilmişse ilk değerlendirilecek input değişkeni a karakteri olacak. başlangıç state i 0 olduğu için ilk if bloğuna girilip karakterin w olup olmadığına bakılacak , olmadığı için state değişkenimiz 0 olarak kalacak. Kontroller bu şekilde devam ederek sonuçta bulunduğumuz state döndürülecek.

not: i değişkeninin herhangi bir görevi bulunmamakta

dx

public: void send (string) fonksiyonumuzun görevi girilen stringin her karakteri için tek tek transition fonksiyonumuzu çağırmak.

dm

public: int didAccepted () Fonksiyonumuzun görevi işlemler bittikten sonra çağrıldığında stringin kabul edilip edilmediğini kontrol etmek. Bunu state değişkenindeki değerin kabul edilen statelerden biri ile eşleşip eşleşmediğini karşılaştırarak yapıyor.

dh

Fonksiyonlarımız automata sınıfımızda yer alıyor.sınıfımızda bulunan state değişkeni private ve  ilk değeri 0 olarak atanmış durumda çünkü başlangıç state imiz 0.

dy

main fonksiyonumuzda ise bir string tanımlıyoruz. automata objesi(object) ile bu stringi send fonksiyonuna gönderiyoruz ve son olarak kabul edilen bir string olup olmadığını didAccepted fonksiyonu ile kontrol ediyoruz.

Dfa örneğimiz bu şekildeydi. Umarım kafanızda bir şeyler oluşmasına yardımcı olur. NFA örneğine buradan ulaşabilirsiniz. Kolay gelsin.