venomous0x / WhatsAPI

Interface to WhatsApp Messenger
2.59k stars 2.14k forks source link

There is a problem in requestCode which always return sent or fail #337

Closed ahmadabudawod closed 11 years ago

ahmadabudawod commented 11 years ago

I have try to request code many time but still get fail or sent as the following below ,is there any one face this problem in PHP API: [status] => fail [reason] => too_recent [retry_after] => 24936

shirioko commented 11 years ago

Gee I wonder what that could possibly mean??

too_recent => you've already requested a code retry_after => timeout in seconds, you can retry after that

I've implemented this in my latest commit https://github.com/shirioko/WhatsAPI/commit/a82446813297e321720662f1efe23abc6acda7bc

murad1981 commented 11 years ago

the problem is that the whole thing of sending a registration code not working, it gives status => sent but i do not receive SMS messages, the issue here: https://github.com/venomous0x/WhatsAPI/issues/335 is still open and still no body could find what is the reason or how to solve the problem.

shirioko commented 11 years ago

Reason? Probably WhatsApp updating or ending S40 support.

// User agent and token used in reques/registration code.
const _whatsAppUserAgent = 'WhatsApp/2.3.53 S40Version/14.26 Device/Nokia302';
const _whatsAppToken = 'PdA2DJyKoUrwLw1Bg6EIhzh502dF9noR9uFCllGk1354754753509';

Using old WP7 user agent will result give the "old_version" error and using the old token will give an invalid token hash.

We need someone with an S40 who can confirm that the registration is still working on the official client and if possible also sniff the code request. I've updated MissVenom to include user agent in the output so we can verify that as well.

ahmadabudawod commented 11 years ago

I have get a work around for this problem , if you want to solve it please follow the below steps:- 1- Download WhatsApp for new Mobile number in your iPhone or any smart device. 2- Request code from your mobile number may be it will get you message that SMS message will take 20 hour ,therefore you can use Voice call and may be it will take 5 minutes.

  1. After you get this registration code , you should set this value in your code for RegistrationCode method without need to call for RequestCode and print the response which include the password . 4.Now you can send messages through this API
shirioko commented 11 years ago

Does this actually work? Because you would expect that requestCode and registerCode need the same identity to work at all.

murad1981 commented 11 years ago

confirmed, the four steps above worked with the same identity ...

shirioko commented 11 years ago

So this means that WhatsApp still uses

md5(strrev($imei))

for it's identity?

murad1981 commented 11 years ago

do not know what's that 'coz I didn't dig into the code ...

shirioko commented 11 years ago

Well I'll be damned, it works! Identity is ignored, so it works as long as the phone number and SMS code are correct.

That's some pretty shitty security, something WhatsApp is well-known for :')

ramonv commented 11 years ago

lol, so let's say we have 1 old smartphone and 30 simcards.. you'll say its just a thing of replace SIMcard, get activation code, add activationcode to php class... replace simcard, etc..

does this really work? on the same IMEI? So this would mean IMEI isn't used until you'll register it with the received activationcode? So we still can 'make' IMEI's ourself in the phpclass.

shirioko commented 11 years ago

This would work anyway because the new generated identity uses both your phonenumber and imei code, so a different number on the same phone would generate a different identity.

old situation:

$identity = md5(strrev($imei));

new situation:

$identity = urlencode(md5($phonenumber . $imei, true));//something like this, we still have no clue how this actually works...

See here: https://github.com/venomous0x/WhatsAPI/issues/283#issuecomment-16415346

murad1981 commented 11 years ago

yes, exactly, you can use 30 sim card credentials with 1 phone ... I'm now using What's Api with my number which i'm currently using with what's app on my iPhone which I'm using its wifi address as the identity on what's api :D

JayFoxRox commented 11 years ago

I don't have any smartphone but would like to have a look at the most recent WP7 WhatsApp DLLs. Could you reupload them please? - Including the native one?

shirioko commented 11 years ago

http://mywapi.nl/whatsapi/share/ The token is in the native DLL which is compiled for ARMv7, so unless you have a WP7 device or your CPU supports virtualization you won't have much use for it.

