 All right. Hey, people. I'm Adam. I'm happy to be here. I hope you're having a great conference so far, and I'm here to talk to you about how the free internet runs on ads, which causes problems when ads go wrong, which is going to be our topic today in this talk. More specifically, I'll be honing in on advertising and Android. I'll bring us up to speed on real-world ad fraud examples. How does that actually look like? Next, we'll get to an awesome open-source dynamic analysis project. I hope you can use called Frida, and then we'll get to my favorite part, being how you can use Frida to win Android ad fraud in practice, and this presentation is going to be packed with a CVE unique detection methods that I save to reveal in this specific OSS demos ad fraud. So please, please ask me questions in the chat. I'm there right now to answer most anything you have. Please go ahead and ask don't be too shy. I'm here for that. To start us off, one reason I care about all this is that I always liked hacking stuff. So my background is in vulnerability research, cyber security, and I'm a reverse engineer here in Double Verify. They're who you go to if you want to measure ads at scale, meaning I'm supposed to know how ads should and shouldn't work. So first topic of the talk is advertising on Android. We're going to cover the players real quick, the Android components, a little bit of Android security, and then we'll get to ad fraud. So about the players, when you see an ad, there's a lot of players behind the scenes. There's the advertiser that's going to be Nike, Beats, the stuck adventure game, anything really. They all have one thing in common. They pay money so you know who they are. And on the other end, there's going to be the publisher. That's going to be the New York Times, this News app, anybody that has audience that like to monetize. So that's the advertiser paying publishers money to buy audience. That's all advertising 10 years ago. The advertiser paying the publisher money to buy audience. Now things are a little bit more tricky. There's a lot more middlemen and in the middle. This guy here we're going to call Johnny and there can be a lot of Johnny's between each sale between an advertiser and a publisher. And when each ad is sold, we're going to focus on a big middleman and Android for now being the ad SDKs. And the other SDKs they came to be because developers, they don't want to bother with this whole ad regulation thing, finding their advertising, sending over everything they need. Developers, they want money. So that's why most developers call ad SDKs. These SDKs, they find the advertiser who want to advertise in this publisher app, in the developers app. And when the developer says it's time to show an ad, ad is shown on the tiny portion of the screen, the developer gets paid, the SDK gets a cut of the profit and everybody's happy in the end. These ad SDKs typically display the advertiser's ad in what's called a web view. We're going to come back to these in a second. Ad SDKs typically display them there. This little blue component doesn't necessarily have to be blue, but web view is a small browser that goes inside the app. Every time an ad is seen, it reports an impression. The web view is out there making these browser calls and network traffic, meaning this is going to be an ad view. Remember web views because we'll dive into them in a bit. Take away here being these web views reporting clicks and impressions is what makes the money. And an Android ad fraud, if you can fake those, you win. So obviously people looked into Android and web views from security perspective. And since we're already on the topic of security, let's address the elephant in the room here. Yeah, the ecosystem was not designed with cybersecurity in mind. And you can already probably think of some of the issues but just to name a few, there's architectural issues with privacy because advertisers, they like to target specific demographics like location and gender. They want to know who they advertise to. So there's a whole market for advertisers out there for who knows more about who. There's also malware sizing. That's when you install malware through an ad. And if you have the demographic data from earlier, it helps you, your malware reach specific targets very easily. And adware is going to be malware that makes money showing ads. Now, typically when you build adware, you build it on top of existing apps, then you spread between devices. Each device loads your ad and displays it, you get paid for each ad being displayed. And each device becomes like its own little money printer. Each ad it generates is making you money. And since you're already going to legitimate with malware, might as well go all the way and put as many ads as possible in there. These people, they don't care whether you're in their app or trying to call 911. They'll show a full screen ad right in there in the middle. They'll make their back now, given that's not the best brand image for the advertiser, obviously, so even better yet, if poor views are getting to you, you don't like the whole human element thing behind it. I give an open GS talk recently about bots, very briefly the use case is you take a computer, you make it navigate to your ad, let's say on a website, the computer fakes anything a user would like interaction or anything. And the advertiser, all their metrics is going to show somebody seeing the ad, maybe somebody clicked on the ad, you're going to make your money. And this thing is going to be way more scalable than growing with humans. Once you have one bot that works, you can put them on the cloud, make a whole operation from VPNs, make work by the thousands. That computer, each one is going to be generating these impressions, showing the advertiser there's somebody rendering the ads, having fun printing money. Meantime that whole brand awareness thing I was talking about earlier, that's like entirely out of the window that money is wasted on somebody's automated browser or something of that sort. Part of why these issues are there in the first place is because monitoring is by design done on the client side. The way you measure these ads is web views on the low like small images in these devices, these are called tracking pixels, small images. And these calls, they're what measures the impressions being made. Let me repeat that. The client gets money for each impression call being made and the client is the one that's responsible to report the impressions. Let me repeat that. Most of the advertiser ecosystem by design gets the people who have the most incentive to report as much calls as possible, the responsibility to report them correctly. Advertisers hate this. So yeah, they pay money, they get less than what they paid for it. The ecosystem itself is hard to work with. An example of that that's gonna become relevant in just a second is how there's no built-in method to verify who you're buying from. And while there's some initiatives out there like Ed's DXD and Sellers Jason being gradually adopted and to help with that, they're not everywhere, there's ways to cheat them and how these work is a whole other thing. But remember, you can't always know where your ads are actually being displayed. All right, that's enough background for now. I think we're good to move into Android ad fraud. So with Android ad fraud, I'll talk about what the fraudsters are trying to achieve. Then I'll show how they can do this in Android by abusing web use. So starting off focusing on app fraud from publishers, what they want is to appear to sell more than they really do. They wanna make as much money as possible. If they do fraud, there's a few methods to go about it. You can see here in the screen, like just a couple of them, you can have pixel stuffing. That's when you put the whole ad inside a one-by-one pixel. So everything is rendered. The web views make the calls, obviously, but no real human is seeing anything on that one-by-one pixel. You can have a pop-up. Now, the example on the right here is something that I actually like seen during my actual work. We talked about earlier, the pop-up comes up as a surprise. The app is not even open. You're calling 911. This pop-up is gonna show very annoying for the user to handle. And yeah, very bad brand image. They do this all the time because the more impressions you show, the more money you get. Otherwise, there's out of view or ad injection or ad stacking, all kinds of different plays with viewability. What happens, ad stacking is when you put ads on top of each other, the advertiser is playing Russian roulette. If you're the one on the top, you might be seen. If you're on the bottom, you're a portal to metrics, but not necessarily getting the brand imagined like the brand image that you deserve. But it's not just publishers in this game. It's not just publishers who can do fraud. This part's gonna become crucial in a second. We talked about Johnny the Middleman with one example being Edesty Case. It was actually a lot of middlemen matching publishers and advertisers buying and selling ads. They do this on open markets called exchanges where these people can buy the rights to advertise looking to sell it later down the line for a higher price. Now, most of these middlemen, and they're gonna be good people that just wanna resell, but if you aren't, you can get a whole lot more money out of what it is you're selling. So what I mean by that is the players in the middle, they can refurbish these impressions. They can buy low sell high because they play with the data in the middle. So good examples of this, bundle spoofing. That's gonna be when you make the advertiser think they're buying ads in an app that's better than what they're actually getting. So let's say I developed out on Fidget Spinner app. Fidget Spinner is a little out of date, like not your best thing and you don't trust me too much because I talk about ad fraud. So as the advertiser, you're paying me let's say one buck per a thousand people viewing. And then on the other end, there's CNN. And to CNN, they're a recognized brand name. Let's say you like them better. So you're willing to pay two bucks for them. So if I'm able to make you think that my traffic from the Fidget Spinner app is the CNN traffic, I'm gonna be making double the money. This concept of faking something is gonna repeat. Device spoofing is the same, but with devices. So under the ads, they're nice and all. But if you've ever heard of connected TVs like Roku and that stuff shows video ads on the screen for like 30 seconds. So the Android banner apps, they're kind of small. Not everybody notices them. Advertisers are onto this. So they're willing to pay more for certain devices like these smart TVs, the big ones that have the big screens and display. And domain spoofing is the same concept just with domains. You make the advertiser thinks that they're selling in a better domain than they actually are. So if you're able to fake this data to the advertiser, you can get paid a whole lot more than what you should be. And we're gonna get to how you actually do this very shortly. But the first place to pay attention to it, Android ad fraud is gonna be web views. So we're moving on to how this fraud can be achieved. That's because an Android ad is the case primarily rely on web views. And those web views are accessible to the developer. And not just that, they actually expose a lot of interfaces that lets you play with the data reported. If we're trying to find spoof data, that's a good place to look at. And that's convenient for the developers. That's not designed to be like that. They have a lot of flexibility developing their app. So this is kind of a trade-off that the Android operating system had to take. How much control do we give the developers in around web views? They actually have a lot. That's actually why they're also an architectural soft spot in Android. So for example, here's a web view method. Once the web view is there, both the developer and the SDK, they can call this. And what it does is it takes the HTML data as a string, it loads it into the web view, having the web view think it's in a specific URL for all intents and purposes. So this is there to help app devs play with web interfaces in all kinds of ways. Again, a trade-off of authentication for usability, but fraudsters can abuse this in practice. You might be asking, how? How can fraudsters do it? For example, if the developer of an ad SDK is bad, they can do app session fraud like we talked about earlier, domain spoofing. If you're in charge of the domain where the ad is being loaded, you take your ad, you reload that same ad that you got into a separate web view with that base URL, new base URL, you're in complete charge of what's the domain that the browser is gonna think. You're in complete control of what the operating system's thinking that the actual URL is. So this kind of method is actually gonna open up a lot of avenues for ad fraud. And don't just take my word for it. Here's gonna be a little demo I made. It's gonna play, while it's playing, just keep in mind what I want you to think about is this is just one example, but it isn't gonna be the only way. So this is gonna be a little app that I made and this app, what it's gonna do is it's gonna open up like an ad in Chrome Inspect. I'm gonna look to see what does the advertiser is actually seeing in terms of the headers being set? What does the operating system think when I'm showing my ad inside the browser? What you could see here, I'll pause it small. The referrer, the HTTP header that reports in which URL is this ad loaded in, the cnn.com. Now, obviously my app, the little app I just developed has no business selling cnn.com traffic, but using webview.load URL, you're able to convince the operating system that whatever content it is you're loading in the webview is gonna be that. And you can make the operating system think that the advertiser when they run JavaScript in the browser in the webview, anything that they have to test would tell them this. So this is architecturally a little bit weak. All right, I'm gonna move on from the demo. Okay, so another issue with these webviews is gonna be network. Some of you are probably already thinking of how dynamic analysis with Frida can help you detect this kind of stuff. And we'll get to that in a moment, sure, but let's first talk about webview client. Webview client is a little class which allows you to modify network requests and program network responses going in and out of a webview browser. Once you attach this class to a webview, all the requests and responses, they're gonna go through whatever you program and you can change URLs, headers, content, anything you really want inside that browser. And for the browser, this is seamless, meaning if you attach this to an ad webview, everything going out to the advertiser, every single metric they can check over the network is gonna be under your control. So you can probably already see where I'm going with this. You can change, for example, the query parameters. So why does that matter? Some advertisers rely on language and country in query parameters. Let's say my traffic is in a country that doesn't pay as much. I can change the country being reported. All of a sudden I'm paid a whole lot more, but the advertiser, like the crowd they're getting is completely relevant for the ad. But why would I care? I'm just making my bucket ad fraud. My impression is gonna be giving me much more than it's actually worth. With the client also lets you control the headers being sent. Advertisers rely on these a lot. For example, let's say like extra question with, this header in Android and iOS as well, a little bit of different implementation, meaning is the same. That's the app that I'm showing the ad in. If I'm able to edit this header, I change the value, the advertiser is gonna see whatever app I put in there. So all of a sudden, Adam Fidget Spinner app can advertiser in whatever app that I actually want as long as I change it. I can advertise in the CNN app in Spotify and Facebook and anything really. Otherwise you can change the user agent. User agent header, we're mostly probably already know this, HTTP header reporting the device the call was made from. I see the sun is getting a little bit strong. That's how it is where I'm from. But like user agent, what's nice about that is you can see that it's gonna control the device that the advertiser is gonna see. So if I play with the WebView client, if I change the user agent, what I'm gonna see is that all the advertiser for all they know, all of a sudden I'm not selling on Android, I'm selling on Roku's, I'm selling on nuclear warheads, anything that can get me more money out of the story that I'm gonna tell. And there's a lot of like these little things that I can change with this point to being as long as I change enough, the advertiser is gonna get a completely different story. I can get paid a whole lot more for each impression that I make. And you'd think they'd make it harder than that, right? You can't just attach a class and do all this, like the demo you showed us Adam, there's no way, right? Now once you figure this thing out, it only gets worse. Android has interfaces for user interaction. Remember the adware from earlier? It doesn't even need you to click on the ad anymore. It loads whatever ads it wants and it clicks it on its own right away. Every day you open your phone, you're welcomed by a completely different home screen, which is gonna be whatever ad they click today. And they could even control, like you scrolling within the page, they can fake the interaction, show how interested you are at this ad that just opened their device out of nowhere. But the funny thing is, you'd think that the more experienced the fraudsters get, the louder things get. Like there's a lot more clicks, a lot more stuff opening, but taking it to the next level is actually gonna get a whole lot more silent. There's gonna be a whole orchestra playing, but not a single note is gonna be heard. Fraudsters who know some security can play with the GUI so you can only hear a whisper, meet window manager. So this is a class that what this guy does is gonna be orders that can order views, like in a Z axis, one on top of the other. And it allows you to have a view that's essentially on top of the view at all times. And as long as it's like that, Android, all the visibility metrics are gonna report that it's completely visible. So this is another trade-off. It's useful for accessibility service. You can show stuff on top of everything if you have the right permission, but it introduces some security concerns. And there's actually a CVE here, 2020-0099. That's about how there's a confusion regarding external monitors. So Android devices have an external monitor connected. And then there's a whole separate screen when you wanna put this window manager. Now what happens is there's no real check in place to verify that external monitor exists. So if you do this on a device without an external monitor, like you and I's phone, what would happen is there would be a sustained screen in memory when the ad is shown, but not a single pixel is gonna be shown on the real screen. And everything's gonna be reported. This we talked about is completely visible. Now this is gonna be a huge issue for ads like trying to measure visibility. And the research here, I'm gonna show you a little demo by my colleague, Arseny Levine. He looked into this in depth and he actually allowed me to use a demo that he made related to this. And when fraudsters leverage security, what we're gonna see here in just a moment is that it's also gonna be a little bit small, but we made with Chrome Inspect, we're looking into these web views. We're gonna look to see whether they're considered visible, whether the operating system thinks they're visible. And it's gonna be in this window manager thing. So the ad is gonna be displayed inside the window manager. And what's gonna happen is in a second, you'll see I'll push it forward a little bit, is that the ad is gonna be considered visible by all the metrics over here, but the screen in a second is actually gonna be closed. So when the screen is closed, shut down, no ads viewed whatsoever. What you're gonna see over here, I don't know if you can see it, visibility state's gonna be visible, the window's gonna be considered focused, there's gonna be no intersection reported. Meantime, while all this visibility is gonna be reported, obviously nothing is playing in the screen. Advertiser's getting nothing out of these ads. So yeah, this whole knowing your ad was seen by someone is really not that simple, and fraudsters can abuse this to show virtually zero ads on your screen. Meantime, they can operate this whole fraud thing, stealing a lot of money, making the internet a little bit less free for all of us. So I've seen fraud schemes generate user traffic by the millions to bring in websites with a lot of user activity during my work. My understanding is like, they understand the different layers of their interaction. They fake everything. They able to, with JavaScript, remotely hot code into the SDK, giving it instructions on what to fake every time. If they're being tested, they behave clean. If they're not, they do all this, device spoofing. They make it seem like the devices are the best. Domain spoofing. They choose top-level domains that we completely trust. Domains, I mean, TLDs or something else, but they choose everything to show that these ads are amazing. Data so clean, these are store players. Meantime, advertisers are not seeing that much turnover. Advertiser's gonna think my ad's not too good. Turns out their ad can be great. The players are not. The publishers or somebody in the middle could be doing something a little bit tricky. So what we've seen here is complex fraud schemes making advertisers think they're advertising premium traffic, convincing you users are out there interacting with this ad. Meantime, this whole ad spends waste that brand images out there, all of the money spent here is gonna go nowhere. So yeah, so there's a lot of ad fraud going on and there's a lot of different issues that we need to tackle to catch this ad fraud. And in this talk, to fight that, allow me to introduce Frida. Frida is an open source tool, allows you to dynamically analyze almost any code in memory using JavaScript. That sounds like science fiction, very high, very low level at the same time, but it exists. The thing can inject the gum JS JavaScript engine proprietary into embedded devices, computers, phones, anything, kind of like injecting V8 JavaScript engine into a process. And in this section, I'm gonna briefly talk about it so we can understand how it can be used for detection. Okay, next couple of slides about how Frida works are copied from an awesome presentation from the creators of Frida. I'll link in the deck first and foremost, Oliver and incredible, like made this whole tool, made a presentation and call his trusty sidekick great contributor to this Frida project. Also made the slides very, very great work from them. I'll link them in the deck, feel free to check them out. Thank them like special thanks for creating such an awesome tool. So as we said, you can dynamically analyze what's going on inside a process. You can look into the memory and modify it in real time with JavaScript. And the way it works is Frida process trace hijacks a thread in the target process. It injects a bootstrapper into it and that bootstrapper connects to your server. You write JavaScript code to change the memory. You look into the memory pages, registers, pointers, whatever you want in that thread in real time and you can do this based on certain events, functions, calls, anything like that. And when you're done running in dynamic hook, the original code is gonna keep running. So you can do what's called the trampling and security research. You can look into what's actually going on the device in the process in real time. This means Frida can help you debug someone else's code, process memory on your device. Let's say an app is doing something suspicious, maybe crushing or there's an extension that you want to look into it change. You can do that. And obviously this can also help you understand your own code. Like this is OSS stuff. After all, we work with many people in our projects. Sometimes you wanna understand why something crashed in your microservice or something like that. So you can debug, connect with Frida into what's actually going in there and look into the memory in real time. And there's gonna be a few text walls here for people to refer to this slide deck to reread. What's important for us now is to remember that there's a lot of use cases. Security folk know how important dynamic analysis can be. I recommend this tool for developers who wanna understand the next microservice crush. How are things working the way they are? Frida's very good at providing these answers with a high level of certainty. Next time you have no idea how that bug even happened, have Frida in your mind for that solution. Now for now, here's a few example of the tool that Frida offers in JavaScript for Android. And this isn't for you. This isn't here for you to memorize every letter. We'll have code in practice in just a second. Rather, this is here to explain how Frida works. So you can add a function to be performed in the main thread that's Java perform. You can see all the classes that are loaded or look into a specific class with Java use, I'm sorry. And if you wanted to debug a specific instance, that's gonna be Java choose. You can find it initiated on the heap. So you can debug what's actually going on with a specific instance of your object. And that let's say also modified during runtime. And there's a whole lot more to this, but for our use case, the most important functionality is you can change the implementation of a function while the code is running. Again, credit to Oliver and all the great Frida contributors. That's good for Frida in general. Let's move on to how Frida can be used for Android ad fraud detection. Finally, my favorite part of this presentation, thank you for staying all the way through. Reminder, feel free to ask questions. This part is gonna be tricky. I'm gonna reveal here methods of detection with Android. So we're gonna start with a quick warm-up. So who here knows about Chrome inspect? If you do, you know that unless you look into any Chrome based browser and look at what's going inside it at real time. And that can actually look into Android web view chromes as well, but only if a specific function was called with a specific value by the developer. So if you like debugging with Chrome inspect, if you wanna understand what's going on on your device in somebody's app, and immediate takeaway, you can use Frida to make sure that that function gets called the way you want so you can look into it. It's that simple. So it'll let you debug any web view on any app on your device. Here it is super simple with Frida. First line, take the web view class in memory. Second line is overloading the set web contents debugging method, meaning we're now in control of anything calling it. We're running our code, our JavaScript code while it is being called. And here we make sure the developer calling it made the right call. No matter what Boolean value they called it with can be false, maybe no, it will be called with true in practice. So anytime anyone's trying to change whether the web view is debuggable, they're gonna change it to true. They're gonna change it to the value we want no matter what they meant to do, which means that all the web views in our device will be available for analysis in Chrome inspect. That's a static method. Isn't that neat? Okay, that's enough warm up. Now we're gonna talk about real Android detection methods. And first thing is gonna be pretty easy. Let's say you have your device and let's say you have an app that's outside of the bonds of the device. So it's not, cannot possibly be seen on the screen. It's breaking out of the Android layout out of the constrained layout of whatever it is you have and it cannot possibly be displayed. Here, these parameters are gonna mean that everything's gonna be okay. So what's gonna happen here is that we'll have the display metrics of the actual application context. We're gonna fetch the screen size from the memory. We're gonna see what's the size of the screen and we're gonna take a web view instance that we're currently looking into and we're gonna see in memory where is it actually loaded, not what the developer reported through JavaScript, not what the add is the case saying. We're gonna see what the memory is saying. And if the memory says in these two parameters down here that for some reason the starting X of the add X axis is beyond the size of the app, beyond the size of the screen, there's no way that thing is being displayed. Same thing for the Y axis. So if these two parameters are ever true, you know there's something fishy in play. And this is actually gonna be super easy to scale because once you have this kind of a fraud detection, you can run it on a myriad of apps. You can download the app from the Play Store. You can run this code on each one of them if it flags one of them, if it flags two, three, four, and so on and so forth. You can be relatively confident there's something fishy going on. If at the time of display, the ad is not even on the screen. Otherwise, in another case we've spoken about is how ad fraudsters can abuse web views, load data with base URL. Now you can look into the parameters of this function with Frida and you can verify that the call being made isn't suspicious in any way. So let's say here you can see Frida opens up new avenues for detection. So we have like all the parameters we have here. You can see like the base URL, the data, everything that we've seen over here. So we're gonna see on each call all these parameters get loaded. And then what we can do is we can retain the instance. So we're gonna still do the load data with base URL earlier. We're not gonna disrupt the flow of the app. But before we do, we're gonna run a couple tests. So every time this function is gonna be called, we're gonna verify what's the base URL this app is trying to convince me this web views loading in. Let's say the app is Adam Fidget spinner app, the web views an ad and the domain is cnn.com. Okay, something suspicious here. Same thing you could do to verify that data is not doing anything suspicious, making any kind of HTML calls or anything like that that it could possibly make. And this opens up a whole lot more of avenues for detection. These detections are gonna be very, very scalable. In a similar fashion, you can check object state when the device is reporting an ad is gonna be displayed. No more caught examples, but a lot more interesting stuff. Say the screen is turned off while the ad is being displayed, that's something that's very hard to guess, just looking at the code statically. With Frida, you can check this dynamically, very easy once you're checking the memory in real time during the display. You can easily look into the network calls. You can see who's putting suspicious headers or query parameters where they shouldn't. And this is really useful against these kinds of web view tricks that we talked about earlier. Let's say the query parameters, the country, the language, you can look into the parameters of certain functions and that can help you fight specific things you know to be wrong. For example, the window manager vulnerability with type presentation, we know this thing is gonna be happening when a function is gonna be called with a specific value. If we see it as being done, we can validate it. With Frida, doesn't matter how the developers trying to hide the code in the end, as long as the call is being made invalidly, you can always catch it. That's one advantage of dynamic analysis in general. And because you control the memory, it's very easy to play around anti-debugging. This can be basic classic anti-debugging like certain functions, trying to kill your hooks whenever you're just trying to override, but this can also be proprietary stuff. So some tricks fraudsters use, they don't do their fraud initially, they wait for a certain amount of time to be passed. And probably we're probing around certain Android operating system internals, job schedule and stuff like that. You can't find these parts of the code that actually do what they shouldn't. So you can make the code that would never run otherwise. You can see it running in practice. You can debug it running in practice even though on a static analysis, just looking into it for like a couple of seconds of analysis, you would never find it. You don't know how much time to wait. With Frida you can understand how much time should you wait and then go on from there. And obviously I can go too deep into the details here. I can't tell you what exactly I would do to achieve this because many of these methods are gonna be proprietary, especially if they get more and more complicated. There's some work there that I'm doing where I'm at, but fraudsters are also keeping their eyes open. What I'm trying to lead into here is gonna be this. If at the start of this talk, I told you the free internet runs on ads and that causes problems when ads go wrong, there's a whole lot more to it, but I hope you can take away Frida for all its awesome use cases and how when you work on open source projects or anything really big, you keep in mind how it can go wrong. Thank you. Feel free to reach out, keep asking questions. I'm here for you to talk to me. Thank you OSS and OpenJS for letting me talk like that. I've had a great time talking and I'm here for Q&A. Thank you so much and have a great rest of your conference.