
yeah good morning Munich thanks for coming and welcome to indirect SS calls a journey from high to low as already mentioned my name is Daniel fter I'm from inbrook and the founder of Rebel redops information security with which I mainly focus on offensive security staff and today we will look uh take a closer look at direct to calls and indirect to calls this talk will cover um system calls in general in Windows OS why are they necessary how they are used in Windows then we will speak about direct system calls um why the red teamers use them or no longer use them at the moment and what is the concept of directives calls we will will also speak about
indirect system calls why red te switch from direct s calls to indirect s calls um what are the limitations of indirect Su calls uh we will also build step by step our own indirect sus call Shell Code loader and at the end we will also talk a bit about um how EDR can use event view for Windows ATV atw uh to D to detect or prevent direct and indirect susal execution and also compare the uh the threat stack call stack from different Shell Code loaders okay so Chapter One windows s system calls so um for what are they responsible when you imagine you have an operating system like Windows you have your user mode and your kernel mode and
if you want to switch or make a transition from user mode to Kernel mode we uh we need system calls so um system calls are necessary for example to access um Parts which are placed in kernel like uh Hardware device drivers canos printers uh if you want to save a file you need um temporary access to the file system therefore we also need um system calls so what is this what is a sus call or system call when you um want to take a look at the SS call instruction you can uh use a debugger like wind GB and search for a native API like anti allocate virtual memory debug it and we can see that we have in the second line
a move instruction which puts the number 18 which is the SS call number or also called system service number into the register eex and then we have the sus call instructure which executes the sus call or the sus call number very important each Su call has a specific ID which can switch from Windows to Windows and also from version to version so they can differ a practical example uh when we use system calls so for example you have not tab open you type in something you want to save it to disk then you need or the operating system needs temporary or the process more specific needs temporary access ACC to the file system in kernel and also to the required
device drivers and both components are placed in the windows kernel that's the reason why we need system calls to make that temporary transition so when we take a look at this illustration we can on the upper side see the windows user mode the Lower Side um Windows kernel mode we have on the left side um notepad to DXE and we want to save a file to disk so we first have to access the window API or Windows 32 API which is always located in or could be located in kernel 32 DL or kernel Bas DL then we want to um access the corresponding native API which is in this case anti create file and is located in the memory area of
ntdll and the native API contains then the sus stop which also includes the sus number or the sus call instruction itself um in the case and yeah these are those are the instructions which we use to make that temporary transition from user mode to Kernel mode so in summary we can say um every SS call has a specific ID it can differ from Windows to Windows um the SS call stop is retrieved from ntid and the sysem call itself is part of the sus call stop and it gives us the possibility to enable temporary privileged access to Kernel mode to access device drivers or file system system for example when we want to save the file so we now get um briefly
understanding of what system calls in windows are used and now we want to try to understand direct system calls so direct system calls are I would say a common or were a common red team technique to for example execute malicious code to use it for Shell Code execution or also to use it to dump the alas process like the tool from outflank which is called dumpert and it simply say it allows us the execution of susol or the execution of the susol stop without using or accessing ndl hence also the name direct Su call so when we take a look at this illustration we see compared to the notepad process we have our malware toxe and we do not want to retrieve the
system call or the sus call stop from ntid uh instead we want to directly implement it into the assembly itself therefore we have our four lines of code directly implemented as assembly code um into the Shell Code loader itself so the question is why would we need or why do we use direct Su cost the answer is very simple when you have or most edrs in the in the time or many edrs um use a technique which is called user user mode API hooking and this techniques gives gives the um Ed the possibility before you the SS call is really executed um to redirect the executed code in context of an Windows API um to analyze it and yeah to check
if we are executing malicious code or not they can use or idas use different kind of hooking techniques so before patch cout it was also possible to use um Kel hook hooking techniques like sstd hooking um there are still some vendors which use a a patch card bypass to use that kind of technique but most uh vendors are yeah I would say forced into user mode by patch card and use um most most common technique which is called inline API hooking which is simply a five by long unconditional jump instruction and yeah redirects the code to the dll of the EDR so we can see this in this illustration again on the upper side user mode on the Lower Side kernel
mode our malware uh will or we will execute windows apis in our malware so we have access kernel 32 DL kernel based D and then we need the corresponding uh Native API in ntid L but now we are not directly executing the sus stop or system call instruction um because the executed code is now first redirected to the EDR level so the EDR does um inject into user mode in every process his own dll which we could also name hook dlll and if the EDR says okay the code is uh is malicious then he will stop the execution if the execution is fine or the EDR is fine with the execution um we jump back to
ANL and then execute the sus call instruction so where are now those EDR hooks um when they started using EDR um or us user mode hooking about I would say six six or 7 years ago um mostly they placed their hooks in antd what's the reason for that because antd is more or less the the lowest common denominator before you make the transition from user mode to Kernel mode but in the meantime when you analyze different kind of EDR you will see that they also um use now um hooks in Auto DLS like um the win inet dll or the wi 32 U DL and many more um others depending on EDR it can be that
or the amount of hooks depends strongly on the EDR so for example you can have an EDR which has about 28 user mode hooks but I also analyzed edrs which have 86 Ed um user mode hooks in user bace so the question is now are we up by Hooks I would say no uh because they cannot simply hook all Native apis this is simply a resource problem cost time um and would slow down the operating system and yeah generally when you analyze an EDR you will see that they mostly focus on um API calls which are heavily abused in malicious context like anti allocate vir memory and similar um API calls if you want to check out how does
an inl inline hook and look like you can use also a debug like wind dgb so on the lower illustration we see a clear um CSCO stop I would say so we have um in the around the red line uh we see that we have a move instruction which puts again the susol service number in this case 18 into eex register U prepare it for execution and when you have an EDR which hook those a or this API on the upper side we see that the second line the move instruction is replaced by an 5X B long unconditional jump instruction and this is the jump which is responsible for redirecting the executed code in context of the API to the dll
from the EDR so what are now the consequences for red team um yeah it makes hooking makes it more difficult to execute malicious code such as Shell Code and we as red teamers can think about different techniques to bypass EDR so we can search for um not hooked apis we can try to use user mode unhooking we can try to temper in EDR and we can use techniques like indirect sus call and direct Su calls and in this talk we will focus on direct and indirect Su calls okay with chapter three we will start uh developing our indirect susal Shell Code loader and we start with a simple wi2 API loader um this will be our reference
loader so from evasive uh perspective Windows 32 32 API loader without using additional unlocking is not really useful for um EDR evation but it serves us simply as a reference loader so when we take a look at this illustration we have on the left side our wi 32 API Shell Code loader use four apis in this loader and because we are using Windows apis we have to ask for the windows API virtual El for example in kernel 32 or kernel Bas D then we we need the corresponding um Native API anti allocate virtual memory in ndl and then we can execute the csal stop from the text section in or the memory uh in ndl so what do we need in our loader we
have to declare our Shell Code we need um possibility to allocate and commit memory in this case we are using um virtual aloc then we want to copy the Shell Code by using wi process memory uh into memory we want to create a new fret um by or execute the Shell Code by creating a new fret and we want to wait until the sh C execution is finished until the main threet can then exits and therefore we use um the windows API wait for single object so in summary we can say as already mentioned as from the evasive perspective not really useful um as until the point you would combine it with a technique like user mode
unhooking but in this case it serves simple as a reference loader for us so in the next step we want to make the transition from high level apis from Windows apis to medium level apis to Native apis so this is the first modification to our Windows 32 API loader and we want now to avoid that we ask kernel 32 D or kernel based D for the windows API and directly Implement um Native apis into our Shell Code loader so when we compare this illustration with the illustration before we see that we now do not have Longo kernel 32 DL and kernel based DL involved uh instead we want to directly ask anti-d for the respective um Native apis which we need
in our native API Shell Code loader compared to our Windows 32 API loader we have to manually Define the instu for the function pointers in our um Shell Code loader for each native API and in the second step we um have to ask ndl or we need to get the memory address for each native API so the first step we have to use the windows API get module handle a to open a handle to ndl and then we use get proc address to get the memory address for the corresponding native API and we simply want to replace all windows windows 32 apis against the correlated native apis in summary we can say um that we
have made the transition from Windows 32 apis to Native apis we do not longer import windows apis by using kernel 32 or kernel based dll and if an EDR would now theoretically only set his hooks in kernel C2 DL we would have bypass DDR but in practice this is not um really the case so we have to go forward with our development process so in the next step we want to make the transition from native apis One Step lower to lowlevel apis to direct SS calls so we want to build a direct SS call loader and compared to um to reference loader we will do now our second modification so we want night now to uh
reach the goal that we do not longer ask ndl for the um sus stop or the sus call instructions instead we want to directly implement the Ned sus stop or um code into our direct to called share code loader so when we take it again a look at the next illustration we see that we now have no longer involved ntid um instead we directly uh search for or implement the SS stop those four instructions directly into the text section um of our assembly again we uh want to use native apis and uh do not want to ask but compared to before we want not to ask ntid so we directly implement it and we have again to manually Define the
struction pointer as in the native API loader but now we want to directly implement the assembly code which we need so we can see in the illustration this is the one of the sus call stops in this case for the native API and the allocate virtual memory and we directly implement it implement it into the text section of our Shell Code loader because we are doing this in Visual Studio we also have to enable um support for Microsoft assembler and from a perspective of EV hooking this loader would be fine so a few years ago direct to loaders or direct t calls in general worked very well well worked very well well against edrs but the problem now is that most
edrs also use event tracing for Windows and when they for example analyze the Fred call stack from your dius C loader um they will they will catch you why when you take a look at the right side we have um the call stack from our direct use call loader and and on the left side from the windows 32 API load which has a very very high leged call stack and we can see on the right side that the call stack from the diis C looks very weird for example the um the last element um anti we for single object is executed from the text section of the shell Cod loo itself and that is a 100% ioc because um the sus
instruction or the API should always be executed from um entity L which means normally entity L should be um the last element on top from the call St so that's the reason why we have to switch to or make the next transition transition from direct to calls to indirect to calls so this is our third modification compared to the reference Minesota 2 API loer and um the um we want now to to reach that the this the the ioc which an EDR can use to to catch your direct sus loer that we spoof we are able to spoof the sus and the return address so it's mostly the same code as a direct C loer we have just a small
change um when we take a look at this illustration we see for example for anti allocate vir memory that after putting the system uh service number into the register eex we do not directly execute the SS call and the return instruction instead we use a jump an unconditional jump and jump into memory of entity L by this we can reach the goal that the sus call um instruction and the return instruction is not executed in text section of your shell Cod loo itself instead it is executed uh in ntid and this gives us the advantage that now entl is put on top of the stack from your um share Cod loader or from your fret more spe
specific so we have to manage the susol and return instruction therefore we have to do a few things we have again to open a handle to ntid then we need to get the start address from native API in ntid we have to set the offset to get the memory of the susol instruction and then store that memory address in a global variable and we have to do this to do to do this for each native API which we use in our could load also four times in this case so again we use get module handle to open a handle to ndl then we use get proc address to get the start address of the function but
now because we want to get the memory address of the sus instruction we have to set or to added an off um offset of 12 bytes why 12 bytes because that's the offset to get the memory address of the susol instruction in the susol stop then we we can declare a global variable to um hold the memory address of the ssll function and then later use it in our assembly code in our loader for execution and there you can see a comparison on the left side we have the um the sus Co stop from our direct s c Shell Code loader and on the right side from the indirect s c Shell Code loader and in the third line we have um this
small difference the sus call instruction is not directly executed in the text section instead we use this unconditional jump and jump to the memory address from susol in memory of ndl also in this case again we have because we do this in Visual Studio we have to enable Microsoft um assembl support and when we now compare it the the cost St from the the Shell Code loader you can see that the indx Cod loader has a much more legit cost de compared to the direct to why because um here the the last element um is the weight for single object or anti- weight for single object API and is not uh executed now from the memory
of the susol loer itself instead we jump to ntid L as it should be and then executed in this memory so also when we compare it with um the in Lo on the right side with the windowss 32 API loader on the left side you see that the indirect Cal loader has a very high level of the GMS I would say okay in summary um cost analysis we can say that indirect Su calls can be used to or a good development further development from direct sus calls but also indirect sus calls are not a civil bullet um also indirect sus calls when you build up your own sh codo are can be just a part of the pzle so you also have
to care about other things like encryption import uh table hashing you have to care about obviously ation you have to care about maybe Hardware breakpoints uh so this is just a part and not a silver bullet and even or depending on EDR it could still be that you get detected uh by analyzing the cack why there are also some edrs which do not just check for if the sus call is executed in the right location they also can or also check for example Microsoft Defender ATP um if the whole cost is so they yeah check the whole call St um if you want to learn more about Fred call booving in general so this is outside
for this for this talk but um there is a very nice guy or clever guy which is called Alexandro magosi alas CL virus which do a lot of great work in that area uh he also for example developed CIS free and gave this year this year a very uh nice talk about costex boofing on Defcon so I highly recommend to check this out okay in summary we can say indirect to colus we make successful transition from direct s calls to indirect s calls and we do not do now just partly execute um part of the um susco stop from the text section of the direct susco loader and jump on the right time to the memory
address from ntid okay so in summary we learned a bit about Windows sus calls about the concept from direct sus calls um we started building our own uh indirect CSCO loader so we started with a Windows 32 apii loader which is more or less our reference then we make the transition to um a native API loader we build in The Next Step a direct tocol loader then an indirect Su loader uh did a bit um cost analysing and yeah so far so good so this was a very was very fast if you want to do all that stuff in much more detail I build up um a repository which was presented a few months ago on defron 31 um which is
a very detailed Workshop where you can read all about this stuff in much more detail and develop your uh indirect loader and debug it uh step by step so at this point many thanks for your attention many thanks to the whole uh Team from bite and all volunteers and all sponsors for the organization really great event and yeah have fun with the rest of the conference thank you thank you thank you very much for the call uh for the talk any questions from the
audience hello um maybe this is a stupid question because I come more from the Linux side so I'm a little surprised has the windows Cal no event framework that you can just say and every time a process is ENT colel mode give me an an event then you can avoid all the hooking for example on Linux I just enable a trace point for system callgate and then us space can do what whatever they want and every time they enter the kernel I get an col event uh it could be that Windows Event racing has such events I'm not aware about at the but I think um they definitely have it because as already mentioned edrs use it also to um
check where the susol is executed from so I think there have to be a mechanism like that that they can use atw to to check those events yeah okay thank you any other question I think we have time for one more
question um hi thank you for your talk um the problem we're having usually when we're trying to evade edrs that we don't know which functions are being hooked or which kind of telemetry that is being you know sent to the EDR so in your experience is there any kind of um project a public project repo that would um have S some information about multiple edrs uh regarding the um let's say the detection of these techniques um so in general the problem is that EDR Vos are very sensitive about that so I personally have a private repository where I collect those information but I cannot release it otherwise I get problems with the vendors um but there is a repository I
think from Mr unic coder which collects for example which hooks uh or which apis are hooked by which EDR but I'm not sure if it is um at the last if it is um the last version from from the hooks which are set um yeah this is one of the repositories which I know so I I have one but I yeah I'm not will not release it otherwise I get again problems okay thank you very much again for the great talk um I'm sure he's available for further questions in the lobby and thanks again thank you