<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Decrypt my World : Debugger scripts</title><link>http://blogs.msdn.com/alejacma/archive/tags/Debugger+scripts/default.aspx</link><description>Tags: Debugger scripts</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>CryptographicException: The data to be decrypted exceeds the maximum for this modulus of 0 bytes</title><link>http://blogs.msdn.com/alejacma/archive/2009/10/09/cryptographicexception-the-data-to-be-decrypted-exceeds-the-maximum-for-this-modulus-of-0-bytes.aspx</link><pubDate>Fri, 09 Oct 2009 14:06:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9905407</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/9905407.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=9905407</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;Some time ago a customer of mine was getting the following &lt;A href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.cryptographicexception.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.cryptographicexception.aspx"&gt;CryptographicException&lt;/A&gt; when calling&amp;nbsp;&lt;A href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.encryptedxml.decryptdocument.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.xml.encryptedxml.decryptdocument.aspx"&gt;EncryptedXml.DecryptDocument&lt;/A&gt;&amp;nbsp;method to decrypt an &lt;A href="http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.aspx" mce_href="http://msdn.microsoft.com/en-us/library/system.xml.xmldocument.aspx"&gt;XmlDocument&lt;/A&gt; in their &lt;STRONG&gt;.NET&lt;/STRONG&gt; app:&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;&amp;nbsp;[System.Security.Cryptography.CryptographicException] = {"&lt;STRONG&gt;The data to be decrypted exceeds the maximum for this modulus of 0 bytes&lt;/STRONG&gt;"}&lt;BR&gt;_HResult = -2146233296&lt;BR&gt;_HResult =&lt;STRONG&gt; 0x80131430&lt;/STRONG&gt;&lt;BR&gt;No Inner Exception&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;This was&amp;nbsp;only happening with a &lt;STRONG&gt;smart card certificate &lt;/STRONG&gt;associated to a specific &lt;STRONG&gt;third-party CSP &lt;/STRONG&gt;(non-MS).&lt;/P&gt;
&lt;P&gt;In order to troubleshoot this, I used my &lt;A href="http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx"&gt;CryptoAPI Tracer script&lt;/A&gt;&amp;nbsp;to get some traces while reproducing the issue. Thanks to my script I could see these &lt;STRONG&gt;calls&lt;/STRONG&gt; that .NET is making to the third-party CSP behind the scenes (I will omit key container and CSP names as they are not needed to understand the issue):&lt;/P&gt;&lt;PRE&gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;

&lt;STRONG&gt;CryptAcquireContextA&lt;/STRONG&gt; (0x570)

&lt;STRONG&gt;IN&lt;/STRONG&gt;
&lt;STRONG&gt;pszContainer&lt;/STRONG&gt;
001bf1a0 "&lt;STRONG&gt;Cert Container Name&lt;/STRONG&gt;"

&lt;STRONG&gt;pszProvider&lt;/STRONG&gt;
001b4698 "&lt;STRONG&gt;Third-party CSP&lt;/STRONG&gt;"

dwProvType
PROV_RSA_FULL

dwFlags
0

&lt;STRONG&gt;OUT&lt;/STRONG&gt;
&lt;STRONG&gt;hProv&lt;/STRONG&gt;
&lt;STRONG&gt;0x1bea28&lt;/STRONG&gt;

RESULT
CryptAcquireContextA (0x570) SUCCEEDED

&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;

&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;

&lt;STRONG&gt;CryptGetUserKey&lt;/STRONG&gt; (0x570)

&lt;STRONG&gt;IN&lt;/STRONG&gt;
&lt;STRONG&gt;hProv&lt;/STRONG&gt;
&lt;STRONG&gt;0x1bea28&lt;/STRONG&gt;

dwKeySpec
AT_KEYEXCHANGE

&lt;STRONG&gt;OUT&lt;/STRONG&gt;
&lt;STRONG&gt;hUserKey&lt;/STRONG&gt;
&lt;STRONG&gt;0x1bf1a0&lt;/STRONG&gt;

RESULT
CryptGetUserKey (0x570) SUCCEEDED

&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;

&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;

CryptGetKeyParam (0x570)

IN
hKey
0x1bf1a0

dwParam
KP_ALGID

pbData
NULL

dwDataLen
0

dwFlags
0

OUT
dwDataLen
4

RESULT
CryptGetKeyParam (0x570) SUCCEEDED

&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;

&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;

CryptGetKeyParam (0x570)

IN
hKey
0x1bf1a0

dwParam
KP_ALGID

pbData
0x1bd228

dwDataLen
4

dwFlags
0

OUT
bData
001bd228 0000a400

dwDataLen
4

RESULT
CryptGetKeyParam (0x570) SUCCEEDED

&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;

&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;

&lt;STRONG&gt;CryptGetKeyParam&lt;/STRONG&gt; (0x570)

&lt;STRONG&gt;IN&lt;/STRONG&gt;
&lt;STRONG&gt;hKey&lt;/STRONG&gt;
&lt;STRONG&gt;0x1bf1a0&lt;/STRONG&gt;

&lt;STRONG&gt;dwParam&lt;/STRONG&gt;
&lt;STRONG&gt;KP_KEYLEN&lt;/STRONG&gt;

pbData
NULL

&lt;STRONG&gt;dwDataLen
0&lt;/STRONG&gt;

dwFlags
0

&lt;STRONG&gt;OUT
dwDataLen
4&lt;/STRONG&gt;

RESULT
CryptGetKeyParam (0x570) SUCCEEDED

&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;

&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;

&lt;STRONG&gt;CryptGetKeyParam&lt;/STRONG&gt; (0x570)

&lt;STRONG&gt;IN
hKey
0x1bf1a0&lt;/STRONG&gt;

&lt;STRONG&gt;dwParam
KP_KEYLEN&lt;/STRONG&gt;

&lt;STRONG&gt;pbData
0x1bd228&lt;/STRONG&gt;

&lt;STRONG&gt;dwDataLen
4&lt;/STRONG&gt;

dwFlags
0

&lt;STRONG&gt;OUT
bData
001bd228 00000000&lt;/STRONG&gt;

&lt;STRONG&gt;dwDataLen
4&lt;/STRONG&gt;

RESULT
CryptGetKeyParam (0x570) SUCCEEDED

&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;

&lt;/PRE&gt;
&lt;P&gt;These calls mean the following: before .NET tries to decrypt the XML, it asks the CSP for some information on the key it will use to decrypt, like its length (&lt;A href="http://msdn.microsoft.com/en-us/library/aa379949(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa379949(VS.85).aspx"&gt;CryptGetKeyParam&lt;/A&gt; API with &lt;STRONG&gt;KP_KEYLEN&lt;/STRONG&gt; flag). For some unknown reason the &lt;STRONG&gt;third-party CSP is returning a length of 0 for the key&lt;/STRONG&gt;&amp;nbsp;(&lt;STRONG&gt;pbData&lt;/STRONG&gt; points to &lt;STRONG&gt;0&lt;/STRONG&gt;), which is &lt;STRONG&gt;invalid&lt;/STRONG&gt;, thus .NET won't continue with the decryption and will raise the exception we've seen. Why is the CSP returning an invalid length? Only the CSP developers can answer that question.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;In my customer's particular case, the CSP developers quickly localized and fixed the issue.&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Regards,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9905407" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugger+scripts/default.aspx">Debugger scripts</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/System.Security/default.aspx">System.Security</category></item><item><title>CryptographicException: Unable to open the access token of the current thread</title><link>http://blogs.msdn.com/alejacma/archive/2008/07/30/cryptographicexception-unable-to-open-the-access-token-of-the-current-thread.aspx</link><pubDate>Wed, 30 Jul 2008 10:41:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8791188</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8791188.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8791188</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;When working with &lt;STRONG&gt;RSACryptoServiceProvider&lt;/STRONG&gt;, we may get an exception like the following:&lt;/P&gt;&lt;PRE&gt;System.Security.Cryptography.&lt;STRONG&gt;CryptographicException&lt;/STRONG&gt;: &lt;STRONG&gt;Unable to open the access token of the current thread&lt;/STRONG&gt;
   at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
   at System.Security.Cryptography.Utils._GetKeyParameter(SafeKeyHandle hKey, UInt32 paramID)
   at System.Security.Cryptography.Utils.GetKeyPairHelper(CspAlgorithmType keyType, CspParameters parameters, Boolean randomKeyContainer, Int32 dwKeySize, SafeProvHandle&amp;amp; safeProvHandle, SafeKeyHandle&amp;amp; safeKeyHandle)
   at System.Security.Cryptography.RSACryptoServiceProvider.GetKeyPair()
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(Int32 dwKeySize, CspParameters parameters, Boolean useDefaultKeySize)
   at System.Security.Cryptography.RSACryptoServiceProvider..ctor(CspParameters parameters)
