Soru:
"Üst üste gelen talimatlar" gizlemesi nedir?
perror
2013-04-03 13:11:29 UTC
view on stackexchange narkive permalink

Bazı şaşırtma hilelerini kullanarak x86 / x86-64'teki bazı ikili dosyaları analiz ettim. Birine çakışan talimatlar deniyordu. Birisi bu gizlemenin nasıl çalıştığını ve nasıl çözüleceğini açıklayabilir mi?

Bunun için uygun terimin ne olduğunu merak ettim. Oldukça sık kullanılan 'talimat kesmesi' duydum.
Bu teknik hakkında konuşmanın birkaç yolu ile karşılaşıyorum. Ancak, hiçbirinin topluluk tarafından genel olarak benimsenmediği doğrudur. Şu andan beri bulabildiğim en çok "_ Örtüşen Talimatlar_" oldu. Ancak, bu konudaki mevcut belgelerin sadece küçük bir bölümünü okumuş olabilirim.
Dört yanıtlar:
#1
+28
Remko
2013-04-03 13:25:43 UTC
view on stackexchange narkive permalink

x86 Yürütülebilir Dosyalarının Statik Analizi raporu, örtüşen talimatları oldukça iyi açıklıyor. Aşağıdaki örnek buradan alınmıştır (sayfa 28):

  0000: B8 00 03 C1 BB mov eax, 0xBBC103000005: B9 00 00 00 05 mov ecx, 0x05000000000A: 03 C1 add eax, ecx000C : EB F4 jmp $ -10000E: 03 C3 add eax, ebx0010: C3 ret  

Koda bakıldığında, dönüş talimatında eax değerinin ne olacağı belli değil ( veya bu konuda iade talimatına ulaşıldığını). Bunun nedeni, listede açıkça bulunmayan bir adres olan 000C'den 0002'ye atlamadır (jmp $ -10, 0xC ve 0xC10 = 2 olan geçerli program sayacı değerinden göreceli bir sıçramayı belirtir). Bu atlama, kontrolü 0000 adresindeki beş bayt uzunluğundaki hareket talimatının üçüncü baytına aktarır. 0002 adresinde başlayan bayt dizisinin yürütülmesi, tamamen yeni bir talimat akışını açar:

  0000: B8 00 03 C1 BB mov eax, 0xBBC103000005: B9 00 00 00 05 mov ecx, 0x05000000000A: 03 C1 add eax, ecx000C: EB F4 jmp $ -100002: 03 C1 add eax, ecx0004: BB B9 00 00 00 mov ebx, 0xB90009: 05 03 C1 EB F4 add eax, 0xF4EBC103000E: 03 C3 add eax, ebx0010: C3 ret  

Ida Pro'nun ve özellikle Hex Rays eklentisinin bunu işleyip işlemediğini / nasıl işlediğini bilmek ilginç olurdu. Belki @IgorSkochinsky bu konuda yorum yapabilir ...

#2
+16
Ange
2013-04-08 19:47:54 UTC
view on stackexchange narkive permalink

"Ortadan atlama" numarası olarak da bilinir.

açıklama

yürütme kuralları

  • çoğu talimat birden fazla bayt alır kodlanmaları
    • modern CPU'larda 15 bayta kadar sürebilir
  • izinler geçerli olduğu sürece yürütme herhangi bir konumda başlayabilir

bu nedenle, bir talimatın ilkini izleyen herhangi bir bayt, başka bir talimatı başlatmak için yeniden kullanılabilir.

sökücüleri kötüye kullanma

  • düz sökücüler Bir sonraki talimat sonuncunun sonundan hemen sonra.

Bu nedenle bu tür sökücüler (akışı takip etmeyenler) ortadaki talimatı gizler

örnekler

önemsiz

  00: EB 01 jmp 302: 68 c3 90 90 90 push 0x909090c3  

  00: EB 01 jmp 303: C3 retn ...  
ilk jmp ilk baytı 68 (anında bir itmeyi kodlar).

birden fazla örtüşme

bu örnekten 69 84 , 11 bayta kadar alabilen bir imul talimatını tanımlar. Böylece, 'sahte' işlenenlere birkaç talimat satırı sığdırabilirsiniz.

  00: EB02 jmp 402: 69846A40682C104000EB02 imul eax, [edx + ebp * 2 + 0102C6840], 0x002EB00400D: ... .  

aslında şu şekilde yürütülecektir:

  00: EB02 jmp 404: 6A40 push 04006: 682C104000 push 0x40102C0B: EB02 jmp 0xF0F: ...  

komut kendisiyle örtüşüyor

