From 71a50ce4a1a39766414993da9310675fae5bb6fa Mon Sep 17 00:00:00 2001 From: George Hazan Date: Sat, 19 Mar 2016 17:21:24 +0000 Subject: built-in skylogin library (gotten from https://github.com/msndevs/skylogin.git) git-svn-id: http://svn.miranda-ng.org/main/trunk@16512 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c --- protocols/MSN/msn.vcxproj | 8 + protocols/MSN/src/msn_auth.cpp | 133 +++------- protocols/MSN/src/skylogin/README.md | 2 + protocols/MSN/src/skylogin/common.c | 92 +++++++ protocols/MSN/src/skylogin/common.h | 128 +++++++++ protocols/MSN/src/skylogin/crc.c | 113 ++++++++ protocols/MSN/src/skylogin/crc.h | 6 + protocols/MSN/src/skylogin/credentials.c | 163 ++++++++++++ protocols/MSN/src/skylogin/credentials.h | 3 + protocols/MSN/src/skylogin/login.c | 414 ++++++++++++++++++++++++++++++ protocols/MSN/src/skylogin/login.h | 2 + protocols/MSN/src/skylogin/objects.c | 252 ++++++++++++++++++ protocols/MSN/src/skylogin/objects.h | 136 ++++++++++ protocols/MSN/src/skylogin/platform.h | 6 + protocols/MSN/src/skylogin/platform_w32.c | 195 ++++++++++++++ protocols/MSN/src/skylogin/random.c | 178 +++++++++++++ protocols/MSN/src/skylogin/random.h | 7 + protocols/MSN/src/skylogin/rc4comm.c | 83 ++++++ protocols/MSN/src/skylogin/rc4comm.h | 3 + protocols/MSN/src/skylogin/skylogin.c | 165 ++++++++++++ protocols/MSN/src/skylogin/skylogin.h | 57 ++++ protocols/MSN/src/skylogin/uic.c | 105 ++++++++ protocols/MSN/src/skylogin/uic.h | 3 + 23 files changed, 2161 insertions(+), 93 deletions(-) create mode 100644 protocols/MSN/src/skylogin/README.md create mode 100644 protocols/MSN/src/skylogin/common.c create mode 100644 protocols/MSN/src/skylogin/common.h create mode 100644 protocols/MSN/src/skylogin/crc.c create mode 100644 protocols/MSN/src/skylogin/crc.h create mode 100644 protocols/MSN/src/skylogin/credentials.c create mode 100644 protocols/MSN/src/skylogin/credentials.h create mode 100644 protocols/MSN/src/skylogin/login.c create mode 100644 protocols/MSN/src/skylogin/login.h create mode 100644 protocols/MSN/src/skylogin/objects.c create mode 100644 protocols/MSN/src/skylogin/objects.h create mode 100644 protocols/MSN/src/skylogin/platform.h create mode 100644 protocols/MSN/src/skylogin/platform_w32.c create mode 100644 protocols/MSN/src/skylogin/random.c create mode 100644 protocols/MSN/src/skylogin/random.h create mode 100644 protocols/MSN/src/skylogin/rc4comm.c create mode 100644 protocols/MSN/src/skylogin/rc4comm.h create mode 100644 protocols/MSN/src/skylogin/skylogin.c create mode 100644 protocols/MSN/src/skylogin/skylogin.h create mode 100644 protocols/MSN/src/skylogin/uic.c create mode 100644 protocols/MSN/src/skylogin/uic.h diff --git a/protocols/MSN/msn.vcxproj b/protocols/MSN/msn.vcxproj index 87e7feff21..603d726bdc 100644 --- a/protocols/MSN/msn.vcxproj +++ b/protocols/MSN/msn.vcxproj @@ -29,5 +29,13 @@ Sync + + libeay32.lib;%(AdditionalDependencies) + + + + NotUsing + + diff --git a/protocols/MSN/src/msn_auth.cpp b/protocols/MSN/src/msn_auth.cpp index e1c4b1713f..3e05906b30 100644 --- a/protocols/MSN/src/msn_auth.cpp +++ b/protocols/MSN/src/msn_auth.cpp @@ -24,6 +24,11 @@ along with this program. If not, see . #include "msn_ieembed.h" #include "des.h" +extern "C" +{ + #include "skylogin\skylogin.h" +}; + #define LOGIN_POST_PARAMS "client_id=00000000480BC46C&scope=service%3A%3Askype.com%3A%3AMBI_SSL&response_type=token&redirect_uri=https%3A%2F%2Flogin.live.com%2Foauth20_desktop.srf" #define AUTH_URL "https://login.live.com/oauth20_authorize.srf?"LOGIN_POST_PARAMS #define POST_URL "https://login.live.com/ppsecure/post.srf?"LOGIN_POST_PARAMS @@ -33,18 +38,6 @@ along with this program. If not, see . typedef BOOL (*pfnInternetGetCookieExA)(LPCSTR, LPCSTR, LPSTR, LPDWORD, DWORD, LPVOID); pfnInternetGetCookieExA fpInternetGetCookieExA = NULL; - -/* SkyLogin Prototypes */ -typedef void* SkyLogin; -typedef SkyLogin (*pfnSkyLogin_Init)(); -typedef void (*pfnSkyLogin_Exit)(SkyLogin pInst); -typedef int (*pfnSkyLogin_LoadCredentials)(SkyLogin pInst, char *pszUser); -typedef int (*pfnSkyLogin_PerformLogin)(SkyLogin pInst, char *pszUser, char *pszPass); -typedef int (*pfnSkyLogin_CreateUICString)(SkyLogin pInst, const char *pszNonce, char *pszOutUIC); -typedef int (*pfnSkyLogin_PerformLoginOAuth)(SkyLogin pInst, const char *OAuth); -typedef int (*pfnSkyLogin_GetCredentialsUIC)(SkyLogin pInst, char *pszOutUIC); -typedef char *(*pfnSkyLogin_GetUser)(SkyLogin pInst); - #define LOAD_FN(name) (##name = (pfn##name)GetProcAddress(hLibSkylogin, #name)) static const char defaultPassportUrl[] = "https://login.live.com/RST2.srf"; @@ -661,48 +654,25 @@ CMStringA CMsnProto::HotmailLogin(const char* url) int CMsnProto::MSN_SkypeAuth(const char *pszNonce, char *pszUIC) { int iRet = -1; - pfnSkyLogin_Init SkyLogin_Init; - pfnSkyLogin_Exit SkyLogin_Exit; - pfnSkyLogin_LoadCredentials SkyLogin_LoadCredentials; - pfnSkyLogin_PerformLogin SkyLogin_PerformLogin; - pfnSkyLogin_CreateUICString SkyLogin_CreateUICString; - - HMODULE hLibSkylogin = LoadLibrary(_T("Plugins\\skylogin.dll")); - if (hLibSkylogin) { - - // load function pointers - if (!LOAD_FN(SkyLogin_Init) || - !LOAD_FN(SkyLogin_Exit) || - !LOAD_FN(SkyLogin_LoadCredentials) || - !LOAD_FN(SkyLogin_PerformLogin) || - !LOAD_FN(SkyLogin_CreateUICString)) - { - FreeLibrary(hLibSkylogin); - return -2; - } - // Perform login - SkyLogin hLogin = SkyLogin_Init(); - if (hLogin) { - char szPassword[100]; - if (!db_get_static(NULL, m_szModuleName, "Password", szPassword, sizeof(szPassword))) { - if (SkyLogin_LoadCredentials(hLogin, MyOptions.szEmail) || - SkyLogin_PerformLogin(hLogin, MyOptions.szEmail, szPassword)) - { - if (SkyLogin_CreateUICString(hLogin, pszNonce, pszUIC)) - iRet = 1; - } - else - iRet = 0; - SkyLogin_Exit(hLogin); + // Perform login + SkyLogin hLogin = SkyLogin_Init(); + if (hLogin) { + iRet = 0; + + char szPassword[100]; + if (!db_get_static(NULL, m_szModuleName, "Password", szPassword, sizeof(szPassword))) { + if (SkyLogin_LoadCredentials(hLogin, MyOptions.szEmail) || + SkyLogin_PerformLogin(hLogin, MyOptions.szEmail, szPassword)) + { + if (SkyLogin_CreateUICString(hLogin, pszNonce, pszUIC)) + iRet = 1; } - else - iRet = 0; + + SkyLogin_Exit(hLogin); } - else - iRet = -3; - FreeLibrary(hLibSkylogin); } + return iRet; } @@ -715,52 +685,29 @@ int CMsnProto::MSN_SkypeAuth(const char *pszNonce, char *pszUIC) int CMsnProto::LoginSkypeOAuth(const char *pRefreshToken) { int iRet = -1; - pfnSkyLogin_Init SkyLogin_Init; - pfnSkyLogin_Exit SkyLogin_Exit; - pfnSkyLogin_LoadCredentials SkyLogin_LoadCredentials; - pfnSkyLogin_PerformLoginOAuth SkyLogin_PerformLoginOAuth; - pfnSkyLogin_GetCredentialsUIC SkyLogin_GetCredentialsUIC; - pfnSkyLogin_GetUser SkyLogin_GetUser; - - HMODULE hLibSkylogin = LoadLibrary(_T("Plugins\\skylogin.dll")); - if (hLibSkylogin) { - // load function pointers - if (!LOAD_FN(SkyLogin_Init) || - !LOAD_FN(SkyLogin_Exit) || - !LOAD_FN(SkyLogin_LoadCredentials) || - !LOAD_FN(SkyLogin_PerformLoginOAuth) || - !LOAD_FN(SkyLogin_GetCredentialsUIC) || - !LOAD_FN(SkyLogin_GetUser)) - { - FreeLibrary(hLibSkylogin); - return -2; - } - // Perform login - SkyLogin hLogin = SkyLogin_Init(); - if (hLogin) { - char szLoginToken[1024]; - if (RefreshOAuth(pRefreshToken, "service::login.skype.com::MBI_SSL", szLoginToken) && - SkyLogin_PerformLoginOAuth(hLogin, szLoginToken)) - { - char szUIC[1024]; - if (SkyLogin_GetCredentialsUIC(hLogin, szUIC)) { - char *pszPartner; - - replaceStr(authUIC, szUIC); - iRet = 1; - if (pszPartner = SkyLogin_GetUser(hLogin)) - setString("SkypePartner", pszPartner); - } + // Perform login + SkyLogin hLogin = SkyLogin_Init(); + if (hLogin) { + char szLoginToken[1024]; + if (RefreshOAuth(pRefreshToken, "service::login.skype.com::MBI_SSL", szLoginToken) && + SkyLogin_PerformLoginOAuth(hLogin, szLoginToken)) + { + char szUIC[1024]; + if (SkyLogin_GetCredentialsUIC(hLogin, szUIC)) { + char *pszPartner; + + replaceStr(authUIC, szUIC); + iRet = 1; + if (pszPartner = SkyLogin_GetUser(hLogin)) + setString("SkypePartner", pszPartner); } - else - iRet = 0; - SkyLogin_Exit(hLogin); - } + } else - iRet = -3; - FreeLibrary(hLibSkylogin); - } + iRet = 0; + SkyLogin_Exit(hLogin); + } + return iRet; } diff --git a/protocols/MSN/src/skylogin/README.md b/protocols/MSN/src/skylogin/README.md new file mode 100644 index 0000000000..2139b870d7 --- /dev/null +++ b/protocols/MSN/src/skylogin/README.md @@ -0,0 +1,2 @@ +# skylogin +C Code to login to Skype for UIC generation needed for msnp24 diff --git a/protocols/MSN/src/skylogin/common.c b/protocols/MSN/src/skylogin/common.c new file mode 100644 index 0000000000..4aa14956e8 --- /dev/null +++ b/protocols/MSN/src/skylogin/common.c @@ -0,0 +1,92 @@ +/* + * Skype Login + * + * Based on: + * FakeSkype : Skype reverse engineering proof-of-concept client + * Ouanilo MEDEGAN (c) 2006 http://www.oklabs.net + * pyskype : Skype login Python script by uunicorn + * + * Written by: leecher@dose.0wnz.at (c) 2015 + * + * Module: Common stuff, especially Skype Modulus + * + */ +#include "common.h" + +char *SkypeModulus1536[] = {"c095de9e868dc9fe1de94ab5e38e8dbdcae7e6249ef147de503f3e1c76e65af06f7714872f3527ee16410170196e4b2277db206827505bc48b4b63159f8eb0d56d14de686e5f6840e32522f8b7dafc6b901b83495757f4269b59440bc7824d4543eae2b00b9d4d21b0b056ae53d6cc6c3a35a5b10e72710cad00db5a42903e277e361cd1761a074afe997cc4a2c77427854ea1176da481cadb981ee145711c7160c5b31f5194f64ec919bf57dc544656f39bad7bbdacb6e46f22c30173df2ea7", + "a8f223612f4f5fc81ef1ca5e310b0b21532a72df6c1af0fbec87304aec983aab5d74a14cc72e53ef7752a248c0e5abe09484b597692015e796350989c88b3cae140ca82ccd9914e540468cf0edb35dcba4c352890e7a9eafac550b3978627651ad0a804f385ef5f4093ac6ee66b23e1f8202c61c6c0375eeb713852397ced2e199492aa61a3eab163d4c2625c873e95cafd95b80dd2d8732c8e25638a2007acfa6c8f1ff31cc2bc4ca8f4446f51da404335a48c955aaa3a4b57250d7ba29700b", + "aa4bc22ba5b925573c48bf886efad103a37d697283a3d37b8bf5a3eb2d09a9ae73e6905fcb3c6af06e4170b7a1856c70eab972cd3a468a28d7a87ceaad2404126dd5843f8895a0cfd9b07085afe60b8ae391a703479846d800737ab02fca5ead5673f416d5fb4a95e1d27bb4b7ca5411e74e98623f563b1d3709d749b3ee6d87242a8da04f39fd61ea679acc8e28601dadcc4434918dc544cd365f7b897600b3fb62875f4517ae32601764ae8d28b924074e47ebc2bcaaa42d9d8feb82137787", + NULL + }; + +char *SkypeModulus2048[] = {"b8506aeed8ed30fe1c0e6774874b59206a77329042a49be2403da47d50052441067f87bcd57e6579b83df0bade2beff5b5cd8d87e8b3edac5f57fabccd49695974e2b5e5f0287d6c19ecc31b4504a9f8be25da78fa4ef345f91d339b73cc2d70b3904e11ca570ce9b5dc4b08b3c44b74dc463587ea637ef4456e61462b72042fc2f4ad5510a9850c06dc9a7374412fcadda955bd9800f9754cb3b8cc62d0e98d8282180971055b457c06f351e61164fc5a9de9d83d1d1378964001380b5b99ee4c5c7d50ac2462a4b7ea34fd32d90bd8d4b46410263673f900d1c60470165df9f3cb48016ab8ca45ce6875a71d977915ca8251b50258748dbc37fe332edc2855", + "bfe2db4bdf48358d3ae7c7d260989e4c7c1d81e6d9bd62e3a34dcaaa55f16c8c976a8862bc2462ae1b4063fd3d0de97e8aee5b793e171e22136319ff3474667c47ed1c14a892a19644005401cef46b5a8bd9510b3c8eeff80755decd2932cdca9119d96c5e16f6603b24ccc062822ca250336915a77aeab693268e1e22b1209d22f65a54cf7bcc7a4f9677eab54df8c33b16755ce1cf907efae988df8a4b4fad0591d95617189cd5ae0ef0935b2b458d72c7cc3de19a6268af4b06a8ce324292ca01b6a3adf7d133101a1e6659b03e0a1e14f07f8a11f5ec945c1a6f1eff06e75764262749acd6c3bf59503d970b038f77018cb09eb924fc2045db9b3248d6d5", + "9f2a6038e8132c3545bc7c5fbe56903e08e83353b1defe7042b5c8457ba5a40254b2812a843be54993dafed5fa55a415be652e2ff533483a1ab3907c5603df47a59311973c2b4c39cf942a58f12149ce0437b341aa58add6dc2ab27800f1f529975506c10925e5254ff0766ed276b194d36c783a7d426672e32e7d6881c91e167ccbb38f4f9ee703d621712b7de384c6c97fe5cf557c839d47ebf1c45db2ec554b4aebf203d00896e9b202e564251f6fc623f6810208ffd1497c4de673d87d693febc17ec5157aa5aa8a0055976fd4817b6ccef76d4525741820d72ef89c2558971189c5e42cdeb271590f6bb0e2bede43a28003f54298be689a39791ec8a919", + "bf137933ab269e3bacbea76da16f6ff06748028e79efe20aa696368fc88f6abca4571790f3d67ea4b6f382850f8f27a2ee4c044be541083d74ecbb30142070a7bc2746ff01fb243c4ec2a5fba296c3fb9c357429b4d511741bd2bf97034d29fe4fbd9013df87b725941e9696635fd53caf2f56b7b3609c51b8448256c4fb6078dde89f06d54c8bb4e2f6fbfb6ee42e698649e32e74dc542c94c2be3f9833ef22f988f9aa9c4fa5267b8aaf455ef06c693a36ca4447763e865086070713328e2f835649e1a15d78eaa6f90f9b5a6fac3f2eb3e24979bdacc4843956ef44c186f5007278c7d6cc1ceaefd8c56121ffa39c8d75873ae5a853b7cd1002885b49b209", + "d7edafe450023e3a4b0f7f1925196943ce1defd4d158cc868a29973bbedb9b90d203331b01c9752f254d7c922f8b5bdba2d25bd5955b887f26532afda73e37527f1265925ddbb6f1ed5efd660b1cad6ecb94628e1c90311a320db1a758ec36e3df926df48ebc1c099714dfe5e7541eec3ce96dd7d6f8b55288c081646c51a6b77f5c1ef1025b7862ee9d5e7d491293471ae7159daa40ccd7db2753071c11264aa5cc861d5fedc8fed6f2503b0a68a17d78cdfe3f698bd8af21ac1152f2dcef7c515bd9c9e4934cd9c9977ade4c77fbcd184111332f2737847b5ee713b6568d55c14618ae1e4ce088431709d9ad8fae987887ac829c3f7968bee8d1cfd347e341", + "d52af9c4194936e76ca66fd276533926d073b261c8de4cba4ea8f758dcce63e1c391220085ac94492926fde61ac0ca4b7b1acdd90a4d601b242cd2f890d8f826ab0c269bf1d23f497f2c236f1f57c01b881b88616eab2aa2028d533bb449b579063fcd287fba64ab0d64f4c1f38845d22017be45b7942348b494b1dd73982719be5ee37384b9feb41473e8bf71c8c4edab7a486907879e6a797baa2d7d9462fc24a7ad6a00598646064beb19f27513bee559f0316a398eaa5d5e618a41fc0d16ee1c6cf17e84bf7571227fe98a29d205c0ffd5546bed9f87e22e49ebee6d58e908e268d258d7520589f2b730d72639bb751ac4fb4d39125bb5b205bacfb423df", + "a4deafb40a982a87c989fe919b888dfe185113b17106b3241e7d166177b322b790131ddebae8d878bd8ae7e2e39794cab70988778cb13d121528e260eedabb3df35a320a02b7e68b63d4cd143d0ef93ab565d2163e467b77ae4644e9850e922fcdc61c58020e236a70557188e8ff2c332ff9e4f3d984042a2c802917ba9bcdf9277b4de3bf7055423bcac61332f2983d3fd9074dcb610e4c8d751bb38d4c20b470a8314d44790462e62c3b45a77cc290aab52b0a237fccd7513b5e8fd50ec4e79dac5047191417ffd68ebfa023f275a0fff93531cdda7b6287d34e41e89227c2942b6aeca11956fdb566f65be7f1c456b1b07b731cb78698b08478f5e7c856cb", + "a903c6079aac211634af60c85955889da69a552a2e994ef9395a53fc258c78c6308961d7bf3e87dd85ebb55087ffa151433514901e5b8e79458209864e82d839de8793002e15528d979a4b853a47a7d74e463ebdc321827308559c68a81f6de72660625f577ac42fc0addd31ad8697155de21d977bd9874ce65a6232cad0c08a21b9a2a3d4d14923115ff0d9b5f09e645f4d3a6c45ca1838a8f7a519b2d82fd82282678260d934bc8d42314ac6c703189ad734b2e9c8d285a50447fda2d01bd26452e63ce290ca1f88b1237abdd942372a384902ab3495a37bfd68c45d46008d134984f06f9114d411bd560fe48ec3a16a3f4ff0127ca52928f3261ddbb76b9d", + "b4792d7289d6aaba727b338d6ed91f7fa34f9d9abca23795bff72f7f38f4c27b416149489891c2b615d0b5db19a09d6462d26ee12526f93f4bd129655ecc890727f8a6ec71c17a82b02f68afe8dab6e40620236753784d4a279159dc613b2eebc1bbf9fa65b8ca1d13ded28ea575c591738772369ca4049329d10c06c194e92e13394f8b53c890235b922f18b24ccc71d59065aa6e45889da11d33feee17bd994c456d7635238f431403badb45b9ea907e4385ae2ef178dd5154c77895e9a8f60eef3c3969b356a0c11e6d3d4d0563c1e76d8268117f0eb4c160b3b941e77518a6361d17241f28c7f84ee0e378a831782e9dc688584a0ef9b383835e202bd67f", + NULL + }; + +char *SkypeModulus4096[] = {"c3ac2b9912720fd9d5d121570bb8acb6c5b9b5ad4af08b75a68728860759a256f1c4357a329ac61528e968b7b41cae0f7c61784e0e72e465828fbb4e92931a2e14856d4a9600045df661cca37ccd6b993c93fcf62c0eab46882460df70b6f866293bd6d8fe35bcbd9c63ca4909c30652933d2b1943e67633af7ad0599ac8a61b914e2b97d9b1736683f1457695842951fff68e36fc170a54ddbb6b4f7d0361f5a6c36ad2837281aa9359460e6e15aa84d0e17ba9f1a9de3c88cc9233e371a6f18e48892e570679be601ddc134669967e2c550895ed97e49189b7164997eb266540b6b19d259188ddb9224ee846d1d2ca4e86eba4be39a7b1662f7e230b9d8a8f2553f3394a8b6f0668c3372bbba713064543b8f932ca34b3eb44bd8533191550b06960553a0e69386770569c1bc087d21976ef570f6634a5dd127407af32f39a56f5e72aed3590fa4722dc0a55e475b2d1ab39b2f0904168f97a16f4762d6804f7164feecc1a57823a3786c53bcdd73a7086ecd56142af052b86dec233ef8abeab437436c6c1c6ce231aa93bdf669f25c1c30b12df932df4b9662f90b1e1aaeca77a6c773dcb28669cf1852b8c14615e52905ccf3beac1546f499778dd01fc060876afe3f5f97de6d3cccae7a686222c17699f5968c453fd6f692e8254961018f5986d98c01c357d624d3d6c44e3b4ca344de00b2d8bf3939c2758b057bd4985", + "ba7463f3b6ccfd1327750915654e4823a5594b656cb9114b17146425bf5d720c9d94ca0bd2ca74ee8ac1af7940950ceebd161b1a631e4a6c98015a056d7af2decc2fc582a0b04ccb5eebb06a438816fbc594de942f9a90fb5c89bdcf215f0ddd59afba36b03538f5ef348dd96366900419c488263dbc547f26ffb54e9fb8faa5a9fed038bc2bd3b14a6b4ffaa5e01e84a029df338e47b267e15976508abb83b4bf88c523b5af7ba597fc4f4b07da84cd4eafb06cd9dee246854bb82be2620981e0c1491d0ed9ad67810cbf1ee7ad7d89a4c66ecb24f10d1c57e7a6947566a8a9739b2ca0af160761cddb4bf279ff6668a46c6c38a365dfeac5ba0f130418fe6234ae0642bff18c9a3422b0ef0f64373f7414ccf80cfd5440b3752de911542cdc10a25899ef7ff7ef32e8d6626caf5d8887d593a7323d663d5c1cd4885b48f3adfa529c42c9177519a2c283db8b68791dd8020cf2fb047fcf58d4605d3891074598eadf1b9c8da1a88b7fd7635d419c16ad109ed288f461d64325ae4929298c204e877515417645057bca10c6ceb3de4bd63441f2e2e2b03bad33781bf4e242f30da3e2407736668ced9193e022b75ab4f65d7201999fa317e9ad30a80080797279bfebd89614827c323979ec5141a25c15bf800f337907fe50b0cdb9eb07b9665958cc9373188dd58eb6571f1f41c4aa7b6357138557a37d122ab6c3f7cd2de9", + NULL + }; + + +uchar KeyDescTable[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x02, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, + 0x03, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, + 0x04, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x05, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, + 0x06, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x07, 0x10, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, + 0x00, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x01, 0x20, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x80, 0x00, 0x10, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF + }; + + +char *KeySelect(uint KeyIndex) +{ + uint *pKeyDescTable = (uint*)KeyDescTable; + char *pRet; + + if (pKeyDescTable[1] <= 0x1000) + { + while (pKeyDescTable[2]<0xFFFFFFFF) + { + switch (pKeyDescTable[1]) + { + case 0x600: + pRet = SkypeModulus1536[pKeyDescTable[2]]; break; + case 0x800: + pRet = SkypeModulus2048[pKeyDescTable[2]]; break; + case 0x1000: + pRet = SkypeModulus4096[pKeyDescTable[2]]; break; + default: + return NULL; + } + if (pKeyDescTable[0] == KeyIndex) return pRet; + pKeyDescTable += 3; + if (pKeyDescTable[1]>0x1000) return pRet; + } + } + return NULL; +} + + + + +#ifdef CRYPT_WOLFSSL +#include "wolfssl.c" +#endif diff --git a/protocols/MSN/src/skylogin/common.h b/protocols/MSN/src/skylogin/common.h new file mode 100644 index 0000000000..863d8af07a --- /dev/null +++ b/protocols/MSN/src/skylogin/common.h @@ -0,0 +1,128 @@ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#ifdef _WIN32 + +#define WIN32_LEAN_AND_MEAN +#include +#include +#pragma comment (lib,"ws2_32.lib") +#define int64_t __int64 + +#else + +#include +#include +#include +#include +typedef int SOCKET; +#define closesocket close +typedef int BOOL; +#define TRUE 1 +#define FALSE 0 + +#endif + +#ifdef DEBUG +#include +#define DBGPRINT printf +#else +#define DBGPRINT +#endif + +/* Use Skype 5+ Diffie-Hellmann RC4 wrapped login comunication. + * Fortunately Login servers also still work without it too. + * To keep library small and clean, we keep it disabled too, + * but you can enable it if you want. + */ +//#define USE_RC4 + +#ifdef CRYPT_WOLFSSL +#include "wolfssl.h" +#else +#include +#include +#include +#include +#ifdef USE_RC4 +#include +#include +#endif +#endif + +typedef unsigned char uchar; +typedef unsigned short ushort; +typedef unsigned int uint; +typedef unsigned long ulong; + +#define MAX_IP_LEN 15 +#define HTTPS_PORT 443 + +#define NODEID_SZ 8 +#define HANDSHAKE_SZ 0x05 +#define CONCAT_SALT "\nskyper\n" +#define KEYSZ 0x200 +#define SK_SZ 0xC0 +#define MODULUS_SZ 0x80 +#define HTTPS_HSR_MAGIC "\x16\x03\x01" +#define HTTPS_HSRR_MAGIC "\x17\x03\x01" +#define LOGIN_OK 4200 + +#define RAW_PARAMS 0x41 +#define EXT_PARAMS 0x42 + +#define VER_STR "0/6.18.0.105" + +typedef struct +{ + char ip[MAX_IP_LEN + 1]; + int port; +} Host; + +typedef struct +{ + uchar *Memory; + int MsZ; +} Memory_U; + +typedef struct +{ + uchar *User; + uchar LoginHash[MD5_DIGEST_LENGTH]; + uint Expiry; + RSA *RSAKeys; + //Memory_U Modulus; + Memory_U SignedCredentials; +} SLoginDatas; + +typedef struct +{ + uchar SessionKey[SK_SZ]; + uchar NodeID[NODEID_SZ]; + uchar Language[2]; + uint PublicIP; + SLoginDatas LoginD; +} Skype_Inst; + +typedef struct +{ + SOCKET LSSock; +#ifdef USE_RC4 + RC4_KEY rc4_send; + RC4_KEY rc4_recv; +#endif +} LSConnection; + +#pragma pack(1) +typedef struct +{ + unsigned char MAGIC[3]; + unsigned short ResponseLen; +} HttpsPacketHeader; + +#pragma pack() + +extern char *SkypeModulus1536[]; + +char *KeySelect(uint KeyIndex); +#endif diff --git a/protocols/MSN/src/skylogin/crc.c b/protocols/MSN/src/skylogin/crc.c new file mode 100644 index 0000000000..48cf20762c --- /dev/null +++ b/protocols/MSN/src/skylogin/crc.c @@ -0,0 +1,113 @@ +#include "crc.h" + + /* ============================================================= */ + /* COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or */ + /* code or tables extracted from it, as desired without restriction. */ + /* */ + /* First, the polynomial itself and its table of feedback terms. The */ + /* polynomial is */ + /* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */ + /* */ + /* Note that we take it "backwards" and put the highest-order term in */ + /* the lowest-order bit. The X^32 term is "implied"; the LSB is the */ + /* X^31 term, etc. The X^0 term (usually shown as "+1") results in */ + /* the MSB being 1. */ + /* */ + /* Note that the usual hardware shift register implementation, which */ + /* is what we're using (we're merely optimizing it by doing eight-bit */ + /* chunks at a time) shifts bits into the lowest-order term. In our */ + /* implementation, that means shifting towards the right. Why do we */ + /* do it this way? Because the calculated CRC must be transmitted in */ + /* order from highest-order term to lowest-order term. UARTs transmit */ + /* characters in order from LSB to MSB. By storing the CRC this way, */ + /* we hand it to the UART in the order low-byte to high-byte; the UART */ + /* sends each low-bit to hight-bit; and the result is transmission bit */ + /* by bit from highest- to lowest-order term without requiring any bit */ + /* shuffling on our part. Reception works similarly. */ + /* */ + /* The feedback terms table consists of 256, 32-bit entries. Notes: */ + /* */ + /* The table can be generated at runtime if desired; code to do so */ + /* is shown later. It might not be obvious, but the feedback */ + /* terms simply represent the results of eight shift/xor opera- */ + /* tions for all combinations of data and CRC register values. */ + /* */ + /* The values must be right-shifted by eight bits by the "updcrc" */ + /* logic; the shift must be unsigned (bring in zeroes). On some */ + /* hardware you could probably optimize the shift in assembler by */ + /* using byte-swap instructions. */ + /* polynomial $edb88320 */ + /* */ + /* -------------------------------------------------------------------- */ + +static unsigned int crc32_tab[] = { + 0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L, + 0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L, + 0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L, + 0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL, + 0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L, + 0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L, + 0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L, + 0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL, + 0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L, + 0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL, + 0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L, + 0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L, + 0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L, + 0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL, + 0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL, + 0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L, + 0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL, + 0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L, + 0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L, + 0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L, + 0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL, + 0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L, + 0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L, + 0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL, + 0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L, + 0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L, + 0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L, + 0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L, + 0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L, + 0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL, + 0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL, + 0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L, + 0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L, + 0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL, + 0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL, + 0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L, + 0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL, + 0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L, + 0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL, + 0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L, + 0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL, + 0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L, + 0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L, + 0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL, + 0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L, + 0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L, + 0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L, + 0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L, + 0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L, + 0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L, + 0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL, + 0x2d02ef8dL + }; + +/* Return a 32-bit CRC of the contents of the buffer. */ + +unsigned int crc32(const unsigned char *s, unsigned int len, int salt) +{ + unsigned int crc32val; + unsigned int i; + + crc32val = salt; + for (i = 0; i < len; i ++) + { + crc32val = + crc32_tab[(crc32val ^ s[i]) & 0xff] ^ + (crc32val >> 8); + } + return crc32val; +} diff --git a/protocols/MSN/src/skylogin/crc.h b/protocols/MSN/src/skylogin/crc.h new file mode 100644 index 0000000000..d2964e841b --- /dev/null +++ b/protocols/MSN/src/skylogin/crc.h @@ -0,0 +1,6 @@ +#ifndef CRC_H +#define CRC_H +/* This computes a 32 bit CRC of the data in the buffer, and returns the + CRC. The polynomial used is 0xedb88320. */ +unsigned int crc32(const unsigned char *buf, unsigned int len, int salt); +#endif /* CRC_H */ diff --git a/protocols/MSN/src/skylogin/credentials.c b/protocols/MSN/src/skylogin/credentials.c new file mode 100644 index 0000000000..0fc886eea7 --- /dev/null +++ b/protocols/MSN/src/skylogin/credentials.c @@ -0,0 +1,163 @@ +/* + * Skype Login + * + * Based on: + * FakeSkype : Skype reverse engineering proof-of-concept client + * Ouanilo MEDEGAN (c) 2006 http://www.oklabs.net + * pyskype : Skype login Python script by uunicorn + * + * Written by: leecher@dose.0wnz.at (c) 2015 + * + * Module: Credentials handling, reads/writes old Skype credentials format + * + */ +#include "common.h" +#include "objects.h" +#include "random.h" +#include "crc.h" +#include "credentials.h" +#ifdef _WIN32 +#define CRC_SIZE sizeof(short) +#else +#define CRC_SIZE 0 +#endif + + +Memory_U Credentials_Write(Skype_Inst *pInst) +{ + Memory_U creds; + uchar *Browser; + uint Crc; + + creds.MsZ = sizeof(pInst->LoginD.LoginHash) + MODULUS_SZ + pInst->LoginD.SignedCredentials.MsZ + CRC_SIZE; + if (!(Browser = creds.Memory = malloc(creds.MsZ))) + { + creds.MsZ = 0; + return creds; + } + memcpy(Browser, pInst->LoginD.LoginHash, sizeof(pInst->LoginD.LoginHash)); + Browser+=sizeof(pInst->LoginD.LoginHash); + BN_bn2bin(pInst->LoginD.RSAKeys->d, Browser); + Browser+=MODULUS_SZ; + memcpy(Browser, pInst->LoginD.SignedCredentials.Memory, pInst->LoginD.SignedCredentials.MsZ); + Browser+=pInst->LoginD.SignedCredentials.MsZ; +#ifdef _WIN32 + Crc = crc32(creds.Memory, Browser-creds.Memory, -1); + *Browser++ = *((uchar *)(&Crc) + 0); + *Browser++ = *((uchar *)(&Crc) + 1); +#endif + return creds; +} + +/* + 0 - OK + -1 - Invalid size of credentials blob + -2 - Invalid CRC + -3 - Out of memory + -4 - Unable to parse Signed credentials + -5 - RSA public key not found +*/ +int Credentials_Read(Skype_Inst *pInst, Memory_U creds, SResponse *LoginDatas) +{ + uchar *Browser; + uint Crc, Idx; + RSA *Keys; + + if (creds.MsZ < sizeof(pInst->LoginD.LoginHash) + MODULUS_SZ + 16 + CRC_SIZE) + return -1; + +#ifdef _WIN32 + Crc = crc32(creds.Memory, creds.MsZ-2, -1); + if (*((uchar *)(&Crc) + 0) != *((uchar*)creds.Memory+creds.MsZ-2) || + *((uchar *)(&Crc) + 1) != *((uchar*)creds.Memory+creds.MsZ-1)) + { + DBGPRINT("Credentials: Bad CRC!"); + return -2; + } +#endif + + Browser = creds.Memory; + memcpy (pInst->LoginD.LoginHash, Browser, sizeof(pInst->LoginD.LoginHash)); + Browser+=sizeof(pInst->LoginD.LoginHash); + Keys=RSA_new(); + BN_hex2bn(&(Keys->e), "010001"); + Keys->d = BN_bin2bn(Browser, MODULUS_SZ, NULL); + Browser+=MODULUS_SZ; + if (pInst->LoginD.SignedCredentials.Memory) free(pInst->LoginD.SignedCredentials.Memory); + pInst->LoginD.SignedCredentials.MsZ = creds.MsZ - CRC_SIZE - (Browser-creds.Memory); + if (!(pInst->LoginD.SignedCredentials.Memory = malloc(pInst->LoginD.SignedCredentials.MsZ))) + { + pInst->LoginD.SignedCredentials.MsZ = 0; + RSA_free(Keys); + return -3; + } + memcpy(pInst->LoginD.SignedCredentials.Memory, Browser, pInst->LoginD.SignedCredentials.MsZ); + + // Now credentials are read, but we need to finish LoginD.RSAKeys by unpacking Signed Credentials + if (Credentials_Parse(pInst->LoginD.SignedCredentials, LoginDatas)<0) + { + RSA_free(Keys); + return -4; + } + + for (Idx = 0; Idx < LoginDatas->NbObj; Idx++) + { + if (LoginDatas->Objs[Idx].Id == OBJ_ID_LDMODULUS) + { + Keys->n = BN_bin2bn(LoginDatas->Objs[Idx].Value.Memory.Memory, + LoginDatas->Objs[Idx].Value.Memory.MsZ, NULL); + if (pInst->LoginD.RSAKeys) RSA_free(pInst->LoginD.RSAKeys); + pInst->LoginD.RSAKeys = Keys; + return 0; + } + } + + RSA_free(Keys); + return -5; +} + +int Credentials_Parse(Memory_U Pcred, SResponse *LoginDatas) +{ + uchar *PostProcessed, *Browser; + char *Key; + uint KeyIdx, PPsZ; + RSA *SkypeRSA; + Memory_U creds = Pcred; + + if (!(creds.Memory = malloc(creds.MsZ))) + return -2; + KeyIdx = htonl(*(uint *)Pcred.Memory); + Pcred.Memory += sizeof(uint); + Pcred.MsZ -= sizeof(uint); + + SkypeRSA = RSA_new(); + Key = KeySelect(KeyIdx); + BN_hex2bn(&(SkypeRSA->n), Key); + BN_hex2bn(&(SkypeRSA->e), "010001"); + PPsZ = RSA_public_decrypt(Pcred.MsZ, Pcred.Memory, creds.Memory, SkypeRSA, RSA_NO_PADDING); + RSA_free(SkypeRSA); + if (PPsZ == -1) + { + DBGPRINT("Decryption failed..\n"); + free(creds.Memory); + return -1; + } + + PostProcessed = FinalizeLoginDatas(creds.Memory, &PPsZ, NULL, 0); + + if (PostProcessed == NULL) + { + DBGPRINT("Bad Datas Finalization..\n"); + free (creds.Memory); + return -1; + } + + LoginDatas->Objs = NULL; + LoginDatas->NbObj = 0; + Browser = PostProcessed; + + ManageObjects(&Browser, PPsZ, LoginDatas); + free(PostProcessed); + free(creds.Memory); + return 0; +} diff --git a/protocols/MSN/src/skylogin/credentials.h b/protocols/MSN/src/skylogin/credentials.h new file mode 100644 index 0000000000..ec09b8a89c --- /dev/null +++ b/protocols/MSN/src/skylogin/credentials.h @@ -0,0 +1,3 @@ +Memory_U Credentials_Write(Skype_Inst *pInst); +int Credentials_Read(Skype_Inst *pInst, Memory_U creds, SResponse *LoginDatas); +int Credentials_Parse(Memory_U creds, SResponse *LoginDatas); diff --git a/protocols/MSN/src/skylogin/login.c b/protocols/MSN/src/skylogin/login.c new file mode 100644 index 0000000000..6e6856ad8e --- /dev/null +++ b/protocols/MSN/src/skylogin/login.c @@ -0,0 +1,414 @@ +/* + * Skype Login + * + * Based on: + * FakeSkype : Skype reverse engineering proof-of-concept client + * Ouanilo MEDEGAN (c) 2006 http://www.oklabs.net + * pyskype : Skype login Python script by uunicorn + * + * Written by: leecher@dose.0wnz.at (c) 2015 + * + * Module: Skype server login + * + */ +#include "common.h" +#include "objects.h" +#include "random.h" +#include "platform.h" +#include "crc.h" +#ifdef _DEBUG +#include +#endif + +#ifdef USE_RC4 +#include "rc4comm.c" +#else +#define RC4Comm_Init(conn) 0 +#define RC4Comm_Send(conn,buf,len) send(conn->LSSock,buf,len,0) +#define RC4Comm_Recv(conn,buf,len) recv(conn->LSSock,buf,len,0) +#endif + +static Host LoginServers[] = { + {"91.190.216.17", 33033}, + {"91.190.218.40", 33033}, +}; + +static BOOL SendHandShake2LS(LSConnection *pConn, Host *CurLS) +{ + uchar HandShakePkt[HANDSHAKE_SZ] = {0}; + HttpsPacketHeader *HSHeader, Response; + struct sockaddr_in Sender={0}; + + HSHeader = (HttpsPacketHeader *)HandShakePkt; + memcpy(HSHeader->MAGIC, HTTPS_HSR_MAGIC, sizeof(HSHeader->MAGIC)); + HSHeader->ResponseLen = 0; + DBGPRINT("Sending Handshake to Login Server %s..\n", CurLS->ip); + Sender.sin_family = AF_INET; + Sender.sin_port = htons((short)CurLS->port); + Sender.sin_addr.s_addr = inet_addr(CurLS->ip); + if (connect(pConn->LSSock, (struct sockaddr *)&Sender, sizeof(Sender)) < 0) + { + DBGPRINT("Connection refused..\n"); + return FALSE; + } + if (RC4Comm_Init(pConn) < 0 || + RC4Comm_Send(pConn, (const char *)HandShakePkt, HANDSHAKE_SZ)<=0 || + RC4Comm_Recv(pConn, (char*)&Response, sizeof(Response))<=0 || + memcmp(Response.MAGIC, HTTPS_HSRR_MAGIC, sizeof(Response.MAGIC))) + return FALSE; + return TRUE; +} + +/* If Pass is NULL, User is assumed to be OAuth string and OAuth logon is performed */ +static int SendAuthentificationBlobLS(Skype_Inst *pInst, LSConnection *pConn, const char *User, const char *Pass) +{ + int64_t PlatForm; + uchar AuthBlob[0xFFFF] = {0}; + uchar SHAResult[32] = {0}; + uchar Modulus[MODULUS_SZ * 2] = {0}; + uchar ivec[AES_BLOCK_SIZE] = {0}; + uchar ecount_buf[AES_BLOCK_SIZE] = {0}; + uint MiscDatas[0x05] = {0}; + uchar SessionKey[SK_SZ]; + uchar *Browser; + uchar *Mark; + uchar *MarkObjL; + uint Idx, Size, Crc, BSize, ret = 0; + HttpsPacketHeader *HSHeader; + uchar HSHeaderBuf[sizeof(HttpsPacketHeader)], RecvBuf[0x1000]; + AES_KEY AesKey; + MD5_CTX Context; + RSA *SkypeRSA; + ObjectDesc Obj2000, ObjSessionKey, ObjZBool1, ObjRequestCode, ObjZBool2, ObjModulus, ObjPlatForm, ObjLang, ObjMiscDatas, ObjVer, ObjPubAddr; + SResponse Response={0}; + + + if (!pInst->LoginD.RSAKeys) + { + BIGNUM *KeyExp; + + DBGPRINT("Generating RSA Keys Pair (Size = %d Bits)..\n", KEYSZ); + pInst->LoginD.RSAKeys = RSA_new(); + KeyExp = BN_new(); + BN_set_word(KeyExp, RSA_F4); + Idx = RSA_generate_key_ex(pInst->LoginD.RSAKeys, KEYSZ * 2, KeyExp, NULL); + BN_free(KeyExp); + if (Idx == -1) + { + DBGPRINT("Error generating Keys..\n\n"); + RSA_free(pInst->LoginD.RSAKeys); + pInst->LoginD.RSAKeys = NULL; + return (0); + } + } + + Idx = BN_bn2bin(pInst->LoginD.RSAKeys->n, Modulus); + Idx = BN_bn2bin(pInst->LoginD.RSAKeys->d, Modulus + Idx); + + Browser = AuthBlob; + + HSHeader = (HttpsPacketHeader *)Browser; + memcpy(HSHeader->MAGIC, HTTPS_HSR_MAGIC, sizeof(HSHeader->MAGIC)); + HSHeader->ResponseLen = htons(0xCD); + Browser += sizeof(HttpsPacketHeader); + + *Browser++ = RAW_PARAMS; + *Browser++ = 0x03; + + Obj2000.Family = OBJ_FAMILY_NBR; + Obj2000.Id = OBJ_ID_2000; + Obj2000.Value.Nbr = 0x2000; + WriteObject(&Browser, Obj2000); + + SpecialSHA(pInst->SessionKey, SK_SZ, SHAResult, 32); + AES_set_encrypt_key(SHAResult, 256, &AesKey); + + SkypeRSA = RSA_new(); + BN_hex2bn(&(SkypeRSA->n), SkypeModulus1536[1]); + BN_hex2bn(&(SkypeRSA->e), "010001"); + Idx = RSA_public_encrypt(SK_SZ, pInst->SessionKey, SessionKey, SkypeRSA, RSA_NO_PADDING); + RSA_free(SkypeRSA); + if (Idx < 0) + { + DBGPRINT("RSA_public_encrypt failed..\n\n"); + return (0); + } + + ObjSessionKey.Family = OBJ_FAMILY_BLOB; + ObjSessionKey.Id = OBJ_ID_SK; + ObjSessionKey.Value.Memory.Memory = (uchar *)&SessionKey; + ObjSessionKey.Value.Memory.MsZ = SK_SZ; + WriteObject(&Browser, ObjSessionKey); + + ObjZBool1.Family = OBJ_FAMILY_NBR; + ObjZBool1.Id = OBJ_ID_ZBOOL1; + ObjZBool1.Value.Nbr = 0x01; + WriteObject(&Browser, ObjZBool1); + + Mark = Browser; + HSHeader = (HttpsPacketHeader *)Browser; + memcpy(HSHeader->MAGIC, HTTPS_HSRR_MAGIC, sizeof(HSHeader->MAGIC)); + HSHeader->ResponseLen = 0x00; + Browser += sizeof(HttpsPacketHeader); + + MarkObjL = Browser; + if (Pass) + { + ObjectDesc ObjUserName, ObjSharedSecret; + + *Browser++ = RAW_PARAMS; + *Browser++ = 0x04; + + ObjRequestCode.Family = OBJ_FAMILY_NBR; + ObjRequestCode.Id = OBJ_ID_REQCODE; + ObjRequestCode.Value.Nbr = 0x1399; + WriteObject(&Browser, ObjRequestCode); + + ObjZBool2.Family = OBJ_FAMILY_NBR; + ObjZBool2.Id = OBJ_ID_ZBOOL2; + ObjZBool2.Value.Nbr = 0x01; + WriteObject(&Browser, ObjZBool2); + + ObjUserName.Family = OBJ_FAMILY_STRING; + ObjUserName.Id = OBJ_ID_USERNAME; + ObjUserName.Value.Memory.Memory = (uchar *)User; + ObjUserName.Value.Memory.MsZ = (uchar)strlen(User); + WriteObject(&Browser, ObjUserName); + + MD5_Init(&Context); + MD5_Update(&Context, User, (ulong)strlen(User)); + MD5_Update(&Context, CONCAT_SALT, (ulong)strlen(CONCAT_SALT)); + MD5_Update(&Context, Pass, (ulong)strlen(Pass)); + MD5_Final(pInst->LoginD.LoginHash, &Context); + + ObjSharedSecret.Family = OBJ_FAMILY_BLOB; + ObjSharedSecret.Id = OBJ_ID_USERPASS; + ObjSharedSecret.Value.Memory.Memory = (uchar *)pInst->LoginD.LoginHash; + ObjSharedSecret.Value.Memory.MsZ = MD5_DIGEST_LENGTH; + WriteObject(&Browser, ObjSharedSecret); + + *Browser++ = RAW_PARAMS; + *Browser++ = 0x06; + + ObjModulus.Family = OBJ_FAMILY_BLOB; + ObjModulus.Id = OBJ_ID_MODULUS; + ObjModulus.Value.Memory.Memory = (uchar *)Modulus; + ObjModulus.Value.Memory.MsZ = MODULUS_SZ; + WriteObject(&Browser, ObjModulus); + + PlatForm = PlatFormSpecific(); + + ObjPlatForm.Family = OBJ_FAMILY_TABLE; + ObjPlatForm.Id = OBJ_ID_PLATFORM; + memcpy(ObjPlatForm.Value.Table, (uchar *)&PlatForm, sizeof(ObjPlatForm.Value.Table)); + WriteObject(&Browser, ObjPlatForm); + + ObjLang.Family = OBJ_FAMILY_STRING; + ObjLang.Id = OBJ_ID_LANG; + ObjLang.Value.Memory.Memory = pInst->Language; + ObjLang.Value.Memory.MsZ = sizeof(pInst->Language); + WriteObject(&Browser, ObjLang); + + FillMiscDatas(pInst, MiscDatas); + ObjMiscDatas.Family = OBJ_FAMILY_INTLIST; + ObjMiscDatas.Id = OBJ_ID_MISCD; + ObjMiscDatas.Value.Memory.Memory = (uchar *)MiscDatas; + ObjMiscDatas.Value.Memory.MsZ = 0x05; + WriteObject(&Browser, ObjMiscDatas); + + ObjVer.Family = OBJ_FAMILY_STRING; + ObjVer.Id = OBJ_ID_VERSION; + ObjVer.Value.Memory.Memory = (uchar *)VER_STR; + ObjVer.Value.Memory.MsZ = (uchar)strlen(VER_STR); + WriteObject(&Browser, ObjVer); + + ObjPubAddr.Family = OBJ_FAMILY_NBR; + ObjPubAddr.Id = OBJ_ID_PUBADDR; + ObjPubAddr.Value.Nbr = pInst->PublicIP; + WriteObject(&Browser, ObjPubAddr); + } + else + { + int64_t PartnerId = 999; + ObjectDesc ObjPartnerId, ObjOauth; + + // OAuth logon + *Browser++ = RAW_PARAMS; + *Browser++ = 0x02; + + ObjRequestCode.Family = OBJ_FAMILY_NBR; + ObjRequestCode.Id = OBJ_ID_REQCODE; + ObjRequestCode.Value.Nbr = 0x13a3; + WriteObject(&Browser, ObjRequestCode); + + ObjZBool2.Family = OBJ_FAMILY_NBR; + ObjZBool2.Id = OBJ_ID_ZBOOL2; + ObjZBool2.Value.Nbr = 0x3d; + WriteObject(&Browser, ObjZBool2); + + *Browser++ = RAW_PARAMS; + *Browser++ = 0x08; + + ObjModulus.Family = OBJ_FAMILY_BLOB; + ObjModulus.Id = OBJ_ID_MODULUS; + ObjModulus.Value.Memory.Memory = (uchar *)Modulus; + ObjModulus.Value.Memory.MsZ = MODULUS_SZ; + WriteObject(&Browser, ObjModulus); + + PlatForm = PlatFormSpecific(); + + ObjPlatForm.Family = OBJ_FAMILY_TABLE; + ObjPlatForm.Id = OBJ_ID_PLATFORM; + memcpy(ObjPlatForm.Value.Table, (uchar *)&PlatForm, sizeof(ObjPlatForm.Value.Table)); + WriteObject(&Browser, ObjPlatForm); + + FillMiscDatas(pInst, MiscDatas); + ObjMiscDatas.Family = OBJ_FAMILY_INTLIST; + ObjMiscDatas.Id = OBJ_ID_MISCD; + ObjMiscDatas.Value.Memory.Memory = (uchar *)MiscDatas; + ObjMiscDatas.Value.Memory.MsZ = 0x05; + WriteObject(&Browser, ObjMiscDatas); + + ObjLang.Family = OBJ_FAMILY_STRING; + ObjLang.Id = OBJ_ID_LANG; + ObjLang.Value.Memory.Memory = pInst->Language; + ObjLang.Value.Memory.MsZ = sizeof(pInst->Language); + WriteObject(&Browser, ObjLang); + + ObjPartnerId.Family = OBJ_FAMILY_TABLE; + ObjPlatForm.Id = OBJ_ID_PARTNERID; + memcpy(ObjPlatForm.Value.Table, (uchar *)&PartnerId, sizeof(ObjPlatForm.Value.Table)); + WriteObject(&Browser, ObjPlatForm); + + ObjOauth.Family = OBJ_FAMILY_STRING; + ObjOauth.Id = OBJ_ID_OAUTH; + ObjOauth.Value.Memory.Memory = (uchar *)User; + ObjOauth.Value.Memory.MsZ = strlen(User); + WriteObject(&Browser, ObjOauth); + + ObjVer.Family = OBJ_FAMILY_STRING; + ObjVer.Id = OBJ_ID_VERSION; + ObjVer.Value.Memory.Memory = (uchar *)VER_STR; + ObjVer.Value.Memory.MsZ = (uchar)strlen(VER_STR); + WriteObject(&Browser, ObjVer); + + ObjPubAddr.Family = OBJ_FAMILY_NBR; + ObjPubAddr.Id = OBJ_ID_PUBADDR; + ObjPubAddr.Value.Nbr = pInst->PublicIP; + WriteObject(&Browser, ObjPubAddr); + } + + Size = (uint)(Browser - MarkObjL); + HSHeader->ResponseLen = htons((u_short)(Size + 0x02)); + + Idx = 0; + memset(ivec, 0, AES_BLOCK_SIZE); + memset(ecount_buf, 0, AES_BLOCK_SIZE); + AES_ctr128_encrypt(MarkObjL, MarkObjL, Size, &AesKey, ivec, ecount_buf, &Idx); + + Crc = crc32(MarkObjL, Size, -1); + *Browser++ = *((uchar *)(&Crc) + 0); + *Browser++ = *((uchar *)(&Crc) + 1); + + Size = (uint)(Browser - AuthBlob); + + if (RC4Comm_Send(pConn, (const char *)AuthBlob, Size)<=0) + { + DBGPRINT("Sending to LS failed :'(..\n"); + return (-1); + } + + while (!ret && RC4Comm_Recv(pConn, (char *)&HSHeaderBuf, sizeof(HSHeaderBuf))>0) + { + HSHeader = (HttpsPacketHeader *)HSHeaderBuf; + if (strncmp((const char *)HSHeader->MAGIC, HTTPS_HSRR_MAGIC, strlen(HTTPS_HSRR_MAGIC)) || + RC4Comm_Recv(pConn, (char *)RecvBuf, (BSize=htons(HSHeader->ResponseLen)))<=0) + { + DBGPRINT("Bad Response..\n"); + return (-2); + } + DBGPRINT("Auth Response Got..\n\n"); + + Idx = 0; + memset(ivec, 0, AES_BLOCK_SIZE); + memset(ecount_buf, 0, AES_BLOCK_SIZE); + BSize-=2; + ivec[3] = 0x01; + ivec[7] = 0x01; + AES_ctr128_encrypt(RecvBuf, RecvBuf, BSize, &AesKey, ivec, ecount_buf, &Idx); + + Browser = RecvBuf; + while (BrowserLoginD.SignedCredentials.Memory) free(pInst->LoginD.SignedCredentials.Memory); + if (!(pInst->LoginD.SignedCredentials.Memory = malloc(Response.Objs[Idx].Value.Memory.MsZ))) + { + FreeResponse(&Response); + return -2; + } + memcpy (pInst->LoginD.SignedCredentials.Memory, Response.Objs[Idx].Value.Memory.Memory, + (pInst->LoginD.SignedCredentials.MsZ = Response.Objs[Idx].Value.Memory.MsZ)); + break; + } + } + FreeResponse(&Response); + } + + return ret; +} + + +int PerformLogin(Skype_Inst *pInst, const char *User, const char *Pass) +{ + uint ReUse = 1; + int i; + LSConnection conn={0}; + int iRet = 0; + + for (i=0; !iRet && iSessionKey, sizeof(pInst->SessionKey)); + InitNodeId(pInst); + memcpy(pInst->Language, "en", 2); + pInst->PublicIP = 0x7F000001; // 127.0.0.1, we could use hostscan to get real IP, but not necessary for just login +} diff --git a/protocols/MSN/src/skylogin/login.h b/protocols/MSN/src/skylogin/login.h new file mode 100644 index 0000000000..6d5113466d --- /dev/null +++ b/protocols/MSN/src/skylogin/login.h @@ -0,0 +1,2 @@ +int PerformLogin(Skype_Inst *pInst, const char *User, const char *Pass); +void InitInstance(Skype_Inst *pInst); diff --git a/protocols/MSN/src/skylogin/objects.c b/protocols/MSN/src/skylogin/objects.c new file mode 100644 index 0000000000..f5941128f0 --- /dev/null +++ b/protocols/MSN/src/skylogin/objects.c @@ -0,0 +1,252 @@ +/* + * Skype Login + * + * Based on: + * FakeSkype : Skype reverse engineering proof-of-concept client + * Ouanilo MEDEGAN (c) 2006 http://www.oklabs.net + * pyskype : Skype login Python script by uunicorn + * + * Written by: leecher@dose.0wnz.at (c) 2015 + * + * Module: Object management functions + * + */ +#include "common.h" +#include "objects.h" +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include +#include +#endif + +void WriteValue(uchar **BufferAddr, uint Value) +{ + uint a; + + for (a = Value; a > 0x7F; a >>= 7, (*BufferAddr)++) **BufferAddr = (uchar)a | 0x80; + **BufferAddr = (uchar) a; + (*BufferAddr)++; +} + +void ReadValue(uchar **BufferAddr, uint *Value) +{ + uint a=0; + uchar c; + + for (*Value=0, c=**BufferAddr; a==0 || (c & 0x80); a+=7, (*BufferAddr)++) *Value|=((c=**BufferAddr) & 0x7F) << a; +} + + +void WriteObject(uchar **Buffer, ObjectDesc Object) +{ + int IdxDown, IdxUp; + + Object.ObjListInfos.Id = -1; + Object.ObjListInfos.Rank = 0; + + WriteValue(Buffer, Object.Family); + WriteValue(Buffer, Object.Id); + switch(Object.Family) + { + case OBJ_FAMILY_NBR: + WriteValue(Buffer, Object.Value.Nbr); + break; + case OBJ_FAMILY_TABLE: + IdxUp = 0; + IdxDown = sizeof(Object.Value.Table) - 1; + while (IdxDown >= 0) + (*Buffer)[IdxDown--] = Object.Value.Table[IdxUp++]; + *Buffer += sizeof(Object.Value.Table); + break; + case OBJ_FAMILY_NETADDR: + *(unsigned int *)(*Buffer) = inet_addr(Object.Value.Addr.ip); + *Buffer += 4; + *(unsigned short *)(*Buffer) = htons((u_short)Object.Value.Addr.port); + *Buffer += 2; + break; + case OBJ_FAMILY_BLOB: + WriteValue(Buffer, Object.Value.Memory.MsZ); + memcpy(*Buffer, Object.Value.Memory.Memory, Object.Value.Memory.MsZ); + *Buffer += Object.Value.Memory.MsZ; + break; + case OBJ_FAMILY_STRING: + memcpy(*Buffer, Object.Value.Memory.Memory, Object.Value.Memory.MsZ); + *Buffer += Object.Value.Memory.MsZ; + *(*Buffer) = 0x00; + *Buffer += 1; + break; + case OBJ_FAMILY_INTLIST: + { + uint *IntList; + + IdxUp = 0; + IntList = (uint *)Object.Value.Memory.Memory; + WriteValue(Buffer, Object.Value.Memory.MsZ); + while (IdxUp < Object.Value.Memory.MsZ) + { + WriteValue(Buffer, IntList[IdxUp]); + IdxUp++; + } + break; + } + default: + DBGPRINT("WriteObject : Unmanaged Object Family\n"); + break; + } +} + +int DecodeRawObjects(uchar **Buffer, uint Size, SResponse *Response, ObjectDesc **Objs, int Suffix) +{ + int NbObjs, lIdx, IdxUp, IdxDown; + uint Family, Id; + uchar *Str, *Mark; + struct in_addr IP; + ObjectDesc *Object; + static int Idx = 0; + static int Level = 0; + static int CurObjListId = -1; + static uint CurObjListRank = 0; + uint LocalObjListRank; + + LocalObjListRank = CurObjListRank; + NbObjs = Family = Id = lIdx = 0; + Mark = *Buffer; + + ReadValue(Buffer, &NbObjs); + Level += 1; + + if (Level == 1) + Idx += Suffix; + + while (lIdx < NbObjs) + { + Family = **Buffer; + *Buffer += 1; + ReadValue(Buffer, &Id); + *Objs = (ObjectDesc *)realloc(*Objs, sizeof(ObjectDesc) * (Idx + 1)); + Object = &((*Objs)[Idx]); + Object->Family = Family; + Object->Id = Id; + Object->ObjListInfos.Id = CurObjListId; + Object->ObjListInfos.Rank = LocalObjListRank; + + switch (Family) + { + case OBJ_FAMILY_NBR: + ReadValue(Buffer, &(Object->Value.Nbr)); + break; + case OBJ_FAMILY_TABLE: + IdxUp = 0; + IdxDown = sizeof(Object->Value.Table) - 1; + while (IdxDown >= 0) + Object->Value.Table[IdxUp++] = (*Buffer)[IdxDown--]; + *Buffer += sizeof(Object->Value.Table); + break; + case OBJ_FAMILY_NETADDR: +#ifdef _WIN32 + IP.S_un.S_addr = *(unsigned int *)*Buffer; +#else + IP.s_addr = *(unsigned int *)*Buffer; +#endif + memset(Object->Value.Addr.ip, 0, MAX_IP_LEN + 1); + strncpy(Object->Value.Addr.ip, inet_ntoa(IP), MAX_IP_LEN + 1); + *Buffer += 4; + Object->Value.Addr.port = htons(*(unsigned short *)(*Buffer)); + *Buffer += 2; + break; + case OBJ_FAMILY_BLOB: + ReadValue(Buffer, &(Object->Value.Memory.MsZ)); + Object->Value.Memory.Memory = (uchar *)malloc(Object->Value.Memory.MsZ); + memcpy(Object->Value.Memory.Memory, *Buffer, Object->Value.Memory.MsZ); + *Buffer += Object->Value.Memory.MsZ; + break; + case OBJ_FAMILY_STRING: + Str = *Buffer; + Object->Value.Memory.MsZ = 1; + while (*Str++ != 0) + Object->Value.Memory.MsZ += 1; + Object->Value.Memory.Memory = (uchar *)malloc(Object->Value.Memory.MsZ); + memcpy(Object->Value.Memory.Memory, *Buffer, Object->Value.Memory.MsZ); + *Buffer += Object->Value.Memory.MsZ; + break; + case OBJ_FAMILY_INTLIST: + ReadValue(Buffer, &(Object->Value.Memory.MsZ)); + Object->Value.Memory.Memory = (uchar *)malloc(Object->Value.Memory.MsZ * sizeof(uint)); + for (IdxUp = 0; IdxUp < Object->Value.Memory.MsZ; IdxUp++) + ReadValue(Buffer, (uint*)(Object->Value.Memory.Memory + (IdxUp * sizeof(uint)))); + break; + case OBJ_FAMILY_OBJLIST: + { + uint OldNbObj; + int OldCurObjListId; + + OldCurObjListId = CurObjListId; + CurObjListId = (int)Id; + CurObjListRank += 1; + OldNbObj = Response->NbObj; + ManageObjects(Buffer, Size - (*Buffer - Mark), Response); + CurObjListId = OldCurObjListId; + //Suffix += Response->NbObj - OldNbObj; + NbObjs -= 1; + //Idx += (Response->NbObj - OldNbObj); + goto ContinueDecode; + break; + } + default : + break; + } + Idx += 1; + lIdx += 1; +ContinueDecode: + continue ; + } + + Level -= 1; + if (Level == 0) + { + Idx = 0; + CurObjListId = -1; + CurObjListRank = 0; + } + return (NbObjs); +} + +int ManageObjects(uchar **Buffer, uint Size, SResponse *Response) +{ + uchar Mode; + + Mode = **Buffer; + *Buffer += 1; + switch (Mode) + { + case RAW_PARAMS: + Response->NbObj += DecodeRawObjects(Buffer, Size - 1, Response, &(Response->Objs), Response->NbObj); + return 0; + case EXT_PARAMS: + // Not supported as not needed by plain login + //Response->NbObj += DecodeExtObjects(Buffer, Size - 1, Response, &(Response->Objs), Response->NbObj); + break; + default: + break; + } + return -1; +} + +void FreeResponse(SResponse *Response) +{ + uint Idx; + + for (Idx=0; IdxNbObj; Idx++) + { + switch (Response->Objs[Idx].Family) + { + case OBJ_FAMILY_BLOB: + case OBJ_FAMILY_STRING: + case OBJ_FAMILY_INTLIST: + if (Response->Objs[Idx].Value.Memory.Memory) free (Response->Objs[Idx].Value.Memory.Memory); + break; + } + } + free (Response->Objs); + memset(Response, 0, sizeof(SResponse)); +} diff --git a/protocols/MSN/src/skylogin/objects.h b/protocols/MSN/src/skylogin/objects.h new file mode 100644 index 0000000000..1c11ef9a8e --- /dev/null +++ b/protocols/MSN/src/skylogin/objects.h @@ -0,0 +1,136 @@ +#include "common.h" + +typedef struct +{ + int Id; + uint Rank; +} ObjListInfos_S; + +typedef struct +{ + uint Family; + uint Id; + union + { + Memory_U Memory; + uchar Table[8]; /* Actually DOUBLE int */ + uint Nbr; + Host Addr; + } Value; + ObjListInfos_S ObjListInfos; +} ObjectDesc; + +typedef struct +{ + ushort Cmd; + ushort PacketID; + ushort Reply2ID; + uint NbObj; + ObjectDesc *Objs; +} SResponse; + + + +#define OBJ_FAMILY_NBR 0x00 +#define OBJ_FAMILY_TABLE 0x01 +#define OBJ_FAMILY_NETADDR 0x02 +#define OBJ_FAMILY_STRING 0x03 +#define OBJ_FAMILY_BLOB 0x04 +#define OBJ_FAMILY_OBJLIST 0x05 +#define OBJ_FAMILY_INTLIST 0x06 + +#define OBJ_ID_NODEID 0x0D +#define OBJ_ID_LPORT 0x10 +#define OBJ_ID_UPTIME 0x01 +#define OBJ_ID_STVL 0x23 +#define OBJ_ID_2000 0x09 +#define OBJ_ID_SK 0x08 +#define OBJ_ID_ZBOOL1 0x0C +#define OBJ_ID_REQCODE 0x00 +#define OBJ_ID_ZBOOL2 0x02 +#define OBJ_ID_USERNAME 0x04 +#define OBJ_ID_USERPASS 0x05 +#define OBJ_ID_MODULUS 0x21 +#define OBJ_ID_PLATFORM 0x31 +#define OBJ_ID_LANG 0x36 +#define OBJ_ID_VERSION 0x0D +#define OBJ_ID_PUBADDR 0x0E +#define OBJ_ID_MISCD 0x33 +#define OBJ_ID_OAUTH 0x3D +#define OBJ_ID_PARTNERID 0x3E +#define OBJ_ID_STACKVER 0x0B +#define OBJ_ID_STACKTS 0x0C +#define OBJ_ID_PEERLPORT 0x10 +#define OBJ_ID_PUBNETADDR 0x11 +#define OBJ_ID_NBCONNECTED 0x09 +#define OBJ_ID_LOGINANSWER 0x01 +#define OBJ_ID_CIPHERDLOGD 0x24 +#define OBJ_ID_LDUSER 0x00 +#define OBJ_ID_LDEXPIRY 0x04 +#define OBJ_ID_LDMODULUS 0x01 +#define OBJ_ID_ESAUTHANSWR 0x0A +#define OBJ_ID_ESHASHLIST 0x35 +#define OBJ_ID_HASH 0x32 +#define OBJ_ID_DISPLAYNAME 0x34 +#define OBJ_ID_UBLOB 0x33 +#define OBJ_ID_INTERNALNAM 0x10 +#define OBJ_ID_BUDDYSTATUS 0x79 // BUDDYSTATUS +#define OBJ_ID_AUTHCERT 0x03 +#define OBJ_ID_USER2SEARCH 0x00 +#define OBJ_ID_BCMID 0x00 +#define OBJ_ID_BCMVER 0x01 +#define OBJ_ID_SLOTID 0x00 +#define OBJ_ID_SLOTNBSN 0x07 +#define OBJ_ID_SLOTSNADDR 0x03 +#define OBJ_ID_DIRBLOB 0x0B + +#define OBJ_ID_CIRNAME 0x14 // FULLNAME +#define OBJ_ID_CILANG 0x24 // LANGUAGES +#define OBJ_ID_CICOUNTRY 0x28 // COUNTRY +#define OBJ_ID_CIREGION 0x2C // PROVINCE +#define OBJ_ID_CIVILLE 0x30 // CITY +#define OBJ_ID_CILOCATION 0x03 +#define OBJ_ID_CIPSTN_BAL 0x12D // PSTN_BALANCE +#define OBJ_ID_CIPSTN_BALC 0x128 // PSTN_BALANCE_CURRENCY +#define OBJ_ID_CIBIRTHDAY 0x1D // BIRTHDAY +#define OBJ_ID_CIPHONE_H 0x34 // PHONE_HOME +#define OBJ_ID_CIPHONE_O 0x38 // PHONE_OFFICE +#define OBJ_ID_CIPHONE_M 0x3C // PHONE_MOBILE +#define OBJ_ID_CIHOMEPAGE 0x44 // HOMEPAGE +#define OBJ_ID_CIABOUT 0x48 // ABOUT +#define OBJ_ID_CIALIASES 0x60 // ALIASES +#define OBJ_ID_CIMOOD_TEXT 0x68 // MOOD_TEXT +#define OBJ_ID_CIRICH_MOOD 0x334 // RICH_MOOD_TEXT +#define OBJ_ID_CITIMEZONE 0x6D // TIMEZONE + +#define OBJ_ID_AUTHEDBUDD 0x71 // NROF_AUTHED_BUDDIES +#define OBJ_ID_RCVDAUTHREQ 0x50 // RECEIVEDAUTHREQUEST +#define OBJ_ID_ISAUTHORIZD 0x5D // ISAUTHORIZED / ISBLOCKED +//#define OBJ_ID_DISPLAYNAME 0x84 // DISPLAYNAME +#define OBJ_ID_ONLINESTAT 0x89 // ONLINESTATUS +#define OBJ_ID_LASTONLINET 0x8D // LASTONLINETIMESTAMP +#define OBJ_ID_CISEX 0x21 // SEX (MALE=1, FEMALE=2, UNKNOWN=0) + + +#define OBJ_ID_FWTESTID 0x19 +#define OBJ_ID_FWTESTER 0x11 +#define OBJ_ID_PINGER 0x02 +#define OBJ_ID_TESTED 0x02 +#define OBJ_ID_TESTER 0x00 +#define OBJ_ID_RELAY 0x08 +#define OBJ_ID_SESPROPOSER 0x01 +#define OBJ_ID_SESCHALLENG 0x09 +#define OBJ_ID_SID2DEC 0x03 +#define OBJ_ID_SOLVEDCHALL 0x0A +#define OBJ_ID_USRDBLOB 0x05 +#define OBJ_ID_AESPART1 0x06 +#define OBJ_ID_PEERLOGIN 0x00 +#define OBJ_ID_PEERSESSID 0x03 + +#define OBJ_ID_GROUPID 0x269 +#define OBJ_ID_GROUPNAME 0x25C + +void WriteValue(uchar **BufferAddr, uint Value); +void WriteObject(uchar **Buffer, ObjectDesc Object); +int ManageObjects(uchar **Buffer, uint Size, SResponse *Response); +void FreeResponse(SResponse *Response); diff --git a/protocols/MSN/src/skylogin/platform.h b/protocols/MSN/src/skylogin/platform.h new file mode 100644 index 0000000000..c5cf2d4438 --- /dev/null +++ b/protocols/MSN/src/skylogin/platform.h @@ -0,0 +1,6 @@ +int64_t PlatFormSpecific(); +void InitNodeId(Skype_Inst *pInst); +void FillMiscDatas(Skype_Inst *pInst, unsigned int *Datas); +void FillRndBuffer(unsigned char *Buffer); +Memory_U Credentials_Load(char *pszUser); +int Credentials_Save(Memory_U creds, char *pszUser); diff --git a/protocols/MSN/src/skylogin/platform_w32.c b/protocols/MSN/src/skylogin/platform_w32.c new file mode 100644 index 0000000000..eb75ed4e28 --- /dev/null +++ b/protocols/MSN/src/skylogin/platform_w32.c @@ -0,0 +1,195 @@ +/* + * Skype Login + * + * Based on: + * FakeSkype : Skype reverse engineering proof-of-concept client + * Ouanilo MEDEGAN (c) 2006 http://www.oklabs.net + * pyskype : Skype login Python script by uunicorn + * + * Written by: leecher@dose.0wnz.at (c) 2015 + * + * Module: WINDOWS platform specific functions + * + */ +#include +#include "common.h" +#include "random.h" +#define WIN32_LEAN_AND_MEAN +#include +#pragma comment (lib,"rpcrt4.lib") + +static uchar RandomSeed[SHA_DIGEST_LENGTH] = {0}; + +static BOOL QueryRegValue(HKEY hKey, LPCTSTR lpSubKey, LPBYTE lpValue, LPDWORD pCbValue) +{ + char *pSubKey, *pTok, szKey[256]={0}; + DWORD dwIndex; + LONG ret; + + if ( !lpSubKey || !*lpSubKey ) return FALSE; + if ( *lpSubKey != '*' ) + { + for (pSubKey = (char*)lpSubKey; *pSubKey != '*'; pSubKey = pTok + 1) + if (!(pTok = strchr(pSubKey, '\\'))) break; + if ( pSubKey > lpSubKey ) + { + if ( pSubKey - lpSubKey == 1 ) return FALSE; + strncpy (szKey, lpSubKey, pSubKey - lpSubKey - 1); + if (RegOpenKeyA (hKey, szKey, &hKey) == ERROR_SUCCESS) + { + ret = QueryRegValue(hKey, pSubKey, lpValue, pCbValue); + RegCloseKey(hKey); + return ret; + } + return FALSE; + } + if ( *lpSubKey != '*' ) return RegQueryValueExA (hKey, lpSubKey, NULL, NULL, lpValue, pCbValue) == ERROR_SUCCESS; + } + if (lpSubKey[1] != '\\') + return RegQueryValueExA (hKey, lpSubKey, NULL, NULL, lpValue, pCbValue) == ERROR_SUCCESS; + for (dwIndex = 0; (ret = RegEnumKeyA (hKey, dwIndex, szKey, sizeof(szKey))) == ERROR_SUCCESS; dwIndex++) + { + char szSubKey[256]; + + sprintf (szSubKey, "%s%s", szKey, lpSubKey+1); + if (QueryRegValue (hKey, szSubKey, lpValue, pCbValue)) break; + } + return ret == ERROR_SUCCESS; +} + +int64_t PlatFormSpecific() +{ + BYTE Buffer[0x400]; + DWORD BufSz = 0x400; + int Idx, Used; + + Used = Idx = 0; + + if (QueryRegValue(HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ProductId", + (LPBYTE)Buffer, &BufSz)) + Used += BufSz; + BufSz = sizeof(Buffer)-Used; + if (QueryRegValue(HKEY_LOCAL_MACHINE, + "HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter\\*\\DiskController\\*\\DiskPeripheral\\*\\Identifier", + (LPBYTE)Buffer + Used, &BufSz)) + Used += BufSz; + if (GetVolumeInformationA("C:\\", 0, 0, (LPDWORD)(Buffer + Used), 0, 0, 0, 0)) + Used+=4; + return BytesSHA1I64(Buffer, Used); +} + +void InitNodeId(Skype_Inst *pInst) +{ + DWORD BufSz = sizeof(pInst->NodeID); + HKEY hKey; + + if (QueryRegValue(HKEY_LOCAL_MACHINE, + "SOFTWARE\\FakeSkype\\NodeId", + (LPBYTE)&pInst->NodeID, &BufSz)) return; + *(int64_t *)&pInst->NodeID = BytesRandomI64(); + if (RegCreateKey(HKEY_LOCAL_MACHINE, "SOFTWARE\\FakeSkype", &hKey) == ERROR_SUCCESS) + { + RegSetValueEx(hKey, "NodeId", 0, REG_BINARY, (LPBYTE)&pInst->NodeID, sizeof(pInst->NodeID)); + RegCloseKey(hKey); + } + + //FIXED NODEID + //memcpy_s(NodeID, NODEID_SZ, "\x49\x63\xff\xee\xe0\x5c\x9d\xf8", NODEID_SZ); + //memcpy_s(NodeID, NODEID_SZ, "\x97\xca\xb1\x72\x06\xf6\x72\xb4", NODEID_SZ); +} + +Memory_U Credentials_Load(char *pszUser) +{ + Memory_U creds={0}; + HKEY hKey; + char szKey[MAX_PATH]; + + sprintf (szKey, "SOFTWARE\\FakeSkype\\%s", pszUser); + if (RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey) == ERROR_SUCCESS) + { + if (RegQueryValueEx(hKey, "Credentials", NULL, NULL, NULL, &creds.MsZ) == ERROR_SUCCESS && + creds.MsZ) + { + if (!(creds.Memory = malloc(creds.MsZ))) + creds.MsZ = 0; + if (creds.Memory && RegQueryValueEx(hKey, "Credentials", NULL, NULL, creds.Memory, &creds.MsZ) != ERROR_SUCCESS) + { + free(creds.Memory); + ZeroMemory(&creds, sizeof(creds)); + } + } + RegCloseKey(hKey); + } + return creds; +} + +int Credentials_Save(Memory_U creds, char *pszUser) +{ + HKEY hKey; + int iRet = 0; + + char szKey[MAX_PATH]; + + sprintf (szKey, "SOFTWARE\\FakeSkype\\%s", pszUser); + if (RegCreateKey(HKEY_LOCAL_MACHINE, szKey, &hKey) == ERROR_SUCCESS) + { + iRet = RegSetValueEx(hKey, "Credentials", 0, REG_BINARY, creds.Memory, creds.MsZ) == ERROR_SUCCESS; + RegCloseKey(hKey); + } + return iRet; +} + +void FillMiscDatas(Skype_Inst *pInst, unsigned int *Datas) +{ + BYTE Buffer[0x400]; + DWORD BufSz = 0x400; + int ret; + int64_t PlatForm; + + PlatForm = PlatFormSpecific(); + Datas[0] = *(unsigned int *)&PlatForm; + Datas[1] = *(unsigned int *)&pInst->NodeID; + + if (!QueryRegValue(HKEY_LOCAL_MACHINE, + "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\ProductId", + (LPBYTE)Buffer, &BufSz)) + return; + Datas[2] = BytesSHA1(Buffer, BufSz); + + BufSz = 0x400; + if (!QueryRegValue(HKEY_LOCAL_MACHINE, + "HARDWARE\\DESCRIPTION\\System\\MultifunctionAdapter\\*\\DiskController\\*\\DiskPeripheral\\*\\Identifier", + (LPBYTE)Buffer, &BufSz)) + return; + Datas[3] = BytesSHA1(Buffer, BufSz); + + ret = GetVolumeInformationA("C:\\", 0, 0, (LPDWORD)Buffer, 0, 0, 0, 0); + Datas[4] = BytesSHA1(Buffer, 0x04); +} + +void FillRndBuffer(unsigned char *Buffer) +{ + SHA_CTX Context; + int idx; + + idx = 0; + memcpy(Buffer, RandomSeed, SHA_DIGEST_LENGTH); + idx += sizeof(RandomSeed); + GlobalMemoryStatus((LPMEMORYSTATUS)&Buffer[idx]); + idx += sizeof(MEMORYSTATUS); + UuidCreate((UUID *)&Buffer[idx]); + idx += sizeof(UUID); + GetCursorPos((LPPOINT)&Buffer[idx]); + idx += sizeof(POINT); + *(DWORD *)(Buffer + idx) = GetTickCount(); + *(DWORD *)(Buffer + idx + 4) = GetMessageTime(); + *(DWORD *)(Buffer + idx + 8) = GetCurrentThreadId(); + *(DWORD *)(Buffer + idx + 12) = GetCurrentProcessId(); + idx += 16; + QueryPerformanceCounter((LARGE_INTEGER *)&Buffer[idx]); + SHA1_Init(&Context); + SHA1_Update(&Context, Buffer, 0x464); + SHA1_Update(&Context, "additional salt...", 0x13); + SHA1_Final(RandomSeed, &Context); +} diff --git a/protocols/MSN/src/skylogin/random.c b/protocols/MSN/src/skylogin/random.c new file mode 100644 index 0000000000..3e41ec4da5 --- /dev/null +++ b/protocols/MSN/src/skylogin/random.c @@ -0,0 +1,178 @@ +/* + * Skype Login + * + * Based on: + * FakeSkype : Skype reverse engineering proof-of-concept client + * Ouanilo MEDEGAN (c) 2006 http://www.oklabs.net + * pyskype : Skype login Python script by uunicorn + * + * Written by: leecher@dose.0wnz.at (c) 2015 + * + * Module: Data creation functions, i.e. random data + * + */ +#include +#include "common.h" +#include "random.h" +#include "platform.h" + +#define skrand(x) ((x)*0x00010DCD+0x00004271) + +unsigned int BytesSHA1(uchar *Data, uint Length) +{ + uchar Buffer[SHA_DIGEST_LENGTH]; + SHA_CTX Context; + + SHA1_Init(&Context); + SHA1_Update(&Context, Data, Length); + SHA1_Final(Buffer, &Context); + return *(unsigned int *)Buffer; +} + +int64_t BytesSHA1I64(uchar *Data, uint Length) +{ + uchar Buffer[SHA_DIGEST_LENGTH]; + SHA_CTX Context; + + SHA1_Init(&Context); + SHA1_Update(&Context, Data, Length); + SHA1_Final(Buffer, &Context); + return *(int64_t *)Buffer; +} + +unsigned int BytesRandom() +{ + uchar Buffer[0x464]; + + FillRndBuffer(Buffer); + return BytesSHA1(Buffer, 0x464); +} + +int64_t BytesRandomI64() +{ + uchar Buffer[0x464]; + + FillRndBuffer(Buffer); + return BytesSHA1I64(Buffer, 0x464); +} + +unsigned short BytesRandomWord() +{ + unsigned short RandomW; + unsigned int RandomDW; + + RandomDW = BytesRandom(); + RandomW = *(unsigned short *)&RandomDW; + RandomW += 0; + return (RandomW); +} + +void SpecialSHA(uchar *SessionKey, uint SkSz, uchar *SHAResult, uint ResSz) +{ + SHA_CTX Context; + uchar Buffer[SHA_DIGEST_LENGTH]; + char *Salts[] = {"\x00\x00\x00\x00", "\x00\x00\x00\x01"}; + uint Idx = 0; + + if (ResSz > 40) + return ; + while (ResSz > 20) + { + SHA1_Init(&Context); + SHA1_Update(&Context, Salts[Idx], 0x04); + SHA1_Update(&Context, SessionKey, SkSz); + SHA1_Final(Buffer, &Context); + memcpy(SHAResult + (Idx * SHA_DIGEST_LENGTH), Buffer, SHA_DIGEST_LENGTH); + Idx++; + ResSz -= SHA_DIGEST_LENGTH; + } + + SHA1_Init(&Context); + SHA1_Update(&Context, Salts[Idx], 0x04); + SHA1_Update(&Context, SessionKey, SkSz); + SHA1_Final(Buffer, &Context); + memcpy(SHAResult + (Idx * SHA_DIGEST_LENGTH), Buffer, ResSz); +} + +void BuildUnFinalizedDatas(uchar *Datas, uint Size, uchar *Result) +{ + uchar *Mark; + uint Idx; + SHA_CTX MDCtx; + + Result[0x00] = 0x4B; + for (Idx = 1; Idx < (0x80 - (Size + SHA_DIGEST_LENGTH) - 2); Idx++) + Result[Idx] = 0xBB; + Result[Idx++] = 0xBA; + + Mark = Result + Idx; + + memcpy(Result + Idx, Datas, Size); + Idx += Size; + + SHA1_Init(&MDCtx); + SHA1_Update(&MDCtx, Mark, Size); + SHA1_Final(Result + Idx, &MDCtx); + Idx += SHA_DIGEST_LENGTH; + + Result[Idx] = 0xBC; +} + +uchar *FinalizeLoginDatas(uchar *Buffer, uint *Size, uchar *Suite, int SuiteSz) +{ + int Idx; + uchar *Result; + SHA_CTX Context; + uchar SHARes[SHA_DIGEST_LENGTH] = {0}; + + Idx = 0; + if (Buffer[*Size - 1] != 0xBC) + return (NULL); + if (SuiteSz) + { + if (*Buffer != 0x6A) + return (NULL); + *Size = 0x6A + SuiteSz; + Idx += 1; + goto Copy; + } + while ((Buffer[Idx] & 0x0F) == 0x0B) + Idx++; + if ((Buffer[Idx] & 0x0F) != 0x0A) + return (NULL); + Idx += 1; + *Size = (*Size - 0x15) - Idx; + +Copy: + Result = (uchar *)malloc(*Size); + memcpy(Result, Buffer + Idx, *Size - SuiteSz); + if (SuiteSz) memcpy(Result + (*Size - SuiteSz), Suite, SuiteSz); + + SHA1_Init(&Context); + SHA1_Update(&Context, Result, *Size); + SHA1_Final(SHARes, &Context); + + if (strncmp((char *)SHARes, (char *)(Buffer + Idx + (*Size - SuiteSz)), SHA_DIGEST_LENGTH)) + { + DBGPRINT("Bad SHA Digest for unencrypted Datas..\n"); + free(Result); + return (NULL); + } + + return (Result); +} + +void GenSessionKey(uchar *Buffer, uint Size) +{ + uint Idx, Rander; + + Rander = BytesRandom(); + for (Idx = 0; Idx < Size; Idx++) + { + Rander = skrand(Rander); + Buffer[Idx] = ((uchar *)&Rander)[sizeof(Rander) - 1]; + //Buffer[Idx] = (uchar)(Idx + 1); + } + Buffer[0] = 0x01; +} + diff --git a/protocols/MSN/src/skylogin/random.h b/protocols/MSN/src/skylogin/random.h new file mode 100644 index 0000000000..d87d1f784d --- /dev/null +++ b/protocols/MSN/src/skylogin/random.h @@ -0,0 +1,7 @@ +unsigned int BytesSHA1(uchar *Data, uint Length); +void GenSessionKey(uchar *Buffer, uint Size); +void SpecialSHA(uchar *SessionKey, uint SkSz, uchar *SHAResult, uint ResSz); +uchar *FinalizeLoginDatas(uchar *Buffer, uint *Size, uchar *Suite, int SuiteSz); +int64_t BytesSHA1I64(uchar *Data, uint Length); +int64_t BytesRandomI64(); +void BuildUnFinalizedDatas(uchar *Datas, uint Size, uchar *Result); diff --git a/protocols/MSN/src/skylogin/rc4comm.c b/protocols/MSN/src/skylogin/rc4comm.c new file mode 100644 index 0000000000..00890e245f --- /dev/null +++ b/protocols/MSN/src/skylogin/rc4comm.c @@ -0,0 +1,83 @@ +/* + * Skype Login + * + * Based on: + * FakeSkype : Skype reverse engineering proof-of-concept client + * Ouanilo MEDEGAN (c) 2006 http://www.oklabs.net + * pyskype : Skype login Python script by uunicorn + * + * Written by: leecher@dose.0wnz.at (c) 2015 + * + * Module: RC4 wrapped communication layer + * + */ +#include "common.h" +#include "rc4comm.h" +#ifdef USE_RC4 +#ifdef _WIN32 +#define alloca _alloca +#endif + +static char *SkypeDHModulus348 = "ffffffffffffffffc90fdaa22168c234c4c6628b80dc1cd129024e088a67cc74020bbea63b13b202ffffffffffffffff"; + +int RC4Comm_Init(LSConnection *pConn) +{ + DH *dh; + char pub_key[96], sec_key[48], ls_keybuf[1024]; + BIGNUM *ls_key; + int ret = 0; + + if (!(dh = DH_new())) return -1; + BN_hex2bn(&dh->g, "2"); + BN_hex2bn(&dh->p, SkypeDHModulus348); + DH_generate_key(dh); + if (send(pConn->LSSock, pub_key, BN_bn2bin(dh->pub_key, pub_key), 0)>0) + { + if (recv(pConn->LSSock, ls_keybuf, sizeof(ls_keybuf), 0)>0) + { + ls_key = BN_bin2bn(ls_keybuf, 48, NULL); + if (DH_compute_key(sec_key, ls_key, dh)<=0) ret = -3; else + { + MD5_CTX Context; + uchar BufHash[MD5_DIGEST_LENGTH]; + + MD5_Init(&Context); + MD5_Update(&Context, "O", 1); + MD5_Update(&Context, sec_key, 48); + MD5_Final(BufHash, &Context); + if (send(pConn->LSSock, BufHash, 8, 0)>0) + { + /* Setup RC4 */ + RC4_set_key(&pConn->rc4_send, 48, sec_key); + if (sec_key[0] == 0xFF) {DBGPRINT("First byte overflow, negotiation failed?");} + sec_key[0]++; + RC4_set_key(&pConn->rc4_recv, 48, sec_key); + } else + ret=-1; + } + BN_free(ls_key); + } else + ret=-1; + } else + ret=-1; + + DH_free(dh); + return ret; +} + +int RC4Comm_Send (LSConnection *pConn, const char * buf, int len) +{ + char *out = alloca(len); + + RC4(&pConn->rc4_send, len, buf, out); + return send(pConn->LSSock, out, len, 0); +} + +int RC4Comm_Recv (LSConnection *pConn, char * buf, int len) +{ + int ret = recv(pConn->LSSock, buf, len, 0); + if (ret > 0) RC4(&pConn->rc4_recv, ret, buf, buf); + return ret; +} + +#endif diff --git a/protocols/MSN/src/skylogin/rc4comm.h b/protocols/MSN/src/skylogin/rc4comm.h new file mode 100644 index 0000000000..c9c24bb7b1 --- /dev/null +++ b/protocols/MSN/src/skylogin/rc4comm.h @@ -0,0 +1,3 @@ +int RC4Comm_Init(LSConnection *pConn); +int RC4Comm_Send (LSConnection *pConn, const char * buf, int len); +int RC4Comm_Recv (LSConnection *pConn, char * buf, int len); diff --git a/protocols/MSN/src/skylogin/skylogin.c b/protocols/MSN/src/skylogin/skylogin.c new file mode 100644 index 0000000000..4e42d552d1 --- /dev/null +++ b/protocols/MSN/src/skylogin/skylogin.c @@ -0,0 +1,165 @@ +/* + * Skype Login + * + * Based on: + * FakeSkype : Skype reverse engineering proof-of-concept client + * Ouanilo MEDEGAN (c) 2006 http://www.oklabs.net + * pyskype : Skype login Python script by uunicorn + * + * Written by: leecher@dose.0wnz.at (c) 2015 + * + * Module: Main module which contains public functions of library + * + */ +#ifdef _WIN32 +#define EXPORT __declspec(dllexport) +#define strcasecmp stricmp +#endif +#include +#include "common.h" +#include "login.h" +#include "platform.h" +#include "uic.h" +#include "objects.h" +#include "credentials.h" +#include "skylogin.h" + +EXPORT SkyLogin SkyLogin_Init() +{ + Skype_Inst *pInst = calloc(1, sizeof(Skype_Inst)); + +#ifdef _WIN32 + WORD wVersionRequested; + WSADATA wsaData; + + wVersionRequested = MAKEWORD( 2, 2 ); + WSAStartup( wVersionRequested, &wsaData); +#endif + + if (pInst) InitInstance(pInst); + return (SkyLogin*)pInst; +} + +EXPORT void SkyLogin_Exit(SkyLogin pPInst) +{ + Skype_Inst *pInst = (Skype_Inst*)pPInst; + if (pInst->LoginD.User) free(pInst->LoginD.User); + if (pInst->LoginD.RSAKeys) RSA_free(pInst->LoginD.RSAKeys); + if (pInst->LoginD.SignedCredentials.Memory) free(pInst->LoginD.SignedCredentials.Memory); + free(pInst); +} + +EXPORT int SkyLogin_LoadCredentials(SkyLogin pPInst, char *User) +{ + Skype_Inst *pInst = (Skype_Inst*)pPInst; + + Memory_U creds = Credentials_Load(User); + int ret = 0; + + if (creds.Memory) + { + // Credentials were found and loaded, now let's parse them. + SResponse LoginDatas; + + if (Credentials_Read(pInst, creds, &LoginDatas) == 0) + { + // Credentials were successfully read :) + // Now verify if they are still valid + uint Idx; + time_t t; + + for (Idx = 0, ret = 1; ret && Idx < LoginDatas.NbObj; Idx++) + { + switch (LoginDatas.Objs[Idx].Id) + { + case OBJ_ID_LDUSER: + // Credentials for wrong user? + ret = !strcasecmp(LoginDatas.Objs[Idx].Value.Memory.Memory, User); + if (pInst->LoginD.User) free(pInst->LoginD.User); + pInst->LoginD.User = strdup(LoginDatas.Objs[Idx].Value.Memory.Memory); + break; + case OBJ_ID_LDEXPIRY: + // Credentials expired? + ret = (int)LoginDatas.Objs[Idx].Value.Nbr * 60 > time(&t)-60; + break; + } + } + FreeResponse(&LoginDatas); + } + free(creds.Memory); + } + return ret; +} + +EXPORT int SkyLogin_PerformLogin(SkyLogin pPInst, char *User, char *Pass) +{ + int ret; + Skype_Inst *pInst = (Skype_Inst*)pPInst; + + if ((ret = PerformLogin(pInst, User, Pass)) > 0) + { + // On successful login, save login datas + Memory_U creds = Credentials_Write(pInst); + if (creds.Memory) + { + Credentials_Save(creds, User); + free (creds.Memory); + } + + if (pInst->LoginD.User) free(pInst->LoginD.User); + pInst->LoginD.User = strdup(User); + } + return ret; +} + +EXPORT int SkyLogin_PerformLoginOAuth(SkyLogin pPInst, const char *OAuth) +{ + int ret; + Skype_Inst *pInst = (Skype_Inst*)pPInst; + + if ((ret = PerformLogin(pInst, OAuth, NULL)) > 0) + { + // On successful login, save login datas + Memory_U creds = Credentials_Write(pInst); + if (creds.Memory) + { + SResponse LoginDatas; + + // We don't know user name, so read it from Credentials + if (Credentials_Parse(creds, &LoginDatas) == 0) + { + uint Idx; + + for (Idx = 0; Idx < LoginDatas.NbObj; Idx++) + { + if (LoginDatas.Objs[Idx].Id == OBJ_ID_LDUSER) + { + Credentials_Save(creds, LoginDatas.Objs[Idx].Value.Memory.Memory); + if (pInst->LoginD.User) free(pInst->LoginD.User); + pInst->LoginD.User = strdup(LoginDatas.Objs[Idx].Value.Memory.Memory); + break; + } + } + FreeResponse(&LoginDatas); + } + free (creds.Memory); + } + } + return ret; +} + + +EXPORT int SkyLogin_CreateUICString(SkyLogin pInst, const char *pszNonce, char *pszOutUIC) +{ + return CreateUICString((Skype_Inst*)pInst, pszNonce, "WS-SecureConversationSESSION KEY TOKEN", pszOutUIC); +} + +EXPORT int SkyLogin_GetCredentialsUIC(SkyLogin pInst, char *pszOutUIC) +{ + return GetCredentialsUIC((Skype_Inst*)pInst, pszOutUIC); +} + +EXPORT char *SkyLogin_GetUser(SkyLogin pInst) +{ + return ((Skype_Inst*)pInst)->LoginD.User; +} diff --git a/protocols/MSN/src/skylogin/skylogin.h b/protocols/MSN/src/skylogin/skylogin.h new file mode 100644 index 0000000000..c03b2d6283 --- /dev/null +++ b/protocols/MSN/src/skylogin/skylogin.h @@ -0,0 +1,57 @@ +typedef void* SkyLogin; + +/* Size of the buffer you should supply as pszOutUIC on SkyLogin_CreateUICString */ +#define UICSTR_SIZE 1024 + +#ifndef EXPORT +#define EXPORT +#endif + +/* Initialize SkyLogin Instance */ +EXPORT SkyLogin SkyLogin_Init(); + +/* Uninitialize Skylogin Instance */ +EXPORT void SkyLogin_Exit(SkyLogin pInst); + +/* Load Credentials from cache, if they are available and valid + * Returns: + * 1 if credentials are successfully loaded, + * 0 if they are invalid or don't exist */ +EXPORT int SkyLogin_LoadCredentials(SkyLogin pInst, char *pszUser); + +/* Perform login with Username and Password + * Returns: + * 1 on success, 0 on failure, -1 on socket error, -2 on bad response */ +EXPORT int SkyLogin_PerformLogin(SkyLogin pInst, char *pszUser, char *pszPass); + +/* Perform login with OAuth token + * Returns: + * 1 on success, 0 on failure, -1 on socket error, -2 on bad response */ +EXPORT int SkyLogin_PerformLoginOAuth(SkyLogin pInst, const char *OAuth); + +/* Creates UIC string from nonce pszNonce and places it in pszOutUIC + * pszOutUIC buffer should be at least UICSTR_SIZE in size. + * + * Returns: + * Size of UIC string in Bytes on success, 0 on failure + */ +EXPORT int SkyLogin_CreateUICString(SkyLogin pInst, const char *pszNonce, char *pszOutUIC); + +/* Gets the base64 encoded signed Credentials after login. They are required if + * you do OAUTH-Login instead of UICString from above. + * pszOutUIC buffer should be at least UICSTR_SIZE in size. + * + * Returns: + * Size of UIC string in Bytes on success, 0 on failure + */ +EXPORT int SkyLogin_GetCredentialsUIC(SkyLogin pInst, char *pszOutUIC); + +/* Gets the Skype username of the currently loaded login credentials. + * This can be useful if you do OAuth login and want to get the assigned + * Skype username without the need to query it seperately so that you can + * i.e. store it in your DB for later calls of SkyLogin_LoadCredentials() + * + * Returns: + * Pointer to the username, NULL if it doesn't exist. Ne need to free()! + */ +EXPORT char *SkyLogin_GetUser(SkyLogin pInst); diff --git a/protocols/MSN/src/skylogin/uic.c b/protocols/MSN/src/skylogin/uic.c new file mode 100644 index 0000000000..fe7ab64f94 --- /dev/null +++ b/protocols/MSN/src/skylogin/uic.c @@ -0,0 +1,105 @@ +/* + * Skype Login + * + * Based on: + * FakeSkype : Skype reverse engineering proof-of-concept client + * Ouanilo MEDEGAN (c) 2006 http://www.oklabs.net + * pyskype : Skype login Python script by uunicorn + * + * Written by: leecher@dose.0wnz.at (c) 2015 + * + * Module: UIC generation + * + */ +#include "common.h" +#include "random.h" +#include "skylogin.h" + +#ifndef CRYPT_WOLFSSL +/* OpenSSL Base64_Encode */ +#include +#include + +static int Base64_Encode(const uchar* in, uint inLen, uchar* out, uint* outLen) +{ + BIO *bmem, *b64; + BUF_MEM *bptr; + int ret=0; + + b64 = BIO_new(BIO_f_base64()); + bmem = BIO_new(BIO_s_mem()); + b64 = BIO_push(b64, bmem); + BIO_write(b64, in, inLen); + BIO_flush(b64); + BIO_get_mem_ptr(b64, &bptr); + if (*outLen>(uint)bptr->length) *outLen=bptr->length; else ret=-1; + memcpy(out, bptr->data, *outLen); + BIO_free_all(b64); + return ret; +} +#endif + + +Memory_U CreateUIC(Skype_Inst *pInst, const char *pszNonce, const char *pszSalt) +{ + Memory_U uic_pkt, uic={0}; + SHA_CTX CredCtx; + uchar *p; + uchar SignedChallenge[0x80] = {0}; + int cbSalt = strlen(pszSalt), cbNonce = strlen(pszNonce); + + if (!(uic_pkt.Memory = (uchar*)malloc(uic_pkt.MsZ = SHA_DIGEST_LENGTH + cbSalt + cbNonce))) + return uic; + SHA1_Init(&CredCtx); + SHA1_Update(&CredCtx, pInst->LoginD.SignedCredentials.Memory, pInst->LoginD.SignedCredentials.MsZ); + SHA1_Update(&CredCtx, pszSalt, cbSalt); + SHA1_Final(uic_pkt.Memory, &CredCtx); + p = uic_pkt.Memory + SHA_DIGEST_LENGTH; + memcpy(p, pszSalt, cbSalt); + p+=cbSalt; + memcpy(p, pszNonce, cbNonce); + BuildUnFinalizedDatas(uic_pkt.Memory, uic_pkt.MsZ, SignedChallenge); + if (RSA_private_encrypt(sizeof(SignedChallenge), SignedChallenge, SignedChallenge, + pInst->LoginD.RSAKeys, RSA_NO_PADDING)<0) + return uic; + free (uic_pkt.Memory); + if (!(uic.Memory = (uchar*)malloc(uic.MsZ = sizeof(SignedChallenge) + pInst->LoginD.SignedCredentials.MsZ + 4))) + { + uic.MsZ=0; + return uic; + } + p = uic.Memory; + *((uint*)p) = htonl(pInst->LoginD.SignedCredentials.MsZ); + p+=sizeof(uint); + memcpy(p, pInst->LoginD.SignedCredentials.Memory, pInst->LoginD.SignedCredentials.MsZ); + p+=pInst->LoginD.SignedCredentials.MsZ; + memcpy(p, SignedChallenge, sizeof(SignedChallenge)); + return uic; +} + + +int CreateUICString(Skype_Inst *pInst, const char *pszNonce, const char *pszSalt, char *pszOutUIC) +{ + Memory_U uic = CreateUIC(pInst, pszNonce, pszSalt); + uint outlen = UICSTR_SIZE; + + if (uic.MsZ && uic.Memory) + { + Base64_Encode(uic.Memory, uic.MsZ, pszOutUIC, &outlen); + pszOutUIC[outlen]=0; + free(uic.Memory); + } else return 0; + return outlen; +} + +int GetCredentialsUIC(Skype_Inst *pInst, char *pszOutUIC) +{ + uint outlen = UICSTR_SIZE; + + if (pInst->LoginD.SignedCredentials.MsZ) + { + Base64_Encode(pInst->LoginD.SignedCredentials.Memory, pInst->LoginD.SignedCredentials.MsZ, pszOutUIC, &outlen); + pszOutUIC[outlen]=0; + } else return 0; + return outlen; +} diff --git a/protocols/MSN/src/skylogin/uic.h b/protocols/MSN/src/skylogin/uic.h new file mode 100644 index 0000000000..ad870035a8 --- /dev/null +++ b/protocols/MSN/src/skylogin/uic.h @@ -0,0 +1,3 @@ +Memory_U CreateUIC(Skype_Inst *pInst, const char *pszNonce, const char *pszSalt); +int CreateUICString(Skype_Inst *pInst, const char *pszNonce, const char *pszSalt, char *pszOutUIC); +int GetCredentialsUIC(Skype_Inst *pInst, char *pszOutUIC); -- cgit v1.2.3