Overwrite Standard Math.random() Function

2,277 views
Skip to first unread message

ndauten

unread,
Nov 8, 2010, 5:15:42 PM11/8/10
to Chromium-extensions
Hi All-

I need to use an extension or user script to overwrite any call to
Math.random() on web pages out of my control. The functionality I hope
to induce is that on any webpage I navigate to that each call to
Math.random() will call my function my.math.random(). I have attempted
to do this by injecting a .js file (using user scripts) into the
header of the page, but it appears as though it may not be overwriting
the standard library function. If I put my script directly into a page
it works correctly. I have tried using anonymous functions as well,
but to no avail.

Thanks for the help!

::n::

PhistucK

unread,
Nov 9, 2010, 1:48:20 AM11/9/10
to ndauten, Chromium-extensions
Either -
Math = {random = function(){return 0}};
Math.random = function(){return 0};

Seems to work.

If you run the content\user script at document_start and inject the script to the documentElement, does it still not work?

PhistucK




--
You received this message because you are subscribed to the Google Groups "Chromium-extensions" group.
To post to this group, send email to chromium-...@chromium.org.
To unsubscribe from this group, send email to chromium-extens...@chromium.org.
For more options, visit this group at http://groups.google.com/a/chromium.org/group/chromium-extensions/?hl=en.


ndauten

unread,
Nov 9, 2010, 9:32:37 AM11/9/10
to Chromium-extensions
Hey PhistucK-

Thanks for the advice. I attempted what you said, and it partially
works, but I seem to be missing something. You will have to excuse me
as I'm a bit of a javascript/extensions/web development noob. I set up
the script to load at document_start, but I couldn't quite figure out
how to inject the script to the documentElement.

I have tried several solutions that provide some level of success.
What I mean by this is that I can overwrite the Math.random() and then
execute this from the javascript console, and my function returns
correctly. But when viewing an html page that already has source in it
for Math.random() it returns the original JS library version. I am
using the document_start as you suggested as well. The following are
some things that I have tried:

****** BEGIN CODE *******
// ==UserScript==
// @name Hello World
// @namespace http://endomorph.cs.uiuc.edu
// @description example script to alert "Hello world!" on every page
// @include *
// @require http://endomorph.cs.uiuc.edu/injection.js
// @run_at document_start
// ==/UserScript==

/*
* This function inserts the script after the head tag
*/
// This function works as well, but it doesn't overwrite the
function early
// enough to make calls in the body to ref our function.
var sc = document.createElement('script');
sc.setAttribute('type', 'text/javascript');
sc.setAttribute('charset', 'UTF-8');
sc.src = 'http://endomorph.cs.uiuc.edu/injection.js';
document.getElementsByTagName('head')[0].appendChild(sc);
//(document.body || document.head ||
document.documentElement).appendChild(sc);
//document.documentElement.appendChild(sc);

****** END CODE *******

I tried each of the three append methods (two are commented out)

Another attempt that overwrites, but not soon enough:

****** BEGIN CODE *******

/*
* The following is testing some function load methods
* This is in fact working correctly. The problem is that it isn't
overwriting
* the function prior to its initial execution.
*/

function main () {
// ...
Math.random = function() {return .9};
//alert('test');
// ...
}
var script = document.createElement('script');
script.appendChild(document.createTextNode('('+ main +')();'));
(document.body || document.head ||
document.documentElement).appendChild(script);

****** END CODE *******

Like I said each of these methods allows me to call Math.random() from
the javascript console,which returns my function. But when loading the
following webpage:

<html>
<head>
</head>
<body>
this is a test
<script>var a=Math.random();document.write("<br>"+a);</script>

<form>
<input type='text' onchange="alert('asdfasdf');"></input>
</form>
</body>
</html>

The call to random returns the original library function.

Thanks all-

::n::


On Nov 9, 12:48 am, PhistucK <phist...@gmail.com> wrote:
> Either -
> Math = {random = function(){return 0}};
> Math.random = function(){return 0};
>
> Seems to work.
>
> If you run the content\user script at document_start and inject the script
> to the documentElement, does it still not work?
>
> ☆*PhistucK*
>
>
>
>
>
>
>
> On Tue, Nov 9, 2010 at 00:15, ndauten <kainos...@gmail.com> wrote:
> > Hi All-
>
> > I need to use an extension or user script to overwrite any call to
> > Math.random() on web pages out of my control. The functionality I hope
> > to induce is that on any webpage I navigate to that each call to
> > Math.random() will call my function my.math.random(). I have attempted
> > to do this by injecting a .js file (using user scripts) into the
> > header of the page, but it appears as though it may not be overwriting
> > the standard library function. If I put my script directly into a page
> > it works correctly. I have tried using anonymous functions as well,
> > but to no avail.
>
> > Thanks for the help!
>
> > ::n::
>
> > --
> > You received this message because you are subscribed to the Google Groups
> > "Chromium-extensions" group.
> > To post to this group, send email to chromium-extensi...@chromium.org.
> > To unsubscribe from this group, send email to
> > chromium-extensions+unsubscr...@chromium.org<chromium-extensions%2Bunsubscr...@chromium.org>
> > .

PhistucK

unread,
Nov 9, 2010, 10:27:41 AM11/9/10
to ndauten, Chromium-extensions
A few options.
One -
var script = document.createElemet("script");
script.src = "...";
document.documentElement.appendChild(script);
Two -
location.href = "javascript:inline_code";
(Where "inline_code" is replaced with the actual code);

PhistucK



To post to this group, send email to chromium-...@chromium.org.
To unsubscribe from this group, send email to chromium-extens...@chromium.org.

ndauten

unread,
Nov 9, 2010, 7:04:20 PM11/9/10
to Chromium-extensions
Hi-

I tried what you suggested and a bit more of the same. I have looked
further into the situation and it appears as though I am successfully
overwriting the function, so that if I execute Math.random() with a
onclick event it returns my function, but the problem is that it
doesn't overwrite those calls to Math.random() that are just in the
body of the message. It's almost as if those calls are being made
before my overwrite occurs.

I think it might be that you cannot do this via user scripts.

Thanks for the efforts!

::n::

On Nov 9, 9:27 am, PhistucK <phist...@gmail.com> wrote:
> A few options.
> One -
> var script = document.createElemet("script");
> script.src = "...";
> document.documentElement.appendChild(script);
> Two -
> location.href = "javascript:inline_code";
> (Where "inline_code" is replaced with the actual code);
>
> > <chromium-extensions%2Bunsubscr...@chromium.org<chromium-extensions%252Bunsubscr...@chromium.org>

Johan Sundström

unread,
Jan 2, 2011, 5:03:22 PM1/2/11
to ndauten, Chromium-extensions
On Tue, Nov 9, 2010 at 16:04, ndauten <kain...@gmail.com> wrote:
Hi-

I tried what you suggested and a bit more of the same. I have looked
further into the situation and it appears as though I am successfully
overwriting the function, so that if I execute Math.random() with a
onclick event it returns my function, but the problem is that it
doesn't overwrite those calls to Math.random() that are just in the
body of the message. It's almost as if those calls are being made
before my overwrite occurs.

I think it might be that you cannot do this via user scripts.

If you wrap your user script in a thin extension, i e create a manifest.json looking like this:

{ "name": "Make Math.random always return 1"
, "version": "0"
, "content_scripts":
    [{ "matches": ["*://*/*"]
     , "run_at": "document_start"
     , "js": ["math.random.user.js"]
     }]
}

and make math.random.user.js look like this:

var script = document.createElement('script');
script.textContent = 'Math.random = function() { return 1; };';
document.documentElement.appendChild(script);

…then your example page with inline <script> tag code calling Math.random() gets 1.

If you instead make it look like this:

location.href = 'javascript:void(Math.random = function() { return 1; });';

…it does not, for some reason.

I am a bit puzzled by why the stand-alone content script does not work, though; what is the UserScript counterpart for setting the run_at property? It seems @run-at (not @run_at) is reacted to in some fashion, as a user script math.random.user.js looking like this:

// ==UserScript==
// @name Make Math.random always return 1
// @run-at document_start
// ==/UserScript==

var script = document.createElement('script');
script.textContent = 'Math.random = function() { return 1; };';
document.documentElement.appendChild(script);

…yields an "Invalid script header." alert when I try to install it. What is the proper syntax for @run-at?

-- 
 / Johan Sundström, http://ecmanaut.blogspot.com/

Giovani Ceotto

unread,
Jan 2, 2011, 8:18:46 PM1/2/11
to Chromium-extensions
There is a really simple way to do this by injecting a script into the
page with the following code:

math.random = function() {
//anything you want it to do
}

I hope I understood what you meant.

On Jan 2, 8:03 pm, Johan Sundström <oyas...@gmail.com> wrote:
>  / Johan Sundström,http://ecmanaut.blogspot.com/

Johan Sundström

unread,
Jan 3, 2011, 7:54:42 AM1/3/11
to Giovani Ceotto, Chromium-extensions
On Sun, Jan 2, 2011 at 17:18, Giovani Ceotto <ghce...@gmail.com> wrote:
There is a really simple way to do this by injecting a script into the
page with the following code:

math.random = function() {
 //anything you want it to do
}

I hope I understood what you meant.

No, ndauten's problem was not how to reassign a new function to Math.random, but how to do it in the page scope, and before a page looking like this ends up using it:

<html><body><script>document.write(Math.random())</script></body></html>

This, as best I can tell, currently needs you to write a Chrome extension (that wraps a tiny content script), though in theory a stand-alone content script running at document start should do the job, too, if there's a way of declaring "run_at": "document_start" for naked content scripts. I quite sincerely hope there is, as that would make Chrome almost on par with Opera's user javascript, in terms of basic functionality, which would be great. (And if I could make Greasemonkey cater the same for Firefox, that would be  great too, but that's off topic for this list.)

My main interest in this issue is if and how to make this work with just a naked content script, and what that script's ==UserScript== header should look like. In an ideal future I would next be able to nudge the good Opera people to support the same syntax (and have Greasemonkey do, as well, and maybe ), so all who can settle for just writing zero-privileges content scripts can do in a browser agnostic fashion.

-- 
 / Johan Sundström, http://ecmanaut.blogspot.com/

Nathan Dautenhahn

unread,
Jan 15, 2011, 11:39:33 AM1/15/11
to Johan Sundström, Chromium-extensions

2011/1/2 Johan Sundström <oya...@gmail.com>

On Tue, Nov 9, 2010 at 16:04, ndauten <kain...@gmail.com> wrote:
Hi-

I tried what you suggested and a bit more of the same. I have looked
further into the situation and it appears as though I am successfully
overwriting the function, so that if I execute Math.random() with a
onclick event it returns my function, but the problem is that it
doesn't overwrite those calls to Math.random() that are just in the
body of the message. It's almost as if those calls are being made
before my overwrite occurs.

I think it might be that you cannot do this via user scripts.

If you wrap your user script in a thin extension, i e create a manifest.json looking like this:

{ "name": "Make Math.random always return 1"
, "version": "0"
, "content_scripts":
    [{ "matches": ["*://*/*"]
     , "run_at": "document_start"
     , "js": ["math.random.user.js"]
     }]
}

and make math.random.user.js look like this:

var script = document.createElement('script');
script.textContent = 'Math.random = function() { return 1; };';
document.documentElement.appendChild(script);

…then your example page with inline <script> tag code calling Math.random() gets 1.

Hey Johan! Thanks for the advice. I actually finally figured this out. Turns out that I had created a content script and assumed the format for the run_at followed that of the other config option (e.g., "option":["value"]). This solved my problem as you suggested. 

As per the proper syntax for the UserScript version of it, I'm not sure to be honest. I was able to execute the script without errors. I can't remember which one I used (@run-at or @run_at), but the script did not execute at the same time as in the content script. I guess the easy answer is that one should create a content script instead of user script. 

::ndd::
Reply all
Reply to author
Forward
0 new messages