Komut kendisinin 2. baytında atlıyor:

  00: EBFF jmp 102: C0C300 rol bl, 0  

aslında şu şekilde yürütülecektir:

  00: EBFF jmp 101: FFC0 inc eax03: C3 retn  

farklı CPU modları

bu şaşırtma aynı EIP'ye atlamak için genişletilebilir, ancak farklı CPU modunda:

  • 64b CPU hala 32b komutunu destekliyor
  • 64b modu cs için 0x33 kullanıyor
  • bazı talimatlar yalnızca belirli bir modda kullanılabilir:
    • arpl 32b modunda
    • movsxd 64b modunda

böylece aynı EIP 'ye ancak farklı bir CS ile atlayabilir ve farklı talimatlar alabilirsiniz.

Bu örnekte, bu kod ilk olarak 32b modunda çalıştırılır:

  00: 63D8 arpl ax, bx02: 48 dec eax03: 01C0 add eax, eax05: CB retf  

ve sonra şu şekilde 64 bit modunda yeniden çalıştırıldı:

  00: 63D8 movsxd rbx, eax02: 4801C0 rax ekle, rax05: CB retf  

Bu durumda, farklı bir EIP nedeniyle değil, CPU geçici olarak 32b'den 64b moduna değiştiği için talimatlar çakışıyor.

Herhangi bir büyük işletim sisteminde kullanıcı alanında çalışan bir program olarak 32'den 64-bit moduna geçmek mümkün müdür?
@Dougall evet. Windows'ta bu, X86SwitchTo64BitMode () tarafından (veya segment seçici 33 ile bir uzak arama / atlama ile manuel olarak) yapılır. Ancak bunun Windows WOW64 uygulamasına özgü olduğundan ve başka bir işletim sisteminde uygulanamayacağından oldukça eminim.
@Ange, https://code.google.com/p/corkami/source/browse/trunk/src/CoST/CoST.asm?r=1593#2247 bağlantısını güncelleyebilir misiniz? Teşekkür ederim!
#3
+8
joxeankoret
2013-04-03 14:19:39 UTC
view on stackexchange narkive permalink

Hemen hemen tüm çok baytlı talimatlar, x86 / x86_64'te çakışan bir talimat olarak kullanılabilir. Nedeni çok basit: x86 ve x86_64 komut setleri CISC'dir. Bu, diğer şeylerin yanı sıra, talimatların sabit bir uzunluğa sahip olmadığı anlamına gelir. Bu nedenle, talimat değişken uzunlukta olduğundan, bu makine kodunu dikkatlice yazdığından, her talimat üst üste binen talimatları gizlemeye yatkındır.

Örneğin, aşağıdaki kod verildiğinde:

  [ 0x00408210: 0x00a31e10] > b0x000050f5 (01) 56 PUSH ESI 0x000050f6 (04) 8b742408 MOV ESI, [ESP + 0x8] 0x000050fa (01) 57 PUSH EDI 0x000050fb (03) c1e603 SHL58000 ESI + 0x40a058] 0x00005104 (01) 57 PUSH EDI 0x00005105 (06) ff15f4804000 ÇAĞRI 0x004080f4; 1 KERNEL32.dll! GetModuleHandleA0x0000510b (02) 85c0 TEST EAX, EAX 0x0000510d (02) 750b JNZ 0x0000511a; 2 

Son komuttan sonra bir yerde, örneğin, MOV ESI'deki 2. bayta olduğu gibi, görüntülenen kodda bazı talimatların ortasında bir atlama olduğunu varsayalım ... talimat:

  [0x000050f7: 0x00405cf7] > c0x000050f7 (02) 7424 JZ 0x0000511d; 1 0x000050f7 ------------------------------------------------ ---------------------- 0x000050f9 (03) 0857c1 VEYA [EDI-0x3f], DL 0x000050fc (02) e603 OUT 0x3, AL  

Görünüşe göre bu komut bir JZ'ye dönüşüyor. Hangisi geçerlidir. 3. bayta atlanıyor ...

  [0x000050f7: 0x00405cf7] > s +1 [0x000050f8: 0x00405cf8] > c0x000050f8 (02) 2408 VE AL, 0x8 0x000050faI (01) P57 (03) c1e603 SHL ESI, 0x3 0x000050fe (06) 8bbe58a04000 MOV EDI, [ESI + 0x40a058]  

CALL talimatının 2. baytına atlama:

  [0x000050f5: 0x00405cf5] > s 0x5106 [0x00005106: 0x00405d06] > c0x00005106 (05) EA, 0xsolgt c0x00005106 (05) EAX4804000 ADC '\ x8e \ x91'0x0000510b (02) 85c0 TEST EAX, EAX 0x0000510d (02) 750b JNZ 0x0000511a; 1 

