A comprehensive guide on how to recover IOTA Wallet SEED [Windows PowerShell]

in #iota7 years ago (edited)

UPDATE 23.08

Hi guys, glad that the devs have listened and put up an announcement to the whole network about this potential security breach. I want to emphasize that this IS NOT IOTA'S FAULT but rather a non-intentional loophole in the Get-Random function in Windows PowerShell.

This post targets not only the one who have lost their seeds or also for those who generated their seeds in this insecurely way! And I only re-upload this blog post after a "24-hour curfew" so that people have time to move their seeds to a safer generator.

And I URGE the people who used Windows PowerShell to generate their seeds to change their seeds IMMEDIATELY. Please refer to this IOTA SUPPORT BLOG for more information on the new methods (yea, they have removed the "Windows Powershell" part). And the urandom of MacOS and Ubuntu version there are confirmed SAFE!

Also, I came to know that most of the exchanges out there are potentially exploited as well if their operating system is Windows and the seeds are generated using Powershell... So yea.... the choice is yours!

UPDATE 22.08

Apparently Dominik Schiener (co-founder of IOTA) just messaged me and wanted me to remove this blog post. He wants everyone to have a chance to move to a safer seed generator and doesn't want people with bad intention use my method. So I have to remove this post, but if you have any trouble, please don't hesitate to contact me!

To sum up, my method would work if you used Windows's PowerShell to generate your seed! With this command:
Windows (PowerShell)

-join ([char[]](65..90+57..57)*100 | Get-Random -Count 81) 

Cheers!


How to recover your IOTA Wallet SEED

(Windows Powershell)

Table of Contents

  1. Intro
  2. Background Story
  3. Methodology
    3a. Information Gathering
    3b. Get-Random Explanation
  4. Recovery Guide
    4a. "Kinda Brute-Force Method"
    4b. "A Bit Less Brute-Force Method"
  5. Final Words

TL;DR: Just jump to section 4 & 5 then :) ! But i recommend you to read everything.... since it is better to understand what you are doing.

1. Intro

Losing your seed wallet is the worst in this crypto world, and trust me, I know how it feels. After hours of investigating and trying different methods, I would like to share to you one possible way to recover your lost seed (beside the typical brute-force method which mainly depends on your lucks). It requires a bit of digging into your system event log and calculating the "ticktime" of your computer when you generated the seeds.

*Disclaimer: This method might work if you GENERATED YOUR SEED BASE IN YOUR WINDOWS POWERSHELL.

2. Background Story

  • I bought around 250 Mi IOTA on Bitfinex on last Sunday morning (20 Aug 2017)
  • Then I transferred them to a newly installed IOTA Light-Wallet client with my seed GENERATED FROM POWERSHELL. Since I installed the newest version (2.4.0), I didn't have to go through the transition guide. If you belong to the "old wallet upgrade to new and lost my balance" group, please see THIS instead!
  • After that, I wrote down the seed and closed the wallet ( I should have checked the seed 3 more times and also wrote down the checksum - will come back to this later)
  • Later, I came back, entered my seed and found out there is nothing in my wallet. Tried to enter many possible different version of my seeds too, but no luck. Then I started to dig down into the root.

3. Methodology

Just to remind you again, if you generate your seed in Windows Powershell like from the old version IOTA Support blog, this might be able to help you. The codes I used there was

Windows (PowerShell)

-join ([char[]](65..90+57..57)*100 | Get-Random -Count 81) 

3a. Information Gathering

Here are the info you should gather:

  1. The time you turned on your computer when you first generated the seed
  2. The time you opened Powershell
  3. Maybe the "wrong" seed that you are keeping
  4. Additional info (for brute-forcing) might be the address you used to send/receive IOTA and check-sum (a.k.a when you input the 81 characters into the wallet, there are 3 characters appear next to it on the right-hand side. It's crucial to keep it and I hope the developers will do something to make it more visible for normal users)

3b. Explanation of "Get-Random" function

Normally, when you want to generate a random number in powershell, there is an option of inputting the seed of the function. For example:

HERE! You will notice that I used the code from the IOTA support blog (depreciated 23rd Aug 2017) for generating the seed. However, I specified the seed directly inside the code; thus, this will ensure that *every single time i run this piece of code again with the same seed, i will be able to get the exact same result.

When a seed value is not provided to Get-Random, the system tick count – the number of milliseconds elapsed since the system started is used as a seed. Executing Get-Random without a seed is equivalent to executing:

Get-Random -SetSeed ([Environment]::TickCount)

Now, the tick count is a 32-bit number which means that there are 4,294,967,295 possible seed values (however since it is an Int-32 type, you only have 2,147,483,647 possible values now!). Such a massive number ought to produce sufficiently unpredictable sequences. However, this is where the information I told you to gather in the above section comes to the rescue!

Let's think of a scenario where you use the Get-Random to generate random passwords and the script is scheduled to run just 2 minutes after the system is turned on. It is probably unlikely for you to hit the exact number of mili-seconds but for a fast computer it’s probably likely that you are guaranteed that a set of seeds within a specific time interval will be used. Let’s say that we determined that the script was likely to execute within 2000 milliseconds (2 seconds) of the last time the script executed. That means that there is only a maximum of 2000 possible passwords that one would need to guess. For a determined adversary intent on obtaining a critical password, this is not an impossible task.

4. Recovery Guide

So now there are 2 way of getting the seed back after knowing all the things above:

Remember, you need to run this on the computer you used to generate the seeds!

4a. "Kinda Brute-Force Method"

Since there are only 4,294,967,295 2,147,483,647 seeds in the Powershell - well, thanks to Microsoft - (it is a much much lower number than (27+1)^81 combinations), you can create a loop function and run from 1 to 4,294,967,295 2,147,483,647. Then compare your seed with the list of 4,294,967,295 2,147,483,647 (of course you can narrow them down by similarities - in my case, I am sure that the first 20 characters of my seed is correct, so i only need to look for same seeds). I encourage you to try this method first! And here is the code to do that, I will explain in the next section:

Here, I divided into 2 small parts, you can run 2 Powershell at the same time (or even more) to retrieve the results faster.

Bottom-up

$i=1
$target = 'INSERT THE PART THAT YOU ARE SURE 100% CORRECT FROM YOUR "WRONG" SEED HERE'
$x = 'START POSITION OF YOUR $target IN THE SEARCH SEED'
$y = 'HOW MANY CHARACTERS'

$Path = 'D:\Test.txt'

While ($i  -2147483647)
{
$i
$key = -join ([char[]](65..90+57..57)*100 | Get-Random -Count 81 -SetSeed $i)
$test = $key.Substring($x,$y)
If (($test).CompareTo($target) -eq 0) 
{$key | Add-Content -Path $Path
-join ([char[]](65..90+57..57)*100 | Get-Random -Count 81 -SetSeed $i)
}
$i++
}

Top-down

$i=  2147483647
$target = 'INSERT THE PART THAT YOU ARE SURE 100% CORRECT FROM YOUR "WRONG" SEED HERE'
$x = 'START POSITION OF YOUR $target IN THE SEARCH SEED'
$y = 'HOW MANY CHARACTERS'
$Path = 'D:\Test1.txt'

While ($i  -1)
{
$i
$key = -join ([char[]](65..90+57..57)*100 | Get-Random -Count 81 -SetSeed $i)
$test = $key.Substring($x,$y)
If (($test).CompareTo($target) -eq 0) 
{$key | Add-Content -Path $Path
-join ([char[]](65..90+57..57)*100 | Get-Random -Count 81 -SetSeed $i)
}
$i-- 
}

Now, here are the variables you need to specify yourself: $target, $x and $y. Take "ABCDEFG" as your first 7 characters of your "WRONG" SEED, but you are sure this 7 first characters are correct (match with your original seed). We would edit the variable as follow:

$target = 'ABCDEFG'
$x = '0'
$y = '7'

So $x is the starting position of your string and $y is the number of character you would like to put into the substring function. The Bottom up code above is running the loop from 1 ---> 4294967295 2147483647 and compare all your seeds and only print out the seeds that match the first 7 characters of the example here. The Top down do the opposite: run the loop from 4294967295 2147483647 --> 1.

With above, I believe you will get your seeds back pretty quick (imagine if you open 10 Powershell at the same time and narrow the range by 1 billion each).

4b. "A Bit Less Brute-Force Method"

By narrowing the seeds range to even smaller by calculating the time you started the system and the time you generated the seed, we can determine the range of the tick and thus, just need to run the loop in a even shorter range!

Note: It is better to clarify that this [Environment]::TickCount

gets the number of milliseconds elapsed since the system started

Possible Recover Steps

1. Get the correct time & date for Tickcount

Now we know that once we determine the time, we can try to guess the tick, and then wallet seed !!! So first, if you don't remember when you opened your computer, just try to remember the time you open the Powershell. To do that, there is a shorter and more precise way:

  1. Open "Event Viewer" (in Windows 10), just click on the ⊞ Win + S and type "Event Viewer"
  2. Navigate through this path: Applications and Services Logs\ Microsoft\ Windows\ PowerShell\ Operational
  3. Then select the event that have "Task Category" as "PowerShell Console Startup" like this

2. Get the correct TickCount

Now open your PowerShell (⊞ Win + S and type in "PowerShell") and input your time & date you got in the step above (save this as $end_time).
Then either use the Event Log above to determine the time you start your system (Event Viewer/ Windows Logs/ Application or System), check for Event ID (6005,6006,6008,6009,6013,1074,1076,41,1001) to get the correct uptime

Or try to remember it through simpler way (such as the application you turn on immediately after you turn on your computer - Chrome? Facebook? Or games?). Then note it and input the variable $i as the above code with either Top-down or Bottom-up method.

And remember to open multiple PowerShell windows to get the result asap by dividing the loops into chunks (1-billion or smaller 100-million)

5. Final

I was reached out by Dominik Schiener yesterday (a real surprise and honor :) ) about this. I would expect them to notify this officially for those who have used their method to generate seeds could know and change their seeds. But except for his message to tell me to postpone the post. All my other messages and suggestions were ignored. But in the end I still post this with good intention (to help those facing similar problem as mine and those who have used powershell)

