███████╗███╗ ███╗███████╗██╗ ██╗ ██╗ ██╗ ██╗ ██╗██╗ ██╗ ██╔════╝████╗ ████║██╔════╝██║ ██║ ╚██╗ ██╔╝ ██║ ██║╚██╗██╔╝ ███████╗██╔████╔██║█████╗ ██║ ██║ ╚████╔╝ ██║ ██║ ╚███╔╝ ╚════██║██║╚██╔╝██║██╔══╝ ██║ ██║ ╚██╔╝ ╚██╗ ██╔╝ ██╔██╗ ███████║██║ ╚═╝ ██║███████╗███████╗███████╗██║███████╗███████╗╚████╔╝ ██╔╝ ██╗ ╚══════╝╚═╝ ╚═╝╚══════╝╚══════╝╚══════╝╚═╝╚══════╝╚══════╝ ╚═══╝ ╚═╝ ╚═╝ MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXKOkxdoodxk0XNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMWNXKOkdlc;,... ..;lkXWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMWNKOkdl:,'.. 'lKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMWNKOxoc;'.. 'xNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMN0xo:,.. .dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMWKd;.. 'OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMWKl'. .lNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMWk,.... ,OMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMWk,..... .cKMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMXc...... .lXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MM0;........ .................... .oNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXXXXNWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MM0,......... .........................'''..... ..dNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNKkoc;,'..',;:codkOKXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MM0;........ ................................'''''''..... ....,OWMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKd;. ..',:codk0KNWMMMMMMMMMMMMMMMMMMMMMM MMO,......................................,cdxkOOkxoc;'.........lXMMMMMMMMMMMMMMMMMMMMMMMMMMMXd'. ...,:coxk0XNWMMMMMMMMMMMMMM MMk'....................................;dKWMMMMMMMMNXOo:'......,OMMMMMMMMMMMMMMMMMMMMMMMMMMK:. ...';cldk0NWMMMMMMMM MWk'.....',,,,'''''....................:0WMMMMMMMMMMMMMWXkc'.....xWMMMMMMMMMMMMMMMMMMMMMMMMXl. ...........,lkXWMMMMM MWx....,,,,,,,''''''''................;OWMMMMMMMMMMMMMMMMMNk;....lNMMMMMMMMMMMMMMMMMMMMMMMWk'.. ...............,oKWMMM MWd..',,,;cdkkOkxo:,','''.............lXMMMMMMMMWXK0kxddoll:. .,0MMMMMMMMMMMMMMMMMMMMMMMXc... ....................;kNMM MNd',;,;lONWMMMMMWXOl,''''............dWMMWNKOdl;'... .cXMMMMMMMMMMMMMMMMMMMMMWk'... ............................'xWM MWx;,;:xXMMMMMMMMMMMNk:...............;xxdc;.. .cKMMMMMMMMMMMMMMMMMMMW0;... ...............................:0M MM0c,;dNMMMMMMMMMMMMMW0:...... .......... .;0WMMMMMMMMMMMMMMMMMK:..... ..................................'kW MMNd;cKMMMMMMMWWWNNNXKO:...... ..............................,kNMMMMMMMMMMMMMMMKc..... ............................................'xW MMMKloXMWX0kdlc:;;;,''........ ...............................'xNMMMMMMMMMMMMMNo...... ......'''''''''....................................'xW MMMWxcoo:'... .............. . .................................'kWMMMMMMMMMMMWO,.........',,;;;;;;;;;,,,''.................................'xW MMMWk'......................... .......................................;KMMMMMMMMMMMXl.......',,;;:coodooc:,,,,,,''''..............................dW MMMNo.......................... ........................................dWMMMMMMMMMM0,......',cok0XNWWWWWNKOo;,,,,,,,'..............'',,,,,'.......oN MMWO,.......................... .......................''''..............lXMMMMMMMMMWk'.....,lOXWMMMMMMMMMMMMW0l,,,;;,'''......'''',,;:cccccc:;,....oN MMXl...............................................''''''''''............:XMMMMMMMMMNo....'oKWMMMMMMMMMMMMMMMMMKl,;;;,''''''''',,;;:cccccclllllc:,''oN MMK:................................ ........'''',,,,,,'''..........cXMMMMMMMMM0;.....cdkOO0KXNWMMMMMMMMMMWk;,,,'''''''',;::ccccldxkkkxdllllc:,oN MM0:'''.......................... . ......'',,,,;;,,,''''........lNMMMMMMMMXc.. .....';:ldk0XWMMMMM0:'''......',;:ccccdOKNWMMMWNKxllll:oX MMKc',,'''''''...................... .......'',;;;;;;,,,'''......'xWMMMMMMMKc... ...,cok0XNO;.........',::::lONMMMMMMMMMMW0ocllxX MMNo,,,,,,,,''''''..................................'',;;;;;;,,'''......:KMMMMMMWO:..........................',;'..........',;;;oKWMMMMMMMMMMMMW0ocoOW MMWO:;;;;;;;,,,,'''''.......',,;;;;;,,;;:;,'..........'',,;;,,,'''.....'dWMMMMMWk,..........................................''';kNWMMMMMMMMMMMMMNkcxXM MMMXd;;;;;;;;;;,,,,'''...',;:cc:::;,,;:::;,''............',,,,,'''.....cKMMMMMWk'...............................................,:clllooddxk0KNWWOo0WM MMMMKl;;;:::::;;;,,,''...,;:cllc:,'''''''..................''''''.....,kWMMMMWO,.............................................................';locxNMM MMMMW0l;::::::::;;;,''....',,,,,,''..........................''''.....lXMMMMMXc..............'''''''''''''........................................oNMM MMMMMW0l::::::c::;;,'.................. .....................''.....;kWMMMMMO,........'''',,,,,,,,,,,,'''''...............''.....................;0MM MMMMMMW0o::::::::;;,'........... .........................''....lXMMMMMWx'.....''',,,,;;;;:;;;;;;,,,''''.............'''''''..................lXM MMMMMMMWXxc::::::;;,'................',;::ccccc:;'..............'...,xWMMMMMWd.....'''''',,;;;:::::;;;,,,'''..............''''''''''''''''''''''''';OW MMMMMMMMMW0oc:::::;,''''''....',;coxkO0KXNNNNNNXK0xo:'.....'........:0MMMMMMWx'...''''',,;;;:::::::;;;,,''................''',''''''',,,,,,,,,,,,,,;kW MMMMMMMMMMMXkl::::;,,,,,,'',;cxOKNWMMMMMMMMMMMMMMMMWXOd:,...'......'oNMMMMMMMO;...''',,,'''''',,,,,,,'''.....................'''',,,,,,;;;;;;;::::::xW MMMMMMMMMMMMWXxc::;;,;;,,,;cxKWMMMMMMMMMMMMMMMMMMMMMMMWXkl,........,xWMMMMMMMXc..'''''........................................',,,,,;;;::::cccccccccOW MMMMMMMMMMMMMMW0d::;;;;;;;ckNMMMMMMMMMMMMMMMMMMMMMMMMMMMMXx:'......:0MMMMMMMMWk,..'''......'..........................',,,'....',,,;;::cccllllllllcoKM MMMMMMMMMMMMMMMMNkl:;;;;;;oXMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWk:'...''cXMMMMMMMMMXl''''......:do;'.............',,;;;,;;:cclc:;'..'',,;;:ccclllllllollkNM MMMMMMMMMMMMMMMMMWKd:;;;;;lXMMMMMMMMMMMMMMMMMMMWWWWMMMMMMMMNd,...''dNMMMMMMMMMWO:''''....'dNNOc'.........'',;cllool:::cccllc:;,''',,,;::cllollllllxXMM MMMMMMMMMMMMMMMMMMMNkc;;;,cKMMMMMMMMMWNXKOxdoollcccclodx0XNXo'.''',kWMMMMMMMMMMNd,''''...'oNMWKo,.........'',,;::::;,;;:clllc:;,'''''''',;;clllllxXMMM MMMMMMMMMMMMMMMMMMMMW0l:;,:0MMMMMWX0xl:,'......'''''....',;;'.','':0MMMMMMMMMMMMKl,''''''':0MMMXx;..............',,,,;;;:::::;;''''.....''',:lllxXMMMM MMMMMMMMMMMMMMMMMMMMMWKd:''xWMMNOl;'.',,;;::::c:ccc:::::;;;,;;;;,,oXMMMMMMMMMMMMWk;'''',,,,dNMMMW0o;..............'''''''',,,''.......',;;;;:cokXMMMMM MMMMMMMMMMMMMMMMMMMMMMMXx,.;0NOc,,,;:::cccccccc::::::::::::::;;;,:OWMMMMMMMMMMMMMXo,,,,,,,,:OWMMMMWKxc;'............................';okl,;:coONMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMNx,.;c;;::::c:::::::::::;;;;;;;;;;;;;;,,,oXMMMMMMMMMMMMMMW0c,,,,,,,,c0WMMMMMMNKkdl:,,'''..................':xKN0;.'cxKWMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMNOc,;:::::::::;;;;::::::;;;,,,,,,,,,,,,:OWMMMMMMMMMMMMMMMWk;,,,,,,;;l0WMMMMMMMMWNX0Oxdolc:;;,,'''....',;lkXWWO;.'l0NMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMWXxc::::::::::;;::cc:::::;;,,,,,,,,,,;xNMMMMMMMMMMMMMMMMMXo,,,,,,;;,c0WMMMMMMMMMMMMMWNNXK0OkxxdddddxO0XWMWKl'.;xXMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMNOo::::::::::::ccccccc:::;;,,,,,;;:dXMMMMMMMMMMMMMMMMMMWOc,,,,,;;;,cOWMMMMMMMMMMMMMMMMMMMMWWWWWWWMMMMW0o,.'l0WMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMWXxl::::::::ccccc:::cccc::::;;;;ckNMMMMMMMMMMMMMMMMMMMMNd;,,,;;;;;,;xNMMMMMMMMMMMMMMMMMMMMMMMMMMMMN0l'.'lONMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKxc::::::cc::::::::::::::::cxKWMMMMMMMMMMMMMMMMMMMMMWO:,,,,;;;;;,,cOWMMMMMMMMMMMMMMMMMMMMMMMWXk:..'cOXWMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWKxl::::::::::::;;::::cldkKWMMMMMMMMMMMMMMMMMMMMMMMMXl,,,,,;;;;;;,,lkXWMMMMMMMMMMMMMMMMMMN0o;..'lOXMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWX0xoc:::::ccodxkkOOKXWMMMMMMMMMMMMMMMMMMMMMMMMMMMNd,,,,,,,;;;;;;'';lx0XWMMMMMMMMMMWXOo:...,lONWMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNX00OO0KXNWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWk;',,,,,,,;;;::;;,'';:lodxxxxdol:'...';lkNMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM0:''''''',,;;;::cc::;;,'''.......',;:ldKWMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMXl,'''''''',,;;:ccccccccc:::::::ccllokXMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWx;,'''''''',,;:ccccccccccccccccllloONMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMKl,,,''',,,,;:ccllllccccccllllllld0WMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWk:,,,,,,;;;:cclllllllccclllllclxKWMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNx:;;;;;::cclllllllllllllllllokNMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNxc;;:::cccccccccclcllllllld0WMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMW0dc::::cc:::::ccccccccloxKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMNKkolcc::::::::::::clx0NMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWNXK00OkxdoooodxOKWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMWWNXNNWWMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM -- Contact -- https://twitter.com/vxunderground vxug@null.net

