I am reversing an old Path of Exile client with the purpose of building an emulator. I managed to reach the character select screen in a newer, 64-bit client but I am struggling to make the same progress in an older 32-bit client. FWIW they use the same encryption setup, CryptoPP library and Salsa20 with public key encryption. I'm just trying to NOP the encrypt functions so I can ignore it.

I found function calls to Call EDX both shortly before send and shortly after recv and these are the only function calls that seem likely to be crypt related. After NOPing the two functions, I did indeed confirm that the first login packet sends the username in plaintext so I think my encryption skip is good. But the client crashes upon receiving my second server packet. The unmodified client complains at this point about being unable to deserialise the packet I am sending.

I am referencing a huge (600MB) collection of decrypted packets someone very generously shared with me in order to craft my server responses.

My question is this - where should I look next? I am thinking of setting API Monitor to just watch every call made by the exe to see the last few things that happen as so far I've only been monitoring the network related calls. Or should I first confirm that the calls I'm NOPing are the only crypt related functions? I'm still new to this and unsure where my time is best spent. Thanks for any general insight you can provide!

2 Answers 2


Depending on the calling convention, the indirect call you NOPped out might end in "RET nn". IIRC this is in fact the case in Microsoft's variant of the x86 thiscall convention. If you NOP the call out, ESP is wrong after the call. This is harmless if ESP is no longer used in that function, and it ends in a standard epilog that uses LEAVE or MOV ESP, EBP, but it can also cause very weird crashes.

Another possibility is that the function you do no longer call returns a C++ object. The calling convention in this case is that the called function constructs the object, but the callee has to destruct it later. If you NOP out the construction, it will result in destructing uninitialized memory, which is also likely to crash.

In your case, I don't think its the second problem, because that would manifest on x64 and x86, and not just on 32-bit binaries - but I won't make any hard claims, because destructing an uninitialized object might luckily not crash by chance.


Turns out I was looking at the wrong part of the equation. The encrypt/decrypt is actually being bypassed correctly, but I was still sending the key as the first packet since that is what works in later versions. In this particular client, I had to skip sending the key altogether and just start with the "Login Success!" packet. Once I did this, I got to the character select. Thanks for the responses! I'm in!  Just 1 billion more steps to go...

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.