Samstag, 21. Februar 2009

Tracing the crypt API

I managed to get lotro to run on wine on linux. I pretty much used the steps described at lotros appdb entry and also did "winetricks directx9 because of "d3dx9_36.dll".

Here is the complete dump of that run (stripped down to the relevant trace to the crypt api):
Code:
trace:crypt:CryptAcquireContextA (0x5acfb4c, C982860F-EB79-4CFB-8EFC-6F0426F796B6, Microsoft Enhanced Cryptographic Provider v1.0, 1, 00000008)
trace:crypt:CryptAcquireContextW (0x5acfb4c, L"C982860F-EB79-4CFB-8EFC-6F0426F796B6", L"Microsoft Enhanced Cryptographic Provider v1.0", 1, 00000008)
trace:crypt:RSAENH_CPAcquireContext (phProv=0x4f4b008, pszContainer="C982860F-EB79-4CFB-8EFC-6F0426F796B6", dwFlags=00000008, pVTable=0x4f4b088)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000001)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000001)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000000)
trace:crypt:CryptImportKey (0x4f4aff8, 0x1020b30, 308, 0x0, 00000001, 0x582feac)
trace:crypt:RSAENH_CPImportKey (hProv=00000001, pbData=0x1020b30, dwDataLen=308, hPubKey=00000000, dwFlags=00000001, phKey=0x4f4b624)
trace:crypt:import_private_key installing key exchange key
trace:crypt:RSAENH_CPDestroyKey (hProv=00000001, hKey=ffffffff)
trace:crypt:CryptProtectData called
trace:crypt:report pPromptStruct: (nil)
trace:crypt:report dwFlags: 0x0000
trace:crypt:report pDataIn cbData: 308
trace:crypt:report pDataIn pbData @ 0x4f501c0:07,02,00,00,00,a4,00,00,52,53,41,32,00,02,00,00,01,00,00,00,ab,ef,fa,c6,7d,e8,de,fb,68,38,09,92,d9,42,7e,6b,89,9e,21,d7,52,1c,99,3c,17,48,4e,3a,44,02,f2,fa,74,57,da,e4,d3,c0,35,67,fa,6e,df,78,4c,75,3
trace:crypt:CryptProtectData szDataDescr: (nil)
trace:crypt:CryptAcquireContextW (0x33f98c, (null), L"Microsoft Enhanced Cryptographic Provider v1.0", 1, f0000000)
trace:crypt:RSAENH_CPAcquireContext (phProv=0x4f4b160, pszContainer=(null), dwFlags=f0000000, pVTable=0x4f4b170)
trace:crypt:fill_protect_data called
trace:crypt:CryptGenRandom (0x4f4b150, 0, 0x4f4b0e8)
trace:crypt:RSAENH_CPGenRandom (hProv=00000004, dwLen=0, pbBuffer=0x4f4b0e8)
trace:crypt:fill_protect_data &pInfo->salt cbData: 16
trace:crypt:fill_protect_data &pInfo->salt pbData @ 0x4f4b0e8:c8,00,11,00,b8,00,11,00,6f,00,73,00,6f,00,66,00
trace:crypt:CryptCreateHash (0x4f4b150, 0x8004, 0x0, 00000000, 0x33f86c)
trace:crypt:RSAENH_CPCreateHash (hProv=00000004, Algid=00008004, hKey=00000000, dwFlags=00000000, phHash=0x4f4b104)
trace:crypt:CryptHashData (0x4f4b100, 0x4f4b118, 7, 00000000)
trace:crypt:RSAENH_CPHashData (hProv=00000004, hHash=00000005, pbData=0x4f4b118, dwDataLen=7, dwFlags=00000000)
trace:crypt:CryptHashData (0x4f4b100, 0x7bfe56f4, 19, 00000000)
trace:crypt:RSAENH_CPHashData (hProv=00000004, hHash=00000005, pbData=0x7bfe56f4, dwDataLen=19, dwFlags=00000000)
trace:crypt:CryptHashData (0x4f4b100, 0x4f4b0e8, 16, 00000000)
trace:crypt:RSAENH_CPHashData (hProv=00000004, hHash=00000005, pbData=0x4f4b0e8, dwDataLen=16, dwFlags=00000000)
trace:crypt:CryptDeriveKey (0x4f4b150, 0x00006603, 0x4f4b100, 0x00a80001, 0x33f984)
trace:crypt:RSAENH_CPDeriveKey (hProv=00000004, Algid=26115, hBaseData=00000005, dwFlags=00a80001 phKey=0x4f4b134)
trace:crypt:RSAENH_CPGetHashParam (hProv=00000004, hHash=00000005, dwParam=00000002, pbData=0x33f618, pdwDataLen=0x33f7d0, dwFlags=00000000)
trace:crypt:CryptDestroyHash (0x4f4b100)
trace:crypt:RSAENH_CPDestroyHash (hProv=00000004, hHash=00000005)
trace:crypt:CryptCreateHash (0x4f4b150, 0x8004, 0x0, 00000000, 0x33f988)
trace:crypt:RSAENH_CPCreateHash (hProv=00000004, Algid=00008004, hKey=00000000, dwFlags=00000000, phHash=0x4f4b104)
trace:crypt:CryptEncrypt (0x4f4b130, 0x0, 1, 00000000, 0x4f501c0, 0x33f980, 0)
trace:crypt:RSAENH_CPEncrypt (hProv=00000004, hKey=00000006, hHash=00000000, Final=1, dwFlags=00000000, pbData=0x4f501c0, pdwDataLen=0x33f980, dwBufLen=0)
trace:crypt:CryptProtectData required encrypted storage: 312
trace:crypt:CryptEncrypt (0x4f4b130, 0x4f4b100, 1, 00000000, 0x4f50a28, 0x33f980, 312)
trace:crypt:RSAENH_CPEncrypt (hProv=00000004, hKey=00000006, hHash=00000005, Final=1, dwFlags=00000000, pbData=0x4f50a28, pdwDataLen=0x33f980, dwBufLen=312)
trace:crypt:RSAENH_CPHashData (hProv=00000004, hHash=00000005, pbData=0x4f50a28, dwDataLen=308, dwFlags=00000000)
trace:crypt:CryptProtectData &protect_data.cipher cbData: 312
trace:crypt:CryptProtectData &protect_data.cipher pbData @ 0x4f50a28:75,ed,86,25,73,e8,fb,9c,fa,98,dc,41,d2,0c,81,98,bf,ec,43,4b,48,95,af,ce,ec,19,11,80,17,ce,56,9c,04,7b,bd,03,cb,cd,a4,7f,43,50,e4,cb,43,b4,26,cb,44,41,b5,42,84,69,3b,e4,00,de,37,62,32,37,64,46,1a,d6,7
trace:crypt:convert_hash_to_blob called
trace:crypt:CryptGetHashParam (0x4f4b100, 4, 0x33f974, 0x33f86c, 00000000)
trace:crypt:RSAENH_CPGetHashParam (hProv=00000004, hHash=00000005, dwParam=00000004, pbData=0x33f974, pdwDataLen=0x33f86c, dwFlags=00000000)
trace:crypt:CryptGetHashParam (0x4f4b100, 2, 0x4f4af78, 0x33f86c, 00000000)
trace:crypt:RSAENH_CPGetHashParam (hProv=00000004, hHash=00000005, dwParam=00000002, pbData=0x4f4af78, pdwDataLen=0x33f86c, dwFlags=00000000)
trace:crypt:serialize called
trace:crypt:CryptDestroyHash (0x4f4b100)
trace:crypt:RSAENH_CPDestroyHash (hProv=00000004, hHash=00000005)
trace:crypt:CryptDestroyKey (0x4f4b130)
trace:crypt:RSAENH_CPDestroyKey (hProv=00000004, hKey=00000006)
trace:crypt:free_protect_data called
trace:crypt:CryptReleaseContext (0x4f4b150, 00000000)
trace:crypt:RSAENH_CPReleaseContext (hProv=00000004, dwFlags=00000000)
trace:crypt:CryptProtectData pDataOut cbData: 450
trace:crypt:CryptProtectData pDataOut pbData @ 0x4f50b68:01,00,00,00,57,69,6e,65,20,43,72,79,70,74,33,32,20,6f,6b,00,01,00,00,00,57,69,6e,65,20,43,72,79,70,74,33,32,20,6f,6b,00,00,00,00,00,02,00,00,00,00,00,03,66,00,00,a8,00,00,00,10,00,00,00,57,69,6e,65,2
trace:crypt:CryptProtectData returning ok
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000001)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000001)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb28, pdwDataLen=0x33fb84, dwFlags=00000000)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb24, 0x33fb80, 00000001)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb24, pdwDataLen=0x33fb80, dwFlags=00000001)
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb24, 0x33fb80, 00000000)
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb24, pdwDataLen=0x33fb80, dwFlags=00000000)
trace:crypt:CryptImportKey (0x4f4aff8, 0xe5f6b8, 148, 0x0, 00000001, 0x582fec0)
trace:crypt:RSAENH_CPImportKey (hProv=00000001, pbData=0xe5f6b8, dwDataLen=148, hPubKey=00000000, dwFlags=00000001, phKey=0x4f4b6ec)
trace:crypt:import_public_key installing public key
trace:crypt:RSAENH_CPDestroyKey (hProv=00000001, hKey=00000003)
trace:crypt:CryptProtectData called
trace:crypt:report pPromptStruct: (nil)
trace:crypt:report dwFlags: 0x0000
trace:crypt:report pDataIn cbData: 596
trace:crypt:report pDataIn pbData @ 0x4f50598:07,02,00,00,00,a4,00,00,52,53,41,32,00,04,00,00,01,00,01,00,4d,03,8d,d7,d8,a8,85,97,2d,04,de,57,e2,77,c4,bf,c6,13,15,0e,26,72,99,11,a1,cd,f3,8f,d5,5d,63,4c,f3,75,b7,62,9d,ee,e8,d5,c5,a7,0e,3c,9c,51,d
trace:crypt:CryptProtectData szDataDescr: (nil)
trace:crypt:CryptAcquireContextW (0x33f9b0, (null), L"Microsoft Enhanced Cryptographic Provider v1.0", 1, f0000000)
trace:crypt:RSAENH_CPAcquireContext (phProv=0x4f4b180, pszContainer=(null), dwFlags=f0000000, pVTable=0x4f4b190)
trace:crypt:fill_protect_data called
trace:crypt:CryptGenRandom (0x4f4b170, 0, 0x4f4b118)
trace:crypt:RSAENH_CPGenRandom (hProv=00000006, dwLen=0, pbBuffer=0x4f4b118)
trace:crypt:fill_protect_data &pInfo->salt cbData: 16
trace:crypt:fill_protect_data &pInfo->salt pbData @ 0x4f4b118:c8,00,11,00,b8,00,11,00,70,00,68,00,69,00,63,00
trace:crypt:CryptCreateHash (0x4f4b170, 0x8004, 0x0, 00000000, 0x33f890)
trace:crypt:RSAENH_CPCreateHash (hProv=00000006, Algid=00008004, hKey=00000000, dwFlags=00000000, phHash=0x4f4b134)
trace:crypt:CryptHashData (0x4f4b130, 0x4f4b148, 7, 00000000)
trace:crypt:RSAENH_CPHashData (hProv=00000006, hHash=00000005, pbData=0x4f4b148, dwDataLen=7, dwFlags=00000000)
trace:crypt:CryptHashData (0x4f4b130, 0x7bfe56f4, 19, 00000000)
trace:crypt:RSAENH_CPHashData (hProv=00000006, hHash=00000005, pbData=0x7bfe56f4, dwDataLen=19, dwFlags=00000000)
trace:crypt:CryptHashData (0x4f4b130, 0x4f4b118, 16, 00000000)
trace:crypt:RSAENH_CPHashData (hProv=00000006, hHash=00000005, pbData=0x4f4b118, dwDataLen=16, dwFlags=00000000)
trace:crypt:CryptDeriveKey (0x4f4b170, 0x00006603, 0x4f4b130, 0x00a80001, 0x33f9a8)
trace:crypt:RSAENH_CPDeriveKey (hProv=00000006, Algid=26115, hBaseData=00000005, dwFlags=00a80001 phKey=0x4f4af7c)
trace:crypt:RSAENH_CPGetHashParam (hProv=00000006, hHash=00000005, dwParam=00000002, pbData=0x33f63c, pdwDataLen=0x33f7f4, dwFlags=00000000)
trace:crypt:CryptDestroyHash (0x4f4b130)
trace:crypt:RSAENH_CPDestroyHash (hProv=00000006, hHash=00000005)
trace:crypt:CryptCreateHash (0x4f4b170, 0x8004, 0x0, 00000000, 0x33f9ac)
trace:crypt:RSAENH_CPCreateHash (hProv=00000006, Algid=00008004, hKey=00000000, dwFlags=00000000, phHash=0x4f4b134)
trace:crypt:CryptEncrypt (0x4f4af78, 0x0, 1, 00000000, 0x4f50598, 0x33f9a4, 0)
trace:crypt:RSAENH_CPEncrypt (hProv=00000006, hKey=00000007, hHash=00000000, Final=1, dwFlags=00000000, pbData=0x4f50598, pdwDataLen=0x33f9a4, dwBufLen=0)
trace:crypt:CryptProtectData required encrypted storage: 600
trace:crypt:CryptEncrypt (0x4f4af78, 0x4f4b130, 1, 00000000, 0x4f50f20, 0x33f9a4, 600)
trace:crypt:RSAENH_CPEncrypt (hProv=00000006, hKey=00000007, hHash=00000005, Final=1, dwFlags=00000000, pbData=0x4f50f20, pdwDataLen=0x33f9a4, dwBufLen=600)
trace:crypt:RSAENH_CPHashData (hProv=00000006, hHash=00000005, pbData=0x4f50f20, dwDataLen=596, dwFlags=00000000)
trace:crypt:CryptProtectData &protect_data.cipher cbData: 600
trace:crypt:CryptProtectData &protect_data.cipher pbData @ 0x4f50f20:37,4d,86,43,7b,79,12,11,08,e0,7d,84,98,81,59,51,c1,ca,16,8e,11,99,c0,b5,18,52,ab,94,43,9e,33,7a,69,67,e8,96,1b,22,35,2a,19,5f,5b,d3,de,b9,c2,0d,c8,d8,2f,24,19,5f,55,9c,08,aa,87,da,17,b6,9c,55,6d,e6,1
trace:crypt:convert_hash_to_blob called
trace:crypt:CryptGetHashParam (0x4f4b130, 4, 0x33f998, 0x33f890, 00000000)
trace:crypt:RSAENH_CPGetHashParam (hProv=00000006, hHash=00000005, dwParam=00000004, pbData=0x33f998, pdwDataLen=0x33f890, dwFlags=00000000)
trace:crypt:CryptGetHashParam (0x4f4b130, 2, 0x4f4b148, 0x33f890, 00000000)
trace:crypt:RSAENH_CPGetHashParam (hProv=00000006, hHash=00000005, dwParam=00000002, pbData=0x4f4b148, pdwDataLen=0x33f890, dwFlags=00000000)
trace:crypt:serialize called
trace:crypt:CryptDestroyHash (0x4f4b130)
trace:crypt:RSAENH_CPDestroyHash (hProv=00000006, hHash=00000005)
trace:crypt:CryptDestroyKey (0x4f4af78)
trace:crypt:RSAENH_CPDestroyKey (hProv=00000006, hKey=00000007)
trace:crypt:free_protect_data called
trace:crypt:CryptReleaseContext (0x4f4b170, 00000000)
trace:crypt:RSAENH_CPReleaseContext (hProv=00000006, dwFlags=00000000)
trace:crypt:CryptProtectData pDataOut cbData: 738
trace:crypt:CryptProtectData pDataOut pbData @ 0x4f51180:01,00,00,00,57,69,6e,65,20,43,72,79,70,74,33,32,20,6f,6b,00,01,00,00,00,57,69,6e,65,20,43,72,79,70,74,33,32,20,6f,6b,00,00,00,00,00,02,00,00,00,00,00,03,66,00,00,a8,00,00,00,10,00,00,00,57,69,6e,65,2
trace:crypt:CryptProtectData returning ok
trace:crypt:CryptGenKey (0x4f4aff8, 26625, 00000001, 0x582fed4)
trace:crypt:RSAENH_CPGenKey (hProv=00000001, aiAlgid=26625, dwFlags=00000001, phKey=0x4f4b704)
trace:crypt:CryptExportKey (0x4f4b700, 0x4f4b6e8, 1, 00000000, (nil), 0x79f1c89c)
trace:crypt:RSAENH_CPExportKey (hProv=00000001, hKey=00000006, hPubKey=00000004, dwBlobType=00000001, dwFlags=00000000, pbData=(nil),pdwDataLen=0x79f1c89c)
trace:crypt:CryptExportKey (0x4f4b700, 0x4f4b6e8, 1, 00000000, 0x6e15be0, 0x79f1c89c)
trace:crypt:RSAENH_CPExportKey (hProv=00000001, hKey=00000006, hPubKey=00000004, dwBlobType=00000001, dwFlags=00000000, pbData=0x6e15be0,pdwDataLen=0x79f1c89c)
trace:crypt:CryptEncrypt (0x4f4b700, 0x0, 1, 00000000, (nil), 0x79f1c87c, 265)
trace:crypt:RSAENH_CPEncrypt (hProv=00000001, hKey=00000006, hHash=00000000, Final=1, dwFlags=00000000, pbData=(nil), pdwDataLen=0x79f1c87c, dwBufLen=265)
trace:crypt:CryptEncrypt (0x4f4b700, 0x0, 1, 00000000, 0x6e1fe34, 0x79f1c880, 265)
trace:crypt:RSAENH_CPEncrypt (hProv=00000001, hKey=00000006, hHash=00000000, Final=1, dwFlags=00000000, pbData=0x6e1fe34, pdwDataLen=0x79f1c880, dwBufLen=265)
trace:crypt:CryptExportKey (0x4f4b700, 0x4f4b6e8, 1, 00000000, (nil), 0x79f1c944)
trace:crypt:RSAENH_CPExportKey (hProv=00000001, hKey=00000006, hPubKey=00000004, dwBlobType=00000001, dwFlags=00000000, pbData=(nil),pdwDataLen=0x79f1c944)
trace:crypt:CryptExportKey (0x4f4b700, 0x4f4b6e8, 1, 00000000, 0x6e4ea48, 0x79f1c944)
trace:crypt:RSAENH_CPExportKey (hProv=00000001, hKey=00000006, hPubKey=00000004, dwBlobType=00000001, dwFlags=00000000, pbData=0x6e4ea48,pdwDataLen=0x79f1c944)
trace:crypt:CryptEncrypt (0x4f4b700, 0x0, 1, 00000000, (nil), 0x79f1c924, 265)
trace:crypt:RSAENH_CPEncrypt (hProv=00000001, hKey=00000006, hHash=00000000, Final=1, dwFlags=00000000, pbData=(nil), pdwDataLen=0x79f1c924, dwBufLen=265)
trace:crypt:CryptEncrypt (0x4f4b700, 0x0, 1, 00000000, 0x6e58c9c, 0x79f1c928, 265)
trace:crypt:RSAENH_CPEncrypt (hProv=00000001, hKey=00000006, hHash=00000000, Final=1, dwFlags=00000000, pbData=0x6e58c9c, pdwDataLen=0x79f1c928, dwBufLen=265)
trace:crypt:CryptExportKey (0x4f4b700, 0x4f4b6e8, 1, 00000000, (nil), 0x79f1c944)
trace:crypt:RSAENH_CPExportKey (hProv=00000001, hKey=00000006, hPubKey=00000004, dwBlobType=00000001, dwFlags=00000000, pbData=(nil),pdwDataLen=0x79f1c944)
trace:crypt:CryptExportKey (0x4f4b700, 0x4f4b6e8, 1, 00000000, 0x6e4ea48, 0x79f1c944)
trace:crypt:RSAENH_CPExportKey (hProv=00000001, hKey=00000006, hPubKey=00000004, dwBlobType=00000001, dwFlags=00000000, pbData=0x6e4ea48,pdwDataLen=0x79f1c944)
trace:crypt:CryptEncrypt (0x4f4b700, 0x0, 1, 00000000, (nil), 0x79f1c924, 265)
trace:crypt:RSAENH_CPEncrypt (hProv=00000001, hKey=00000006, hHash=00000000, Final=1, dwFlags=00000000, pbData=(nil), pdwDataLen=0x79f1c924, dwBufLen=265)
trace:crypt:CryptEncrypt (0x4f4b700, 0x0, 1, 00000000, 0x6e58c9c, 0x79f1c928, 265)
trace:crypt:RSAENH_CPEncrypt (hProv=00000001, hKey=00000006, hHash=00000000, Final=1, dwFlags=00000000, pbData=0x6e58c9c, pdwDataLen=0x79f1c928, dwBufLen=265)
So, I hope you brought some time sine we are going through these calls ... one by one.