JayFoxRox commented 11 years ago

I haven't worked with WP7 native DLLs yet. I'm new to Dis# because I can't remember what I used back in 2011 to disassemble the WP client. However, it's confusing because the IMisc interface from the native DLL does not seem to match the function order from the .NET dll.

Starting at .data:0007A284 are seven function pointers (followed by the GUID for IMisc: "53a4a6b2-424d-4198-887b-9e8d68fca9c2"). I believe them to be this:

  1. sub_15AB0
  2. sub_15158
  3. sub_155D0
  4. sub_1531C
  5. 000151D4 IMiscGetString
  6. sub_15268
  7. 000151C4 IMiscExit

The first row is rank, sorted by actual function address. Shown order is order in function pointer table.

Disassembled using Dis#:

[Guid("53a4a6b2-424d-4198-887b-9e8d68fca9c2")]
[ComVisible(true)]
public interface IMisc {
    string DumpLog();
    void Exit(uint code);
    CELL_INFO GetCellInfo();
    uint GetHr([MarshalAs(UnmanagedType.Interface)] object hackObj);
    void GetPowerStatus([MarshalAs(UnmanagedType.Struct)] ref CEPowerStatus out, bool bypassCache);
    string GetString(int idx);
    IByteBuffer GetToken(IByteBuffer prefix, IByteBuffer fuzz);
}

As you can see, Exit and GetString are not at the expected positions in the interface (not by address, not by order, not by type - I can't find any system. It seems as if Dis# just sorts the interface alphabeticly [which would be wrong..]) However, I should at least have Exit identified correctly because all the native DLL does is a call to TerminateProcess(0x42, code).

GetString at 000151D4 is also likely because it accepts values from 0 to 4 as argument and returns a copy from a string-pointer-table string (which, however, seems to contain garbage, (0x7B59C + idx \ 4) would be the actual string pointer I believe).

sub_1505C is a warning / error print function which passes the string to sub_14F30 which allocates buffers, does printf and then calls OutputDebugStringW.

If it was easier to figure out which function is actually GetToken this would be a lot easier.

Ideas / Thoughts? Who else had a look at the DLLs yet? I need this so I can actually create a new account..

//Edit: Did not know that IDA had support for .NET. I matched the functions now:

GetPowerStatus = 15AB0
GetHr = 15158 GetToken = 155D0 GetCellInfo = 1531C GetString = 151D4 DumpLog = 15268 Exit = 000151C4

This order (which IDA suggests) would confirm my findings for Exit and GetString. So I will continue work on 155D0.

To me, it appears that the new token is just a simple hash (using the windows crypto functions) of the phone number.

shirioko commented 11 years ago

Uhh it's kind of late now, I'll try to comprehend this big lump of information in the morning... It's awesome to see someone who knows what they're doing!

I've tried building a WP7 app which calls the DLLs as-is, so you wouldn't need to decompile/reverse-engineer them. I have a spare WP7 device lying around so I could use it as an interface to generate tokens from my desktop. Can't remember why I stopped working on it though...

If you need to register a number you can always request the code through an official client and use that code to register on WhatsApi, the identity is not matched, only number and sms code :)

JayFoxRox commented 11 years ago

Unfortunaly I don't have any WhatsApp device. I used android-x86 back in November of 2011 when I completed my first WhatsApp hack/client [Back then you were able to send broadcast to the server and only v1 existed, so most of this security is new to me]. In December 2011 / January 2012 WhatsApp then stopped working on android-x86.

It appears (to me) the following happens:

Whatsapp.verify.Registration.RequestCode will combine "GetBuildHash + number" (without cc). Then it passes that into GetToken. GetToken seems to be a rather thin wrapper around MD5 using PROV_RSA_FULL with CryptAcquireContext function. So far I was able to isolate most crypto imports and now I try to figure out what it actually hashes. Once the token is returned from the native part the .NET part will turn it into a lowercase hexstring - so everything normal.

