2

I am trying to do Chrome extension, that will pretend, that some plugins are installed. I was trying to edit navigator.plugins, but these properties are read-only. I can add new item navigator.plugins[x], but I do not know, how to create new (Plugin, PluginArray or MimeType) objects in navigator.plugins.

Is it even possible ?

MartySK
  • 117
  • 2
  • 10
  • What about doing it in the similar fashion as [Changing navigator.userAgent using Chrome Extension](http://stackoverflow.com/q/23202136) ? – wOxxOm Oct 30 '15 at 01:07
  • I do not have a problem to change useragent, because it is simple value, but I am not sure, how to create objects like - Plugin, PluginArray or MimeType in navigator.plugins – MartySK Oct 30 '15 at 09:49
  • Ah, just reuse the existing object's prototype like `var plugin = Object.create(Object.getPrototypeOf(navigator.plugins[0]))` – wOxxOm Oct 30 '15 at 09:54
  • @wOxxOm If I write this - [link](http://jsfiddle.net/4hc7mons/) to the console, it will create type Object, it does not help me, because I need type Plugin [link](http://i.imgsafe.org/ddbb0cf.jpg) – MartySK Oct 30 '15 at 12:11

2 Answers2

9

Here's an approach that works quite well for spoofing the PluginArray (notice the Object.setPrototypeOf):

(function generatePluginArray() {
  const pluginData = [
    { name: "Chrome PDF Plugin", filename: "internal-pdf-viewer", description: "Portable Document Format" },
    { name: "Chrome PDF Viewer", filename: "mhjfbmdgcfjbbpaeojofohoefgiehjai", description: "" },
    { name: "Native Client", filename: "internal-nacl-plugin", description: "" },
  ]
  const pluginArray = []
  pluginData.forEach(p => {
    function FakePlugin () { return p }
    const plugin = new FakePlugin()
    Object.setPrototypeOf(plugin, Plugin.prototype);
    pluginArray.push(plugin)
  })
  Object.setPrototypeOf(pluginArray, PluginArray.prototype);
  return pluginArray
})()

Console output:

enter image description here

I haven't added the MimeType property yet, but that should be accomplishable in a similar manner.

Feel free to submit a PR in case you flesh this out (I've developed a plugin for puppeteer that's implementing various detection evasion techniques): https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth

Edit: I've had some spare time and added code to fully emulate navigator.plugins and navigator.mimeTypes here. It even mocks functional methods, instance types and .toString properties, to make them look native and resemble a normal Google Chrome.

endzeit
  • 685
  • 1
  • 6
  • 15
3

Tried cracking it but failed. Apparently Plugin type can't be instantiated manually. It's read-only by specification and Chrome implements it accordingly (source code). As you can see the constructor is not exposed to DOM, so we can't use new Plugin or other methods to instantiate it.

On the other hand you can try injecting the code into webpage via <script> element, for example, that will replace the entire built-in Plugin class with your own implementation and use that fake class to populate navigator.plugins. Ditto for PluginArray.

wOxxOm
  • 65,848
  • 11
  • 132
  • 136