Closed whatsappnomedia closed 5 years ago
PS: the 'token' referred to above is the 'id' field for https://v.whatsapp.net/v2/code
In addition, it stores on the SD card (in "Exteranal Storage/WhatsApp/Profile Pictures/.nomedia") a token that can be used for registration without confirmation via SMS.
Are you kidding me? That's so stupid >.< And here we were speculating about how to possibly retrieve/replicate/reverse engineer the registration ID...
glad I could help ;)
I need to execute this python code on my Android device and do all the job, correct?
No you need to extract the pw file from your Android device and run the code on your PC
Note that both the 'pw' and '.nomedia' files are encrypted The provided code decrypts these files (the 'me' file is not encrypted).
Hey where is the pw and me file stored? How to retrieve them I found the .nomedia file, but couldn't find the pw and me file.
Also what is the 2nd parameter decode_nomedia(".nomedia", "12125551234", "your.google.account@gmail.com")
which is taken in as pn in the function definition
ok i am assuming that pn is the phone number. also i assume it includes the country code.
pn is phone number - including country code the pw & me files are stored in the sandbox - not on the SD card
yeah i got the part that they are stored in sandbox. I just want to know how to access the sandbox, i want to fetch the files.
also i got something like |**_f\xfa\x0c\xacu\xdf\xdc****) *_* on running that file with my gmail account and phone number. Is it correct. Some encoding error is happening when i try to feed it to the yowsup library.
when i try to utf encode the stuff then it shows that there are some invalid starting bytes. :(
can you please explain where did you get the salt values?
@whatsappnomedia ^
any of you guys on IRC specially any one among @whatsappnomedia or @shirioko or @tgalal ?
What is this "IRC" you speak of..?
Internet Relay Chat. Never heard of freenode servers? That's really interesting.. If you guys ever roam around in IRC then ping me on #yosapp channel I generally hang around there.
Hey @shirioko were you able to successfully use the above script to figure out the password of an existing account.
IRC? That's the dark underground communication channel of the hacker scene. 2spooky4me
I've ported the script to C# but was unable to get a working password. I'll try using the original python script on my files to see if I get a different result.
I tried on my files and gave the password and id generated by the script to use yowsup but it failed. Auth fail.
@shirioko this is the same algorithm that is being used by Whatsapp Xtract. At least looked similar to me. http://forum.xda-developers.com/showthread.php?t=1583021
@whatsappnomedia dude were you successful in converting any workking password? I was confused only in one part I explain below: def decode_nomedia(nomedia, pn, account): g = C.match(pn) e = g.group(1) + g.group(2) jabberid = e + account pw = javaobj.JavaObjectUnmarshaller(open(nomedia)).readObject() pw_file_content = "".join([chr(c) if c>=0 else chr(c+256) for c in pw]) return do_decode(sauce2, jabberid, pw_file_content)
Here you create jabberid by using a sub part of phone number contac with email acc. But I think when I used yowsup I remember seeing jabberid being phone_number@s.whatsapp.net
So I am kind of confused. @shirioko can you help me solve this problem?
Salt is extracted as follows (see the code):
salt = pw_file_content[2:6]
Seems the first 2 bytes (after unmarshalling) are not used @debarko: seems that for the 'nomedia' file, WhatsApp mixes in the Google account and phone number (after going through the regex) to create the encryption key for the file - I think 'jabberid' is incorrect. Got my hands on an Android and tried this on the '.nomedia' file - the original Python works (I was able to use the result as the 'id' parameter passed in request-code - no SMS verification). Not sure what WA version was on the phone. Note that 'nomedia' does not contain the password - you can only use it in registration to bypass the SMS verification (also, note that this unregisters Whatsapp on the phone - needed to re-register WhatsApp on the original Android phone :()
As for code being similar to Xtract: according to the Python code, the file encryption method is used for both the 'pw' file and the 'nomedia' file - but the details are different.
The id field which is returned by the above script is some bunch of values which definitely doesn't suit the yowsap id format in the file.
And if encryption is same then it shouldn't be a problem to find the pw from the file. But alas it doesn't work :( @johnstern
Join #yosapp on freenode to chat. @johnstern
@debarko, Seems I've modified a bit the code - the original code didn't work. Oops. If you look at the decoding of 'pw', the returned value is in Base64 format:
return base64.b64encode(wa_key)
(I didn't try to decode 'pw' - getting to the sandbox seems non-trivial; at least, non-trivial for someone that knows nothing about Android). We need to do the same for id:
return base64.b64encode(do_decode(sauce2, jabberid, pw_file_content))
@johnstern you can get your pw file from your android device easily if you have a rooted device in case of a rooted device just connect your phone to a machine with a terminal in terminal type the following commands (assuming you have android sdk installed)
now you should have both the files in your current directory. try if they work
i dont know how to pull these files for a non rooted device :(
@debarko - don't have the Android anymore (and it ain't rooted)... Anyway, another small (but important detai): if you use the yowsup CLI app, it seems the 'id' goes through a processIdentity() function which performs passes it through MD5 - this will not work! you need to use the id as-is - it's already in the right format.
(I didn't use yowsup for my little experiment)
@johnstern ok cool! will try to improve on it.. and see when it works with existing apps
@debarko, Oops - sorry. I think the base64 is wrong - it should be hex instead (it's quite late and doing this from memory...)
it's cool man! thanks for all the help @johnstern
The "me" file only contains your phone number and not the Jabber ID, have you tried making it into a real JID by appending the domain to it? phonenumber@s.whatsapp.net
yes yes. i tried that. but to no gain.
@debarko, I think that @whatsappnomedia's variable names are misleading. This is what the code seems to suggest: Both 'pw' and '.nomedia' files are encoded as follows (after unmarshalling): <some header - 2 bytes> <salt - 4 bytes> <iv - 16 bytes> <encrypted data - 20 bytes> In addition, we need a fixed "sauce" (if we have salt, why not sauce...) and the a "secret" that is unique per device. Now, we compute:
key = PBKDF2(sauce + secret, salt, 16).read(16)
that is - we concatenate the "sauce" and "secret" and use them as the passphrase for PBKDF2 using "salt" as salt, and HMAC, SHA1 as MAC and digest. The first 16 means we do 16 iterations of PBKDF2 (the 2nd just cuts the output at 128 bit - which is apparently the key size).
This key is then used to decrypt the 20 bytes encrypted data:
crypt = AES.new(key, AES.MODE_OFB, iv)
return crypt.decrypt(encrypted_data + '1'*12)[:20]
iv is what we read from the file. The weird '1'*12 seems to pad the length to 32 - as the output is then cut but to 20, it doesn't seem to make much sense (in OFB mode, the message to be ec/decrypted is xored with some stream generated by AES; the extra 12 bytes can't make any difference on the actual 20 bytes of data).
This is done for both 'pw' and '.nomedia' (code reuse, I guess...), but there are some differences:
>>> "0000".encode("hex")
'30303030'
Lastly, instead of looking at "sauce1" and "sauce2" as stings, we can look at the bytes (which I think would be more portable):
>>> sauce1 = '\xc2\x99\x1e\xc2\x9b\x1d\x0c\xc2\xb8\xc3\xb7UdX\xc2\x98\xc2\x92\x03\xc2\x8bE\xc2\x97>x\xc3\x86\xc3\x95'
>>> sauce2 = 'S\x16\x0fR\x03\nD\xc2\x83\x10\xc2\x82\xc2\x9a\xc2\x8d\xc2\x8cF:!i)WA'
>>> [ord(c) for c in sauce1]
[194, 153, 30, 194, 155, 29, 12, 194, 184, 195, 183, 85, 100, 88, 194, 152, 194, 146, 3, 194, 139, 69, 194, 151, 62, 120, 195, 134, 195, 149]
>>> [ord(c) for c in sauce2]
[83, 22, 15, 82, 3, 10, 68, 194, 131, 16, 194, 130, 194, 154, 194, 141, 194, 140, 70, 58, 33, 105, 41, 87, 65]
Hope this helps
PS: if someone has a .nomedia file to play with, please post the 42 bytes here (along with the phone number and Google account) and let's see whether we can decrypt it.
WARNING: do not post details on your personal WhatsApp/phone.
Here's my .nomedia file Base64 encoded:
rO0ABXVyAAJbQqzzF/gGCFTgAgAAeHAAAAAqAAJdgEBrOesj2nLvRhPHvTOvgOEZfpElLEJeh6Aydkc5gQo1cfpN4NU0
PN 316 474 85 673 maxkovaljov at gmail dot com
This is what my C# port makes of it:
53160F52030A44C28310C282C29AC28D92F780F7
but I was unable to use that identity to request a new password, and I was also unable to get Python to run on my PC >.< so let me know if the original Python code returns something different.
PS the phone number has now been registered to a new identity, so the extracted identity from the data I posted won't work anymore.
I've tried extract your identity in Python and I've obtained three values
49202a6a49a3bb5b6d126d750063abc5---MD5
\xbd\xd4p\x1f\x17e\xe0\xa7\x19o\xebt4\xd5^oC\x95M--HEX (I think)
556f4e8bf1686252827fe7c527be8df11ecbf493--SHA1
So, check you if they're correct or not
I tried with my own files, and the pw works very well but I've not achieved to extract the id from the .nomedia
This is what I get running the Python code:
python a.py
20bdd4701f1765e0a7196feb7434d55e6f43954d
(didn't try to see if it actually works).
This is what is sent into do_decode():
jabber_id: 31485673maxkovaljov@gmail.com
sause: 53160f52030a44c28310c282c29ac28dc28c463a2169295741
nomedia file: 00025d80406b39eb23da72ef4613c7bd33af80e1197e91252c425e87a032764739810a3571fa4de0d534
(hex encoded) Within do_decode(), these are the variable's values before the call to pbkdf2:
salt: 5d80406b
iv: 39eb23da72ef4613c7bd33af80e1197e
encrypted_key: 91252c425e87a032764739810a3571fa4de0d534
and the AES encryption key is:
file_enc_key: f341b410eefde993e2eda2f5c734e979
As I've mentioned before, I think that to make this work you should use:
https://v.whatsapp.net/v2/code?cc=31&in=647485673&id=20bdd4701f1765e0a7196feb7434d55e6f43954d...
I've obtained the same result you've obtained, but using this with my files, it doesn't work, so I think there's something wrong in the code, maybe the sauce or the jabberid
stupid, but i can't find javaobj module for linux :)
Hmm... the request code that I have seems to generate a bad token:
{u'status': u'fail', u'reason': u'bad_token'}
it should work for 2.11.151, though... So sorry, can't check further whether this works or not
@satup, with your files, you should get a different result...
@satup, with your files, you should get a different result...
Yes, I know, but I don't get my result (my identity)
@droopy just learn python
@CODeRUS Thanks i have managed to do it myself as you seems only code for symbian jaja.
For decoding .nomedia which phone number format? same as appears inside "me" right? As i see 2 formats. a) international format b) local country format
Resutls shows: /// j\xa4\xd3.\xe2"\x06\xce\xeb"\xf5------- what to do with it? It is just one line. DO i need to replace this somewhere?
Can anyone help me get into a whatsapp account? or teach me to ? I would really appreciate it. E-mail me at comme.cartier@gmail.com
Isn't that like... illegal and stuff?
This may be useful for someone:
WhatsApp stores the user credentials in a 'pw' file within the sandbox, while the 'me' file contains the Jabber ID. In addition, it stores on the SD card (in "Exteranal Storage/WhatsApp/Profile Pictures/.nomedia") a token that can be used for registration without confirmation via SMS.
Here's a small Python program to get you started:
from pbkdf2 import PBKDF2 from Crypto.Cipher import AES import base64 import time import javaobj import re
sauce1 = '\xc2\x99\x1e\xc2\x9b\x1d\x0c\xc2\xb8\xc3\xb7UdX\xc2\x98\xc2\x92\x03\xc2\x8bE\xc2\x97>x\xc3\x86\xc3\x95' sauce2 = 'S\x16\x0fR\x03\nD\xc2\x83\x10\xc2\x82\xc2\x9a\xc2\x8d\xc2\x8cF:!i)WA'
def do_decode(special_sauce, jabber_id, pw_file_content): salt = pw_file_content[2:6] iv = pw_file_content[6:22] encrypted_key = pw_file_content[22:] file_enc_key = PBKDF2(special_sauce + jabber_id, salt, 16).read(16) crypt = AES.new(file_enc_key, AES.MODE_OFB, iv) return crypt.decrypt(encrypted_key + '1'*12)[:20]
def decode_pw(mefname, pwfname): jabber_id = javaobj.JavaObjectUnmarshaller(open(mefname)).readObject().jabber_id pw = javaobj.JavaObjectUnmarshaller(open(pwfname)).readObject() pw_file_content = "".join([chr(c) if c>=0 else chr(c+256) for c in pw]) wa_key = do_decode(sauce1, jabber_id, pw_file_content) return base64.b64encode(wa_key)
C = re.compile("^([17]|2[07]|3[0123469]|4[013456789]|5[12345678]|6[0123456]|8[1246]|9[0123458]|\d{3})\d*?(\d{4,6})$")
def decode_nomedia(nomedia, pn, account): g = C.match(pn) e = g.group(1) + g.group(2) jabberid = e + account pw = javaobj.JavaObjectUnmarshaller(open(nomedia)).readObject() pw_file_content = "".join([chr(c) if c>=0 else chr(c+256) for c in pw]) return do_decode(sauce2, jabberid, pw_file_content)
print "%r" % (decode_nomedia(".nomedia", "12125551234", "your.google.account@gmail.com"),)
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.