Hello and welcome to my talk about I met our more curtain My name is René Frank Rubin and I'm going to tell you something about exploit development and especially about how to buy us Different mitigation techniques of a met in the next minutes. So, let's have a look at the plan for the day First of all, I will give you a short introduction about my personal and my company after that we come to the basics So I will introduce Concepts like address visualization or data execution prevention to you We'll also talk about the firefox vulnerability, which I will use during this talk to demonstrate all the bypass techniques on top of it After that we come to the first emit related chapter. It's about finding or locating emit delay in memory And we will see why this is important in this chapter and after that I come to that once code reuse technique Which is a technique which is already public well known by exploit developers But I think if you are trying to talk about how emit can be bypassed this technique is really useful And that's why I've included it here after that we come to the different mitigation techniques of emit So today I will talk about the five different drop protection. So the return orientated programming protections and about address base ERF protection and how we can bypass these mitigation techniques At the end I will give you some final thoughts and show you the demonstration and you also have time to ask me some questions As already mentioned my name is Rene Frank Rubar Working since about two years at as a security consultant at second site And I'm also currently a student at the technical University of Vienna I'm doing there my bachelor thesis about exploitation and I hereby. I really want to thank my professor Christian platzer That he gave me this possibility to write about such a great topic I also have here one slide about my company second site I think the most interesting part for you is that we are currently hiring So if you are want to work as a security consultant in Germany Just drop me a mail or just go to our website or come to me after the talk Yeah basics Exploitation was quite easy 15 years ago So in the year 2000 if you have to write a buffer of low a stack-based buffer of low You just had to pay it until to reach the return address Overwrite the return address with a hard-coded address pointing again to the stack and place the area shellcode and the shellcode will be Executed and everything is working Nowadays everything becomes a little bit harder because we have many many different protections there which must be bypassed So on the left side you see a picture of some of the names of these protections This is not a complete list, but from the perspective of the attacker We have to buy us all these mitigation techniques and the two biggest ones here are data execution prevention tap and address visualization ESLR Just a quick question. Who of you knows data execution prevention? Just raise your hand Okay, it's good. And who of you knows address basically atomization. Okay, so just go very quickly over this and then we move on the idea of address basically atomization is that Everything is loaded at a random address in the memory So if I start firefox or any application two times everything the old code sections old data sections will be loaded at a random address So so from the perspective of the attacker I don't know anything where the data is in memory and The idea of data execution prevention on the other side is that data which is stored on the stack or on the heap There should just be data stored which is read and write table, but not execute table so that means I can just make assigned the The pages as read and write table, but not as executable That means if I store my shell code on a stack and try to execute it It would just segmentation for it because this page is not marked as executable and yes The typical way to bypass data execution prevention is to use a technique Which is called return on data programming that means I'm just returning to already existing code in the program So I'm just executing one to three instructions Which are currently there in the program and then return to the next one to three instruction Instructions and then chain all these instructions together to build new logic in the program for example logic to disable data execution prevention and Here you see why it's so hard to bypass address Be ceremonization and data execution prevention together because if a SLR is also there this address of this already existing code is Randomized so I don't know where this already existing code is stored in memory So the typical way is to first somehow bypass address visualization For example, I can turn the vulnerability into an information disclosure vulnerability by making partial overrides or Overriding the length of string fields or something like that and then leak the base address of One module and based on this module I can then develop a rock chain to disable data execution prevention You will see this concept in some slides some later slides When I show you the firefox vulnerability and this case I have chosen The firefox array reduce write vulnerability, which is a little bit old amount So it's from 2011 because then I can show you the exploitation code without risking that any attacker can abuse this code here That's what also works very reliable against all different kinds of operating systems So starting from windows xp so aspect zero until windows 8.1 And we can bypass address visualization and data execution prevention. We are not doing stuff like keep spraying Because he brings one technique which can be used to defeat address visualization Because the idea is that you just stored the data in the complete memory range So we're just spraying the data that will complete memory range That means you can use any address because the data is everywhere and the problem here is that the browser would freeze for some seconds While we are doing this spraying and that means that the victim could notice that an attack is ongoing In this case if the victim goes to my website, he really notes nothing So there is no browser freeze the browser is not crashing. It just looks like a normal website and is just infected with my payload Unfortunately, I don't have enough time to talk about all details of this Vulnerability today. So if you want to find out more just have a look at this great talk by Fian Bihar Davis It's called a tale of it's called a tale of two Firefox bugs You can find it on YouTube or just have a look at my bachelor work, which I will release in two or three weeks For everyone who does not know the array reduce functioner this function can be used to invoke a callback functions on all elements of Sorry, give me one second Sorry For everyone who doesn't know the reduce function it can be used to invoke a callback function all elements of an array So let's say that the callback functioner is the print function It would just go to the first element and walk this function So print the first element and then go to the next one print this one and so on until it reaches the last element and The array reduce right function on the other side just say starts with the last element so with the right element and goes from right to left and Starting with the last element means that you start with the element that index length minus one And the problem here is that in JavaScript You can just set the length field to any value which we like in this case if I set the length field to a very huge value like C0 C0 in this case The problem is then that the index is declared as a signed integer and that means that index can wrap down to a negative number So if I sign a length a very huge value index becomes negative and that means I can access elements outside the scope of the array and You will see this here in the next slide So if I store something at index 0 in the array it would come up here in memory If I store something at index 1 it comes here You see that this array here has a capacity of six elements so we can store six elements here And if I try to access index 0 it says yeah, this is allowed because 6 is smaller than the capacity of the array So this is allowed another example is if I try to access the last element This is also loud, but if I try to access higher elements elements outside the scope of this array. This is not allowed But if I use a negative index, this will be always allowed because only the upper boundary is checked So now can access elements which are stored in front of this this array Here if I allocate an array in JavaScript you would end up with this data structure here So we have here this data structure and I have different fields describing this array and As already mentioned if I store something at index 0 it would come here at index 1 it would come to this location here And every entry consists of 8 bytes So the first 4 bytes are used to store the data entry for example if I store an integer The integer value would be stored here and the second 2 bytes 4 bytes are used To store the data type for example if it's a string if it's an object if it's an integer and so on But if it would be an string it would just say here It's a string and the first 4 byte would be used as a pointer pointing to the string data structure You also see here that we This this array here has a fixed size So for example, I can just store 10 elements in this case here and if I try to Store more elements in this 10 elements this green array would be relocated This is the slots array so it would come here to a new memory location, which is bigger to fulfill the request and Then we obtain we have here a pointer in this point as always pointing to the actual used Slots array so typically it's pointing to this location, but if it's going to be relocated it will be pointing to this new used memory Now come to the first attack. So what I have done is I just relocated this array to a to an allocation of the fixed size 512 bytes and then I just made many many Irrigations of the same size before making this relocation and that means that I have full control over the memory Which is in front of this slots array So the blue marked memory here is under my control and I can set it to any values Which I like if I now use the length field of C 0 C 0 and so on it would become the negative index minus 1 that means I'm just accessing working with this memory, which is under my control and here I can just set the data type to ff ff ff 005 this 0 5 here means it's an String that means the first pointer the first d-word is interpreted as a string pointer. I Can then just say this point as pointing again to my own data here and their specify Fields of the string like the length of the string or the address of the string And I can just say that this address is pointing to the memory Which I want to read because then this code returns me a string pointer and I can just read from this string You see here. This is the implementation of this code in JavaScript You see this is the length field. I just set This location here the length then invoke the reduce write functioner give the leak function as callback functioner This is this function here Then the current element which is passes argument is the element which is under my full control I just verify if the data type is really string and if it's in string I just set here my Variable so an exception to exit this reduce function here Just catching it here and just return the string and I now can read from this string the memory Which I want to read so now able to read any memory in this program The next step is to get code executioner I can achieve this but just changing the data type from a string to an object because every object has at its start a pointer to the virtual table and Inside this virtual table virtual table virtual function pointers are stored. So if you go a little bit back If the data type of current would be object I would invoke with this line here the type of function of it. So it would just follow the object pointer Then followed a virtual table pointer inside this table at this relative offset from the start to the virtual to the type of function pointer and then just invoke this type of function and Since I have full control over the point over the point of the object I also have full control over the virtual table pointer That means I can just point it let it point to my own data and can let the type of function point to my shellcode and execute it In this case, I've just chosen the set element function instead because it has some benefits Which allows me that the browser will not crash after executing this vulnerability after triggering this vulnerability So the tech looks like this. I've just changed the data type to 0 7 Which is the data type of an object. That means the first you would is interpreted as an object pointer If I then follow the virtual table pointer I come here This is the relative offset which is added inside this virtual table to reach the set element function pointer And if I invoke this function Can just let it point to my own shellcode and the shellcode will be executed At the end you see that I have stored the opcode C3, which is the opcode for a return So this opcode here would just return from the set element function and Firefox would just continue execution as what nothing had happened The problem with this is that This attack would just work against older systems like windows xp series back zero because the shellcode is in this case stored on the heap And because of data execution prevention, the heap is not marked as executable That means we have first have to somehow disable data execution prevention by using a rob chain And the problem of the rob chain is that the next location the next address of the Instructions is taken from the location where the stack point is pointing to so from the stack and As the name implies stack point is typically pointing to the stack But we don't have control over this location there So we cannot place the address of the next instruction We only have control over this red marked area here on the heap And that means that we first have is the first gadget have to somehow shift the stack pointer from the stack to the heap To be able to control the address of the next gadget So we have to find one such gadget and we can do this by looking into the file box module If you have a look here, this code is from the file box module You see here This is a jump operation and this jump operation is stored using two bytes So the 72 says it's a jump and C9 would be the relative offset which goes upwards because it's bigger than 80 And the problem is that using return data programming We don't have to jump to the return to the start of this instruction You can just return into the middle of it and Reinterpret this code here as a new instructions We can build a new instruction which are not there But just jumping into the middle of already existing instructions So if you if I look here if I just jump to the start of it The C9 would be now interpreted as a leaf instruction and leaf is exactly doing what I want to do because it takes the Content of the base pointer register and moves it into the stack pointer in the base point That's currently pointing to this red area from which is under my control I have here a quick digression how about how to find such Rob gadgets I think because we are quite bad in time I just skip this you can have a look at it after the talk But the basic idea is that making syntax based searchers like this case here There are many many different possibilities to make the same behavior with another instruction And you have to try out all of them to find one which is there in the program And this is very time-consuming. So what I was doing is I was just using PI email to emulate the gadgets and Then start a behavior based to these gadgets. So for example, I just started this gadget emulated this gadget several times these different starting registers and Then observe the behavior of it and start the behavior together with the gadget in the database And then I can make behavior base searchers like give me all gadgets which can be used to set this register to zero So this greatly reduces the workload and now come to the first emulated chapter so if you start and that you would end up with this user interface so in the upper part you can Configure global operating system-wide protectors like data execution prevention or dress base lettermization You see here the running processes and which are protected by emit And if you click the apps button, you can make pair process configurations In this case, I've just enabled all protections for firefox And if I now start my firefox exploit, you would see that firefox just crashed And at the right bottom you see that emit detected and attack is ongoing In this case the stack people mitigation technique detected this attack So just remember for the later slides the stack people mitigation detected that an attack is ongoing Before making before talking about different bypass techniques. We have to make some general considerations So what we really want to do is we want to protect against real world attackers so that means We have to think like a real world attacker because I don't want to protect against some very academic approaches a academic bypass techniques, which are just working against one specific operating system So what are the goals of real world attackers? They want a bypass technique which works reliable Against all different kinds of operating systems. So if 100 Victims go to my website. I want that 100 victims are infected And that means it must work against all operating systems and all service back levels and against all emit versions And even if emit is also not there Another nice thing is that the exploit should be easy to reuse So for example if I spend one month to develop all my bypass techniques For firefox vulnerability, I just want to make copy and paste if I later find a vulnerability in Internet Explorer or something like that Don't want to spend another month to implement everything from from crutch So this last thing brings us to the idea that you can Build everything on top of emit DLL because emit works by injecting its own library to all protected applications And then I can just hook functions critical functions and say execute my own code before invoking this function and if the check succeed and walk the function if not just terminate the Application before doing anything else And you see here emit DLL is a great target to build everything on top of it because if we have to bypass emit We know emit DLL is always there. So if you Write everything based on emit DLL and on firefox, we know it's also there if I try to attack a dope reader or something like that So the first step is that we find emit DLL in memory Other researchers for example the researchers from offensive security also found ways to bypass emit and Approach from offensive security also required that they found emit DLL first in memory So I really recommend you that you have a look at these three great blog posts of offensive security I will later talk about their technique But what they were doing is they just assumed that one of the modules is important to get module handle functioner And then they are just writing a rob chain which invokes this function and give it as argument I am at and this function would just return the image space of it But the problem in this case is that if the model if the attack application is not important this function It's just I just not apply able and in addition it adds additional dependencies in some cases So I then developed my own approach. I call this approach the hook approach and Yeah, as already mentioned emit works by hooking critical functions So some examples for critical functions are virtual analog or virtual product because they can be used to disable data execution prevention Other examples are winexec because of course you can invoke any Program or load library because you can use it to load an additional module from a window share so from the attacker share And this way emit can implement some checks before invoking the function like the stack pivot mitigation technique Which we already saw in the picture So this the stack pivot mitigation technique just checks if the stack pointer is currently pointing to the stack Or if it was shifted away to the heap So in our case we just shifted it away and that's exactly how emit detects that and the tech is ongoing here To understand the hook approach we have to have to make a look at the implementation of the virtual protect a function And how emit hooks this function. So this is the implementation inside current 32 of virtual product. You see here This implementation is just forwarding execution. So this is the standard prologue which is always there This pop eb line just rewards the standard prologue here And then we're just making a jump to jump into the current base implementation of it But if we protect now this application with emit, it would change change this function and just places here a hook So it would just make Replaces the first the standard prologue with a jump to its own code and then replaces a random number of bytes It's a breakpoint And if you follow this jump this hooking code we come to code which is was allocated by emit and You see here It's just pushing some some arguments to the stack and after that we make you hear a final call into emit delay So what the hook approach tries to do is it just follows follows this first hook the first jump Until it comes to this location and then just goes downwards and extracts the address Which is used as code target And as soon as I have a pointer inside emit delay I can just go downward until you find the be header and Then I've extracted the image space. You see here something other interesting. It's the third push value this value here This value points exactly to this location here so because emit has copied await the old bytes the old Implementation of the functional and replace them with the hooking code emit has to store the old bytes somewhere in memory And this is exactly the location where it stores the old bytes This will be important in the at a later moment. So just remember it So this is a summary of the hook approach I'm just resolving the input address table entry of one of the critical functions Then I can just read the first five bytes if it's a move if it's a move instruction I know that emit is not there because this function is not hooked That means I can just run the exploit without any emit bypasses and if it's a jump I just follow this jump until I find the image space and Yeah, then I'm done. See here. This is a rob chain which implements this a Quick question. Who of you or has written a rob chain? Just raise your hand okay, I Just go over very quickly over the first three lines and That ever some every one knows what's going on here. So this is the address Which I write to the stack or to the heap this address is overwrites the return address and at this address These assembly instructions are stored. So it would basically just start executing this assembly instructions It would execute a pop ex because the stack pointer is for currently pointing to this location It would just take this value here and pop this value into the ex register and Then start executing the next line, which is this line here It would just make a move ex ex that means I just popped the pointer to the virtual Alloc input address table entry into ex and this this line I'm just resolving the input address table entry and The next line would just move this content from the ex register into the ed register Using some push and pop because there was no move instruction and so on so it would just continue doing this stuff But you see here that I have used hard-coded values based on the emit version So for example, if it's emit 4.1, I need to use this offset and for emit 5.0 I need to use this This value and the problem is that currently I don't really know which emit version is there So this approach is very bad So it would just work against against one specific emit version, which is not what we like If I try to target a local application like a video player application or something like that I really have to write a better Rob chain But this is very very complex because then I have to make conditional jumps inside a Rob chain and this Increases the size a lot but if you are dealing with a browser like vulnerability and you can apply this advanced code reuse technique Basically the idea of return to the programming is that we reuse or abuse or re-existing code in the program But if you are taking a browser or PDF reader or something like that We know that there must be code related to handle data structures in JavaScript For example to handle strings and the idea is now that we can just use a Rob chain or directly the vulnerability To manipulate these data structures. So for example, we can just say that the string is now pointing to a new location and Then return to JavaScript and implement everything in JavaScript I later found out that this approach was already public Discussed by young you this year at Kensac West. So have a look at this great talk if you want to find out more about this Here are some examples First example is that we can just manipulate the string and say that the string is now pointing to the hooking code And we can implement a complete passing inside JavaScript another very nice example is the third example here In this example We can just say that the string starts at the code section of any loaded module for example I'm a DLL and the length field is set to the length of this code section Then we can use functions search functions like index of to search inside this code section to dynamically find Rob gadgets so we dynamically find the relative offset for this Rob gadget so we can save Tell me the location where I can find a find a pop-up return instruction And that means I can just write my exploit for example emit 5.1 And if Microsoft later releases emit for 5.2 or something like that The exploit would just keep working because I dynamically find everything So using this technique I can write very reliable code Is he here? This is an implementation inside JavaScript. So I'm just calling this arbitrary leak bytes function which returns me the string From the address of the virtual a lock function and then I can just use access here the bytes and say yeah If it's a move instruction Just run the exploit without any emit bypasses and if it's a jump instruction. I know emit is there so just follow this jump and Just iterate until we find the call instruction so e8 would be the opcode of a call instruction I'm just looping until I find this call instruction and then say yeah, if it's this opcode It's a sub-instruction that means sub has a size of three So just skip three bytes if it's a push instruction at five bytes and so on until I find the call instruction And as soon as I found the call instruction, I can read the p-header In this case, I'm just reading the checksum field and the timestamp field and based on these values I can identify which version of emit is there so that I now know which version of emit is there and the image space of it Yeah, I now come to the different protectors as already mentioned Amit contains five different return on the programming protectors And if you want to bypass these protectors we have three different possibilities three different approaches The first approach is that we can just bypass each protection separately. So this is described in this paper by chart the mod Gives a great overview about it Another idea is that we can use the trick developed by offensive security So what they were doing is they just reversed and material and found out that there's a global flag And if this global flag is set to folds all protections are just disabled So what they were doing is they just wrote a short rope chain which this able which zeroes out this flag Then recommended during my talks that the Microsoft moves this flag to a read-only location because if it's read-only they cannot override it but Microsoft has chosen another approach with emit 5.0 They just encoded the pointer to the flag But the problem is that decoding this point that's quite easy inside the rope chain So in the second blog post from offensive security They they use this approach that just decode the pointer and just apply the same technique With the release of emit 5.1 Microsoft fixed it by using a read-only section as I mentioned but The problem now is that there's a third trick So there's another trick which can be used to bypass emit and what offensive security is now doing is they're just using here This third trick to make this section this this read-only section right able again And then they can just apply the same trick by overriding this flag So as soon as this third trick is not patched by Microsoft It's just possible to play it again and again, but as soon as they would fix this This third trick it would really require us that we bypass each protection separately, which really puts a higher workload on the attacker The third approach was developed by myself during my research, but I think About the same time offensive security also found this trick because it's quite easy to find and Here's the idea that you can just make direct system codes because emit is completely in user space And if you just make a code directly to the kernel emit has no way to to somehow get in between of this and just See that then tech is ongoing I Not talk about the different Protection separately and how we can bypass them and at the end I just talk a little bit about the tricks load library is the first protection and here's the idea that emit denies the attacker from loading additional modules from Windows shares and I didn't really had to bypass this one because I'm not loading any additional models from Windows shares But you can have a look at this bypassing all of the things talk by a room partner if you want to see a bypass But I think this was just working for emit 3.5, but yeah finding a way around this would not be too hard Another protection is the man protect protection. Here's the idea that Functions like virtual protect and virtual a lock are prevented from making the stack executable because the stack should never ever contain executable code and You can easily be bypassed this one, but just making any other location Executable for example the heap but this requires that we modify the Rob chain So typically we are quite lazy We just use a tool such as Mona to generate the Rob chain So in this case, this is the Rob chain which disables data execution prevention and this was generated using Mona But the important fact here is that push it the instructions used to invoke this The virtual a lock function and this would also push the arguments to the stack and that means I don't have control over this arguments So I now have developed my own Rob chain in this case I'm using a push instruction to invoke the function And that means I have full control over all arguments and can just say that the address the target address is not pointing to the heap instead I will come to this Rob chain a little bit later The stack pivot mitigation technique was already mentioned Here's the idea that that image just verifies If the stack point is pointing to the stack and was not shifted away because in my case I just had to shift it away to the heap to bypass this we can just Copy everything from the heap back to the stack before invoking the critical function You see here. This is the code to do this. It's not very interesting just in a while loop I'm just copying everything there and using a exchange or just Go from the heap to the stack The color mitigation technique is a very interesting one because we have three different possibilities to invoke a functional So first of all we can call a function. This is the valid case But you can also jump to the start of the functional or we can make a fake functional return So we can push the functional address or push the return address and directly making a return That means it just jumps to this address here And if you apply return to the programming we typically are using this sort approach here And what Emma is now doing is If we make the valid case the loud one if you call a function the core instruction would push the return address So it would push the address of the next instruction. So this address here to the stack and Emma can then read this This return address and just go backward and check if there's really a call to this function there So this is what Emma is doing and if you are doing here the second or the third approach There would be no such return address there and that's how Emma detects this attack and we can bypass this one But just returning instead of returning directly to the function we can return to a call of the function. So This approach was was Developed by chatty mod and he was using this gadget here. So instead of directly returning to virtual a lock We return to the start of this call here to dislocation here So if I met now goes backward it would so the return address would be this one here So I met would just go here backward five bytes and check if this is a call and says yeah This is fine and the protection is bypassed, but I see some problems with this gadget here So first of all the addresses are take if you have a look at the addresses You see that's from a windows library and that means it would just work against one specific operating system Against one specific service back level, which is bad because yeah We cannot attack any other operating system and you see here that are many memory references there Which can maybe lead to a segmentation fold So this is quite bad because it's this call to the virtual a lock is quite far away from the from the return So what I was using instead is a gadget inside Emma delay and you see here it's again a code of virtual project and You have just one memory reference here But I can ensure that this is not crashing after that just a compare and then I just take this jump Which leads to a return to return would go to the next gadget But what to do if there's no such gadget at all, which is very near the return And what we can do is we can just use any code to any register So in my Rob chain, I feel my push ex which this is making to the code of the functional and this just Invokes this code here So I'm making here a core to eddy and just ensures that eddy is pointing to the target function, which I want so You see here. I'm just popping eggs. That means the next value is popped into eggs This is what the address of the virtual a lock input address table entry this line Just resolves it and with the exchange. I'm just moving the value into the eddy register So I'm just ensuring that eddy is pointing to this location. You see also see it here That eddy is currently pointing to a virtual a lock And after that, there's just a jump so this cannot lead to a segmentation fault and then I just take this jump this goes here And yeah, no memory reference at all. So this cannot crash The last robot action is sim exit flow and it just brings the idea of this color mitigation technique It just applies this this technique for all return addresses on the stack So it just simulates execution forward and applies this technique again and again for all return addresses But if you bypass call me the call mitigation this this protection is also bypassed at the same time during a later stage when I execute my shell code this mitigation technique also triggers because of my shell code and I then found out that I can just make a code to itself So this code here just codes the pop instruction and then a pop the pushed return address So this code is exactly doing nothing, but just confusing the simulation of the foretaxi simulation So this can be used to also bypass this protection mechanism I now come to the trick which can be used to bypass all these protections at one at one time and Here's the idea that I can just make direct system codes because I met is completely in user space You can just check user land functions And if I make directly a code to the kernel and it has no possibility to intercept this call And the problem is here that hard coding system and call numbers is bad because From one operating system or from one service back level the system call numbers changes So I cannot hard code these values. So one approach could be that I write the rob chain which first identifies the the version of the operating system at the service back level and then use many hard-coded values for all different kinds of operating systems But we have something better If you have again a look how I met hooks a function We see this one here. This is the implementation inside entity layer So if I invoke the virtual project functioner, it would call the implementation of it inside kernel 32 This would just forward the execution to the kernel base implementation and the kernel base Implementation just forwards execution to the entity layer version so to this version here You see here the first line just moves the system call number into the EX register and Then the following two lines just make the call into the kernel So these two lines depend on the exact operating system. In this case, it's a 32-bit system And if I follow this you just see it leads to a system enter And if I now protect this this function with emet it just do the same again It just hooks the function so it replaces the first bytes with a jump And if I follow this code you see here that the third Push argument points to this blue marked area here So emeter has just copied away this bytes to this location and the problem is that I can Get this base address by just adding some relative offsets So it's very easy to find this base address here Then I can just extract the push push argument this points to this location and I can directly jump to this location So I can just jump over all protections from emet execute this System call and just return to my next sketch art You see here. This is the implementation of it. This is a little bit more complex Rob chain So I don't want to go into too much detail here But yeah, it's so big because it's finding first itself in memory and then modifying itself. That's why it's so big here Now come to the last mitigation technique. It's the export address table access filtering The idea here is a cell code typically has to pass a field Which is called the address of functions field inside the pe header of modules such as the kernel kernel 32 kernel base or entity L module to locate functions such as load library or get process address and What emeter is doing is it just places hardware breakpoints on this field here and As soon as one instructions trying to read this field this Breakpoint is triggered and emet code kicks in and can do additional checks For example, you can check if the instruction belongs to a loaded module then it's valid And if it's not belonging to a loaded module, for example, it's stored on the heap It's most likely from a shell code and that means execution can be can be terminated And we have again many many different ideas how this protection can be bypassed So first of all, you can just use again a Rob chain because then the instruction is from a loaded module Or we can use some other techniques But the problem with the first three techniques is that we have to modify the shell code when we use this technique And because exploit developers are typically very lazy. We can use this This last approach here. You can just say remove all the breakpoints before executing our own shell code And to remove the breakpoints. We have again many different possibilities So the main approach was developed by p on Dr Bania, you can have a look at his blog posts here But the problem is that he was using hard-coded system code numbers So he's using the sets red contacts and the anti-continue system code to do it So what I was doing then was I just use the API instead and just return to a location inside Emet DLL which called this API function But since image 5.0 emet is also hooking these functions So it's not possible to apply this technique anymore unless we first disable all protections using the approach from offensive security But I think this is no In the next releases of emet this will not be possible to apply and that's not that's why I think it's not so interesting here So the first approaches are just using the system code numbers But the downside is that this would just work against one specific operating system and sales back Then I feel some other techniques, but For the newest version of emet they are not so interesting. So just skip them. So just Some methods to do it, but I think the most Interesting one is that we can just jump over the whole hooks to darkly invoke the system code as mentioned in the robs chapter So this technique has no Disadvantage it works against all windows versions against also respects and against all emet versions Yeah, and I'll come to the final thoughts emet has many many more protections, but I think these two protections the raw protections and Yeah, if are the most Interesting one from the technical perspective Other protections are for example that text you have is reduction where I can say that You can just load Java from the Internet, but not from the Internet another one is for example Certificate trust which verifies the certificate or say up, but see up just protect the exception handlers It's from the from the operating system, but as soon as you can bypass address base lettering station see up is easily be bypassed Then heaps pre mitigation and null page pre-location It's very easy to bypass these ones It's the tactic is to just use an address which is not protected by emet So if you want to find out more about this just have a look at my slides from the ruckscon But I think it's not so interesting mandatory address base little musician and bottom up randomization Just increase the functionality of address base little musician, but if you can bypass address base little musician These are bypassed and also be bypassed and EF plus is an interesting protection because it should protect my current exploit my current version of the exploit But it doesn't I don't really know why but we are currently discussing this situation is Microsoft But even if it would protect against my current version of the exploit it would not be too hard to extend the exploit to also bypass this one I have here a quick recap Just a few Just skip this one here. It's just a summary of what I have told you today We from second side would really advocate to work together with Microsoft and improving the resilience of further emit releases We have many many different ideas how emet can be improved, but of course no protection is 100% bulletproof I feel a demonstration video You can see the exploit in action. See here everything is green. So all protections are enabled firefox is protected Then you see here all protections are enabled if you click the advanced options tab You see that the export address table access filtering plus protection is configured correctly And if I now start firefox is the old exploit is out the bypasses You see that it's crashing and emet detected that the tech is ongoing and if I restart firefox and refresh the task list See it's still protected and if I now use the one with the bypass as you see that calculator spawns up and You also see that firefox is not crashing so you can just execute the exploit again and again and yeah victim really notes nothing that there is something ongoing Fear a summary of about the workload. So writing the initial exploit without any emet bypasses Was quite easy. So it just took me about three to five days I think if you really try to make it very fast, you can do it in one day But yeah, I was doing this in my free time. So I was watching TV and stuff like that while I'm doing this so just took me three days, yeah, and Then writing the first bypass really was high effort I can't estimate and can tell you how long it took but you see here the exploit code has about five thousand lines of code So it's really huge. So took me really much time But my idea was that I just developed many many different ideas to bypass this mitigation technique So it just showed you here some of the techniques which can be used and that means I can just configure So if at the time emet updated itself to five dot zero It was quite easy to mitigate the migrator exploit it just took me five minutes because I just had to configure to use other techniques and Add four lines of code because I had to pass two additional Sample instructions. So I'm passing there the sample instructions and saying if it's a push It's has a size of five and just had to add two of such instructions And the same applies for the release of emet for five to one So this is the current version of it Took me about 40 minutes because They tried to break my scan down approach So I'm leaking a pointer to emet delay and from this pointer just go downward until I find the be header and See it here in the next slide So these are the sections of emet. This is the be header and this is the text section So I have a pointer inside this text section and then I just go downwards. So here To this location to find the be header and you see that there is no gap in between So if you add to this base address here the size, which is one thousand You would end up exactly with this address here So it's exactly the address of the text section the same applies for emet five to zero so if you add up here this one you come up to the next address and What emet was then doing in emet five to one was that if I now add here this one thousand I don't come to this text section So there's a hole in between this unmet memory and for try to scan down Just access this unmet memory. That means I'm just segmentation folding So what I'm doing instead of just search for the start of the text section and then I can just Substract a relative offset of it to reach the be header or I don't really have to extract the be header at all So it's quite easy to bypass this one You see here, it's also working against the newest version of emet just verified two days ago that this is the actual version Yeah, yeah, you have some contact information And just remember that we are currently searching for new employees So if you're interested you can just drop me a mail or send to our office a mail Yeah, thank you for your attention and if you have any questions Thank you for this very nice talker me if you have any questions Please do line up at the six microphones. We have here at the ground level While you're doing this quick announcement Today at 5 p.m. At the fairy dust rocket in front of the building there will be a meeting For the Freyheidstadt angst freedom not fear demonstration if you want to join them just go down there at 5 p.m. Today We have a question at microphone number two Okay, thanks for the very interesting talk Well, I wanted to know so you said that after the rob chain you can return execution to JavaScript, right? Yeah, that I have it on the slide that this requires some Some conditions so it must be able to trigger the vulnerability without crashing the application and of course you need some scripting support So if you attack a local application, it's not apply ever. Okay, but the question is what if the rob gadgets you are using Changes the value of some Kali save the registers Because then it could like spoil the execution of the rest of the you know the environment JavaScript environment Sorry again, I didn't so if one of your rob gadgets changes the value of a Kali saved register It will not be restored when you return and so it would that's the risk to spoil the execution of the JavaScript environment What I'm doing is I just fix everything before returning. So I really just touched In this case, I'm just touching the data structure But you don't really have to execute a rob gadget at all you can just use directly the vulnerability in this case So for example, I've really abstracted many things away from this presentation to make it very basic But what you can do is with the vulnerability you can directly instead of executing a rob chain You can directly write to memory. So you don't really have to use a rock chain to write to memory at all. So For example, if I go a little bit back here So you see here the second the second example in this case Here here in the second example Tells you that you can use this advanced code reuse technique to write to memory. So what you can do is You can generate an array in memory and redirect the rights of this array to overwrite the data structures, for example So don't really have to execute a rob chain at all. Are there any more questions? There is a question from our signal angel on IRC. Yes, is M it often used as a company's I Didn't really see it very often because the problem is with the compatibility So for example, if I'm using it at home my Firefox is just crashing or three or four days because Emmet says that there's an attack but in reality, there's no attack, so it's has a high false positive rate and I think that's the main problem of it But yeah, and let's also think that's a problem that it's not so easy to deploy it into domain So yes, thank you Any more questions? Yes, microphone number two, please. Do you consider Windows secure to operate in a cooperation organizations? Sorry, would you recommend deploying Windows within organizations? Windows yes It's hard to say but in my opinion Yeah In my opinion in the basic configuration windows is harder to exploit than Linux because in Linux you have to to compile Because in my opinion you have to in Linux you have to add the compiler flag for Python position dependent execute labels That address based optimization is really effective So if you just compile an execute table in Linux, it's not relocated to another to another location So the code section will be always at the same location And the problem is that many standard applications are Have not address based realization enabled there and this situation is better on on Windows But yeah, it just depends Because if more people are using Windows that take a stride to attack Windows and yeah Any more questions? Seems like we have two additional questions from from ISE Have you tested this technique with other exploits? I Have tested this with a test of is a test application for myself And I also verified that it is working for for file C exploit but this other Browse exploits I didn't really test it is because I know it's just working because Because I have built everything based on Emma delay But in this case this special vulnerability really allows me to do much stuff because I can just read from memory I can write to memory as I like And I'm not crashing anything so I can't just read it again and again So in this case, it's quite easy to do it if you really have to bypass a Local application like file C or something like that Everything becomes a little bit harder because you cannot apply this advanced code reuse technique So that you cannot execute JavaScript code inside a local application And that means you have to implement everything inside a rob chain And that means everything becomes really hard because you then have to make Contetitional jumps to ensure that it's works reliable against all different kinds of rating systems, but it's still possible We have another question from microphone number three. Hey, thank you for the presentation Are there any plans to implement some of those protections on the kernel side? I mean I've seen rope guard and sent in L by core and emat everything is implemented on the user space Some of those protection I assume and I know could be implemented kernel I just want to know why Just know that I made it implements the null page protectioner This is a protection for current vulnerabilities, but I'm not aware of other tools which implement anything in kernel for windows So sorry don't know Another question from our signal angel Yes, isn't the added size of exploit code for lines of code with M without emit and five thousands with emit A huge win in terms of added complexity Yeah, that's I think that's the idea of emit What they say it is that they know that emit can be broken, but they just want to add additional workload for the attacker so if I would be an attacker and 100% go into my website and just one person has emit enabled would not make I think it would not make any sense to add Bipers as for emit because it's just one person which I miss But if more persons would use emit, I would add this work additional workload but In this 5000 lines of code, I really have implemented many many bypass techniques So if you just want to bypass it one time, it's quite easy for example the Exploitation code from offensive security has about 300 lines of code or something like that and can also bypass emit But in my case 5000 lines of code were generated because I have implemented about six or ten Methods to bypass each protection. So that's why it's so much. I Think we have no further questions from the audience. Thank you, Rene Frank uber


Hello, students. So, myself, Mr. Siddeshwar B. Turzapure, associate professor, department of mechanical engineering, Valchand Institute of Technology, Solapur. So, in this session, we are going to deal one topic from the section, it is fluid dynamics and the name of the topic is modified Bernoulli's theorem, learning outcome. At the end of this session, students will be able to explain difference between the Bernoulli's theorem and modified Bernoulli's theorem. The contents are the first one, it is the assumptions of the Bernoulli's theorem. Then we will go for Bernoulli's theorem. Then fulfillment of assumptions in real-world situations. Then it is need of modifications to Bernoulli's theorem. Then lastly, it is the modified Bernoulli's theorem and references we are going to have. The first one, it is the assumptions of the Bernoulli's theorem. Just we are going to revise those assumptions as we have dealt this in the first section. The fluid should be ideal. We are knowing that the ideal fluids are the fluids which are having zero viscosity, that is the fluid will not have any viscosity. So, in case of this world, we are going to have number of fluids are existing and then all these fluids are having to some extent the viscosity. The viscosity of the fluids which are existing may be to some extent lesser or it will be more but they are having the viscosity because of which they are called as real fluids and in case of the ideal fluid, ideal conditions as these are not existing, so the fluid having zero viscosity, it is not existing at all. So, in case of the fulfillment of this one, we are saying that ideal conditions as these are not existing, so ideal fluid is not there and in case if we want to perform the experiment or you have to go for the analysis by making use of the Bernoulli's theorem, etc. So, in case of that one, so as the fluid is not ideal, we are going to come across some differences in this equation. So, now secondly, the flow should be in case of the flow should be the flow should be steady and then the second one it is flow should be incompressible then flow should be irrotational. Now, let us see what happens to the steady incompressible and irrotational type, the flows. Now, in case of the flows which are existing in the real world, in some cases the flow might be steady. Steady flow refers to the say the constant parameters with reference to time at a point it is. Now, suppose the flow is there at one particular point if when we are fixing the pressure gauges, etc. where we are measuring the pressure and then we are measuring the pressure now and after some time. So, number of times when as the time passes we are going to measure the pressure many times and even though the time is different the pressure is remaining constant. Similar to that one at a point if the velocity is remaining constant discharge is remaining constant. So, like this number of parameters if they are having the constant values at a point with reference to time we are going to call this type of the flow as steady flow. So, steady flow can exist and this condition even in case of the practicals etc. it can be satisfied. The second one it is the flow should be incompressible. In case of the liquids we are going to have the liquids are incompressible. So, the flow associated with the liquids these are incompressible so next to that one we are going to have the flow should be of irrotational type. In case when we are having the fluid particles travelling from one position to another position if the fluid particles are rotating about their own axis or mass centers. So, these are called as rotational flows. If they are not rotating these fluid particles are not rotating about their mass centers or axis we are going to call that type of the flow as irrotational flow. To some extent the flow may be irrotational and to some extent the flow may be rotational. So, it is not perfectly possible for us to go for the irrotational type the flow. So, the Bernoulli's equation also we will see. So, if the above conditions or the assumptions these are satisfied. So, in case of that one the Bernoulli's theorem can be represented in the form of the equation as it is p by rho g plus v square by 2g plus z is equal to constant.  The summation of these three it remains constant. Now, when we are say going for the assumptions how many assumptions we have satisfied and how many are remaining. So, the first one that is the fluid should be ideal. So, it is not satisfied it cannot be satisfied any time the flow may be steady. So, it may be it is in our in our hand we can go for the steady flows then it is incompressible we can go for the liquids and then lastly the flow it is irrotational it is not satisfied. Now, think of the fluid flow through a pipe which is having the different diameters at different sections it is. Now, the section number one say at that section we are having the larger diameter then it continues for some time then the further we are going to have the reduction in that diameter, but that reduction it is sudden one you can say that the sudden contraction of that pipe it has occurred and the diameter now it is lesser than the diameter at the section one one and now the fluid flow it is occurring and now we are having the fluid flow from the section one one to the section two two the lines just you can observe. So, these lines curved lines these are indicating the fluid flow and now you can observe say after the sudden contraction we are having some section where the diameter of that particular fluid flow it has reduced that C C we have said it is the vena contracta portion where the cross section area it will be smallest one and then further it goes to the section two two on the right hand side and the flow is from the left hand side to the right hand side. Now, in case of this one you have to think now whether the total energy at section number one and section number two it is same if it is same then it is over or if it is suppose not same in case of that one we might have the total energy at one of the sections greater than the total energy at the another section. So, if the difference is there the which one is larger that is the total energy where it is more at section one or section two see the answer of this one. Now the total energy at section number one it is more than the total energy at section number two that is the summation of the pressure head kinetic head and the datum head he at the section number one it is more than the summation of the pressure head, atom head and the kinetic head at the section number two. Now, we can have the explanation of this one. Now, first assumption we can see. In case of the first assumption, the fluid it was ideal. So, the fluid flow whichever we have shown now, how it is existing and now all real fluids they are having viscosity. So, some energy will be lost when the fluid is flowing from section number one to section number two and in case of this one the loss due to it will be the viscosity. So, energy loss due to the viscosity it is one of the reasons why the Bernoulli's theorem needs to be modified. In case of the second one, the energy loss due to the friction between the inner surface of the pipes and the liquids we can consider. Now, when we are going for the losses the losses these are of two types when it is a major loss and the second one it is the minor loss. The major loss refers to the loss due to the say friction between the inner surface of the pipe and the liquid which is flowing. So, this value it is larger. So, because of which it is called as a major loss. Now, the second loss you can observe. So, it is say the loss due to the say different reasons like say the pipe it is connected to the tank then sudden expansion or sudden contraction has occurred. In the present case you might observe that the sudden contraction it has occurred because of which we are going to have the energy loss. So, this is minor loss. So, other losses are also there which are also minor and they are due to the say fittings etcetera the valves etcetera. So, like this the losses these are coming into place when we are going for the real world situation and these losses needs to be considered and then the equation needs to be modified. Now, the same equation how it can be written when it is modified. So, it is the at section 1 we are having this P 1 by rho g plus V 1 square by 2 g plus z 1 is equal to and x n section 2 it is say P 2 by rho g plus V 2 square by 2 g plus z 2 and now on the right hand side we are going to add the head loss it is these are the references. Thank you.


