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