thread_44.sh

Capstone Disassembler ve PEFile ile Çapraz Referansları Belirleme

0 replies 2 views {"en": "Reverse Engineering", "tr": "Tersine Mühendislik", "ru": "Реверс-инжиниринг"}
0ffset.net
0ffset.net
OP
user
2024-04-30 05:37:00

Bu yazıda, tersine mühendislikte genellikle yararlı olan Python modüllerini kullanarak çapraz referansları programlı olarak nasıl bulabileceğinizi açıklayacağım. Gördüğünüz gibi bu benim 0ffset'teki ilk paylaşımım olacak ve bu konuyu yazma fikri 0verfl0w'dan ilham aldıktan sonra aklıma geldi.postyığın dizelerini çözmek için Capstone ve Unicorn'un kullanılması ve Capstone'un belirli bir kod bitindeki işlevlere çapraz referanslar bulma yeteneği veya bunun eksikliği hakkında tartışılması. Bundan yola çıkarak çimlere dokunmaya kısaca ara vermeye ve bunun nasıl yapılabileceğine dair bir gösteri yapmaya karar verdim.😎

Bu yazıyı okuduktan sonra, PE formatı hakkında biraz daha iyi bir genel anlayışa sahip olmanın yanı sıra, işlem kodlarının Assembly'de nasıl çalıştığı hakkında bilgi sahibi olabilirsiniz. Ayrıca, dize şifre çözücüler oluşturmak veya benzer amaçlarla kullanmak istiyorsanız, kodun herhangi bir bölümünü kullanabilir ve ona referans verebilirsiniz.

Bu yazıda aşağıdaki Python modüllerini kullanacağız:

  • kapak taşı – bu modül, ikili analiz için en üst düzeyde ayrıştırma motoru olarak ismine yakışır ve bugün gördüğünüz birçok RE aracının kalbinde yer alır; örneğinTek boynuzlu at, Qilingand Angr.
  • dosya – bu modülü bölümleri, başlıkları ve bunların yapı üyelerini programlı olarak ayrıştırmak için kullanacağız.
  • yapı – bu modül Python değerleri ile Python olarak temsil edilen C yapıları/türleri arasında dönüşüm yapmak için kullanılabilir bytes nesneler.

PE dosyasının mimarisini keşfetme

Taşınabilir bir yürütülebilir dosyanın derlenmiş kodunu yorumlarken Windows yükleyicinin yaptığı ilk şeylerden biri, mimarisini belirlemektir. Microsoft'un sahip olduğudokümantasyonsabitleri belirten ikili dosyanın makine tipini bulma konusunda IMAGE_FILE_MACHINE_I386 (0x14c) Ve IMAGE_FILE_MACHINE_AMD64 (0x8664).

Bunu da bulmak istiyorsanız pefile modül, aşağıya başvurabilirsiniz:

Senaryomuzda ikilinin mimarisini bu sabitlerle eşleştirip kurulumu yapardık. capstone buna göre.

match f.FILE_HEADER.Machine:
    case 0x14c: # IMAGE_FILE_MACHINE_I386
        md = Cs(CS_ARCH_X86, CS_MODE_32)
    case 0x8664: # IMAGE_FILE_MACHINE_AMD64
        md = Cs(CS_ARCH_X86, CS_MODE_64)

Bölüm Özelliklerini Bulma

Çoğu durumda, birbölümÇalıştırılacak kodu içeren bir dosya, sabit kullanılarak, özellikleri aracılığıyla çalıştırılabilir olarak işaretlenir. IMAGE_SCN_MEM_EXECUTE (0x20000000).

Bu örnekte PE Viewer, bölümün kod olarak yorumlanacağını ve okunabilir ve çalıştırılabilir olduğunu ortaya koyuyor (RX) izinler (diğer araçlar gibi)CFF Gezgini, Kolayca Algılayın, PE Ayı and PE Stüdyosubu amaçla da kullanılabilir).

