![]() |
|
[The Brotherhood] PEB Walking, and Exploring ntdll.dll - Printable Version +- Hack Forums (https://hackforums.net) +-- Forum: Hacks, Exploits, and Various Discussions (https://hackforums.net/forumdisplay.php?fid=45) +--- Forum: Blackhat • Red Team • Offensive Security (https://hackforums.net/forumdisplay.php?fid=447) +---- Forum: Cryptography, Encryption, and Decryption (https://hackforums.net/forumdisplay.php?fid=126) +---- Thread: [The Brotherhood] PEB Walking, and Exploring ntdll.dll (/showthread.php?tid=6266052) Pages: Pages
1
2
|
PEB Walking, and Exploring ntdll.dll - Hackers - Mar 14, 2024 PEB Walking, & NTDLL ![]() Enjoy More Software, Source Code, Tools, and Tutorials https://hackforums.net/showthread.php?tid=6265944 https://hackforums.net/showthread.php?tid=6266404 https://hackforums.net/showthread.php?tid=6265473 https://hackforums.net/showthread.php?tid=6265665 https://hackforums.net/showthread.php?tid=6266377 https://hackforums.net/showthread.php?tid=6264320 https://hackforums.net/showthread.php?tid=6263383 https://hackforums.net/showthread.php?tid=6264286 https://hackforums.net/showthread.php?tid=6266614 https://hackforums.net/showthread.php?tid=6264522 https://hackforums.net/showthread.php?tid=6266052 https://hackforums.net/showthread.php?tid=6265700 https://hackforums.net/showthread.php?tid=6266289 https://hackforums.net/showthread.php?tid=6265197 https://hackforums.net/showthread.php?tid=6265430 As you may know, I have been learning C++ the last few months and researching low level functions. This has always been part of my goal in life, to better understand operating systems and maybe one day even work on a new one. The following information is for educational purposes only. You will learn more about: - PEB Walking - TEB / Thread Environment Block - ntdll.dll - Documented & undocumented Windows functions - linked research papers for you to discover all the possibilities ... aka 1 step closer to syscalls & interacting directly with, or as close as possible to, the kernel. No, not a popcorn kernel. When it comes to syscalls & really any functionality in Windows, I've learned about a system called 'rings'. Think of it like limbo - how low can you go? Ring 0 & kernel mode is like winning limbo with it an inch off the ground. Ring 3 is like winning participation trophies - anyone can do it. ![]() What if I told you that you could use any Windows dll / library, without including windows.h, winternl.h, or any Windows header file? What if I told you we can do it without a third party tool, and also without even using standard LoadLibrary functions to do it? The first thing I want to make clear: You will be able to successfully use any library or Windows function you want, without including any headers in your final program - This is an exclusive thread for Hack Forums by Brotherhood ![]() This advanced kernel learning part of my journey began when I was researching Hell's Gate, Windows syscalls, and more. This led me to research a few other related projects: Halos Gate, Tartarus Gate, and more. I wanted to know more about it, but didn't know enough. I went head down and built 3 crypters that I released, 2 that are unfinished, and I started my master project, Lucid Dream DMT. I had to stop Lucid a few weeks ago to focus on the other projects, learn more, keep researching. I am happy to say that last night I made a huge breakthrough. Before last night I started with some simple methods to create my own definitions for default functions in Windows: Code typedef NTSTATUS (NTAPI *pNtAllocateVirtualMemory)(With these type definitions, I could call on them as replacements to the real nt functions. It interfaced with Windows, it worked at obscuring my program (to legally & ethically protect intellectual property & data privacy) in runtime, and it was a good start. Types are very important for making sure your program in user-mode can talk to the kernel. Doing it like this means we can potentially avoid calling on a library to get a function/type because we've defined it in our code ourselves. The problem? Before last night it was still using LoadLibrary and GetProcAddress functions. Don't worry, I'll show you exactly how it's all done! First let's cover the basics: finding these typedefs in the first place. You can head to the official learning docs from MS: https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/_kernel/ For my first two functions I created typedefs for, I found them here: https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntfreevirtualmemory https://learn.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntallocatevirtualmemory After playing with these for a few days, I discovered guides about walking the PEB, using base addresses, and more. To do this, one of the first things involved is getting the 'pbi' or Process Basic Information. This is what lets us get the base address of a func. So, I head over to MS' docs and look for the typedef for this. Code typedef NTSTATUS (NTAPI *pNtQueryInformationProcess)(During this I also learned I would need to define my own types for PROCESS_BASIC_INFORMATION & more. Hint: When trying to remove windows.h or winternl.h from your end program, just do it & then go to MS page to find all types and add to your custom .h file. Or, you can ask GPT for types too which (if its documented at least) is pretty reliable. Great, now I can start to think about PEB a bit more, but at this point in my journey I started slow. At first I started with code like this: Code HMODULE ntdll = LoadLibraryW(L"ntdll.dll");There are a few key pieces to that code. For one, I am using LoadLibraryW() to get the ntdll module. Then although I am using my own type (for NtQueryInformationProcess), I still was relying on GetProcAddress to load that in originally with my own type. How can I load in an Nt function, without using GetProcAddress? And how can I load in without LoadLibrary_ funcs?. I had to keep researching. It was at this time that I found other projects such as Artemis. Artemis was an important project to take a look at because it clued me into the load order module list - or in other words, the list of all modules / dlls loaded into the current program, in runtime. I quickly adopted a way to loop through all loaded modules and string-match for ntdll.dll (image from Artemis, not me): ![]() Why ntdll? It's always loaded. It's also our little "gateway" to the rest of the Windows funcs. Now that I had a method to find ntdll without using LoadLibraryW like my original code, I ended up with this: Code void FindNtdll() {First thing I did was update the memory functions to use this new method for testing. Luckily the rest of the program worked fine! This means ntdll from the loaded module list & finding it via PEB "walking" works! No need to waste time with a silly load library function anymore just to load up ntdll! Let's break it down.... Code // Access the PEB directly from the TEB (Thread Environment Block)Code PPEB_LDR_DATA ldr = peb->Ldr;Code for (LIST_ENTRY* entry = moduleList->Flink; entry != moduleList; entry = entry->Flink) {Within minutes my mind was racing... How can I load up another library? I can't use the same method because ntdll is auto-loaded and that's the only reason it's in the module list. kernel32.dll is not auto included for example. - EDIT: I am not able to see kernel32 or kernelbase on my tests, but documentation does say it is auto loaded. I will have to figure out why I can't see it - perhaps a timing issue or if not that then an obscure bug I suppose. - However, even if you don't get the auto loaded kernel, you can load it which is what I did after never finding kernel32/base dlls loaded: Can it be loaded now that we have ntdll? Yes : thanks to ldrLoadDll. My first undocumented function! http://undocumented.ntinternals.net/index.html?page=UserMode%2FUndocumented%20Functions%2FExecutable%20Images%2FLdrLoadDll.html ![]() Before I jump into this, I want to mention my function GetFunctionAddress - it's how we finish off this first part by not using GetProcAddress. Code // Function to parse the export table and get function addressesThe reason we can use this is because: - we have ntdll's base address / full handle - we can request a string-value function name such as "ldrLoadDll") - this works for any dll we load into our program, and for any function - even undocumented This custom function from me is critical for making sure we're not using GetProcAddress. Why don't we use it? Well, our goal is to protect intellectual property & data in runtime, and using GetProcAddress or a LoadLibrary_ func is a great way for a malicious actor or another software to detect what modules you use & perhaps try to pull analyze your program after you use one. The method in this thread helps with this tremendously, and of course brings us 1 level closer in our ring system (aka "limbo" analogy above ~ how low can we go?). for ldrLoadDll, let's define our type just like we did for others: Code typedef NTSTATUS (NTAPI *pLdrLoadDll)(PWCHAR PathToFile, ULONG Flags, PUNICODE_STRING ModuleFileName, PHANDLE ModuleHandle);Now let's use it to try loading up another library. How about... kernel32? This uses ntdll's base address & the get function address method above: Code auto LdrLoadDllFunc = (pLdrLoadDll)GetFunctionAddress(moduleEntry->DllBase, "LdrLoadDll");Now let's use it. I can't begin to express how overjoyed I was that this worked: Code UNICODE_STRING dllName;It worked! I celebrated, jumped up & down, etc. But it was time to try 1 more thing : using kernel32 to create a process. Code typedef BOOL (WINAPI *pCreateProcessW)(Cool, we got the definitions... Code auto CreateProcessWFunc = (pCreateProcessW)GetFunctionAddress(moduleHandle, "CreateProcessW");We have the address for create process... Oh my (right??), time to use it! Code STARTUPINFOW si = {};It was at this point that I knew I had done something magical. I had successfully: - hooked into ntdll to get all functions - used ntdll mem functions & now ldrLoadDll - used ldrLoadDll / a low level function to load another library (kernel32) - used the loaded kernel32 handle to create a process Check out the complete POC here: https://github.com/LNodesL/PEB-Crawl-POC What's next? Well, ntdll has thousands of functions related to it, some documented, many undocumented, and most are useful: http://undocumented.ntinternals.net/index.html Possible ways to advance further with the info in this thread: - Leverage the kernel mode Zw methods/types instead of the Nt versions (user mode) - use a DLL instead of a PE/exe to access this same information I'll be working on finishing up my Github repo for this POC (proof of concept) to include the remaining win types in the .h files. Then I'll be bringing this over to my Lucid Dream DMT project for more research. Now that I am loading ntdll from the module list & finding function addresses dynamically, and able to load any other library, the next step is to actually map out the real syscall IDs and use those for even more direct access to kernal / ring 0. Maybe I'll release another tutorial on that, but for now I have a lot more reading to do to learn more about methods like this: ![]() Special shoutout to Geoff Chappell who documents so much about this on his website too. Special thanks to all the members who helped me get started with C++. You know who you are, but I appreciate the assistance. I hope in turn this thread can help others :) RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - notagh0st - Mar 14, 2024 mmmmm love me some undocumented WinAPI's. Really great writeup! RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - ttbr0 - Mar 15, 2024 i really like seeing these technical posts. unfortunately its not the norm here so i appreciate it a lot. great work. i do want to mention that kernel32.dll (and kernelbase.dll by extension) is always loaded into standard processes. ntdll will call LdrLoadDll to load kernel32.dll (which will load kernelbase.dll) for process initialization purposes with things like the heap, command line arguments, and console allocation (for console processes). so you will find kernel32 in the peb's module list after ntdll (i think its the next entry). RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - Hackers - Mar 15, 2024 (Mar 14, 2024 10:26 PM)shatter Wrote: Very awesome! :) Thanks!! Yeah HG seems like a solid method & a lot of the concepts are still valid / useful today. I had issues loading up HG related POC repos as-is without changes being needed, which basically led to me doing all this on my own. The other piece was most of the examples requiring assembly and I had trouble finding pure C/C++ solutions. However that might be more because of the syscalls and compiling as a driver, so i think in the next phase of my research I'll be required to do that anyways, but we'll see. Thanks for that - definitely agreed that people just want a magic answer that doesn't require effort. For me I'm more interested in learning how to do it than actually having the working tool/end product so I'm always trying to go step by step / line by line to figure things out. I hope others will read my thread here, the ability to now drop in any lib or function should be useful. I'm going to go back to some of my other projects too to see how I can bring this in. (Mar 14, 2024 11:47 PM)notagh0st Wrote: mmmmm love me some undocumented WinAPI's. Really great writeup!Thanks, appreciate that! Let me know if you have any questions (Mar 15, 2024 01:30 AM)ttbr0 Wrote: i really like seeing these technical posts. unfortunately its not the norm here so i appreciate it a lot. great work.Thanks, glad to contribute :) I think that the kernel32.dll loading may be dependent on device/program/etc for either being available in Ldr, or maybe it's a permission or timing issue on my end - because I can't see that & I only get my exe & ntdll.dll. If kernel32 is available I'm glad I couldn't find it because it led to me figuring out the load lib func, but I am definitely going to re-review this. If I can find it I'll update the thread with more info about this. Thanks for sharing this info! RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - ttbr0 - Mar 15, 2024 (Mar 15, 2024 04:36 AM)nodes Wrote: Thanks, glad to contribute :) shouldnt be any permission (its within the same process) or timing (it should be there before your main function starts). perhaps its because the name is in caps (KERNEL32.DLL and KERNELBASE.dll) and your string compare is case sensitive? RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - Hackers - Mar 15, 2024 (Mar 15, 2024 06:14 AM)ttbr0 Wrote: shouldnt be any permission (its within the same process) or timing (it should be there before your main function starts). perhaps its because the name is in caps (KERNEL32.DLL and KERNELBASE.dll) and your string compare is case sensitive? that could be it if it was just on the string matching, but I print out every dll loaded too before the string match so I can see all and I've only ever seen the .exe & ntdll.dll loaded I'm guessing that kernel is not loaded yet when my code runs and it's a timing issue because otherwise it would show up. I can add a delay or other tests to see if this is true because documentation does suggest kernel is not guaranteed to be loaded immediately - but I would expect it to load before my code runs, so it does feel weird. Thanks again for this info, very good to know. RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - Euaggelistes - Mar 15, 2024 Thank you for sharing. This is huge to me. Really appreciate it! RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - Hackers - Mar 15, 2024 (Mar 15, 2024 06:35 AM)Euaggelistes Wrote: Thank you for sharing. This is huge to me. Really appreciate it! Thanks for that & you're welcome! I hope it can save people hours of research at least, and at best let them use things they may have never heard about. The other thing I'm hoping to achieve next is the actual syscall IDs to call directly, and am going to try to do it with pure C/C++ without having to use assembly if I can. Not sure if I'll succeed but that would be Part 2 of this thread basically. RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - SIM-5468029 - Mar 15, 2024 Great releases for the community! (Mar 14, 2024 10:26 PM)shatter Wrote: Very awesome! :) I've also come across another newer technique called EDR preloading, but I haven't had the chance to test it yet. (Mar 15, 2024 06:37 AM)nodes Wrote: Thanks for that & you're welcome! You will get the hang of assembly pretty fast! RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - Hackers - Mar 15, 2024 (Mar 15, 2024 07:24 AM)Kang Wrote: Great releases for the community!This is something I am looking into as well. Here's 1 article: https://pastebin.com/Kr5Je7bE Spoiler (Click to View) Also looking more into the load order and how you can have your own named dll load in first, to avoid another program from injecting theirs - but still researching right now, not coding this out yet. (Mar 15, 2024 07:24 AM)Kang Wrote: You will get the hang of assembly pretty fast!Thanks, it doesn't look so bad, it was actually more the compiling & includes that was throwing me off because I'm still learning Visual Studio. I think once I figure out the proper way to build in VS I can use assembly-based HG codebases easily. It had problems with g++ manual compiling, but again - glad I didn't figure it out otherwise I would've just used Halosgate and never learned as much as I had to here. RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - Infinity. - Apr 10, 2024 Man your tutorials are the reason which takes most of time on HF these days I tried a psuedo approach in Rust and here's the thing so far.. need more time in this Code fn main() {Will probably finish this this weekend or probably block you somehow <3 RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - Hackers - Apr 10, 2024 (Apr 10, 2024 11:12 AM)Infinity. Wrote: Man your tutorials are the reason which takes most of time on HF these days ahahaha! Nice, that's a huge compliment - thanks! I'll make sure to feed you some new content soon :) I am working on a DLL in C++ that you then load into Python or PHP to do some stuff as a POC, to make it easier to access lower level in those langs for things like this :) RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - JohnFitzgeraldKennedy - Apr 12, 2024 Very HQ post OP! I am coming back to HF after a long time away, and I just wanted to say, these types of posts are the exact reason why. Im a sucker for windows internals type stuff. Each post like this makes all the "pls give me FUD cypter I dont understand" posts worth it. Just wanted to call that out, looking forward to seeing more posts from you! (Mar 15, 2024 06:21 AM)nodes Wrote: I've only ever seen the .exe & ntdll.dll loaded Are you compiling your binary as a "native" binary? My understanding based on the imho very good book Windows Internals 7th edition (recommend reading this if you're curious on some other useful to know windows undocumented type stuff), and personal experience working on the same types of PE loading stuff you're working on (although it has been a while since I've worked on PE stuff) is that kernel32.dll and its associated sub DLLs will be loaded prior to your entry point function gaining code execution in most cases, unless the binary is so called "native" or doesnt have a specific subsystem. I think only a few processes which are early in the usermode startup for windows normally are "native" iirc. Might be worth checking your compilation settings, although I think use ntdll / direct syscalls is cooler anyways lol Will be waiting eagerly for a potential part 2 ;) RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - Hackers - Apr 14, 2024 (Apr 12, 2024 08:22 PM)JohnFitzgeraldKennedy Wrote: Very HQ post OP! I am coming back to HF after a long time away, and I just wanted to say, these types of posts are the exact reason why. Im a sucker for windows internals type stuff. Each post like this makes all the "pls give me FUD cypter I dont understand" posts worth it. Just wanted to call that out, looking forward to seeing more posts from you! Nice, welcome back! Glad to know this thread was cool to you :) There are definitely a lot of people, on any site, who just want the magical answers. I'm a bigger fan of learning, sharing what I learn, and encouraging people to build their own tools > trying to find a solution that probably won't be 100% perfect for every use case... You're probably right that the other dlls would be loaded prior to entry point, but I was surprised to not see it in modules list, so guessing it must be somewhere else, or it's something specific to my computer. I'll try to learn more about this This isn't a full part2, but is a followup thread related to this that I shared recently: https://hackforums.net/showthread.php?tid=6267385 RE: PEB Walking, and Exploring ntdll.dll ~ 2024 C++ Tutorial ~ - JohnFitzgeraldKennedy - Apr 14, 2024 (Apr 14, 2024 04:51 AM)nodes Wrote: You're probably right that the other dlls would be loaded prior to entry point, but I was surprised to not see it in modules list, so guessing it must be somewhere else, or it's something specific to my computer. I'll try to learn more about this Sorry to keep harping on this (just trying to provide hopefully useful info! will let it go after this reply...), but did you check if your PE is so called "native"? Ie., is the Subsystem field in the PE image "optional" headers struct set to 1? If so, only ntdll will be loaded by default. If its set to 2 or 3, (GUI or CLI Win32 app, respectively) the kernel should load/map kernel32.dll by default unless something has changed in recent Windows editions (X to doubt for backward compatibility reasons). If it is loaded you should see it using the same PEB in memory module walking technique used to find ntdll. Recommend reading chapter 3 of this book (or just the whole thing tbh, I love this book and cant recommend it enough) for more good information on processes/PE image loading under the hood in Windows: https://archive.org/details/windows-internals-part1-7th/page/n171/mode/1up Godspeed, and feel free to hmu if you have any questions, Im always happy to help if I can (especially on Windows internals stuff!) :) |