Code:
trace:crypt:CryptAcquireContextA (0x5acfb4c, C982860F-EB79-4CFB-8EFC-6F0426F796B6, Microsoft Enhanced Cryptographic Provider v1.0, 1, 00000008)
  • 0x5acfb4c: memory offset where the generated crypt provider will be placed, uninteresting
  • C982860F-EB79-4CFB-8EFC-6F0426F796B6: the key containers name ... a GUID which I have no info about. I think it's a GUID chosen by Codemasters to identify their container.
  • Microsoft Enhanced Cryptographic Provider v1.0: this is MS_ENHANCED_PROV
  • 1: this is PROV_RSA_FULL
  • 00000008: this is CRYPT_NEWKEYSET

Code:
trace:crypt:CryptAcquireContextW (0x5acfb4c, L"C982860F-EB79-4CFB-8EFC-6F0426F796B6", L"Microsoft Enhanced Cryptographic Provider v1.0", 1, 00000008)
Wine internally forwards ASCII calls to theid unicode equivalents. you can ignore this.

Code:
trace:crypt:RSAENH_CPAcquireContext (phProv=0x4f4b008, pszContainer="C982860F-EB79-4CFB-8EFC-6F0426F796B6", dwFlags=00000008, pVTable=0x4f4b088)
This is wines internal call the actual cryptographic provider, RSA. Not much of an interest here.

