简体   繁体   中英

Why is all of my output appearing before each brute-force attempt when attempting to crack an ethereum keystore wallet file in node.js

I found a post describing how to recover an Ethereum wallet keystore by guessing a single password, however, it uses node synchronous code, and I'm trying to convert it into asynchronous code so that I can use multithreading using worker_threads.

run.js (snippet)

for (let x = 0; x <= maxX*passesPerThread; x++) {
  passes[x +1] = c.iterate(passes[x], chars)
}
for (let x = 0; x < maxX; x++) {
  dcWorker[x] = new Worker('./worker.js', { workerData: { FILE: FILE, PASSWORD: passes[x*passesPerThread], workerNum: x, passesPerThread: passesPerThread, CHARS: chars}, })
  dcWorker[x].on('message', (data) => {
    if (data.status === 'done') {
      console.log(" w" + x + "d")
    }
  })
}

crack.js (snippet)

function crack(PASSWORD, FILE) {
  const data = fs.readFile(FILE, {encoding: "utf8"}, (err, data) => {
    if (err) throw err
    const content = data
    attempt(data, PASSWORD, FILE)
  })
}

function attempt(data, PASSWORD, FILE) {
  const keythereum = require("keythereum")
  const keyObject = JSON.parse(data)
  keythereum.recover(PASSWORD, keyObject, privateKey => {
    if (!privateKey.toString() === "message authentication code mismatch") {
      console.log("\npossible password: " + PASSWORD + "\naddress: " + `0x${keyObject.address}` + "\npriv key: " + `0x${privateKey}`)
      savePass(PASSWORD, FILE)
      //process.exit()
    }
  })
}

worker.js (snippet)

passes = new Array()
passes[0] = pass
maxX = workerData.passesPerThread

const cProm = 
  new Promise((resolve, reject) => {
    for (let x = 1; x < maxX; x++) {
      passes[x] = c.iterate(passes[x -1], chars)
    }
    resolve('done')
  })
  .then(value => {
    for (let x = 1; x < maxX; x++) {
      process.stdout.write(" w" + workerData.workerNum + "a" + passes[x] + "T" + Date.now() + ", ")
      c.crack(passes[x], FILE)
    }
    parentPort.postMessage({ status: value })
  })
  .catch(err => {
    parentPort.postMessage({ status: err })
  })

I don't understand why the stack is processing all output before actually attempting each crack attempt.

The following is output, then a long pause while it attempts to crack ONE password for each thread, instead of many passwords per thread like the output seems to indicate:

 w1aeasyaspsi, w1d
 w1aeasyaspsi,
 w1aeasyaspyeT1641634988273,  w1aeasyaspyaT1641634988274,  w1aeasyaspysT1641634988274,  w1aeasyaspyyT1641634988274,  w1aeasyaspypT1641634988274,  w1aeasyaspyiT1641634988274,  w1aeasyasppeT1641634988274,  w1aeasyasppaT1641634988274,  w1aeasyasppsT1641634988274,  w0aeasyaspaa, w3aeasyasiea, w0d
 w3d
 w0aeasyaspaa,
 w0aeasyaspasT1641634988279,  w0aeasyaspayT1641634988280,  w0aeasyaspapT1641634988280,  w0aeasyaspaiT1641634988280,  w0aeasyaspseT1641634988280,  w0aeasyaspsaT1641634988280,  w0aeasyaspssT1641634988280,  w0aeasyaspsyT1641634988280,  w0aeasyaspspT1641634988280,  w3aeasyasiea,
 w3aeasyasiesT1641634988279,  w3aeasyasieyT1641634988280,  w3aeasyasiepT1641634988280,  w3aeasyasieiT1641634988280,  w3aeasyasiaeT1641634988280,  w3aeasyasiaaT1641634988280,  w3aeasyasiasT1641634988280,  w3aeasyasiayT1641634988280,  w3aeasyasiapT1641634988280,  w2aeasyasppy, w2d
 w2aeasyasppy,
 w2aeasyaspppT1641634988296,  w2aeasyasppiT1641634988297,  w2aeasyaspieT1641634988297,  w2aeasyaspiaT1641634988297,  w2aeasyaspisT1641634988297,  w2aeasyaspiyT1641634988297,  w2aeasyaspipT1641634988297,  w2aeasyaspiiT1641634988298,  w2aeasyasieeT1641634988298,

after this is output almost instantaneously, it pauses while it attempts to crack 4 passwords, then the process drops out (without error).

I was expecting the output to pause after each comma , but it outputs everything before attempting anything.

The idea is to, for example, crack 10 passwords per thread, where there are 4 threads, then when the worker is terminated, a new worker in its place is started with the next 10 passwords, however, I'm just trying to run each worker_thread once to start until I can debug the rest of it.

So, my questions are:

  • Why isn't it attempting all crack attempts like the output seems to indicate?
  • How do I make the output align with what is actually being attempted when it's being attempted?

i gave up trying to understand promises (but i understand some of it) so i reverted to synchronous code while still implementing true multithreading via nodejs cluster and it now runs much, much faster than single threaded

run.js

//(synchronous functions not displayed)
//...
workers = new Array()
if (cluster.isMaster) {
  pass = ""
  if(PROGRESS === "CONTINUE") {
    if (checkFileExists(FILE + ".progress.txt")) {
      console.log("progress file found: continuing")
      try {
        const data = fs.readFileSync(FILE + ".progress.txt", 'utf8')
        pass = data
      } catch (err) {
        console.error(err)
      }
      if (!pass.length > 0) pass = chars.substring(0,1)
    } else {
      console.log("progress file not found: starting at beginning; this is ok if first time running")
      pass = chars.substring(0,1)
    }
  } else pass = chars.substring(0,1)
  let r = 0
  for (let x = 0; x < cpuCount; x++) {
    workers[x] = cluster.fork()
    workers[x].send({ message: pass })
    workers[x].on('message', function(msg) {
      if (msg.stat) {
        for (sworker in workers) {
          workers[sworker].process.kill()
        }
        process.exit()
      }
      if (msg.att) {
        process.stdout.write("\rattempted: " + msg.att)
        r++
        if (r % 100 == 0) {
          fs.writeFileSync(FILE + '.progress.txt', msg.att, function (err) {
            if (err) throw err
          })
          r = 0
        }
        pass = iterate(pass)
        workers[x].send({ message: pass })
      }
    })
    pass = iterate(pass)
  }
} else {
  process.on('message', function(pass) {
    crack(pass.message)
    process.send({ att: pass.message })
  })
}

please note that this is a bit of an ugly hack-job and shouldn't be implemented in a server and definitely should not be implemented in production because it uses blocking code, but for my narrow purpose it does the job

thanks to everyone of whom tried to show me the way of using asynchronous code in the comments above

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM