Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Created WASM module. #3

Merged
merged 6 commits into from
Apr 1, 2021
Merged

Created WASM module. #3

merged 6 commits into from
Apr 1, 2021

Conversation

mrcbax
Copy link
Contributor

@mrcbax mrcbax commented Mar 31, 2021

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
Copy link
Contributor Author

mrcbax commented Mar 31, 2021

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
Copy link
Contributor Author

mrcbax commented Mar 31, 2021

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
Copy link
Contributor Author

mrcbax commented Apr 1, 2021

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
Copy link
Contributor Author

mrcbax commented Apr 1, 2021

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
Copy link
Contributor Author

mrcbax commented Apr 1, 2021

A video of it functioning

2021-03-31.23-11-52.mp4

@mrcbax
Copy link
Contributor Author

mrcbax commented Apr 1, 2021

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

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
Copy link
Owner

troyhunt commented Apr 2, 2021

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

@mrcbax
Copy link
Contributor Author

mrcbax commented Apr 4, 2021

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
Copy link

ghost commented Jun 28, 2022

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