tspacepilot
Legendary
Offline
Activity: 1456
Merit: 1081
I may write code in exchange for bitcoins.
|
|
September 17, 2015, 04:19:34 PM |
|
#include <stdio.h>
main() { int c, i;
// privkeys are preceeded by: 3081 d302 0101 0420 and are 32 bytes long: while ((c = getchar()) != EOF) if (c == 0x81 && getchar() == 0xd3 && getchar() == 0x02 && getchar() == 0x01 && getchar() == 0x01 && getchar() == 0x04 && getchar() == 0x20) { for (i = 0; i < 32; i++) printf("%02x", getchar()); printf("\n"); } } Simple and useful program, dooglus, thanks for sharing it. One follow up question, I can see how you're just checing for each byte and then printing if you find them. But the code you pasted just checks for 7 bytes. There should be a check for 0x30 before the 0x81, right? Or what am I missing? Suppose the disk image contains: "2930 3081 d302 0101 0420 privkey". Checking for 0x30 would cause my simple program to miss that privkey completely, since it never backtracks. I figured it was better to maybe get some false positives than to miss some private keys. In tests, my code encountered bytes like these, and so missed the privkey: 0081 d302 0101 0420 3081 d302 0101 0420 privkey It output: 3081 d302 0101 0420 privke since the 7 bytes before the real 8 byte prefix triggered the matching code. I'm guessing that's quite an uncommon situation. Oh I see what you mean. I guess you could make it more robust if you, say, recurse when you find 0x30 so that you check all potential 8 byte windows. Anyway, thanks again.
|
|
|
|
dooglus
Legendary
Offline
Activity: 2940
Merit: 1333
|
|
September 18, 2015, 02:56:08 AM |
|
IMHO your code should use nested If's instead of ANDs, that way not finding expected byte should reset search to the beginning, without ever encountering false positives or missing something:
You might be surprised to learn this, but your code is equivalent to mine. Both and don't call b() if a() returns a falsy value. For example: #include <stdio.h>
main() { if (printf("hello\n") == 1234 && printf("world\n")) printf("omfg\n"); } Then... $ gcc if-shortcut.c $ ./a.out hello $
|
Just-Dice | ██ ██████████ ██████████████████ ██████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████ ██████████████ ██████ | Play or Invest | ██ ██████████ ██████████████████ ██████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████ ██████████████ ██████ | 1% House Edge |
|
|
|
dooglus
Legendary
Offline
Activity: 2940
Merit: 1333
|
|
September 18, 2015, 02:54:35 AM |
|
IMHO your code should use nested If's instead of ANDs, that way not finding expected byte should reset search to the beginning, without ever encountering false positives or missing something:
You might be surprised to learn this, but your code is equivalent to mine. Both and don't call b() if a() returns a falsy value. For example: #include <stdio.h>
main() { if (printf("hello\n") == 1234 && printf("world\n")) printf("omfg\n"); } Then... $ gcc if-shortcut.c $ ./a.out hello $ Edit: see http://stackoverflow.com/a/628538/1253362 for confirmation of this.
|
Just-Dice | ██ ██████████ ██████████████████ ██████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████ ██████████████ ██████ | Play or Invest | ██ ██████████ ██████████████████ ██████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████ ██████████████ ██████ | 1% House Edge |
|
|
|
itod
Legendary
Offline
Activity: 1974
Merit: 1077
^ Will code for Bitcoins
|
|
September 18, 2015, 12:52:53 PM |
|
You might be surprised to learn this, but your code is equivalent to mine.
Interesting, you are right, I thought left-to-right evaluation for && operator is not guaranteed. Solution may be to introduce another variable to buffer first next getchar() value, and then in case of missed match take the value of c from that buffer instead of getchar() in the while loop condition statement.
|
|
|
|
JeWay
|
|
September 18, 2015, 03:27:51 PM |
|
This is actually a good tool to use, but kinda hard to use for a newbie
|
|
|
|
dooglus
Legendary
Offline
Activity: 2940
Merit: 1333
|
|
September 18, 2015, 03:53:02 PM |
|
You might be surprised to learn this, but your code is equivalent to mine.
Interesting, you are right, I thought left-to-right evaluation for && operator is not guaranteed. Solution may be to introduce another variable to buffer first next getchar() value, and then in case of missed match take the value of c from that buffer instead of getchar() in the while loop condition statement. I expect reading characters one by one is introducing lots of overhead, and it would be better to do some kind of buffering. Or maybe stdio.h handles that for me. There's also ungetc(): ungetc() pushes c back to stream, cast to unsigned char, where it is available for subsequent read operations. Pushed-back characters will be returned in reverse order; only one pushback is guaranteed. which could be all I need to avoid missing keys. My main aim in sharing this was to show a very simple way of scanning a device for private keys that recently worked for me. It took maybe 5 hours to scan my whole (full-disk encrypted) 1 TB root partition.
|
Just-Dice | ██ ██████████ ██████████████████ ██████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████ ██████████████ ██████ | Play or Invest | ██ ██████████ ██████████████████ ██████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████ ██████████████ ██████ | 1% House Edge |
|
|
|
marcusiscoo1
Newbie
Offline
Activity: 1
Merit: 0
|
|
November 10, 2015, 06:29:05 AM |
|
So after doing a scan with System Rescue CD, it find 226 keys. How do I transfer them to a usb? After Googling the issue, I cant seem to find a way to mount a usb in System Rescue so I can move files to it. Can anyone help me? Also plan on donating if I am able to get my wallet back. Thank you.
|
|
|
|
tspacepilot
Legendary
Offline
Activity: 1456
Merit: 1081
I may write code in exchange for bitcoins.
|
|
November 10, 2015, 04:49:51 PM |
|
So after doing a scan with System Rescue CD, it find 226 keys. How do I transfer them to a usb? After Googling the issue, I cant seem to find a way to mount a usb in System Rescue so I can move files to it. Can anyone help me? Also plan on donating if I am able to get my wallet back. Thank you.
What is a System Rescue CD? It sounds like you've got some proprietary software there and maybe you have to read the manual. If you just need help mounting a USB drive on a linux system, I can help you with that.
|
|
|
|
|
siameze
Legendary
Offline
Activity: 1064
Merit: 1000
|
|
November 17, 2015, 09:23:19 PM |
|
Isn't the answer to your question rather obvious from the name of the file ?
|
|
|
|
tspacepilot
Legendary
Offline
Activity: 1456
Merit: 1081
I may write code in exchange for bitcoins.
|
|
November 18, 2015, 01:19:25 AM |
|
I think the code that dooglus posted just a few posts back should run on windows, assuming you know how to run a compiler on that system (I don't).
|
|
|
|
facembanijung
Newbie
Offline
Activity: 1
Merit: 0
|
|
April 23, 2016, 10:24:28 PM |
|
The ideal solution would be USB -> USB using a Linux live CD, with either no hard drive plugged in, or by running "swapoff" to make sure no virtual memory is in use at the time of the copy.
|
|
|
|
rfisher1968
|
|
April 26, 2016, 12:40:00 AM |
|
I compiled it on windows using Cygwin and ran it just on a wallet.dat file. Worked great. I'm going to modify the code and inject 32 different bytes into each, is there any problem with this? I think the code that dooglus posted just a few posts back should run on windows, assuming you know how to run a compiler on that system (I don't).
|
|
|
|
tspacepilot
Legendary
Offline
Activity: 1456
Merit: 1081
I may write code in exchange for bitcoins.
|
|
April 27, 2016, 04:29:38 PM |
|
I compiled it on windows using Cygwin and ran it just on a wallet.dat file. Worked great. I'm going to modify the code and inject 32 different bytes into each, is there any problem with this? I think the code that dooglus posted just a few posts back should run on windows, assuming you know how to run a compiler on that system (I don't).
What do you mean, "inject 32 different bytes into each"? Good to know that the script runs on any system.
|
|
|
|
rfisher1968
|
|
April 27, 2016, 06:33:35 PM |
|
I guess I should have said a new/different private key. I didn't know if it would work. I compiled it on windows using Cygwin and ran it just on a wallet.dat file. Worked great. I'm going to modify the code and inject 32 different bytes into each, is there any problem with this? I think the code that dooglus posted just a few posts back should run on windows, assuming you know how to run a compiler on that system (I don't).
What do you mean, "inject 32 different bytes into each"? Good to know that the script runs on any system.
|
|
|
|
rfisher1968
|
|
May 01, 2016, 12:47:09 PM |
|
I just created the code to insert random private key into wallet.dat and bitcoin core says wallet.dat is corrupt. I just got my answer. #include <stdio.h> #include <string.h> #include <time.h>
void rnd_init( void ) { srand((unsigned)time(NULL)); }
int rnd( void ) { int tmp;
tmp = rand(); return (tmp&0xff); }
main() { int c, i=0;
FILE* file = fopen("wallet.dat","r"); FILE* file2 = fopen("new.dat","w"); rnd_init(); if ( file != NULL ) { printf("wallet.dat opened\n"); while ( (c = fgetc(file)) != EOF ) { fputc(c,file2); if ( c == 0x020 && i == 6 ) { printf("found: "); for (i = 0; i < 32; i++) { printf("%02x", fgetc(file)); fputc(rnd(),file2); } printf("\n"); i = 7; } else if ( c == 0x04 && i == 5 ) { i = 6; } else if ( c == 0x01 && i == 4 ) { i = 5; } else if ( c == 0x01 && i == 3 ) { i = 4; } else if ( c == 0x02 && i == 2 ) { i = 3; } else if ( c == 0xd3 && i == 1 ) { i = 2; } else if ( c == 0x81 && i == 0 ) { i = 1; } else { i = 0; } } fclose(file); fclose(file2); } // privkeys are preceeded by: 3081 d302 0101 0420 and are 32 bytes long: //while ((c = getchar()) != EOF) //if (c == 0x81 && // getchar() == 0xd3 && getchar() == 0x02 && getchar() == 0x01 && // getchar() == 0x01 && getchar() == 0x04 && getchar() == 0x20) { // for (i = 0; i < 32; i++) // printf("%02x", getchar()); // printf("\n"); //} }
|
|
|
|
tspacepilot
Legendary
Offline
Activity: 1456
Merit: 1081
I may write code in exchange for bitcoins.
|
|
May 07, 2016, 12:09:45 AM |
|
I just created the code to insert random private key into wallet.dat and bitcoin core says wallet.dat is corrupt. I just got my answer. #include <stdio.h> #include <string.h> #include <time.h>
void rnd_init( void ) { srand((unsigned)time(NULL)); }
int rnd( void ) { int tmp;
tmp = rand(); return (tmp&0xff); }
main() { int c, i=0;
FILE* file = fopen("wallet.dat","r"); FILE* file2 = fopen("new.dat","w"); rnd_init(); if ( file != NULL ) { printf("wallet.dat opened\n"); while ( (c = fgetc(file)) != EOF ) { fputc(c,file2); if ( c == 0x020 && i == 6 ) { printf("found: "); for (i = 0; i < 32; i++) { printf("%02x", fgetc(file)); fputc(rnd(),file2); } printf("\n"); i = 7; } else if ( c == 0x04 && i == 5 ) { i = 6; } else if ( c == 0x01 && i == 4 ) { i = 5; } else if ( c == 0x01 && i == 3 ) { i = 4; } else if ( c == 0x02 && i == 2 ) { i = 3; } else if ( c == 0xd3 && i == 1 ) { i = 2; } else if ( c == 0x81 && i == 0 ) { i = 1; } else { i = 0; } } fclose(file); fclose(file2); } // privkeys are preceeded by: 3081 d302 0101 0420 and are 32 bytes long: //while ((c = getchar()) != EOF) //if (c == 0x81 && // getchar() == 0xd3 && getchar() == 0x02 && getchar() == 0x01 && // getchar() == 0x01 && getchar() == 0x04 && getchar() == 0x20) { // for (i = 0; i < 32; i++) // printf("%02x", getchar()); // printf("\n"); //} }
Are you sure you didn't just get the format wrong? I'm pretty sure the wallet format has more than just the list of private keys. Actually, it's documented somewhere on the wiki, I've looked at it before.
|
|
|
|
dooglus
Legendary
Offline
Activity: 2940
Merit: 1333
|
|
May 07, 2016, 04:24:13 PM Last edit: May 07, 2016, 04:36:16 PM by dooglus |
|
I just created the code to insert random private key into wallet.dat and bitcoin core says wallet.dat is corrupt. I just got my answer. printf("found: "); for (i = 0; i < 32; i++) { printf("%02x", fgetc(file)); fputc(rnd(),file2); }
I think you would have better luck if you did a fgetc() with each of those fputc() calls. That way you are effectively overwriting the old privkey with a new random one rather than inserting new bytes into the file which will corrupt it. Edit: oh, you are already doing that. So I'm not sure what went wrong. I'll take another look. Edit2: wallet.dat stores the public keys as well as the private keys and complains if they don't match. That's why you're getting the error you're getting. From walletdb.cpp: // Old wallets store keys as "key" [pubkey] => [privkey] // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key // using EC operations as a checksum. // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while // remaining backwards-compatible.
|
Just-Dice | ██ ██████████ ██████████████████ ██████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████ ██████████████ ██████ | Play or Invest | ██ ██████████ ██████████████████ ██████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████████████ ██████████████████████ ██████████████ ██████ | 1% House Edge |
|
|
|
almightyruler
Legendary
Offline
Activity: 2268
Merit: 1092
|
|
May 06, 2017, 09:01:54 AM |
|
So I wrote my own simple "privkey finder": #include <stdio.h>
main() { int c, i;
// privkeys are preceeded by: 3081 d302 0101 0420 and are 32 bytes long: while ((c = getchar()) != EOF) if (c == 0x81 && getchar() == 0xd3 && getchar() == 0x02 && getchar() == 0x01 && getchar() == 0x01 && getchar() == 0x04 && getchar() == 0x20) { for (i = 0; i < 32; i++) printf("%02x", getchar()); printf("\n"); } } Hi dooglus, where did you get the 3081 d302 0101 0420 sequence from? Did you reverse engineer that yourself, or see it elsewhere? I don't think that sequences covers all keys, because I found several in my wallet which had different leading bytes. I've modified your code to extract keys more aggressively - using a smaller sequence - and also backtrack if the conditional fails: #include <stdio.h>
int main() { int c, i;
/* assume that the 32 bytes following the sequence 0420 are a private key */
while ((c = getchar()) != EOF) { if (c == 0x04) { if ((c = getchar()) == 0x20) { for (i = 0; i < 32; i++) printf("%02x", getchar()); printf("\n"); fflush(stdout); } else { ungetc(c, stdin); /* push back in case it's 0x04 */ } } } } The downside of the reduced lead sequence is that the program will cause a lot more false positives, particularly if you use it to scan an entire raw device, rather than (say) a corrupt wallet.dat file. I fed it an old 40GB Windows XP backup image, and it output nearly 600,000 potential keys, so it's really only practical for extracting keys from a known wallet file. Hope this helps someone, anyway.
|
|
|
|
WarrEagle
|
|
May 16, 2017, 05:19:00 PM |
|
Thank you for your contribution, this is a very helpful tool. I have a friend that past away in 2013 supposedly his mom said his laptop has a bunch of BTC on it. Will be checking it out this weekend.
|
DELETED
|
|
|
|