Skip to content

Created WASM module.#3

Merged
troyhunt merged 6 commits into
troyhunt:mainfrom
mrcbax:main
Apr 1, 2021
Merged

Created WASM module.#3
troyhunt merged 6 commits into
troyhunt:mainfrom
mrcbax:main

Conversation

@mrcbax

@mrcbax mrcbax commented Mar 31, 2021

Copy link
Copy Markdown
Contributor

Edit: I have solved a lot of my listed problems and learned a lot from this. Read all of my comments for my progress/brain dump on solving this and see the success in the video of my last comment.

I have created the groundwork for a WASM module that also displays the modal. Without knowing more about how coinhive calls this WASM function (i.e. the javascript that loads and runs the WASM miner), there is not much else I can do from here. If you get me a copy or stub of the actual calling javascript I can finish this implementation.

Created in rust using:

An awesome guide on how to utilize Rust with WASM: https://rustwasm.github.io/docs/wasm-bindgen/introduction.html

@mrcbax

mrcbax commented Mar 31, 2021

Copy link
Copy Markdown
Contributor Author

I must admit after reading the CoinHive code:

image

I am not proficient enough at JavaScript to understand just what this is doing. All I need to get this to work is know what the very first function called by the CoinHive script from the WASM module is named.

@mrcbax

mrcbax commented Mar 31, 2021

Copy link
Copy Markdown
Contributor Author

Here is the WASM file I extracted from the CoinHive JS module, pulled into radare2 it looks to have been stripped of all function names:

coinhive.wasm.zip

This WASM file is a "last resort" only unpacked from a massive bin2dec array in the CoinHive JS when asking the server for a new WASM file fails.

it appears to use emscripten which is considered "old-school" in the WASM world. This will require changes to my implementation depending on how the CoinHive script loads the WASM module.

@mrcbax

mrcbax commented Apr 1, 2021

Copy link
Copy Markdown
Contributor Author

I have found a function call: _cryptonight_create I should be able to intercept this call and use it run the custom WASM page modifier:
image
image

@mrcbax

mrcbax commented Apr 1, 2021

Copy link
Copy Markdown
Contributor Author

After testing a compile, the binary has the necessary function and should override the _cryptonight_create() call:
image

You can download the WASM file to test it yourself here:
coinhive_modal.wasm.zip

I currently have no idea how to get the CoinHive script to pull in this WASM file. Testing is going to be interesting to say the least.

To compile this yourself you will need to:

  1. Install Rust, use rustup
  2. Install support for the correct target, in this case just run rustup target add wasm32-unknown-unknown
  3. Install wasm-pack by running cargo install wasm-pack
  4. If you intend to test also install simple-http-server: cargo install simple-http-server
  5. Change directory to the wasm folder of this project and run: wasm-pack --target web
  6. The coinhive_modal.wasm file will be located at pkg/coinhive_modal.wasm
  7. You will probably want to strip this file as it is huge. Use the Web Assembly Binary Toolkit wasm-strip utility. (This is available in most Linux package managers, they also have release binaries).

@mrcbax

mrcbax commented Apr 1, 2021

Copy link
Copy Markdown
Contributor Author

A video of it functioning

2021-03-31.23-11-52.mp4

@mrcbax

mrcbax commented Apr 1, 2021

Copy link
Copy Markdown
Contributor Author

@troyhunt troyhunt merged commit dbf6d2a into troyhunt:main Apr 1, 2021
@hackcasual

Copy link
Copy Markdown

