Soru:
Mevcut bir ikili yürütülebilir dosyaya nasıl işlevsellik eklerim?
asheeshr
2013-03-23 18:55:13 UTC
view on stackexchange narkive permalink

Mevcut bir ikili dosyaya bazı işlevler eklemek istiyorum. İkili dosya gcc kullanılarak oluşturuldu.

  • Programın işleyişini yeterince anladığım halde, önce ikili dosyayı çözmem gerekir mi?
  • Gerekli kodu eklemeye nasıl başlamalıyım?
  • Bunu yapabilmek için herhangi bir araca ihtiyacım var mı?
hangi platform için, örneğin windows, linux?
Eklemek istediğiniz işlevsellik nedir? çünkü buna bağlı olarak farklı yaklaşımlar var. Örneğin, bir GUI'yi otomatikleştirmek için, örneğin bir veritabanı motorunu değiştirmek gibi farklı bir teknik kullanırsınız.
http://stackoverflow.com/questions/4309771/disassembling-modifying-and-then-reassembling-a-linux-executable
Sekiz yanıtlar:
#1
+38
Ed McMan
2013-03-23 20:47:41 UTC
view on stackexchange narkive permalink

Bunu yapmanın birkaç geniş yolu vardır.

  1. Dinamik araçlar

    PIN, Valgrind veya DynamoRIO, bir programın davranışını dinamik olarak değiştirmenize izin verir. Örneğin, belirli adreslerde yeni işlevlere çağrılar ekleyebilir, kitaplık çağrılarını yakalayabilir ve değiştirebilir ve çok daha fazlasını yapabilirsiniz.

    Dezavantajı, dinamik araçların genellikle yüksek ek yüke sahip olmasıdır. >

  2. Statik araçlar

    İstenilen davranışı eklemek için programı statik olarak değiştirmeyi de deneyebilirsiniz. Bir zorluk, sık sık çalıştırılabilir dosya formatıyla uğraşmanız gerekmesidir. ERESI projesinden elfsh gibi bazı araçlar bunun için var, ancak onları hatalı ve kullanması zor buldum.

    Statik için başka bir strateji enstrümantasyon "yeniden derlemektir". Bunu, programı yeniden derleyerek, kaynak kodunu değiştirerek ve yeniden derleyerek yapabilirsiniz. Teorik olarak, programı IL'ye yükseltmek, değiştirmek ve sonra LLVM kullanarak yeniden derlemek için BAP gibi bir araç da kullanabilirsiniz. Ancak, mevcut sürüm muhtemelen bunun için yeterince olgun değildir.

  3. Dinamik yükleme

    İşlevleri geçersiz kılmak için LD_PRELOAD kullanabilirsiniz dinamik olarak bağlantılı olacak. Bu, bir kitaplık işlevinin davranışını değiştirmek istediğinizde güzel bir seçenektir. Doğal olarak, statik olarak bağlı ikili dosyalar üzerinde veya statik fonksiyonlar için çalışmaz.

  4. İkili yama

    Genellikle bir ikili dosyada basit değişiklikler yapabilirsiniz. onaltılık düzenleyici. Örneğin, atlamak istediğiniz bir işlev çağrısı veya dal varsa, bunu genellikle nop talimatlarıyla değiştirebilirsiniz. Büyük miktarda yeni kod eklemeniz gerekiyorsa, ikiliyi yeniden boyutlandırmanıza yardımcı olması için muhtemelen ERESI projesinden elfsh gibi bir şey kullanmanız gerekecektir.

#2
+17
Gilles 'SO- stop being evil'
2013-03-23 19:53:18 UTC
view on stackexchange narkive permalink

Çoğu zaman, bir programın davranışını, ona dikkatlice bağlanarak değiştirebilirsiniz. İstediğiniz işlevselliği bu şekilde ekleyip ekleyemeyeceğiniz, programın nasıl yapılandırıldığına bağlıdır. Programın bir ana yürütülebilir dosya ve birkaç kitaplık biçiminde gelmesi yardımcı olur.

İlk önce LD_PRELOAD ile kendi kitaplığınızı bağlayarak programın paylaşılan kitaplıklara yaptığı herhangi bir çağrıya bağlanabilirsiniz. . foo işlevini tanımlayan bir kitaplık yazın ve başladığınızda LD_PRELOAD ortam değişkenini derlenmiş ( .so ) kitaplığınızın yoluna ayarlayın program: daha sonra program amaçladığı foo 'nuzu çağıracaktır. dlsym() ile bir işaretçi elde ederek orijinal foo işlevini, yerine koyduğunuz yerden çağırabilirsiniz.

İşte birkaç örnek ve öğretici:

LD_PRELOAD:

  • fakechroot, PlasticFS kullanan bazı program örnekleri - program tarafından kullanılan dosya adlarını yeniden yazın
  • Electric Fence, Valgrind - malloc 'u geçersiz kılarak bozuk yığın kullanımını tespit edin
  • Libshape - ağ bant genişliğini sınırlayın
  • KGtk - bir Gtk programında KDE iletişim kutularını kullanın

LD_PRELOAD 'un sınırlaması, yalnızca çalışma zamanında çözülen işlev çağrılarını kesebilmenizdir (dinamik bağlantı ). Dahili bir aramaya müdahale etmek istiyorsanız, daha ağır tekniklere başvurmanız gerekir (yürütülebilir disk üzerinde veya bellek içinde ptrace ile değiştirme).

#3
+7
Michael Anderson
2013-03-23 22:06:39 UTC
view on stackexchange narkive permalink

Mevcut bir ikili dosyaya bazı işlevler eklemek istiyorum.

Dolayısıyla genel olarak bu dört büyük Soru bir Yürütülebilir dosyayı değiştirmek için geçerlidir:

Sorulan ilk temel soru: Program Kod Değişikliklerine karşı ihtiyatlı mıdır (Otomatik Kontrol, Hata Ayıklama Önleme, Kopya koruması, ...)?

Öyleyse:

  1. Bu korumaları kolayca kaldırmak / önlemek mümkün mü (örneğin, paketlenmişse ambalajını açmak)
  2. Bunu yapmak için zaman ayırmaya değer mi?
  3. ol>

    İkinci Soru:
    Yürütülebilir dosyayı üretmek için hangi Derleyicinin / Dilin kullanıldığını öğrenebilir misiniz?

    Daha Fazla Ayrıntı daha iyidir, ancak çoğu temel yapılar ( if ve diğer kontrol yapıları), çeşitli derleyiciler üzerinde oldukça benzer şekilde eşleşmelidir.

    Bu, RE-Stackexchange ile ilgili önceki bir soru ile ilgilidir.


    Kullanıcı arayüzü nasıl uygulanır (CLI, Win32-Pencere Kontrolleri, Özel, ...)?

    Bu biliniyorsa:
    Değiştirmek istediğiniz kullanılan Derleyici / Dil ile birlikte ortak HLL-Yapımlarının (Menüler, Açılır Menüler, Onay Kutuları, ...) eşlemesini bulabilir misiniz?

    Dördüncü ve en büyük Soru şudur:
    Programda istenen işlevselliği nasıl oluşturabilirsiniz?

    Temelde bu, biraz tersine çevrilmesini gerektirebilir mühendislik, programı bozmadan en iyi şekilde nasıl bağlanabileceğinizi öğrenmek için.

    Merkezi Nokta: Mevcut dahili API'leri Hedefinize ulaşmak için, İşleri bozmadan (CRTL + Z, Sürüm Oluşturma, Kurtarma gibi) nasıl kullanabilirsiniz? özellikler)?

  • mevcut Veri yapıları (ve bunlar nasıl ilişkilendirilir?)
  • Mevcut Fonksiyonlar (Parametreler, Parametre-Biçim, ...)
    • Ne işe yarar?
    • Başka ne yapabilir?
    • GERÇEKTEN ne işe yarar?
    • ...
  • mevcut Süreçler (= Program, benzer özellikleri uygulamak için dahili olarak, adım adım nasıl ilerler)
    • Hangi işlevler, hangi sırayla çağrılır?
    • Hangi Veri Yapıları kullanılır?
  • Özelliğin / programın Eti nerede (veriler, örneğin ana boyama alanı ve dahili olarak nasıl ilişkilendirilir?)
  • Şeyler şunlara dikkat edin (istenen özellikle ilgiliyse):
    • Günlük Kaydı
    • Kurtarma Özellikleri
    • Sürüm Oluşturma
  • İstenilen Özellik ile ilgili olan Meta Veriler nasıl işlenir (ör. Perde hızı, f-Duraklar, ...).