Aracı diğer ikili dosyalarla işlevsel hale getirmek için şunu kullanabiliriz: bit düzeyinde VE Bu bayrağı içeren bölümlere odaklanmak için operatör. Programlama dillerinde bitsel operatörleri kullanmaya aşina değilseniz, bu durumda bu esas olarak iki sayıda aynı konumu işgal eden bit çiftini yazdırarak "yürütülebilir" bayrağının mevcut olup olmadığını bulmak için kullanılıyor. Değilse, bu, dönüş değeriyle sonuçlanır 0x0. Ayrıca fark ettiyseniz, tüm karakteristik değerler belgelerle eşleşmez, çünkü bunlar bir araya toplanır ve sonuç bunun yerine toplam izinler olur. Bu durumda, aşağıdaki toplamı elde ederiz:0x00000020, 0x20000000 and 0x40000000sırasıyla:

IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ

Bit maskelerinin nasıl çalıştığını daha iyi anlamak için buna göz atabilirsiniz. madde.

İşte kullanacağımız sonuçtaki Python kodumuz:

if (section.Characteristics & 0x20000000):

Çağrı Anımsatıcılarını Bulma

Buna göre dokümantasyoncall mnemonic'in birden fazla işlem kodu vardır. İşlem koduna bağlı olarak bunlar aynı zamanda farklı anlık türlere de yol açabilir (WORDs, DWORDvb.) argüman olarak kullanılıyor. Dikkat edilmesi gereken önemli bir nokta, işlenendir. call aradığımız anımsatıcı, o adresten gelen bir sonraki talimata göre yer değiştirmeyi veya daha basit bir ifadeyle, işlev kodunun başlangıcını bulmak için gereken bayt sayısını tutar. Bu çağrının göreceli uzaklığını çıkardıktan sonra, bunu fonksiyon adresini hesaplamak için kullanabiliriz.

Bunu yapabilmek için doğru adreslerin ve boyutların verileri ayrıştırabilmesini de isteriz. PE Studio'da bölümün başlangıcını görebiliriz (yani VirtualAddressdeğerini tutan 0x1000) boyutuyla birlikte 0x7600 (30208 bayt), hangi üye adıdır? SizeOfRawData (referans).

Aşağıdaki kodu kullanarak, aşağıdaki kodu içeren tüm satırları bulabilir ve yazdırabiliriz. call anımsatıcı:

for i in md.disasm(section.get_data(), 0, section.SizeOfRawData):
    if i.mnemonic == "call":
        print(i)

Çalıştırıldıktan sonra aşağıdaki sonuçları göreceğiz:

Windows API işlevlerine adresleri depolayan bellek konumlarına işaretçiler içerdikleri için tüm mutlak dolaylıcall satırları kaldırmak isteriz. Bunlar daha sonra bellekte çözümlendikten sonra örnek tarafından kullanılır. Geliştiricinin yazdığı fonksiyonlara çapraz referans vermek istediğimizden ve işaretçileri tutmak kodumuzda hatalara neden olacağından amacımız bu değil. Bunu önlemek için, tüm callanımsatıcıların özellikle 0xe8 opcode'u kullanmasını sağlayarak bu satırı geliştirebiliriz:

if i.mnemonic == "call" and i.bytes[0] == 0xe8:

Dikkat edilmesi gereken başka bir nokta da işlenenlerin hemen bir Python tamsayısına dönüştürülememesidir. Sadece iyi bir fikir vermek için aşağıdaki ekran görüntüsünde bunu yapmayı denedim:

...



⚠️ Bu konu 0ffset.net botu tarafindan otomatik olarak ice aktarilmistir.

🔗 Kaynak Baglantisi: https://www.0ffset.net/reverse-engineering/identifying-xrefs-with-capstone/

Thread Statistics

Views 2
Replies 0
Author 0ffset.net
Created 2024-04-30
Status
Open