This won't work, even without seeing a page that uses it. The functions imported by the modal wasm are

  (import "wbg" "__wbindgen_object_drop_ref" (func $wbg.__wbindgen_object_drop_ref (type $t5)))
  (import "wbg" "__wbg_instanceof_Window_9c4fd26090e1d029" (func $wbg.__wbg_instanceof_Window_9c4fd26090e1d029 (type $t3)))
  (import "wbg" "__wbg_document_249e9cf340780f93" (func $wbg.__wbg_document_249e9cf340780f93 (type $t3)))
  (import "wbg" "__wbg_body_0d97f334de622953" (func $wbg.__wbg_body_0d97f334de622953 (type $t3)))
  (import "wbg" "__wbg_createElement_ba61aad8af6be7f4" (func $wbg.__wbg_createElement_ba61aad8af6be7f4 (type $t2)))
  (import "wbg" "__wbg_setid_16518c90432c2f8e" (func $wbg.__wbg_setid_16518c90432c2f8e (type $t4)))
  (import "wbg" "__wbg_setclassName_5f8aa8af1f203c85" (func $wbg.__wbg_setclassName_5f8aa8af1f203c85 (type $t4)))
  (import "wbg" "__wbg_setinnerHTML_bd35babb04d64bb9" (func $wbg.__wbg_setinnerHTML_bd35babb04d64bb9 (type $t4)))
  (import "wbg" "__wbg_outerHTML_ab9cbd959fa5adc3" (func $wbg.__wbg_outerHTML_ab9cbd959fa5adc3 (type $t1)))
  (import "wbg" "__wbg_setAttribute_0b50656f1ccc45bf" (func $wbg.__wbg_setAttribute_0b50656f1ccc45bf (type $t9)))
  (import "wbg" "__wbg_settextContent_fa342bf9999ed3eb" (func $wbg.__wbg_settextContent_fa342bf9999ed3eb (type $t4)))
  (import "wbg" "__wbg_appendChild_6ae001e6d3556190" (func $wbg.__wbg_appendChild_6ae001e6d3556190 (type $t0)))
  (import "wbg" "__wbg_call_cb478d88f3068c91" (func $wbg.__wbg_call_cb478d88f3068c91 (type $t0)))
  (import "wbg" "__wbindgen_object_clone_ref" (func $wbg.__wbindgen_object_clone_ref (type $t3)))
  (import "wbg" "__wbg_newnoargs_3efc7bfa69a681f9" (func $wbg.__wbg_newnoargs_3efc7bfa69a681f9 (type $t0)))
  (import "wbg" "__wbg_self_05c54dcacb623b9a" (func $wbg.__wbg_self_05c54dcacb623b9a (type $t6)))
  (import "wbg" "__wbg_window_9777ce446d12989f" (func $wbg.__wbg_window_9777ce446d12989f (type $t6)))
  (import "wbg" "__wbg_globalThis_f0ca0bbb0149cf3d" (func $wbg.__wbg_globalThis_f0ca0bbb0149cf3d (type $t6)))
  (import "wbg" "__wbg_global_c3c8325ae8c7f1a9" (func $wbg.__wbg_global_c3c8325ae8c7f1a9 (type $t6)))
  (import "wbg" "__wbindgen_is_undefined" (func $wbg.__wbindgen_is_undefined (type $t3)))
  (import "wbg" "__wbindgen_debug_string" (func $wbg.__wbindgen_debug_string (type $t1)))
  (import "wbg" "__wbindgen_throw" (func $wbg.__wbindgen_throw (type $t1)))

These are functions that need to be provided by the page for this wasm to work, so without a way of also injecting JS, this will just cause a console error message.

The imports the existing wasm uses are

(import "env" "abort" (func $env.abort (type $t1)))
(import "env" "enlargeMemory" (func $env.enlargeMemory (type $t2)))
(import "env" "getTotalMemory" (func $env.getTotalMemory (type $t2)))
(import "env" "abortOnCannotGrowMemory" (func $env.abortOnCannotGrowMemory (type $t2)))
(import "env" "___setErrNo" (func $env.___setErrNo (type $t1)))
(import "env" "___syscall20" (func $env.___syscall20 (type $t3)))
(import "env" "_emscripten_memcpy_big" (func $env._emscripten_memcpy_big (type $t4)))
(import "env" "_ftime" (func $env._ftime (type $t5)))
(import "env" "_gmtime" (func $env._gmtime (type $t5)))

None of which seem to provide a way to access the DOM. On top of that I believe any page using this would only run the WASM inside a worker, which means we would need a way to use the postMessage interface to cause something to display

@troyhunt

troyhunt commented Apr 2, 2021

Copy link
Copy Markdown
Owner

I'm open to pull requests on this if anyone can find a better approach.

@mrcbax

mrcbax commented Apr 4, 2021

Copy link
Copy Markdown
Contributor Author

Perhaps we could use the syscall20 import to do something interesting.

Edit: on second thought probably not:

int env$$__syscall20(int Which, WasmArray<int> VarArgs) {
TRACE_ENTRY();
(void)Which;
(void)VarArgs;

return trace(getpid());
}

@ghost

ghost commented Jun 28, 2022

Copy link
Copy Markdown

I'm open to pull requests on this if anyone can find a better approach.

The current code cannot possibly work, nor can it be made to actually create the message to alert the user that coinhive has been halted.

Your post makes a somewhat misleading claim:

Edit: Less than half a day after publishing this, I received a pull request with a full WASM implementation that will show the same message to any browser directly calling a .wasm file. Massive thanks to Chad Baxter for doing this!

This simply did not happen.

As mentioned by another user, it would definitely crash (the WebAssembly engine would not be able to link symbols). How about a simply not hosting the WebAssemby module? Nothing useful can be done with it. Alternatively, just trapping upon module instantiation, and trapping upon accessing any of the externalized functions - this should prevent/reduce overall code (JS/Wasm) execution, thus reducing resource consumption on affected users' machines.

@ghost ghost mentioned this pull request Jun 28, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants