Hi, I'm Trey Cowan, I'm here with Brenda So, and we're security researchers here at Red Balloon Security. For the past year and a half, we've been working on this ATM, partially as a CTF target, but later as a research project. So this was something that kind of evolved out of the CTF work that we've done. So our agenda today, first we're going to talk about this ATM, what's involved in here, what's involved in a normal ATM, then we're going to talk about setting up our own payment processor, what we had to do to get that to work, and then our two vulnerabilities that we discovered. So the first in the remote management system on this device, and the second in its implementation of the extensions for financial services component, which we'll get more into later. So one of the things to note here is that, you know, there's been a lot of talk of ATMs in the past. One of the more famous ones was Barnaby Jack's talk ten years ago, where he demonstrated a bunch of cool things, jackpotting ATMs, installing rootkits. And you know, we kind of wanted to see how things improved in over a decade. And yeah, that's one of the ways we got here. The initial spark was, we were at a conference and accidentally unplugged an ATM as we were setting up our own table. And notice something funny on the screen when we turned it back on. This is the startup screen on the ATM. And you'll see here that this is running Microsoft Windows CE 6.0, which is quite an old version. And you know, at Red Balloon, we've worked with embedded devices quite a bit. And so there are people here who know quite a bit about Windows CE. So we thought it would be an interesting target to start tearing into. Now you'll see these ATMs all around the city. Our city is Manhattan. In things like bodegas, gas stations, street corners, anywhere. They're a fairly common ATM. And you know, we thought we may as well get this one. So we did. We got our own ATM shipped to our office. In fact, we're up to, I believe it's five ATMs now. Three of this larger ATM, this is the Halo 2. And then two of a smaller ATM that is actually able to go on a flight with some modifications. So it's easier to take around to conferences. So one of the things we want to do on our CTF was teach people about, you know, card technologies. We got people to interface with the EMV chip, magnetic stripes on the card. And just any way that you can think of to interface with this device in ways that you wouldn't normally be able to interface with something. So that was cool to be able to, you know, create a ecosystem around that. So we actually had this at the IoT Village last year. This is the leaderboard, the final leaderboard. And those are real cash payouts. So we paid everyone in $2 bills. It was quite a fun experience. So this is the smaller ATM that we took around, the MX4000W. So it's almost able to be taken on a flight, but not quite. You have to take out the cash dispenser in order to get it to be underweight. This is the case we took it in. There's actually a number of times we've taken it on flights for quite a bit of money. And also across international borders. So we took it to Canada one time, which was quite a struggle to get through border security. And it ended up not being the thing they gave us the hardest time about. They were more concerned about the T-shirts we were importing into the country to give away. So we registered as importers. So there was a lot of people that I want to thank for the work in the CTF that we did. Alex, Alex, our CEO Ong, Brian, Jatin, James, Rafi, and Tim. This was a lot of people helping, a big group effort. So thank you guys for that. One thing you need to be able to understand about the ATM industry is there's generally two market segments. The first being retail and the second one financial. Retail is generally more focused on cost and being appealing to people who just want an ATM on their property to be able to give to their customers, let them get cash out of it. Just any time you need cash to appear out of thin air. The second one is financial. That one's generally more focused on being more secure and more up to date. Those are much larger ATMs often, and you generally won't find those except in a bank. Most of these ATMs run Windows, and there's a number of manufacturers, but this is one of the most common ones that we found. So how does an ATM work? You insert your card, some magic happens, and then cash comes out. Well, there's a lot of moving components here. Firstly, it's a vault with some holes in it, notably the Ethernet cable coming out the back, though not all ATMs have that. Some actually use a cellular connection. So this is our ATM. There's two components to it, two compartments. The top section, which is a little bit lower security in terms of the lock, and the bottom section, which actually contains the cash. The top section, you'll see, has the receipt printer, card reader, pin pad, and also the main CPU and any network connections in it. The bottom component has the cash dispenser, which works with the cassettes. So the cassettes will actually hold all of the cash, and the cash dispenser obviously dispenses that. So there's two separate sections there. And in fact, the key for the top section, as Barnaby Jack mentioned 10 years ago, all the keys for the tops of the ATMs are the same. So you can't trivially get to the bottom of the ATM where the vault is, because there's different keys there, and then there's also an electronic lock, which has a numeric code. However, the top section only has a key that's commonly available. So when we originally got the ATM, one of the problems we had was our intern actually locked the key inside of the ATM, which is possible to do, because this thing automatically latches when it's closed. So we went and actually 3D printed a key that we used in the top of the ATM, because all the keys are the same, and we were able to open it, retrieve the real key, and continue on our way. Again, most of these devices run Windows. This one specifically runs Windows CE 6, which is quite old in terms of operating systems. This was released before Barnaby Jack's talk. There's a lot of modern protections missing from it that you would expect in a device that literally holds thousands of dollars. So when we opened up the ATM, we were greeted with this main circuit board. It has an HDMI, USB, Ethernet, and interestingly, a dial-up connection, so you can hook this up to a phone line and set things up that way. And then connections to the cash dispenser and receipt printer. So immediately looking at it, there's HDMI and USB, so can we just hook up a monitor and keyboard and get something going with it? Well, unfortunately, there's no Explorer shell that pops up with this. It's all in this kiosk mode application, winatm.exe. So our initial attempts to interface with it through a keyboard actually completely failed. The keyboard didn't work at all. Even caps lock didn't work. And the reason that that would happen is there's actually no driver for the keyboard built into this operating system image, which is actually very smart, because there's no situation really where you'd need a keyboard on this device. The pinpad is not treated as a keyboard. It's all about reducing the attack surface area there, so you can't just hook up a USB rubber ducky and run some bad scripts. So I'm going to hand it off to Brenda now to talk about, since we couldn't interface with it through a keyboard, what we actually did to work with this device initially. All right. So on the main port, we found these very suspicious pads, and on the back, around the same location, there are these resistor pads. So we suspect that this might be JTAG. And it turns out it is. It is a standard 10-pin ARM connector. We do need to solder some pull-up, pull-down resistors on the back. But after we do that, we're able to connect it with JTAGulator, identify it as JTAG, and use a JTAG debugger afterwards to interface with the ATM. So that's good. The next step is to dump the flash in order to get the firmware from the ATM. Now, on the ATM, the firmware is stored on the NAND flash. As you can see inside the little red box, it's 48 pins and a service mount. So it's pretty painful to rip out from the board. But we did desolder it at one point, and we used the SuperPro, which is a flash reader-writer, to read and write to the flash. We did it a couple of times, but eventually the board died. The board just can't handle that many times of soldering and desoldering, and we did rip out some pin pads, and we cannot recover it afterwards. So at that point, we're kind of panicking, right? Do we need to buy a new ATM? No, not really, because we found out that we can just go online and buy the main board at $400 a pop at atmpartmark.com. So we bought a few main boards, and they did work, but we don't want them to break again. So this time, second try, let's be more resourceful. We think maybe there is someone who did some reverse engineering and put them online. Maybe the firmware is already online packaged nicely, but it could also be behind some paywall. We don't know. But with enough Googling, we found out that the firmware is actually publicly available. Now, Trey mentioned the two versions of ATM that we got. It turns out that they both share the same firmware update. So we only need to download it once, and we start looking at it. So in the firmware update, there are three main files. The bootloader, nk.bin, which is where the kernel and other kernel libraries are stored, and most importantly, a master.zip file, where all the application binaries are. This is where the ATM executable is, it's where the libraries that the executable uses are, and it's where all the audio files, the JPEG that is used by the ATM are. And we look at the application binary. The exported entry in the application binary still has their names on it. So from a reverse engineer's perspective, it gets pretty easy to figure out what each function does. So for instance, if you want to figure out the dispense money functionality, you just find a function that is called dispense. Or if you want to figure out how the receipt printer works, you find another function called printReceipt. So that's a win for us, right? So with this firmware update, we tried our first firmware modification attempt. We didn't do anything fancy, we just tried to change the please wait while loading screen to please wait while pwning. However, when we changed that one character, we got stuck on the boot up screen. Now why does that happen? That's because in this firmware update, the manufacturer enabled Microsoft code signing. It is used to ensure that the software has not been corrupted by third parties. And in our case, our application binary is assigned with a certificate that is named MX5300CE. Now, at that point, we don't really know where the certificate is, and we don't really know how the verification process works. So in order to figure out the digital signature, we have two ways to do it. Either we take the time, reverse engineer the code signing algorithm, create our own certificate, resign everything, or we just find where the certificate verification function is and return true. So in order to do that, we need to take a deeper dive into how the kernel files and the kernel is structured. As mentioned before, there is this file called nk.bin where the kernel is. So that file is packaged in something called a bin.fs format, and within a bin.fs format, there are these records. In one of the records, that's where the kernel and the libraries are. We took out the record, and we started trying to figure out how that binary works. In that binary, there is the Windows CE header. It's pretty standard. You have your magic byte, you have your start address, and more importantly, there's a pointer to the ROM HDR structure inside a binary. This structure has some very interesting information. It has the physical start address, it has the physical end address, number of files, but more importantly, it also points us to the module entries. With that table of contents, with the ROM HDR structure, we figure out where nk.exe, which is the kernel, is. We figure out where the library is inside the binary, and we're able to parse out the kernel and the libraries. We use a tool called eimgfs to extract the files. And we figure out that although the application binaries are signed, since in this version of Windows CE, the kernel is used to verify the application binary, the kernel itself is not signed. We found a file called filesys.dll, which checks for certificate verification. Now, this is part of the control flow graph of the certificate verification function. We figured that out because there's a string, literally, that says, search verify. And as we're analyzing the control flow graph, we realize that every successful operation would return a number 4 to the caller. So, here's what we do. Instead of returning an error code on other paths, we just modify to always move the number 4 to r0, which is the return register in ARM. And after we patch filesys.dll, we package the whole thing, we successfully bypass signature verification. And from then on, we're able to modify our firmware and add our own custom code to the ATM. So, here's a video of the ATM having custom code on it. As you can see, we press a button and we printed out a small receipt, like a portrait of the ATM, so we think it's kind of cheeky. So, that's why we did it. So, that's good, right? We got firmware modification working, but now it really has to work as an ATM. And throughout this process, we found some very interesting stuff, right? So, firstly, this is a very old device. It's a pretty slow device. And each update takes around 20 minutes. We have to sit there and babysit the ATM as it's updating and manually punching the settings. We also found a lot of peculiar commands. So, for instance, within 5 seconds of the loading screen, if you hit clear, left, right, clear, clear, cancel, you can clear the settings on the NVRAM. Or if you hit enter, clear, cancel, 1, 2, 3, it would bring you to a password prompt, which brings you to the operator screen where you can change the settings on the ATM. So, we figured out the firmware update process. We're pretty good now, right? We have JTAG. We have the firmware itself with some debugging symbols. We have an understanding of how the firmware update process works. We are able to modify, add, and remove executables. One last hurdle. It keeps on getting stuck on the whole screen. Like, we got stuck on this screen for a while trying to connect something. What is it trying to connect to exactly? So, we did some digging, and it turns out that the ATM is actually trying to connect to a service called the payment processor. Now, there are these big card networks that issue a card to you. So, for instance, it could be your MasterCard or Amex or Visa. And when you put in your debit card into the ATM and try to draw money out, there is a middleman called the payment processor that would help the ATM connect to these card networks. So, there are different kinds of protocol for communication between the ATM and the payment processor. But the one that we looked at is called the Triton Protocol. Now, the Triton Protocol is a request-response communication protocol. There are four different types of communication pairs, but the most common ones are the configuration pair and the transaction pair. We did find the documentation online. However, it is a preliminary specification, and it is very out of date, so some of the information is wrong. And we needed to use Wireshark to figure out the correct request-response format. So, this is how it works, right? When you first boot up the ATM, it tries to connect to this payment processor. And the payment processor, once it receives a request, it sends back a response having some important information in it, such as the surcharge amount that it is going to take on the ATM. And for subsequent transactions, it would send a balance inquiry or withdrawal transaction code. So, the ATM would send a packet to the payment processor, having the card number, encrypted PIN, withdrawal balance if you are withdrawing money. The payment processor takes that packet, talks to the network, talks to different card networks, and returns whether you can successfully withdraw money or not with a success-slash-error code. So, you might think, this information is pretty important, right? So, is that information encrypted? And the answer is yes. It is encrypted with SSL or TLS. However, this is an option, which means that operators can actually opt out not to use encryption for Triton traffic. However, the PIN numbers do have an extra layer of protection. And most use triple DES for encryption. It is pretty standard triple DES. It uses two keys, K1 and K2. So, the PIN would be enclosed in its own padding. The ATM encrypts it, sends it to the server, so the server would decipher it. So, triple DES is a block cipher. It is a shared key protocol. And the setup is actually pretty interesting, right? So, when a technician comes to your store or restaurant to set up the ATM, it would punch in two keys. And these two keys are XORed together to form a master key. Now, the server also has knowledge of this key, but it is not the final keys used to encrypt the PIN. So, this is how it happens. Once the technician punches in the key, both the ATM and the payment processor would have a copy of the master key. The ATM would tell the payment processor, hey, I'm using triple DES. The payment processor would acknowledge it and encrypt two other keys, which is the final K1 and K2, with the master key, and send the encrypted pair of keys back to the ATM. The ATM decrypts K1 and K2 with the master key, and those two keys would be used to encrypt your PIN number. So, when someone enters their PIN on the ATM, the PIN is encrypted with K1 and K2, and that encrypted PIN gets sent over, and the payment processor would decrypt it with K1 and K2. So, after we understand the Trident Protocol, how the PIN encryption scheme works, we wrote a server, a Trident Protocol server, put it on a Raspberry Pi, and connect it to the ATM, and the ATM is finally functional. So, one of the first things you want to do on a device like this that's hooked up to a network is to see what surface area it exposes in terms of open ports. So, that's what we did. We actually found eight open ports on this device initially. The first two are the Windows CE web server, the default web server that's built into all Windows CE images, if that option's enabled, running on this device. When you actually pull it up, it's just the default web page that gets returned. So, likely this was something that just wasn't removed from the image as it was being built. Interesting aside is that you'll find a lot of Windows CE devices on the Internet. There's a couple of queries you can run to look that up, but especially something as old as Windows CE 6.0 on the public Internet would be a concern, ATMs, I haven't seen many, if any, ATMs on the public Internet. Mostly other devices. So, this second port, or I guess third port that we found here, the 5555, was a bit puzzling at first, but we realized it was the remote management system default listening port. So, that's something that you use to update the ATM, to administrate it, to check balances, that sort of deal. So, that's what that port was. And then we had these last five ports here. So, these were ones that we didn't quite know, ones that we weren't able to figure out easily. So, we tried connecting to them, but for quite a while we just weren't able to get any results from it, or send any data and have it be acknowledged. So, we'll come back to that in a bit, but first I'm going to hand it off to Brenda to talk a little bit more about RMS and what remote management system does. All right, so what is RMS? So, RMS stands for Remote Monitoring System Service, Remote Management System Service. However you want to call it, it is a service that lets customers control the collection of ATM remotely. So, the customer can use this service to update the firmware on a bunch of ATMs, check the amount of money left, download the transaction history from the ATM. Now, this is an optional service, meaning that users can enable or disable it. The default port for RMS is 5555, which corresponds to Trey's port scan. So, in RMS it uses the ATM's ID and the custom password for verification. So, when we were reverse engineering it, we realized there was close to no documentation on RMS. So, at the end we needed to use a combination of Wireshark, Ghidra, and AIDA to figure out a communication protocol, and the process took around two weeks. But we eventually got it, right? So, the RMS packet is pretty standard, you know, you have a start by a terminal, but there's like an LLC at the end. The more interesting part is like the encoded data, where that part is actually obfuscated with an extra table hard-coded in the binary. And this is actually not the first time someone looked into RMS. In fact, in Barnaby Jack's talk in 2010, he jackpotted an ATM via a vulnerability in RMS. And since then, and we looked at his report, it turns out that the RMS packet structure is still the same. Obfuscation techniques didn't really change. And in his talk, he found out that a malformed packet can lead to authentication bypass and eventual firmware modification. So, the service should be secure now, right? Well, let's put it to the test. We want to use a fuzzer to fuzz it, but we don't want to set up memory or emulate some Windows CE functions. So, we used BooFuzz, which is a network fuzzer. It takes a lot of heavy work out of it, so we only needed to define the protocol in code, and BooFuzz would take it, test different inputs, and do the rest. So, we did get around five to six crashes. And when we're analyzing the crashes, we see that every time when we send a really large packet, so any packet more than 10 kilobytes, the device would crash and reboot. Interestingly, this happens regardless of whatever password or ID you send to the device. And with JTAG, we figured out that a crash happened in this function called RMSProcessTCP in the library that controls the RMS communication. So, let's take a deeper dive into this function and how it works. So, at first, the function accepts any incoming connections via TCP, receives the packet, decrypts it with the XOR table, verifies the ID and the password, parses the command, closes the connection. And the problem happened at this stage, where it received the RMS packet and decrypts it with the XOR table. So, what exactly went wrong? Well, it turns out it's basically a buffer overflow. In the function that received the RMS packet, it copies the TCP packet over to a global buffer without any bounce check. And what it did is that this eventually overrides a function point it has called when the application exits. And this copy happens before any kind of terminal ID or password verification. So, the consequence is, as long as you understand the packet structure, as long as your packet structure is sound, the buffer overflow could happen, and you can write shellcode in your packet to lead to arbitrary code execution. Now, what can the attacker do? We were investigating it, and we realized that most DLLs are paged out as the application exits, except for the functions that control the NVRAM. And in this device, in this ATM, NVRAM is pretty important because it basically controls anything on the admin screen. It stores all the settings on the ATM. So, for instance, an attacker can point the ATM to the malicious server because within the NVRAM, it stores the IP of the payment processor. You can change the denomination of the ATM. So, for instance, if your ATM is supposed to have $20 bills, you can change the denomination to $1 bills in order to extract more money from the ATM. And let's go to a demo of the RMS vulnerability. All right, so we have our ATM here. It has RMS running on the background. So, now Trey is going to send a packet over to the ATM. And as you see here, it says remote monitoring system is in progress. Trey sends a malformed packet over, but it still looks fine here, right? So, now let's say I'm the operator, and I need to perform a firmware update. So, I will do and declare cancel 1, 2, 3 in order to go into a password prompt. And then I put the operator password in. That brings me to an administration screen. You can change a bunch of stuff here. But right now, since I'm doing a firmware update, I'll go into system setup, system control, software update. Yes, I want to do a software update. So, this is where the shellcode gets executed, right? Because as the application exists cleanly, the function pointer that we overwrote would be called, and that would execute our shellcode. In this specific demo, we set the shellcode so that it would point... instead of pointing to the Raspberry Pi with the Triton protocol running, it would point back to Trey's laptop, which has the Triton server running. Right. So, as you see here, it just updated successfully, and we needed to wait a few seconds to reboot. Once again, this device is pretty slow. As you can see here, it's going to take a while for it to go past the boot screen and go back into normal operation again. So, one interesting thing to note is that as we're writing the shellcode, we need to figure out where the functions are. And as Trey said, since this is a pretty old device, it's a pretty old version of Windows CE, a lot of the modern protections against... a lot of modern protections and binaries are implemented. So, for instance, we don't see any ASR implemented in the binary through JTAG. So, what we're able to do is that once we use JTAG to figure out where all the libraries are in one boot process, the next time we rebooted those libraries, the executables would be loaded back into the same location, which makes the process of writing shellcode easier. And as I mentioned before, the shellcode would point the ATM to Trey's computer, and how it does is modify some settings on the NVRAM. The NVRAM controls all the settings, right? It controls whether SSL is turned on or off. It controls where the ATM is pointing to. And it's also a pretty simple function to reverse engineer. It takes two numbers, and each pair of numbers would point to, for instance, whether SSL is turned on or not. It would point to the IP string of the payment processor host. So, as you see here, now it's initializing. It takes a while. It's loading, and it's trying to interface with the peripherals. It prints out a receipt whenever it reboots, right? So, it's just saying, oh, test printing, okay, and it prints out a version of the printer within the ATM. It takes a while to initialize. But after initializing, you would see that instead of pointing to the payment processor on the Raspberry Pi, it would point to the Triton server that Trey is running on his computer. It makes a lot of noises, right? It's trying to print something. It's trying to make sure the cache dispenser works. All right, now it's trying to connect to the host. And as you can see on Trey's computer, our malicious payment processor is working. It's interfacing with the ATM. So, I have a card here. It's one of the cards that we printed in-house at Red Balloon. So, it has track 2. So, it has tracks here, and track 2 is where the interesting information is stored, is where your card number is stored, in fact. So, let's say I'm a customer, and I wanted to check my balance. It takes a while. I hit English. It asks me to enter a PIN, right? It can be anything. Enter. And let's say I want to inquire my balance on the ATM. Let's say I want to check my checking. No receipt, thank you. And it is connecting to the host, although it says an ineligible account on Trey's computer. So, you can actually see the expiration date of the card and the card number itself. All right. Back to you, Trey. Cool. So, we just saw the RMS demo. And now I want to talk a little bit more about interacting with this device and what we had to do to actually get things to work on it, since we didn't have a keyboard or any HRD device to really interface with it. So, we kind of had to actually take a look at this. So, there's an ActiveSync, probably, port on here. But we couldn't quite get that working. ActiveSync is the way you would work with Windows CE devices to interface with them on a desktop computer. But we couldn't get that working, so we actually compiled our own tool. This is Windows CE. It's a standard platform. How difficult should it be to be able to just compile something to work on it? Well, the caveat here is that it's Windows CE 6.0. So, this was released in 2006, initially. So, we actually had to go all the way back to Visual Studio 2008 to get this really going. It's quite an old IDE, but we knew it worked well under Windows XP. So, what we were able to do with this IDE was actually build some C-sharp applications, get them to run on the .NET Framework, which is actually on this device. It has a .NET Compact Framework on here. However, it's fairly old, so a lot of examples for C-sharp code, if you're not incredibly familiar with it initially, you can't just copy-paste off of Stack Overflow to get things working on here. A lot of useful features are missing. But, in the end, we did get an application working on here. So, we really wanted an application for our CTF to be able to have a web server that people could connect to, to interface with the ATM. So, this was the start of that. We actually popped a dialog box here. And, you know, we could have used the built-in web server on this device that you saw in the port scan earlier. However, there wasn't any DLL or any capabilities for any sort of dynamic content or scripting. So, that would have been a bit difficult to actually get up and running. So, instead, we created our own web server, which was difficult in its own right, because HTTP primitives aren't in the .NET version we're using. So, we had to build things on top of just straight TCP sockets. But, with some good examples, we fast-forwarded a bit and had a web server working, which is what you see here. So, this is our test setup. This is a device emulator running the .NET code and displaying our CTF web page there. So, for launching on Startup, there's a number of ways we could have gone about this. But, again, we didn't quite have any way to interface with the ATM at this point, since we are trying to compile our own tool. So, in order to be able to launch that tool, to be able to probe how the device works, we actually used the debugger every single time we wanted to run it, and hijacked the startup process, the call and create process, and pointed that towards our custom server. So, we could reverse the startup procedure and do the proper way through registry edits, which can be a bit difficult on Windows CE. But, what we ended up doing was actually just taking the executable that was on here, that would normally be launched, called winatm.exe, renamed it to something else, and then named our own executable winatm.exe, and then launched the original process that would normally be launched as a child process of our server. So, we've got this C-sharp code running, it's all good, but what would it take to get some native code running? So, let's actually dig into it here. What we ended up needing to do was use Visual Studio 2005, going even further back, and install a number of different packages to actually get this to work. It was quite a pain, but in the end it was actually quite worth it, because in one of the most amazing Microsoft things I've ever seen, you can click through a wizard and, from scratch, build an OS image, which is a pretty amazing concept. You're clicking little checkboxes to enable or disable different features, and change how things are built into it. So, from that we were able to actually see different DLLs that would normally be on the ATM, like the keyboard driver and things like that. But by this point, we had already gotten our web server up and running. We've got it launching every boot, and so we built all these commands to be able to interface with the device, check out what processes we're running, how to remove registry keys, how to remove files, any sort of thing we'd need to really dig in and research it, and have fun diversion while we did it. So, this was actually... we found a build of Doom for this device, and we actually got it up and working here. This was an Easter egg in some of our earlier CTF challenges to be able to find this. But it ended up... I'm not sure if it was eating up all the memory, but the system would just randomly reboot partway through after Doom had been launched. So, we had to remove that for further CTF challenges, but it was fun to get it up and running while we had it. And despite being a fairly slower and older ARM core, we were able to run this. So, one of the things we did next was take a look at the registry, see how things were configured, and look for any clues of things that might be interesting on this device. So, one of the things that we initially found that was kind of familiar were some of these keys, and you might take a look at them and recognize those numbers from some of the ports that were open earlier. And even more interesting, if you take a look at the key name, it's a little concerning, because you start to think, maybe this cache dispenser is somehow related to this open port on 8004. So, what is this? What are we taking a look at here? Well, here's a hint. XFS is what this is. Not the file system, the money one. And XFS is this standard platform for financial devices that exposes this sort of middleware, where you can have a Windows application send a command that gets passed through these layers of abstraction, and go to the service provider, the service provider being the thing that actually is able to interface directly with the devices. So, this allows you to build things in sort of Lego's fashion, so you can swap out different components of your system, theoretically. You know, swap out different cache dispensers, swap out different card readers, and there are all these standard different devices that you can put on here. So, you'll see the cache dispenser, you'll see the ID card unit, which is reading your card, pin pad, things of that nature are all in here. So, what is XFS? Where does this come from? It started out as a Microsoft thing, where they wanted to create the standard platform for Windows for financial devices. They seem to have really succeeded, because this is, you know, kind of one of the industry standards for how you would set up an ATM or any other financial device. And so, Microsoft handed it off to SIN, the European Committee for Standardization, who is actually the maintainers of the standard now, and you can go on their website and find all of these documents detailing how devices are hooked up in XFS. So, for example, this is the cache dispenser device description document here. So, this is great for people building these devices. It creates a fairly open ecosystem that allows manufacturers to be able to swap out different things and have that, which also causes an issue in terms that it's a fairly homogenous platform that allows people with very little understanding of ATMs to actually be able to create some fairly portable malware to be able to use on these different devices. That takes advantage of the XFS interface, and we've seen a number of different pieces of malware that use this. So, going back to the ports, again, this is something XFS-related. So, we see those numbers there, and what I did was go through and map out. You can see that after logical services, there's auxiliaries, card reader, cache dispenser, and then there's also the device class, which is what XFS would call that device. IDC and CDM for the cache dispenser. And created this mapping showing which registry key corresponds to which device class, which corresponds to which port. So, you can see here again that this is, you know, the device classes are the standard XFS designations for these types of devices. So, what does this tell us? There's open ports. They're related to XFS somehow. Can we make it dump out some money? Well, the problem again is, you know, we can connect to these ports, but we can't get anything out of them. We don't see any traffic, and we don't know what to send into them. So, let's sniff it. You know, let's see if there's anything on these ports, even on the local network interface on here, that's listening and sending messages to see if we can take that and use it to build our own messages or replay them. The problem here being that this is a Windows CE device, and you can't just download Wireshark for Windows CE because, as this very helpfully points out, there is no Wireshark for Windows CE. So, Windows CE does have packet capture capabilities, but it's not built into this ATM image, and I didn't really want to take the time to try and figure out how to port it to this ATM image. So, the easiest way to do this ended up being JTAG. And the way, the plan of attack here was to intercept the socket create calls, get the handles for them, and then map those handles to the different services, intercept socket sending receive calls, and look at the buffers, and save all that traffic, and then acquire some cutlets. So, what we did was went through, found where these registry strings were being read, and from that we were able to figure out which socket creation call corresponded to which different device class. And here you'll see that this is where we're hooking the send and receive functions in Winsock to be able to look at the buffer and take the data that is either being sent or the data that has been received, save that to a file, and take a look at it. So, this is all in Ladderbock, this is a JTAG debugger that we use, and it's great for scripting like this. So, as you can see here, we have a number of packets that came in. Some of these are send, some of these are received. So, it's just a bunch of binary blobs, and there's not very much that we can easily recognize in there. There is the US dollars string in the packet in the lower right, but it's nothing immediately obvious. So, first thing we tried was, can we just replay one of these packets? Because we know, we were doing actions on the ATM as we were capturing these packets, so we can roughly correlate what might have been sent to the cache dispenser to cause it to dispense cache. So, yes, we can just replay and send out some cache from the cache dispenser. It was actually fairly straightforward to be able to do that, and then you can see we dumped out some cache here. It was no need to learn how all the structure works, no need to learn how to work with these fields. You can literally just take this packet that you've seen, replay it to dispense cache, and that was fairly straightforward. So, that worked in the case where we just wanted to dispense the same amount of cache, but what if we wanted to dispense as much cache as possible over and over? Well, after looking at this dump for a while, we were able to figure out some patterns and see the structures in there, especially after looking at the XFS documentation, and we created some scripts that allowed us to parse these packets and then see what was in there. So, for example, here we have a packet where it's the result of reading card that's been put in the ATM. So you can see the card number there is 555555555555555555555555. That's the track 2 data. And we have these fields here that might not be immediately obvious, this command code, notably. So if you look in the XFS documentation, you can see that there is this concept of a device class, or service class, and then a service offset. So the service class being 2, that's multiplied with 100 to get the service offsets, which is 200. And then all of the commands are some offset from that base number. So 207 is this specific command for idcard read raw data, which corresponds to what we saw here, which is 207, which is hex cf. You can see the result of that read raw data there. So we modified this to work with the structure for the cache dispenser packet and, you know, pumped up the amount of cache that we're dispensing. And yeah, we were able to run that and we can actually run any XFS command on this device if we send it to the appropriate port. So kind of in retrospect here, you know, pro tip, if you're using TCP sockets for IPC, don't listen on 0.0.0.0. And if you're creating a networked device, at least do a port scan before you ship it. So we want to run through the XFS demo here and show you this machine spitting out some cache. Cool. So we have the ATM here. And I'm going to run the script we wrote for XFS. And you should see that the command is being injected directly into the XFS middleware. So none of this will actually show that cache is being dispensed. So if I run the command, it's going to dump out some cache. So this is just going to continually happen. It's going to keep dumping out $2 bills over and over again. And yeah, this is the result of a computer just being on the same network. You know, you can grab the Ethernet cable behind it and send a single packet to the ATM and it will dump out a load of cache. All right. Thank you for coming to our talk. And be sure to join us in our Q&A afterwards.