1

There was the notorious attack on the Copay cryptocurrency wallet in 2018. To recap it briefly, the JavaScript based wallet depended on a library, event-stream. Using social engineering, hackers gained ability to change this library and publish its new versions through npm package manager. Injected malicious code was intended to carry out the following things:

  1. Payload A (a chunk of code) deciphers Payload B and runs it with the aid of Node.js Module.prototype._compile function. Payload B exports a function (with module.exports), which then gets executed. (These code steps are given in much more convenient way in the first comment of the github issue).
  2. This function objective was to inject yet another deciphered Payload C. Its code was introduced by means of writeFileSync() into ReedSolomonDecoder.js file, which in fact was a part of a lib dependency (of a module inside the ./node_modules folder).
  3. When someone calls require('./ReedSolomonDecoder.js') for the first time, injected Payload 3, in turn, would call require('bitcore-wallet-client/lib/credentials.js') and fiddle with its function prototypes, so for now on user passwords would send to a hackers server.
  4. When Node.js environment emits process.exit event, ReedSolomonDecoder.js is returned to its initial state.

My question is why did the hacker opt for this involved and precarious way including OS file modifications? Instead, they could tinker with the credentials.js module immediately after the first injected code (Payload A) get execution. Can anybody at least suggest an explanation of such decision? My only thought is when the Payload A is run, require('bitcore-wallet-client/lib/credentials.js') was not yet been called and it was not safe for attackers to initiate its first call for some reasons.

0 Answers0