Code:
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000001)
  • 0x4f4aff8: This is the provider aquired by CryptAcquireContextA. Interesting is that in CryptAcquireContextA it was 0x5acfb4c while here it is 0x4f4aff8. Looks like it was copied in memory to be safe of modifications (or I'm just misreading the log here).
  • 22: is 0x16 in hex, so PP_ENUMALGS_EX
  • 0x33fb00: an instance of the PP_ENUMALGS_EX structure
  • 0x33fb5c: pointer to the length of the PP_ENUMALGS_EX structure, out param in this case
  • 00000001: first call, so CRYPT_FIRST must be set

Code:
trace:crypt:RSAENH_CPGetProvParam (hProv=00000001, dwParam=00000016, pbData=0x33fb00, pdwDataLen=0x33fb5c, dwFlags=00000001)
  • 00000001: internal handle to the provider
  • 16: PP_PROVTYPE
  • 0x33fb00: out pointer for data
  • 0x33fb5c: out pointer for data length
  • 00000001: CRYPT_FIRST
Forward call to the RSA provider. These calls are pretty much straight forward and not really relevant for our output. I'll skip these from now on and only come back to them if I think they are interesting.

Code:
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb00, 0x33fb5c, 00000000)
Exactly the same call as the CryptGetProvParam above without the CRYPT_FIRST flag set. No idea why one would call that multiple times. Maybe CryptGetProvParam returns information about a different algo each time? And maybe they search for a specific one? No idea.

Code:
trace:crypt:CryptImportKey (0x4f4aff8, 0x1020b30, 308, 0x0, 00000001, 0x582feac)
  • 0x4f4aff8: handle to the CSP, we already know from the calls before
  • 0x1020b30: dang, the public key as a blob. need to figure out where it comes from. really interesting call. Definitely need to find out what is in there.
  • 308: length of the key
  • 0x0: hmm, really interesting! is set to zero which means: they key in not encrypted. plain public key in memory.
  • 00000001: looks like CRYPT_EXPORTABLE
  • 0x582feac: handle to the imported key.

Code:
trace:crypt:CryptProtectData called
trace:crypt:report pPromptStruct: (nil)
trace:crypt:report dwFlags: 0x0000
trace:crypt:report pDataIn cbData: 308
trace:crypt:report pDataIn pbData @ 0x4f501c0:07,02,00,00,00,a4,00,00,52,53,41,32,00,02,00,00,01,00,00,00,ab,ef,fa,c6,7d,e8,de,fb,68,38,09,92,d9,42,7e,6b,89,9e,21,d7,52,1c,99,3c,17,48,4e,3a,44,02,f2,fa,74,57,da,e4,d3,c0,35,67,fa,6e,df,78,4c,75,3
trace:crypt:CryptProtectData szDataDescr: (nil)
Strange looking trace, i guess.
  • pDataIn: data to be encrypted.
  • szDataDescr: no description of the pDataIn given. totally ok.
  • pOptionalEntropy: missing this one .... means no extra password or entropy given
  • pPromptStruct: no prompts given. totally ok.
  • dwFlags: no special crypt protect, good.
  • pDataOut: encrypted data ... pretty much irrelevant