It would be great if anyone could provide me with the BuildHash for the DLL shirioko posted. Also the User-Agent string for a current WP7 WhatsApp would be great. At the moment I use one which I made up: "WhatsApp/2.9.4 WP7/7.10.8773.98 Device/NOKIA-Lumia_800-H112.1402.2.3"

jonnywilliamson commented 11 years ago

@shirioko should be able to give you the UserAgent String. I tried his Miss Venom earlier and saw my own iphone one in the logs.

For info, the iphone is: USERAGENT:WhatsApp/2.8.7 iPhone_OS/6.1.3 Device/iPhone_4S

shirioko commented 11 years ago

Here you go: WhatsApp/2.9.4 WP7/7.10.8858 Device/HTC-HTC-H0002

JayFoxRox commented 11 years ago

Thanks :)

0x1332C seems to be were all the magic happens. I was wrong before. This functions seems to return function pointers only. So it should work like this: getPointers(&pArrayFunc1,&pArrayFunc2); wip..

Before that GetToken creates the crypto context, afterwards it already passes the data to be hashed to the crypto functions. Then checks the hashlength, allocates memory for the hashvalue, then requests the hashvalue, probably just converts it back to a string, then frees the memory for the hashvalue and returns it.

(I still need the BuildHash - even if I can generate it myself I would need someone who can confirm it)

shirioko commented 11 years ago

First check if generated identity is registered in WhatsApp: USERAGENT:WhatsApp/2.9.4 WP7/7.10.8858 Device/HTC-HTC-H0002 REQUEST: https://v.whatsapp.net/v2/exist?cc=31&in=650568134&id=%b3%c5VT%c5%d8%89%e9~%e5X%911WW%9f%7c%b2I%d5&lc=NL&lg=nl RESPONSE: {"status":"fail","reason":"incorrect","sms_length":6,"voice_length":6}

Second request to send an SMS code: USERAGENT:WhatsApp/2.9.4 WP7/7.10.8858 Device/HTC-HTC-H0002 REQUEST: https://v.whatsapp.net/v2/code?cc=31&in=650568134&to=31650568134&lg=nl&lc=NL&method=sms&mcc=204&mnc=004&token=5f795c7dbe10348b42d4be823fd16583&id=%b3%c5VT%c5%d8%89%e9~%e5X%911WW%9f%7c%b2I%d5 RESPONSE: {"status":"sent","length":6,"method":"sms","retry_after":1805}

Third request to verify SMS code (the number is fake so I had to enter something) USERAGENT:WhatsApp/2.9.4 WP7/7.10.8858 Device/HTC-HTC-H0002 REQUEST: https://v.whatsapp.net/v2/register?cc=31&in=650568134&id=%b3%c5VT%c5%d8%89%e9~%e5X%911WW%9f%7c%b2I%d5&code=123456&lc=NL&lg=nl RESPONSE: {"status":"fail","reason":"mismatch","retry_after":2}

JayFoxRox commented 11 years ago

Thanks, but that doesn't really help - the token is just an MD5 and can't be reversed. I need the BuildHash of the DLL which is some kind of checksum over the PE sections.

I just extracted the BuildHash function and spend some time looking into Mono. I came up with this:

Expected BuildHash for WhatsApp.dll (2.9.4.0): 21a31a2d9dbdc9a8ce324ef2df918064fd26e30a Expected BuildHash for WhatsAppCommon.dll (2.9.4.0): b32a995213f1dd6006e15818c672b715d5d24828

You can find my code to generate these here: http://pastebin.com/hk5F8xsp

It's mostly straight from the decompiler. But it had some problems so it might be flawed. Also it's not clean - just gets the job done.. Which file was the source for the BuildHash in the past?

shirioko commented 11 years ago

I've added the whole WP7 WhatsApp rar archive to my website, you can take a look at that if it's any help :) http://mywapi.nl/whatsapi/share/whatsappwp7.rar

JayFoxRox commented 11 years ago