Örnek projeler: b>

  • Bir grafik programına yeni bir tür boyama aracı oluşturma (eklenti API'siz).
  • Bir programın eklenti API'sini genişletme.
  • Bir eklenti API'sini bir programa eklemek.
  • Dosyalar için yeni bir kaydetme / dışa aktarma formatı eklemek (çıktı formatını istenen formata dönüştürmenin bir yolu yoksa veya dışa aktarılan f dosyasında önemli bilgiler eksik iles).
  • Yeni bir içe aktarma biçimi eklemek (girdi biçimini içe aktarılabilir bir biçime dönüştürmenin bir yolu yoksa veya bazı bilgiler doğru bir şekilde aktarılmadıysa).
  • Mspaint'i renkli arama ve değiştirme aracıyla genişletme (bir seçim içinde veya tüm resimde)
  • Bir Programa Proxy Desteği / Temel Proxy Kimlik Doğrulaması Ekleme.
  • Ekleme ( yeni) Komut satırı, yeni / mevcut Özellikleri ortaya çıkaran bir programa geçer.
  • Programın İşlemlerini harici olarak Yönetmek için Uzaktan Prosedür Çağrıları için bir API Ekleme
  • Komut Dosyası Desteği Ekleme sık tekrarlanan İşlemleri otomatikleştirmek için (Başlangıçta eklenti / komut dosyası oluşturma API'si yoksa) veya toplu işlemeyi desteklemek için.

Sarılmış Kod & Decompilers ile ilgili: Bir VM / Yorumlayıcı (Py2Exe, Java 2 Exe, ...) ile paketlenmiş veya yüklü olanı (JVM, C #) kullanan diğer Dillerdeki sarılmış Kod hakkında konuşmayacağım. Bu durumlardan bazıları için oldukça iyi Derleyici var. Başarılı bir derlemeden sonra, Kod Gizleme'yi (eğer varsa) yenmekle sonuçlanır.

C / C ++ - Derleyici Çözücülerle ilgili:
C hakkında konuşamam / C ++ - Derleyici çözücüler, Yürütülebilir dosyada başka Koruma olmaması koşuluyla, en iyi çaba için HLL-Yeniden Eşleştirme (Derleyicinin alamadığı şeyler için) ve Kod Gizleme (Semboller olmadan derlenmişse) için kaynatılır.

HLL eşlemesine ilişkin öneri:
Temelde bu Sorunun büyük bir kısmı, "HLL eşlemesi" (Yüksek seviyeli dil eşlemesi (makine kodunda)) bu yapılar ilgili makine kodunda.

Bu Konuda burada (binary-auditing.com) "IDA Free" kullanan mükemmel bir indirilebilir başlangıç ​​kursu buldum.

#4
+7
Ange
2013-03-26 12:49:26 UTC
view on stackexchange narkive permalink

(Biraz modası geçmiş, ancak bu başlıkta daha önce bahsedilmediği gibi)

Uzun zaman önce, bir yazılımı yalnızca ikili programla genişletmek için aylar harcadım.

  • Analiz için IDA ve canlı hata ayıklama için SoftICE kullandım. Hedefi işlem kodu / bayt kodu düzeyinde anlayabiliyorsanız derlemeyi çözmenize gerek yoktur.
  • Ardından, x86 PE ikili olduğu için Tasm ve Iczelion'un Kod Parçacığı Oluşturucusunu : Artık ünlü bir araç değil, ancak Tasm'ı şeffaf bir şekilde kullanmasına ve PE dönüşümleri vb. İle kodu yeniden enjekte etmesine izin verdi ...

    EntryPoint'e kod ekledi, bu yüzden kendi yamalarımı manuel olarak yaptım , sonra orijinal EntryPoint'e atladı.

Şimdi biraz eski moda - bugünlerde muhtemelen bir DLL enjekte ederdim - ama kesinlikle işe yaradı.

Ve en azından ASM aracılığıyla tam kontrol sağlarken, otomatik yamalama yoluyla bakım kolaylığı sağlar.

#5
+6
Andrew
2013-03-23 19:30:43 UTC
view on stackexchange narkive permalink

İkili dosyayı yeniden derlemenize gerek yoktur. Hangi değişiklikleri yapmak istediğinizi anlarsanız ve bu değişiklikler yalnızca ikili dosyayı veya bağımlılıklarını değiştirerek yapılabilir, o zaman bu değişiklikleri diskte veya bellekte yapabilirsiniz.

Değişikliğin kendisini nasıl etkileyeceğiniz konusunda birkaç seçeneğiniz var.

Bağlayıcının ikili çalışmadan önce paylaşılan bir nesneyi yüklemesini sağlamak için LD_PRELOAD kullanabilirsiniz. O zaman diskteki ikili dosyayı değiştirmenize gerek kalmaz. Bu, valgrind'in yaptığı bir türdür, paylaşılan bir nesne olarak yükler ancak daha sonra dinamik ikili enstrümantasyona başlar.

valgrind kullanabilirsiniz. Valgrind, programı dinamik olarak yeniden yazmanıza ve davranışını rastgele değiştirmenize izin verir. Valgrind, araçlarının yürütülürken programı düzenlemesine izin veren dinamik bir ikili enstrümantasyon programıdır. Yalnızca program davranışını değiştirmek istiyorsanız, bu işe yarayabilir, ancak valgrind ayrıca küresel bir yavaşlamaya neden olur ve bir programı yamalamak ve yeniden dağıtmak istiyorsanız, muhtemelen ideal değildir.

Programa yeni kod eklemek için elfsh / eresi gibi araçları da kullanabilirsiniz. Bu araçlar, kodunuzu ELF program başlığı gibi şeylerle ilgili olarak enjekte etme eylemine dikkat etmelidir. Bir "ELF bulaştırıcı" kavramı vardır, burada, enjekte edilen kodunuz yeni program giriş noktası olur, bir şeyler yapar ve sonra eski program giriş noktasına atlar.

#6
+6
0xC0000022L
2013-04-07 03:19:50 UTC
view on stackexchange narkive permalink

Bunu Windows'da yapmak

Bu soru, kişisel olarak benim diğer yanıtlarda belirtildiği gibi kolay LD_PRELOAD yöntemini kullanacağım Linux'a odaklanmış olsa da, Windows benzer bir mekanizma biliyor. aslında daha yakın geçmişte kötüye kullanıldı (ayrıca aşağıdaki alternatif yaklaşımlara bakın). Bir dongle sistemini "kırmak" için bu yöntemi kullandım.

Gir ...

DLL yerleştirme (aka önyükleme, diğer adıyla ele geçirme) saldırıları

Adı, Bu yönteme oldukça yakın bir zamanda, uzak paylaşımlara DLL'leri yerleştirmenin ve ardından bir medya oynatıcı gibi paylaşımlara gitmenin, medya oynatıcısının yerel bir sürüm yerine uzak DLL'yi yüklemesine neden olacağı ortaya çıktı. Bu tasarım gereğidir. Şimdi değiştirmek binlerce olmasa da yüzlerce uygulamayı bozar.

Tek gerçek çözüm uygulama tarafında doğru uygulama olmasına rağmen, bu durum Microsoft tarafından belirli şekillerde ele alınmıştır. Ancak Windows 2000, NT platformunu temel alan ilk tüketici işletim sistemi haline geldiğinden beri pek çok geliştirici NT güvenliğini kavramak zorunda kalmamıza rağmen kavrayamadı bile.

Sizinle ne alakası var? hedef tanımlandı mı?

İşlevsellik eklemek, mutlaka disk üzerindeki yürütülebilir yama uyguladığınız anlamına gelmez. Bunu bellekte de yapabilirsiniz.

Bundan nasıl yararlanabilirsiniz?

Bir uygulama bir DLL kullandığında, Dependency Walker ile yükleme sırasını söyleyebilirsiniz. a> veya bir hata ayıklayıcı altında, içe aktardığı DLL'lerden birini seçip onu değiştirebilir (mevcut konumunda) veya yükleme sırasındaki mevcut DLL'den önce gelen bir yola başka bir DLL yerleştirebilirsiniz.

Bir alternatif yöntem, içe aktarılan DLL'lerin adını değiştirmektir. Nadir durumlarda (örneğin, iyi bilinen DLL'ler) bu, alternatif bir DLL'yi yüklemek için tek uygun yöntemdir ve yine de bazı özel durumlarda başarısız olabilir.

Sınırlamalar

Kullanılan DLL DLL arama sırasının ilk konumunda mevcutsa, içe aktarmayı yukarıda kısaca belirtildiği gibi yeniden adlandırmadığınız sürece, diskteki dosyayı tam anlamıyla değiştirmeniz gerekir.

Uygulamalar

Yalnızca birkaç dışa aktarılan sembol içeren DLL'ler için manuel bir yaklaşım kullanılabilir. En kolayı, DLL'den bir modül tanımlama dosyası oluşturmak ve bundan sadece işlev ileticileriyle bir DLL oluşturmaktır. Bu şekilde yerleştirdiğiniz DLL zaten yüklenir ve aramalardan basitçe geçer.

Ancak, bu yaklaşım dışa aktarılan değişkenlerle (işlevlerin aksine) başarısız olacaktır.

İşte basit bir StackOverflow'da başka bir yanıt için yazdığım pefile tabanlı Python komut dosyası:

  import osimport sysimport redef main (yazım adı): pefile içe aktarmadan PE yazdırma "Ayrıştırma% s"% pename pe = PE (takma ad) modname = os.path.basename (takma adı) libname = re.sub (r "(? i) ^. *? ( [^ \\ /] +) \. (?: dll | exe | sys | ocx) $ ", r" \ 1.lib ", modname) defname = libname.replace (". lib "," .def ") print "% s için modül tanımlama dosyası% s yazılıyor"% (defname, modname) f = open (defname, "w") # atmasını istiyorum, burada karmaşık bir hata işleme yok f.write ("LIBRARY% s \ n \ n "% modname) f.write (" EXPORTS \ n ") pe.DIRECTORY_ENTRY_EXPORT.symbols için exp için numexp = 0: if exp.name: numexp + = 1 f.write (" \ t% s \ n "% exp .name) print "% Yazdı s% d dışa aktarımıyla "% (defname, numexp) print" \ n \ nBunu dışa aktarma kütüphanesini oluşturmak için kullanın: \ n \ tlib / def:% s / out:% s "% (defname, libname) __name__ == '__main__': eğer len (sys.argv)! = 2: sys.stderr.write ("ERROR: \ n \ tSyntax: fakelib <dllfile> \ n") sys.exit (1) sys.exit (main (sys.argv [1]))  

Dışa aktarılan adlara sahip basit bir modül tanımı yerine işlev ileticileri oluşturmak için bunu ayarlayabilirsiniz.

Yani bu kodunuzu hedef uygulamaya aktarmanın ve oradan gitmenin yolu.

Alternatif yaklaşımlar

Enstrümantasyon ve kancadan daha önce bahsedilmişti. Detours, çoğu pratik amaç için uygunsuz bir EULA ile kancaya sıkça bahsedilen bir örnektir. Bu tür bir yaklaşım için mevcut yanıtlara bakın.

Bir DLL'yi erkenden enjekte etmek için AppInit_DLL kayıt defteri değerini de kullanabilirsiniz. Veya bir hata ayıklayıcı döngüsüyle küçük bir başlatıcı yazabilir ve hedefinizin önce hata ayıklayıcınızı başlatmasını sağlamak için Görüntü Dosyası Yürütme Seçenekleri kullanabilirsiniz. Bir hata ayıklayıcı, DLL yüklemesini de etkileyebilir veya çalıştırılabilir ve DLL'ler arasındaki sınırdaki çağrıları kolayca yakalayabilir.

Diğer bilgiler: Bu ( Görüntü Dosyası Yürütme Seçenekleri ) nasıl olur? Process Explorer içindeki seçeneği belirlediğinizde Görev Yöneticisi'nin yerine geçer.


Bu yaklaşımları Ed McMan'ın cevabında bahsettiği kategorilere nasıl ayırabileceğinizi göreceksiniz. Ancak bunu bir alıştırma olarak okuyucuya bırakacağım :)

#7
+3
jyz
2013-03-23 20:36:48 UTC
view on stackexchange narkive permalink

Bunu Windows'ta Notepad.exe ile yaptım. Calc.exe'yi sadece eğlence için açmak için bir üst menü öğesi eklemek istedim (Sorunuzun Linux ve gcc derleyicisi olarak etiketlendiğini biliyorum, ancak fikir muhtemelen aynıdır).

Bu yüzden Calc menüsünü eklemek için Kaynak Hacker aracı ve Immunity Debugger 'da notepad.exe'yi açtı ve WinExec kabuk kodumu koyabileceğim kodda biraz boşluk aradı. Başlangıçta yürütülebilir dosyayı değiştirmedim, not defteri çökmesine neden olmadan montaj talimatlarımı yapıştırabileceğim bir yer bulmak için programa bellekte bakmam gerekti.

Yeterli alan bulduğumda (orijinal kodu değiştirerek bazı gerekli olmayan montaj talimatlarını ortadan kaldırarak veya hatta optimize ederek) XVI Hex Editor üzerinde notepad.exe'yi açtım ve Immunity üzerinde çalışan işlem kodlarını aradım. Demek istediğim, hata ayıklayıcı bazı işlem kodlarını çalıştırıyordu değil mi? Değiştirmek istediğim yazılımın doğru parçasında olduğumdan emin olmak için bir dizi işlem kodu aradım ve onu kabuk kodumla hızlandırdım (şimdi bu montaj kodu değil, "derlenmiş" montaj - makine kodu)

Tekrar: Sorunuzun Linux ve gcc derleyicisi olarak etiketlendiğini biliyorum, ancak belki birisi Linux'ta Windows'ta yaptığımın aynısını elde etmek için bazı araçları gösterebilir. Fikir muhtemelen aynı.

#8
+1
Peter Teoh
2014-11-15 13:38:19 UTC
view on stackexchange narkive permalink

"ptrace ()" Giles tarafından gelişigüzel bir şekilde bahsedilmiştir. Ama başlı başına bir bölümü hak ettiğini düşünüyorum. "ptrace ()", başka bir işlem üzerinde hata ayıklama denetimi uygulamak için işletim sistemi (Linux ve tüm UNIX'lere sahiptir ve Windows da vardır) tarafından sağlanan bir sistem çağrısı API'sidir. PTRACE_ATTACH'ı (ptrace () işlevinin bir parçası olarak) başka bir işleme iliştirmek için kullandığınızda, çekirdek bu işlemi çalıştıran CPU'yu tamamen duraklatacak ve sürecin HERHANGİ BİR bölümünde değişiklik yapmanıza izin verecektir: CPU, herhangi bir kayıt, bunun herhangi bir parçası işlem belleği vb. Dinamik satır içi kancalama bu şekilde çalışır. (ptrace () iliştirin, ikili bellek içinde değişiklik yapın ve ardından ptrace () bağlanmadan). Bildiğim kadarıyla, başka bir sürecin tüm dinamik modifikasyonlarının ptrace () kullanması gerekiyor - çünkü bu noktada sistem çağrısı yoluyla bütünlüğü garanti etmek için çekirdek tarafından sağlanan tek mekanizma bu.

Ancak son zamanlarda benzer API utrace () ortaya çıkıyor ve bu nedenle satır içi bağlantı teorik olarak da mümkün:

http://landley.net/kdocs/ols/2007/ols2007v1-pages-215-224.pdf

Kernel hooking için pek çok yöntem vardır: syscall, interrupt ve inline hooking. Bu, kesintiye uğramak için:

http://mammon.github.io/Text/linux_hooker.txt



Bu Soru-Cevap, otomatik olarak İngilizce dilinden çevrilmiştir.Orijinal içerik, dağıtıldığı cc by-sa 3.0 lisansı için teşekkür ettiğimiz stackexchange'ta mevcuttur.
Loading...