Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Abusing the Chromium Devtools Scope Pane (medium.com/weizmangal)
213 points by kiyanwang on Sept 5, 2021 | hide | past | favorite | 65 comments


Anti-debugging, as a field, is just one of those things that I think is inherently distasteful. As in, the sole point of doing it isn't to make or fix something, like so much else in programming, it's to break something, and deny a feature. That just...feels like making a giant "screw you" to somebody else, which is very unpleasant.

As an aside, I was very glad to see that if you browse to the example sites with firefox you get an angry "This only works in Chromium based browsers" popup.


Important to clarify here that in describing the exploit, the author of this article is not doing anything wrong -- they're raising awareness of an issue with the Chromium dev tools that people absolutely should be made aware of. It's very much in the same vein as some of the "login interceptor" extensions that got published back when the tech community was trying to encourage sites like Facebook to switch to HTTPS. The full text of the article makes the author's intentions pretty clear, and I think it's good that they published this article.

Otherwise, agreed. Users have a fundamental right to inspect code that is running on their devices (https://anewdigitalmanifesto.com/#right-to-modify), and anti-debugging techniques (including invasive systems like DRM) are distasteful because they try to deny users that right.

I'm also pleased to see the Firefox alert, but there's no specific mention I can find about why it doesn't work in Firefox. I'd love to see some more information about that.


I think there is a distinction we can make here. What sets anti-debugging apart is not denying something -- after all, the point of cryptography is to make things impossible for adversaries -- but whom does it serve. In the case of anti-debugging it serves the manufacturer and third parties first, and user only gets secondary or tertiary benefits. Whereas things like full-disk encryption or encrypted messaging serve the user first. (Of course, not all crypto serves the user: imagine using MPC to bypass the Fourth Amendment protections.)


I see your point, but I think this distinction is incidental.

Technologies are fundamentally devoid of ethics, as are laws of nature. A technology only works well for "good guys" if it works equally well for "bad guys".

The intent of development does initially play a role, but anything deep enough will eventually find both bad and good uses, no matter how we see the initial intent.

(But for a specific application, the intent, of course, plays a major role.)


I strongly disagree with this. Taken to its extreme, A machine where you can push a button and kill everybody everywhere is a fundamentally immoral technology.

The laws of nature are not devoid of ethics either. Screw nature. Plague came from nature.


A technology that can affect all people on Earth is rarely strongly limited to killing people. Look at explosives. They can be used to kill and maim people at scale, and also to build roads and tunnels in mountains. Look at viruses, think of all the diseases they cause. Now also look at viral vectors that deliver medicines into patient cells, including some of the modern anti-COVID vaccines. Look at cryptography.

If laws of nature are not devoid of ethics, take any fundamental law, say, Newton's laws, or classical electrodynamics, or general relativity, anything from mathematics, and try to put it anywhere in the alignment matrix but the "true neutral" cell. Explain your answer — I will gladly listen! (Not ironically.)

And pray don't screw nature. There were numerous attempts, all ended badly, just look around. You are a part of nature, by screwing nature, you also screw yourself (which is of course your inalienable right), and, sadly, others around you.


s/make it impossible/make it prohibitively expensive/


Yeah, distasteful is putting it lightly. Its entire purpose is to deny us our computing freedom. To protect their code from us like we're some adversary in their threat model. To prevent us from understanding what our system is executing.


This is at least as ugly as binaries which embed themselves into VMs to prevent and detect reversing. I don’t condone either one but can understand first one up to a point. Rigging a website… That’s really some next level ugliness.


Yeah. Those video game obfuscation schemes work like that. Denuvo and its friends. It's a virtual machine with a instruction set designed for maximum obfuscation. Some of game's code is compiled for it in order to make reverse engineering and cracking ridiculously hard. These technologies are known for killing the game's framerate and responsible for cracked versions being superior to genuine ones.


Well, if we're not aware of it and we don't take steps to stop these techniques, malicious people will use it to their advantage.


> malicious people will use it to their advantage.

There's a good chance they already are. Your average ransomware shop probably won't pull this off, but the three letter agencies around the world with insanely good staff and a lot of budget to search for flaws in some of the most used software? You bet they already have this in their toolbelt.


Erm, the three letter agencies target their exploits usually a bit deeper in the system - and these light anti debugging exploits are indeed for ransomware, trackers, adware and obfuscation, to protect IP and malicious behavior. Afaik in the realm of web, mainly to conceil shaddy behavior. Tracking, data mining, ...


it's exactly the same idea as DRM. I think society should outlaw DRM as a mechanism to enforce intellectual property rights.


I agree, because DRM has potential to outlive copyright law. Sure, many DRMs are broken, but there are many that are not. As the arms race escalates, DRM will become harder and harder to crack (I can think of a few offhand that AFAIK have never been cracked publicly, like the encryption used on cable systems in the US). The people in control of the various DRM systems are not even thinking about future noninfringing use, because they're not even thinking about current fair use in developing these systems. These are largely people who do not think copyright should expire that are driving these anti-public efforts.


Also, think about what a waste of talented peoples' time this represents. Probably many person-hours are spent implementing these increasingly sophisticated DRM systems, and then many more trying to crack them, rendering all of it completely pointless.


You’re right, I never thought about the long term effects of DRM. But we’re really just talking about its effects on our grand children. To be fair we’ll all be dead by the time works made today will go into the public domain.


> it's to break something

One of my university professors told me, during intro. to algorithms class, "some people understand things by building them, some by breaking them, and you are of the latter type". Nothing wrong about that, the way I see it!


That implies you'd dislike this more than most because it prevents "breaking" things efficiently by intentionally crippling tools and throwing out red herrings.


On the topic of distasteful, the author sounds obnoxiously proud of his accomplishments...


Read the whole article, his tone changes.


How is this different from closed source software, which constitutes the overwhelming majority of the industry?


It's possible to reverse engineer closed source software. I have done it.

Anti-debugging is a whole new level of obnoxiousness. Imagine a proprietary executable that scans your memory for debuggers and similar tools and then kills them or kills itself to make it harder for you. They use your own computer to subvert you.


Been around for awhile they are called viruses.


Yeah but that's malware. It's expected in those cases. We should not tolerate these hostile actions from normal software.


Video game DRM also does this, so we see it in commercial software.


Skype does it too (or did for a long time - not sure about the current state).


"Closed source" is a pretty poor analogy, since regular executables can be disassembled or even decompiled. Reversing is a big field. DRM and obfuscation to prevent that reversing is a better analogy.

How is it different from that? It isn't, really.


This technique is already being used in commercially available pop up scripts… everywhere.

It’s been done since at least 2 years ago, and probably longer.

Currently, if you ever pop up dev tools and see the console is constantly being cleared, the reason is to obscure that the anti debugging software is in effect.

Once the script detects dev tools is open, it will definitely not follow the normal path of pop up creation but instead default to a Rube Goldberg machine obfuscating the entire operations.


uBlockOrigin has defusers killing this very easily, no-setInterval-if no-setTimeout-if

example https://github.com/uBlockOrigin/uAssets/issues/8128


> Currently, if you ever pop up dev tools and see the console is constantly being cleared, the reason is to obscure that the anti debugging software is in effect.

The article notes that the technique does not require logging to the console.


One scenario where you have to do something similar to this is as an extension author, because some websites are hostile to the user. A couple examples from my past:

A non-profit built an extension that would scrape data on advertisements from users' facebook feeds (opt-in). Facebook decided they weren't a fan of this so they introduced some special mouse event handlers designed to identify mouse events generated by extensions (and unfortunately, accessibility tools). I worked with the extension author to introduce a very elaborate set of tricks to forge the 'event not generated from user input' flag so that it would keep working.

Another scenario was that I maintained an accessibility extension (keyboard shortcuts, tooltips, etc) for a browser game. The developers became increasingly hostile to extensions in general because some people used extensions to cheat. Over time I had to do things like forge properties, mask events, hide DOM elements, forge property/method names and toString values, forge stack traces, and automatically shut off functionality in response to anti-cheat code changes (using a custom structural hashing algorithm for JS I created). They still eventually found ways to detect this unfortunately and used that to aggressively harass and then ban users of my extension, but I kept the arms race up for a year or two. Chrome is very bad at protecting extension users from hostile pages - there are various ways to detect whether a user has an extension installed/enabled and it's very difficult to stop that. Most extensions also need to inject scripts into the page to work due to the poor design of WebExtensions and that is also sadly detectable :(

Oddly one far more robust approach to work around these issues is by writing a custom Chrome debugger using their debugging protocol. Custom debuggers can forge real input events, block script execution, filter stack traces, silence exceptions, etc. I eventually prototyped a replacement using this approach and got it working but it really wasn't worth the hassle.


> (and unfortunately, accessibility tools)

Why did this problem need a technical solution then? Wouldn't an ADA lawsuit have both solved it plus given Facebook a very strong financial incentive to never do such a thing again?


Let me know if you manage to actually find a lawyer willing to file an ADA lawsuit over a website. I tried, most bar associations don't even have anyone to refer you to.


Am i the only one to think that the 'id' trick is a plain Chrome devtool bug ?

Either the ids should be queried without side effect or not queried at all without a user action.

The second idea, using 'toString()' is well know and also works in other OO languages, Java, C#, etc.


You could fix it by doing Object.getOwnPropertyDescriptor(div, 'id') to check if there's a getter instead of plain value, not sure about performance impact though.


But a work around might be being able to craft a Proxy target that looks like a HTMLDivElement but has a handler that captures the get('id') operation, and does the same thing as the example. In that case it may not be so easily inspectable...


No need to do any of this when you control V8. Chrome DevTools can decide to run code iff there are no side effects (by executing it and bailing on any writes/native functions like alert marked as having side effects). Presumably it costs some overhead to do that and that is why logging elements to the console does not enable the "no side effects" flag.


But I think the point is more about how does a regular web app in web land detect devtools? Not, how does an app with DevTools privileges (via a Chrome extension, or connecting to the remote debugging port) that controls V8 via debugging APIs detect/prevent if DevTools pane has been opened (there are even APIs/events for this in chrome remote debugging protocol), so no need to rely on the side effects bailout you mention if your goal is to detect DevTools panels and you have "control" over V8.

But maybe you're point was more about how would Chrome prevent this DevTools detection? I honestly don't think they would do this, but not because of "overhead"--simply because the console and debugging is useful, and it requires displaying elements, and inspecting those. So there will be no way around having actually printed out elements when DevTools is open. Except if you always printed them out whether it was open or not, but this would be too much overhead, as Chrome only lazily executes console commands (and optimizes things away if DevTools is not open).

This is hilarious I'm saying this to you because you work at Lighthouse---so I'm about to learn something I guess! :p ;) xx haha