byte[] unk = { 0xBF,0xAB,0x64,0x89,0x7C,0xF6,0xD9,0x12,0xEC,0xED, 0xFE,0x72,0x58,9,0xD0,0xF9,0xEE,0x20,0xB1,0x4A, 0x39,0x51,0x98,0xC9,0x7F,0x14,0x1B,0xDC,0,0x6D, 0xB,0xD1,0x66,0x5D,0x53,0xEB,0xC6,0x86,0x4B,0xA3 }; // .WAobs:00085B48

I believe this has to do with the token generation.

Here is my understanding of the GetToken function so far:

  1. .text:00015640 Aquire a Crypto Context with PROV_RSA_FULL
  2. .text:00015688 CryptCreateHash(provider,CALG_MD5, ...);
  3. .text:000159E4 R1 = Pointer to the array I posted above, R2 = 0x28 (40, probably length of array in bytes, note that the old token prefixes were also 40 bytes [but ASCII / Base64]!)
  4. .text:00015770 CryptHashData the array above
  5. .text:000157F0 CryptHashData what I assume to be BuildHash + number
  6. Token must be complete by now!
  7. .text:00015A30 CryptGetHashParam(hHash, HP_HASHSIZE, ...);
  8. .text:00015844 Allocate necessary memory for the hash
  9. .text:00015890 CryptGetHashParam(hHash, HP_HASHVAL, ...);
  10. Now probably just moves back the data to the .NET arrays
  11. .text:000159B0 releaseCryptoContext and free of hash

//Edit: My code still does not work though.. Won't do anything unless someone confirms (or atleast tells me I'm wrong) my BuildHash. - I need to know which BuildHash is used in RequestCode.

JayFoxRox commented 11 years ago

I checked the disassembled code about a hundred times now. I'm very sure that what I previously posted is correct. The token above is the new token.

But it still doesn't work for me. So I guess either IDA is screwing up, my http request is bad or the BuildHash is not correct.. [Or WhatsAppNative.dll is buggy because encoding differences in the DLLs - but that is highly unlikely]

//Edit: Maybe .WAobs is encrypted?! .text:00013970 is called from DllEntryPoint and references the first and last byte from .WAobs =Looks like we are doomed! If you want to figure out the token I'd recommend loading the DLL yourself, then reading it's memory at .WAobs:00085B48 which hopefully is a base64 string at that point.

shirioko commented 11 years ago

I can provide you with the 2.8.2 DLLs if that's any help? The hashes for that are in yowsup's source: https://github.com/tgalal/yowsup/blob/master/src/Yowsup/Common/Http/warequest.py#L38

("WhatsApp/2.8.2 WP7/7.10.8773.98 Device/NOKIA-Lumia_800-H112.1402.2.3", 
                "k7Iy3bWARdNeSL8gYgY6WveX12A1g4uTNXrRzt1H"+"889d4f44e479e6c38b4a834c6d8417815f999abe{phone}"),
JayFoxRox commented 11 years ago

Yes, that would be helpful as I can verify my BuildHash code probably :)

But by now I'm pretty sure that .WAobs and maybe some other sections are encrypted or scrambled. They are read+write which is unlikely and even pointers which probably should be strings seem to end up in random data. Also the entire section is full of data with almost no 0xFF or 0x00 bytes.

If you have a windows phone you can test this easily though by loading the DLL and reading back its contents in memory.

shirioko commented 11 years ago

It's up! http://mywapi.nl/whatsapi/share/wapp_wp7_282.rar

Regarding loading the DLL into memory and reading back it's contents, can you PM me on how to do this? :)

EDIT Oh damn it I just realized 2.8.2 doesn't have a native DLL :/ Bummer

JayFoxRox commented 11 years ago

Thanks for helping!