&lt;/PRE&gt;
&lt;P&gt;I've seen this exception i.e. when signing an XML with a certificate associated to a specific Cryptographic Service Provider (CSP).&lt;/P&gt;
&lt;P&gt;Let's use my &lt;A class="" href="http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx"&gt;CryptoAPI Tracer script&lt;/A&gt;&amp;nbsp;to get all &lt;STRONG&gt;CryptoAPI calls&lt;/STRONG&gt; that .NET is making &lt;STRONG&gt;behind the scenes&lt;/STRONG&gt;. This will help us to know exactly what's going on.&lt;/P&gt;
&lt;P&gt;We can see in the logs generated by the script the call to &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa379886(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa379886(VS.85).aspx"&gt;CryptAcquireContext&lt;/A&gt; we make to get the &lt;STRONG&gt;key container&lt;/STRONG&gt; of the certificate. We can&amp;nbsp;also see the &lt;STRONG&gt;CSP&lt;/STRONG&gt; associated to the certificate:&lt;/P&gt;&lt;PRE&gt;&lt;STRONG&gt;CryptAcquireContextA&lt;/STRONG&gt; (0xd8c)

IN
pszContainer
00228620  "2e065b6c-027a-4746-bdf3-901a9980"
00228640  "66ea"

pszProvider
00205e60  "&lt;STRONG&gt;Third-party CSP&lt;/STRONG&gt;"

dwProvType
PROV_RSA_FULL

dwFlags
0

OUT
hProv
0x228248

RESULT
CryptAcquireContextA (0xd8c) SUCCEEDED
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;Note: I won't use the real name of the third-party CSP where I detected this issue. This post is for illustration purposes only. I don't prettend to blame anyone in particular.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Then .NET makes the following call to &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa379949.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa379949.aspx"&gt;CryptGetKeyParam&lt;/A&gt; to find out the &lt;STRONG&gt;size of a buffer&lt;/STRONG&gt; which will hold the value of the &lt;STRONG&gt;algorithm&lt;/STRONG&gt; &lt;STRONG&gt;of the key&lt;/STRONG&gt;:&lt;/P&gt;&lt;PRE&gt;&lt;STRONG&gt;CryptGetKeyParam&lt;/STRONG&gt; (0xd8c)

&lt;STRONG&gt;IN&lt;/STRONG&gt;
hKey
0x230058

&lt;STRONG&gt;dwParam&lt;/STRONG&gt;
&lt;STRONG&gt;KP_ALGID&lt;/STRONG&gt;

&lt;STRONG&gt;pbData&lt;/STRONG&gt;
&lt;STRONG&gt;NULL&lt;/STRONG&gt; 

&lt;STRONG&gt;dwDataLen&lt;/STRONG&gt;
&lt;STRONG&gt;0&lt;/STRONG&gt;

dwFlags
0

&lt;STRONG&gt;OUT&lt;/STRONG&gt;
&lt;STRONG&gt;dwDataLen&lt;/STRONG&gt;
&lt;STRONG&gt;4&lt;/STRONG&gt;

RESULT
CryptGetKeyParam (0xd8c) FAILED
LastErrorValue: (HRESULT) &lt;STRONG&gt;0x80010125&lt;/STRONG&gt; (2147549477) - &lt;STRONG&gt;Unable to open the access token of the current thread&lt;/STRONG&gt;
LastStatusValue: (NTSTATUS) 0xc0000034 - Object Name not found.
&lt;/PRE&gt;
&lt;P&gt;Note on &lt;STRONG&gt;IN parameters&lt;/STRONG&gt;: &lt;/P&gt;
&lt;P&gt;- This &lt;STRONG&gt;hKey&lt;/STRONG&gt; value is the key handle. &lt;/P&gt;
&lt;P&gt;- This &lt;STRONG&gt;dwParam&lt;/STRONG&gt; value indicates that we want the algorithm of the key. &lt;/P&gt;
&lt;P&gt;- This &lt;STRONG&gt;pbData&lt;/STRONG&gt; value indicates that there is no buffer available yet. &lt;/P&gt;
&lt;P&gt;- This &lt;STRONG&gt;pdwDataLen&lt;/STRONG&gt; value is 0 because we want to find out the size that we need for the pbData buffer. &lt;/P&gt;
&lt;P&gt;- &lt;STRONG&gt;dwFlags&lt;/STRONG&gt; should always be 0. &lt;/P&gt;
&lt;P&gt;This call is returning 4 in &lt;STRONG&gt;dwDataLen&lt;/STRONG&gt;, which is correct as the &lt;STRONG&gt;ALGID&lt;/STRONG&gt; will be 4 bytes long. But the API is also returning the error &lt;STRONG&gt;0x80010125&lt;/STRONG&gt; (2147549477) - "&lt;STRONG&gt;Unable to open the access token of the current thread&lt;/STRONG&gt;". CryptoAPI just passes the parameters to the CSP and returns the results. The&amp;nbsp;call to the API is 100% correct, but the CSP is not honoring it. This is &lt;STRONG&gt;not a bug in .NET or CryptoAPI&lt;/STRONG&gt;. This is a &lt;STRONG&gt;bug on the CSP&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;If you are facing this issue please &lt;STRONG&gt;contact the CSP&amp;nbsp;provider&lt;/STRONG&gt;. At least in&amp;nbsp;the case of the third-party CSP where we found the issue they were already aware of it. They immediately sent an upgrade to our customers which fixed this issue.&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8791188" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/RSACryptoServiceProvider/default.aspx">RSACryptoServiceProvider</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptAcquireContext/default.aspx">CryptAcquireContext</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugger+scripts/default.aspx">Debugger scripts</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/System.Security/default.aspx">System.Security</category></item><item><title>RSACryptoServiceProvider fails when used with ASP.NET</title><link>http://blogs.msdn.com/alejacma/archive/2007/12/03/rsacryptoserviceprovider-fails-when-used-with-asp-net.aspx</link><pubDate>Mon, 03 Dec 2007 12:00:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6596423</guid><dc:creator>alejacma</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/6596423.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=6596423</wfw:commentRss><description>&lt;P&gt;Hi, welcome back,&lt;/P&gt;
&lt;P&gt;I will talk today about a very common issue we face when we try to use .NET's &lt;STRONG&gt;RSACryptoServiceProvider&lt;/STRONG&gt; class in &lt;STRONG&gt;ASP.NET&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;When we try to create a new RSACryptoServiceProvider object in this scenario, we may&amp;nbsp;get the following exception: &lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;EM&gt;"System.Security.Cryptography.CryptographicException: The system cannot find the file specified".&lt;/EM&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;By using my &lt;A class="" title="CryptoAPI Tracer script" href="http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx"&gt;CryptoAPI Tracer script&lt;/A&gt;&amp;nbsp;we can take a look to the &lt;STRONG&gt;CryptoAPI&lt;/STRONG&gt; calls that .NET is making behind the scenes. Thanks to this script we will be able to see the exact API that is failing and the exact error (which most of the time .NET masks).&lt;/P&gt;
&lt;P mce_keep="true"&gt;In our case, the API that fails is &lt;STRONG&gt;CryptAcquireContext&lt;/STRONG&gt;, and it fails with error &lt;STRONG&gt;#2&lt;/STRONG&gt;&amp;nbsp;(&lt;STRONG&gt;ERROR_FILE_NOT_FOUND&lt;/STRONG&gt;). According to &lt;A class="" title=CryptAcquireContext href="http://msdn2.microsoft.com/en-us/library/aa379886.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa379886.aspx"&gt;CryptAcquireContext&lt;/A&gt; documentation, this error means the following:&lt;BR&gt;"&lt;BR&gt;&lt;EM&gt;The profile of the user is not loaded and cannot be found. This happens when the application impersonates a user, for example, the IUSR_ComputerName account.&lt;/EM&gt;&lt;BR&gt;"&lt;/P&gt;
&lt;P&gt;By default, ASP.NET won't load the user profile. Take a look to the parameters of the problematic&amp;nbsp;&lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa379886.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa379886.aspx"&gt;CryptAcquireContext&lt;/A&gt; call as being shown in the log file that my script generated. If this API is not being called with CRYPT_MACHINE_KEYSET (to use the machine profile) or CRYPT_VERIFYCONTEXT (to use temporary key stores), it will try to access the key stores in the user profile, and it will fail because its not loaded.&lt;/P&gt;
&lt;P&gt;Which options do we have here then?&lt;/P&gt;
&lt;P&gt;1) If we need each user running your ASP.NET app to use their own key stores, we will have to load their user profile. We can do it with &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa374341.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa374341.aspx"&gt;LoadUserProfile&lt;/A&gt; API. The only problem is that the privileges needed to execute this API are quite powerful for a standard user.&lt;/P&gt;
&lt;P&gt;2) If we still need the user profile and don't want to give users enough privileges to run LoadUserProfile, there is a trick we can use: &lt;STRONG&gt;Service Control Manager &lt;/STRONG&gt;(&lt;STRONG&gt;SCM&lt;/STRONG&gt;) will automatically load the profile of the user that a Windows service uses to run. So we may create a dummy Windows service which runs with our user's credentials. This service won't need to do anything special, just stay alive. SCM will load the user profile for us and ASP.NET will be able to use it automatically once it gets loaded.&lt;/P&gt;
&lt;P&gt;3)&amp;nbsp;We may also use machine key stores instead of user's. We just have to pass &lt;STRONG&gt;CRYPT_MACHINE_KEYSET&lt;/STRONG&gt; flag to CryptAcquireContext. In order to do that in .NET, we may use a code like this:&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;CspParameters RSAParams = new CspParameters();&lt;BR&gt;RSAParams.Flags = CspProviderFlags.&lt;STRONG&gt;UseMachineKeyStore&lt;/STRONG&gt;;&lt;BR&gt;RSACryptoServiceProvider sp = new RSACryptoServiceProvider(1024, RSAParams);
&lt;/PRE&gt;
&lt;P&gt;Note. When we use machine key stores, any user in that machine may have access to those keys.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;U&gt;&lt;FONT color=#0066cc&gt;&lt;/FONT&gt;&lt;/U&gt;I hope this helps.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Alex&amp;nbsp;(Alejandro Campos Magencio)&lt;BR&gt;&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6596423" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/RSACryptoServiceProvider/default.aspx">RSACryptoServiceProvider</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptAcquireContext/default.aspx">CryptAcquireContext</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugger+scripts/default.aspx">Debugger scripts</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/System.Security/default.aspx">System.Security</category></item><item><title>How to trace CryptoAPI calls (2)</title><link>http://blogs.msdn.com/alejacma/archive/2007/11/08/how-to-trace-cryptoapi-calls-2.aspx</link><pubDate>Fri, 09 Nov 2007 01:46:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5999992</guid><dc:creator>alejacma</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/5999992.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=5999992</wfw:commentRss><description>&lt;P&gt;Hi, welcome back,&lt;/P&gt;
&lt;P&gt;Let's try to understand a bit better what's going on my&amp;nbsp;&lt;A class="" title="CryptoAPI Tracer script" href="http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx"&gt;CryptoAPI Tracer script&lt;/A&gt;.&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's take a look to one of the most important breakpoints I set on a &lt;STRONG&gt;CryptoAPI&lt;/STRONG&gt; function:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;STRONG&gt;bm Advapi32!CryptAcquireContextW ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptAcquireContextW (%#x)\\n\", @$tid;&amp;nbsp;&amp;nbsp;&amp;nbsp; .echo;.echo IN;&amp;nbsp;&amp;nbsp;&amp;nbsp; .echo pszContainer; .if(poi(@esp+8)=0) {.echo NULL} .else {du poi(@esp+8)};&amp;nbsp;&amp;nbsp;&amp;nbsp; .echo;.echo pszProvider; .if(poi(@esp+c)=0) {.echo NULL} .else {du poi(@esp+c)};&amp;nbsp;&amp;nbsp;&amp;nbsp; .echo;.echo dwProvType; .if(poi(@esp+10)=1) {.echo PROV_RSA_FULL} .elsif(poi(@esp+10)=0x18) {.echo PROV_RSA_AES} .else {.printf \"%d\\n\", poi(@esp+10)};&amp;nbsp;&amp;nbsp;&amp;nbsp; .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+14); .if((poi(@esp+14)&amp;amp;0x0`F0000000)=0x0`F0000000) {.echo CRYPT_VERIFYCONTEXT(0xf0000000)}; .if((poi(@esp+14)&amp;amp;0x0`00000008)=0x0`00000008){.echo CRYPT_NEWKEYSET(0x8)}; .if((poi(@esp+14)&amp;amp;0x0`00000010)=0x0`00000010) {.echo CRYPT_DELETEKEYSET(0x10)}; .if((poi(@esp+14)&amp;amp;0x0`00000020)=0x0`00000020) {.echo CRYPT_MACHINE_KEYSET(0x20)}; .if((poi(@esp+14)&amp;amp;0x0`00000040)=0x0`00000040) {.echo CRYPT_SILENT(0x40)};&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; bp /t @$thread poi(@esp) \"&amp;nbsp;&amp;nbsp;&amp;nbsp; .echo;.echo OUT;&amp;nbsp;&amp;nbsp;&amp;nbsp; .if(poi(@esp-14)=0) {.echo phProv;.echo NULL} .else {.echo hProv; .if(poi(poi(@esp-14))=0) {.echo NULL} .else {.printf \\\"%#x\\\\n\\\", poi(poi(@esp-14))} };&amp;nbsp;&amp;nbsp;&amp;nbsp; .echo;.echo RESULT;&amp;nbsp;&amp;nbsp;&amp;nbsp; .if(@eax=1) {.printf \\\"CryptAcquireContextW (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptAcquireContextW (%#x) FAILED\\\\n\\\", @$tid;!gle};&amp;nbsp;&amp;nbsp;&amp;nbsp; .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;&amp;nbsp;&amp;nbsp;&amp;nbsp; G;\";&amp;nbsp;&amp;nbsp;&amp;nbsp; G;";&lt;BR&gt;&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;It looks a bit complex, but it's not so much. Some of the basics where already explained &lt;A class="" title=here href="http://blogs.msdn.com/alejacma/archive/2007/10/29/how-to-trace-cryptoapi-calls.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/10/29/how-to-trace-cryptoapi-calls.aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;Imagine we have the following API declaration in C:&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;int __stdcall myFunction(int a, int b, int c);&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;If I set a &lt;STRONG&gt;breakpoint&lt;/STRONG&gt; on &lt;EM&gt;myFunction&lt;/EM&gt;, and because we use &lt;A class="" title=__stdcall href="http://msdn2.microsoft.com/en-us/library/zxk0tw93(VS.80).aspx" mce_href="http://msdn2.microsoft.com/en-us/library/zxk0tw93(VS.80).aspx"&gt;__stdcall&lt;/A&gt; calling convention (the same as Win32 API/CryptoAPI functions), the &lt;STRONG&gt;stack&lt;/STRONG&gt; will look this way just when we reach the breakpoint, before we run any code on &lt;EM&gt;myFunction&lt;/EM&gt;:&lt;/P&gt;&lt;PRE&gt;return address &amp;lt;-- esp
a              &amp;lt;-- esp+4
b              &amp;lt;-- esp+8
c              &amp;lt;-- esp+c
xxxxxxxx
yyyyyyyy
zzzzzzzz
&lt;/PRE&gt;
&lt;P&gt;"&lt;STRONG&gt;esp&lt;/STRONG&gt;" (stack pointer) register will be pointing to the address where we'll return after finishing executing &lt;EM&gt;myFunction&lt;/EM&gt;. If we want to i.e. access the second parameter of the function, we can use the address esp+8.&lt;/P&gt;
&lt;P&gt;When we finish executing &lt;EM&gt;myFunction&lt;/EM&gt;&amp;nbsp;and we return from it&lt;EM&gt;,&lt;/EM&gt; "&lt;STRONG&gt;eax&lt;/STRONG&gt;" register will&amp;nbsp;contain the return value of the API and the stack will look like this:&lt;/P&gt;&lt;PRE&gt;xxxxxxxx       &amp;lt;-- esp
yyyyyyyy
zzzzzzzz
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;Now, if we want to access one of the parameters of the API we just called (i.e. because it's an out parameter), we have to remember that the information of the stack is not cleaned. So even if "esp" register points to "xxxxxxxx" now, the parameters of the API are still on the stack:&lt;/P&gt;&lt;PRE&gt;a              &amp;lt;-- esp-c
b              &amp;lt;-- esp-8
c              &amp;lt;-- esp-4
xxxxxxxx       &amp;lt;-- esp
yyyyyyyy
zzzzzzzz
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;So if we want to i.e.&amp;nbsp;access the first parameter of the API we can use esp-c address.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;Having said this, let's write the breakpoint above in a different way:&lt;/P&gt;&lt;PRE&gt;000 bm Advapi32!CryptAcquireContextW 
001 "
002     .printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptAcquireContextW (%#x)\\n\", @$tid;
003
004     .echo;
005     .echo IN;
006
007     .echo pszContainer;
008     .if(poi(@esp+8)=0)
009     {
010         .echo NULL
011     }
012     .else
013     {
014         du poi(@esp+8)
015     };
016
017     .echo;
018     .echo pszProvider;
019     .if(poi(@esp+c)=0)
020     {
021         .echo NULL
022     }
023     .else 
024     {
025         du poi(@esp+c)
026     };
027
028     .echo;
029     .echo dwProvType;
030     .if(poi(@esp+10)=1) 
031     {
032         .echo PROV_RSA_FULL
033     }
034     .elsif(poi(@esp+10)=0x18) 
035     {
036         .echo PROV_RSA_AES
037     }
038     .else
039     {
040         .printf \"%d\\n\", poi(@esp+10)
041     };
042
043     .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+14); 
044     .if((poi(@esp+14)&amp;amp;0x0`F0000000)=0x0`F0000000) 
045     {
046         .echo CRYPT_VERIFYCONTEXT(0xf0000000)
047     }; 
048     .if((poi(@esp+14)&amp;amp;0x0`00000008)=0x0`00000008)
049     {
050         .echo CRYPT_NEWKEYSET(0x8)
051     };
052     .if((poi(@esp+14)&amp;amp;0x0`00000010)=0x0`00000010)
053     {
054         .echo CRYPT_DELETEKEYSET(0x10)
055     };
056     .if((poi(@esp+14)&amp;amp;0x0`00000020)=0x0`00000020)
057     {
058         .echo CRYPT_MACHINE_KEYSET(0x20)
059     };
060     .if((poi(@esp+14)&amp;amp;0x0`00000040)=0x0`00000040)
061     {
062         .echo CRYPT_SILENT(0x40)
063     };
064
065     bp /t @$thread poi(@esp)
066     \"
067         .echo;
068         .echo OUT;
069
070         .if(poi(@esp-14)=0)
071         {
072             .echo phProv;
073             .echo NULL
074         }
075         .else
076         {
077             .echo hProv;
078             .if(poi(poi(@esp-14))=0)
079             {
080                 .echo NULL
081             }
082             .else
083             {
084                 .printf \\\"%#x\\\\n\\\", poi(poi(@esp-14))
085             }
086         };
087
088         .echo;
089         .echo RESULT;
090
091         .if(@eax=1)
092         {
093             .printf \\\"CryptAcquireContextW (%#x) SUCCEEDED\\\\n\\\", @$tid
094         }
095         .else
096         {
097             .printf \\\"CryptAcquireContextW (%#x) FAILED\\\\n\\\", @$tid;!gle
098         };
099
100         .echo;
101         .echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;
102
103         G;
104     \";
105
106     G;
107 ";
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;000) We set a breakpoint on the UNICODE version of &lt;A class="" title=CryptAcquireContext href="http://msdn2.microsoft.com/en-us/library/aa379886.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa379886.aspx"&gt;CryptAcquireContext&lt;/A&gt; API. This is the declaration of the API:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;BOOL WINAPI CryptAcquireContext(__out HCRYPTPROV* phProv,&amp;nbsp;__in LPCTSTR pszContainer, __in LPCTSTR pszProvider, __in DWORD dwProvType, __in DWORD dwFlags);&lt;/EM&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;The following commands will be executed when the application calls this API and we reach the breakpoint:&lt;/P&gt;
&lt;P mce_keep="true"&gt;002) We print the name of the API and the id of the thread which calls it.&lt;/P&gt;
&lt;P mce_keep="true"&gt;005) We print the string "IN", and after that we'll print the values of the __in parameters of the API.&lt;/P&gt;
&lt;P mce_keep="true"&gt;007-015) We print &lt;EM&gt;pszContainer&lt;/EM&gt; parameter as a string of Unicode chars,&amp;nbsp;after checking if it's NULL or not.&lt;/P&gt;
&lt;P mce_keep="true"&gt;018-026) We print &lt;EM&gt;pszProvider&lt;/EM&gt; parameter as a string of Unicode chars, after checking if it's NULL or not.&lt;/P&gt;
&lt;P mce_keep="true"&gt;029-041) We print &lt;EM&gt;dwProvType&lt;/EM&gt; parameter. If we know the type we print it in clear text, otherwise we just print its numeric value.&lt;/P&gt;
&lt;P mce_keep="true"&gt;043-063) We print &lt;EM&gt;dwFlags&lt;/EM&gt; parameter in Hexadecimal. If we know the values of those flags, we print them in clear text.&lt;/P&gt;
&lt;P mce_keep="true"&gt;065) Now we want to know what happened after the API finished executing. We set a breakpoint at the return address where we will return after calling the API. If we don't want weird things to happen on multi-threaded applications, we have to specify on which thread ("$thread" pseudo-register) we are setting that breakpoint. &lt;/P&gt;
&lt;P mce_keep="true"&gt;106) Once we've set the breakpoint at 065, we can continue the execution of the application.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Now, let see what happens when we stop on breakpoint set at 065:&lt;/P&gt;
&lt;P mce_keep="true"&gt;068) We print the string "OUT", and after that we'll print the values of the __out parameters of the API.&lt;/P&gt;
&lt;P mce_keep="true"&gt;070-086) We print&amp;nbsp;&lt;EM&gt;phProv&lt;/EM&gt; parameter. This is a pointer to &lt;EM&gt;hProv&lt;/EM&gt;. If the pointer is not NULL, we print the Hexadecimal value of &lt;EM&gt;hProv&lt;/EM&gt;, after checking if&amp;nbsp;this value is&amp;nbsp;NULL or not.&lt;/P&gt;
&lt;P mce_keep="true"&gt;089) We print the string "RESULT", and after that we'll print the return value of the API, and the error if there was one.&lt;/P&gt;
&lt;P mce_keep="true"&gt;091-098) We show if the API succeeded or not. If not, we also show the error value that the API returned.&lt;/P&gt;
&lt;P mce_keep="true"&gt;103) Now that we know the result of calling the API, we can continue the execution of the application and trace more APIs.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5999992" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptAcquireContext/default.aspx">CryptAcquireContext</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/WinDbg/default.aspx">WinDbg</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Cdb/default.aspx">Cdb</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugger+scripts/default.aspx">Debugger scripts</category></item><item><title>CryptoAPI Tracer script</title><link>http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx</link><pubDate>Thu, 01 Nov 2007 00:09:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5805089</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/5805089.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=5805089</wfw:commentRss><description>&lt;P&gt;Hi, welcome back,&lt;/P&gt;
&lt;P&gt;As I promised in my previous post, &lt;A class="" title="How to trace CryptoAPI calls" href="http://blogs.msdn.com/alejacma/archive/2007/10/29/how-to-trace-cryptoapi-calls.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/10/29/how-to-trace-cryptoapi-calls.aspx"&gt;How to trace CryptoAPI calls&lt;/A&gt;, I'm posting the complete&amp;nbsp;&lt;STRONG&gt;script&lt;/STRONG&gt; I'm developing to &lt;STRONG&gt;trace&lt;/STRONG&gt; all &lt;STRONG&gt;CryptoAPI&lt;/STRONG&gt; calls being made by an application. This script shows the In &amp;amp; Out parameters being passed to the API, the result of calling the API, and in case of error, the error number and message that the API returned. &lt;/P&gt;
&lt;P&gt;This script is a Beta version. I'm missing many APIs, and what I call in the script "DEFAULT TRACERS" are there to catch any API starting by Crypt* and Cert* and remind me which ones I'm missing in case I need them. Currently those default tracers are disabled.&amp;nbsp;Additionally,&amp;nbsp;when flags are passed to an API I try to show those flags in clear text, but I'm still missing many of them. MSDN and Platform SDK will help me complete the script. I just need time. A lot of time. There are many APIs, many parameters, many flags.&lt;/P&gt;
&lt;P&gt;But with current version of the script I've solved many, many cases related to CryptoAPI issues very, very easily. The APIs I have already included are the most commonly used by my customers, .NET and CAPICOM.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;PRE&gt;************************************************************************
* CRYPTO API TRACER by ALEJANDRO CAMPOS MAGENCIO (BETA)
************************************************************************
*
* DISCLAIMER
*
* This sample script is not supported under any Microsoft standard 
* support program or service. 
* The sample script is provided as it is without warranty of any kind.
* Microsoft further disclaims all implied warranties including, without 
* limitation, any implied warranties of merchantability or of fitness 
* for a particular purpose.
* The entire risk arising out of the use or performance of the sample 
* script remains with you. In no event shall Microsoft, its authors, or 
* anyone else involved in the creation, production, or delivery of the 
* script be liable for any damages whatsoever (including, without 
* limitation, damages for loss of business profits, business 
* interruption, loss of business information, or other pecuniary loss) 
* arising out of the use of or inability to use the sample script, even 
* if Microsoft has been advised of the possibility of such damages.
*
* PREREQUISITES:
*
* 1) Download the latest version of "Debugging Tools for Windows"
*    http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx
*
* 2) Install the tools in any machine, and copy the directory with the 
*    tools to the target machine (they don't need to be installed in the 
*    target machine). We will use "cdb.exe" to run the script.
*
* HOW TO TRACE an already running application:
*
* -  Run the following command to attach the "cdb.exe" debugger to the 
*    application and run the script:
*    "
*    cdb.exe -pn application.exe -cf "PathToScript\script.txt"
*    "
*
*    Note: You may target the application by PID by using "-p PID" 
*          instead of "-pn application.exe".
*    Note: All traces will be written to log.txt in the current 
*          directory. You may change the path to the log file at the end 
*          of the script.
*
* HOW TO FINISH the tracing:
*
* A) If the application has finished execution, enter the "q" command on 
*    "cdb.exe" to quit the debugger.
*
* B) If the application is still running, press "Ctrl+Break" to break
*    into "cdb.exe" and pause the application. Enter the "qd" command to
*    detach and quit the debugger (it won't kill the target app which 
*    will resume execution) or "q" to just quit (it will kill the target 
*    app).
*
************************************************************************

