Lets reverse this sheet! coinhive that is

javascript
cryptology
encryption
coinhive
reverseengineering

#1

So we all want it, a server type coinhive miner that doesnt need a browser and to do this we need to figure out how to create our own copy of its networking and hashing protocols, So i have taken the liberty to format the miner script as best i can as well as start finding where the hell the socket is because there isnt a socket varibal in the script but there is one visable in the chromium console while the script is loaded.

LinkToDownloadTheFile ‘Warning the file is a minner and so may anit malware programms will most likly mark it as a threat’

MinimalUserOperatedMinner this is a small html file that i made for minning without loading the 0x00sec.org site to make it an automaticly starting script just add

	var Running = false;//init miner and glbals
	Start()//calls start function as soon as script loads
	
	function Start()

and remove

    }//end of OnUpdate
	setInterval(OnUpdate, 1000);//remove this
</script>

edit this

function Start()
{
	//the site key is pre-set for 0x00sec.org
	miner = new miner = new CoinHive.User(document.getElementById("sitekey").value,
									  "<YourUserName>");
	miner._targetNumThreads = document.getElementById("threads").value;
	miner._throttle = document.getElementById("throttle").value;
	miner.start();
	Running=true;
	document.getElementById("sk").innerHTML="SiteKey:"+miner._siteKey;
	document.getElementById("px").innerHTML="Proxy:"+miner._socket.url;
	document.getElementById("us").innerHTML="Username:"+miner._user;
}

to

function Start()
{
	miner = new miner = new CoinHive.User(document.getElementById("sitekey").value,
									  "<YourUserName>");
	//you can use this
	miner._targetNumThreads = <MaxNumOfThreads>;//its a number
	//or
	miner.setAutoThreadsEnabled()//auto handle threads i think
	miner._throttle = <YourThrottle>;//its a number/float
	miner.start();
	Running=true;//dont need but leave it just cuz
}

This is to reduse the load on the server/computer, after doing this just run the html doc in ‘–headless’ and your done it should run in the background.

So im going to go over the CoinHiveMinner script and try to say what i made of it but keep in mind this is the first time i have read/used javascript so i could be missing some major thing’s, So just edit the doc or leave it in the comments so that i dont keep saying lies :smiley:.