I don't have .NET 4.0 in my VM, so no ilspy. Dis# fails to disassemble either WhatsApp.dll (WhatsAppCommon.dll works fine) so I can't have a look at the decompiled 2.8.2.0 BuildHash.Create() as it was still in WhatsApp.dll at that point (it's in WhatsAppCommond.dll now [2.9.4.0]).

I only checked the disassembly with DILE and it looks to be exactly the same in 2.8.2 and 2.9.4. Just a SHA1 of the ".rsrc" section.

However, I'm not able to generate the same hash which is in yowsup using my own tool. One thing I noticed is that mono and windows HashFinal() return different things after calling it multiple times. Calling it more than once will result in different output than calling it the first time [why is that?], but even worse, it's different the second time on each platform too. The first returned value is a proper SHA1 though [tested with known plaintext / hash], so I trust my tool.

I'm not sure why my BuildHash shouldn't work as I pulled it out of the decompiled code + it executes and parses the PE fine.

I would have loved to throw my own 2.8.2 buildhash at the whatsapp code request but that only checks the user agent and earlys-out with "old_version" so it won't verify my token / buildhash.

To load the DLL yourself you can have a look at WhatsAppCommon.dll -> WhatsApp.NativeInterfaces which is the DLL loader. It will use RegisterComDll("WhatsAppNative.dll", GUIDs) to register all the interfaces the DLL provides. You should be able to copy the decompiled code if your decompiler is any good. If you want to do any calls you will need the proper IMisc interface etc. though. That can be found at WhatsAppCommon.dll -> WhatsAppNative However, make sure your decompiler doesn't sort these imports by alphabetical order but by their order which they have in the file. Check one of my previous posts for the proper order of IMisc.

You should then be able to call GetToken already. Signature of GetToken is: IByteBuffer GetToken(IByteBuffer tokenPrefix, IByteBuffer buildHashNumber)

I'm not sure how easy it is to debug on a windows phone. But if you have a proper debugger you can probably set a breakpoint in GetToken and jump to the .WAobs section of the WhatsAppNative.dll to check if the token was decrypted. Additionally you can also create a breakpoint at .text:00014C44 which is CryptHashData. At that point R1 is a pointer to bytes which will be hashed, R2 the number of bytes to be hashed.

CryptHashData will be called twice from GetToken:

shirioko commented 11 years ago

I've decompiled both DLLs from 2.8.2 for you using ILSpy you can download the complete package in ilspy.rar or look into specific files here: http://mywapi.nl/whatsapi/share/ilspy/whatsappcommon_dll/WhatsApp/

EDIT: As you can see the first part of the registration token can be found in Constants.cs

JayFoxRox commented 11 years ago

Yeah I noticed that token already in WhatsAppCommon.dll which Dis# had no problems with.

I also compared the BuildHash functions. There is one subtle difference - a bug in fact..

Decompiler differences aside, what happens is this (Header described at http://msdn.microsoft.com/en-us/library/ms809762.aspx ):

This explains why my BuildHash tool was not able to get the same hash for 2.8.2

This is what my new tool spits out (for the 2.8.2 WhatsApp.dll):

BuildHash (2.9.4 Algorithm) is 835e38484a0060bdf99eceb38c53d435de6df5a8 BuildHash (2.8.2 Algorithm) is 889d4f44e479e6c38b4a834c6d8417815f999abe

This is what my new tool spits out (for the 2.9.4 WhatsApp.dll):

BuildHash (2.9.4 Algorithm) is 21a31a2d9dbdc9a8ce324ef2df918064fd26e30a BuildHash (2.8.2 Algorithm) is a0338e1d716a8cb4a52835698a3258c8eff9eef9

It's kinda safe to assume that 21a31a2d9dbdc9a8ce324ef2df918064fd26e30a is the new BuildHash. The problem is probably still the token prefix from the native dll which might be encrypted.

I attempted this token in yowsup but it still did not work:

        ("WhatsApp/2.9.4 WP7/7.10.8858 Device/HTC-HTC-H0002", 
    "\xBF\xAB\x64\x89\x7C\xF6\xD9\x12\xEC\xED\xFE\x72\x58\x09\xD0\xF9\xEE\x20\xB1\x4A\x39\x51\x98\xC9\x7F\x14\x1B\xDC\x00\x6D\x0B\xD1\x66\x5D\x53\xEB\xC6\x86\x4B\xA3"+"21a31a2d9dbdc9a8ce324ef2df918064fd26e30a{phone}"),

What we need is probably the first part / token array - but decrypted. If I had a proper ARM decompiler I would probably work on that - but with desquirr you get a lot of crap for ARM. It was okay for the GetToken function but it won't be enough for the huge function which I assume to be the decryption / descrambler code. Simply executing the decryption on a windows phone and reading back the token is way easier.

//Edit: I looked at the decryption function again - if I have some free time tonight I will try rewriting it in C using some emulation framework I worked on in the past.. That might work here because the function is platform independent

shirioko commented 11 years ago

I would gladly run the app to decrypt the token on one of my WP7 devices, I'll look into it when I get home in a few hours

ulihecht commented 11 years ago

I'm still not sure if I understood what's going on here, so I try to summarize:

Is this correct?

shirioko commented 11 years ago

Android also uses SMS & voice registration, it's just that its Java code has been obfuscated making it next to impossible to work with.

ulihecht commented 11 years ago

But everything else is correct? What do think about the idea to use an S40 emulator?

JayFoxRox commented 11 years ago

Mostly. Yes.

JayFoxRox commented 11 years ago

I can't figure out what's wrong.. I know.. it's a mess - but it's just a dirty hack, so don't judge the code please:

http://www.jannikvogel.de/scratchpad/WhatsApp/2.9.4-Token/TokenPrefix/

http://www.jannikvogel.de/scratchpad/WhatsApp/2.9.4-Token/BuildHash/

http://www.jannikvogel.de/scratchpad/WhatsApp/2.9.4-Token/

If you want to help you can try checking if my flags in arm.h are generated properly. Also, you can try comparing decrypted.c to disassembly and look for differences or logic flaws / missunderstanding of instructions in my emulation. If you REALLY want to help, run this on an actual device and set a breakpoint at .text:00013CAC. Then tell me what you read back at 0x85B48 (40 bytes) and 0x854B0 (String or DWORD, so a couple of bytes - at least 4).

shirioko commented 11 years ago

I can get you remote desktop access to my windows 7 Ultimate home server with VS2012, .NET4.5, WP8 SDK and my WP7 device connected to it, guess that should give you some more stuff to play around with.

Let me know if you'd like that, I'll set up the required software on the machine.

I can't get this stupid native DLL to load in my WP7 app, hopefully you'll have more luck with it :)

ulihecht commented 11 years ago

Thanks, JayFoxRox. That clearified everything ;)

