ghidra disassembler sorunu

taydin

Timur Aydın
Staff member
Katılım
24 Şubat 2018
Mesajlar
23,776
Bir haftadır ghidra ile bir binary inceliyorum. Kullanılan string'lerde de şöyle bir tuhaflık var: ilgili kod, string'i başından itibaren kullanmıyor da 4. karakterden itibaren kullanıyor

1730099031746.png


Başka yerlerde bu offset 8. Hatta 24 e kadar çıktığı yerler var

1730099095144.png


Bundan da abzürt bir durum var. Aynı string'i farklı fonksiyonlar farklı yerlerinden yakalamış. Sadece listedeki son fonksiyon string'i olması gerektiği gibi başından itibaren kullanıyor. Hatta AYNI fonksiyon içinde de iki farklı yerinden yakalanmış string!

1730099545269.png
 
Artık ghidra disassembler'dan şüphelenmeye başladım. Kullanılan instruction set ARMv5t, ama v8 de denedim, v5 de denedim sonuç hiç değişmiyor.
 
Mesela şu string

1730100171761.png


İlgili kod spesifik olarak string'in ortalarından bir yerden alıyor.

1730100261600.png


Bütün string'lerde bu durum yok. İstatistiğini bilmiyorum birçok doğru yerden adresi alınan string de görüyorum yanlış alınan da görüyorum. Her zaman hata 4 ün katı da değil. Bazan 2 kayma da olabiliyor.
 
Hani eğer bütün string'lerde kayma tam olarak aynı olsaydı, o zaman diyecektim ki belki programın ayrı bellek bölgesi var, ayrı olarak yükleniyor, ve yükleme adresi yanlış. Ama öyle değil. Kayma olmayan da var, çok büyük kayma olan da var ...
 
Yaklaşık bir yıl önce avr risc tabanlı bir binary dosyadan bir algoritma çıkartmak için ghidra da kullanmıştım. Binary dosyanın bazı kısımlarını decompile edemiyordu.
Ghidra ve birkaç farklı tool ile ilgili algoritmayı çıkarmayı başarmıştım.

Kaymanın nedeni decompile işleminin %100 başarı ile yapılamamış olması olabilirmi?
 
İki ihtimal var bana göre: Ya ghidra kodu yanlış disassemble ediyor, yada adamlar kodun içine tersine mühendisliği engelleyecek tedbirler koydular. Mesela dosya NAND'den RAM'e yükleniyor, sonra da bir tabloda yer alan direktiflere göre koddaki bütün string referanslar olması gereken yerlere getiriliyor, sonra program çalışmaya başlıyor olabilir.
 
kodu gizlemek istesem en azından böyle bir ip ucu bırakmam. basitce tüm string literalleri xor ile kodlarım. bunları alıp kullanırken de o aşamada tek bi fonksiyon ile decode ederim. armV5 için obfuscation teknikleri nelermiş bir bakmak lazım.
 
ARM islemci ayni veri alanina program alaninin farkli yerlerinden erismek isterse adres hesabinda farklilik oluyor.

Benim disasm yeterince test edilmedi ama onunla bakmayi denedin mi?
 
IDA pro ile de aynı şey oluyor

1730105298388.png
 
ARM islemci ayni veri alanina program alaninin farkli yerlerinden erismek isterse adres hesabinda farklilik oluyor.

Benim disasm yeterince test edilmedi ama onunla bakmayi denedin mi?

Bütün adreslemeler öyle zaten. Disassembler nihai olarak hesaplanan adresi "hint" olarak gösteriyor.

Deneyeyim, Nereden indiriyorum?
 
Yukarıdaki çıktıdaki adrese bakabilirsin.
 

Ekler

  • DP800Update_descrambled_GEL.zip
    1.1 MB · Görüntüleme: 13
Bundaki ARM core ARM926EJ-S. Komut seti de ARM v5TE. Yani Cortex'lerden daha eski. Zaten şu anda obsolete.
 
Benim asıl yapmak istediğim iş, elimdeki elektronik yükü kalibre etmek. SCPI komutlarını binary'deki string'lerden belirledim. Komut argümanları belirlemek için de ilgili string hangi fonksiyonda işleniyor onu bulsam iş bitecek. Ama ilgili string'lere hiç referans yok. Yakınında bile yok. Bir şekilde string adreslerini program dinamik bir şekilde hesaplıyor olmalı. Program da çok büyük, bütün fonksiyonları analiz etme şansım da yok.
 