Everything you need to know about position independence on Windows

or in other words: Im going to regurgitate the same shit everyone else has said, except ill try to explain some more mystical concepts better. ill also throw in some odd-ball tricks ive learned along the way. because for whatever reason, no one has explained everything in a singular location to summarize position independence: code can run from anywhere, not dependent on stuff -Read more here: Position Independent Code OK, why is that important? well, you need it for shellcode. it also helps vxers out because when code is position independent it offers a way to obfuscate API calls. (unless theyre hooked and/or running under a DBI, thats a different conversation). but, either way just because your vx is under the spotlight of some heuristic engine, doesnt mean that youll be flagged. in fact, ive written some proof of concepts vx stuff that was not flagged and has yet to be flagged. of course though, ive never released it in the wild, if i did that, eventually the signature would be flagged ... eventually. tl;dr position independence is stealthy when done right. and finally, it should be noted that this technique is not my work. it was originally noted in 29a labs ezine #2 from jack qwerty. when win32 api first launched[1], 29a labs was the first to really reverse engineer the windows loader and disclose it publically.... february 13th 1998[2].. ya, so this trick is old as that white flakey dog shit you see in the parks. but, it still works, not much has changed with this technique and its still applicable to this day. whew. now, because we have a LOT to cover, im not going to write literal paragraphs of horseshit. i hate it when authors do that. instead, im going to get straight to the point with bulletins. GENERAL INFO -PI (position independence) -PI is achieved by traversing the PEB -PI needed because ASLR, If you dont know ASLR, google it -Process Environment Block -Each process is assigned their own PEB -You can get access to the PEB easily using ASM or intrinsic instructions -ASM or intrinsic function used depends on architecture -Some members of the PEB are a convuluted fuckin mess, making explaining this a nightmare -Still_works.jpeg HOW TO GET ACCESS TO THE PEB IN C -32bit Windows PEB is offset of FS register at 0x30 (48 bytes) -64bit Windows PEB is offset of GS register at 0x60 (96 bytes) -Need to define your own instance of PEB, the windows headers are incomplete because "fuck you" - microsoft, probably -Everyone has reversed it online, can google it -Here is one I use Process Environment Block header CODE TO GET ACCESS TO THE PEB IN C #include #include "peb.h" //use the shit i gave you or google your own definition int main(void) { PPEB Peb = (PPEB)__readgsqword(0x60); //64bit, its 2019 //PPEB Peb = (PPEB)__readfsdword(0x30); //if youre stuck in the past return 0; } https://docs.microsoft.com/en-us/cpp/intrinsics/readgsbyte-readgsdword-readgsqword-readgsword https://docs.microsoft.com/en-us/cpp/intrinsics/readfsbyte-readfsdword-readfsqword-readfsword -Reads GS or FS register at offset (0x60 or 0x30) -Typecast to PEB structure -ezpz INTEREST ATTRIBUTES OF THE PEB NO ONE SEEMS TO TALK ABOUT -BOOLEAN BeingDebugged; -literally is process being debugged, some debuggers set this to false though -PVOID ProcessParameters; -Typecasts to RTL_USER_PROCESS_PARAMETERS -Stores information for ... -ConsoleHandle; -Used by GetConsoleWindow() -ConsoleFlags; -Used by SetConsoleMode() -Used by GetConsoleMode() -StandardInput; -StandardOutput; -StandardError; -Used by GetStdHandle() -CurrentDirectory; -Used by GetCurrentDirectory() -DllPath; -Used by GetModuleFileName() -ImagePathName; -Used by GetModuleFileName() -CommandLine; -Used by CommandLineToArgvW() -Environment; -Used by GetEnvironmentVariable() -StartingX; -StartingY; -CountX; -CountY; -CountCharsX; -CountCharsY; -Used by SetConsoleCursorPosition() -Used by GetConsoleScreenBufferInfo() -FillAttribute; -WindowFlags; -ShowWindowFlags; -WindowTitle; -Used by GetWindowText() -Used by SetWindowTitle() -DesktopInfo; -ShellInfo; -RuntimeData; -RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32]; -EnvironmentSize; OK... Im getting tired of finding the kernel32 functionality for all of these, you get the point -PVOID ProcessHeap; -Used by GetProcessHeap() -ULONG OSMajorVersion; -ULONG OSMinorVersion; -ULONG OSBuildNumber; -ULONG OSPlatformId; -ULONG ImageSubSystem; -ULONG ImageSubSystemMajorVersion; -ULONG ImageSubSystemMinorVersion; -Used by GetVersionExA() -Used by VerifyVersionInfoA -Used by all 'Version Helper functions' The point being, kernel32.dll is actually a lot of wrappers/forwards/shortcuts so you dont have to dig around in the internals. in a lot of cases for vx, you may not even need to make function calls in your code. you can literally just redevelop kernel32.dll functionality yourself. try hooking kernel32 calls that you made yourself :P CODE TO RECREATE RTL_USER_PROCESS_PARAMETERS FUNCTIONALIY -See definition here RTL_USER_PROCESS_PARAMETERS #include windows.h #include "peb.h" //use the shit i gave you or google your own definition int main(void) { PPEB Peb = (PPEB)__readgsqword(0x60); //64bit, its 2019 PRTL_USER_PROCESS_PARAMETERS UserProcessInfo = (PRTL_USER_PROCESS_PARAMETERS)Peb->ProcessParameters; printf("%ws\r\n", UserProcessInfo->Environment); printf("%ld\r\n", UserProcessInfo->CountX); //idk, just an example return 0; } ENOUGH BULLSHIT, POSITION INDEPENDENCE TIME -PLDR_MODULE in PEB is double linked list -Points to all loaded dlls with PE file #include windows.h #include "peb.h" //use the shit i gave you or google your own definition int main(void) { PPEB Peb = (PPEB)__readgsqword(0x60); //64bit, its 2019 PLDR_MODULE pLoadModule; pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink printf("%ws\r\n", pLoadModule->FullDllName.Buffer); //prints your pe files + full path e.g. //C:\Users\You\Desktop\MyApp.exe return 0; } -Normally, for a common console application, this is the order youll see -1 flink gets access to your actual PE file / the full path to your OWN PE file -2 flink gets ntdll.dll -contains kernel functionality -3 flink gets kernel32.dll -contains misc. I/O functionality, wrappers to ntdll.dll, etc -4 flink gets user32.dll -contains functionality for UI elements -5 flink gets msvcrt.dll -contains console I/O functionality, posix stuff like stdio.h, etc. -6 goes back to pe file int main(void) { PPEB Peb = (PPEB)__readgsqword(0x60); //64bit, its 2019 PLDR_MODULE pLoadModule; pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink; //1 printf("%ws\r\n", pLoadModule->FullDllName.Buffer); //prints full path to pe file pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink; //2nd call printf("%ws\r\n", pLoadModule->FullDllName.Buffer); //prints full path ntdll.dll pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink; //3rd call, you get the point printf("%ws\r\n", pLoadModule->FullDllName.Buffer); //prints full path to kernel32.dll return 0; } alternatively, you can just do int main(void) { PPEB Peb = (PPEB)__readgsqword(0x60); //64bit, its 2019 PLDR_MODULE pLoadModule; pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink->Flink; //2 flinks printf("%ws\r\n", pLoadModule->FullDllName.Buffer); //prints full path to ntdll return 0; } -Flink to dll you want -I want ntdll for LdrLoadDll (LoadLibrary wraps to this) -Definition of LdrLoadDll can be found here -Simple, pLoadModule->BaseAddress -In order to get functions from ntdll need to work way through PE file -Must traverse IMAGE_DOS_HEADER, IMAGE_FILE_HEADER, IMAGE_OPTIONAL_HEADER -Not hard, must do some basic arithmetic as follows 1. Get IMAGE_DOS_HEADER, achieved by typecasting ImageBase to IMAGE_DOS_HEADER -Definition of IMAGE_DOS_HEADER -PIMAGE_DOS_HEADER Dos = (PIMAGE_DOS_HEADER)ImageBase; 2. Add IMAGE_DOS_HEADER.e_lfanew + sizeof(DWORD) and the base address of our DLL to get IMAGE_FILE_HEADER -Definition of IMAGE_FILE_HEADER -PIMAGE_FILE_HEADER File = (PIMAGE_FILE_HEADER)(ImageBase + (Dos->e_lfanew + sizeof(DWORD)); 3. Add the address of IMAGE_FILE_HEADER with the sizeof(IMAGE_FILE_HEADER) to get the address of IMAGE_OPTIONAL_HEADER -Definition of IMAGE_OPTIONAL_HEADER -PIMAGE_OPTIONAL_HEADER Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)File + sizeof(IMAGE_FILE_HEADER)); int main(void) { PPEB Peb = (PPEB)__readgsqword(0x60); //64bit, its 2019 PLDR_MODULE pLoadModule; PBYTE ImageBase; pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink->Flink; //2 flinks to ntdll ImageBase = (PBYTE)pLoadModule->BaseAddress; //save us 1 million typecasts PIMAGE_DOS_HEADER Dos = (PIMAGE_DOS_HEADER)ImageBase; //typecast to IMAGE_DOS_HEADER structure if (Dos->e_magic != IMAGE_DOS_SIGNATURE) return 1; //fucked up, idk, baseaddress was bad PIMAGE_FILE_HEADER File = (PIMAGE_FILE_HEADER)(ImageBase + (Dos->e_lfanew + sizeof(DWORD)); //Imagebase + Dos->e_lfanew + sizeof a dword gets image_file_header PIMAGE_OPTIONAL_HEADER Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)File + sizeof(IMAGE_FILE_HEADER)); //file header + file header size gets us image_optional_header return 0; } -Convoluted fuckin mess -Thats how you can get access to PE file headers without invoking api calls -Once youve worked your way through PE file you can now walk Export address table of ntdll.dll -To get export address table we do -ImageBase + Optional->DataDirectory[0].VirtualAddress -Optional->DataDirectory is array of different structures -You can read more on these here IMAGE_DATA_DIRECTORY Values -Everything listed below is calculated as a virtual address (or relative virtual address) -Fancy word for, incomplete address, gotta brain it -All you need to do is ImageBase + RelativeVirtualAddress, gg -Must loop through the Export address table now for our functions -PDWORD FunctionNameAddressArray = (PDWORD)((LPBYTE)ImageBase + ExportTable->AddressOfNames); -Pointer to array of memory addresses of function names -PDWORD FunctionAddressArray = (PDWORD)((LPBYTE)ImageBase + ExportTable->AddressOfFunctions); -Pointer to array of function addresses -PWORD FunctionOrdinalAddressArray = (PWORD)((LPBYTE)ImageBase + ExportTable->AddressOfNameOrdinals); -Pointer to array of function positions in array -Loop through ExportTable->NumberOfNames -for(DWORD dwX = 0; dwX < ExportTable->NumberOfNames; dwX++); -Get function name from NumberOfNames ordinal -FunctionName = FunctionNameAddressArray[dwX] + (PBYTE)ImageBase; -This will be the literal string of the function name e.g. "LdrLoadDll" -Check with string compare to string hashing -String hashes -I use wcscmp (unicode strcmp) in this example for simplicity -When dwX in FunctionNameAddressArray is the function name we want we use dwX to get the index in FunctionAddressArray and FunctionOrdinalAddressArray -LdrLoadDll = (LDRLOADDLL)((DWORD64)ImageBase + FunctionAddressArray[FunctionOrdinalAddressArray[dwX]]); -I use DWORD64 because this is a 64bit implemention, if 32bit can use regular DWORD #include windows.h #include "peb.h" typedef NTSTATUS(NTAPI *LDRLOADDLL) (PWCHAR, DWORD, PUNICODE_STRING, PHANDLE); int main(void) { PPEB Peb = (PPEB)__readgsqword(0x60); //64bit, its 2019 PLDR_MODULE pLoadModule; PBYTE ImageBase; LDRLOADDLL LdrLoadDll; pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink->Flink; //2 flinks to ntdll ImageBase = (PBYTE)pLoadModule->BaseAddress; //save us 1 million typecasts PIMAGE_DOS_HEADER Dos = (PIMAGE_DOS_HEADER)ImageBase; //typecast to IMAGE_DOS_HEADER structure if (Dos->e_magic != IMAGE_DOS_SIGNATURE) return 1; //fucked up, idk, baseaddress was bad PIMAGE_NT_HEADERS Nt = (PIMAGE_NT_HEADERS)((PBYTE)Dos + Dos->e_lfanew); //Dos + Dos->e_lfanew == IMAGE_NT_HEADERS PIMAGE_FILE_HEADER File = (PIMAGE_FILE_HEADER)(ImageBase + (Dos->e_lfanew + sizeof(DWORD)); //Imagebase + Dos->e_lfanew + sizeof a dword gets image_file_header PIMAGE_OPTIONAL_HEADER Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)File + sizeof(IMAGE_FILE_HEADER)); //file header + file header size gets us image_optional_header PIMAGE_EXPORT_DIRECTORY ExportTable = (PIMAGE_EXPORT_DIRECTORY)(ImageBase + Optional->DataDirectory[0].VirtualAddress); //get Export address table PDWORD FunctionNameAddressArray = (PDWORD)((LPBYTE)ImageBase + ExportTable->AddressOfNames); //array of function names PDWORD FunctionAddressArray = (PDWORD)((LPBYTE)ImageBase + ExportTable->AddressOfFunctions); // array of function addresses PWORD FunctionOrdinalAddressArray = (PWORD)((LPBYTE)ImageBase + ExportTable->AddressOfNameOrdinals); //array of function positions in array DWORD dwX; for (dwX = 0; dwX < ExportTable->NumberOfNames; dwX++) { pFunctionName = FunctionNameAddressArray[dwX] + (PBYTE)ImageBase; DWORD dwFunctionHash = VxHashString(pFunctionName); if(wcscmp(L"LdrLoadDll", pFunctionName) == 0)//dont use string compare, this is an example, cant use functions if youre position independent :) { LdrLoadDll = (LDRLOADDLL)((DWORD64)ImageBase + FunctionAddressArray[FunctionOrdinalAddressArray[dwX]]); break; } } return 0; } Obviously this is an example so there are a few problems with the code showed above. We cant use LdrLoadDll without first importing RtlInitUnicodeString :) also, youre wondering, why LdrLoadDll? Why not LoadLibrary? First I will show a full implementation of the position independent code with RtlInitUnicodeString and LdrLoadDll and then well discuss API forwarding on windows The following example gets both the PEB and the PRTL_USER_PROCESS_PARAMETERS but also implements string hashing. 0 function calls :) It stores the function calls in the API_TABLE structure :) #define pRtlInitUnicodeString 0x29b75f89 typedef VOID(NTAPI *RTLINITUNICODESTRING) (PUNICODE_STRING, PWCHAR); #define pLdrLoadDll 0x307db23 typedef NTSTATUS(NTAPI *LDRLOADDLL) (PWCHAR, DWORD, PUNICODE_STRING, PHANDLE); typedef struct __APITABLE { RTLINITUNICODESTRING RtlInitUnicodeString; LDRLOADDLL LdrLoadDll; PRTL_USER_PROCESS_PARAMETERS UserProcessInfo; DWORD64 PeBase; DWORD64 dwError; }API_TABLE, *PAPI_TABLE; int APIENTRY wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow) { PPEB Peb = (PPEB)RtlGetProcessEnvironmentBlock(); PLDR_MODULE pLoadModule; API_TABLE Api; pLoadModule = (PLDR_MODULE)((PBYTE)Peb->LoaderData->InMemoryOrderModuleList.Flink->Flink); Api.PeBase = (DWORD64)pLoadModule->BaseAddress; Api.UserProcessInfo = (PRTL_USER_PROCESS_PARAMETERS)Peb->ProcessParameters; Api.RtlInitUnicodeString = (RTLINITUNICODESTRING)ImportFunction(Api.PeBase, pRtlInitUnicodeString); Api.LdrLoadDll = (LDRLOADDLL)ImportFunction(Api.PeBase, pLdrLoadDll); if (!Api.LdrLoadDll || !Api.RtlInitUnicodeString) goto FAILURE; return ERROR_SUCCESS; FAILURE: return 1; } PPEB RtlGetProcessEnvironmentBlock(VOID) { return (PPEB)__readgsqword(0x60); } DWORD64 __stdcall ImportFunction(DWORD64 ModuleBase, DWORD64 Hash) { PBYTE pFunctionName; PIMAGE_DOS_HEADER Dos; PIMAGE_NT_HEADERS Nt; PIMAGE_FILE_HEADER File; PIMAGE_OPTIONAL_HEADER Optional; RtlLoadModuleHeaders(&Dos, &Nt, &File, &Optional, (PBYTE*)&ModuleBase); IMAGE_EXPORT_DIRECTORY *ExportTable = (PIMAGE_EXPORT_DIRECTORY)(ModuleBase + Optional->DataDirectory[0].VirtualAddress); PDWORD FunctionNameAddressArray = (PDWORD)((LPBYTE)ModuleBase + ExportTable->AddressOfNames); PDWORD FunctionAddressArray = (PDWORD)((LPBYTE)ModuleBase + ExportTable->AddressOfFunctions); PWORD FunctionOrdinalAddressArray = (PWORD)((LPBYTE)ModuleBase + ExportTable->AddressOfNameOrdinals); DWORD dwX; for (dwX = 0; dwX < ExportTable->NumberOfNames; dwX++) { pFunctionName = FunctionNameAddressArray[dwX] + (PBYTE)ModuleBase; DWORD dwFunctionHash = HashString(pFunctionName); if (Hash == dwFunctionHash) return ((DWORD64)ModuleBase + FunctionAddressArray[FunctionOrdinalAddressArray[dwX]]); } return 0; } BOOL RtlLoadModuleHeaders(PIMAGE_DOS_HEADER *Dos, PIMAGE_NT_HEADERS *Nt, PIMAGE_FILE_HEADER *File, PIMAGE_OPTIONAL_HEADER *Optional, PBYTE *ImageBase) { *Dos = (PIMAGE_DOS_HEADER)*ImageBase; if ((*Dos)->e_magic != IMAGE_DOS_SIGNATURE) return FALSE; *Nt = (PIMAGE_NT_HEADERS)((PBYTE)*Dos + (*Dos)->e_lfanew); if ((*Nt)->Signature != IMAGE_NT_SIGNATURE) return FALSE; *File = (PIMAGE_FILE_HEADER)(*ImageBase + (*Dos)->e_lfanew + sizeof(DWORD)); *Optional = (PIMAGE_OPTIONAL_HEADER)((PBYTE)*File + sizeof(IMAGE_FILE_HEADER)); return TRUE; } DWORD HashString(PBYTE String) { DWORD dwHash = 0x1505; INT nX; while (nX = *String++) dwHash = ((dwHash << 0x5) + dwHash) + nX; return dwHash; } Now, to complete this paper Id like to review API forwarding on windows. On windows because a lot of functionality is simplified e.g. GlobalAlloc. there is a lot of forwarding in place which can be used for hooking/heuristic analysis. For example: 1. malloc / calloc 2. GlobalAlloc / LocalAlloc 3. HeapAlloc 4. RtlAllocateHeap 5. MmAllocateContiguousMemory 1. CreateFile 2. CreateFileExW 3. NtCreateFile 4. ZwCreateFile 1. LoadLibrary 2. LdrLoadDll 1. GetProcessHeap 2. PEB->ProcessHeap You get the point. Every API forward is a place an AV can hook you. Be careful, VXers. Of course avoiding API forwarding doesnt save you from dynamic binary instrumentation analysis (DBI), but there are ways to avoid this, but that is a paper for a later time :) Oh, and if you want to see an ASM implementation of the code discussed above, hh86 did it. Its her DreamLoader project. https://github.com/86hh/DreamLoader -Smelly