JayFoxRox commented 11 years ago

I just noticed this:

.text:00014E2C sub_14E2C ; CODE XREF: DllEntryPoint+20p .text:00014E2C MOV R3, 0xFFFFCFFF .text:00014E30 LDR R2, [R3,#-0x7AB]

Maybe IDA also fails to relocate the file properly? I highly doubt that this would work on an actual device.

The code would do something like this:

unsigned int r2 = (unsigned int)(-0x37AC);

As negative memory addresses don't exist (on ARM), this is probably wrong..

//Edit: Tried disassembling with different ARM instructions sets now and checked the file headers. No relocation or different instruction at that address. Mysterious.. - I don't get it

jonnywilliamson commented 11 years ago

As someone who understands what you are doing when you explain it, but can't provide any help - this is fascinating watching the "hunt" for the solution!

:)

shirioko commented 11 years ago

I've tried to load the DLL into a homebrew WP7 app and even constructing the app from within another app

WhatsApp.App app = new WhatsApp.App();

But I keep getting this error:

NativeException was unhandled
DLL registration, hr=0x800700c1

Stack trace:

   at WhatsApp.NativeInterfaces.CheckHr(UInt32 hr, Func`1 msg)
   at WhatsApp.NativeInterfaces.CheckHr(UInt32 hr, String msg)
   at WhatsApp.NativeInterfaces.Initialize()
   at WhatsApp.App..ctor()
   at PhoneApp1.MainPage..ctor()
   at System.Reflection.RuntimeConstructorInfo.InternalInvoke(RuntimeConstructorInfo rtci, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
   at System.Reflection.RuntimeConstructorInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
   at System.Activator.InternalCreateInstance(Type type, Boolean nonPublic, StackCrawlMark& stackMark)
   at System.Activator.CreateInstance(Type type)
   at System.Windows.Navigation.PageResourceContentLoader.BeginLoad_OnUIThread(AsyncCallback userCallback, PageResourceContentLoaderAsyncResult result)
   at System.Windows.Navigation.PageResourceContentLoader.<>c__DisplayClass4.<BeginLoad>b__0(Object args)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(RuntimeMethodInfo rtmi, Object obj, BindingFlags invokeAttr, Binder binder, Object parameters, CultureInfo culture, Boolean isBinderDefault, Assembly caller, Boolean verifyAccess, StackCrawlMark& stackMark)
   at System.Reflection.RuntimeMethodInfo.InternalInvoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture, StackCrawlMark& stackMark)
   at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
   at System.Delegate.DynamicInvokeOne(Object[] args)
   at System.MulticastDelegate.DynamicInvokeImpl(Object[] args)
   at System.Delegate.DynamicInvoke(Object[] args)
   at System.Windows.Threading.DispatcherOperation.Invoke()
   at System.Windows.Threading.Dispatcher.Dispatch(DispatcherPriority priority)
   at System.Windows.Threading.Dispatcher.OnInvoke(Object context)
   at System.Windows.Hosting.CallbackCookie.Invoke(Object[] args)
   at System.Windows.Hosting.DelegateWrapper.InternalInvoke(Object[] args)
   at System.Windows.RuntimeHost.ManagedHost.InvokeDelegate(IntPtr pHandle, Int32 nParamCount, ScriptParam[] pParams, ScriptParam& pResult)

any thoughts?

EDIT: NativeInterfaces constructor:

public static void Initialize()
{
    lock (NativeInterfaces.initLock)
    {
        OEMPublicDirectory.Initialize();
        string[] array = new string[]
        {
            "9eb98dc6-afda-460c-9949-d17135c07612",
            "c28a9cd1-963b-4660-929d-ea82e0baf4d7",
            "7b947cca-f203-41cc-aa9b-96952eae168a",
            "f990f7de-fd2c-46f1-ab07-50e20b9a1ebc",
            "932540fe-c52e-47bd-9643-6b462648bca1",
            "7263fc58-6ca4-4708-a047-17152fed7141"
        };
        string[] array2 = array;
        for (int i = 0; i < array2.Length; i++)
        {
            string text = array2[i];
            uint hr = ComBridge.RegisterComDll("WhatsAppNative.dll", new Guid(text));
            NativeInterfaces.CheckHr(hr, "DLL registration");
        }
        NativeInterfaces.init = true;
    }
}

And the CheckHR method:

public static void CheckHr(uint hr, Func<string> msg)
{
    if ((hr & 2147483648u) != 0u)
    {
        throw new NativeException(hr, string.Format("{0}, hr=0x{1}", msg.Invoke() ?? "Native function failed", hr.ToString("x")));
    }
}
JayFoxRox commented 11 years ago

Are you sure you have the DLL in your app path? Are you allowed to use InteropServices [Manifest exists etc.]? Also, are you running this on an actual phone? 0x800700C1 seems to be BadImageFormatException - this would happen when trying to run ARM code on an x86 system.

The code looks fine to me.

shirioko commented 11 years ago

Holy crap you were right, just ran this on my HD2 and it gave no errors :o

WhatsApp.NativeInterfaces.Initialize();
ByteBuffer inp = new ByteBuffer();
IByteBuffer res = WhatsApp.NativeInterfaces.Misc.GetToken(inp as IByteBuffer, inp as IByteBuffer);

Now let's see what the next move would be..

JayFoxRox commented 11 years ago

You are using it wrong. Try this:

  WhatsApp.NativeInterfaces.Initialize();
  string number = "*YourNumber*";
  string s4 = "21a31a2d9dbdc9a8ce324ef2df918064fd26e30a"; 
  ByteBuffer inp = new ByteBuffer();
  inp.put(Encoding.UTF8.GetBytes(s4 + number));
  IByteBuffer res = WhatsApp.NativeInterfaces.Misc.GetToken(null as IByteBuffer, inp as IByteBuffer);
  // Now convert res back to a hex-string or output all bytes

It should be the same code whatsapp calculates. Try setting your debugger to native and read back the memory at the address I mentioned above. Then we should be able to register new clients too :)

shirioko commented 11 years ago

Ooooooh I think we're getting somewhere... :D

Settings.RecoveryToken
{byte[20]}
    [0]: 0
    [1]: 191
    [2]: 27
    [3]: 131
    [4]: 247
    [5]: 234
    [6]: 89
    [7]: 254
    [8]: 234
    [9]: 63
    [10]: 133
    [11]: 228
    [12]: 41
    [13]: 67
    [14]: 102
    [15]: 236
    [16]: 47
    [17]: 22
    [18]: 53
    [19]: 80
Convert.ToBase64String(Settings.RecoveryToken)
"AL8bg/fqWf7qP4XkKUNm7C8WNVA="

@JayFoxRox you sure you don't want to play around on Remote Desktop? ^^

jonnywilliamson commented 11 years ago

Well if that doesn't look like a Whatsapp password I'll eat my hat!

JayFoxRox commented 11 years ago

Which array is that? That looks like the token-hash send to WhatsApp. Still not the one we need to calculate it (what I refer to as TokenPrefix). I would like to test on your server - but your domain was not reachable for the last days. I thought you were still working on it.

//Edit: That base64 string appears wrong - the one in memory (tokenPrefix, the array we look for) will already be one - no need to encode that. What you get back from GetToken() is actually the token for your number + buildhash + tokenPrefix (first argument or the one we want to read from the dll - currently ALWAYS the one from the dll as first argument is always null)

shirioko commented 11 years ago
            WhatsApp.NativeInterfaces.Initialize();
            string number = "650568134";
            string s4 = "21a31a2d9dbdc9a8ce324ef2df918064fd26e30a";
            IByteBuffer inp = new ByteBuffer() as IByteBuffer;
            inp.Put(System.Text.Encoding.UTF8.GetBytes(s4 + number));
            IByteBuffer res = WhatsApp.NativeInterfaces.Misc.GetToken(null as IByteBuffer, inp as IByteBuffer);
            byte[] output = res.Get();
            string data = System.Text.Encoding.UTF8.GetString(output);
            string data2 = Convert.ToBase64String(output);

output = {byte[16]}

[1]: 121
[2]: 92
[3]: 125
[4]: 190
[5]: 16
[6]: 52
[7]: 139
[8]: 66
[9]: 212
[10]: 190
[11]: 130
[12]: 63
[13]: 209
[14]: 101
[15]: 131

data = _y}�4�BԾ�?�e� data2 = X3lcfb4QNItC1L6CP9Flgw==

EDIT: This seems to be the interesting part of the code (in Registration.RequestCode)

    string buildHash = Registration.GetBuildHash();
    IByteBuffer prefix = Registration.NewByteBuffer(null);
    IByteBuffer fuzz = Registration.NewByteBuffer(Encoding.get_UTF8().GetBytes(buildHash + number));
    IByteBuffer token = NativeInterfaces.Misc.GetToken(prefix, fuzz);
    string text4 = token.Get().ToHexString().ToLower();
JayFoxRox commented 11 years ago

Used it wrong again ;) You need a hexstring and compare that token to one you get from a phone registration using your actual phone / whatsapp. That verifies that the used function and logic works.

This is how you format the output: http://codepad.org/Os7y0dyN As you can see, this token is correct as it matches one in your previous posts.

So the native DLL works fine. Time to dump the token from the binary now by setting a breakpoint at the address I mentioned above or reading back the memory directly.

//Edit-1: This also confirms that my buildHash is correct! 2.9.4.0 BuildHash is verified to be: "21a31a2d9dbdc9a8ce324ef2df918064fd26e30a"

//Edit-2: The code you just edit-ed in is pretty much the one which I posted before - which you just ran to get the token above your edit ;)

PS: Might not be too smart to post your phone number online.