Kysymys:
Segmentit IDA: ssa. Kuinka voittaa NONAME-ongelma
ScumCoder
2014-08-13 19:20:53 UTC
view on stackexchange narkive permalink

Purkan pakatun 16-bittisen DOS MZ EXE: n.

Hämärtääksesi sen, olen asettanut DOSboxiin katkaisupisteen purkamisrutiinin lopussa, antanut sen käydä ja tehnyt muistin kaataa. Näin sain olennaisesti epämääräisen EXE-kuvan.

Ongelmat alkoivat, kun latain kuvan IDA: han. En ymmärrä IDA: n käsitystä segmenteistä. Ne ovat samanlaisia ​​kuin x86-segmentit, mutta on olemassa lukuisia eroja, joita en voi ymmärtää. Kun IDA pyysi minua luomaan ainakin yhden segmentin, tein vain yhden valtavan segmentin, joka on 1 Mt, koska ohjelman osoitetilassa oleva koodi ja data ovat sekoitettuja, eikä ole järkevää ottaa käyttöön erillisiä segmenttejä, kuten CODE , DATA jne.

IDA: n syöttökohdan näyttämisen jälkeen kaikki toimi hyvin: IDA: n toiminnot, paikalliset muuttujat, argumentit jne. on onnistunut. Ainoa ongelma on, että jotkut puhelut on merkitty nimellä NONAME , vaikka ne osoittavat oikeisiin aliohjelmiin. Oudoin on, että näillä aliohjelmilla on oikeat XREF-tiedostot "laittomiin" puheluihin. Tässä on esimerkki:

  seg000: 188FF 004 puhelu 1AD9h: 1; Soittomenettely  

Tämä rivi on punainen ja siihen liittyy ongelma-luettelossa oleva NONAME -ongelma. Miksi?

1AD9h: 1 seg: offset-osoite vastaa lineaarista osoitetta 0x1ad91 , jolla on tämä:

  seg000: 1AD91; =============== ALARUUTU ================================= ===== seg000: 1AD91seg000: 1AD91; Attribuutit: bp-pohjainen frameseg000: 1AD91seg000: 1AD91 sub_1AD91 proc far; KOODI XREF: sub_188F2 + DP  

Huomaa XREF. Joten IDA todella käsittelee puhelun oikein! Miksi puhelu katsotaan kelpaamattomaksi? IDA-ohjetiedosto sanoo tämän:

Ongelma: Nimeä ei löydy

  • Description

    Kaksi syytä voi aiheuttaa tämän ongelman :

    1. Viittaus laittomaan osoitteeseen tehdään olemassa olevassa ohjelmassa purettu;
    2. IDA ei löytänyt osoitteelle nimeä, mutta sen on oltava olemassa.

    Mitä tehdä

    1. Jos tämän ongelman aiheuttaa viittaus laittomaan osoitteeseen

      • Yritä syöttää operandi manuaalisesti
      • Tai tee laiton osoite lailliseksi luomalla uusi segmentti .
    2. Muuten tietokanta on vioittunut.

  • Joten, ongelmana on kai se, että minulla on yksi jättimäinen segmentti useiden pienten sijasta . Mutta miten voin jakaa osoitetilan oikein sopiviin segmentteihin?

    Tiedän rekisteriarvot (mukaan lukien DS , CS , SS , IP , jne.) tulopaikassa. Oletetaan, että luon CODE -segmentin lähtökohdasta CS-rekisteriarvoa vastaavasta segmentistä. Mutta minkä pituisen tämän segmentin tulisi olla?

    Mikä on segmenttien tarkoitus IDA: ssa ollenkaan? Jos DATA-segmentit voivat sisältää ohjeita ja CODE-segmentit voidaan lukea ja kirjoittaa tiedoina?

    Anteeksi tällaisessa aloittelijakysymyksessä, mutta virallinen IDA-käsikirja on tunnetusti niukka ja HexRays-foorumit ovat minulle suljettuja, koska olen käytä freeware-versiota.

    Kolme vastused:
    Igor Skochinsky
    2014-08-13 23:32:04 UTC
    view on stackexchange narkive permalink
    1. Ohjelmasi käyttää segmenttiä, jonka peruskoodi on 1AD9h (kaukopuhelun segmenttiosa). Sinun on luotava uusi segmentti, joka vastaa sitä.

        Start = 0x1AD90 (0x1AD9<<4) Loppu = 0x2AD90 [esimerkiksi] (alku + 64 kt - enimmäiskoko) Base = 0x1AD9 (o) 16-bittinen  
    2. Käy nyt läpi uusi segmentti ja varmista, että kaikella on järkeä. Leikkaa segmentti (pienennä loppuosoitetta) tarvittaessa.

    3. Etsi toinen kaukopuhelu / puhelu, jolla on eri segmentin arvo. Toista vaihe 1 uudelle tukiasemalle.

    4. Tee sama tietosegmenttien kanssa (etsi arvot, jotka on ladattu ds / es / ss ).

    Tarkoitat siis, että IDA: lla tulisi olla jokaiselle kaukopuhelulle segmentti, jonka tukikohta on yhtä suuri kuin puhelun segmenttiosa? Mutta x86-segmentit voivat olla päällekkäisiä, ja IDA-segmentit eivät. Entä jos luon segmentin, joka alkaa arvosta 0x1AD90, törmään kaukopuheluun segmenttiin 1ADAh? Pitäisikö minun pienentää ensimmäinen segmentti 16 tavuun voidakseni luoda uuden segmentin alkaen 0x1ADA0? Näyttää siltä, ​​että päädyin pieniin osiin. Epäilen, että tämä on tarkoitettu tapa edetä.
    Todellisissa ohjelmissa käytetään harvoin päällekkäisiä segmenttejä.
    Rolf Rolles
    2014-08-14 00:48:17 UTC
    view on stackexchange narkive permalink

    Käsittelin kerran ROM-kuvaa ja kohtasin tämän ongelman. Minäkin olin hämmentynyt siitä, mitä tehdä, kunnes Igor tarjosi neuvoja.

    Näytti siltä, ​​että tapahtui, että linkkeri asetti jokaisen objektitiedoston omaan segmenttiinsä, joten jokainen objektien välinen funktiokutsu renderoitiin binääri kaukopuheluna, jossa segmenttipohja oli moduulin kaikille toiminnoille annettu perusta. Eli tapaus, jonka mainitsit vastauksessasi Igorin kommenttiin, ei toteutunut minulle.

    Korjatakseni sen etsin binaarista kaikki kaukopuheluohjeet ja loin sitten uuden (mahdollisimman suuren) IDA-segmentin. ) kunkin viitatun x86-segmentin lineaarisessa osoitteessa. Eli, minulla todellakin oli paljon pieniä segmenttejä. Tämä ei todellakaan ole ongelma; todellakin ongelmana on, että tekemättä tätä, viitteitä ei pureta oikein. Se oli melko nopeaa työtä, ja se voidaan todennäköisesti automatisoida komentosarjalla.

    Oikein. Mutta voi olla ohjelma, joka kutsuu yhden ja saman funktion kahdella eri segmentti-arvolla. Esimerkiksi, funktio alkaa osoitteesta "0x12345", ja sitä kutsutaan yhdestä paikasta nimellä "call far 1233h: 0015h" ja toisesta nimellä "call far 1234h: 0005h". Sitä voidaan käyttää 'harvoin todellisissa ohjelmissa', mutta se on fyysisesti mahdollista, eikä siinä tapauksessa voida asettaa funktion segmenttiä siten, että molemmilla puheluilla ei olisi NONAME-ongelmaa. On vain outoa, että niin tehokkaalla työkalulla kuin IDA voi olla ongelmia tällaisessa tilanteessa, riippumatta siitä, kuinka puhtaasti teoreettinen se on.
    Kyllä, se varmasti * voi tapahtua: hämärtymisen vuoksi tai vain jonkin kokoonpanokooderin ollessa fiksu. IDA: n ja sen rajoitusten osalta se on kaikkien aikojen suosikkiohjelmistoni yhdessä SoftICE: n kanssa, mutta sen pitkän kehityksen aikana on tehty monia arkkitehtonisia päätöksiä, jotka voivat viedä sinut takaisin päinvastaisissa yrityksissäsi. Tällaiset asiat turhautuivat ja ärsyttivät minua, kunnes minulla oli työ ohjelmistokehittäjänä, ja nyt ymmärrän. Hex-Rays valmistaa upeita tuotteita, kun otetaan huomioon niiden rajoitetut resurssit. Voit tehdä melkein kaiken mitä haluat, tuki on suuri ja SDK / IDAPython on hyvä. Tee limonadi.
    Guntram Blohm supports Monica
    2014-08-13 20:47:53 UTC
    view on stackexchange narkive permalink

    Tämän takana on se, että jokainen segmentti käsittää enintään 64 kt, ja mielekkäiden kokoonpanojen luomiseksi IDA: n on tiedettävä, mitä segmenttirekistereiden on tarkoitus olla, kun koodi suoritetaan.

    Oletetaan, että olet sinulla on seuraava koodi lineaarisessa osoitteessa 0x23456:

      mov bx, 6789call [bx]  

    Mitä toimintoa tämä kutsuu? No, jos CS-rekisterissäsi on 0x2000 ja IP-osoitteesi on 0x3456 , tämä kutsuu 2000: 6789 tai (linear) 0x26789 . Mutta yhtä hyvin, sinulla voi olla 0x2345 CS: ssä ja 0x0006 IP: ssä. Tällöin 2345: 6789 tai ( 0x23450 + 0x6789 =) 0x29BD9 kutsutaan.

    Joissakin tapauksissa hyppy- / puhelukohteet eivät ole niin epämääräisiä, esimerkiksi absoluuttisten kaukopuheluiden, kuten puhelu 1AD9: 1 , tai suhteellisten hyppyjen kanssa (siksi käytin epäsuoraa [bx] puhelu; puhelu 6789 käyttäisi kokoonpanokäskyä, joka on suhteessa IP: hen, niin riippumaton segmentistä)

    Jos sinulla on tällainen koodi
      mov ax, 1234push axpop esmov bx, es: [abcd] mov ax, 5678push axpop esmov dx, es: [cdef]  

    haluat muuttujan määrityksen (bx: lle) kohtaan 1234: abcd ja toisen (dx: lle) kohtaan 5678: cdef . Mikä tarkoittaa, että IDA: n on tiedettävä, että yksi segmentti alkaa kohdasta 1234 ensimmäisen muuttujan sijoittamiseksi ja toinen alkaa muuttujan 5678 toisesta muuttujasta. (Käytin push / popia, koska sikäli kuin muistan, ei ollut prosessorin opkoodia segmenttirekisterin lataamiseen suoraan, ja mielestäni myös niiden siirtämisessä oli joitain rajoituksia, joten push / popia käytettiin voimakkaasti lataamiseen heille).

    Segmenttien tarkoitus on tietysti se, että ne ovat huono idea ja aiheuttivat paljon ongelmia, mutta Intel halusi pystyä vastaamaan yli 64 kt: n 16-bittisellä prosessorilla, joten he keksivät ne. Mikä tarkoittaa, että ne ovat olemassa, ja meidän on saatava ne oikein purettaessa 16-bittisiä ohjelmia. Pitäisikö meistä vai ei, ei ole kysymys.

    Parasta mitä voit tehdä, on löytää niin monta viittausta segmentteihin kuin mahdollista - alkuperäiset CS / DS / ES / SS-arvot, kaukaiset puhelut joillekin cs: ip sijainti ja arvot, jotka ladataan segmenttirekistereihin. Kirjoita sitten mitä segmenttiarvoja esiintyy, oletetaan, että kukin niistä on tarpeeksi suuri sijoittamaan koko tila seuraavaan, ja syötä tämä luettelo IDA: lle.

    Kiitos, mutta tiedän x86-segmentointijärjestelmästä. Näyttää siltä, ​​että sillä ei ole mitään tekemistä IDA-segmenttien kanssa. (1) purettavassa koodissa ei ole käytännössä mitään lähihyppyjä, vain lyhyet ja kaukaiset, jotka eivät tarvitse kunnollisia segmenttejä. (2) Mainitsemani `call 1AD9h: 1` -ohje on kaukahyppy (opkoodi` 9a 01 00 d9 1a`), ja se on silti merkitty virheelliseksi. (3) En vieläkään ymmärrä, miksi IDA onnistui luomaan oikean XREF: n tälle 'virheelliselle' puhelulle. (4) AFAIK, jota et hallitse segmenttirekistereiden arvoja ei "Ohjelman segmentointi" -näkymällä, vaan "Segmenttirekisterit" -näkymällä, mikä näyttää olevan erilainen asia.


    Tämä Q & A käännettiin automaattisesti englanniksi.Alkuperäinen sisältö on saatavilla stackexchange-palvelussa, jota kiitämme cc by-sa 3.0-lisenssistä, jolla sitä jaetaan.
    Loading...