Spørgsmål:
Kan jeg statisk linke (ikke importere) Windows-system-DLL'er?
daehee
2013-05-22 13:29:47 UTC
view on stackexchange narkive permalink

Jeg har samlet følgende C-kildekode i VS2010-konsolprojekt.

  #include <stdio.h>int main (int argc, char * argv []) {printf ("hej verden \ n" ); returner 0;}  

så brugte jeg / MT mulighed for frigivelsestilstand til statisk at forbinde C-runtime-biblioteket. Men så vidt jeg ved, C- runtime-bibliotek påberåber stadig systemfunktioner på lavere niveau - for eksempel kalder C-runtime-funktion printf til sidst WriteFile Windows API.

Og den aktuelle funktionsdel af WriteFile er i kernel32.dll . Så selvom jeg linker C-runtime-biblioteket statisk, indeholder binærsystemet ikke hele rutinen inklusive SYSENTER kode> eller INT 0x2E instruktioner ... Kernedelen er stadig i en DLL. Følgende diagram beskriver, hvordan jeg forstår det:

enter image description here

Hvad jeg ønsker er statisk at linke ALT til en enkelt EXE-fil. Inkluderende kernel32.dll , user32.dll for at eliminere nødvendigheden af ​​at parsere IAT og løse funktionsnavne af loader.

Det følgende billede beskriver, hvad jeg ønsker:

enter image description here

Jeg forstår, at dette er simpelt i Linux med gcc . Alt hvad jeg skal gøre er at give muligheden -statisk

Er der nogen mulighed som denne i VS2010? Ret mig, hvis jeg misforstår.

Svaret er klart "nej". Du bliver nødt til at skrive dit eget OS-specifikke syscall-lag. Spørgsmålet er: hvorfor vil du ikke bruge en standard CRT? Til hvilken fordel?
tak skal du have. faktisk ledte jeg ikke efter præstationsfordel. Jeg troede, på denne måde kan jeg fjerne alle symboler ligesom Linux strippet binært og gøre reverseringen sværere.
@daehee:, der giver dit spørgsmål en helt anden vinkel, ser du.
Din beskrivelse er samlet set korrekt, men du skal tilføje endnu et lag, NT native api: fread (msvcrt) -> ReadFile (kernel32) -> NtReadFile (ntdll.dll) -> kernel
Med tilstrækkelig indsats kan du muligvis udføre inline windows-funktioner, men så er du bundet til den specifikke Windows-version, og du vil sandsynligvis krænke MS's copyright.
Tre svar:
Igor Skochinsky
2013-05-22 14:53:59 UTC
view on stackexchange narkive permalink

Windows-kernen bruger i modsætning til Linux eller OS X ikke ensartet syscall-nummerering på tværs af versioner. Tallene kan ændres, selv efter en servicepack frigivelse. For eksempel var NtReadFile syscall 0x0086 på Windows NT 4, men i Windows 7 er det 0x0111 (se her for hele listen). Derfor bruger alle korrekte programmer kernel32.dll (eller ntdll.dll ) til at udføre det aktuelle opkald - disse DLL'er er garanteret at bruge syscall-numrene matchende kernen.

Forresten sparer du ikke noget ved ikke at angive kernel32.dll i din IAT - det kortlægges altid i Win32-processer af systemlæsseren (startende fra Windows 2000 IIRC ).

Jeg troede Windows syscall-nummerering var den samme som Linux. tak for informationen, det hjælper min forståelse meget!
@daehee: det ændrer sig en gang imellem. Det er grunden til, at `fil 'lister kerneversionen til ELF-filer.
0xC0000022L
2013-05-22 21:59:11 UTC
view on stackexchange narkive permalink

Lad mig starte med at fortælle dig, at det, du ønsker, ville være umuligt på grund af, hvor velkendte DLL'er fungerer. Du kan prøve noget lignende med værktøjer som PEBundle eller dllpackager, men det vil normalt (jeg vil helt sikkert sige) mislykkes med de kendte DLL'er (såsom system-DLL'er som såvel som selv MSVC-runtime-DLL'er i deres forskellige inkarnationer). Se dette og dette om relevansen og betydningen af ​​kendte DLL'er.

kernel32.dll spiller en meget speciel rolle i Win32-undersystemet, idet det hjælper med at registrere Win32-tråde og processer med delsystemet ( csrss.exe ).


Besvarelse den del af kommentaren fra OP til spørgsmålet:

faktisk ledte jeg ikke efter præstationsfordel. Jeg troede, på denne måde kan jeg fjerne alle symboler ligesom Linux fjernet binært og gøre reverseringen sværere.

Der er ingen mening i at gøre det på denne måde. Du kan stadig kun importere en enkelt funktion og bruge en indviklet måde at importere DLL'er og / eller løse funktioner på. Dvs. skjuler hvilke funktioner du importerer fra hvilke DLL'er. En ting, der er temmelig populært i hacker-cirkler, er at hash de eksporterede funktionsnavne og derefter gå eksporten af ​​det indlæste billede selv, hashing hvert af de funktionsnavne, der findes, og sammenligne med de kendte hashværdier.

Her er et godt papir om en metode, der bruges til det, du ønsker, fordi shell-kode ikke har nogen anelse om importerede funktionsadresser i en kapret proces.

Som Igor påpegede kernel32. dll indlæses i processen og AFAIR rækkefølgen af ​​det har også ændret sig med Vista (tidligere ntdll.dll var den første i PEB ' s DLL-liste, aka LoaderData ). Så den nøjagtige metode er beskrevet i ovenstående papir.

Et par punkter til:

  1. hvis du ikke vil bruge LoadLibrary (eller dets ntdll.dll modstykke) til dynamisk at indlæse DLL'er, kan du beholde en henvisning til en enkelt importeret funktion i IAT - sådan gør nogle eksekverbare pakkere det.
  2. hvis ikke, start med at løse LoadLibraryA , indlæse de ønskede DLL'er og brug derefter den løste GetProcAddress (eller din egen metode, der allerede er brugt på kernel32.dll og beskrevet i papiret) for at indlæse flere funktioner.
  3. du kan muligvis gøre dit liv sværere, mens du ikke gør det mærkbart sværere for en dygtig / erfaren reverse engineer. De fleste af dem vil have set et lignende skema;) ... dynamisk analyse afslører nemt dine tricks og gør det muligt for en reverse engineer at omgå dem.

Som et alternativ kunne du ty til systemets opkaldsnumre ved at skrive en forenklet disassembler, der er i stand til at vælge indekset i SSDT (systemtjenestebeskrivelsestabel), og så gør du resten selv. Dette er blevet dokumenteret for længe siden, fordi det var, hvordan folk plejede at finde indekset i SSDT, da de ønskede at tilslutte det fra en kerne-mode driver. Groft, hvis du har markøren til funktionen i ntdll.dll som du har brug for SSDT-indekset til, skal du kontrollere dine antagelser og derefter hente den relevante værdi. I Windows NT 4 til og med 2003 (32 bit) ser det ud som

  B8 ?? ?? ?? ??  

hvor B8 er for mov eax, ???????? og spørgsmålstegnene er indekset i SSDT. Så efter at have tjekket for B8 , springer du over den og henter det næste DWORD. Eksempel i C-kode:

  hvis ((lpAddr) && * ((usigneret tegn *) lpAddr) == 0xB8) {resultat = * ((ULONG *) ((usigneret tegn *) lpAddr +1));}  

Ting vil være forskellige på forskellige operativsystemversioner og afhængigt af bittheden - du er blevet advaret.

Men jeg kan ikke se nogen fordel - hverken præstationsmæssigt eller afskrækkende reverse engineering-indsats.

faktisk er den eneste import, du har brug for, GetProcAddress, fordi du kan GetProcAddress ("LoadLibrary") og gå derfra.
James
2013-09-18 07:20:57 UTC
view on stackexchange narkive permalink

Sandsynligvis med fuld hensigt fra MS ændres ikke kun syscall-nummerering mellem versioner, men også mange ordinære DLL-værdier også. Brug for at binde til WIN32 og bruge det fulde funktionsnavn, hvis du vil have din kode til at fungere på tværs af OS-udgivelser.



Denne spørgsmål og svar blev automatisk oversat fra det engelske sprog.Det originale indhold er tilgængeligt på stackexchange, som vi takker for den cc by-sa 3.0-licens, den distribueres under.
Loading...