So at this point the valuable data from pbData was symetric encrypted. The wine source states that this is only for host encryption where you cant trust other users, see dlls/crypt32/protectdata.c. It's worth noting that this call ends with
Code:
trace:crypt:CryptProtectData returning ok
while the stuff in between is wines interal calls.

Code:
trace:crypt:CryptGetProvParam (0x4f4aff8, 22, 0x33fb28, 0x33fb84, 00000001)
Looks like they are searching a algo or a key again.

Code:
trace:crypt:CryptImportKey (0x4f4aff8, 0xe5f6b8, 148, 0x0, 00000001, 0x582fec0)
  • 0x4f4aff8: handle to the CSP, as always
  • 0xe5f6b8: again, the key to import
  • 148: short one this time
  • 0x0: not encrypted
  • 00000001: CRYPT_EXPORTABLE
  • 0x582fec0: handle to the imported key.

Code:
trace:crypt:CryptProtectData called
trace:crypt:report pPromptStruct: (nil)
trace:crypt:report dwFlags: 0x0000
trace:crypt:report pDataIn cbData: 596
trace:crypt:report pDataIn pbData @ 0x4f50598:07,02,00,00,00,a4,00,00,52,53,41,32,00,04,00,00,01,00,01,00,4d,03,8d,d7,d8,a8,85,97,2d,04,de,57,e2,77,c4,bf,c6,13,15,0e,26,72,99,11,a1,cd,f3,8f,d5,5d,63,4c,f3,75,b7,62,9d,ee,e8,d5,c5,a7,0e,3c,9c,51,d
trace:crypt:CryptProtectData szDataDescr: (nil)
Again protects the key against access from other users.

Code:
trace:crypt:CryptGenKey (0x4f4aff8, 26625, 00000001, 0x582fed4)
  • 0x4f4aff8: handle to the CSP
  • 26625: this is CALG_RC4, stream encryption
  • 00000001: CRYPT_EXPORTABLE
  • 0x582fed4: handle where the key will be stored

Code:
trace:crypt:CryptExportKey (0x4f4b700, 0x4f4b6e8, 1, 00000000, (nil), 0x79f1c89c)
  • 0x4f4b700: handle to the key that will be exported.
  • 0x4f4b6e8: this is the handle to a public key used for encryption of 0x4f4b700
  • 1: SIMPLEBLOB
  • 00000000: no dwParam
  • (nil): ok, we have no idea how large the exported key will be. this is a dry run to determine the size
  • 0x79f1c89c: size will be put here
This was only a dry run to find out how large the exported key will be. Now the client will allocate a buffer and really export the key.

Code:
trace:crypt:CryptExportKey (0x4f4b700, 0x4f4b6e8, 1, 00000000, 0x6e15be0, 0x79f1c89c)
  • 0x4f4b700: same as above
  • 0x4f4b6e8: same as above
  • 1: same as above
  • 00000000: same as above
  • 0x6e15be0: buffer where the encrypted key will end in
  • 0x79f1c89c: same as above

Code:
trace:crypt:CryptEncrypt (0x4f4b700, 0x0, 1, 00000000, (nil), 0x79f1c87c, 265)
  • 0x4f4b700: handle to the key that will be used for encryption
  • 0x0: encrypted data will not be hashed
  • 1: final is set so the data passed in this call is the complete data
  • 00000000: no dwFlags
  • (nil): again, dry run. will put the size into the next param
  • 0x79f1c87c: size of the buffer necessary to store the encrypted result
  • 265: means we want to encrypt 265 bytes
Dry run is through, now on the the encryption with the buffer.

Code:
trace:crypt:CryptEncrypt (0x4f4b700, 0x0, 1, 00000000, 0x6e1fe34, 0x79f1c880, 265)
  • 0x4f4b700: same as a above
  • 0x0: same as a above
  • 1: same as a above
  • 00000000: same as a above
  • 0x6e1fe34: buffer containing the plain text and containing the ciphered text after this function passed
  • 0x79f1c87c: size of ciphered data
  • 265: same as above

Ok, that's pretty much it. I'll try to explain in normal text what happens here.
  • The client is loading 2 stored keys here. I'm not sure why there are 2 but I guess that at least on of them is the public key RSA of the server.
  • The client creates a key that can be used for fast encryption (RC4 based).
  • This key is exported and encrypted with the public key of the server. The result is transfered to the server where it decrypts the RC4 key with his private RSA key.
  • I guess the next logical step would be the server creating so "welcome" packet and encrypting it with RC4. The client would then check if the welcome message from the server was valid (which means: the server had the private RSA key necessary for decrypting the RC4).

The big issue: We are not the server and we don't own the private key. This means there is no possibility to get this private key. So where is the point we could attack to break the encrpytion? Well, what if the client wouldn't use the original public key for encryption, but one that we created ourselves? This way we would have the public and the private key. Once we have the RC4 key we can encrypt and decrypt any of the data.

Next to that we need the possibility to decrypt the traffic between client and server of a production system. We could hack the CryptGenKey to dump the key it creates. This would enable us to look into the traffic that is happening between the client and the server.

Hope I didn't bore you to death. Thanks for reading.

Donnerstag, 19. Februar 2009

