FFI nasıl çalışıyor?

Evet, ctypes’in yaptigini yapmis olacaksin.

lib.hello() ?

Valla bende yukardaki kod1/kod2 “cat” diye calisti. Parametre/return’lerini soylemem bile gerekmedi. (Herhalde int(void)'e default ediyor)

0 yazdırıyor.

Peki kodun neresine eklemem gerekiyor ? Ne işe yaradıklarını anladım da nereye eklendiklerini anlamadım.

Kodu terminalde çalıştırın.

Return değeri ve paslanan bütün argümanlar default olarak int.

İşe yaradı! Artık sonuç:
Hello World!
0
print(hello) vardı 0 ı yazdıran o onu kaldırırsam Hello World! kalıcak geriye.

Konu çok güzel.

Satır satır katılımcıları okudum.

Sonra neden ben de iki link paylaşmayayım ki dedim.

mesela ben ctypes nasıl çalışıyor diye merak etsem şöyle yapardım.

Python kaynak koduna bir bakayım sonuçta açık kaynak değil mi?

Ne gerek var efsanelere neyse içine bakıp kendim göreyim dedim…

GitHub - python/cpython: The Python programming language

Adamlar yapmış…

Sonra ctype ı merak ettim…

Nerededir diye baktım lib altında…

cpython/init.py at main · python/cpython · GitHub

Bir kaç klasör var ama en can alıcılarından biri yukarıdaki link.

Kodu kurcalarken

cpython/wintypes.py at main · python/cpython · GitHub

Tip çevrimlerine de bakmadan geçmedim.

Tabi bu arada init içinde:

cdll = LibraryLoader(CDLL)
pydll = LibraryLoader(PyDLL)

if _os.name == "nt":
    pythonapi = PyDLL("python dll", None, _sys.dllhandle)
elif _sys.platform == "cygwin":
    pythonapi = PyDLL("libpython%d.%d.dll" % _sys.version_info[:2])
else:
    pythonapi = PyDLL(None)

dll dosyalarına nasıl davrandığını da görme şansım oldu.

Şimdi gelelim işin en başına.

Yukarıdakilerin hiç biri python’ın marifeti değil.

Windows’un marifeti.

Windows gençlik yıllarında OLE (object linking and embeding), COM gibi teknolojiler geliştirdi.

Burada amaç, herhangi bir derlenmiş program parçasına başka programlardan erişim sağlamak ve böyleyece bazı nesneleri ortak kullanarak hem programlar arası iletişimi artırmak hem de bellekten tasarruf sağlamaktı.

Mesela dll içinde duran ve bazı davranışlar sergileyen bir buton nesnesini, o dönemler, hem c, hem visualbasic, hemde delphi gibi üçüncü parti dil ve yazılımlar bu yapı sayesinde paylaşabiliyordu.

Ki hala öyle.

Yani COM tabanlı bir nesne oluşturup, com template ile istediğin programda kullanabilirsin.

The Component Object Model - Win32 apps | Microsoft Docs

Bu com modeli sana componetlerini başka diller ve programlarla paylaşma ve yazdığın bir objeyi derledikten sonra istediğin kadar programdan çağırma ve farklı dillerde kullanmayı sağlar.

Teknolojinin reklamını yapmayacağım, çok da microsoft sever birisi değilim zaten.

Yine windows işletim sisteminin bazı marifetleri, bazı windows çağrılarını doğrudan yapmaya izin vermez.

Güvenlik anlayışı tartışılır ama doğrudan hook apileri çağırmana izin vermez.

Hook, windows un herhangi bir programının herhangi bir mesaj kuyruğuna kanca atmak demektir…

Ne işe yarar, çakma keylogger ları bir kenara koyarsak, keyboardhook ile keyboard olaylarını doğrudan yakalamak, mouse hareketlerini işletim seviyesi takip edebilmek için bir yapıdır.

Böyle anlatılmaz ama sabahın 6 sında benden bu kadar. :slight_smile:

Ve hazin olan şudur, ki bu, api hook işi de dll ler üzerinden yapılmalıdır. Doğrudan yürütülebilir bir process üzerinden hook yapmanıza izin vermez.

Yani dll ler içine nesne (object), kaynak (resource) ve kod gömebileceğiniz, kendiliğinden çalışmayan ama çağrılarak çağrılan programlar üzerinden çalışan enteresan canlılardır.

İşin acı tarafı buraya kadar ki anlattıklarımız, linux ve türevlerini hiç ırgalamaz.

Windows kendi yürütülebilir dosyaları için kendi kurallarını koymuş ve dll ler de bu kuralların bir parçası olarak yaşamına devam etmektedir.

Bir dll oluşturmak ayrı çağırıp çalıştırmak ayrı bir konu.

İkisine de girmek niyetinde değilim aslında

Ama işin sürprizi de aklımda.

Bkz. rundll32.exe

rundll32 | Microsoft Docs

dll dosyaları, aslında program entry pointları olmadığından çalışamayan budanmış exe dosyalarıdır.

Bunlara rundll32.exe ile hayat öpücüğü verebilirsiniz. Rundll32 ile istediğiniz dll dosyasındaki kodu çalıştırabilirsiniz. (istisnalar hariç) yani dll dosylarının çalışması için gerekli exe dosyası rundll32.exe dir.

Garibim python un bunlara yapabilecek veya karışabilecek bir durumu yok.

O sadece, az önce verdiğim windtpes dönüşümü ile windows un istediği veri tiplerini simüle eder, işletim sistemine bu dll leri çalıştırmasını rica eder o da çalıştırır. Ve sonucu python a geri verir.

Çok daha gelişmiş araçlar olsa da

ihtiyar pe explorer sevdiklerimden dir. Maalesef 64 bit desteği yapamadan gittiler ama,

PE Explorer: EXE File Editor, Resource Editor, DLL View Scan Tool, Disassembler. (heaventools.com)

kurup dll ve exe dosyalarını dump ettiğinde, program entry poinlerini, içindeki cdecl olarak tanımlanan fonksiyonları görebilirsin.

Örnek resim de atacaktım ama nasıl becerdiysem elimde birtane 32 bit program görüp de decompile edemedim sabah sabah.

Muhtemelen katılımcılar da bu konuya değinmişlerdir.

Yani yukarıda anlattıklarımın hepsi windows un halt yemesi.

Linux dünyası buna .o dosyasıyla tam olmasa da karşılık vermiş olmakla beraber. Bir yürütülebilir dosyayı linux ile çalıştırmak için uzantısı bile olması gerekmez.

Her neyse oralara girmeyim şimdilik.

Özetle.

Bu işin ana müsebbibi windows. Herhangi bir windows derleyicisi alıp, lib ve include altında bulunan, windows.h dosyalarını incelersen zaten windows tiplerini nerelerde kullanıldığını görebilirsin.

PE formatını da araştırdığında zaten yürütlebilir dosyaları derledikten sonra neden linkere bağladıklarını da anlayabilirsin.

Tabi araştırırsan.

Sonuç en baştaki linklerden kodu incelemen çok yere götür.

Ama windows üzerinden c gibi bir dille bu işi yaparsan daha iyi kavrarsın Python sadece arayüzü verebilir sana.

Kolay gelsin.

2 Beğeni

Soyle diyelim: Fonksiyonun int dondurdugunu, ve pasladigin arguman kadar int parametresi aldigini varsayiyor. Burada otorite fonksiyonun kendisi, ctypes veya baska bir kutuphane fonksiyonun ne alip dondurdugunu sadece tahmin edebilir.

Modulun cogu surada:

Isletim sisteminin marifeti.

Microsoft’un “developer’larin islerini kolaylastiralim ama sadece Microsoft ekosisteminde yasayip Microsoft aletleri kullandiklari surece” teknolojileri… Diger ornekleri icin—aslinda butun diger MS teknolojilerine bakabilirsiniz.

Ne yalan soyliyim, Microsoft vizyonu icinde dahice, ve bilisim tarihinde mutlaka denenmesi gereken fikirlerdi.

*Istedigin Windows programinda. Su aralar olusturdugumuz nesneler baskalarinin bilgisayarinda, VM, container, web aplikasyonu, browser veya ciplak bir *nix altinda kullanilmak isteniyor cogunlukla.

Burada hook mekanizmasinin calisma detaylarina degiliniyor. Bu mekanizmanin dynamic loading (DLL) kullanmasi kaza eseri, programla hook’un ayni address space icinde yasamasi gerektigi icin. (Cunku 16-bit Windows’ta oyleydi.)

Linux’teki (ve aslinda Windows’daki diger) onlarca trace/probe/hook mekanizmasina bakarsan, hemen hic biri boyle calismiyor.

Yaptigi sey LoadLibrary+GetProcAddress+cagridan cok fazlasi degil. Ve (ben de yanlis biliyormusum, ama) sadece ozel programlari calistirmak icin kullanilan bir program, yani bizim DLL’lerle bir alakasi yok.

Terminalde calisabiliyorsan objdump (ve bilumum binutils programi) 'dan iyisine hic denk gelmedim. Zorda kalinca herhangi bir debugger da ayni bilgileri (tek tek bakmak gerekse bile) gosterir.

.o → .obj
.so → .dll

Kesinlikle. Konsept diller arasi iletisim oldugu icin en az 2-3 dille calismak lazim. Cumlenin “Windows uzerinden” kismini ozellikle sildim.

3 Beğeni

Teşekkürler, hepinizin destekleriyle bilgilendirici bir konu haline geldiğini düşünüyorum.

Bunu bende incelemiştim.

Yani aslında her dll çağırdığımızda rundll32.exe yi mi çalıştırıyorduk.

Yani derlediğimiz c koduna main eklemessek hiç bir şeyin çalışmaması gibi mi ? DLL ler de başlangıç için bir nokta (main fonksiyonu) olmadığından hiç bir şey başlamıyor.

İllaki bir video falan bulurum hem kullanımını hem de bahsettiğin entry point ve fonksiyonları görürüm.

Windows derleyicisi ?

Araştırırım tabii.

C yi pek bilmiyorum ama denerim (eğer C# ile de oluyorsa C# bilgim var C# ta denerim)

:heart:

Keşke her (en azından çoğu) işletim sisteminde çalışabilecek şekilde tasarlasalarmış.

Önemli değil, burası öğrenmek için var zaten.

Bildiğim diller ile deneme yapayım o zaman.

Ben tek tek alıntılarayarak cevaplamaya üşeniyorum kusura bakma.

rundll32.exe sadece windows ( aib e göre işletim sisteminin) 'un çağırdığına benzer şekilde dll leri çağırıyor.

Ama bir programı yürütmek demek farklı bir şey, detaylarına ayrıca bakmak istersen uzunca yazarım.

dll ler’in entry point ı yok diyemem.

Bir tane exe dosya benim dijital mikroskopun yazılımı.

Adress of entry point.

Import listesine bakasak.

Bu durumda bu fonksiyonları aşağıdaki şekilde export edebildiğimizi görürüz.

Aynı şekilde bir de dll dosyası ekleyim.

Bunda da bir entry point var.

Yukarı da da export örnekleri var.

Aslında PE dosya formatında önce bir ön DOS programı var. Bu, eğer windows PE yi eski windows sistemlerinde çalıştırmaya çalışınca bu bir DOS programı diyecek kadar bir kod ekler ve her türlü oraya gider.

Arkasından eğer işletim sistemi PE yürütebiliyorsa yeni bir entry point a zıplar.

Yani dll lerinde bir giriş noktası var ama, yürütmek için ikinci bir yürütülecek kod adres tablosu yerine direkt kod tablosu var.

Yani yürütülmesine izin vermez ama bellek üzerinde bu kod parçalarının adreslenerek yürütülmesine olanak sağlar.

Biliyorum, anlatma kabiliyetim yok, ama elimden bu kadarı geliyor.

Aslında dll çağırdığımızda, windows un win.exe, dahil bir çok exe ve dll ve servis bir arada çalışıyor.

İstersen o konuda da uzunca yazarım.

Yani konu çekirdek seviyesi işletim sistemi ve çağrılara dönüşür.

Aslen rundll32.exe bunun bir örneği.

1 Beğeni

Önemli değil.

Olur tabii.

Yani bizim giriş noktası yazmamıza gerek yok zaten yazılmış bir tane var.

Gayet iyi anlatıyorsun.

İstediğiniz konuda yazabilirsiniz yeni bir şeyler öğreniyoruz sonuçta, bana başka konularda da uzunca yazdığınızı hatırlıyorum (sanırım C# ile ilgili bir soruydu) ve epey bilgilendirici oluyor.

run32dll.exe dll leri çağırmak için mecbur değil anladığım kadarıyla.

Linker demiştim. Linker işte bu işe yarıyor. Kaynakları, icon, resim, string gibi, kod ile birleştiriyor.

Dosya başlıklarını hazırlıyor, windows’un istediği PE formatında hepsini bir paket halinde bağlıyor.

Entry point i belirleyip adresini başlığa yazıyor, hatta check sum hesabı yazıp onu da dosyaya yazıyor ki dosya üzerinde oynama olursa check sum hatası versin. Tabi virüs yazarken, zaten check sum ı yeniden hesaplıyorsun, sonra eğer araya kod gireceksen bu entry point i önce kendi virüs koduna oradan da tekrar normal koda atlatıyorsun (jump, jnz vs gibi komutlarla).

Burada adresleri değiştirip istediğin kodu çalıştırabilirsin. Checksum ı da yeniden hesaplatıp kaydedersen. İçindeki virüs imzasını antivirüs tanımıyorsa, dosyada bir tuhaflık olduğunu anlamaz.

Evet rundll32.exe sadece dll nasıl çağırılır denemek istersen diye gündemde.

Aslında onunla da eğer kodun tablosunu biliyorsan, kod çağırıp dönüş alabilirsin.

1 Beğeni

Sanırım DLL i programa ekledikten sonra da DLL den yüklenen fonksiyonların adresleri ile onları çağırabiliyoruz. Entry point te de main yerine başka bir fonksiyonun adresini yazsam o fonksiyon en başta çalışacak.

Aslında öyle değil.

Bir kod yazalım mı?

PE header file okumak için.

Orada zaten çok şey öğrenirsin.

GitHub - erocarrera/pefile: pefile is a Python module to read and work with PE (Portable Executable) files

Şuna benzer bir şey yada bunu da deneyebilirsin.

Bir dll de export table vardır.

Bu export edebileceğin kodların adreslerini gösterir. exe lerde nadiren export table olur.

Yani export edilebilen her fonksiyonun kendisi bir entry point.

2 Beğeni

pefile ı yükledim ve bir kod yazdım, e_magic değerini az önce bir siteden görmüştüm e_magic i ve Signature ı almayı başardım.

import pefile

dosya = "mydll.dll"

pe = pefile.PE(dosya)

print("e_magic değeri: %s" % hex(pe.DOS_HEADER.e_magic))
print("Signature değeri: %s" % hex(pe.NT_HEADERS.Signature))

Bu konu için mydll diye bir dll oluşturmuştum ekrana Hello World! yazıyordu onda denedim.
Sonuçlar şöyle oldu:

e_magic değeri: 0x5a4d
Signature değeri: 0x4550

Artık yapman gereken tek şey kadı.

PE Expolrer’ın 64 bitliğini yazmak :slight_smile:

0x4550 zaten PE demek, dosyanın Portable executable olduğunu teyit etmiş oldun.

Bence tüm header ı okumayı öğrendiğinde.

Exe dosyların içindeki menu, icon gibi kaynakları dahi manipüle edebilirsin.

Eğlenceli konudur. Gençken çok bırkalamıştım PE leri MZ leri.

1 Beğeni

Şuan bir siteden pefile ın kullanımını okuyorum. Eğer pefile ile halledebilirsem 5dkye bitermiş gibi duruyor :smiley: (Yani gui olmadan, ve pek gelişmiş bir şey çıkacağını sanmıyorum)

Portable Executable - Wikipedia

Bu tabloyu incelersen, bir dll veya exe dosyasından hangi bilgileri alabileceğini görebilirsin.

1 Beğeni

Biter tabi ki, çok karmaşık değil.

Her zaman bunun içinde ne var bu nasıl çalışıyor diye kurcalayana rastlamıyorum.

Sevindim.

Öğrenebileceğine de inanıyorum.

1 Beğeni

Bir de aklıma gelmişken.

Asıl önemli konu.

__stdcall, __cdecl

Conventions for Calling DLL Functions (microfocus.com)

Bir fonksiyonu çağıracaksak.

İki metot var.

Bunları da irdelemen ve anlamanda da fayda var.

1 Beğeni

Programı bitirdim ve epey bilgiyi inceleyebiliyoruz: dller, dllerin fonksiyonları, tablodaki çoğu bilgiyi (bazılarına baktım da yoktu) ve sectionları. Hatta örnek olsun diye mydll.dll ile ilgili yukarıda konusu geçen bir kaç değeri vereyim:

e_magic değeri: 0x5a4d
Signature değeri: 0x4550
CheckSum değeri: 0xD914
EntryPoint adresi: 0x1330
Linker versiyonu (linkerler ile ilgili konu geçince bunu da koyayım dedim, bunda major ve minor olarak 2 tane varmış) : 0x2 ve 0x1E

Ayrıca

inceleyeceğim

1 Beğeni