Fråga:
Finns det ett sätt att lägga till en referens till en dynamiskt importerad funktion i IDA på fliken Import?
0xC0000022L
2013-05-29 21:04:24 UTC
view on stackexchange narkive permalink

Titeln säger det mesta. Säg att jag har en Windows PE (x86, 32bit) binär (bara så vi har fall att diskutera), importlistan visar vanligtvis bara importen som finns i importkatalogen. Attributen som visas är adressen till funktionen, namnet och biblioteket från vilken den importerades, som visas i det här skärmdumpavsnittet:

Screenshot of import tab in IDA Pro

Finns det ett sätt för mig genom skript (IDC eller Python, jag bryr mig inte för mycket), för att lägga till egna import till listan och till exempel få dem att peka (adressattributet) på kod som denna (markerad rad)?:

Dynamically imported function in IDA Pro

Dvs. raden skulle i så fall se ut:

  0DCBA987 GetLongPathNameW kernel32.dll  

eller till och med bara

  0DCBA987 GetLongPathNameW ???  

förutsatt att ovanstående -samtal GetProcAddress skulle vara på adressen 0DCBA987.

Fördelen för mig skulle vara läsbarhet. Men det skulle också ge en mer omfattande lista över import (och därmed xrefs) eftersom vissa funktioner ofta importeras dynamiskt på grund av deras tillgänglighet i de olika Windows-versionerna.

Det borde vara ganska trivialt med tanke på en viss binär till räkna ut alla xrefs till kandidatfunktioner som hämtar den importerade funktionsadressen (t.ex. GetProcAddress ) och sedan gå deras samtal för att hitta vilken funktion som importerades. DLL-delen kan vara mer komplicerad att ta reda på, men den kan lämnas tom eller anges manuellt. Men jag hittade inte en funktion som tillät mig att lägga till import. Finns det ett sätt?

Intressant fråga, det skulle vara användbart när man analyserar ett program från en minnesdump. Att ha möjlighet att redigera importen skulle lägga till korsreferenser och göra analysen enklare.
Om du inte har sett det bör du kolla in [reiat.py] (https://bitbucket.org/Alexander_Hanel/reiat/src/). Det gör det mesta av vad du diskuterade förutom att lägga till importflikarna.
@alexanderh: hade inte, även om jag såg några av de andra reporna du har på Bitbucket tidigare. Har du någon aning om hur du får det sista steget gjort?
@0xC0000022L Nej, det gör jag inte. Jag ska försöka ta en spricka på det i helgen. Min e-postadress är i källkoden. Skicka gärna provet via e-post om du kan dela det. Dum sidoanteckning, kommentaren "GetLongPathNameW" kan användas för att samla icke-kommenterade korsreferenser via snabbtangenten X. Inte användbart för automatiserad analys men ändå till hjälp.
Du kan försöka uppdatera "import_node" (exporteras från SDK: s nalt.hpp), men det är oklart om IDA läser om dessa "netnode" varje gång det ritar upp importlistan igen.
Om du inte kan lägga till något på importfliken kan du skriva egen importflik, det är ganska enkelt. Kommer en sådan lösning att vara tillräckligt tillfredsställande?
Tre svar:
NirIzr
2013-05-31 22:15:56 UTC
view on stackexchange narkive permalink

Jag vet inte om många vet det här, men IDA använder något slags knep för att avgöra om ett segment är ett importsegment och hanterar det helt annorlunda.

IDA använder ett fåtal segment egenskaper för att behandla ett segment som ett import segment. till exempel genom att namnge ett segment .idata eller ställa in segmentets klass till XTRN kommer det omedelbart att bli ett importsegment. sådana segment kommer inte att visa de vanliga kod- / dataförteckningarna, funktionsdefinitionerna och de flesta andra saker vi är vana vid i kodvyn.

Mer specifikt, lägga till kod till dessa segment kommer att döljas i IDA, vilket kommer att vägra att visa någon montering i dessa segment. Ett trevligt Anti-IDA-trick skulle jag säga :)

Istället visar de bara namndefinitioner, förskjutningar och kommentarer. När en förskjutning tilldelats ett namn på ett API som lagras i IDA: s databas kommer IDA få API: s prototyp och annan info, tilldela typdefinition och kommentarer.

IIRC Dessa API: er kommer också att visas i importfönstret men jag är inte säker på vad som exakt utlöser detta. det kan också bero på IDA-versioner och andra importrelaterade PE-egenskaper.

EDIT
Det har gått mer än tre år och jag kunde självklart inte hitta skriptet då, och jag gick bara över en gammal kod av mig och kunde rekonstruera vad jag gjorde i det skriptet, och här är kärnan i det:

  import idaapiimport idcfor import_rva, import_name i LIST_OF_IMPORTS: ea = imagebase + import_rva om idaapi.get_segm_class (getseg (ea)) == "XTRN": skriv ut ("import finns redan i ett XTRN-segment," förutsatt att det har rätt namn ") fortsätt elif idaapi.get_segm_class (getseg (ea-1 )) == "XTRN": skriv ut ("Importera är strax under ett importsegment," "utvidga segmentet till att inkludera denna ytterligare import") # krympande det aktuella segmentet # VARNING: detta förutsätter att den nuvarande importen är högst upp i sitt segment
# annars måste vi SPLITA importens nuvarande segment # och till det säger jag CBA aka kvar som en övning till läsaren idaapi.set_segm_start (ea, SegStart (ea) +4, 0) # expanderar det nya segmentet idaapi.set_segm_end (ea-1, SegEnd (ea-1) +4, 0) annat: skriv ut ("Skapa nytt segment för import") idc.AddSeg (ea, ea + 4, 0, 1, 4, 0) idc.SetSegClass ( ea, "XTRN") # byta namn på import till API-namn. Detta gör att IDA lägger till typinformation och automatiska kommentarer för alla funktioner som det är # bekant med idc.MakeName (ea, import_name) # Gör det en förskjutning att IDA visar det som import istället för att dölja det idc.MakeDword (ea)  
@Nirlzr: i alla fall, jag skulle vara nyfiken på att se detta svar konkretiserat lite. Tack.
@Nirlzr: några nyheter om nämnda manus?
@0xC0000022L: Fruktansvärt ledsen! Jag är för närvarande i reservtjänst och jag kan inte komma till saker jag har på jobbet. glömde inte bort det.
@0xC0000022L Jag vet att det har gått länge (och det är en underdrift), men jag har redigerat mitt svar för att inkludera manuset)
blabb
2015-03-25 04:28:05 UTC
view on stackexchange narkive permalink

om att lägga till ett extra importavsnitt till PE-filen är ett acceptabelt alternativ

använd verktyg som iidking och lägg till ett importavsnitt med all import som löses dynamiskt

använd add korsreferensdialog eller idc add_dref () för att lägga till korsreferenser till dem

kod för demo

  #include <stdio.h> # include <windows.h> # pragma comment (lib, "user32.lib") DWORD (WINAPI * MyGetShortPathName) (LPCTSTR, LPTSTR, DWORD); int main (void) {MessageBox (NULL, "testing add import", "Test", MB_OK); char modname [MAX_PATH] = {0}; GetModuleFileName (NULL, modnamn, MAX_PATH); printf ("% s \ n", modnamn); HMODULE hMod = LoadLibrary ("kernel32.dll"); if (hMod) {* (FARPROC *) &MyGetShortPathName = GetProcAddress (hMod, "GetShortPathNameA"); if (MyGetShortPathName) {MyGetShortPathName (modnamn, modnamn, MAX_PATH); printf ("% s \ n", modnamn); }} returnera 0;}  

kompilerat och kört

  C: \ codesnips \ addimp \ addimp.exeC: \ CODESN ~ 1 \ addimp \ addimp. exe  