Gördüğünüz gibi, hemen hemen her çok baytlı talimat, örtüşen bir talimat olarak kullanılmaya müsaittir.

Bu ters çevirmeyi önleme hilesi, genellikle akış grafiğini bozmak için opak tahminler.

Yani, böyle bir liste oluşturmanın bir yolu olmadığını mı söylüyorsunuz? X86 / x86-64 işlem kodlarıyla ilgili beni çok şaşırtan bir diğer nokta da, bir süre sonra orijinal talimat akışıyla yeniden senkronize etme kapasitesidir. Bu özellik, aynı zamanda komutların örtüşmesini sağlamada çok yardımcı olur. Yine de, yeniden senkronizasyonun neden bu kadar güzel çalıştığını bilmiyorum.
#4
+3
Dougall
2013-04-08 20:16:04 UTC
view on stackexchange narkive permalink

x86 komutları herhangi bir uzunlukta olabileceğinden ve hizalanmaları gerekmediğinden, bir talimatın anlık değeri tamamen başka bir talimat olabilir. Örneğin:

  00000000 0531C0EB01 add eax, 0x1ebc03100000005 055090EB01 add eax, 0x1eb90500000000A 05B010EB01 add eax, 0x1eb10b00000000F EBF0 jmp kısa 0x1  

Bu tam olarak söylediği şeyi yapıyor , atlayana kadar. Atladığında, eax'a eklenen anlık değer bir talimat haline gelir, dolayısıyla kod şöyle görünür:

  00000000 05 db 500000001 31C0 xor ax, ax xor ax, ax00000003 EB01 jmp short 0x600000005 05 db 500000006 50 itmeli balta itme ax00000007 90 nop00000008 EB01 jmp kısa 0xb0000000A 05 db 50000000B B010 hareketli, 0x10 hareketli, 0x10 ....  

Gerçekte önemli olan talimatlar sağda gösterilmiştir - el sütunu. Bu örnekte, talimatın add eax bölümünü ( 05 ) atlamak için kısa atlama talimatları kullanılmıştır. Bunun, 05 'leri yemek için tek bayt kullanılarak, cmp al, 0x5 olan 3C05 gibi daha etkili bir şekilde yapılabileceğine dikkat edilmelidir. kod> ve bayrakları umursamayan kodda zararsız olur.

Yukarıdaki desende, tüm 05 'leri 90 (nop). Bu, 05 'leri gizli koda (yürütmenin bağlı olduğu) anlık değerler olarak kullanarak daha zor hale getirilebilir. Gerçekte, kodu gizleyen kişi muhtemelen add eax 'ı tekrar tekrar kullanmayacaktır ve izlenmesi daha karmaşık hale getirmek için yürütme sırasını değiştirebilir.

Yukarıdaki kalıbı kullanarak bir örnek hazırladım. Bu, base64'te 32 bitlik bir Linux ELF dosyasıdır. Gizli kodun etkisi execve ("// usr / bin / python", 0, 0) çalıştırıyor. SE cevaplarından rastgele ikili dosyalar çalıştırmamanızı öneririm. Bununla birlikte, sökücülerinizi test etmek için kullanabilirsiniz. IDA Hopper ve sana IDA doğru bir şekilde bunu yapmak için alabilirsiniz hayal olsa hepsi ilk bakışta sefil başarısız objdump.

  f0VMRgEBAQAAAAAAAAAAAAIAAwABAAAAYIAECDQAAAAoAQAAAAAAADQAIAABACgAAwACAAEAAAAAAAAAAIAECACABAgUAQAAFAEAAAUAAAAAEAAAAAAAAAAAAAAAAAAABTHA6wEFUJDrAQWwEOsBBffg6wEF9 + DrAQWJw + sBBbRu6wEFsG / rAQX34 + sBBbRo6wEFsHTrAQVQkOsBBbR56wEFsHDrAQX34 + sBBbQv6wEFsG7rAQVQkOsBBbRp6wEFsGLrAQX34 + sBBbQv6wEFsHLrAQVQkOsBBbRz6wEFsHXrAQX34 + sBBbQv6wEFsC / rAQVQkOsBBTHJ6wEF9 + HrAQWJ4 + sBBbAL6wEFzYDrAelN //// AC5zaHN0cnRhYgAudGV4dAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACwAAAAEAAAAGAAAAYIAECGAAAAC0AAAAAAAAAAAAAAAQAAAAAAAAAAEAAAADAAAAAAAAAAAAAAAUAQAAEQAAAAAAAAAAAAAAAQAAAAAAAAA =  kod> 


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...