Dedigim gibi olma ihtimali cok yuksek. Su anda decode islemlerini hatirlamiyorum fakat ayni adrese program alaninin farkli yerlerinden erisirken kod uzantisi adres farkli olabiliyordu.
 
Opcode farklı olacak zaten. Listinge de bakarsan farklı. Ama nihai adresin string başı olması lazım ve değil.
 
Programin bir bolumunde

LDR R1,=XXX gibi bir komut olsun.

Burada XXX stringin adresi olsun.

Opcode icinde bu xxx degeri, stringin adresini gostermez zaten opcode icine bitlerin arasina sikismis durumda. Bu xxx, komutun bulundugu adresden itibaren stringin adresinin yazili oldugu adresi gosterir.

Program buyudukce xxx adresi lazim oldukca bu adreslerin yazili oldugu havuza gore ofset hesaplanr ve kullanilir.

Bu havuza programda benzer adresler yazilir ve yer kalmaz bir baska havuz acilir.
Lazim oldugunda o havuza ayni adres bir daha yazilir. Fakat ayni komut LDR R1,=XXX de opcode da XXX degeri degisir.

Sonucta disasm gosterimde bu benim de kafami karistirdi cunku baktigimda hedef adresi goremeyecektim. Sirf bunun icin gosterim kismini Keil disasm gosterimine gore daha iyi yaptim (Kendimce/kendi dusunceme gore). Keil de dogru adresi dolayli gosteriyor. Fakat benim DISASM de gosterim kisminda dogrudan bunu gosteriyorum.
Dolayisi ile ortada hata falan yoktur.


LDR R1=xxx ; burada xxx in adresi degil HAVUZdaki xxx adresi yazan adresi yazar.
.....
.....
.....

HAVUZ
xxx adresi burada yazar.

Programa ekle cikar yaptikca LDR R1=xxx deki xxx degeri sasar. Ama hesaplanirsa dogru degeri gosterir.

LDR R1=xxx R1=xxx anlamina gelir.

Fakat assembler derleyici xxx yazmaz R1=[PC+N] islemine ait kod yazar. Disasm de aynini tersden yapar.

Asagida LDR immediate'in bir tipi icin yazdigim disasm kod parcasi var.

Kod:
function Tform1.LDR_____0xF85F0000(CodeLen:byte):boolean;  // LDR (literal) T2 (289)
var Rt, u, imm12, imm32, Data:integer;
begin

       Rt:=(Code32 shr 12) and $F;
       u:=(Code32 and $800000) shr 23;
       imm12:=(Code32 and $FFF);

       if (Rt=15) AND InITBlock() AND NOT LastInITBlock() then unpredictable:=true;

       if u=1 then imm32:=AlignPC(Index,4)+imm12  //Sayfa 290
       else imm32:=AlignPC(Index,4)-imm12;

       imm32:=imm32+4; // Sayfa 290 ile Keil uyusmuyor 4 eklemeyi ben getirdim. !!!!!
       Data:=Get32(Imm32);

//     Memory'den veri okunduguna gore Flash'daki DCD ile tanimli data okunuyor olabilir.
//     PC ile buralardan gecmemek icin bu adresi ve veriyi saklayalim

       Komut:=Susle('LDR',0)+RegName(Rt)+', ='+Hex(Data,32,'0x',true);
       if Degistir then DatayiIsaretle(imm32, Data, 4);
       result:=Ilerle(CodeLen);
       Type2Komut:=Susle('LDR',0)+RegName(Rt)+', [PC+'+OzelHex(imm32-4,'',1)+']';      
end;
 
Son düzenleme:
İşte bu anlattıklarının hepsini hem ghidra hem ida yapıyor ve nihai adresi gösteriyor. Böylece senin bunları adım adım yapmana gerek kalmıyor.
 

Çevrimiçi personel

Çevrimiçi üyeler

Forum istatistikleri

Konular
6,811
Mesajlar
116,026
Üyeler
2,772
Son üye
Burhan Öz

Son kaynaklar

Son profil mesajları

hakan8470 wrote on Dede's profile.
1717172721760.png
Dedecim bu gul mu karanfil mi? Gerci ne farkeder onu da anlamam. Gerci bunun anlamini da bilmem :gulus2:
Lyewor_ wrote on hakan8470's profile.
Takip edilmeye başlanmışım :D ❤️
Merhaba elektronik tutsakları...
Lyewor_ wrote on taydin's profile.
Merhabalar. Elektrik laboratuvarınız varsa bunun hakkında bir konunuz var mı acaba? Sizin laboratuvarınızı merak ettim de :)
Back
Top