First of all, thank you to everybody who is here now, thanks for joining the Meetup today. So today is the March Meetup. So I'll be going through like, okay, so what's going to happen today? We will have one talk by Ted on event-driven notifications in Rails. And after that, we will be spending some time just in a breakout room, just to get to know each other, just for 10 minutes, just a very quick one. And then a short section, if anybody has any job shout-out, like want to hire or want to find job, et cetera, like both ways, feel free to say something then. And then we should, if everything is on time, we should end in one hour, 8.30. So again, shout-out to Michael and engineers SG. Thank you for hosting today's Meetup. As usual, thank you for hosting us. Then for those who don't know that we have a Telegram group, recently there has been some people who has been asking me how to join, apparently the QR code on Ruby S3 is broken. So yeah, this is the QR code to join the Ruby S3 Telegram. So yeah, Ted, are you ready? We can, yeah, let's start with Ted's talk today. Okay, let's see if I can share with you. See it working? Yep, I can see it. Okay, excellent. All right, hello. My name is Ted. Unless you haven't met me before. And today will really be a sort of case study of how we have used event listeners to implement our notification system in Ruby on Rails. Before I start, I should say that I work for a company named Ascenda and in fact, I'm in our office right now and at Ascenda, we do a lot of Ruby, really. We have quite a few applications. Some are Rails, some are Hanami, some are pure Ruby. And we have one application that is written in Elixir as well. And we're more or less always hiring Ruby developers. So if you're interested in coming and working with us or even working on my team, then feel free to reach out to me on the Ruby SG Telegram chat or you can check out our website AscendaLoyalty.com where you will also see some of the job descriptions there. All right, so I'm going to start with some background for what we're doing. And this will serve as sort of the answer to the question why for what I'm going to show you next. So what you need to know is the application that I am specifically working on is a sort of orchestration app that coordinates a lot of the work that is done by our other Ruby applications and it interfaces with all the frontends and also it interfaces with our partners and vendors through JSON APIs. So you can think of our whole ecosystem as sort of macro services. We have five or six Ruby applications that work together to accomplish what we do, which is loyalty points related and the application we're talking about today is sort of the hub in the middle of the wheel that does a lot of orchestration of what's happening in the other apps. All right, one of the things that we do quite a bit of in this application is send notifications to end users. End user meaning that you are a customer of a bank or an airline and you are either earning points or you are spending points in one of our marketplaces. So when you do that we will send you all sorts of notifications sometimes by email, sometimes by SMS, sometimes push notification if you're using a banking app for example, sometimes through some sort of widget. So this is a recurring task that sort of finds its way into most of the workflows in this orchestration application. So what we did initially was we built a simple notification system because we figured this is something that we're going to need to do quite a bit. And one of the things we considered was we don't want any unexpected errors in the notification code to break the flow for the user. Because notifications aren't really that critical and if the user was about to spend some points which translates to spend some money then we definitely don't want to prevent that from happening because our notification fails. So we built this simple notification system that has two steps, a triggering of notification and then delivery of said notification. And if you wonder why one trigger will or could lead to multiple deliveries it's because we can deliver the same notification through any number of channels. So you could receive the notification both by email and push notification, for example. So that's why the triggering of a notification might lead to multiple notifications being delivered. So looking at the first step of triggering the notification what we do is we create some notification records in the database. These records will have some information like which template are we going to use, which is the user we want to deliver it to. And what is the data we need to populate the template. So our templates are using liquid text as a templating language so we interpolate some data into there. And then the triggering of the notification schedules some background jobs, any number of background jobs depending on how many channels we want to deliver to. So here is a heavily redacted version of the trigger notification class. And you can see, notably, that it takes in a user, an event, and some data. And for each channel we try to create the notification record and schedule the job. And then we have the trigger notification. And then we have the trigger notification schedule the job. And this trigger notification class does not contain any code that can unexpectedly fail. So this is quite safe. It fulfills our requirement of notifications, not breaking things. So far so good. This is how you would call trigger notification from anywhere inside the application. So in this example, we are triggering the checkout completed notification for a certain user. And take note of the third argument here, which is the hash. It's the hash named data. And note how we are sort of digging into the transaction to pick out bits and pieces. And these bits and pieces are what will be interpolated into the template string when we render the actual notification template. So in this example, I have actually taken out a lot of code so that it's easier to digest. But this kind of data hash will normally have something like six to seven keys. And the values have some varying degree of complexity when it comes to picking them out of the domain objects that we're dealing with. But remember this hash because it's a key to what we'll be doing next. Then once we trigger the notification, it will schedule some background jobs. What these jobs will do is they will render the templates and they will try to deliver the notifications using the correct channel. So delivery could be send a mail using our own Ascenda SMTP system, send a mail using the partners system, send a push notification through the partners API, send an SMS through the partners API. We have all sorts of channels implemented here. And here is a redacted version of what the job looks like. So we have some retry logic here. And other than that, it's fairly straightforward. We try to find the notification again. And we have some deliver notification method which figures out how to deliver it based on the channel and tries to do that. So far so good. We are quite happy with our little notification system. It's quite flexible. It's easy to trigger notifications. And it's easy to add new notification templates. And because, of course, the delivery is done in background jobs, we don't really care if that fails or not because it's not going to error out the whole application. Unfortunately, there was something that we didn't quite foresee here. There's a hidden step almost. It turns out that a lot of times there's a lot of code involved in preparing the notification data that needs to be stored in the notification record in the database in order to eventually render the template for the notification. And this was sort of an unforeseen thing. But it led us to the problem that we're trying to solve using events. And this is that any bugs in this code that sort of cherry picks data out of objects and formats it somehow and puts that into a hash will basically blow up the application. Which is really not good if the customer is trying to do a checkout, i.e. they are committed to spending some points and we error out because of some notification code issue. It's really bad because that notification we could have gotten away with not sending it really. And if we just error out uncontrollably, then this order is going to end up in some undefined state and it's going to require manual intervention to fix it most likely. So I did some checking in our existing order flows and it turns out that this type of code that just prepares the data for triggering the notification is usually somewhere between a quarter and one third of the total length of code. So there is quite a substantial bit of the order flow that is just preparing data for notifications. And that means it's a pretty big footprint for bugs as well. So another way to visualize it is like this. We started out with our notification system in the green rectangle which is known to be safe. There can't be any errors in trigger notification and if there are errors in deliver notification job then that's fine. It can just retry itself until it eventually fails permanently. But it turned out there was this hidden step where we prepare the templates data that is not safe and it will cause exactly the kind of failure that we try to avoid. And that kind of failure did happen once or twice. So I decided to try to fix that. So one of the solutions we came up with, we considered a few of them, is to turn the service that needs to trigger the event into or trigger a notification rather into an event source or a subject if you're looking at the formal definition of the observer pattern. And then we let other parts of our call base subscribe to this service. And importantly, any callbacks that are subscribed will automatically handle errors in those callbacks. So the errors won't bubble up into the main flow. Then what we hope to end up with is something like this. So on the right hand side you see what we previously had. It's the notification system. But now we have some callback that has been registered with our, say our checkout class. And that one is automatically error handled. It is wrapped in an error handling wrapper when we register it, which we will see how it works soon. And then the event source being any class that can trigger events like a checkout class will call all the callbacks that are registered with it on some certain condition, like if it was successful or if it's had an error. So this is the state that we want to get to. So some of the pros of this solution is it solves the original problem, which was one of robustness. It turns out we can integrate this quite neatly with some of our existing systems. A positive side effect is it makes business logic code more focused. So it turns out that once you take out these 25 to 40 percent of code that do nothing but cherry pick and format data for notifications out of like a checkout class, that class becomes much more focused and it's a lot easier to see what's actually going on with this checkout. So it becomes a little bit less clear that it does send a notification, but at the same time we don't put all the nitty gritty details of sending that notification inside. Another nice thing is because the registering of callbacks can be done from anywhere basically, we can organize the registration of those listeners in any way we want. So if we want to optimize the code base for discoverability in some certain way, then we can play around with how we put those pieces of code in our directories and files. And another nice side effect is we can actually use these events for unrelated things, but that also should never make the application error out. So things like logging and instrumentation, like having this inside the checkout class is not really critical. Actually, it's detrimental and we also don't want errors in here to do anything bad to the actual business logic. But of course, everything is trade-offs, right? So it's important to consider the cons of the solution as well. So the big one, which is like a general critique of the observer pattern, which is rather obvious, is that the cause and the effect becomes obscured here. If you look at the checkout class now, there is no notion whatsoever about triggering notifications. So if you unwittingly just stumble on the code base and then you are tasked with doing something notification-related and you try to go into the checkout class to look for it, it won't be there. This is sort of a minor thing because we are using this for notifications across the board and we have a lot of them. So you only need to learn once that okay, notifications are sent through event callbacks and then you know where to look for them. And because of how we organize the files, you can also fussy search for notification and you will instantly find where the notifications are being triggered. But yeah, this is the biggest downside. Like if this is not such a cross-cutting thing, if you are trying to fix a single point in your code, then maybe you wouldn't go with events, maybe you'll go with something else. Another con is errors inside the actual preparing of the template data will now get swallowed up, unhandled. So it's actually harder to catch errors in preparing notification data in production and I will go through in the third part on enhancements how we can fix this. There are also some possible possible issues with lazy loading. So because you put the registering of the event callback in some arbitrary file, if that file is not loaded when you want the event or the notification to trigger, nothing will happen because no callbacks have been registered because the file hasn't been loaded. This isn't something I have experienced myself. It could theoretically happen in development if you have lazy loading enabled, but there are some ways to get around that, like Rails lets you specify directories to get eager loaded. So you should be able to fix that relatively easy. But important to note that before you get super excited about using events for something, just make sure that you have the right problem to match it to. Finally, before we go into the implementation, I set some success criteria just for the heck of it. We want primarily the robustness to go up and the way I will know this is I will never again see in app signal that check out failed because we failed to prepare some notification data. Hopefully, our confidence will go up overall. I think our confidence will go up when it comes to the critical parts, which is doing the actual business logic, even if our confidence gets slightly lower in the triggering of notifications, which I think is a fair trade-off. And ideally, we should see no change or a little bit of an increase in productivity. There might be a tiny increase because we have removed a lot of the noise in the relevant business logic, but that might be offset by someone being confused by the whole event listener concept. Okay, I think I'm done with the why and the what. So part two will be the how. So this will show you some diagrams and some Ruby code that will hopefully explain how this works. A lot of the code here is redacted, not because it's confidential, but because I don't want to overwhelm you with things that are unrelated to the stuff I'm going to show. But it's actually not that far off in terms of complexity. So I think you can appreciate that it works anyway. Okay, let's take a look at a typical check out or order flow. The user wants to spend his hard-earned points on something. He goes to the front end to pick something from the marketplace, and then he decides to check out. This application that I'm working on will receive the request from the front end. It will do a number of things depending on what you order. A lot of checks are done before we can carry on. And the way you can read this diagram is the green arrow means that the step was successful, and we can proceed to the next step. The red arrows represent edge cases, which means that there was an error in the check out, but it was not something exceptional. So we handled it gracefully. This could include you don't have enough points in your account to buy the thing. The thing went out of stock before you hit the check out button and all sorts of other things. If the check out is successful, we move into the fulfillment phase, which means we prepare to order this thing from the supplier. This is the simplest step. It basically just runs a background job that places the order with the supplier's API. And eventually we will hear back from the supplier, and that usually happens through a webhook. And in that webhook, they will tell us whether the order was successful or not. So again, there are some possibilities that we will exit the flow unsuccessfully here. And when that happens, usually we trigger a bunch of other steps like refunding of your points and sending notifications. All right. This is how it used to work. This is where we call trigger notification directly, and the part of the code that prepares notification data sits inside these services. So the checkout service has 25% of its code dedicated to crunching this data. Fulfillment has 40%. Webhook processor has 35%. And all that code has the chance of having a bug in it. With Ruby, it's usually the no method error. We try to access some attribute that was nil. And so it will just explode, and this order flow will be left in some weird state. And the front end will probably get some sort of unexpected error. So this is the old solution. You will see the familiar trigger notification method here. It's the same piece of code that we looked at earlier, but out of context. And you can also see some simple DSLs that we're using in this checkout class, like specifying the options, which are like keyword arguments, and also specifying what result key will be there if this service succeeds. So if you check the call method from top to bottom, you will see a guard close there. And this is basically one of those red arrows that says if the price check fails, then we will just return the result of the price check, which will be an error result. And the call sites can handle that. If all the checks pass, we will schedule the fulfillment, and we will trigger a notification. So this is one place where you could potentially end up with the code failing, because preparing of this hash that is the third argument to trigger notification had some bad code in it. Instead, what we want to do is in the new solution, we want to emit an event. And instead of having all this cherry picked and hyper formatted data sent to the callbacks, we will pick some bigger objects, just the objects themselves. So in this example, you can see the trigger event is now gone from our call method. Instead, we have a callback at the top that says just before we return success from this service, we will emit an event. And its name will be success. And its data will be a transaction. And this before success callback is evaluated in the context of the instance. So that is how we can call redemption transaction there and actually have it return something that is an instance method of this. So this callback at the top before success, this is not part of the event system. It is a feature of the code that lets you call success at the bottom with some result. That was there before we even started this work. So what will happen when we call emit? Well, the before success is called in the context of the instance. So we know it is an instance method. And it is defined in the event source mixing. And it is a deceptively simple method. It just goes through a list of registered listeners. A listener is a callback wrapped in an error handler. And one by one, it will invoke them. So one thing to take note of here is this happens in the same thread, in the same call stack synchronously. So even though you have this event system that can automatically swallow errors for you, you should not put some long running task in this event listener. What you could do is you could have the event listener schedule a background job. That would be a better use of it. Otherwise, your main thread is going to end up spending a lot of time in here. And the whole request is going to take a lot longer than expected, which might be a bit hard to debug because we might not know exactly what listeners are there at the time. This is the implementation of the emit instance method. Basically, we just create a qualified event name. So it's prefixed with the name of the class, which for us will be the checkout class. And this is so that if you have the same event emitted from multiple classes, they won't be confused with each other. We turn that into an event object. And then we look at event listeners defined in event source. And event listeners is just a hash with a key, which is the event name, and the value, which is a listener, which is a block wrapped in an error handler. So we look at all the event listeners for this event, and we just call them with the event as the argument. Event is a very simple class. It's just a wrapper for the event name and data. And we have some open struct like shortcuts so that you can you don't have to type so much. And also, instead of doing hash access that can silently return nil if the key doesn't exist, we get proper errors if you call some method on data that doesn't exist. All right, so we know how to trigger events. Now we need to register a listener that can be called when the event is triggered. And for that, we have a class method called on and you just pass it an event name success, which you will recognize from earlier when we decided to emit the event success. And it will take a block, and the block will basically be whatever you want to happen when this event is triggered. And here, again, now you see the trigger notification call. This used to be inside the checkout class. Now instead, it is registered from outside. And you can really organize this any way you like. If you notice here, you just need to reference the class and call on. In our case, we said, okay, let's introduce this concept called notifiers since it fits with how Rails likes to classify things. And also notifier should make it pretty clear that this thing sends notifications down the line. And it works quite well with fuzzy finding. If you type notify, you will find these files and you can figure out where notifications are sent. It also lets us organize the event listeners in neat ways. So our order flows tend to have this checkout fulfillment completion three step approach. So what we do is we just put all the event listeners for the whole flow in one file. So then if you want to answer the question, hey, what notifications do we send for points transfers? Then you can just look in that file and you can see, oh, and check out, we send this on fulfillment, we send that. And if the thing completes successfully, we will send this final email. But this could really be organized any way that works for you. This is the implementation of the on class method, even simpler than the emit method. It has the event name. It has an optional keyword argument that allows you to override the error handling. So in case you're debugging something, you can register this with race errors true. And it will help you by actually racing the error instead of just silently failing. And of course, it takes the block, which is the actual callback. So the only thing we do is we wrap this block in a listener. And we push that listener on to the event listeners hash, where the key is the name of this class, plus the event name. And as mentioned earlier, a listener is just a block wrapped in error handling, basically. And this is how errors are not raised by default. When you call emit and it executes all these listeners, you can see that the error handling is in there. Unless you've passed race errors true, then it will raise an error. So if you look at the whole implementation of event source, it's only really the event listeners hash, which is omitted here. And one class method on, and one instance method emit. And this is the whole implementation of the event system right now. So a very simple code, very easy to understand, but quite a powerful concept. Now that was quite a deep dive into the implementation itself. So in this third part, I'll just talk about some enhancements that I'm already working on. And these are addressing some of the shortcomings I mentioned earlier. And they're also simplifying the use case for our application. So one of the things I want to do is for our particular service classes, I might want to define some default event data that is always included and then allow the addition of custom event data. So if you take a look at the checkout class that we used this in earlier, you will see that the event data is the same as the data we return if the whole thing is successful. And it turns out this is not that incidental in maybe nine out of 10 cases. The data we need for the notification is the same as the data we return in the success call. Or at least it can be reached from that entry point. So what I want to do is instead of explicitly calling this before success emit this, I might just have the base class do that automatically. And the data will then be whatever the data is for success. But in that one out of 10 cases where we need more data, then we need some way of specifying that right. So then we will just add an event data method that you can pass some symbols to which will represent instance methods. Or potentially we could allow a block here as well. Another nice thing about this is we can make it even safer in that if this instance method is missing, for example, we could just ignore that as well and have an even more robust implementation. The next thing I want to do is a configurable error handler. So I've already implemented this actually. And it addresses one of the problems I mentioned earlier that because listeners just swallow their errors, we wouldn't know if the preparation of some notification has failed. So I just decided to add the option to define your own error handler, which is just anything responding to call. So in production, we can report to app signal. And in development, we can just re-race the error so that we can have it instantly debuggable. The last thing I want to do is maybe a bit more unobvious. So if we look again at our checkout class, we have this edge case, which is that if the price check fails, we return the result of the price check. This will not trigger a callback in the service. So there's an error method that you can call if the error is in this class. And that will invoke the before error callback, which means we can emit an event from that and listen to it if we want to send notifications. But because this price check is its own service, it is going to emit the event with that class name. So if we wanted to listen to notifications from checkout, we would have to do it in a very indirect way where we actually register the event listener on the price check service class, which is a bit indirect and maybe not immediately obvious. Not to mention, it would be really nice if we could just say checkout before error emit this event, even if the error is coming from an inside service class. Yes, so those are the three enhancements I'm currently working on. And that's all I had for this presentation. I have no idea how long I've been going, so I guess if there are any questions, we can take those now. If anyone is still here, I'm still in full screen mode, so I'm not entirely sure. Anybody has any questions? Okay, I'm going to stop sharing. I guess not. I guess since Michael is here, if there is anything you want to revisit, then there will be a video? Yes, there will be a video, there will be a recording. Okay, oh, there is a question by L3 if I'm pronouncing your name correctly. While you're working on rebuilding this feature, what was your greatest challenge while using Ruby? That's an interesting question. Okay, the biggest challenge is making an informed decision where to put this event listener's data. So if you recall, the event listener's is a hash that has keys that is a class name, dot event name, and then it has an array of listeners. And then you need to ask, where does this hash go? Do I do a class instance variable in each of the service classes? Or do I put this one registry inside the event source mixing or what? And then it's very easy to get lost in the object model of Ruby with class instance variables and single-ton classes and all that. So it's relatively easy to do, but it's hard to do in a deliberate or informed way that you feel like you have made the right decision, if that makes sense. Anybody else have any questions? Yeah, thank you, Ted, for your sharing today. Thank you.