HN Duyurusu: Programın bir bölümünü object file olarak dışa aktaran Ghidra eklentisi
(github.com/boricj)- Bu Ghidra eklentisi, bir programın bir bölümünü object file olarak dışa aktarır; dışa aktarılan dosya, semboller ve relocation table gibi geçerli metadata içerdiği için toolchain içinde yeniden işlenebilir
- Başlıca kullanım alanları ileri düzey binary patching, yazılım portlama, dosya biçimi dönüştürme, kütüphane oluşturma ve decompilation projelerinde programı birden çok object file'a bölerek yeniden uygulamadır
- Desteklenen kombinasyonlar COFF x86/x86_64, ELF x86/x86_64/MIPS ve OMF x86; COFF MIPS, OMF x86_64 ve OMF MIPS desteklenmez
- Kullanıcı, Ghidra Listing içinde çıkarılacak adres aralığını seçer, ardından Relocation table synthesizer analyzer'ını çalıştırır ve sonra
File > Export Program…içinden relocatable object file exporter'ı çağırır - Relocation table sentezi, Ghidra veritabanı doğruluğuna bağlıdır; yanlış veya eksik bilgi varsa relocation'lar bozulabilir ya da eksik kalabilir, bu yüzden dışa aktarmadan hemen önce analyzer'ı yeniden çalıştırmak güvenlidir
Bu eklenti ne yapıyor?
- Object file exporter extension for Ghidra, bir programın bir bölümünü object file olarak dışa aktarmayı sağlayan bir Ghidra eklentisidir
- Oluşturulan object file, semboller ve relocation table gibi geçerli metadata içerir
- Bu metadata sayesinde dışa aktarılan object file, toolchain içinde doğrudan yeniden kullanılarak ek işlemlerden geçirilebilir
Kullanım örnekleri
- Advanced binary patching
- Orijinal bölüm ile değiştirilmiş bölümü elle eşleştirmek yerine, bunların birlikte uyumlu hale gelmesi için linker kullanılabilir
- Software ports
- Programdan sistemden bağımsız kod ayrıştırılabilir ve geri kalan kısım değiştirilebilir
- Programları veya object file'ları bir dosya biçiminden diğerine dönüştürebilir
- Programın bir bölümünü çıkarma ve kütüphane oluşturma
- Programın bir bölümü çıkarılıp başka bir bağlamda yeniden kullanılabilir
- Decompilation projelerinde program, birden çok object file'a bölünebilir ve Ship of Theseus yaklaşımıyla yeniden uygulanabilir
Desteklenen mimariler ve object file biçimleri
- Destek matrisi şöyledir
- COFF: x86, x86_64 desteklenir / MIPS desteklenmez
- ELF: x86, x86_64, MIPS desteklenir
- OMF: x86 desteklenir / x86_64, MIPS desteklenmez
Derleme ve kurulum
- CLI derleme adımları
- Depo clone edilir
GHIDRA_INSTALL_DIRortam değişkeni, Ghidra kurulum dizinine ayarlanırgradle buildExtensionçalıştırılır- Oluşturulan Ghidra eklenti arşivi
dist/dizininde üretilir
- GitHub Maven deposundan paketi indirmek için kimlik doğrulama gerekir
read:packagesyetkisine sahip bir GitHub classic token oluşturulur ve${GRADLE_USER_HOME}/gradle.propertiesiçinegithubToken=ghp_xxxeklenir- Alternatif olarak
gradle installStandaloneDepsçalıştırılarak submodule içindeki vendored dependency derlenip kurulur
- Kurulum adımları
- releases page üzerinden eklenti indirilir veya yerelde derlenir
- Ghidra içinde File > Install Extensions… ile eklenti kurulur
- CodeBrowser penceresinde File > Configure > Experimental altında RelocationTableSynthesizedPlugin eklentisi etkinleştirilir
Kullanım akışı ve dikkat edilmesi gerekenler
- Temel kullanım adımları
- Listing görünümünde çıkarılacak adres kümesi seçilir
- one-shot mode olarak sunulan Relocation table synthesizer analyzer'ı çalıştırılır
- File > Export Program… içinde relocatable object file exporter çağrılır
- Yeniden oluşturulan relocation'lar Window > Relocation table (synthesized) içinde görüntülenebilir
- Ayrıntılı değerlendirme raporu, Analysis > Auto Analyze... iletişim kutusunda Relocation table synthesizer analyzer'ının Evaluation report policy seçeneği ayarlanarak etkinleştirilebilir
- Eklentiyi kullanmadan önce tüm programın baştan sona reverse engineering işleminden geçirilmesi gerekmez
- Başarılı delinking genellikle dışa aktarılacak bölümdeki ve harici referanslardaki metadata'ya büyük ölçüde bağlıdır
- relocation konumu olarak kullanılan fonksiyonlar ve pointer'lar
- relocation hedefi olarak kullanılan symbol footprint
- ikisi arasındaki referanslar
- Relocation table synthesizer analyzer'ı, Ghidra veritabanının doğruluğuna bağlıdır
- Hatalı veya eksik bilgi, analiz sırasında bozuk relocation'lara ya da eksik relocation'lara yol açabilir
- Object file exporter, Relocation table synthesizer analiz sonuçlarına bağlıdır
- Şüpheli bir durum varsa, relocation table'ın güncel olduğundan emin olmak için object file dışa aktarımından hemen önce analyzer çalıştırılmalıdır
Nasıl çalışıyor?
- Object file üç bölümden oluşur
- Relocatable section byte'ları
-
Symbol table
- Relocation table
- Linker'ın birden çok object file'dan executable oluştururken yaptığı işlemler
- Section'ları belleğe yerleştirir
- Sanal adres alanında symbol adreslerini hesaplar
- Son symbol adreslerine göre section byte'larına relocation uygular
- Genellikle bu işlem tamamlandıktan sonra relocation table atılır
- Debugging symbol'ları korunmazsa symbol table de atılır ve geriye yalnızca relocate edilemeyen section byte'ları kalır
- Bu eklenti, dikkatli analizle bu verileri yeniden oluşturabilir ve böylece programın yeniden object file olarak delink edilmesini sağlayabilir
1 yorum
Hacker News yorumları
Bunu burada görmek sevindirici. Gerçekten harika bir proje olduğunu düşünüyorum ve MS COFF desteği eklenmesine yardımcı oldum.
Ancak ilk PR'ım mevcut ELF desteğine kıyasla epey yetersizdi; bu yüzden bir sorun çıkarsa muhtemelen benim hatam olabilir. Yine de geliştiğini görmek mümkün.
Henüz büyük bir işte kullanmadım ama şimdiye kadarki en eğlenceli denemem, Visual Studio 2003 ile derlenmiş bir Hello World çalıştırılabilir dosyasını delink edip Linux x86 üzerinde GCC+glibc ile yeniden linklemek, sonra da MinGW+msvcrt ile tekrar linklemek oldu.
Hello World'den daha büyük şeyler hâlâ zor; özellikle Ghidra'ya çok hâkim olmadığım için büyük ikili dosyalarda delink edilecek aralığı seçmenin iyi bir yolunu da henüz bulamadım.
Tam da bugün bu aracın Nixpkgs türev paketi merge edildi; bu yüzden NixOS unstable'da
ghidra.withExtensionsile kurulabiliyor. Konumughidra-extensions.ghidra-delinker-extension.Ancak birkaç gün önce yeni bir sürüm çıktı ve PR'ı rebase etmediğim için şu anda eski sürümde; yakında bir güncelleme göndermeyi deneyeceğim.
Örneğin, özgün çalıştırılabilir dosyayı oluşturan çeşitli nesne dosyalarının adlarını ve aralıklarını saptamış bir Ghidra programınız varsa, ilgili klasöre veya fragment'e sağ tıklayıp Select Addresses ile tamamını seçebilirsiniz.
Relocation synthesis analyzer ve dışa aktarma da sırasıyla betiklenebilir veya programın ağaç yöneticisi üzerinden otomatikleştirilebilir; böylece istenen aralığı elle seçme, analyzer'ı ve dışa aktarmayı manuel çalıştırma ihtiyacı azalır.
Oldukça ilginç görünüyor; birkaç yıl önce bıraktığım oyun reverse engineering projesine tekrar bakmak istememe neden oldu.
Bunun nasıl kullanılacağını ve çıktısının nasıl değerlendirileceğini baştan sona gösteren eksiksiz bir örnek olsa iyi olurdu.
https://github.com/boricj/ghidra-delinker-extension/blob/mas...
Çalıştırılabilir dosyanın hangi bölümünün dışa aktarılacağını belirlemenin ne kadar iş gerektirdiğini merak ediyorum.
2008~2015 civarından görece modern bir Win32 oyununu nesne dosyası olarak dışa aktarıp birkaç saat içinde tekrar tam bir çalıştırılabilir dosya hâline derlemek/linklemek gerçekçi mi?
Neyi dışa aktaracağınız ayrı bir mesele ve program hakkında bilgi gerektirir. Debug sembolleri varsa iş çok daha kolaylaşır; yoksa bile Ghidra veritabanını dışa aktarılabilecek kadar doğru hâle getirdikten sonra genellikle nerede ne olduğuna dair bir fikir edinirsiniz.
Gönderideki kullanıcı örneğinde, ilk issue Temmuz başında açılmıştı; Ağustos ortası civarında ise işlevsel olarak aynı şekilde çalışan yeniden linklenmiş bir çalıştırılabilir elde edilmişti.
Ancak o sırada COFF dışa aktarımında düzeltilmesi gereken çok sayıda bug vardı ve i386 analyzer'ının da elden geçirilmesi gereken yerleri bulunuyordu; bu yüzden artık başkalarının aynı sorunlarla daha az karşılaşacağını umuyorum.
Ne kadar süreceğini bilmiyorum ama debug sembolleri yoksa ve gerçekten çok şanslı değilseniz, birkaç saatten uzun sürme olasılığı yüksek. Deneyimli bir reverse engineer o süre içinde bir şeyleri çalışır hâle getirebilir; ama ilk yükleme ekranının ortasında çökebilir de. İş bitene kadar ne zaman biteceğini bilmediğiniz türden bir uğraşa daha yakın.
Güzel görünüyor. Bir gün mevcut programları daha kolay parçalara ayırıp istediğimiz şekilde kullanmamıza yardımcı olabilir.
Meta'nın LLM Compiler'ı veya LLM kullanarak decompile etme gibi araştırmalar var; programı parçalamak ve bazı bölümleri değiştirmek, LLM'lerin keşfetmesi ve kendi kendini iyileştirmesi için de veri açısından zengin ve ilginç bir alan olabilir.
Öğrenme açısından da içinde çok sayıda ilginç token saklı gibi görünüyor; bunlarla yapılabilecek şeyler de çok.
Dürüst olmak gerekirse kulağa sihir gibi geliyor. Bunun nasıl mümkün olduğunu anlamam lazım
Bağlayıcı birden fazla nesne dosyasından çalıştırılabilir dosya oluştururken bölümleri belleğe yerleştirir, sanal adres alanında sembol adreslerini hesaplar ve ardından nihai sembol adreslerine dayanarak bölüm baytlarına yeniden konumlandırmaları uygular.
Delink’in püf noktası, bu yeniden konumlandırmaların nereye uygulandığını bulup geri almak ve yeniden konumlandırılabilir baytları tekrar elde etmektir. Sonra geri alınan içeriğe dayanarak yeniden konumlandırma tablosu ve sembol tablosu oluşturup paketlerseniz nesne dosyası ortaya çıkar.
Gerçekten zor kısım, yeniden konumlandırma noktalarını bulmaya yönelik analizdir. Bunun çoğunu Ghidra’ya bırakıyoruz ama referansları yeniden konumlandırma noktalarına dönüştürmek gerekiyor. x86’da nispeten kolay, MIPS’te ise kâbus gibi zor. Bu uzantıyı, bunun için gereken verileri toplama ve nesne dosyasını serileştirme işini de otomatikleştirmek için yaptım.
Microsoft platformları dışında gerçek dosya biçiminin aynı olduğu durumlar da çoktur; örneğin ELF böyledir.
Büyük fark yeniden konumlandırmadır. Nesne dosyalarında ince ayrıntılı yeniden konumlandırma bilgisi bulunur, çalıştırılabilir dosyalarda ise genellikle yoktur. Windows’un çalıştırılabilir imajlarında, çalıştırılabilir dosya yeniden konumlandırıldığında düzeltilmesi gereken kod ve veri adreslerini gösteren asgari yeniden konumlandırmalar vardır; imajın kendisi ise yalnızca tüm imaj taban adresi düzeyinde yeniden konumlandırılabilir.
Buna karşılık nesne dosyalarında sembol düzeyinde yeniden konumlandırma bulunur. Bu bilgiyi doğru şekilde yeniden oluşturmak için disassembly’ye semboller hakkında epey doğru bilgi iliştirmek gerekir.
Bir diğer büyük fark, nesne dosyasının henüz linklenmemiş olmasıdır. Hiçbir sembol çözümlenmiş durumda değildir. Bu aslında düzeltmesi daha kolay bir şeydir; delink sırasında mevcut kapsamın dışındaki bir sembol varsa çoğunlukla çözümlenmemiş sembole çevirmek yeterlidir. Daha sonra yeniden linkleme sırasında başka bir nesne dosyası veya kütüphane o sembolü sağlamalıdır ki tekrar bağlanabilsin.
Giriş noktası olmaması gibi küçük farklar da vardır ama bunların büyük bir önemi yoktur.
Dolayısıyla bir çalıştırılabilir imajdan veya paylaşımlı nesneden nesne dosyası kesip çıkaracağınız sınır fiilen keyfidir. İlk derlendiğinde muhtemelen çeviri birimlerine ayrılmıştı ama linkleme aşamasında bu sınırlar pek önemsenmez. Elbette eşleşen bir decompile istiyorsanız nesne dosyası sınırı yanlışsa işler çok zorlaşabilir; bu yüzden mümkünse bunu öğrenmek iyi olur.
Bu sorunla pratikte uğraştım ama ayrıntılarda biraz yanılıyor olabilirim, o yüzden bunu kabaca böyle değerlendirmek gerekir. Nesne dosyaları hakkında bir blog yazısı yazmayı denemiştim; halihazırda birkaç iyi yazı da var.
Bu sürecin tamamen güvenli olup olmadığını merak ediyorum. Başarının her zaman garanti olup olmadığını, yoksa analizin muhafazakâr mı davrandığını bilmek istiyorum.
Örneğin ELF’te bir parça, veri veya işlev eksikse Delink başarısız mı oluyor?
Analiz aracım, en azından dışa aktarmaya çalıştığınız kısım için doğru bir Ghidra veritabanına dayanıyor. Düzeltilmesi gereken çeşitli sorunları günlüklemek için epey uğraştım ama var olmayan şeyi göremem.
Özellikle eksik referanslar ve kesilmiş değişkenler tespit edilmez ve tuhaf tanımsız davranışlara yol açabilir.
Bu sorunların bir kısmını izlemenin yolları var. Şimdiye kadar bulduğum en iyi yöntem, çalıştırılabilir dosyayı farklı bir taban adresiyle yeniden linklemek ve özgün programın adres aralığının eşlenmemesini sağlamak. Böylece kaçırılan mutlak yeniden konumlandırma noktalarında segmentation fault oluşur ve bunlar debug edilebilir. Ancak bu yalnızca hedefte MMU varsa mümkündür.
Kesilmiş değişkenleri, özellikle şüphelenmiyorsanız, izlemek son derece zahmetlidir. Çünkü bozulan şey kesilmiş değişkenden sonraki bellektir. Bir tamsayıyı pointer sanma durumunu izlemek de zordur. Çünkü tamsayı değeri, hedef sembolün yerleştirildiği adrese göre değişir ve program davranışı tutarsızlaşır; bu özellikle adres alanının çok düşük bir yerine yüklenen programlarda büyük sorun olur.
Yine de Ghidra veritabanı yeterince doğruysa ve özgün olarak kullanılanla aynı nesne dosyası biçiminde tekrar dışa aktarıp aynı platformu ve aynı araç zincirini kullanırsanız, megabaytlar düzeyinde program kodu ve verisini başarıyla delink edebilirsiniz. Linker’ın yaptığı bir şeyse, geri almak da mümkün olmalı diye düşünüyorum.
Buna karşılık Linux i386 ELF çalıştırılabilir dosyasından COFF nesne dosyasına delink edip bunu i386 Windows araç zincirinde kullanmak gibi, özgün programın platformu ve araç zinciriyle uyuşmayan çapraz delink işine başlarsanız durum değişir. Dışa aktarma yeniden konumlandırmayı ifade edebiliyorsa çalışan, yeniden konumlandırılabilir bir nesne dosyası elde edebilirsiniz; ama ABI uyumsuzluklarıyla da uğraşmanız gerekir. Mümkün, fakat ilk proje olarak önermem.
Özetle, ne yaptığınıza ve Ghidra veritabanının doğruluğuna bağlı olarak durum “kendiliğinden çalışır” seviyesinden “Cthulhu’dan merhamet dileme” seviyesine kadar değişir.
Örneğin
int getSpecialArrayElement(char *array, uint64 key) { i = computeOffset(key); return array[i]; }gibi bir fonksiyonu düşünün.computeOffsetkeyfi derecede karmaşık olabilir; obfuscation istiyorsanız bilerek analiz edilmesi zor hale de getirilebilir. Bu fonksiyonun bellekte keyfi bir konuma erişmesini engelleyen hiçbir şey yoktur.Olası tüm girdileri tek tek denemediğiniz sürece, linker’ın bellekte zaten tanımlamış olduğu bir sembole erişip erişmediğini bilemezsiniz;
computeOffsetiçinde böyle bir denemeyi engelleyecek Turing tuzakları da bulunabilir.Daha önce yalnızca hayal edip gerçekten yapmadığım bir fikirle bağlantı kurunca ilginç olabilir. Debug bilgisinden header dosyası üretmek ve gerekirse bunu LLM ile toparlatmak.
https://github.com/wbenny/pdbex
LLM ile toparlama kısmına gelince, henüz tersine mühendislikte LLM modellerinin uygulanıp büyük başarı elde ettiği çok fazla örnek görünmüyor. Belki de bu alan, LLM mimarisinin sınırlarının ortaya çıktığı yerlerden biri olabilir diye de düşünüyorum
Uzmanı değilim ama bahis oynayacak olsam, birçok tersine mühendislik kullanımında diffusion modelleri tarafının daha ilginç olacağını düşünürdüm
Tam olarak aynı şey değil ama Binary Ninja’da, LLM ile disassembly’yi toparlamaya çalışan Sidekick adlı bir özellik var. Kişisel olarak beni pek etkilemedi ama birileri için faydalı olabilir
pahole, ELF DWARF bilgisinden derlenebilir C header dosyaları üretebiliyorBurada LLM pek ilgili görünmüyor. Header dosyası, çalıştırılabilir dosyanın dışa aktardığı tüm tipleri özgün değerleriyle doğru biçimde içeriyorsa kullanılabilir; aksi halde hatalı ya da eksiktir. LLM’in bir şeyler daha uydurması yardımcı olmaz
Ghidra’da da veri yapılarını dışa aktarmak için yerleşik bir özellik var ve DWARF yapılarından üretim yapılabiliyor. Sağ tık -> Export to C header
Header üretimi ve sonrasında tip kısıtlarına uyacak şekilde değiştirilebilen mutator üretimi de bunun bir parçasıydı
LLM tarafını eklersek, anonim struct’lar gibi şeylere isim vermek mümkün görünüyor ama bunun iyi bir fikir olup olmadığından emin değilim. Daha ilginç olan, dokümantasyon amacıyla bilinen tip kısıtlarını LLM’in doğal dille açıp özetlemesini denemek olabilir
Henüz uygulamamış olmamın nedeni, şimdiye kadar onsuz idare edebilmem. Üstelik epey derin bir tavşan deliği gibi geliyor; içinde bulunduğum tavşan delikleri de zaten yeterince büyük
Gerçekten harika görünüyor ve daha önce düşündüğüm oyun modlama fikriyle de bağlantılı. Tenchu decompilation blog serisi de güzeldi
Şu an yaptığım işte hemen kullanabileceğim bir yer yok ama geçmişte olsaydı gerçekten çok faydalı olacak bir araç gibi görünüyor
Yakında denemek için zaman ya da fırsat bulabilirsem iyi olur