I actually think this is beneficial for IOTA in the long run because they can pay more attention to security issue. I suggest they should create some kind of bounty program to reward those who can point out issues like this.

One final important note for those who are still reluctant to change their seed. Since IOTA's node has the ability to "spam" seeds until they get the correct one, they can utilize this and a dictionary of addresses (easily obtain through the unofficial tangle networks) to search for your seed and .... well...you know what will happen.

Cheers and best regards!

Donation Address (if you like this guide :), please..)

BTC

1GL9ZnLGu1zvTRPieXKMXURKLfrshtZv9

ETH

0xa2492f8263c3ec3b6e8cb8b4dc88f676eea19984

IOTA

MSQRAJGTQRNNBUZAZYOBDYLBSIJIVHFKCPKJIJV9W9VOIESGBDFYQ9PATFROYWLZSHZDFQQAETRETWCXCQOGY9DAVW

UTUOSZWYWBQKZABVBPQRMDOSOJPGPVUWPPGFQFDTR9BUMOVNZHDVKOPOMWFDEQY9FHKAYBVTHYOLCWP9WIZDLDTBJX

LTC

LYpidHJmkk7fPeKKBtLUHmEnvh5sfr6QW8

BCH

16gRYgdTWnA7kKiUTTDoEHhkh5TmCULPGX

DOGE

D7VWpk1RHTemFSBeUrETAdXnE4rToNUMx6

References

  1. Environment.TickCount Property
  2. DateTime.Ticks Property
  3. Testing the effectiveness of Get-Random

Coin Marketplace

STEEM 0.20
TRX 0.13
JST 0.029
BTC 65927.86
ETH 3481.42
USDT 1.00
SBD 2.66