First we have the first ‘(function(window){…’ this is the Miner class thingy and in the miner i can see all the functions but not all the members for example the _socket member is missing and sadly this is the most importatnt member right now as we will need to first find a way of connecting/authenticating to the servers to extract more info about how the hashes are sent but as far as i have found out about the connection it uses TLS1.2 to encrypt the socket traffic so we cant use wireshark to easily see what its sending but i did see that it recives an ACK for every packet sent so it might be reciving a job throw the ACK or it is simpily there to say yes i have got the hashes thank you.

But lets get to the code.

var Miner=function(siteKey,params){
	params=params||{};//this im not too sure about but it does have stuff to do with 
					  //sending data
	this._siteKey=siteKey;//0x00sec site key
	this._user=null;//is set to the username
	this._threads=[];//all threads are JobThreads 'this will come later'
	this._hashes=0;//total hashes made this session
	this._currentJob=null;//no clue what this deffines but i think its the block
	this._autoReconnect=true;
	this._reconnectRetry=3;
	this._tokenFromServer=null;//this stays null
	this._goal=0;
	this._totalHashesFromDeadThreads=0;
	this._throttle=Math.max(0,Math.min(.99,params.throttle||0));
	this._autoThreads={enabled:!!params.autoThreads,interval:null,adjustAt:null,adjustEvery:1e4,stats:{}};
	this._tab={ident:Math.random()*16777215|0,mode:CoinHive.IF_EXCLUSIVE_TAB,grace:0,interval:null};
	this._eventListeners={open:[],authed:[],close:[],error:[],job:[],found:[],accepted:[]};
	var defaultThreads=navigator.hardwareConcurrency||4;
	this._targetNumThreads=params.threads||defaultThreads;
	this._useWASM=this.hasWASMSupport()&&!params.forceASMJS;//no idea but i think it is to do with the socket type
	this._asmjsStatus="unloaded";
	this._onTargetMetBound=this._onTargetMet.bind(this);
	this._onVerifiedBound=this._onVerified.bind(this)
};

This is the ‘global members’ as id like to call it but not all the things are in here like i said

Miner.prototype._connect=function(){
	if(this._socket){
		return
	}
	var shards=CoinHive.CONFIG.WEBSOCKET_SHARDS;
	var shardIdx=this._hashString(this._siteKey)%shards.length;
	if(this._siteKey.match(/^nyJe9/)){
		shardIdx=Math.random()*shards.length|0
	}
	var proxies=shards[shardIdx];
	var proxyUrl=proxies[Math.random()*proxies.length|0];
	this._socket=new WebSocket(proxyUrl);
	this._socket.onmessage=this._onMessage.bind(this);
	this._socket.onerror=this._onError.bind(this);
	this._socket.onclose=this._onClose.bind(this);
	this._socket.onopen=this._onOpen.bind(this)
};

Oh this is an interessting one its the connection function if the site key has/is ‘’/^nyJe9/’’ then it will select a different then normal shard ‘proxy set, this will be seen later in the config’ and then creates a WebSocket to the proxy and sets the _socket member to that WebSocket but the _Socket member was never created in the first place so where is it beeing stored?
this is an honest question of mine.

Miner.prototype._send=function(type,params){
	if(!this._socket){
		return
	}
	var msg={type:type,params:params||{}};
	this._socket.send(JSON.stringify(msg))
};

So this is the send function as you can see it sends a json file most likly with all the hashes made in the past x time or as soon as the hash is created, I dont know like i said this is only what i found by looking at this file with no idea on what im dong and i havent found where the hashes are made yet.

So at the second ‘(function(window){…’ We have the JobThread stuff this is most likly where the threads are for making the hashes but not the code for making the hashes.

var JobThread=function(){
	this.worker=new Worker(CoinHive.CRYPTONIGHT_WORKER_BLOB);//the blob is a very long line of code inside a
															 //string like its just one long as line
															//i have yet to start looking at it properly
	this.worker.onmessage=this.onReady.bind(this);
	this.currentJob=null;
	this.jobCallback=function(){};
	this.verifyCallback=function(){};
	this._isReady=false;
	this.hashesPerSecond=0;
	this.hashesTotal=0;
	this.running=false;
	this.lastMessageTimestamp=Date.now()
};

So from what i can see here i was right this hosts the hasher but isnt the hashing algorithm im thinking the hasher is inside the Worker from The BLOB ‘look at file at the bottom you cant miss it’, And it stores the amount of hashes that it has made but it must be fead a job mayby we could use said job later to grab more info on how exactly the hashes are used/created.

JobThread.prototype.setJob=function(job,callback){
	this.currentJob=job;
	this.jobCallback=callback;
	if(this._isReady&&!this.running){
		this.running=true;
		this.worker.postMessage(this.currentJob)
	}
};

Looks like the Miner sets the job.

Miner.prototype._setJob=function(job){
	this._currentJob=job;
	this._currentJob.throttle=this._throttle;
	for(var i=0;i<this._threads.length;i++){
		this._threads[i].setJob(job,this._onTargetMetBound)
	}
};

Yep but where does this get called from?

Miner.prototype._onMessage=function(ev){
	var msg=JSON.parse(ev.data);
	if(msg.type==="job"){
		this._setJob(msg.params);
		this._emit("job",msg.params);
		if(this._autoThreads.enabled&&!this._autoThreads.interval){
			this._autoThreads.adjustAt=Date.now()+this._autoThreads.adjustEvery;
			this._autoThreads.interval=setInterval(this._adjustThreads.bind(this),1e3)
		}
	}
	else if(msg.type==="verify"){
		this.verifyThread.verify(msg.params,this._onVerifiedBound)
	}
	else if(msg.type==="hash_accepted"){
		this._hashes=msg.params.hashes;
		this._emit("accepted",msg.params);
		if(this._goal&&this._hashes>=this._goal){
			this.stop()
		}
	}
	else if(msg.type==="authed"){
		this._tokenFromServer=msg.params.token||null;
		this._hashes=msg.params.hashes||0;
		this._emit("authed",msg.params);
		this._reconnectRetry=3
	}
	else if(msg.type==="error"){
		if(console&&console.error){
			console.error("Coinhive Error:",msg.params.error)
		}
		this._emit("error",msg.params);
		if(msg.params.error==="invalid_site_key"){
			this._reconnectRetry=6e3//never reconnect
		}
	}
	else if(msg.type==="banned"||msg.params.banned){
		this._emit("error",{banned:true});
		this._reconnectRetry=600//wonder how you get bannd and why it trys to reconnect later??
	}
};

Looks like it is given by the server _OnMessage is set inside the connect function.

So i have ran out of things for show and tell so im going to show you my last thing

self.CoinHive.CONFIG={//proxeys and other urls
	LIB_URL:"https://coinhive.com/lib/",
	WEBSOCKET_SHARDS:
	[
		[
			"wss://ws001.coinhive.com/proxy",
			"wss://ws002.coinhive.com/proxy",
			"wss://ws003.coinhive.com/proxy",
			"wss://ws004.coinhive.com/proxy",
			"wss://ws005.coinhive.com/proxy",
			"wss://ws006.coinhive.com/proxy",
			"wss://ws007.coinhive.com/proxy",
			"wss://ws029.coinhive.com/proxy"
		],
		[
			"wss://ws008.coinhive.com/proxy",
			"wss://ws009.coinhive.com/proxy",
			"wss://ws010.coinhive.com/proxy",
			"wss://ws011.coinhive.com/proxy",
			"wss://ws012.coinhive.com/proxy",
			"wss://ws013.coinhive.com/proxy",
			"wss://ws014.coinhive.com/proxy",
			"wss://ws030.coinhive.com/proxy"
		],
		[
			"wss://ws015.coinhive.com/proxy",
			"wss://ws016.coinhive.com/proxy",
			"wss://ws017.coinhive.com/proxy",
			"wss://ws018.coinhive.com/proxy",
			"wss://ws019.coinhive.com/proxy",
			"wss://ws020.coinhive.com/proxy",
			"wss://ws021.coinhive.com/proxy",
			"wss://ws031.coinhive.com/proxy"
		],
		[
			"wss://ws022.coinhive.com/proxy",
			"wss://ws023.coinhive.com/proxy",
			"wss://ws024.coinhive.com/proxy",
			"wss://ws025.coinhive.com/proxy",
			"wss://ws026.coinhive.com/proxy",
			"wss://ws027.coinhive.com/proxy",
			"wss://ws028.coinhive.com/proxy",
			"wss://ws032.coinhive.com/proxy"
		]
	],
	CAPTCHA_URL:"https://coinhive.com/captcha/",
	MINER_URL:"https://coinhive.com/media/miner.html"
};

This config witch contains all the proxys ‘the WEBSOCKET_SHARDS are the proxy’s’ the capcha, miner and root for all the lib’s.

So like i said if there is anything you find or i made a mistake do tell in the comments and edit the post.

-dedady157

Some things I discovered sometime after.
You only need to use 4 threads because each thread can use up to a maximum of 25% cpu (windows).
CoinHive.CRYPTONIGHT_WORKER_BLOB is
cryptonight-asmjs.min.js i dont know why but the entire file is there just without any comments and so if you want to try and decrypt CRYPTONIGHT_WORKER_BLOB then just look at 'link goes here’
i will upload this soon im just gonna pre format it fo you -well shit shouldnt have said that i cant do it anymore due to me now have 8 other projects to deal with after i get that done i ll continue this


#2

its messy but a start


(Burning away in an Explosion) #3

I’ve made something like this:

But it’s pretty normie, 'cause it works with the “Coinhive Documentation”. Nice work :wink:


(Command-Line Ninja) #4

Hey man, can you please fix the formatting? Add subtitles, headings, and use capital letters at the beginning of a paragraph? Simple english and formatting stuff. We want the content on this site to be formatted nicely and be readable.

Looking forward to see this improvement.


#5

I like the idea of this, it would be very good to have an open source alternative of Coinhive miner but…

This would be illegal and it probably infringing Coinhive’s copyright and that could be bad for this site.

Correct me if I’m wrong!


(Command-Line Ninja) #6

Reverse Engineering is not illegal. It’s interesting topic. He just needs to fix his formatting.


#7

That’s interesting, it uses the new WebSocket API. I speculated that it had some HTTP->TCP bridge but I was wrong.

So the miner doesn’t work on older browsers which do not support WebSocket API.


#8

The file where the magic happens is

cryptonight-asmjs.min.js

It has over 16k lines


#9

yes thats where the hashing is done but i havent gotten around to looking at that instead im looking at the connection first so that then i can create a connection then i will be looking at what the hashes are and how to make them then after that we can make a designe for how to system works to then recreate different versions of it IE porting it to a better lang like c/c++


#10

The link for FORMATED_coinhive.min.js is down. Does someone still have a copy?


(Command-Line Ninja) #11

This topic was automatically closed after 4 days. New replies are no longer allowed.