************************************************************************
* DEFAULT TRACERS 
************************************************************************

* Remove * to enable 
*bm Advapi32!Crypt* ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\n(%#x)\\n\\n\", @$tid;    .echo CALL;kb 1;    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT; .printf \\\"%#x\\\\n\\\\n\\\", @eax; !gle;    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

* Remove * to enable 
*bm Crypt32!Crypt* ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\n(%#x)\\n\\n\", @$tid;    .echo CALL;kb 1;    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT; .printf \\\"%#x\\\\n\\\\n\\\", @eax; !gle;    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

* Remove * to enable 
*bm Crypt32!Cert* ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\n(%#x)\\n\\n\", @$tid;    .echo CALL;kb 1;    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT; .printf \\\"%#x\\\\n\\\\n\\\", @eax; !gle;    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

************************************************************************
* ADVAPI32!CRYPT* TRACERS
************************************************************************

bm Advapi32!CryptAcquireContextW ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptAcquireContextW (%#x)\\n\", @$tid;    .echo;.echo IN;    .echo pszContainer; .if(poi(@esp+8)=0) {.echo NULL} .else {du poi(@esp+8)};    .echo;.echo pszProvider; .if(poi(@esp+c)=0) {.echo NULL} .else {du poi(@esp+c)};    .echo;.echo dwProvType; .if(poi(@esp+10)=1) {.echo PROV_RSA_FULL} .elsif(poi(@esp+10)=0x18) {.echo PROV_RSA_AES} .else {.printf \"%d\\n\", poi(@esp+10)};    .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+14); .if((poi(@esp+14)&amp;amp;0x0`F0000000)=0x0`F0000000) {.echo CRYPT_VERIFYCONTEXT(0xf0000000)}; .if((poi(@esp+14)&amp;amp;0x0`00000008)=0x0`00000008){.echo CRYPT_NEWKEYSET(0x8)}; .if((poi(@esp+14)&amp;amp;0x0`00000010)=0x0`00000010) {.echo CRYPT_DELETEKEYSET(0x10)}; .if((poi(@esp+14)&amp;amp;0x0`00000020)=0x0`00000020) {.echo CRYPT_MACHINE_KEYSET(0x20)}; .if((poi(@esp+14)&amp;amp;0x0`00000040)=0x0`00000040) {.echo CRYPT_SILENT(0x40)};     bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .if(poi(@esp-14)=0) {.echo phProv;.echo NULL} .else {.echo hProv; .if(poi(poi(@esp-14))=0) {.echo NULL} .else {.printf \\\"%#x\\\\n\\\", poi(poi(@esp-14))} };    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptAcquireContextW (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptAcquireContextW (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptAcquireContextA ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptAcquireContextA (%#x)\\n\", @$tid;    .echo;.echo IN;    .echo pszContainer; .if(poi(@esp+8)=0) {.echo NULL} .else {da poi(@esp+8)};    .echo;.echo pszProvider; .if(poi(@esp+c)=0) {.echo NULL} .else {da poi(@esp+c)};    .echo;.echo dwProvType; .if(poi(@esp+10)=1) {.echo PROV_RSA_FULL} .elsif(poi(@esp+10)=24) {.echo PROV_RSA_AES} .else {.printf \"%d\\n\", poi(@esp+10)};    .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+14); .if((poi(@esp+14)&amp;amp;0x0`F0000000)=0x0`F0000000){.echo CRYPT_VERIFYCONTEXT(0xf0000000)}; .if((poi(@esp+14)&amp;amp;0x0`00000008)=0x0`00000008){.echo CRYPT_NEWKEYSET(0x8)}; .if((poi(@esp+14)&amp;amp;0x0`00000010)=0x0`00000010) {.echo CRYPT_DELETEKEYSET(0x10)}; .if((poi(@esp+14)&amp;amp;0x0`00000020)=0x0`00000020) {.echo CRYPT_MACHINE_KEYSET(0x20)}; .if((poi(@esp+14)&amp;amp;0x0`00000040)=0x0`00000040) {.echo CRYPT_SILENT(0x40)};    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .if(poi(@esp-14)=0) {.echo phProv;.echo NULL} .else {.echo hProv; .if(poi(poi(@esp-14))=0) {.echo NULL} .else {.printf \\\"%#x\\\\n\\\", poi(poi(@esp-14))} };    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptAcquireContextA (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptAcquireContextA (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptGetProvParam ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptGetProvParam (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hProv\\n%#x\\n\\n\", poi(@esp+4);    .echo dwParam; .if(poi(@esp+8)=0x16) {.echo PP_ENUMALGS_EX} .else {.printf \"%#x\\n\", poi(@esp+8)};    .echo;.echo pbData; .if(poi(@esp+c)=0) {.echo NULL} .else {.printf \"%#x\\n\", poi(@esp+c)};    .printf \"\\ndwDataLen\\n%d\\n\", poi(poi(@esp+10));        .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+14);    bp /t @$thread poi(@esp) \"   .echo;.echo OUT;    .if((poi(@esp-c)!=0) &amp;amp; (poi(poi(@esp-8))!=0)) {r $t0=(poi(poi(@esp-8))+3)/4; .echo bData; dd poi(@esp-c) l@$t0; .echo};    .printf \\\"dwDataLen\\\\n%d\\\\n\\\", poi(poi(@esp-8));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptGetProvParam (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptGetProvParam (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptGenRandom ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptGenRandom (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hProv\\n%#x\\n\\n\", poi(@esp+4);    .printf \"dwLen\\n%d\\n\", poi(@esp+8);    r $t0=(poi(@esp+8)+3)/4; .echo;.echo bBuffer; dd poi(@esp+c) l@$t0;    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    r $t0=(poi(@esp-8)+3)/4; .echo bBuffer; dd poi(@esp-4) l@$t0;    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptGenRandom (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptGenRandom (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptReleaseContext ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptReleaseContext (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hProv\\n%#x\\n\\n\", poi(@esp+4);    .printf \"dwFlags\\n%#x\\n\", poi(@esp+8);    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptReleaseContext (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptReleaseContext (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptCreateHash ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptCreateHash (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hProv\\n%#x\\n\\n\", poi(@esp+4);    .echo Algid; .if(poi(@esp+8)=0x00008004) {.echo CALG_SHA} .elsif(poi(@esp+8)=0x00008003) {.echo CALG_MD5} .else {.printf \"%#x\\n\", poi(@esp+8)};    .printf \"\\nhKey\\n%#x\\n\\n\", poi(@esp+c);    .printf \"dwFlags\\n%#x\\n\", poi(@esp+10);    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .printf \\\"hHash\\\\n%#x\\\\n\\\", poi(poi(@esp-4));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptCreateHash (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptCreateHash (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";


bm Advapi32!CryptHashData ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptHashData (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hHash\\n%#x\\n\\n\", poi(@esp+4);    r $t0=(poi(@esp+c)+3)/4; .echo bData;dd poi(@esp+8) l@$t0;    .printf \"\\ndwDataLen\\n%d\\n\\n\", poi(@esp+c);    .printf \"dwFlags\\n%#x\\n\", poi(@esp+10);    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptHashData (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptHashData (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptDestroyHash ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptDestroyHash (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hHash\\n%#x\\n\", poi(@esp+4);    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptDestroyHash (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptDestroyHash (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptGetHashParam ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptGetHashParam (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hHash\\n%#x\\n\", poi(@esp+4);    .echo;.echo dwParam; .if(poi(@esp+8)=0x1) {.echo HP_ALGID} .elsif(poi(@esp+8)=0x2) {.echo HP_HASHVAL} .elsif(poi(@esp+8)=0x4) {.echo HP_HASHSIZE} .else {.printf \"%#x\\n\", poi(@esp+8)};    .echo;.echo pbData; .if(poi(@esp+c)=0) {.echo NULL} .else {.printf \"%#x\\n\", poi(@esp+c)};    .printf \"\\ndwDataLen\\n%d\\n\", poi(poi(@esp+10));    .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+14);    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .if((poi(@esp-c)!=0) &amp;amp; (poi(poi(@esp-8))!=0)) {r $t0=(poi(poi(@esp-8))+3)/4; .echo bData; dd poi(@esp-c) l@$t0; .echo};    .printf \\\"dwDataLen\\\\n%d\\\\n\\\", poi(poi(@esp-8));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptGetHashParam (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptGetHashParam (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptGetUserKey ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptGetUserKey (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hProv\\n%#x\\n\\n\", poi(@esp+4);    .echo dwKeySpec; .if(poi(@esp+8)=0x1) {.echo AT_KEYEXCHANGE} .elsif(poi(@esp+8)=0x2) {.echo AT_SIGNATURE} .else {.printf \"%#x\\n\", poi(@esp+8)};    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .printf \\\"hUserKey\\\\n%#x\\\\n\\\", poi(poi(@esp-4));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptGetUserKey (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptGetUserKey (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptGenKey ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptGenKey (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hProv\\n%#x\\n\\n\", poi(@esp+4);    .echo Algid; .if(poi(@esp+8)=0x1) {.echo AT_KEYEXCHANGE} .elsif(poi(@esp+8)=0x2) {.echo AT_SIGNATURE} .elsif(poi(@esp+8)=0x00008004) {.echo CALG_SHA} .else {.printf \"%#x\\n\", poi(@esp+8)};    .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+c); r $t0=(poi(@esp+c))&amp;gt;&amp;gt;10; .printf \"Key Size(%d)\\n\", @$t0; .if((poi(@esp+c)&amp;amp;0x0`00000001)=0x0`00000001) {.echo CRYPT_EXPORTABLE(0x1)};    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .printf \\\"hKey\\\\n%#x\\\\n\\\", poi(poi(@esp-4));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptGenKey (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptGenKey (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptGetKeyParam ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptGetKeyParam (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hKey\\n%#x\\n\\n\", poi(@esp+4);    .echo dwParam; .if(poi(@esp+8)=0x7) {.echo KP_ALGID} .elsif(poi(@esp+8)=0x9) {.echo KP_KEYLEN} .else {.printf \"%#x\\n\", poi(@esp+8)};    .echo;.echo pbData; .if(poi(@esp+c)=0) {.echo NULL} .else {.printf \"%#x\\n\", poi(@esp+c)};    .printf \"\\ndwDataLen\\n%d\\n\", poi(poi(@esp+10));    .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+14);    bp /t @$thread poi(@esp) \"   .echo;.echo OUT;    .if((poi(@esp-c)!=0) &amp;amp; (poi(poi(@esp-8))!=0)) {r $t0=(poi(poi(@esp-8))+3)/4; .echo bData; dd poi(@esp-c) l@$t0; .echo};    .printf \\\"dwDataLen\\\\n%d\\\\n\\\", poi(poi(@esp-8));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptGetKeyParam (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptGetKeyParam (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptDestroyKey ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptDestroyKey (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hKey\\n%#x\\n\", poi(@esp+4);   bp /t @$thread poi(@esp) \"    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptDestroyKey (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptDestroyKey (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptEncrypt ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptEncrypt (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hKey\\n%#x\\n\\n\", poi(@esp+4);    .printf \"hHash\\n%#x\\n\\n\", poi(@esp+8);    .echo Final; .if(poi(@esp+c)=0) {.echo FALSE} .else {.echo TRUE};    .echo;.echo dwFlags; .if(poi(@esp+10)=0x40) {.echo CRYPT_OAEP} .else {.printf \"%#x\\n\", poi(@esp+10)}; .echo;    .if((poi(@esp+14)!=0) &amp;amp; (poi(poi(@esp+18))!=0)) {r $t0=(poi(poi(@esp+18))+3)/4; .echo bData; dd poi(@esp+14) l@$t0} .elsif(poi(@esp+14)=0) {.echo pbData;.echo NULL} .else {.printf \"pbData\\n%#x\\n\", poi(@esp+14)}; .echo;    .printf \"dwDataLen\\n%d\\n\\n\", poi(poi(@esp+18));    .printf \"dwBufLen\\n%d\\n\", poi(@esp+1c);    bp /t @$thread poi(@esp) \"   .echo;.echo OUT;    .if((poi(@esp-c)!=0) &amp;amp; (poi(poi(@esp-8))!=0)) {r $t0=(poi(poi(@esp-8))+3)/4; .echo bData; dd poi(@esp-c) l@$t0; .echo};    .printf \\\"dwDataLen\\\\n%d\\\\n\\\", poi(poi(@esp-8));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptEncrypt (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptEncrypt (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptDecrypt ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptDecrypt (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hKey\\n%#x\\n\\n\", poi(@esp+4);    .printf \"hHash\\n%#x\\n\\n\", poi(@esp+8);   .echo Final; .if(poi(@esp+c)=0) {.echo FALSE} .else {.echo TRUE};    .echo;.echo dwFlags; .if(poi(@esp+10)=0x40) {.echo CRYPT_OAEP} .else {.printf \"%#x\\n\", poi(@esp+10)}; .echo;    .if((poi(@esp+14)!=0) &amp;amp; (poi(poi(@esp+18))!=0)) {r $t0=(poi(poi(@esp+18))+3)/4; .echo bData; dd poi(@esp+14) l@$t0; .echo} .elsif(poi(@esp+14)=0) {.echo pbData;.echo NULL;.echo};    .printf \"dwDataLen\\n%d\\n\\n\", poi(poi(@esp+18));    bp /t @$thread poi(@esp) \"   .echo;.echo OUT;    .if((poi(@esp-8)!=0) &amp;amp; (poi(poi(@esp-4))!=0)) {r $t0=(poi(poi(@esp-4))+3)/4; .echo bData; dd poi(@esp-8) l@$t0; .echo};    .printf \\\"dwDataLen\\\\n%d\\\\n\\\", poi(poi(@esp-4));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptDecrypt (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptDecrypt (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptSetHashParam ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptSetHashParam (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hHash\\n%#x\\n\", poi(@esp+4);    .echo;.echo dwParam; .if(poi(@esp+8)=0x2) {.echo HP_HASHVAL} .elsif(poi(@esp+8)=0x5) {.echo HP_HMAC_INFO} .else {.printf \"%#x\\n\", poi(@esp+8)};    .echo; .if(poi(@esp+c)=0) {.echo pbData;.echo NULL} .else {.echo bData;dd poi(@esp+c)};     .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+10);    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptSetHashParam (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptSetHashParam (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptSignHashW ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\CryptSignHashW (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hHash\\n%#x\\n\", poi(@esp+4);    .echo;.echo dwKeySpec; .if (poi(@esp+8)=0x1) {.echo AT_KEYEXCHANGE} .elsif (poi(@esp+8)=0x2) {.echo AT_SIGNATURE} .else {.printf \"%#x\\n\", poi(@esp+8)};    .echo;.echo sDescription; .if (poi(@esp+c)=0) {.echo NULL} .else {du poi(@esp+c)};    .printf \"dwFlags\\n%#x\\n\", poi(@esp+10);        .echo;.echo pbSignature; .if (poi(@esp+14)=0) {.echo NULL} .else {.printf \"%#x\\n\", poi(@esp+14)};    .printf \"\\ndwSigLen\\n%d\\n\", poi(poi(@esp+18));    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .if((poi(@esp-8)!=0) &amp;amp; (poi(poi(@esp-4))!=0)) {r $t0=(poi(poi(@esp-4))+3)/4; .echo bSignature; dd poi(@esp-8) l@$t0; .echo};    .printf \\\"dwSigLen\\\\n%d\\\\n\\\", poi(poi(@esp-4));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptSignHashW (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptSignHashW (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;"; 

bm Advapi32!CryptSignHashA ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptSignHashA (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hHash\\n%#x\\n\", poi(@esp+4);    .echo;.echo dwKeySpec; .if (poi(@esp+8)=0x1) {.echo AT_KEYEXCHANGE} .elsif (poi(@esp+8)=0x2) {.echo AT_SIGNATURE} .else {.printf \"%#x\\n\", poi(@esp+8)};    .echo;.echo sDescription; .if (poi(@esp+c)=0) {.echo NULL} .else {da poi(@esp+c)};    .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+10);        .echo;.echo pbSignature; .if (poi(@esp+14)=0) {.echo NULL} .else {.printf \"%#x\\n\", poi(@esp+14)};    .printf \"\\ndwSigLen\\n%d\\n\", poi(poi(@esp+18));    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .if((poi(@esp-8)!=0) &amp;amp; (poi(poi(@esp-4))!=0)) {r $t0=(poi(poi(@esp-4))+3)/4; .echo bSignature; dd poi(@esp-8) l@$t0; .echo};    .printf \\\"dwSigLen\\\\n%d\\\\n\\\", poi(poi(@esp-4));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptSignHashA (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptSignHashA (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;"; 

bm Advapi32!CryptVerifySignatureW ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptVerifySignatureW (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hHash\\n%#x\\n\\n\", poi(@esp+4);    .if((poi(@esp+8)!=0) &amp;amp; (poi(@esp+c)!=0)) {r $t0=(poi(@esp+c)+3)/4; .echo bSignature; dd poi(@esp+8) l@$t0;} .elsif(poi(@esp+8)=0) {.echo pbSignature;.echo NULL;} .else {.printf \"pbSignature\\n%#x\\n\", poi(@esp+8)};    .printf \"\\ndwSigLen\\n%d\\n\\n\", poi(@esp+c);    .printf \"hPubKey\\n%#x\\n\", poi(@esp+10);    .echo;.echo sDescription; .if (poi(@esp+14)=0) {.echo NULL} .else {du poi(@esp+14)};    .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+18);    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptVerifySignatureW (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptVerifySignatureW (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptVerifySignatureA ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptVerifySignatureA (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hHash\\n%#x\\n\\n\", poi(@esp+4);    .if((poi(@esp+8)!=0) &amp;amp; (poi(@esp+c)!=0)) {r $t0=(poi(@esp+c)+3)/4; .echo bSignature; dd poi(@esp+8) l@$t0;} .elsif(poi(@esp+8)=0) {.echo pbSignature;.echo NULL;} .else {.printf \"pbSignature\\n%#x\\n\", poi(@esp+8)};    .printf \"\\ndwSigLen\\n%d\\n\\n\", poi(@esp+c);    .printf \"hPubKey\\n%#x\\n\", poi(@esp+10);    .echo;.echo sDescription; .if (poi(@esp+14)=0) {.echo NULL} .else {da poi(@esp+14)};    .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+18);    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptVerifySignatureA (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptVerifySignatureA (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptImportKey ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptImportKey (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hProv\\n%#x\\n\\n\", poi(@esp+4);    .if((poi(@esp+8)!=0) &amp;amp; (poi(@esp+c)!=0)) {r $t0=(poi(@esp+c)+3)/4; .echo bData; dd poi(@esp+8) l@$t0;} .elsif(poi(@esp+8)=0) {.echo pbData;.echo NULL;} .else {.printf \"pbData\\n%#x\\n\", poi(@esp+8)};    .printf \"\\ndwDataLen\\n%d\\n\\n\", poi(@esp+c);    .printf \"hPubKey\\n%#x\\n\\n\", poi(@esp+10);    .printf \"dwFlags\\n%#x\\n\", poi(@esp+14); .if((poi(@esp+14)&amp;amp;0x0`00000001)=0x0`00000001) {.echo CRYPT_EXPORTABLE(0x1)};    bp /t @$thread poi(@esp) \"    .echo;.echo OUT; .printf \\\"hKey\\\\n%#x\\\\n\\\", poi(poi(@esp-4));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptImportKey (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptImportKey (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Advapi32!CryptExportKey ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptExportKey (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"hKey\\n%#x\\n\\n\", poi(@esp+4);    .printf \"hExpKey\\n%#x\\n\\n\", poi(@esp+8);    .echo dwBlobType; .if(poi(@esp+c)=0x7) {.echo PRIVATEKEYBLOB} .else {.printf \"%#x\\n\", poi(@esp+c)};    .printf \"\\ndwFlags\\n%#x\\n\", poi(@esp+10); .if((poi(@esp+10)&amp;amp;0x0`00000040)=0x0`00000040) {.echo CRYPT_OAEP(0x40)};    .echo;.echo pbData; .if(poi(@esp+14)=0) {.echo NULL} .else {.printf \"%#x\\n\", poi(@esp+14)};    .printf \"\\ndwDataLen\\n%d\\n\", poi(poi(@esp+18));    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .if((poi(@esp-8)!=0) &amp;amp; (poi(poi(@esp-4))!=0)) {r $t0=(poi(poi(@esp-4))+3)/4; .echo bData; dd poi(@esp-8) l@$t0; .echo};    .printf \\\"dwDataLen\\\\n%d\\\\n\\\", poi(poi(@esp-4));    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptExportKey (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptExportKey (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

************************************************************************
* CRYPT32!CRYPT* TRACERS
************************************************************************

bm Crypt32!CryptProtectData ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptProtectData (%#x)\\n\", @$tid;    .echo;.echo IN;    .if (poi(@esp+4)=0) {.echo pDataIn;.echo NULL} .else {.printf \"pDataIn-&amp;gt;cbData\\n%d\\n\\n\", poi(poi(@esp+4)); r $t0=(poi(poi(@esp+4))+3)/4;.if(@$t0 &amp;gt; 40){r $t0=40}; .echo pDataIn-&amp;gt;pbData;dd poi(poi(@esp+4)+4) l@$t0};    .echo;.echo szDataDescr; .if(poi(@esp+8)=0) {.echo NULL} .else {du poi(@esp+8)};    .echo; .if (poi(@esp+c)=0) {.echo pOptionalEntropy;.echo NULL} .else { .printf \"pOptionalEntropy-&amp;gt;cbData\\n%d\\n\", poi(poi(@esp+c)); r $t0=(poi(poi(@esp+c))+3)/4;.if(@$t0 &amp;gt; 40){r $t0=40}; .echo;.echo pOptionalEntropy-&amp;gt;pbData;dd poi(poi(@esp+c)+4) l@$t0};    .echo;.echo vReserved; .if (poi(@esp+10)=0) {.echo NULL} .else {.printf\"%#x\\n\", poi(@esp+10)};    .echo; .if (poi(@esp+14)=0) {.echo pPromptStruct;.echo NULL} .else {.printf \"pPromptStruct-&amp;gt;cbSize\\n%d\\n\\n\", poi(poi(@esp+14)); .printf \"pPromptStruct-&amp;gt;dwPromptFlags\\n%#x\\n\", poi(poi(@esp+14)+4); .if((poi(poi(@esp+14)+4)&amp;amp;0x0`00000001)=0x0`00000001) {.echo CRYPTPROTECT_PROMPT_ON_UNPROTECT(0x1)}; .if((poi(poi(@esp+14)+4)&amp;amp;0x0`00000002)=0x0`00000002) {.echo CRYPTPROTECT_PROMPT_ON_PROTECT(0x2)}; .printf \"\\npPromptStruct-&amp;gt;hwndApp\\n%#x\\n\\n\", poi(poi(@esp+14)+8); .echo pPromptStruct-&amp;gt;szPrompt; .if(poi(poi(@esp+14)+c)=0) {.echo NULL} .else {du poi(poi(@esp+14)+c)} };    .echo; .printf \"dwFlags\\n%#x\\n\", poi(@esp+18); .if((poi(@esp+18)&amp;amp;0x0`00000004)=0x0`00000004) {.echo CRYPTPROTECT_LOCAL_MACHINE(0x4)}; .if((poi(@esp+18)&amp;amp;0x0`00000001)=0x0`00000001) {.echo CRYPTPROTECT_UI_FORBIDDEN(0x1)}; .if((poi(@esp+18)&amp;amp;0x0`00000010)=0x0`00000010) {.echo CRYPTPROTECT_AUDIT(0x10)}; .if((poi(@esp+18)&amp;amp;0x0`00000040)=0x0`00000040) {.echo CRYPTPROTECT_VERIFY_PROTECTION(0x40)};    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .if (poi(@esp-4)=0) {.echo pDataOut;.echo NULL} .else {.printf \\\"pDataOut-&amp;gt;cbData\\\\n%d\\\\n\\\", poi(poi(@esp-4)); r $t0=(poi(poi(@esp-4))+3)/4;.if(@$t0 &amp;gt; 40){r $t0=40}; .echo;.echo pDataOut-&amp;gt;pbData;dd poi(poi(@esp-4)+4) l@$t0};    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptProtectData (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptProtectData (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Crypt32!CryptUnprotectData ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptUnprotectData (%#x)\\n\", @$tid;    .echo;.echo IN;    .if (poi(@esp+4)=0) {.echo pDataIn;.echo NULL} .else {.printf \"pDataIn-&amp;gt;cbData\\n%d\\n\\n\", poi(poi(@esp+4)); r $t0=(poi(poi(@esp+4))+3)/4;.if(@$t0 &amp;gt; 40){r $t0=40}; .echo pDataIn-&amp;gt;pbData;dd poi(poi(@esp+4)+4) l@$t0};    .echo; .if (poi(@esp+c)=0) {.echo pOptionalEntropy;.echo NULL} .else { .printf \"pOptionalEntropy-&amp;gt;cbData\\n%d\\n\", poi(poi(@esp+c)); r $t0=(poi(poi(@esp+c))+3)/4;.if(@$t0 &amp;gt; 40){r $t0=40}; .echo;.echo pOptionalEntropy-&amp;gt;pbData;dd poi(poi(@esp+c)+4) l@$t0};    .echo;.echo vReserved; .if (poi(@esp+10)=0) {.echo NULL} .else {.printf\"%#x\\n\", poi(@esp+10)};    .echo; .if (poi(@esp+14)=0) {.echo pPromptStruct;.echo NULL} .else {.printf \"pPromptStruct-&amp;gt;cbSize\\n%d\\n\\n\", poi(poi(@esp+14)); .printf \"pPromptStruct-&amp;gt;dwPromptFlags\\n%#x\\n\", poi(poi(@esp+14)+4); .if((poi(poi(@esp+14)+4)&amp;amp;0x0`00000001)=0x0`00000001) {.echo CRYPTPROTECT_PROMPT_ON_UNPROTECT(0x1)}; .if((poi(poi(@esp+14)+4)&amp;amp;0x0`00000002)=0x0`00000002) {.echo CRYPTPROTECT_PROMPT_ON_PROTECT(0x2)}; .printf \"\\npPromptStruct-&amp;gt;hwndApp\\n%#x\\n\\n\", poi(poi(@esp+14)+8); .echo pPromptStruct-&amp;gt;szPrompt; .if(poi(poi(@esp+14)+c)=0) {.echo NULL} .else {du poi(poi(@esp+14)+c)} };    .echo; .printf \"dwFlags\\n%#x\\n\", poi(@esp+18); .if((poi(@esp+18)&amp;amp;0x0`00000001)=0x0`00000001) {.echo CRYPTPROTECT_UI_FORBIDDEN(0x1)};    bp /t @$thread poi(@esp) \"    .echo;.echo OUT;    .if(poi(@esp-18)=0) {.echo ppszDataDescr;.echo NULL} .else {.echo szDataDescr; .if(poi(poi(@esp-18))=0) {.echo NULL} .else {du poi(poi(@esp-18))} };    .echo; .if (poi(@esp-4)=0) {.echo pDataOut;.echo NULL} .else {.printf \\\"pDataOut-&amp;gt;cbData\\\\n%d\\\\n\\\", poi(poi(@esp-4)); r $t0=(poi(poi(@esp-4))+3)/4;.if(@$t0 &amp;gt; 40){r $t0=40}; .echo;.echo pDataOut-&amp;gt;pbData;dd poi(poi(@esp-4)+4) l@$t0};    .echo;.echo RESULT;    .if(@eax=1) {.printf \\\"CryptUnprotectData (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptUnprotectData (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Crypt32!CryptMemAlloc ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptMemAlloc (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"cbSize\\n%d\\n\", poi(@esp+4);    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT; .printf \\\"%#x\\\\n\\\\n\\\", @eax; .if(@eax!=0) {.printf \\\"CryptMemAlloc (%#x) SUCCEEDED\\\\n\\\", @$tid} .else {.printf \\\"CryptMemAlloc (%#x) FAILED\\\\n\\\", @$tid;!gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

bm Crypt32!CryptMemFree ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCryptMemFree (%#x)\\n\", @$tid;    .echo;.echo IN;    .printf \"pv\\n%#x\\n\", poi(@esp+4);    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT;    .printf \\\"CryptMemFree (%#x) SUCCEEDED\\\\n\\\", @$tid;    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";

************************************************************************
* CRYPT32!CERT* TRACERS
************************************************************************

bm Crypt32!CertOpenStore ".printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\nCertOpenStore (%#x)\\n\", @$tid;    .echo;.echo IN;    .echo lpszStoreProvider; .if(poi(@esp+4)=0) {.echo NULL} .elsif(poi(@esp+4)=0x1) {.echo CERT_STORE_PROV_MSG} .elsif(poi(@esp+4)=0x2) {.echo CERT_STORE_PROV_MEMORY} .elsif(poi(@esp+4)=0xa) {.echo CERT_STORE_PROV_SYSTEM_W} .elsif(poi(@esp+4)=0xb) {.echo CERT_STORE_PROV_COLLECTION} .elsif(poi(@esp+4)=0xd) {.echo CERT_STORE_PROV_SYSTEM_REGISTRYW} .else {da poi(@esp+4)}; .echo;    .printf \"dwMsgAndCertEncodingType\\n%#x\\n\", poi(@esp+8); .if((poi(@esp+8)&amp;amp;0x0`00000001)=0x0`00000001) {.echo X509_ASN_ENCODING(0x1)}; .if((poi(@esp+8)&amp;amp;0x0`00010000)=0x0`00010000) {.echo PKCS_7_ASN_ENCODING(0x10000)}; .echo;    .echo hCryptProv; .if(poi(@esp+c)=0) {.echo NULL} .else {.printf \"%#x\\n\", poi(@esp+c)}; .echo;    .printf \"dwFlags\\n%#x\\n\", poi(@esp+10); .if((poi(@esp+10)&amp;amp;0x0`00000001)=0x0`00000001) {.echo CERT_STORE_NO_CRYPT_RELEASE_FLAG(0x1)}; .if((poi(@esp+10)&amp;amp;0x0`00000004)=0x0`00000004) {.echo CERT_STORE_DEFER_CLOSE_UNTIL_LAST_FREE_FLAG(0x4)}; .if((poi(@esp+10)&amp;amp;0x0`00000080)=0x0`00000080) {.echo CERT_STORE_SHARE_CONTEXT_FLAG(0x80)}; .if((poi(@esp+10)&amp;amp;0x0`00000400)=0x0`00000400) {.echo CERT_STORE_UPDATE_KEYID_FLAG(0x400)}; .if((poi(@esp+10)&amp;amp;0x0`00001000)=0x0`00001000) {.echo CERT_STORE_MAXIMUM_ALLOWED_FLAG(0x1000)}; .if((poi(@esp+10)&amp;amp;0x0`FFFF0000)=0x0`00010000) {.echo CERT_SYSTEM_STORE_CURRENT_USER(0x10000)} .elsif((poi(@esp+10)&amp;amp;0x0`FFFF0000)=0x0`00020000) {.echo CERT_SYSTEM_STORE_LOCAL_MACHINE(0x20000)} .elsif((poi(@esp+10)&amp;amp;0x0`FFFF0000)=0x0`00040000) {.echo CERT_SYSTEM_STORE_CURRENT_SERVICE(0x40000)} .elsif((poi(@esp+10)&amp;amp;0x0`FFFF0000)=0x0`00050000) {.echo CERT_SYSTEM_STORE_SERVICES(0x50000)} .elsif((poi(@esp+10)&amp;amp;0x0`FFFF0000)=0x0`00060000) {.echo CERT_SYSTEM_STORE_USERS(0x60000)} .elsif((poi(@esp+10)&amp;amp;0x0`FFFF0000)=0x0`00070000) {.echo CERT_SYSTEM_STORE_CURRENT_USER_GROUP_POLICY(0x70000)} .elsif((poi(@esp+10)&amp;amp;0x0`FFFF0000)=0x0`00080000) {.echo CERT_SYSTEM_STORE_LOCAL_MACHINE_GROUP_POLICY(0x80000)} .elsif((poi(@esp+10)&amp;amp;0x0`FFFF0000)=0x0`00090000) {.echo CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE(0x90000)};    .echo; .if(poi(@esp+14)=0) {.echo pvPara; .echo NULL} .else {.echo vPara; dd poi(@esp+14)};    bp /t @$thread poi(@esp) \"    .echo;.echo RESULT; .if(@eax!=0) {.printf \\\"%#x\\\\n\\\\nCertOpenStore (%#x) SUCCEEDED\\\\n\\\", @eax, @$tid;} .else {.printf \\\"NULL\\\\n\\\\nCertOpenStore (%#x) FAILED\\\\n\\\", @$tid; !gle};    .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    G;\";    G;";
 
************************************************************************
* LET'S GO AND TRACE!!!
************************************************************************

* Don't want any output but my own
*
!sym quiet;
.srcnoisy 0;
sxi ld
.outmask- 0xFFFFFFEE  $$ .outmask /d restores the output mask to default

* Create the log and begin
*
.logopen "log.txt";
G

&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope it helps you as much as it helps me every day.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;PS: If you find any issue with the script, please let me know so I can improve it. &lt;SPAN lang=EN-US style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ES; mso-bidi-language: AR-SA"&gt;Obviously &lt;/SPAN&gt;I couldn't test it in all possible scenarios.&amp;nbsp;For instance, if the debugger breaks on an exception (i.e. Access Violation), the tracing will break, too. We will have to make the tracer to continue with the "g" command in the debugger.&lt;/P&gt;
&lt;P&gt;PS: More explanations on this script can be found in my next post &lt;A class="" href="http://blogs.msdn.com/alejacma/archive/2007/11/08/how-to-trace-cryptoapi-calls-2.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/11/08/how-to-trace-cryptoapi-calls-2.aspx"&gt;How to trace CryptoAPI calls (2)&lt;/A&gt;.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5805089" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/WinDbg/default.aspx">WinDbg</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Cdb/default.aspx">Cdb</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugger+scripts/default.aspx">Debugger scripts</category></item><item><title>How to trace CryptoAPI calls</title><link>http://blogs.msdn.com/alejacma/archive/2007/10/29/how-to-trace-cryptoapi-calls.aspx</link><pubDate>Mon, 29 Oct 2007 14:42:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:5764282</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/5764282.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=5764282</wfw:commentRss><description>&lt;P&gt;Hi, welcome back,&lt;/P&gt;
&lt;P&gt;An application may use &lt;STRONG&gt;CryptoAPI&lt;/STRONG&gt; without us developers realizing it. Security classes in &lt;STRONG&gt;.NET&lt;/STRONG&gt; Framework use CryptoAPI behind the scenes. &lt;STRONG&gt;CAPICOM&lt;/STRONG&gt;.dll uses it, too. &lt;/P&gt;
&lt;P&gt;The issue appears when the API returns an error which can help us to find the real cause of the issue, but the code calling it captures the error and returns a completely different one which won't help us at all. Remember for instance my previous post,&amp;nbsp;&lt;A class="" title="RSACryptoServiceProvider fails when used with mandatory profiles" href="http://blogs.msdn.com/alejacma/archive/2007/10/23/rsacryptoserviceprovider-fails-when-used-with-mandatory-profiles.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/10/23/rsacryptoserviceprovider-fails-when-used-with-mandatory-profiles.aspx"&gt;RSACryptoServiceProvider fails when used with mandatory profiles&lt;/A&gt;, where .NET was returning "Cryptographic Service Provider (CSP) for this implementation could not be acquired" but the real error was being returned by CryptAcquireContext: NTE_TEMPORARY_PROFILE. With .NET's error I don't know what's going on. With CryptAcquireContext's I do know.&lt;/P&gt;
&lt;P&gt;Fortunately&amp;nbsp;debuggers like &lt;STRONG&gt;Windbg.exe&lt;/STRONG&gt;\&lt;STRONG&gt;Cdb.exe&lt;/STRONG&gt;&amp;nbsp;(part of our &lt;A class="" title="Debugging Tools for Windows" href="http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx" mce_href="http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx"&gt;Debugging Tools for Windows&lt;/A&gt;) are very handy here. If we want to &lt;STRONG&gt;trace the calls&lt;/STRONG&gt; that an application is making to CryptoAPI behind the scenes, we can follow these steps:&lt;/P&gt;
&lt;P&gt;1) Attach Windbg or Cdb (command line version of Windbg) to the desired process.&lt;/P&gt;
&lt;P&gt;2) Set the following breakpoint:&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;bm Advapi32!Crypt* ".printf \"&lt;/STRONG&gt;&lt;STRONG&gt;\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\n(%#x)\\n\\n\&lt;/STRONG&gt;&lt;STRONG&gt;", @$tid;&amp;nbsp;&amp;nbsp;&amp;nbsp; .echo CALL;k 1;&amp;nbsp;&amp;nbsp;&amp;nbsp; bp /t @$thread poi(@esp) \"&amp;nbsp;&amp;nbsp;&amp;nbsp; .echo;.echo RESULT;&amp;nbsp;&amp;nbsp;&amp;nbsp; .if(@eax=1) {.echo SUCCEEDED} .else {.echo FAILED;!gle};&amp;nbsp;&amp;nbsp;&amp;nbsp; .echo;.echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;&amp;nbsp;&amp;nbsp;&amp;nbsp; G;\";&amp;nbsp;&amp;nbsp;&amp;nbsp; G;";&lt;/STRONG&gt;&lt;/P&gt;
&lt;P&gt;Note:&amp;nbsp; There are other Crypt* APIs on Crypt32.dll, so an additional breakpoint may be set for them.&amp;nbsp;&lt;/P&gt;
&lt;P&gt;3) Continue running the application under the control of the debugger.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;What&amp;nbsp;is that "&lt;STRONG&gt;bm&lt;/STRONG&gt;" command doing exactly? It will be easier to understand it if I write it this way:&lt;/P&gt;&lt;PRE&gt;00  bm Advapi32!Crypt* 
01  "
02      .printf \"\\n&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt;\\n\\n(%#x)\\n\\n\", @$tid;
03
04      .echo CALL;
05      k 1;
06
07      bp /t @$thread poi(@esp)
08      \"
09          .echo;
10          .echo RESULT;
11
12          .if(@eax=1)
13          {
14              .echo SUCCEEDED
15          }
16          .else
17          {
18              .echo FAILED;
19              !gle
20          };
21
22          .echo;
23          .echo &amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;&amp;lt;;    
24
25          G;
26      \";    
27  
28      G;
29  ";
&lt;/PRE&gt;
&lt;P&gt;00) We set a breakpoint on all APIs found in Advapi32.dll which start by "Crypt". The following commands will be executed when the application calls any of those APIs thus reaching any of those breakpoints:&lt;/P&gt;
&lt;P&gt;02) We print the id of the thread calling the API ("&lt;STRONG&gt;$tid&lt;/STRONG&gt;" pseudo-register). "&lt;STRONG&gt;.printf&lt;/STRONG&gt;" works pretty much the same way as our old friend "printf" in C. Instead of ' " '&amp;nbsp;and ' \n ' we will have to use ' \" '&amp;nbsp;and ' \\n ', because&amp;nbsp;these commands are already between&amp;nbsp;' " '.&lt;/P&gt;
&lt;P&gt;04) We print the string "CALL" with "&lt;STRONG&gt;.echo&lt;/STRONG&gt;".&lt;/P&gt;
&lt;P&gt;05) We print the first line of the call stack gotten when the breakpoint is reached ("&lt;STRONG&gt;k 1&lt;/STRONG&gt;"). The API we are calling will correspond to that first line. Here we could show the parameters being passed to the API by using "&lt;STRONG&gt;kp&lt;/STRONG&gt;" command&amp;nbsp;(if we have symbols -.pdb files- associated to Advapi32.dll), or any other way.&lt;/P&gt;
&lt;P&gt;07) Now we want to know what happened after the API finished executing. When we stop on the breakpoint set at 00, the "&lt;STRONG&gt;esp&lt;/STRONG&gt;" register (stack pointer)&amp;nbsp;points to the return address where we will go after the call to the API ends. So we set a breakpoint at that address with "&lt;STRONG&gt;bp&lt;/STRONG&gt;". And if we don't want weird things to happen on multi-threaded applications, we have to specify on which thread ("&lt;STRONG&gt;$thread&lt;/STRONG&gt;" pseudo-register)&amp;nbsp;we are setting that breakpoint. &lt;/P&gt;
&lt;P&gt;28) Once we've set the breakpoint at 07, we can continue the execution of the application with "&lt;STRONG&gt;g&lt;/STRONG&gt;" command.&lt;/P&gt;
&lt;P&gt;Now, let see what happens when we stop on&amp;nbsp;breakpoint set&amp;nbsp;at 07:&lt;/P&gt;
&lt;P&gt;09 &amp;amp; 10) We print the string "RESULT".&lt;/P&gt;
&lt;P&gt;12) When the API has finished executing, its return value will be stored in the "&lt;STRONG&gt;eax&lt;/STRONG&gt;" register. The Crypt* functions in Advapi32 will return 1 if they succeed or 0 if they don't. We use "&lt;STRONG&gt;.if {} .else {}&lt;/STRONG&gt;" command to determine which one we got.&lt;/P&gt;
&lt;P&gt;14) The API succeeded, so we print the string "SUCCEEDED".&lt;/P&gt;
&lt;P&gt;18 &amp;amp; 19) The API&amp;nbsp;failed, so we print the string "FAILED" and show the last error value with "&lt;STRONG&gt;!gle&lt;/STRONG&gt;" (Get Last Error) command.&lt;/P&gt;
&lt;P&gt;25) Now that we know the result of calling the API, we can continue the execution of the application and trace more APIs.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Comments on this:&lt;/P&gt;
&lt;P&gt;- Some people may think that setting a breakpoint at 07 is unnecessary, as we could use "&lt;STRONG&gt;gu&lt;/STRONG&gt;" command to get to the end of the call instead. But if we use "gu" and a CryptoAPI calls another one, we will miss the return value of the former.&lt;/P&gt;
&lt;P&gt;- I tried setting the breakpoint at 07 using "&lt;STRONG&gt;~~[$tid] bp ...&lt;/STRONG&gt;", but the &lt;SPAN lang=EN-US style="FONT-SIZE: 10pt; LINE-HEIGHT: 115%; FONT-FAMILY: 'Arial','sans-serif'; mso-fareast-font-family: 'Times New Roman'; mso-ansi-language: EN-US; mso-fareast-language: ES; mso-bidi-language: AR-SA"&gt;behavior &lt;/SPAN&gt;wasn't correct. I don't know why the debugger was stopping several times on the same breakpoint instead of just one. Using "bp /t @$thread ..." instead worked just fine.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I&amp;nbsp;hope this helps.&lt;/P&gt;
&lt;P mce_keep="true"&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;PS: I'm currently developing a Windbg\Cdb script based on the principles explained in this post which traces all CryptoAPI calls, but this time showing all their in &amp;amp; out parameters in a very user friendly way. You can see its current version &lt;A class="" href="http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx" mce_href="http://blogs.msdn.com/alejacma/archive/2007/10/31/cryptoapi-tracer.aspx"&gt;here&lt;/A&gt;.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=5764282" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CryptoAPI/default.aspx">CryptoAPI</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/WinDbg/default.aspx">WinDbg</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Cdb/default.aspx">Cdb</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugger+scripts/default.aspx">Debugger scripts</category></item></channel></rss>