omodifierad import

  00412000 GetCurrentThread KERNEL32 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXx400x i extra importavsnittet  
  C: \ codesnips \ addimp>fc / b addimp.exe modaddimp.exeJämför filer addimp.exe och MODADDIMP.EXE000000E6: 04 05 nr i avsnitt 00000131: 90 A0 00000160: F4 0000000161: 47 9000000164: 3C 5000000278: 00 2E, 00000279: 00 49 I0000027A: 00 49 I0000027B: 00 44 D0000027C: 00 4B K0000027D: 00 69 I0000027E: 00 6E N0000027F: 00 67 G00000281: 00 02 vsize00000285: 00 0100000289: 00 020000028D: 00 5E0000028E: 00 010000029C: 00 200000029F: 00 E0  

ida importerar fönster kopiera klistra in av modifierad exe

  00412000 GetCurrentThread KERNEL32 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX00412130 MessageBoxA USER32 00419058 GetShortProck 
  Upp P sub_401000 + 89 samtal ds: GetProcAddress (data xref)  

eller idc-kommando

  add_dref (0x401089,0x419058,53 AddCodeXref (0x419058,0x401089,53);  

AddImports

att sammanställa dessa tre rader till ett plugin kommer att lägga till önskad import till den första modulens import

  ogiltig idaapi-körning (int) {nodeidx_t index = import_node.alt1st (); osignerat långt värde = import_node.altval (index); netnode (värde) .supset (0x410004, "GetShortPathNameA \ 0" );}  

idc-filen för att skapa segment

  #include <idc.idc>static main () {auto addr; addr = 0x410000; SegCreate (addr, Lägg till r + 0x200,0,1,3,2); SetSegmentType (addr, SEG_XTRN); MakeDword (addr + 4); MakeName (addr + 4, "GetShortPathNameA");}  

öppna en exe / kör idc / plugin / stäng och spara databas / öppna databas för att se den tillagda importen i importfliken för den första modulen

redigera
windows -> reset desktop fungerar på samma sätt som att stänga och öppna databasen så att stängning och öppning av databas elimineras

Tack för svaret! Tyvärr fungerar detta inte för vissa uppackade körbara filer eller när det gäller positionsoberoende kod.
kan du utarbeta eller posta / peka på ett prov där detta inte verkar fungera?
Jag kanske tar fel men ditt exempel fungerar inte på prover som saknar den bärbara körbara rubriken. Exempel på dessa skulle vara shellcode, injicerade DLL-filer som nollställer rubriken eller placera oberoende kod (ingen rubrik och löser symboladress genom att korsa PEB för kernel32.dll). Visst, en PE-rubrik kan läggas till men det här är inte alltid ett genomförbart tillvägagångssätt eftersom det förlitar sig på att ha och ändra binären.
om du är övertygad om resonemanget går det bra med mig men min tankeprocess är så här om ida har tillräckligt med information för att hämta och skapa originalimporten så borde den kunna hitta det också. den ursprungliga frågan verkade antyda att pe är tillgänglig och sa inte något om att originalet inte var tillgängligt, så jag lade upp detta tillvägagångssätt med en försiktighet om att ändra exe är acceptabelt om dina nya krav handlar om att slå med en idb fristående då jag har ingen aning
Jag förstår din tankeprocess men det svarar fortfarande inte hur du lägger till import till importfliken via IDC eller Python i IDA. Vilket är den ursprungliga begäran. Kolla in NirIzr svar det är närmast.
uppdaterade svaret med en lösning för idb-filer
Jag kan inte verifiera koden just nu men eftersom belöningen är på väg att löpa ut tilldelar jag den till dig. Tack för uppdateringen.
w s
2015-03-25 21:50:36 UTC
view on stackexchange narkive permalink

Om du inte kan lägga till något i importvisaren kan du skriva ditt eget. Här är det enkla exemplet (det är något modifierat exempel som hänvisas till denna hexblogpost och ligger här med tillagd dubbelklickfunktion, tillagda kolumner, borttagen export och fixad bugg för ett fall av okänd ursprung för den importerade funktionen). Se funktionen BuildImports för att skapa ytterligare import (manual_func1 och manual_func2)

  importera idaapiimport idautilsfrån idaapi import PluginFormfrån PySide import QtGui, QtCoreclass ImpExpForm_t (PluginForm): def import_names_cb (själv, ea, ea, : self.items.append ((ea, '' om inte namn annat namn, ord)) # True -> Fortsätt uppräkning returnera True def BuildImports (själv): träd = {} nimps = idaapi.get_import_module_qty () för i i xrange (0, nimps): namn = idaapi.get_import_module_name (i) om inte namn: namn = "okänt" # Skapa en lista för importerade namn self.items = [] # Enum importerade poster i den här modulen idaapi.enum_import_names (i, self .import_names_cb) om namnet inte finns i trädet: träd [namn] = [] träd [namn] .förläng (själv.items) träd ["manuellt_tillagd"] = [(0x01, "manual_func1", 3), (0x02, "manual_ func2 ", 4)] returnera träd def PopulateTree (själv): # Rensa tidigare objekt self.tree.clear () # Bygg import root = QtGui.QTreeWidgetItem (self.tree) root.setText (0," Imports ") för dll_name , imp_entries in self.BuildImports (). items (): imp_dll = QtGui.QTreeWidgetItem (root) imp_dll.setText (0, dll_name) for imp_ea, imp_name, imp_ord in imp_entries: item = QtGui.QTreeWidgetItem (imp_dset) 0, "% s"% imp_name) item.setText (1, "0x% 08x"% imp_ea) item.setText (2, "0x% 08x"% imp_ord) def dblclick (self, item):
försök: idaapi.jumpto (int (item.text (1) .encode ("ascii", "ignorera"), 16)) utom: skriv ut "Kan inte hoppa" def OnCreate (själv, form): "" "Kallas när pluginformuläret skapas "" "# Skaffa överordnad widget self.parent = self.FormToPySideWidget (form) # Skapa trädkontroll self.tree = QtGui.QTreeWidget () self.tree.setColumnCount (4) self.tree.setHeaderLabels (( "Namn", "Adress", "Ordinarie", "Källa")) self.tree.itemDoubleClicked.connect (self.dblclick) self.tree.setColumnWidth (0, 100) # Skapa layoutlayout = QtGui.QVBoxLayout () layout .addWidget (self.tree) self.PopulateTree () # Populate PluginForm self.parent.setLayout (layout) def OnClose (self, form): "" "Called when the plugin form is closed" "" global ImpExpForm del ImpExpForm print " Stängd "def Visa (själv):" "" Skapar att formuläret inte skapas eller fokuseras det om det var "" "returnera PluginForm.Show (själv," Importera / exportera visare ", alternativ = PluginForm.FORM_PERSIST) # ---------------------- -------------------------------------------------- --def main (): global ImpExpForm försök: ImpExpForm utom: ImpExpForm = ImpExpForm_t () ImpExpForm.Show () # ------------------------- ------------------------------------------------- huvud ()  
Tack, jag har använt tittartillvägagångssättet tidigare. Ett problem som jag har upptäckt är att när IDB är stängd, är tittaren och data borta. Det skulle vara coolt att hitta något mer permanent.
Du kan till exempel använda OnClose för att spara data. Det kommer att kräva lite mer utveckling, men det är fortfarande enkelt
Generellt sett har du några bättre alternativ. Först och främst kan du lagra själva skriptet i skriptfönstret (Arkiv -> Skriptkommandot har ett gränssnitt för det) - detta gör att du kan behålla alla dina senaste tillägg med idb. Du kan också använda OnClose och lagra dina data i en fil med namn härledt från namnet på idb som kan erhållas av idautils.GetIdbPath. Du kan också lagra data i IDB: s anpassade nod.


Denna fråga och svar översattes automatiskt från det engelska språket.Det ursprungliga innehållet finns tillgängligt på stackexchange, vilket vi tackar för cc by-sa 3.0-licensen som det distribueras under.
Loading...