Here are a few packet analysis for:
1st packet from the client to the chatserver
Code:
0x0000 -> 0x0003: spacer sequence 00 00 00 00
0x0004 -> 0x0005: length 2c01 = 1, 2e01 = 2, 3001 = 3, 3201 = 4, 3601 = 6, 3801 = 7, 3e01 = 10
0x0006 -> 0x000d: spacer sequence 00 00 01 00 00 00 00 00
0x000e -> 0x0011: seems to be a weird encoding of unix time
0x0012 -> 0x0015: spacer sequence 00 00 00 00
0x0016 -> 0x0028: 061004_chat_fe_2_2
0x0029 -> 0x002A: length 1501 = 1, 1701 = 2, 1901 = 3, 1b01 = 4, 1f01 = 6, 2101 = 7, 2701 = 10
0x002B -> 0x0034: spacer sequence 00 00 02 00 00 40 04 00 00 00
0x0035 -> 0x0037: seems to be another? a weird encoding of unix time
0x0038 -> 0x0038: I(49) = start of subscription id
0x0039 -> 0x003a: subscription id in UTF-16
0x003b -> 0x0041: spacer sequence 00 02 01 00 00 81 00
0x0042 -> 0x0141: token we got from the login meta server
The encoded unix time looks like that:
Code:
2009-01-26   23:44:xx   469037df   d43c
2009-01-26 23:45:xx 46903705 fa3c
2009-01-26 23:46:xx 47903746 3b3d
2009-01-26 23:47:xx 47903780 753d
2009-01-26 23:47:xx 479037a1 963d
2009-01-26 23:48:xx 479037be b33d
2009-01-26 23:52:xx 489037c4 b93e
2009-01-26 23:53:xx 48903705 fa3e
2009-01-26 23:56:xx 49903790 853f
2009-01-27 00:00:xx 4a9037a6 9b40
2009-01-27 00:02:xx 4a9037ec e140
2009-01-27 00:03:xx 4b90373f 3441
2009-01-27 00:04:xx 4b903790 8541

1st packet from the client to the game server
Code:
0x0000-0x0029: UDP/IP connection from 192.168.1.4 TO 192.168.1.1:9000
0x002A-0x00AD: Spacer 00 00 00 00
0x00AE-0x00AF: Opcode for connect, I guess
0x0030-0x0037: pretty constant 00 00 01 00 00 00 00 00 ... maybe packet number to simulate TCP packet ordering?
0x0038-0x003B: seems pretty much a random number, needs investigation
0x003C-0x003F: Spacer 00 00 00 00
0x0040-0x009F: Pretty much constant, only changing bytes: 0x0080 and 0x008C-0x008E ... looks like these crappy timestamps we also see in the connect to the chat server
0x00A0-0x011F: No idea. Changes completely on every request. Something cyphered. Or the key. High entropy anyway
0x0120-0x0123: length of the following cyphered gls ticket ... 0x08 + len for all length <= 80, 0x09 after that. looks like the heading key gets one byte longer? little endian 8 bit atomic 0x0124-0x022C: cyphered gls ticket
So, what are the next logical steps? As I said earlier the chat server is pretty much irrelevant at this early stage. So we (or to be honest I) should focus on looking into the cyphered stuff. From what I can tell lotroclient.exe uses the crypt API provided by advapi32.dll. I think that we need to intercept the calls to this API to find out what exactly is happening. I tried to get uhooker to run but failed. Now I'm thinking about Wine on Windows or running LOTRO under Linux. This would enable us to run "WINEDEBUG=+crypt lotroclient.exe" to dump the method calls to advapi32.dll. The issue is: I could not get wine to run on windows or lotro to run on linux. And then emupedia went down and I got disappointed and stoped working on that for the last weeks :-)

Relavant DLL calls are:
CryptReleaseContext
CryptDecrypt
CryptEncrypt
CryptGenKey
CryptAcquireContextA
CryptGenRandom
CryptGetKeyParam
CryptExportKey
CryptImportKey
CryptGetProvParam
CryptDestroyKey

As you can see they are using a varity of functions. What I assume is the following:
  1. they are calling CryptAcquireContextA (note: This is the ASCII version!) to get access to the crypto apo
  2. they use CryptGenKey or CryptImportKey to get hold of a key to be used for the session
  3. they CryptEncrypt the payload of the package

I think that the most important point is: do they generate a key? or are they using a precomputed key? If the key is precomputed we are pretty much busted. I think they'd use a secure algorihm and a public key, meaning we'd have no possibility to generate the private key. We'd have to use an advapi32.dll that disables encryption and just returns the unecrypted payload. But replacing advapi32.dll is not trivial. The worst case would be: the generate a random key pair (symetric or asymetric) and encrypt that using the public key of the server and use the generated key for the communication in game. But that's most likely the case. This way you can safely exchange a simple symetric key for blazing fast encryption over a secure inital layer. The later communication would be done using the symetric key.
Whatever it is, we'll need to find out by tracing the calls to the crypto api.