start	end	text
13740	18860	Hey, welcome back to AppSecVillage. Hope you're having a great time here at DEF CON 2020.
19120	23100	Get ready for another wonderful talk. We've got Jared Overson.
23560	28160	And he's going to talk about Hackium, a browser for web hackers.
28160	31920	Okay, let's be honest. With a name like Hackium, you've got to kind of check it out.
31920	35500	It's like the coolest name ever. I know I'm going to be watching this one.
35620	38980	Jared is the Director of Engineering at Shape Security, now F5,
38980	44160	where he designed and led the development of Shape's enterprise web security platform.
44280	48160	Jared is a frequent speaker on modern web threats and has been quoted by Forbes,
48160	51640	The Wall Street Journal, and CNET, along with many others.
52060	55640	He co-authored O'Reilly's Developing Web Components book,
55640	59200	delivered dozens of analysis and reverse engineering tools,
59200	63180	and frequently writes about web development and fraud.
63180	67740	Please welcome Jared to the AppSec security stage.
69500	76880	Hey. Hi. Thank you. Thank you for being here. Thank you.
76880	82320	This is awesome. This is so cool. This is strange.
82320	85780	This is strange. I can't lie. This is strange.
85960	90040	I can't see you. You're not actually here with me.
90040	96860	And I was going to have slides and then it started feeling like a webinar with my little picture in the corner.
97200	102080	And a webinar is the last thing I think of when I think of DEF CON.
102080	106820	And I just I couldn't do it. I just physically could not do it.
106960	109560	So we're just going to we're going to do this live.
109780	113340	It's a prerecorded with a whole bunch of cuts and whatever.
114800	118880	But it is it is what it is. This is this is a strange time.
118880	124980	But anyway, I'm excited to talk to you about what I'm going to talk about.
124980	128460	But first, who am I? I'm I'm Jared Oberson.
128460	131820	I talk a lot about credential stuffing and automated attacks.
131820	136680	And I'm just a web hacker. I've been hacking the web for a million years.
136680	146240	I work at Shape Security, now part of F5, director of engineering, where I built Shape's enterprise web application security platform.
146240	155900	And it was it was an awesome opportunity because it gave me the chance to basically make a product that would defeat me.
156220	163440	And that was fun. I thought like, well, I could do this, but then I could beat me by doing this.
163440	167560	And then if I did this, then I could do that. And if I did that, I could do this.
167560	172120	And it was it was just a cool, fun game against myself.
172120	176140	I ended up building something pretty cool, but I'm no longer building that anymore.
176560	182140	And I'm building other things, which is what I'm going to talk to you today about.
182140	185720	But enough about me. You, let's talk about you.
185720	189740	I mean, everybody knows who you are. It's really awesome to have you.
189740	194360	Thank you very much. So let's get started.
194360	208840	So I am I am really excited to to introduce three major tools, but really a whole suite of tools that I guess I've been working on for my entire life.
208940	220610	Every six to 12 months, I seem to rebuild part of these tools in order to do something with the Internet and the Web that I want to do, but can't given the way the Web works.
220610	230230	So over the course of the past 20 plus years, I've been crafting and honing my strategy for manipulating Web stuff.
230230	239530	And over the course of the past year, year and a half, I've started to to to to focus those into a few projects to see how good I could make it.
239550	242610	And I'm really happy with what I've got.
242610	247150	So today I'm talking about three major projects.
247570	253510	Hackium is the one that's going to be most interesting to most people because it feels like a browser.
253750	266470	But Shift Refactor and Shift Interpreter are much more technically complex and give you the ability to to to mold and twist JavaScript like you're a magician.
267570	276730	JavaScript, I know, is not always the most well-respected language in security circles, but you can't get away from it on the Web.
276730	279030	JavaScript is what you got and you have to deal with it.
279030	293550	And when more and more business logic is showing up in websites, you have to understand more of it because what is transmitted from a Web page to a server is becoming less and less understandable on its own.
293550	307130	So all these tools together give you the ability to manipulate Web stuff, understand Web stuff and transform Web stuff so that you can just control it better, which is awesome.
307130	312070	So this session, I'm going to be going over three or four major topics.
312070	315250	I'm going to be talking about what Hackium is.
315290	321590	I'm going to be going over the REPL and the initialization command and configuration so you can get started.
321590	337890	And then I'm going to be going over how to use Hackium with external services like 2CAPTCHA to solve CAPTCHAs and also how Hackium generates human behavior to make it bypass trivial defenses more easily.
337890	348940	And finally, going to be going over how to use Hackium with Shift Refactor and Shift Interpreter to automatically programmatically deobfuscate JavaScript.
348940	361260	Hackium is a command line tool. It can act as a browser. It's an automation framework. It is a foundation for building Web hacking stuff.
361620	366120	So Hackium is a Node.js library. It is installable via NPM.
366560	375640	You can install it via npm install-g hackium, which will install the Hackium library and the command line tool globally.
376540	382080	Install Hackium. npm install-g hackium.
384780	388760	NPM will do all of the stuff that it needs to do.
388760	392920	It's downloading Chromium R782078.
393080	400740	So Chromium is downloaded via Puppeteer right now, and it's a bundled Chromium that is guaranteed to work with that particular version of Puppeteer.
400740	410980	Hackium started as a bunch of Puppeteer scripts that grew and were extended and copied over and over again over the course of a long period of time.
411580	419480	And for the time being, Hackium extends a lot of Puppeteer's functionality and reuses the bundled version of Chromium.
419480	430160	And it will continue to do this for as long as possible until the code bases of each diverge in a way where code reuse is no longer possible.
430160	434300	All right, so now we have Hackium installed locally.
434300	436900	Version 1.0.4.
436960	442500	We start that up, we get what looks like a normal Chrome browser.
442500	447000	Since we have Hackium running, we can use it just like we would any browser.
447000	454740	Comes with one extension pre-installed as the Puppeteer extension bridge, one of the dependent projects for Hackium.
454740	461900	This allows Hackium to communicate to and from the Chrome extension API.
461900	469100	So Hackium also exposes all the Chrome extension API to Node.js scripts and automation scripts,
469100	479680	so that you have access to a lot of additional functionality that is normally inaccessible from command line scripts.
479680	486280	So Hackium also includes an in-page client for plugins and functionality to hook onto.
486280	496680	So there's a consistent way to share and communicate between the extension and the automation script behind Hackium.
496680	501780	So we can use the event bridge to communicate with the extension.
501780	506440	We can post messages back to our automation script.
506440	511780	And if we had anything else on here, we'd be able to access them.
511780	515980	So Hackium also exposes a REPL to the command line.
515980	520400	Let's see, we have access to page, which is our active page.
520400	525700	page.gotoHPSexample.com
527460	529800	Let's go back to Google.
533930	539030	So you can use the REPL to do everything that you would normally do within a Puppeteer or Hackium script.
539030	547010	Here we are typing into the input that has the attribute aria-label="search".
547010	558190	We're typing Hackium with a new line at the end to basically just search for the term Hackium in Google's website.
558230	561010	So this is a good way to experiment with automation.
561010	569790	And you can also get out of here and use the REPL history to get a recording of everything that you've typed.
569790	577010	So you can just copy and paste these directly into a Hackium script and share these with other people.
577010	589750	The shareability was a very, very high priority for Hackium because historically it's been pretty difficult for people to share their work manipulating websites.
589750	598030	If I were to make something neat that manipulated Google.com or change the functionality of Spotify or Twitter or whatever else,
598030	604590	it would be fairly difficult for me to just quickly share that with somebody else.
604590	610510	There are two main ways that people have historically manipulated websites.
610510	617210	And that's either via the embedded browser dev tools or with a proxy or both.
617210	628370	So a proxy would give you access to intercept and manipulate and change any transactions for the web, which is very, very powerful.
628430	637070	But if you've worked with proxies extensively in the past, you know that they can be somewhat of a pain to install,
637070	643310	especially if you're talking about different platforms, Windows, Mac, Linux, or whatever.
643310	648930	And if you do go this route, then chances are you have a favorite proxy.
649050	654310	And if you try to share it with somebody else, they've got a different favorite proxy or a different configuration for the same proxy
654310	659830	or something that makes it difficult to just quickly share your work with somebody else.
660450	668690	Now, if we do a lot of our work within the embedded browser developer tools, which are extremely powerful and fantastic, definitely,
668690	674410	we have no way really whatsoever to share that with anybody else.
674470	679990	A lot of the work is manual. It's difficult to automate if it's possible to automate at all.
679990	688910	There are like content snippets and other little things that you can use to repeat repetitive work.
688910	693810	But those aren't easily shareable. They're not easy to really configure in the first place for yourself.
693810	705030	And all in all, it's kind of a pain. When you do this work, you get all set up yourself, and it becomes difficult for anyone to use your stuff.
705170	714790	So with Hackium, it was a priority for me to get everything as self-contained and bundled into one project as possible,
714790	723590	so that if you wanted to, you could share just a small configuration implementation to anybody, and they can see what you've done.
723590	739090	One of the important aspects of shareability is making sure that the user this is destined for doesn't have to know anything secret or magic about your configuration to get up and running.
739510	751670	So we take care of that with Hackium by making a lot of the base configuration stored in a configuration file that is just JSON or JavaScript and is portable so that you can deliver it to anyone else.
751670	760670	You can initialize one easily just by using Hackium init. You can set up the URL you want to go to by default.
760730	767690	You can configure whether or not you want DevTools to open automatically, which might be important for your script if you're communicating with DevTools.
767730	773470	We are not going to do that here. We can create a blank JavaScript injection.
773470	784790	One of the other top priorities for Hackium was to make sure that it was as trivial as possible to inject JavaScript before anything else is loaded,
784790	798230	which is the only way that you can guarantee a pristine, stable environment for your code, and to also make it trivial to intercept and manipulate content coming in so that you didn't need a proxy at all.
798230	806270	Hackium makes that possible with just generic injection files and interceptor modules.
806270	813590	We're going to say no to that. We will create a boilerplate interceptor and, sure, a boilerplate Hackium script.
813590	824590	We do not want to run headless, so now we have our hackium.config.js, which is a simple JavaScript file with the configurations that we set up.
824590	834870	We can see that we have a boilerplate interceptor. An interceptor is just a standard Node.js module that exports two properties.
834870	846410	One is the intercept property, which is an array of request patterns that this interceptor will be configured to intercept.
846410	858310	So here, by default, you can see that we have just a wildcard asterisk for the URL pattern, and we are matching script resource types, and we are doing it at the response stage.
859270	871970	And the second thing that an interceptor needs to export is the interceptor property, which takes a synchronous or asynchronous function that can just do something with a request.
871970	880770	So to share this work, we can just archive this directory. We can upload it to GitHub. We can publish it to whatever publishee service you want.
880770	888570	And anyone can download that and run Hackium with just the command hackium and see what you did.
888570	901370	So now that we have gone over the REPL and the getting started, we can jump into what makes Hackium different than other browsers and how to use its APIs to connect to external services.
901370	910290	So if you follow me at all, you know that I talk a lot about automated attacks, things like credential stuffing, scraping, and the trajectory of tools looking more and more human.
910290	933030	Now, since this is a browser that is controlled partially by scripts or extensions or power tools that do stuff, it's important for the behavior that is being generated to look plausibly human so that it doesn't interrupt your browsing and your usage.
933030	951150	So one of the extensions onto Puppeteer that Hackium provides is automatically generated simulated human behavior. Now Puppeteer and a lot of other automation tools have the ability to slow down behavior so that it doesn't come all puking out on the page all at once.
951150	968050	You don't type large, large blocks of text within a fraction of a second all at once. You can slow it down. But still, that's not quite human enough. Humans don't have consistent durations between key presses or mouse movements that all take a certain number of steps.
968050	987010	So one of the things I did with Hackium was to make sure that things like keyboard events happen at different intervals and durations all within a minimum and maximum expected human behavior. And things like mouse movements follow non-direct paths and sometimes make mistakes like this.
987010	1004030	So this is a slow, meandering move. You can see down over here, I kind of have to curve up to get to the point we're looking at. Refresh again. A random, larger curve. Much slower this time. We also overshoot and have to backtrack. Do this again. Overshoot and backtrack.
1004030	1030910	Now things that, where if you're looking at it, it would not definitely be automated behavior. This is important because just naive automation detection techniques will check to see whether or not you're clicking consistently at like a 0, 0 position on every element. Or if you're zipping from one point to another with no mouse move events in between. Or if you're moving all on a straight line or at the same velocity. Things like that.
1030910	1039910	So we have to account for that so that we can generate behavior that is not automatically blocked by everything that's out there.
1039910	1060850	Now another thing that you'll probably know if you follow me is that I hate CAPTCHAs. CAPTCHAs are just such a pain in the ass. Most of them are really, really, really bad. And things like ReCAPTCHA, Google's ReCAPTCHA, seem like they've gotten much, much worse over time.
1060850	1088130	Things like the little grid of pictures where you have to determine what a fire hydrant is or what a bus is, crosswalk, things like that. They're a pain. And CAPTCHAs are things that will pop up in the way of automation all the time. And it's an arms race back and forth trying to make an automated tool that bypasses CAPTCHAs. Then CAPTCHA makers get that tool, figure out how to block it, blah, blah, blah.
1088130	1116090	Now rather than build in any CAPTCHA solving within Hackium, it's much easier to delegate that responsibility to services and companies whose core purpose is solving and bypassing CAPTCHAs. So you can wire up services like 2CAPTCHA very easily within Hackium scripts just by using standard node libraries and node modules to make requests and parse JSON responses.
1116090	1138450	So this is a script that I put together. I am sucking in my API key here just so you don't see it. And next we're going to go to HTTPS old.reddit.com slash login. We are going to initiate a CAPTCHA request with our API key. We get a request ID.
1138450	1165110	And then we type in our username into the user reg input. Samuel Clemens 90210. We type in our password twice on the password inputs. Ctechastronomy is our password. And then we pull for request results. So the way these CAPTCHA solvers work is that you send a request. It's like, hey, solve this CAPTCHA. And then you pull for a response for when that CAPTCHA is done.
1165110	1183610	So you're just not sitting there waiting. You can do additional work while that CAPTCHA is being solved. So after we have solved that, we input the CAPTCHA response to an element on the page, g-recaptcha-response, and then we submit.
1183610	1210630	Now we can run this script, hackium-e-index.js. It'll pop up in Hackium. Go to reddit.com's signup page. Notice how the keyboard typing is not instantaneous, but it's not consistently slow. It's kind of a blah blah blah. That's the technical term for that.
1210630	1224530	So now that we're done, we're going to pop over to the console. See that we're waiting an initial timeout for two CAPTCHA. And then we are done waiting. So now we're pulling for our response.
1225310	1239610	And now that we're done, pop over to the web page and bam, Samuel Clemens 90210. We are on Reddit. We are able to, I don't know, prop up whatever political candidate we are interested in this election cycle.
1239610	1254490	And this is just one technique for getting by all the different defenses out there. And I want to make this clear. I do currently work at Shape and F5. Hackium is not a tool designed to bypass security defenses.
1254490	1276470	Security defenses for things like credential stuffing or spamming or scraping. Those operate at high volumes. And the type of work that a legitimate and curious hacker using Hackium would do is much, much smaller volume.
1276470	1282470	So that you can bypass things at small volume, but you'd be caught at high volume.
1283930	1286390	Cover my ass.
1286390	1303830	All right. So, so far I've talked a bit about just basic usage of Hackium with the REPL and other stuff. I talked about the extensions it has in order to make it look more human driven, as well as showed an example of how to tie it to other services.
1303830	1324630	And I haven't even touched at all on the other parts of the suite of tools, Shift Refactor and Shift Interpreter, nor have I talked really much about the whole point I made at the start, which is about manipulating website content, which leads me into Hackium Interceptors.
1324630	1336670	So Interceptors, like we've already gone over, are just basic node modules that intercept a particular URL or request pattern and just do something with it.
1336670	1355870	You can use the Hackium init command to initialize some basic interceptors. I'll call ours interceptor.js. We can use a basic interceptor template, which just doesn't really do all that much, just gives you the boilerplate.
1355870	1375270	A pretty printer, which uses Prettier to format JavaScript. So we're going to start a basic transformer using Shift Refactor. So Shift Refactor is a library I created that makes it easy to query and transform nodes of a JavaScript AST.
1375270	1398410	An AST, an abstract syntax tree, is just a data structure that represents something that was parsed. So the AST I'm talking about is just a big old JavaScript object that represents JavaScript source code. You can use a tool like AST Explorer to just paste JavaScript in and see what AST it generates.
1398410	1412230	So you can pop through each of the nodes and see what types they are, see how they're structured. And if you change any of those and regenerate source from that AST, then you change the JavaScript source.
1412230	1428290	So Shift Refactor takes JavaScript source, parses it into an AST, and then analyzes the scope tree, creates parent mapping, basically does a lot of legwork that makes it easy to do queries and translation on it.
1428290	1446090	It also leverages Shift Query, which allows you to query a JavaScript AST with CSS-like selectors. And I modeled Shift Refactor based off of the jQuery API. So it actually feels very, very similar to navigate and traverse and replace large trees.
1446930	1468110	So we have a script object based around our parsed response body. This expression replaces all console log expressions with alert calls. So we make a query for call expressions that have an object name of console and a property of log.
1468110	1478330	And we replace those with call expressions for alert. And we translate the arguments from the console to the arguments for the alert.
1478330	1493450	As I'm breezing through this, I know that I am glossing over some fairly complex topics, if you haven't played with JavaScript ASTs before. But I can't stress this enough.
1493450	1514910	Despite all the crazy terms and syntax like call expression and callee and identifier expressions and some more that you'll see, those are just nodes of a JavaScript tree. And all you're dealing with is a gigantic JavaScript tree in a similar way that you would navigate or traverse the DOM.
1514910	1524230	So it might look foreign at the start, but don't let that dissuade you from jumping into this because it's not difficult to get a hold on it once you get the practice in.
1524230	1535030	So here we've got a basic web page that exists only to simulate a real world scenario, because I'm going to be jumping into programmatically de-obfuscating JavaScript.
1535030	1555030	And there are plenty of real world examples out there. And you probably have seen a few of those if you've been looking through a web page source. But we run into some sketchy legal ground if I'm de-obfuscating that live in front of people.
1555030	1571970	So we've got a nice little sample website here that I've crafted to look like a payment form that has a, conveniently, an obfuscated bit of JavaScript just floating around on it.
1571970	1588070	This is a sample of obfuscated JavaScript that was obfuscated via obfuscator.io, which is a pretty common JavaScript obfuscation website because it's the first URL that pops up when you search for JavaScript obfuscator.
1588070	1611970	It actually does a pretty good job at obfuscating JavaScript. It can inject dead code. It can shuffle things. But it is extremely difficult to protect JavaScript. And obfuscation really doesn't actually put all that much of a barrier in front of an adversary trying to understand the JavaScript.
1612870	1626610	So we're going to go through and show how this can be completely reversed and sent to the browser before the browser even gets it. So it looks as though you are browsing the web with de-obfuscated JavaScript.
1626610	1647410	So this is using Firefox's DevTools. Even if we pretty print this, it's not all that much more readable. You see here that we start off with a list of encoded strings, clearly encoded strings. We are followed by a variable declaration that, I don't know, does stuff.
1647410	1663590	It has an alphabet here. And given that these are encoded, this is probably the decoder. I would go down here and we see references to that function all over the place.
1663590	1683850	So 0x227, 0x227a, 227a, 227a, 227a, 227a. This is a common method of making it more difficult for somebody to immediately understand what is going on with JavaScript.
1683850	1699850	So I've created a complete interceptor here so that I don't have to code in front of all of you because that's not very exciting, is it? So we've set our URL pattern to the vendor file that I had on my local server.
1699850	1722890	And we have fleshed out the interceptor so that we are running it through refactor and also loading up our interpreter via shift interpreter and massaging some JavaScript. So refactor, we already went over a little bit. We are sending it the response body and we're also adding a common methods plugin.
1722890	1747530	Next, we are creating our interpreter instance and we're loading the scripts AST and we are passing it a context that we are requiring in from here. So the context is like the set of global variables that are accessible by JavaScript. And by default, this interpreter doesn't have anything in its global context.
1747530	1769530	So if we want to expose things that the interpreter needs, then we're going to have to explicitly set them. And we can do it ourselves. It's just a plain old JavaScript object. I've put together a fairly basic and simple DOM lookalike context that uses JS DOM in order to simulate a browser DOM.
1769530	1792770	So if you're interpreting browser side JavaScript, it'll have access to things like image elements, A to B, B to A, URL, URI decode something, whatever, all those things. One of the interesting things about this interpreter is that it was designed so that it can take statements or expressions piecemeal.
1792770	1812990	So you don't have to execute a script statement by statement, expression by expression in the flow that a script would expect to be executed in. You can take any statement or expression out of the AST and pass it to the interpreter and interpret it as if that was the next expression or statement.
1812990	1841430	This is very, very handy when you're dealing with JavaScript like the way I'm dealing with it, because sometimes we don't want to execute all the JavaScript. And we want to just execute only the pieces that we want to reuse so that we don't have to write our own decoder functions or copy and paste anything. We can just grab it, interpret bits and pieces of it, and then use that to deobfuscate the rest of the script.
1841430	1863660	So it's like using JavaScript against itself. So here we're going to run the first statement in the script, which is this. So this basically primes this variable with these values so that anything else that we execute can access that variable.
1864460	1881240	Next, we're going to be getting the decoder, which is the second statement there. Rather than run it directly, we're going to assign it to a variable so we can play with it later. And we're going to run that decoder statement, which is a variable declaration statement that assigns a function expression to a variable.
1882060	1902140	Next up, we're going to query the innards of that decoder statement in order to get the first binding identifier. Now, a binding identifier is an identifier, like a variable name or something like that, that is basically being assigned to or having a value bound to it.
1902140	1923280	And what that means here is basically we want to get that because we want to know how this function is referenced. So we're looking for this binding identifier. See, it's not that complicated once you start poking through and playing around with things. It sounds weird and scary to some people, but it's not that bad.
1924980	1942000	Next up, we want to get all the references to that name. So that binding identifier is called throughout the script. We want to get all the references, the places where it's called, so that we can do stuff with it. And we're going to map those references and grab the node of that reference.
1942000	1964060	So a reference is an object that has a node property in it, which is an AST node, an accessibility property, which tells you whether or not the reference is being read to, written to, or is read right. So then with those references, they're all going to be like an identifier expressions. So like, let's see down here.
1964060	1980920	So an identifier expression is just this bit of code right here. So we want to get this bit of code, which is the reference where it's being used as an identifier expression as the child of a call expression.
1980920	2000000	So here we're getting all of the parents of our references, and we're filtering out all of those, looking for call expressions. That just makes sure that we don't catch any references that aren't call expressions. I think almost all of them, if not all of them, are in the script, so it's not a big deal, but it's good to be safe.
2000000	2026260	And we're going to replace all of those with the stringified result of the interpreter value executing those functions. So we need to JSON.stringify. So it's a string that contains a string, which is the return value of these functions. You still with me? Basically, what we're getting are the decoded values of these strings.
2027020	2048540	So we've done a lot without actually seeing the effect yet. Let's comment out these statements so we can see our transformations take effect before we do too much magic. And then after that, we are printing out the refactored script to the response.body and returning the response. And bam, we are just about done.
2048540	2066660	All right, we go automatically to our payment page. Let's check our resources. Here's our script. Still looks mostly the same, mostly because we didn't change those top two statements. But everything afterward, you'll notice that it no longer has those function calls anymore.
2066660	2089460	Now you see those computed member access blocks right there? JavaScript still works, but they're not as easily parsable by at least my brain. And now that we've translated all the function calls to strings, we no longer need them to be computed anymore. We can translate them back to static properties.
2089460	2114360	So instead of blah, square, string, we can do blah, dot, string. Well, not string, but the actual thing. You know what I'm talking about. And this is where those functions that we deleted come into play. Script.convertComputerToStatic is part of the Common Methods plugin. And the next two statements there, just delete the two statements above our main script because we don't need them anymore.
2114360	2130480	The strings have been decoded, and since all the strings have been decoded, we no longer need the decoder function. So let's get rid of those and clean up our unobfuscated script. Deobfuscated script? Undeobfuscated? I don't know.
2132080	2160240	So now let's load up Hackium again and check our script. And nothing's there. Oh, it is there. We actually had scrolled down. We were too low. But now this is our script. This is basically very close to the original script, minus some still the identifiers that are still wonky, but not much we can do about that. But you can see what it's doing. There's no sort of misdirection anymore. And it's real code.
2161200	2178720	That's it. There's just a few lines of JavaScript that can just completely deobfuscate obfuscated JavaScript. Now, I'm talking a lot about deobfuscation, but there is a lot you can do with all the JavaScript across the web.
2178720	2198720	Even a site like Twitter.com has a huge array of user-friendly, intuitive methods that could just provide you with an API to all of Twitter, but it's hidden away in the JavaScript so you can't touch it via the console or anything else.
2198720	2227680	Now, all you have to do is find out where those beautiful little functions are and just expose them to the global namespace so that you can access them via the console or via hackymscripts or whatever. And if you're not a JavaScript expert, by exposing to the global namespace, all I'm saying is take a chunk of JavaScript and prepend to it like a window.myExposedVariable
2227680	2246060	equals the stuff you want to expose. And that's it. You have an exposed API that you can access easily with hackymscripts, which then allows you to basically tweet via Node.js without using a developer API key or anything like that.
2246060	2270300	Well, that's about all I can cover in the session. And we actually smashed a whole lot of content in a very, very short period of time. But because I was so excited and there's still so much more to talk about. This is just the tip of the iceberg. And I just barely dove into what shift refactor and shift interpreter can do. And I didn't even talk about any plugins.
2270300	2294660	And I didn't talk about the Chrome extension API, talking with the Chrome DevTools protocol, and all sorts of stuff that I could just talk about for days or hours or so much time. I'm going to be putting more of this content on YouTube because that's, I guess, how people consume content nowadays. And I'll probably write some stuff up.
2294660	2321280	But if you like anything I've talked about, you can follow me on Twitter. It's at JSOverson. There's probably a link somewhere nearby. Actually, I think I should be talking to somebody in Discord. Talk to me. But yeah, I like this stuff. I like making the web do things that I want it to do. And this is why I built this stuff. And I hope you enjoy it.
2321280	2333220	And thank you. Thank you, AppSec Village. Thank you, DEF CON. Thank you, all of you, for watching this. This has been awesome. Thank you very much. Bye.