Naturally this sort of issue has been reported in the past: https://bugs.chromium.org/p/chromium/issues/detail?id=672625

From the comments on that bug there's other ways to detect devtools (including timing attacks), and it wouldn't be worthwhile to track down every possible case.

As someone who uses devtools debugging a lot I think that answer is reasonable, these kinds of shenanigans mostly only slow down and amuse expert debuggers.


> it wouldn't be worthwhile to track down every possible case.

I disagree with this conclusion. I think websites being able to detect or interfere with devtools should be considered a security bug. Do we give up on stopping XSS and memory corruption because it's too hard to detect every possible case of them too?


This seems like a bug, even a security relevant one?

The article doesn't talk about it, but I probably would have at least tried to report this to Google - maybe the Author did as such and just didn't write about it.


"This trick can of course be very helpful not only to attackers but to other entities as well (such as big companies who want to alter their code when it is being investigated by researchers for example)."

Two people are having a conversation.

Person #1: How do I know the difference between an "attacker" and "other entities". Could a "big company" be an attacker.

Person #2: An attacker is trying to do something bad and does not want you to see what its doing. A big company is doing something good and does not you to see what its doing.

Person #1: Wait, how do I know if what its doing is bad or good if I am prevented from knowing what its doing.



thank you


Rookie question: how do you disable pause on "debugger" keyword in Chrome devtool (without disabling other breakpoints, which Ctrl+F8 does)?


Right click on the line number (of the debugger statement), and select "Never pause here". You'll need to do that for each statement.


The trick is you never know where debugger was really called from, try it https://9anime.to/watch/a-certain-magical-index-dub.l1kn/ep-...

You can bypass this by killing setintervals altogether.


I actually managed to bypass this without destroying `setInterval()`.

After a few times clicking "continue", Chrome showed me where the debugger line is in a VM script. And then I can disable it as OP said.


Wow, never knew this. Thanks!


You cant. Just getting a list of defined setintervals and settimeouts would help a lot, like you can access Event Listeners. Afaik devtools has no facility to do that :(


As with every frontend nuisance, such as blocking the right click, showing alerts etc, this can be sidestepped easily [0]. While this technique may deter some people, just like the above annoyances, at the end of the day the old adage still holds — if it's in the frontend, the end user can do anything and everything they want. That said, this is still cool in the technically interesting sense, haven't seen someone do this before.

[0] https://stackoverflow.com/a/13372025/1470607


This reminds me of anti-memhack techniques in game dev. If you store the players money or health in a variable, there are tools to help you find it in memory. These tools work by scanning the memory for the value you give it, changing the value in game (take damage, earn money, etc) and scanning the first scan's results for the new value.

To defeat this you just need to XOR the value with some bits. It doesn't stop a dedicated person at all, but 99% of cheaters are deterred. So it's good enough.


What is the point? To prevent single player cheats? Seems unnessecary.


Depending on how commercially minded the company is it might range from protecting “DLC” or something else that the user should[0] pay for, anti piracy, or to extend the grace period in which certain content remains undocumented online.

[0] not my view


To prevent wide usage of mass produced cheats, called trainers.

In the flash game ecosystem you relied on distribution to make money off a game. You wanted multiple portals to buy rights to the game. If it can be beaten quickly you make less money. So it's worth closing the door on the lowest rung of mass market cheaters.


I don’t get the thing with the ID attribute. Why doesn’t the browser engine query it as soon as the div is created in the DOM tree? Otherwise getElementById wouldn’t work.


The HTML engine probably has an internal list of ids to quickly look them up. The dev tools, however, access it externally. It's quite likely they simple use `treeNode->getId()` without being aware that this call respects JS overwrites.

It might even be a feature; the C# debugger, for example, will call your custom `toString()` function in order to give a nice representation in the debug window. The problem here is, of course, that the debugger is running against untrusted code.


This sounds problematic from a debugger perspective if the function does any sort of side effect, and I'd consider this a bug as well.

In fact, I'd probably argue that causing user-code to run at debug time is not a good idea even if the function is guaranteed to be side-effect free.


While this can be seen as somewhat useful, nothing stops you from deactivating breakpoints inside of the "Sources" section in devtools.

I also believe that the same anti-debugging technique is used by obfuscator.io, and is just a feature you can enable for when obfuscating your code on there. It's called "Debug Protection". It does about the same thing you shown in your blog post, making good use of the debugger statement.


If it can be done in JavaScript, it will be done in JavaScript. ;)

This is good to improve JavaScript and Web security. After all this input simply adds to the arm’s race.

From a hacker perspective I also enjoyed it.


The “security” angle is pure BS. This will only help scammers


I don’t buy that. That’s only true if the author is the only person to ever discover this. Instead, he had brought to light what others may know and probably do, to judge by his prior article. This means we are now aware and the Chromium devs may implement changes.


You are right. However, for the author the “attacker” is whoever wants to debug, not the other way around.


I wonder what would be required to escalate this to executing in the Devtools thread?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: