??xml version="1.0" encoding="utf-8" standalone="yes"?>97久久精品人人澡人人爽,精品国产日韩久久亚洲,久久综合伊人77777http://www.shnenglu.com/jans2002/archive/2010/01/25/106363.htmljans2002jans2002Mon, 25 Jan 2010 01:27:00 GMThttp://www.shnenglu.com/jans2002/archive/2010/01/25/106363.htmlhttp://www.shnenglu.com/jans2002/comments/106363.htmlhttp://www.shnenglu.com/jans2002/archive/2010/01/25/106363.html#Feedback2http://www.shnenglu.com/jans2002/comments/commentRss/106363.htmlhttp://www.shnenglu.com/jans2002/services/trackbacks/106363.htmlCMakeL(fng)是很d跨^台的~译工具Q于是想试用一下,没想到其Windows下的安装E序如此弱智Q把我的环境变量配置的Path路径全给冲了(jin)Q这L(fng)垃圾工具q是用为妙。既然号U跨q_Q连Windows都支持的q么差,也不支持中文Q想必其他^台的也好不到那里厅R还是老老实实的写我的Makefile吧?/p>

jans2002 2010-01-25 09:27 发表评论
]]>
(?怎么获取dll函数的参数类?/title><link>http://www.shnenglu.com/jans2002/archive/2009/10/14/98543.html</link><dc:creator>jans2002</dc:creator><author>jans2002</author><pubDate>Wed, 14 Oct 2009 00:37:00 GMT</pubDate><guid>http://www.shnenglu.com/jans2002/archive/2009/10/14/98543.html</guid><wfw:comment>http://www.shnenglu.com/jans2002/comments/98543.html</wfw:comment><comments>http://www.shnenglu.com/jans2002/archive/2009/10/14/98543.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/jans2002/comments/commentRss/98543.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/jans2002/services/trackbacks/98543.html</trackback:ping><description><![CDATA[<p>可以通过反汇~来知道接口函数的参敎ͼ使用W32DSM来分析,也可以直接用VC来分析,是ȝ(ch)一炏V?nbsp;      <br>  现在使用W32DSM来具体说明:(x)       <br>  1。先打开需要分析的DLLQ然后通过菜单功能-》出口来扑ֈ需要分析的函数Q双d可以?jin)?nbsp;      <br>  它可以直接定位到该函数?nbsp;      <br>  2。看准该函数的入口,一般函数是以以下代码作为入口点的?nbsp;      <br>  push     ebp       <br>  mov         ebp,     esp       <br>  ...       <br>  3。然后往下找到该函数的出口,一般函数出口有以下语句?nbsp;      <br>  ...       <br>  ret         xxxx;//其中xxxx是函数差数的所有的字节敎ͼ?的倍数Qxxxx除以4得到的结?nbsp;      <br>  是参数的个数?nbsp;      <br>  其中参数存放的地方:(x)       <br>  ebp+08                     //W一个参?nbsp;      <br>  ebp+0C                     //W二个参?nbsp;      <br>  ebp+10                     //W三个参?nbsp;      <br>  ebp+14                     //W四个参?nbsp;      <br>  ebp+18                     //W五个参?nbsp;      <br>  ebp+1C                     //W六个参?nbsp;      <br>  。。。?nbsp;      <br>  -------------------------------------------       <br>  q有一U经常看到的调用方式Q?nbsp;      <br>  sub     esp,xxxx                     //开头部?nbsp;      <br>  //函数的内?nbsp;      <br>  。。?nbsp;      <br>  //函数的内?nbsp;      <br>  add     esp,xxxx       <br>  ret                                                         //l尾部分       <br>  其中xxxx/4的结果也是参数的个数?nbsp;              <br>  -------------------------------------------------       <br>  q有一U调用方式:(x)       <br>  有于该函数比较简单,没有参数的压栈过E,       <br>  里面?nbsp;      <br>  esp+04是W一个参?nbsp;      <br>  esp+08是W二个参?nbsp;      <br>  。。?nbsp;      <br>  esp+xx是Wxx/4个参?nbsp;      <br>  你说看到的xx的最大数除以4后的l果Q就是该函数所传递的参数的个数?nbsp;      <br>  ----------------------------------------------       <br>  到现在位|,你应该能很清楚的看到?jin)传递的参数的个数。至于传递的是些什么内容,q需要进一步的分析?nbsp;      <br>  最方便的办法就是先扑ֈ是什么Y件在调用此函敎ͼ然后通过调试的技术,扑ֈ该函数被调用的地斏V一般都是PUSH指o(h)       <br>  来实现参数的传递的。这时可以看一下具体是什么东西被压入堆栈?jin),一般来_(d)如果参数是整敎ͼ一看就可以知道?jin)?nbsp;      <br>  如果是字W串的话也是比较单的Q只要到那个地址上面ȝ一下就可以?jin)?nbsp;      <br>  如果传递的l构的话Q没有很方便的办法解冻I是L该汇~就可以?jin)。对于以上的分析Q本人只其到?jin)抛砖引玉?nbsp;      <br>  希望对大家有点用处?</p><img src ="http://www.shnenglu.com/jans2002/aggbug/98543.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/jans2002/" target="_blank">jans2002</a> 2009-10-14 08:37 <a href="http://www.shnenglu.com/jans2002/archive/2009/10/14/98543.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>(?一个小技巧:(x)SFP OverwriteQ以c语言为实例)(j)http://www.shnenglu.com/jans2002/archive/2009/09/29/97511.htmljans2002jans2002Tue, 29 Sep 2009 01:09:00 GMThttp://www.shnenglu.com/jans2002/archive/2009/09/29/97511.htmlhttp://www.shnenglu.com/jans2002/comments/97511.htmlhttp://www.shnenglu.com/jans2002/archive/2009/09/29/97511.html#Feedback0http://www.shnenglu.com/jans2002/comments/commentRss/97511.htmlhttp://www.shnenglu.com/jans2002/services/trackbacks/97511.html

SFP Overwrite
I'd like a share a little trick I figured out today. I'm sure it has been done before and probably many times but its new to me so I'll describe it here. I asked myself if anything cool could be achieved by overwriting the Saved Frame Pointer instead of the Return Address. I'm not sure what sort of security-related attacks could be leveraged by doing this, but I did find that its possible to affect the program flow in the calling function. This is just another trick to change the flow of execution and even works on a non-executable stack.
The vulnerable program source code
The attack program source code
EBP and Local Variables
The extended base pointer is a register used by the CPU as base for the current stack frame. As we discussed earlier, the EBP for the function that called the current one is stored in the current function's Saved Frame Pointer. The EBP points to this SFP; in this way, there is a chain of saved EBPs for each stack frame. Check out the EIP Redirection page for more details about this. The location of the current stack frame's SFP is stored in the Extended Base Pointer.名称:  sfptut3.jpg
查看ơ数: 22
文g大小:  11.3 KB
Keeping track of the chain of the program's stack frames is not the only purpose of the EBP/SFPs. As the name implies, the Extended Base Pointer register holds an address that is used as the "base" of the current stack frame (this address is the frame's SFP). The code in the current function references local variables using EBP as a base. For example, the C code for setting a variable equal to 3 is myVar = 3;. This might be assembled into something like: MOV SS:[EBP - 4], 0x03. This means that the local variable myVar is referred to as "the address on the stack stored in EBP, minus 4 bytes" by the assembled code. Another variable in the same function called myVar2 might be located at SS:[EBP - 8]. We can see that if an attacker could change the value of EBP, they could also change where the code thinks local variables are.
Using SFP to Modify EBP
名称:  sfptut1.jpg
查看ơ数: 23
文g大小:  14.8 KB
Imagine that there is function called FunctionA that is not vulnerable to any sort of buffer overflow. Inside it is a local integer variable that is used by the function later on. Before the variable is used, another function called FunctionB is called. This one happens to be vulnerable to a buffer overflow. Our goal is to trick FunctionA into using a variable that we define instead of the one that it declared.
We wait until the execution reaches FunctionB and we are able to input our malicious buffer. At the beginning we'll have the value of the fake variable that FunctionA will be tricked into using. From there, we pad the buffer with junk until the saved frame pointer is reached. Now we push the address on the stack that is directly below our fake variable. The reason we do this is that FunctionA references its real variable as SS:[ebp - 4]. Therefore, our injected EBP must be 4 bytes beyond our fake variable. By setting it up in this way, if we can manage to get that address into the Extended Base Pointer while FunctionA is executing; our fake variable will be referenced instead of the real one. We are not overwriting the value in the real variable. Instead, we are changing FunctionA's perception of its location to an address inside the buffer that we control.
The Target
Now its time to put our attack into a context. At the top of the source code, you'll notice the vulnerable test() function. All it does is declare a 5 byte buffer and fail to protect it while its being filled with user input. The main() function declares a local integer variable (4 bytes) and feeds the decimal value 3 into it. Main() then calls the test() function which asks the user for input but doesn't do anything with it. After test() returns, a loop is entered. The loop keeping looping as long as the integer c is greater than zero. Each time it repeats, the value of c is decreased by one and "Later" is displayed on the screen. Overall, this thing prints that word c times. Because the value of this integer was set to 3 earlier, this means that "Later" is printed 3 times by this loop. 名称:  sfptut2.jpg
查看ơ数: 21
文g大小:  10.9 KB
We will trick this program into thinking that a variable we create using the vulnerable buffer is actually c. By filling this fake variable with the decimal value 500,000,001, we'll make this loop run and print "Later" 500 million and one times instead of the expected three.
Buiding the Attack
As before, we'll be writing a program in C that will feed a malicious string into the input of the vulnerable program. Because our ultimate goal is to overwrite the test() function's SFP, we'll need to pad the string appropriately to get there. The first 4 bytes of the attack string will be the value of our fake variable that main() will eventually use in its loop. These bytes need to equal the goal of 500,000,001 so we'll feed "\x01\x65\xCD\x1D" first. The next four do not matter in this case, but take note that they will become main()'s fake SFP. From here use OllyDbg to find the distance between this fake main() SFP and test()'s SFP. If you are unsure where the test() function's SFP is, you can always step the program until inside test() and check the EBP register. You'll find that the buffer begins at 0x0027FF00 and the test() function's SFP is located at 0x0027FF18. After converting to decimal and subtracting the 8 bytes we already used up so far, it means we'll need to add 16 bytes of padding to reach test()'s SFP.
名称:  sfptut4.jpg
查看ơ数: 21
文g大小:  11.1 KB
Next we'll actually overwrite the SFP. Have a look at the main() function and you'll find that the loop references the variable c as SS:[EBP - 4]. This means that if we want it to reference that 4 byte value at the beginning of the buffer instead, we need main()'s EBP to point to the address 4 bytes beyond the beginning of our attack buffer. We've already pointed out that any value we can sneak into test()'s SFP will end up in the EBP when main() returns. So we end the attack string with the following 3 bytes: "\x04\xFF\x27". The value is chosen because 0x0027FF04 - 4 is the address of our fake variable. Writing all four bytes is, again, not necessary because gets() automatically sticks a null byte at the end of the string inputted.
Final Overview
By crafting the above buffer and ensuring that the last 3 bytes overwrite test()'s SFP, we directly control EBP when test() returns back to main(). Because main() uses EBP to reference an important variable c and we control EBP; we make main() think that c is actually where our old overwritten buffer began. The data is still there because there was no reason for the program to erase/modify it. Because c is referenced as SS:[EBP - 4] in main(), we need that overwritten Stack Frame Pointer to point to the address four bytes below the fake variable location on the stack. When main uses our fake EBP to reference variable c is it will subtract 4 from it and find our fake variable value. This was filled in with the decimal value of 500,000,001. Main() runs the loop to print "Later" a number of times determined by c. So by doing all of this trickery we can make the program display "Later" 500,000,001 times instead of 3.



jans2002 2009-09-29 09:09 发表评论
]]>
菜鸟对AspectC++ Add-In for Microsoft&reg; Visual C++&reg;插g的破解过E?/title><link>http://www.shnenglu.com/jans2002/archive/2009/08/14/93354.html</link><dc:creator>jans2002</dc:creator><author>jans2002</author><pubDate>Fri, 14 Aug 2009 09:59:00 GMT</pubDate><guid>http://www.shnenglu.com/jans2002/archive/2009/08/14/93354.html</guid><wfw:comment>http://www.shnenglu.com/jans2002/comments/93354.html</wfw:comment><comments>http://www.shnenglu.com/jans2002/archive/2009/08/14/93354.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.shnenglu.com/jans2002/comments/commentRss/93354.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/jans2002/services/trackbacks/93354.html</trackback:ping><description><![CDATA[<p>AspectC++ Add-In for Microsoft® Visual C++® <br />http://www.pure-systems.com/fileadmin/downloads/acaddin/Aspectc-AddIn-Setup-010101.exe<br />我用的是VS2003环境<br />调试目标QC:\Program Files\pure-systems\AspectC++ Add-In\bin\CPPAddin.dll<br />工具Q用OD调试QIDA+Hex-rays分析<br />重点集中在以下几个地址<br />0x10008e60 弹许可文件询问的对话?br />0x10017a20 解析xml格式的许可文?br />0x10017730 貌似许可(g)查的地方<br />q个?br />0x10008e60的由Hex-ray分析出来的伪代码, </p><p>代码:</p><pre><span style="color: #0000ff">char</span> __usercall sub_1000E860<al>(<span style="color: #0000ff">int</span> a1<ebx>) { <span style="color: #0000ff">int</span> ST14_4_0; <span style="color: #008000">// ST14_4@0</span> <span style="color: #0000ff">int</span> v2; <span style="color: #008000">// ST10_4@1</span> <span style="color: #0000ff">const</span> CHAR *v3; <span style="color: #008000">// eax@3</span> <span style="color: #0000ff">const</span> CHAR *v4; <span style="color: #008000">// eax@10</span> <span style="color: #0000ff">int</span> v6; <span style="color: #008000">// eax@2</span> <span style="color: #0000ff">char</span> v7; <span style="color: #008000">// bl@2</span> <span style="color: #0000ff">char</span> v8; <span style="color: #008000">// al@9</span> <span style="color: #0000ff">int</span> v9; <span style="color: #008000">// [sp+Ch] [bp-9Ch]@1</span> <span style="color: #0000ff">signed</span> <span style="color: #0000ff">int</span> v10; <span style="color: #008000">// [sp+A4h] [bp-4h]@1</span> <span style="color: #0000ff">char</span> v11; <span style="color: #008000">// [sp+10h] [bp-98h]@1</span> <span style="color: #0000ff">char</span> v12; <span style="color: #008000">// [sp+48h] [bp-60h]@2</span> <span style="color: #0000ff">char</span> v13; <span style="color: #008000">// [sp+2Ch] [bp-7Ch]@2</span> LPCSTR lpText; <span style="color: #008000">// [sp+14h] [bp-94h]@3</span> <span style="color: #0000ff">unsigned</span> <span style="color: #0000ff">int</span> v15; <span style="color: #008000">// [sp+28h] [bp-80h]@3</span> <span style="color: #0000ff">char</span> v16; <span style="color: #008000">// [sp+64h] [bp-44h]@15</span> BYTE3(v9) = 0; sub_10016AA0(); v10 = 0; std__basic_string_char_std__char_traits_char__std__allocator_char____basic_string_char_std__char_traits_char__std__allocator_char__(&v11); LOBYTE(v10) = 1; v2 = a1; <span style="color: #0000ff">while</span> ( 1 ) { sub_100169B0(16, (<span style="color: #0000ff">int</span>)&v12); LOBYTE(v10) = 2; v6 = std__operator_(&v13, v6, "<span style="color: #8b0000">\\etc\\licence</span>"); LOBYTE(v10) = 3; v7 = sub_10017A20((<span style="color: #0000ff">int</span>)&unk_10024460, v6, (<span style="color: #0000ff">int</span>)&v11) == 0; LOBYTE(v10) = 2; std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v13); LOBYTE(v10) = 1; std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v12); <span style="color: #0000ff">if</span> ( !v7 ) <span style="color: #0000ff">break</span>; std__basic_string_char_std__char_traits_char__std__allocator_char____operator__( &v11, "<span style="color: #8b0000">\nThe add-in will not work without a valid licence.\n\nInstall the licence file now?</span>", v2); v3 = lpText; <span style="color: #0000ff">if</span> ( v15 < 0x10 ) v3 = (<span style="color: #0000ff">const</span> CHAR *)&lpText; <span style="color: #0000ff">if</span> ( MessageBoxA(0, v3, "<span style="color: #8b0000">AspectC++ Add-In for Visual Studio .NET</span>", 0x24u) != 6 ) <span style="color: #0000ff">break</span>; <span style="color: #0000ff">if</span> ( !sub_1000E690() ) { MessageBoxA(0, "<span style="color: #8b0000">Installation of licence file failed.</span>", "<span style="color: #8b0000">AspectC++ Add-In</span>", 0x40u); <span style="color: #0000ff">break</span>; } } <span style="color: #0000ff">if</span> ( byte_10024465 ) { sub_10017730((<span style="color: #0000ff">int</span>)&unk_10024460, 16, (<span style="color: #0000ff">int</span>)&v11); <span style="color: #0000ff">if</span> ( v8 && (<span style="color: #0000ff">unsigned</span> __int8)sub_10017520(&v11) != 1 ) { BYTE3(v9) = 1; } <span style="color: #0000ff">else</span> { std__basic_string_char_std__char_traits_char__std__allocator_char____operator__( &v11, "<span style="color: #8b0000">\nThe add-in will not work.</span>", ST14_4_0); v4 = lpText; <span style="color: #0000ff">if</span> ( v15 < 0x10 ) v4 = (<span style="color: #0000ff">const</span> CHAR *)&lpText; MessageBoxA(0, v4, "<span style="color: #8b0000">AspectC++ Add-In</span>", 0x40u); } } LOBYTE(v10) = 0; std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v11); v10 = -1; sub_10016910((<span style="color: #0000ff">int</span>)&v16); <span style="color: #0000ff">return</span> BYTE3(v9); }</pre><pre> </pre> <p>基本上可以得出默认是分析<br />C:\Program Files\pure-systems\AspectC++ Add-In\etc\licence 许可文g<br />分析q程应该?x10017a20? </p><p>代码:</p><pre><span style="color: #0000ff">char</span> __thiscall sub_10017A20(<span style="color: #0000ff">int</span> <span style="color: #0000ff">this</span>, <span style="color: #0000ff">int</span> a2, <span style="color: #0000ff">int</span> a3) { <span style="color: #0000ff">int</span> v3; <span style="color: #008000">// ebp@1</span> <span style="color: #0000ff">int</span> v4; <span style="color: #008000">// esi@1</span> <span style="color: #0000ff">int</span> v5; <span style="color: #008000">// eax@2</span> <span style="color: #0000ff">int</span> v6; <span style="color: #008000">// eax@4</span> <span style="color: #0000ff">int</span> v7; <span style="color: #008000">// edi@5</span> <span style="color: #0000ff">char</span> result; <span style="color: #008000">// al@8</span> <span style="color: #0000ff">int</span> v9; <span style="color: #008000">// ecx@1</span> <span style="color: #0000ff">int</span> v10; <span style="color: #008000">// eax@5</span> <span style="color: #0000ff">int</span> v11; <span style="color: #008000">// eax@6</span> <span style="color: #0000ff">int</span> v12; <span style="color: #008000">// ST04_4@6</span> <span style="color: #0000ff">char</span> v13; <span style="color: #008000">// bl@6</span> <span style="color: #0000ff">char</span> v14; <span style="color: #008000">// [sp+Ch] [bp-28h]@6</span> <span style="color: #0000ff">signed</span> <span style="color: #0000ff">int</span> v15; <span style="color: #008000">// [sp+30h] [bp-4h]@6</span> v3 = a3; v4 = <span style="color: #0000ff">this</span>; v9 = <span style="color: #0000ff">this</span> + 96; *(_DWORD *)v9 = 0; *(_DWORD *)(v9 + 4) = 0; *(_DWORD *)(v9 + 8) = 0; *(_DWORD *)(v9 + 12) = 0; *(_BYTE *)(v4 + 5) = 0; std__basic_string_char_std__char_traits_char__std__allocator_char____operator_(v3, "<span style="color: #8b0000">Loading licence file failed.</span>"); <span style="color: #0000ff">if</span> ( *(_DWORD *)(a2 + 24) < 0x10u ) v5 = a2 + 4; <span style="color: #0000ff">else</span> v5 = *(_DWORD *)(a2 + 4); v6 = xmlParseFile(v5); *(_DWORD *)v4 = v6; <span style="color: #0000ff">if</span> ( v6 && (v10 = xmlDocGetRootElement(v6), v7 = v10, v10) && (v11 = std__basic_string_char_std__char_traits_char__std__allocator_char____basic_string_char_std__char_traits_char__std__allocator_char__( &v14, "<span style="color: #8b0000">licence</span>"), v12 = *(_DWORD *)(v7 + 8), v15 = 0, v13 = std__operator__(v11, v12), v15 = -1, std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v14), v13) && sub_10017930(v7) ) { *(_BYTE *)(v4 + 5) = 1; sub_10017730(v4, v3, v3); result = 1; } <span style="color: #0000ff">else</span> { result = 0; } <span style="color: #0000ff">return</span> result; }</pre> <p>q是0x10017730的过E? </p><p>代码:</p><pre><span style="color: #0000ff">void</span> __userpurge sub_10017730(<span style="color: #0000ff">int</span> <span style="color: #0000ff">this</span><ecx>, <span style="color: #0000ff">int</span> ebp0<ebp>, <span style="color: #0000ff">int</span> a2) { <span style="color: #0000ff">int</span> ST18_4_0; <span style="color: #008000">// ST18_4@0</span> <span style="color: #0000ff">int</span> ST1C_4_0; <span style="color: #008000">// ST1C_4@0</span> <span style="color: #0000ff">int</span> v5; <span style="color: #008000">// esi@1</span> <span style="color: #0000ff">signed</span> <span style="color: #0000ff">int</span> v6; <span style="color: #008000">// eax@4</span> <span style="color: #0000ff">int</span> v7; <span style="color: #008000">// ST18_4@6</span> <span style="color: #0000ff">int</span> v8; <span style="color: #008000">// eax@20</span> <span style="color: #0000ff">int</span> v9; <span style="color: #008000">// eax@4</span> <span style="color: #0000ff">int</span> v10; <span style="color: #008000">// ST1C_4@12</span> <span style="color: #0000ff">int</span> v11; <span style="color: #008000">// ST1C_4@18</span> <span style="color: #0000ff">int</span> r; <span style="color: #008000">// [sp+60h] [bp+0h]@1</span> <span style="color: #0000ff">int</span> v13; <span style="color: #008000">// [sp+50h] [bp-10h]@1</span> <span style="color: #0000ff">signed</span> <span style="color: #0000ff">int</span> v14; <span style="color: #008000">// [sp+5Ch] [bp-4h]@3</span> <span style="color: #0000ff">char</span> v15; <span style="color: #008000">// [sp+34h] [bp-2Ch]@4</span> <span style="color: #0000ff">char</span> v16; <span style="color: #008000">// [sp+18h] [bp-48h]@4</span> <span style="color: #0000ff">int</span> v17; <span style="color: #008000">// [sp+1Ch] [bp-44h]@12</span> <span style="color: #0000ff">unsigned</span> <span style="color: #0000ff">int</span> v18; <span style="color: #008000">// [sp+30h] [bp-30h]@20</span> <span style="color: #0000ff">int</span> v19; <span style="color: #008000">// [sp+2Ch] [bp-34h]@22</span> v5 = <span style="color: #0000ff">this</span>; v13 = r ^ dword_100242D0; std__basic_string_char_std__char_traits_char__std__allocator_char____operator_(a2, "<span style="color: #8b0000">Invalid licence file found.</span>"); <span style="color: #0000ff">if</span> ( *(_BYTE *)(v5 + 5) && !*(_BYTE *)(v5 + 4) ) { sub_10017B20((<span style="color: #0000ff">int</span>)&a2, ebp0); v14 = 0; <span style="color: #0000ff">if</span> ( !sub_1001A050((<span style="color: #0000ff">int</span>)&a2) ) { LABEL_23: v14 = -1; sub_1001A060(&a2); <span style="color: #0000ff">goto</span> LABEL_24; } v9 = std__operator_(&v15, v5 + 12, v5 + 40); LOBYTE(v14) = 1; std__operator_(&v16, v9, v5 + 68); LOBYTE(v14) = 3; std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v15); v6 = *(_DWORD *)(v5 + 8); <span style="color: #0000ff">if</span> ( v6 || !*(_DWORD *)(v5 + 96) ) { <span style="color: #0000ff">if</span> ( v6 == 1 && *(_DWORD *)(v5 + 96) && *(_DWORD *)(v5 + 100) && *(_DWORD *)(v5 + 104) && *(_DWORD *)(v5 + 108) ) { std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v16, "<span style="color: #8b0000">evaluation</span>", ST18_4_0); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__( &v17, *(_DWORD *)(v5 + 96), ST1C_4_0); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__( &v17, *(_DWORD *)(v5 + 100), v10); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__( &v17, *(_DWORD *)(v5 + 104), ST1C_4_0); v7 = *(_DWORD *)(v5 + 108); } <span style="color: #0000ff">else</span> { <span style="color: #0000ff">if</span> ( v6 != 2 || !*(_DWORD *)(v5 + 96) || !*(_DWORD *)(v5 + 100) || !*(_DWORD *)(v5 + 104) || !*(_DWORD *)(v5 + 108) ) <span style="color: #0000ff">goto</span> LABEL_20; std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v16, "<span style="color: #8b0000">user</span>", ST18_4_0); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__( &v17, *(_DWORD *)(v5 + 96), ST1C_4_0); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__( &v17, *(_DWORD *)(v5 + 100), v11); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__( &v17, *(_DWORD *)(v5 + 104), ST1C_4_0); v7 = *(_DWORD *)(v5 + 108); } } <span style="color: #0000ff">else</span> { std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v16, "<span style="color: #8b0000">beta</span>", ST18_4_0); v7 = *(_DWORD *)(v5 + 96); } std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v17, v7, ST1C_4_0); LABEL_20: v8 = v17; <span style="color: #0000ff">if</span> ( v18 < 0x10 ) v8 = (<span style="color: #0000ff">int</span>)&v17; *(_BYTE *)(v5 + 4) = sub_10019E30(v5 + 112, v8, v19, (<span style="color: #0000ff">int</span>)&a2); LOBYTE(v14) = 0; std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v16); <span style="color: #0000ff">goto</span> LABEL_23; } LABEL_24: sub_1001A7B0( r ^ v13, ebp0); }</pre> <p> </p> <p>昨天我自p试的时候也犯了(jin)一个错误,是调试CppAddin.dll很痛苦,费不少旉和分散很多的_֊Q中间老是受到Va_X.dll的干扎ͼ而且msdev.exe在CppAddin没加载时没法直接下断点,必须得在OD中设|一个新模块加蝲的断点(选项->调试选项->事g->中断于新模块Q?q样下来Q每ơ调试失败后重启的过E很是O长,费?jin)不时_(d)发帖子的求助的时候,我ؓ(f)?jin)大大们l我能方便的解决问题Q尽量把非技术问题都试验?jin)一下,以免大大们被q些问题C?jin),一怒之下不l我我?jin)。但是这样一来,也ؓ(f)我自p军_发现问题加快?jin)速度?br />ȝ一下:(x)<br />    1.解决问题要东方不亮,西方亮,不要自q力消耗在q离问题本n的地?br />    2.坚持是胜利Q哪怕是菜鸟Q不懂多汇~(看代码还得靠伟大、光荣、正的F5Q,也能取得成W<br />下面写写分析q程Q?br />其实昨天已经扑ֈ?jin)关键的q程Q那是0x10017a20Q这里面是分析xml格式的许可文?br />q里面有两个调用Qsub_10017930()?sub_10017730()<br />大概可以看得出来Qsub_10017930参与?jin)xml格式的许可数据的解析q程Q它调用成功之后Q才调用10017730Ҏ(gu)据进行验证,要分析许可数据格式,必须研究10017930 </p><p>代码:</p><pre><span style="color: #0000ff">char</span> __stdcall sub_10017930(<span style="color: #0000ff">int</span> a1) { <span style="color: #0000ff">int</span> v1; <span style="color: #008000">// ebp@1</span> <span style="color: #0000ff">int</span> v2; <span style="color: #008000">// esi@1</span> <span style="color: #0000ff">int</span> v3; <span style="color: #008000">// esi@3</span> <span style="color: #0000ff">char</span> result; <span style="color: #008000">// al@7</span> <span style="color: #0000ff">int</span> v5; <span style="color: #008000">// eax@1</span> <span style="color: #0000ff">int</span> v6; <span style="color: #008000">// eax@2</span> <span style="color: #0000ff">char</span> v7; <span style="color: #008000">// bl@2</span> <span style="color: #0000ff">char</span> v8; <span style="color: #008000">// [sp+Ch] [bp-28h]@2</span> <span style="color: #0000ff">signed</span> <span style="color: #0000ff">int</span> v9; <span style="color: #008000">// [sp+30h] [bp-4h]@2</span> v1 = a1; v5 = xmlGetProp(a1, "<span style="color: #8b0000">version</span>"); v2 = v5; <span style="color: #0000ff">if</span> ( v5 && (v6 = std__basic_string_char_std__char_traits_char__std__allocator_char____basic_string_char_std__char_traits_char__std__allocator_char__( &v8, L"<span style="color: #8b0000">1</span>"), v9 = 0, v7 = std__operator__(v6, v2), v9 = -1, std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v8), v7) ) { v3 = *(_DWORD *)(v1 + 12); result = (<span style="color: #0000ff">unsigned</span> __int8)sub_10016D60(*(_DWORD *)(v1 + 12)) && (<span style="color: #0000ff">unsigned</span> __int8)sub_10016E70(v3) && (<span style="color: #0000ff">unsigned</span> __int8)sub_10017570(v3) && (<span style="color: #0000ff">unsigned</span> __int8)sub_100172C0(v3); } <span style="color: #0000ff">else</span> { result = 0; } <span style="color: #0000ff">return</span> result; }</pre> <p>在这里面取了(jin)xml的一个属性值version,q且q有四个都不能失败的q程:<br />10016d60  取product 元素<br />10016e70  取creation 元素<br />10017570  取type元素<br />100172c0  取signature元素<br />Z(jin)熟?zhn)libxml,我特意编写了(jin)一D典型libxml用法,q分析了(jin)其反向工E后的代码, </p><p>代码:</p><pre> xmlDocPtr doc = NULL; xmlNodePtr cur = NULL; <span style="color: #0000ff">string</span> filename("<span style="color: #8b0000">test.xml</span>"); doc = xmlParseFile(filename.c_str()); cur = xmlDocGetRootElement(doc); <span style="color: #0000ff">if</span> (xmlStrcmp(cur->name, BAD_CAST "<span style="color: #8b0000">licence</span>")) { fprintf(stderr,"<span style="color: #8b0000">document of the wrong type, root node != mail</span>"); xmlFreeDoc(doc); <span style="color: #008000">/*return -1; */</span> } cur = cur->xmlChildrenNode; xmlNodePtr propNodePtr = cur; <span style="color: #0000ff">while</span>(cur != NULL) { <span style="color: #008000">//¨¨?3??¨²¦Ì??D¦Ì??¨²¨¨Y</span> <span style="color: #0000ff">if</span> ((!xmlStrcmp(cur->name, (<span style="color: #0000ff">const</span> xmlChar *)"<span style="color: #8b0000">product</span>"))) { <span style="color: #0000ff">string</span> name; <span style="color: #0000ff">string</span> version; xmlChar* szAttr = xmlGetProp(cur,BAD_CAST "<span style="color: #8b0000">name</span>"); name=(<span style="color: #0000ff">char</span>*)szAttr; szAttr=xmlGetProp(cur,BAD_CAST "<span style="color: #8b0000">version</span>"); version=(<span style="color: #0000ff">const</span> <span style="color: #0000ff">char</span> *)szAttr; cout<<"<span style="color: #8b0000">Name:</span>"<<name<<"<span style="color: #8b0000"> Version:</span>"<<version<<endl; xmlFree(szAttr); } cur=cur->next; } xmlFreeDoc(doc); <span style="color: #008000">/*return 0;*/</span></pre> <p>得出的结论是Q凡是属性值的获取Q都?x)调用xmlGetPropQ而子元素的获取则是通过直接讉K内存l构或者类似c++的函数访问,不会(x)看到函数名称的引用,Ҏ(gu)q一l论和具体的调试Q大致推出来licence文g的结构如? </p><p>代码:</p><pre><span style="color: #0000ff"><?</span>xml version="1.0" encoding="UTF-8"<span style="color: #0000ff">?></span> <span style="color: #0000ff"><</span><span style="color: #800000">licence</span> <span style="color: #ff0000">version</span>=<span style="color: #0000ff">"1"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">product</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"aspect"</span> <span style="color: #ff0000">version</span>=<span style="color: #0000ff">"1.0"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">product</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"pointcut"</span> <span style="color: #ff0000">version</span>=<span style="color: #0000ff">"1.0"</span> <span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">product</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"advice"</span> <span style="color: #ff0000">version</span>=<span style="color: #0000ff">"1.0"</span> <span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">product</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"slice"</span> <span style="color: #ff0000">version</span>=<span style="color: #0000ff">"1.0"</span> <span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">creation</span> <span style="color: #ff0000">date</span>=<span style="color: #0000ff">"2009-8-13"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"><</span><span style="color: #800000">type</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"user"</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">data</span> <span style="color: #ff0000">code</span>=<span style="color: #0000ff">"xxxx"</span> <span style="color: #ff0000">name</span>=<span style="color: #0000ff">"jans2002"</span> <span style="color: #ff0000">email</span>=<span style="color: #0000ff">"jans2002@gmail.com"</span> <span style="color: #ff0000">regnr</span>=<span style="color: #0000ff">"ccccc"</span><span style="color: #0000ff">/></span> <span style="color: #0000ff"></</span><span style="color: #800000">type</span><span style="color: #0000ff">></span> <span style="color: #0000ff"><</span><span style="color: #800000">signature</span> <span style="color: #ff0000">sign</span>=<span style="color: #0000ff">"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"</span> <span style="color: #0000ff">/></span> <span style="color: #0000ff"></</span><span style="color: #800000">licence</span><span style="color: #0000ff">></span></pre> <p> </p> <p>有了(jin)q个licence文gQ把它放?br />C:\Program Files\pure-systems\AspectC++ Add-In\etc\目录?br />一切问题就变得单了(jin),利执行完了(jin)0x10017930Q一路杀?x10017730 </p><p>代码:</p><pre><span style="color: #0000ff">int</span> __thiscall sub_10017730(<span style="color: #0000ff">int</span> <span style="color: #0000ff">this</span>, <span style="color: #0000ff">int</span> a2) { <span style="color: #0000ff">int</span> v2; <span style="color: #008000">// esi@1</span> <span style="color: #0000ff">signed</span> <span style="color: #0000ff">int</span> v3; <span style="color: #008000">// eax@4</span> <span style="color: #0000ff">int</span> v4; <span style="color: #008000">// ST14_4@6</span> <span style="color: #0000ff">int</span> v5; <span style="color: #008000">// eax@20</span> <span style="color: #0000ff">int</span> v7; <span style="color: #008000">// eax@4</span> <span style="color: #0000ff">int</span> r; <span style="color: #008000">// [sp+4Ch] [bp+0h]@1</span> <span style="color: #0000ff">int</span> v9; <span style="color: #008000">// [sp+3Ch] [bp-10h]@1</span> <span style="color: #0000ff">signed</span> <span style="color: #0000ff">int</span> v10; <span style="color: #008000">// [sp+48h] [bp-4h]@3</span> <span style="color: #0000ff">char</span> v11; <span style="color: #008000">// [sp+20h] [bp-2Ch]@4</span> <span style="color: #0000ff">char</span> v12; <span style="color: #008000">// [sp+4h] [bp-48h]@4</span> <span style="color: #0000ff">int</span> v13; <span style="color: #008000">// [sp+8h] [bp-44h]@20</span> <span style="color: #0000ff">unsigned</span> <span style="color: #0000ff">int</span> v14; <span style="color: #008000">// [sp+1Ch] [bp-30h]@20</span> <span style="color: #0000ff">int</span> v15; <span style="color: #008000">// [sp+18h] [bp-34h]@22</span> v2 = <span style="color: #0000ff">this</span>; v9 = r ^ dword_100242D0; std__basic_string_char_std__char_traits_char__std__allocator_char____operator_(a2, "<span style="color: #8b0000">Invalid licence file found.</span>"); <span style="color: #0000ff">if</span> ( *(_BYTE *)(v2 + 5) && !*(_BYTE *)(v2 + 4) ) { sub_10017B20(); v10 = 0; <span style="color: #0000ff">if</span> ( !(<span style="color: #0000ff">unsigned</span> __int8)sub_1001A050() ) { LABEL_23: v10 = -1; sub_1001A060(); <span style="color: #0000ff">return</span> sub_1001A7B0(); } v7 = std__operator_(&v11, v2 + 12, v2 + 40); LOBYTE(v10) = 1; std__operator_(&v12, v7, v2 + 68); LOBYTE(v10) = 3; std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v11); v3 = *(_DWORD *)(v2 + 8); <span style="color: #0000ff">if</span> ( v3 || !*(_DWORD *)(v2 + 96) ) { <span style="color: #0000ff">if</span> ( v3 == 1 && *(_DWORD *)(v2 + 96) && *(_DWORD *)(v2 + 100) && *(_DWORD *)(v2 + 104) && *(_DWORD *)(v2 + 108) ) { std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, "<span style="color: #8b0000">evaluation</span>"); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 96)); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 100)); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 104)); v4 = *(_DWORD *)(v2 + 108); } <span style="color: #0000ff">else</span> { <span style="color: #0000ff">if</span> ( v3 != 2 || !*(_DWORD *)(v2 + 96) || !*(_DWORD *)(v2 + 100) || !*(_DWORD *)(v2 + 104) || !*(_DWORD *)(v2 + 108) ) <span style="color: #0000ff">goto</span> LABEL_20; std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, "<span style="color: #8b0000">user</span>"); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 96)); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 100)); std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, *(_DWORD *)(v2 + 104)); v4 = *(_DWORD *)(v2 + 108); } } <span style="color: #0000ff">else</span> { std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, "<span style="color: #8b0000">beta</span>"); v4 = *(_DWORD *)(v2 + 96); } std__basic_string_char_std__char_traits_char__std__allocator_char____operator__(&v12, v4); LABEL_20: v5 = v13; <span style="color: #0000ff">if</span> ( v14 < 0x10 ) v5 = (<span style="color: #0000ff">int</span>)&v13; *(_BYTE *)(v2 + 4) = sub_10019E30(v2 + 112, v5, v15, (<span style="color: #0000ff">int</span>)&a2); LOBYTE(v10) = 0; std__basic_string_char_std__char_traits_char__std__allocator_char_____basic_string_char_std__char_traits_char__std__allocator_char__(&v12); <span style="color: #0000ff">goto</span> LABEL_23; } <span style="color: #0000ff">return</span> sub_1001A7B0(); }</pre> <p>׃有了(jin)正确格式的licenceQ前面执行的都很利Q一直到?jin)sub_10019E30,跟进M看,一切了(jin)然了(jin): </p><p>代码:</p><pre><span style="color: #0000ff">bool</span> __thiscall sub_10019E30(<span style="color: #0000ff">int</span> <span style="color: #0000ff">this</span>, <span style="color: #0000ff">int</span> a2, <span style="color: #0000ff">int</span> a3, <span style="color: #0000ff">int</span> a4) { <span style="color: #0000ff">int</span> v5; <span style="color: #008000">// esi@1</span> <span style="color: #0000ff">int</span> v6; <span style="color: #008000">// eax@1</span> <span style="color: #0000ff">int</span> v7; <span style="color: #008000">// eax@1</span> <span style="color: #0000ff">char</span> v8; <span style="color: #008000">// [sp+4h] [bp-10h]@1</span> v5 = <span style="color: #0000ff">this</span>; v6 = EVP_sha1(); EVP_DigestInit(&v8, v6); EVP_DigestUpdate(&v8, a2, a3); v7 = sub_1001A030(); <strong> <span style="color: #0000ff">return</span> EVP_VerifyFinal(&v8, v5, *(_DWORD *)(v5 + 4096), v7) == 1;</strong></pre><pre>}</pre> <p>前面一定都是加密验证的Q但是函数最后来?jin)一? </p><p>代码:</p><pre><strong>EVP_VerifyFinal(&v8, v5, *(_DWORD *)(v5 + 4096), v7) == 1;</strong> </pre> <p>嘿嘿Q看名字估计是q个?jin),看看q个函数的返回|1表示成功Q其他表C失败,那就是只要让此函数永q返?Q就大功告成?jin),该到汇编代码? </p><p>代码:</p><pre>004066F0 /$ 83EC 10 sub esp, 10 ; (g)查数字签名部? 004066F3 |. 56 push esi 004066F4 |. 8BF1 mov esi, ecx 004066F6 |. E8 81270000 call <jmp.&LIBEAY32.#333> 004066FB |. 50 push eax 004066FC |. 8D4424 08 lea eax, dword ptr [esp+8] 00406700 |. 50 push eax 00406701 |. E8 70270000 call <jmp.&LIBEAY32.#268> 00406706 |. 8B4C24 24 mov ecx, dword ptr [esp+24] 0040670A |. 8B5424 20 mov edx, dword ptr [esp+20] 0040670E |. 51 push ecx 0040670F |. 52 push edx 00406710 |. 8D4424 14 lea eax, dword ptr [esp+14] 00406714 |. 50 push eax 00406715 |. E8 56270000 call <jmp.&LIBEAY32.#269> 0040671A |. 8B4C24 34 mov ecx, dword ptr [esp+34] 0040671E |. 83C4 14 add esp, 14 00406721 |. E8 2A100000 call 00407750 00406726 |. 8B8E 00100000 mov ecx, dword ptr [esi+1000] 0040672C |. 50 push eax 0040672D |. 51 push ecx 0040672E |. 8D5424 0C lea edx, dword ptr [esp+C] 00406732 |. 56 push esi 00406733 |. 52 push edx 00406734 |. E8 49270000 call <jmp.&LIBEAY32.#290> 00406739 |. 83C4 10 add esp, 10 0040673C |. 48 dec eax 0040673D |. F7D8 neg eax 0040673F 1BC0 sbb eax, eax <strong>00406741 90 inc eax</strong> 00406742 5E pop esi 00406743 83C4 10 add esp, 10 00406746 \. C2 0C00 retn 0C</pre> <p>一般来Ԍ函数q回值都?x)用EAX,不管三七二十一?jin),先吧EAX做了(jin)再说Q把上面那个黑体?br />inc eax Ҏ(gu)nopQ呵呵,nop是大家的最?机器码是90?q是改过的了(jin)) <br />保存到文件?br />大功告成哈!Q? </p><p>wؓ(f)菜鸟Q能取得q样的结果,真是让h兴奋Q谢谢各位阅读,q请各位高手不吝赐教?br />下蝲<a href="http://www.shnenglu.com/Files/jans2002/crack.zip">安装E序?qing)破?/a></p><img src ="http://www.shnenglu.com/jans2002/aggbug/93354.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/jans2002/" target="_blank">jans2002</a> 2009-08-14 17:59 <a href="http://www.shnenglu.com/jans2002/archive/2009/08/14/93354.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>UnDName工具Q显C函C饰名U工?/title><link>http://www.shnenglu.com/jans2002/archive/2009/08/14/93353.html</link><dc:creator>jans2002</dc:creator><author>jans2002</author><pubDate>Fri, 14 Aug 2009 09:51:00 GMT</pubDate><guid>http://www.shnenglu.com/jans2002/archive/2009/08/14/93353.html</guid><wfw:comment>http://www.shnenglu.com/jans2002/comments/93353.html</wfw:comment><comments>http://www.shnenglu.com/jans2002/archive/2009/08/14/93353.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/jans2002/comments/commentRss/93353.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/jans2002/services/trackbacks/93353.html</trackback:ping><description><![CDATA[<blockquote style="width: 79.16%; height: 578px"> <p>在一个用UNICODE的工E里使用log4cplus 1.0.3库,发现L发生链接错误。猜惛_能是log4cplus需要在UNICODE下编译,ZDebug和Release两个复制?jin)Unicode Debug/Release配置Q开始编译?UniRelease很容易通过?jin)编译,但是UniDebug却L发生链接错误Q但是函数肯定已l实C(jin)Q将链接错误发生的文件Appender.obj文g打开Q然后比较编译器里报出的信息</p> <p>一个是</p> <p><a href="mailto:?error@OnlyOnceErrorHandler@log4cplus@@UAEXABV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@Z">?error@OnlyOnceErrorHandler@log4cplus@@UAEXABV?$basic_string@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@Z</a> <p>而链式器找不到的W号是:(x)</p> <p><a href="mailto:?error@OnlyOnceErrorHandler@log4cplus@@UAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z">?error@OnlyOnceErrorHandler@log4cplus@@UAEXABV?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z</a> <p>q两个符号都很晦涩,很难让h搞明白什么意思,攄一搜,q真有工具叫undname.exeQ在VC7.1里自带, <p>Undecoration of :- "?error@OnlyOnceErrorHandler@log4cplus@@UAEXABV?$basic_string<br>@GU?$char_traits@G@std@@V?$allocator@G@2@@std@@@Z"<br>is :- "public: virtual void __thiscall log4cplus::OnlyOnceErrorHandler::error(cl<br>ass std::basic_string<unsigned short,struct std::char_traits<unsigned short>,cla<br>ss std::allocator<unsigned short> > const &)" <p>Undecoration of :- "?error@OnlyOnceErrorHandler@log4cplus@@UAEXABV?$basic_string<br>@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@@Z"<br>is :- "public: virtual void __thiscall log4cplus::OnlyOnceErrorHandler::error(cl<br>ass std::basic_string<char,struct std::char_traits<char>,class std::allocator<ch<br>ar> > const &)" <p>一Ҏ(gu)Q就知道可能q是UNICODE的原因,仔细(g)查C++预处理符可|,发现好多都还是MCBSQ修改,重新~译Q问题解冟? </blockquote><img src ="http://www.shnenglu.com/jans2002/aggbug/93353.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/jans2002/" target="_blank">jans2002</a> 2009-08-14 17:51 <a href="http://www.shnenglu.com/jans2002/archive/2009/08/14/93353.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单的makefile例子http://www.shnenglu.com/jans2002/archive/2009/04/05/78989.htmljans2002jans2002Sun, 05 Apr 2009 01:35:00 GMThttp://www.shnenglu.com/jans2002/archive/2009/04/05/78989.htmlhttp://www.shnenglu.com/jans2002/comments/78989.htmlhttp://www.shnenglu.com/jans2002/archive/2009/04/05/78989.html#Feedback0http://www.shnenglu.com/jans2002/comments/commentRss/78989.htmlhttp://www.shnenglu.com/jans2002/services/trackbacks/78989.htmlall   :   $(NAME).exe
$(NAME).obj:   $(NAME).cxx
    cl   $(NAME).cxx   /G7   /MD   /Ox   /Ot   /W3   /c   /EHsc   /I "D:\log4cplus-1.0.3\include"
$(NAME).exe:   $(NAME).obj
    link   $(NAME).obj    /out:$(NAME).exe /LIBPATH:"D:\log4cplus-1.0.3\msvc6\Debug"  /SUBSYSTEM:CONSOLE   /MACHINE:X86 log4cplusd.lib
clean:
    del *.obj
    del *.exe

jans2002 2009-04-05 09:35 发表评论
]]>
解开 Windows 下的临界Z的代码死?/title><link>http://www.shnenglu.com/jans2002/archive/2009/02/20/74367.html</link><dc:creator>jans2002</dc:creator><author>jans2002</author><pubDate>Fri, 20 Feb 2009 02:03:00 GMT</pubDate><guid>http://www.shnenglu.com/jans2002/archive/2009/02/20/74367.html</guid><wfw:comment>http://www.shnenglu.com/jans2002/comments/74367.html</wfw:comment><comments>http://www.shnenglu.com/jans2002/archive/2009/02/20/74367.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/jans2002/comments/commentRss/74367.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/jans2002/services/trackbacks/74367.html</trackback:ping><description><![CDATA[<h3>解开 Windows 下的临界Z的代码死?/h3> <p><a >Matt Pietrek</a>?<a >Russ Osterlund</a> <p>本文假定(zhn)熟(zhn)?Win32、C++ 和多U程处理?<p>下蝲本文的代码:(x)<a >CriticalSections.exe</a> (415KB) <p><strong>摘要</strong><strong></strong> <p>临界区是一U防止多个线E同时执行一个特定代码节的机Ӟq一主题q没有引起太多关注,因而h们未能对其深ȝ解。在需要跟t代码中的多U程处理的性能Ӟ?Windows 中(f)界区的深ȝ解非常有用?本文深入研究临界区的原理Q以揭示在查找死锁和认性能问题q程中的有用信息。它q包含一个便利的实用工具E序Q可以显C所有(f)界区?qing)其当前状态?<p>在我们许多年的编E实践中Q对?Win32] 临界区没有受到非常多的“under the hood”关注而感到非常奇怪。当?dng)?zhn)可能了(jin)解有关(f)界区初始化与使用的基知识Q但(zhn)是否曾l花Ҏ(gu)间来深入研究 WINNT.H 中所定义?CRITICAL_SECTION l构呢?在这一l构中有一些非常有意义的好东西被长期忽略。我们将Ҏ(gu)q行补充Qƈ向?zhn)介绍一些很有意义的技巧,q些技巧对于跟t那些难以察觉的多线E处理错误非常有用。更重要的是Q用我们的 MyCriticalSections 实用工具Q可以明白如何对 CRITICAL_SECTION q行微小地扩展,以提供非常有用的Ҏ(gu),q些Ҏ(gu)可用于调试和性能调整Q要下蝲完整代码Q参见本文顶部的链接Q?<p>老实_(d)作者们l常忽略 CRITICAL_SECTION l构的部分原因在于它在以下两个主?Win32 代码库中的实现有很大不同QMicrosoft] Windows] 95 ?Windows NT]。h们知道这两种代码库都已经发展出大量后l版本(其最新版本分别ؓ(f) Windows Me ?Windows XPQ,但没有必要在此处其一一列出。关键在?Windows XP 现在已经发展得非常完善,开发商可能很快׃(x)停止?Windows 95 pd操作pȝ的支持。我们在本文中就是这么做的?<p>诚然Q当今最受关注的?Microsoft .NET FrameworkQ但是良好的旧式 Win32 ~程不会(x)很快消失。如果?zhn)拥有采用了(jin)?f)界区的现?Win32 代码Q?zhn)会(x)发现我们的工具以?qing)对(f)界区的说明都非常有用。但是请注意Q我们只讨论 Windows NT ?qing)其后?hu)版本Q而没有涉?qing)?.NET 相关的Q何内容,q一炚w帔R要?<p>临界区:(x)q?<p>如果(zhn)非常熟(zhn)(f)界区Qƈ可以不假思烦(ch)地进行应用,那就可以略过本节。否则,请向下阅读,以对q些内容q行快速回。如果?zhn)不熟?zhn)这些基内容Q则本节之后的内容就没有太大意义?<p>临界区是一U轻量机制Q在某一旉内只允许一个线E执行某个给定代码段。通常在修改全局数据Q如集合c)(j)时会(x)使用临界区。事件、多用户l端执行E序和信号量也用于多U程同步Q但临界Z它们不同Q它q不L执行向内核模式的控制转换Q这一转换成本昂贵。稍后将?x)看刎ͼ要获得一个未占用临界区,事实上只需要对内存做出很少的修改,光度非常快。只有在试获得已占用(f)界区Ӟ它才?x)蟩臛_核模式。这一轻量U特性的~点在于临界区只能用于对同一q程内的U程q行同步?<p>临界区由 WINNT.H 中所定义?RTL_CRITICAL_SECTION l构表示。因为?zhn)?C++ 代码通常声明一?CRITICAL_SECTION cd的变量,所以?zhn)可能?gu)q不?jin)解。研I?WINBASE.H 后?zhn)会(x)发玎ͼ?x) <pre>typedef RTL_CRITICAL_SECTION CRITICAL_SECTION; </pre> <p>我们在短时间内揭示 RTL_CRITICAL_SECTION l构的实质。此Ӟ重要问题在于 CRITICAL_SECTIONQ也UC RTL_CRITICAL_SECTIONQ只是一个拥有易讉K字段的结构,q些字段可以?KERNEL32 API 操作? <p>在将临界Z递给 InitializeCriticalSection Ӟ或者更准确地说Q是在传递其地址Ӟ(j)Q(f)界区卛_始存在。初始化之后Q代码即(f)界区传递给 EnterCriticalSection ?LeaveCriticalSection API。一个线E自 EnterCriticalSection 中返回后Q所有其他调?EnterCriticalSection 的线E都被LQ直到第一个线E调?LeaveCriticalSection 为止。最后,当不再需要该临界区时Q一U良好的~码?fn)惯是将其传递给 DeleteCriticalSection? <p>在(f)界区未被使用的理x(chng)况中Q对 EnterCriticalSection 的调用非常快速,因ؓ(f)它只是读取和修改用户模式内存?sh)的内存(sh)置。否则(在后文将?x)遇CU例外情况)(j)Q阻止于临界区的U程有效地完成这一工作Q而不需要消耗额外的 CPU 周期。所L的线E以内核模式{待Q在该(f)界区的所有者将光放之前,不能对这些线E进行调度。如果有多个U程被阻止于一个(f)界区中,当另一U程释放该(f)界区Ӟ只有一个线E获得该临界区? <p>深入研究QRTL_CRITICAL_SECTION l构 <p>即(zhn)已l在日常工作中用过临界区,(zhn)也非常可能q没有真正了(jin)解超出文档之外的内容。事实上存在着很多非常Ҏ(gu)掌握的内宏V例如,Z很少知道一个进E的临界区是保存?sh)一个链表中Qƈ且可以对其进行枚举。实际上QW(xu)INDBG 支持 !locks 命o(h)Q这一命o(h)可以列出目标q程中的所有(f)界区。我们稍后将要谈到的实用工具也应用了(jin)临界一鲜ؓ(f)人知的特征。ؓ(f)?jin)真正理解这一实用工具如何工作Q有必要真正掌握临界区的内部l构。记着q一点,现在开始研I?RTL_CRITICAL_SECTION l构。ؓ(f)方便赯Q将此结构列出如下:(x) <pre>struct RTL_CRITICAL_SECTION { PRTL_CRITICAL_SECTION_DEBUG DebugInfo; LONG LockCount; LONG RecursionCount; HANDLE OwningThread; HANDLE LockSemaphore; ULONG_PTR SpinCount; }; </pre> <p>以下各段Ҏ(gu)个字D进行说明? <p><strong>DebugInfo</strong> 此字D包含一个指针,指向pȝ分配的伴随结构,该结构的cd?RTL_CRITICAL_SECTION_DEBUG。这一l构中包含更多极有h(hun)值的信息Q也定义?WINNT.H 中。我们稍后将对其q行更深入地研究? <p><strong>LockCount</strong> q是临界Z最重要的一个字Dc(din)它被初始化为数?-1Q此数值等于或大于 0 Ӟ表示此(f)界区被占用。当其不{于 -1 ӞOwningThread 字段Q此字段被错误地定义?WINNT.H ??应当?DWORD 而不?HANDLEQ包含了(jin)拥有此(f)界区的线E?ID。此字段?(RecursionCount -1) 数g间的差DC有多少个其他线E在{待获得该(f)界区? <p><strong>RecursionCount</strong> 此字D包含所有者线E已l获得该临界区的ơ数。如果该数gؓ(f)Ӟ下一个尝试获取该临界区的U程会(x)成功? <p><strong>OwningThread</strong> 此字D包含当前占用此临界区的U程的线E标识符。此U程 ID ?GetCurrentThreadId 之类?API 所q回?ID 相同? <p><strong>LockSemaphore</strong> 此字D늚命名不恰当,它实际上是一个自复位事gQ而不是一个信受它是一个内核对象句柄,用于通知操作pȝQ该临界区现在空闌Ӏ操作系l在一个线E第一ơ尝试获得该临界区,但被另一个已l拥有该临界区的U程所LӞ自动创徏q样一个句柄。应当调?DeleteCriticalSectionQ它?yu)发Z个调用该事g?CloseHandle 调用Qƈ在必要时释放该调试结构)(j)Q否则将?x)发生资源泄漏? <p><strong>SpinCount</strong> 仅用于多处理器系l。MSDN] 文档Ҏ(gu)字段q行如下说明Q“在多处理器pȝ中,如果该(f)界区不可用,调用U程在对与该(f)界区相关的信h行等待操作之前,旋{ dwSpinCount ơ。如果该临界区在旋{操作期间变(sh)ؓ(f)可用Q该调用U程避免了(jin){待操作。”旋转计数可以在多处理器计算Z提供更佳性能Q其原因在于在一个@环中旋{通常要快于进入内核模式等待状态。此字段默认gؓ(f)Ӟ但可以用 InitializeCriticalSectionAndSpinCount API 其讄Z个不同倹{? <p>RTL_CRITICAL_SECTION_DEBUG l构 <p>前面我们注意刎ͼ?RTL_CRITICAL_SECTION l构内,DebugInfo 字段指向一?RTL_CRITICAL_SECTION_DEBUG l构Q该l构l出如下Q?<pre>struct _RTL_CRITICAL_SECTION_DEBUG { WORD Type; WORD CreatorBackTraceIndex; RTL_CRITICAL_SECTION *CriticalSection; LIST_ENTRY ProcessLocksList; DWORD EntryCount; DWORD ContentionCount; DWORD Spare[ 2 ]; } </pre> <p>q一l构?InitializeCriticalSection 分配和初始化。它既可以由 NTDLL 内的预分配数l分配,也可以由q程堆分配。RTL_CRITICAL_SECTION 的这一伴随l构包含一l匹配字D,hq然不同的角Ԍ(x)有两个难以理解,随后两个提供?jin)理解这一临界区链l构的关键,两个是重复设|的Q最后两个未使用? <p>下面是对 RTL_CRITICAL_SECTION 字段的说明? <p><strong>Type</strong> 此字D|使用Q被初始化ؓ(f)数?0? <p><strong>CreatorBackTraceIndex</strong> 此字D仅用于诊断情Ş中。在注册表项 HKLM\Software\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\YourProgram 之下?keyfield、GlobalFlag ?StackTraceDatabaseSizeInMb 倹{注意,只有在运行稍后说明的 Gflags 命o(h)时才?x)显C些倹{这些注册表值的讄正确ӞCreatorBackTraceIndex 字段由堆栈跟踪中所用的一个烦(ch)引值填充。在 <a >MSDN</a> 中搜?GFlags 文档中的短语“create user mode stack trace database”和“enlarging the user-mode stack trace database”,可以扑ֈ有关q一内容的更多信息? <p><strong>CriticalSection</strong> 指向与此l构相关?RTL_CRITICAL_SECTION?strong>?1</strong> 说明该基l构以及(qing) RTL_CRITICAL_SECTION、RTL_CRITICAL_SECTION_DEBUG 和事仉中其他参与者之间的关系? <p><img height="378" alt="fig01" src="http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/art/Deadlockfig01.gif" width="271" border="0"> <p><strong>?1 临界区处理流E?/strong> <p><strong>ProcessLocksList</strong> LIST_ENTRY 是用于表C双向链表中节点的标?Windows 数据l构。RTL_CRITICAL_SECTION_DEBUG 包含?jin)链表的一部分Q允许向前和向后遍历该(f)界区。本文后面给出的实用工具说明如何使用 FlinkQ前向链接)(j)?BlinkQ后向链接)(j)字段在链表中的成员(sh)间移动。Q何从事过讑֤驱动E序或者研I过 Windows 内核的h都会(x)非常熟?zhn)q一数据l构? <p><strong>EntryCount/ContentionCount</strong> q些字段在相同的旉、出于相同的原因被递增。这是那些因Z能马上获得(f)界区而进入等待状态的U程的数目。与 LockCount ?RecursionCount 字段不同Q这些字D|q都不会(x)递减? <p><strong>Spares</strong> q两个字D|使用Q甚x(chng)被初始化Q尽在删除临界区结构时这些字D进行了(jin)清零Q。后面将?x)说明,可以用这些未被用的字段来保存有用的诊断倹{? <p>即 RTL_CRITICAL_SECTION_DEBUG 中包含多个字D,它也是常规(f)界区l构的必要成分。事实上Q如果系l恰巧不能由q程堆中获得q一l构的存储区QInitializeCriticalSection 返回ؓ(f) STATUS_NO_MEMORY ?LastError l果Q然后返回处于不完整状态的临界区结构? <p>临界区状? <p>当程序执行、进入与d临界区时QRTL_CRITICAL_SECTION ?RTL_CRITICAL_SECTION_DEBUG l构中的字段?x)根据?f)界区所处的状态变化。这些字D는临界?API 中的记代码更新Q在后面会(x)看到q一炏V如果程序ؓ(f)多线E,q且其线E访问是׃(f)界区保护的公用资源,则这些状态就更有意义? <p>但是Q不代码的U程使用情况如何Q有两种状态都?x)出现。第一U情况,如果 LockCount 字段有一个不{于 -1 的数|此(f)界区被占用,OwningThread 字段包含拥有该(f)界区的线E的U程标识W。在多线E程序中QLockCount ?RecursionCount 联合表明当前有多线E被L于该临界区。第二种情况Q如?RecursionCount 是一个大?1 的数|其告知?zhn)所有者线E已l重新获得该临界区多次Q也怸必要Q,该(f)界区既可以通过调用 EnterCriticalSection、也可以通过调用 TryEnterCriticalSection 获得。大?1 的Q何数值都表示代码的效率可能较低或者可能在以后发生错误。例如,讉K公共资源的Q?C++ cL法可能会(x)不必要地重新q入该(f)界区? <p>注意Q在大多数时间里QLockCount ?RecursionCount 字段中分别包含其初始?-1 ?0Q这一炚w帔R要。事实上Q对于单U程E序Q不能仅通过(g)查这些字D|判断是否曾获得过临界区。但是,多线E程序留下了(jin)一些标讎ͼ可以用来判断是否有两个或多个U程试图同时拥有同一临界区? <p>(zhn)可以找到的标记之一是即使在该(f)界区未被占用?LockSemaphore 字段中仍包含一个非零倹{这表示Q在某一旉Q此临界区阻止了(jin)一个或多个U程 ?事g句柄用于通知该(f)界区已被释放Q等待该临界区的U程之一现在可以获得该(f)界区ql执行。因?OS 在(f)界区L另一个线E时自动分配事g句柄Q所以如果?zhn)在不再需要(f)界区时忘记将其删除,LockSemaphore 字段可能?x)导致程序中发生资源泄漏? <p>在多U程E序中可能遇到的另一状态是 EntryCount ?ContentionCount 字段包含一个大于零的数倹{这两个字段保存有(f)界区对一个线E进行阻止的ơ数。在每次发生q一事gӞq两个字D被递增Q但在(f)界区存在期间不会(x)被递减。这些字D可用于间接定E序的执行\径和Ҏ(gu)。例如,EntryCount 非常高时则意味着该(f)界区l历着大量争用Q可能会(x)成ؓ(f)代码执行q程中的一个潜在瓶颈? <p>在研I一个死锁程序时Q还?sh)(x)发CU似乎无法进行逻辑解释的状态。一个用非帔RJ的临界区的 LockCount 字段中包含一个大?-1 的数|也就是说它被U程所拥有Q但?OwningThread 字段为零Q这样就无法扑և是哪个线E导致问题)(j)。测试程序是多线E的Q在单处理器计算机和多处理器计算Z都会(x)出现q种情况。尽?LockCount 和其他值在每次q行中都不同Q但此程序L死锁于同一临界区。我们非常希望知道是否有M其他开发h员(sh)遇到?jin)导致这一状态的 API 调用序列? <p>构徏一个更好的捕鼠? <p>在我们学?fn)?f)界区的工作方式时Q非常偶然地得到一些重要发玎ͼ利用q些发现可以得到一个非常好的实用工兗第一个发现是 ProcessLocksList LIST_ENTRY 字段的出玎ͼq我们惛_q程的(f)界区可能是可枚D的。另一个重大发现是我们知道?jin)如何找Z(f)界区列表的头。还有一个重要发现是可以在没有Q何损q情况下写 RTL_CRITICAL_SECTION ?Spare 字段Q至在我们的所有测试中如此Q。我们还发现可以很容易地重写pȝ的一些(f)界区例程Q而不需要对源文件进行Q何修攏V? <p>最初,我们׃个简单的E序开始,其检查一个进E中的所有(f)界区Qƈ列出其当前状态,以查看是否拥有这些(f)界区。如果拥有,则找出由哪个U程拥有Q以?qing)该临界区阻止?jin)多少个线E?q种做法对于 OS 的狂热者们比较适合Q但对于只是希望有助于理解其E序的典型的E序员就不是非常有用?jin)? <p>即是在最单的控制台模式“Hello World”程序中也存在许多(f)界区。其中大部分是由 USER32 ?GDI32 之类的系l?DLL 创徏Q而这?DLL 很少?x)导致死锁或性能问题。我们希望有一U方法能滤除q些临界区,而只留下代码中所兛_(j)的那些(f)界区。RTL_CRITICAL_SECTION_DEBUG l构中的 Spare 字段可以很好地完成这一工作。可以用其中的一个或两个来指C:(x)q些临界区是来自用户~写的代码,而不是来?OS? <p>于是Q下一个逻辑问题变?sh)如何确定哪些?f)界区是来自?zhn)~写的代码。有些读者可能还记得 Matt Pietrek 2001 q?1 月的 <a >Under The Hood</a> 专栏中的 LIBCTINY.LIB。LIBCTINY 所采用的一个技巧是一?LIB 文gQ它重写?jin)关?Visual C++ q行时例E的标准实现。将 LIBCTINY.LIB 文g|于链接器行的其?LIB 之前Q链接器用这一实现Q而不是?Microsoft 所提供的导入库中的同名后箋(hu)版本? <p>为对临界区应用类似技巧,我们创徏 InitializeCriticalSection 的一个替代版本及(qing)其相兛_入库。将?LIB 文g|于 KERNEL32.LIB 之前Q链接器链接我们的版本Q而不?KERNEL32 中的版本。对 InitializeCriticalSection 的实现显C在<a >?2</a> 中。此代码在概念上非常单。它首先调用 KERNEL32.DLL 中的实际 InitializeCriticalSection。接下来Q它获得调用 InitializeCriticalSection 的代码地址Qƈ其贴至 RTL_CRITICAL_SECTION_DEBUG l构的备用字D之一。我们的代码如何定调用代码的地址呢?x86 CALL 指o(h)返回地址|于堆栈中。CriticalSectionHelper 代码知道该返回地址位于堆栈帧中一个已知的固定位置? <p>实际l果是:(x)?CriticalSectionHelper.lib 正确链接的Q?EXE ?DLL 都将导入我们?DLL (CriticalSectionHelper.DLL)Qƈ占用应用?jin)备用字D늚临界区。这样就使事情简单了(jin)许多。现在我们的实用工具可以单地遍历q程中的所有(f)界区Qƈ且只昄h正确填充的备用字D늚临界Z息。那么需要ؓ(f)q一实用工具付出什么代价呢Q请E等Q还有更多的内容Q? <p>因ؓ(f)(zhn)的所有(f)界区现在都包含对其进行初始化时的地址Q实用工具可以通过提供其初始化地址来识别各个(f)界区。原始代码地址本n没有那么有用。幸q的是,DBGHELP.DLL 使代码地址向源文g、行号和函数名称的{换变得非常容易。即使一个(f)界区中没有?zhn)在其中的{֐Q也可以其地址提交l?DBGHELP.DLL。如果将其声明ؓ(f)一个全局变量Qƈ且如果符号可用,则?zhn)可以在原始源代码中定临界区的名称。顺便说明一下,如果通过讄 _NT_SYMBOL_PATH 环境变量Qƈ讄 DbgHelp 以用其 Symbol Server 下蝲功能Q从而 DbgHelp 发挥其效用,则会(x)得到非常好的l果? <p>MyCriticalSections 实用工具 <p>我们所有这些思想l合hQ提Z(jin) MyCriticalSections E序。MyCriticalSections 是一个命令行E序Q在不用参数运行该E序时可以看C些选项Q?<pre>Syntax: MyCriticalSections <PID> [options] Options: /a = all critical sections /e = show only entered critical sections /v = verbose </pre> <p>唯一需要的参数?Program ID ?PIDQ十q制形式Q。可以用多种Ҏ(gu)获得 PIDQ但最单的Ҏ(gu)可能是通过 Task Manager。在没有其他选项ӞMyCriticalSections 列出?jin)来自代码模块的所有(f)界区状态,(zhn)已l将 CriticalSectionHelper.DLL 链接臌些代码模块。如果有可用于这一Q些Q模块的W号Q代码将试提供该(f)界区的名Uͼ以及(qing)对其q行初始化的位置? <p>要查?MyCriticalSections 是如何v作用的,误?Demo.EXE E序Q该E序包含在下载文件中。Demo.EXE 只是初始化两个(f)界区Qƈ׃对线E进入这两个临界区?a >?3</a> 昄q行“MyCriticalSections 2040”的l果Q其?2040 ?Demo.EXE ?PIDQ? <p>在该图中Q列Z(jin)两个临界区。在本例中,它们被命名ؓ(f) csMain ?yetAnotherCriticalSection。每个“Address:”行昄?CRITICAL_SECTION 的地址?qing)其名称。“Initialized in”行包含?jin)在其中初始?CRITICAL_SECTION 的函数名。代码的“Initialized at”行昄?jin)源文g和初始化函数中的行号? <p>对于 csMain 临界区,(zhn)将看到锁定Cؓ(f) 0、递归Cؓ(f) 1Q表CZ个已l被一U程获得的(f)界区Qƈ且没有其他线E在{待该(f)界区。因Z来没有线E被L于该临界区,所?Entry Count 字段?0? <p>现在来看 yetAnotherCriticalSectionQ会(x)发现光归Cؓ(f) 3。快速浏?Demo 代码可以看出Q主U程调用 EnterCriticalSection 三次Q所以事情的发生与预期一致。但是,q有一个第二线E试图获得该临界区,q且已经被阻止。同PLockCount 字段也ؓ(f) 3。此输出昄有一个等待线E? <p>MyCriticalSections 拥有一些选项Q其对于更为勇敢的探烦(ch)者非常有用?v 开x(chng)C每个(f)界区的更多信息。旋转数与锁定信号字D尤为重要。?zhn)l常?x)看?NTDLL 和其?DLL 拥有一些旋转数非零的(f)界区。如果一个线E在获得临界区的q程中曾被锁定,则锁定信号字Dؓ(f)非零倹{?v 开兌昄?RTL_CRITICAL_SECTION_DEBUG l构中备用字D늚内容? <p>/a 开x(chng)CE中的所有(f)界区Q即使其中没?CriticalSectionHelper.DLL {֐也会(x)昄。如果?/aQ则请做好有大量输出的准备。真正的黑客希望同时使用 /a ?/vQ以昄q程中全部内容的最多细节。?/a 的一个小的好处是会(x)看到 NTDLL 中的LdrpLoaderLock 临界区。此临界区在 DllMain 调用和其他一些重要时间内被占用。LdrpLoaderLock 是许多不太明显、表面上难以解释的死锁的形成原因之一。(Z MyCriticalSection 能够正确标记 LdrpLoaderLock 实例Q需要用?NTDLL ?PDB 文g可供使用。)(j) <p>/e 开关ɽE序仅显C当前被占用的(f)界区。未使用 /a 开x(chng)Q只昄代码中被占用的(f)界区Q如备用字段中的{֐所指示Q。采?/a 开x(chng)Q将昄q程中的全部被占用(f)界区Q而不考虑其来源? <p>那么Q希望什么时候运?MyCriticalSections 呢?一个很明确的时间是在程序被死锁时。检查被占用的(f)界区Q以查看是否有什么(zhn)惊讶的事情。即使被死锁的程序正q行于调试器的控制之下,也可以?MyCriticalSections? <p>另一U?MyCriticalSections 的时机是在对有大量多U程的程序进行性能调整时。在d于调试器中的一个用频J、非重入函数Ӟq行 MyCriticalSectionsQ查看在该时d用了(jin)哪些临界区。如果有很多U程都执行相同Q务,非常容易导致一U情形:(x)一个线E的大部分时间被消耗在{待获得一个用频J的临界Z。如果有多个使用频繁的(f)界区Q这造成的后果就像花园的水软管打了(jin)l一栗解决一个争用问题只是将问题转移C一个容易造成d的(f)界区? <p>一个查看哪些(f)界区最Ҏ(gu)D争用的好Ҏ(gu)是在接近E序l尾处设|一个断炏V在遇到断点Ӟq行 MyCriticalSections q查扑օ有最?Entry Count 值的临界区。正是这些(f)界区D?jin)大多数d和线E{换? <p>管 MyCriticalSections q行?Windows 2000 ?qing)更新版本,但(zhn)仍需要一个比较新?DbgHelp.DLL 版本 Q?5.1 版或更新版本。Windows XP 中提供这一版本。也可以由其他?DbgHelp 的工具中获得该版本。例如,<a >Debugging Tools For Windows</a> 下蝲中通常拥有最新的 DbgHelp.DLL? <p>深入研究重要的(f)界区例程 <p>此最后一节是为那些希望理解(f)界区实现内幕的勇敢读者提供的。对 NTDLL q行仔细研究后可以ؓ(f)q些例程?qing)其支持子例E创Z码(见下载中?NTDLL(CriticalSections).cppQ。以?KERNEL32 API l成临界区的公共接口Q?<pre>InitializeCriticalSection InitializeCriticalSectionAndSpinCount DeleteCriticalSection TryEnterCriticalSection EnterCriticalSection LeaveCriticalSection </pre> <p>前两?API 只是分别围绕 NTDLL API RtlInitializeCriticalSection ?RtlInitializeCriticalSectionAndSpinCount 的瘦包装。所有剩余例E都被提交给 NTDLL 中的函数。另外,?RtlInitializeCriticalSection 的调用是另一个围l?RtlInitializeCriticalSectionAndSpinCount 调用的瘦包装Q其旋{数的gؓ(f) 0。用(f)界区的时候实际上是在q后使用以下 NTDLL APIQ?<pre>RtlInitializeCriticalSectionAndSpinCount RtlEnterCriticalSection RtlTryEnterCriticalSection RtlLeaveCriticalSection RtlDeleteCriticalSection </pre> <p>在这一讨论中,我们采用 Kernel32 名称Q因为大多数 Win32 E序员对它们更ؓ(f)熟?zhn)? <p>InitializeCriticalSectionAndSpinCount 对(f)界区的初始化非常单。RTL_CRITICAL_SECTION l构中的字段被赋予其起始倹{与此类|分配 RTL_CRITICAL_SECTION_DEBUG l构q对其进行初始化Q将 RtlLogStackBackTraces 调用中的q回D?CreatorBackTraceIndexQƈ建立到前面(f)界区的链接? <p>Z说一壎ͼCreatorBackTraceIndex 一般接收到的gؓ(f) 0。但是,如果?Gflags ?Umdh 实用工具Q可以输入以下命令:(x) <pre>Gflags /i MyProgram.exe +ust Gflags /i MyProgram.exe /tracedb 24 </pre> <p>q些命o(h)使得 MyProgram 的“Image File Execution Options”下d?jin)注册表V在下一ơ执?MyProgram 时会(x)看到此字D|收到一个非 0 数倹{有x(chng)多信息,参阅知识库文?Q268343?a >Umdhtools.exe:How to Use Umdh.exe to Find Memory Leaks</a>”。(f)界区初始化中另一个需要注意的问题是:(x)?64 ?RTL_CRITICAL_SECTION_DEBUG l构不是pE堆中分配,而是来自位于 NTDLL 内的 .data 节的一个数l? <p>在完成(f)界区的用之后,?DeleteCriticalSectionQ其命名不当Q因为它只删?RTL_CRITICAL_SECTION_ DEBUGQ的调用遍历一个同样可理解的\径。如果由于线E在试获得临界区时被阻止而创Z(jin)一个事Ӟ通过调用 ZwClose 来销毁该事g。接下来Q在通过 RtlCriticalSectionLock 获得保护之后QNTDLL 以一个(f)界区保护它自q内部临界区列??(zhn)猜对了(jin)Q,调试信息从链中清除Q对该(f)界区链表q行更新Q以反映对该信息的清除操作。该内存q值填充,q且如果其存储区是由q程堆中获得Q则调用 RtlFreeHeap 得其内存被释放。最后,以零填充 RTL_CRITICAL_SECTION? <p>有两?API 要获得受临界Z护的资源 ?TryEnterCriticalSection ?EnterCriticalSection。如果一个线E需要进入一个(f)界区Q但在等待被L资源变(sh)ؓ(f)可用的同Ӟ可执行有用的工作Q那?TryEnterCriticalSection 正是(zhn)需要的 API。此例程试此(f)界区是否可用Q如果该临界占用Q该代码返回?FALSEQؓ(f)该线E提供l执行另一d的机?x)。否则,其作用只是相当于 EnterCriticalSection? <p>如果该线E在l箋(hu)q行之前实需要拥有该资源Q则使用 EnterCriticalSection。此Ӟ取消用于多处理器计算机的 SpinCount 试。这一例程?TryEnterCriticalSection cMQ无临界区是I闲的或已经被该U程所拥有Q都调整对该临界区的记。注意,最重要?LockCount 递增是由 x86“lock”前~完成的,q一炚w帔R要。这保?jin)在某一旉内只有一?CPU 可以修改?LockCount 字段。(事实上,W(xu)in32 InterlockedIncrement API 只是一个具有相同锁定前~?ADD 指o(h)。)(j) <p>如果调用U程无法立即获得该(f)界区Q则调用 RtlpWaitForCriticalSection 该U程|于{待状态。在多处理器pȝ中,EnterCriticalSection 旋{ SpinCount 所指定的次敎ͼq在每次循环讉K中测试该临界区的可用性。如果此临界区在循环期间变(sh)ؓ(f)I闲Q该U程获得该(f)界区Qƈl箋(hu)执行? <p>RtlpWaitForCriticalSection 可能是这里所l的所有过E中最为复杂、最为重要的一个。这q不值得大惊怪,因ؓ(f)如果存在一个死锁ƈ涉及(qing)临界区,则利用调试器q入该进E就可能昄?RtlpWaitForCriticalSection ?ZwWaitForSingleObject 调用中的臛_一个线E? <p>如伪码中所昄Q在 RtlpWaitForCriticalSection 中有一点簿记工作,如递增 EntryCount ?ContentionCount 字段。但更重要的是:(x)发出?LockSemaphore 的等待,以及(qing)对等待结果的处理。默认情冉|一个空指针作ؓ(f)W三个参C递给 ZwWaitForSingleObject 调用Q请求该{待永远不要时。如果允许超Ӟ生成调试消息字W串Qƈ再次开始等待。如果不能从{待中成功返回,׃(x)产生中止该进E的错误。最后,在从 ZwWaitForSingleObject 调用中成功返回时Q则执行?RtlpWaitForCriticalSection q回Q该U程现在拥有该(f)界区? <p>RtlpWaitForCriticalSection 必须认识到的一个(f)界条件是该进E正在被关闭Qƈ且正在等待加载程序锁?(LdrpLoaderLock) 临界区。RtlpWaitForCriticalSection 一?em>不能</em> 允许该线E被LQ但是必蟩q该{待Qƈ允许l箋(hu)q行关闭操作? <p>LeaveCriticalSection 不像 EnterCriticalSection 那样复杂。如果在递减 RecursionCount 之后Q结果不?0Q意味着该线E仍然拥有该临界区)(j)Q则该例E将?ERROR_SUCCESS 状态返回。这是Z么需要用适当数目?Leave 调用来^?Enter 调用。如果该计数?0Q则 OwningThread 字段被清ӞLockCount 被递减。如果还有其他线E在{待Q例?LockCount 大于或等?0Q则调用 RtlpUnWaitCriticalSection。此帮助器例E创?LockSemaphoreQ如果其未存在Q,q发?gu)信号提醒操作pȝQ该U程已经释放该(f)界区。作为通知的一部分Q等待线E之一退出等待状态,行做好准备? <p>最后要说明的一Ҏ(gu)QMyCriticalSections E序如何定临界区链的v始呢Q如果有权访?NTDLL 的正调试符P则对该列表的查找和遍历非常简单。首先,定位W号 RtlCriticalSectionListQ清I其内容Q它指向W一?RTL_CRITICAL_SECTION_DEBUG l构Q,q开始遍历。但是,q不是所有的pȝ都有调试W号QRtlCriticalSectionList 变量的地址?x)?Windows 的各个版本而发生变化。ؓ(f)?jin)提供一U对所有版本都能正常工作的解决Ҏ(gu)Q我们设计了(jin)以下试探性方案。观察启动一个进E时所采取的步骤,?x)看到是以以下顺序?NTDLL 中的临界行初始化的(q些名称取自 NTDLL 的调试符P(j)Q?<pre>RtlCriticalSectionLock DeferedCriticalSection (this is the actual spelling!) LoaderLock FastPebLock RtlpCalloutEntryLock PMCritSect UMLogCritSect RtlpProcessHeapsListLock </pre> <p>因ؓ(f)(g)查进E环境块 (PEB) 中偏U量 0xA0 处的地址可以找到加载程序锁Q所以对该链起始位置的定位就变得比较单。我们读取有兛_载程序锁的调试信息,然后沿着铑֐后遍历两个链接,使我们定位于 RtlCriticalSectionLock ,在该点得到该铄W一个(f)界区。有兛_Ҏ(gu)的说明,请参?strong>?4</strong>? <p><img height="284" alt="fig04" src="http://www.microsoft.com/china/MSDN/library/enterprisedevelopment/softwaredev/art/Deadlockfig04.gif" width="325" border="0"> <p><strong>?4 初始化顺?/strong> <p>结 <p>几乎所有的多线E程序均使用临界区。?zhn)q早都会(x)遇到一个代码死锁的(f)界区Qƈ且会(x)难以定是如何进入当前状态的。如果能够更深入C(jin)解(f)界区的工作原理,则这一情Ş的出现就不会(x)像首ơ出现时那样的o(h)人沮丧。?zhn)可以研究一个看来非常含p的临界区,q确定是谁拥有它Q以?qing)其他有用细节。如果?zhn)愿意我们的库加入(zhn)的链接器行,则可以容易地获得有关?zhn)程序(f)界区使用的大量信息。通过利用临界区结构中的一些未用字D,我们的代码可以仅隔离q命名?zhn)的模块所用的临界区,q告知其准确状态? <p>有魄力的读者可以很Ҏ(gu)地对我们的代码进行扩展,以完成更为异乎寻常的工作。例如,采用?InitializeCriticalSection 挂钩相类似的方式截获 EnterCriticalSection ?LeaveCriticalSectionQ可以存储最后一ơ成功获得和释放该(f)界区的位|。与此类|CritSect DLL 拥有一个易于调用的 APIQ用于枚举?zhn)自己的代码中的?f)界区。利?.NET Framework 中的 Windows H体Q可以相对容易地创徏一?GUI 版本?MyCriticalSections。对我们代码q行扩展的可能性非常大Q我们非怹意看到其他h员所发现和创造的创新性办法? <p><strong>有关文章Q请参阅Q?/strong><br><a >Global Flag Reference:Create kernel mode stack trace database</a><br><a >GFlags Examples:Enlarging the User-Mode Stack Trace Database</a><br><a >Under the Hood:Reduce EXE and DLL Size with LIBCTINY.LIB</a> <p><strong>Matt Pietrek</strong> 是一位Y件架构师和作者。他p?Compuware/NuMega 实验室,w䆾?BoundsChecker 和“分布式分析器”品的首席架构师。他已经创作?jin)三本有?Windows pȝ~程的书c,q是 <em>MSDN Magazine</em> 的特U编辑。他?Web 站点 (<a >http://www.wheaty.net</a>) 有关于以前文章和专栏?FAQ 和信息? <p><strong>Jay Hilyard</strong> ?Compuware/NuMega 实验室的 BoundsChecker 组的Y件工E师。他、他的妻子和他们的猫是新|布什?dng)州的新居民。他的联pL式ؓ(f) <a href="mailto:RussOsterlund@adelphia.net">RussOsterlund@adelphia.net</a> ?Web 站点 <a >http://www.smidgeonsoft.com</a>? <p><a >转到原英文页?/a><img src ="http://www.shnenglu.com/jans2002/aggbug/74367.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/jans2002/" target="_blank">jans2002</a> 2009-02-20 10:03 <a href="http://www.shnenglu.com/jans2002/archive/2009/02/20/74367.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何Ҏ(gu)E序崩溃时的DMP文g使用WinDbg查找调用堆栈http://www.shnenglu.com/jans2002/archive/2009/01/08/71500.htmljans2002jans2002Thu, 08 Jan 2009 07:53:00 GMThttp://www.shnenglu.com/jans2002/archive/2009/01/08/71500.htmlhttp://www.shnenglu.com/jans2002/comments/71500.htmlhttp://www.shnenglu.com/jans2002/archive/2009/01/08/71500.html#Feedback0http://www.shnenglu.com/jans2002/comments/commentRss/71500.htmlhttp://www.shnenglu.com/jans2002/services/trackbacks/71500.html 

HOW TOQ?查找问题的异常堆栈时出现?UnhandledExceptionFilter 调用堆栈跟踪?/h3>

http://support.microsoft.com/kb/313109/zh-cn

察看本文应用于的产品

本页

展开全部 | 关闭全部

概要

没有异常处理E序定义处理引发的异常时Q将调用?UnhandledExceptionFilter 函数?通常Q该函数?x)将异常传递给?Ntdll.dll 为文...

没有异常处理E序定义处理引发的异常时Q将调用?UnhandledExceptionFilter 函数?通常Q该函数?x)将异常传递给?Ntdll.dll 为文件其中捕Pq尝试处理设|?
在进E的内存快照所在某些情况下Q可以看到锁定点保存到线E的U程的调?UnhandledExceptionFilter 函数?在这的种情况下?zhn)可以按照本文以确定导致此异常?DLL?

回到端

使用 Windbg.exe 打开转储文g
  1. 下蝲q安装调试程序?要下载调试程序,误问下面的 Microsoft |站Q?

    Microsoft 调试工具
    http://www.microsoft.com/whdc/devtools/ddk/default.mspx (http://www.microsoft.com/whdc/devtools/ddk/default.mspx)

  2. 打开安装调试E序Q文件夹Q然后双?Windbg.exe 启动调试器?
  3. ?文g 菜单上单?打开的崩溃{?Q或?Ctrl+DQ,然后选择要查看该转储文g?/li>

回到端

使用 Windbg.exe 定异常堆栈
  1. ?Windbg.exeQ打开q程?dmp 文g?
  2. L(fng)保?zhn)W号路径指向正确的位|?有关如何执行此操作,误问下面的 Microsoft Web 站点Q?

    如何获得W号
    http://www.microsoft.com/whdc/devtools/ddk/default.mspx (http://www.microsoft.com/whdc/devtools/ddk/default.mspx)

  3. 在命令提C符下键?~ * kb 以列出所有进E中的线E?
  4. 标识对函数调用的U程 Kernel32! UnhandledExceptionFilter ?它类g以下Q?

    120  id: f0f0f0f0.a1c   Suspend: 1 Teb 7ff72000 Unfrozen
    ChildEBP RetAddr  Args to Child              
    09a8f334 77eb9b46 0000244c 00000001 00000000 ntdll!ZwWaitForSingleObject+0xb [i386\usrstubs.asm @ 2004]
    09a8f644 77ea7e7a 09a8f66c 77e861ae 09a8f674 KERNEL32!UnhandledExceptionFilter+0x2b5 
    [D:\nt\private\windows\base\client\thread.c @ 1753]
    09a8ffec 00000000 787bf0b8 0216fe94 00000000 KERNEL32!BaseThreadStart+0x65 [D:\nt\private\windows\base\client\support.c @ 453]
    					
  5. 切换到该U程 Q在本例中,该线E是"~120s"Q?
  6. 在第一个参数的指定位置昄内存内容 Kernel32! UnhandledExceptionFilter 通过 d W一个参??此指?EXCEPTION_POINTERS l构

    0:120> dd 09a8f66c 
    09a8f66c  09a8f738 09a8f754 09a8f698 77f8f45c 
    09a8f67c  09a8f738 09a8ffdc 09a8f754 09a8f710 
    09a8f68c  09a8ffdc 77f8f5b5 09a8ffdc 09a8f720 
    09a8f69c  77f8f3fa 09a8f738 09a8ffdc 09a8f754 
    09a8f6ac  09a8f710 77e8615b 09a8fad4 00000000 
    09a8f6bc  09a8f738 74a25336 09a8f6e0 09a8f910 
    09a8f6cc  01dc8ad8 0d788918 00000001 018d1f28 
    09a8f6dc  00000001 61746164 7073612e 09a8f71c 
    					
  7. W一?DWORD 代表异常记录?若要获取有关异常的类型信息,误在命令提C符处运行以下:(x)

    .exr first DWORD from step 6

    0:120> .exr 09a8f738 
    ExceptionAddress: 78011f32 (MSVCRT!strnicmp+0x00000092)
       ExceptionCode: c0000005 
      ExceptionFlags: 00000000 
    NumberParameters: 2 
       Parameter[0]: 00000000 
       Parameter[1]: 00000000 
    Attempt to read from address 00000000 
    					
  8. W二?DWORD 是上下文记录?若要获取上下文的信息Q请在命令提C符处运行以下:(x)

    .cxr second DWORD from step 6

    0:120> .cxr 09a8f754 
    eax=027470ff ebx=7803cb28 ecx=00000000 edx=00000000 esi=00000000 edi=09a8fad4 
    eip=78011f32 esp=09a8fa20 ebp=09a8fa2c iopl=0         nv up ei ng nz na po nc 
    cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010286 
    MSVCRT!strnicmp+92: 
    78011f32 8a06             mov     al,[esi] 
    					
  9. q行 kv 命o(h)获得实际的异常的调用堆栈?q有助于(zhn)识别可能未被处理正的q程中实际问?

    0:120> kv
    ChildEBP RetAddr  Args to Child            
    WARNING: Stack unwind information not available. Following frames may be wrong.
    09a8fa2c 780119ab 09a8fad4 00000000 09a8faa8 MSVCRT!strnicmp+0x92
    09a8fa40 7801197c 09a8fad4 00000000 6d7044fd MSVCRT!stricmp+0x3c
    09a8fa80 6e5a6ef6 09a8fad4 2193d68d 00e5e298 MSVCRT!stricmp+0xd
    09a8fa94 6d7043bf 09a8fad4 09a8faa8 0000001c IisRTL!CLKRHashTable::FindKey+0x59 (FPO: [2,0,1])
    09a8faac 749fc22d 09a8fad4 01d553b0 0000001c ISATQ!CDirMonitor::FindEntry+0x1e 
    (FPO: [Non-Fpo]) [D:\nt\private\inet\iis\svcs\infocomm\atq\dirmon.cpp @ 884]
    09a8fac4 749fd1cb 09a8fad4 09a8fb10 525c3a46 asp!RegisterASPDirMonitorEntry+0x6e 
    (FPO: [EBP 0x09a8fb08] [2,0,4]) [D:\nt\private\inet\iis\svcs\cmp\asp\aspdmon.cpp @ 534]
    09a8fb08 749fcdd6 00000000 09a8fcbc 018d1f28 asp!CTemplateCacheManager::RegisterTemplateForChangeNotification+0x8a 
    (FPO: [Non-Fpo]) [D:\nt\private\inet\iis\svcs\cmp\asp\cachemgr.cpp @ 621]
    09a8fb3c 74a08bfe 00000000 000000fa 74a30958 asp!CTemplateCacheManager::Load+0x382 
    (FPO: [Non-Fpo]) [D:\nt\private\inet\iis\svcs\cmp\asp\cachemgr.cpp @ 364]
    09a8fc68 74a0d4c9 04c12518 018d1f28 09a8fcbc asp!LoadTemplate+0x42 
    (FPO: [Non-Fpo]) [D:\nt\private\inet\iis\svcs\cmp\asp\exec.cpp @ 1037]
    09a8fcc0 74a2c3e5 00000000 0637ee38 09a8fd58 asp!CHitObj::ViperAsyncCallback+0x3e8 
    (FPO: [Non-Fpo]) [D:\nt\private\inet\iis\svcs\cmp\asp\hitobj.cpp @ 2414]
    09a8fcd8 787c048a 00000000 77aa1b03 01e91ed8 asp!CViperAsyncRequest::OnCall+0x3f 
    (FPO: [Non-Fpo]) [D:\nt\private\inet\iis\svcs\cmp\asp\viperint.cpp @ 194]
    09a8fce0 77aa1b03 01e91ed8 77a536d8 00000000 COMSVCS!STAActivityWorkHelper+0xa 
    (FPO: [1,0,0])
    09a8fd24 77aa1927 000752f8 000864dc 787c0480 ole32!EnterForCallback+0x6a 
    (FPO: [Non-Fpo]) [D:\nt\private\ole32\com\dcomrem\crossctx.cxx @ 1759]
    09a8fe50 77aa17ea 000864dc 787c0480 01e91ed8 ole32!SwitchForCallback+0x12b 
    (FPO: [Non-Fpo]) [D:\nt\private\ole32\com\dcomrem\crossctx.cxx @ 1644]
    09a8fe78 77aa60c1 000864dc 787c0480 01e91ed8 ole32!PerformCallback+0x50
    (FPO: [Non-Fpo]) [D:\nt\private\ole32\com\dcomrem\crossctx.cxx @ 1559]
    09a8fed4 77aa5fa6 04f2b4c0 787c0480 01e91ed8 ole32!CObjectContext::InternalContextCallback+0xf5 
    (FPO: [Non-Fpo]) [D:\nt\private\ole32\com\dcomrem\context.cxx @ 3866]
    09a8fef4 787bd3c3 04f2b4c0 787c0480 01e91ed8 ole32!CObjectContext::DoCallback+0x1a 
    (FPO: [Non-Fpo]) [D:\nt\private\ole32\com\dcomrem\context.cxx @ 3746]
    09a8ff24 787bf373 0216fb3c 00000007 09a8ffec COMSVCS!STAActivityWork::DoWork+0x73 
    (FPO: [0,4,2])
    09a8ffb4 77e8758a 0216fe94 0216fb3c 00000007 COMSVCS!STAThread::STAThreadWorker+0x2bb 
    (FPO: [EBP 0x09a8ffec] [1,31,4])
    09a8ffec 00000000 787bf0b8 0216fe94 00000000 KERNEL32!BaseThreadStart+0x52 
    (FPO: [Non-Fpo]) [D:\nt\private\windows\base\client\support.c @ 451]
    					


jans2002 2009-01-08 15:53 发表评论
]]>
~译boost 1.37遇到的问?/title><link>http://www.shnenglu.com/jans2002/archive/2008/12/25/70299.html</link><dc:creator>jans2002</dc:creator><author>jans2002</author><pubDate>Thu, 25 Dec 2008 02:08:00 GMT</pubDate><guid>http://www.shnenglu.com/jans2002/archive/2008/12/25/70299.html</guid><wfw:comment>http://www.shnenglu.com/jans2002/comments/70299.html</wfw:comment><comments>http://www.shnenglu.com/jans2002/archive/2008/12/25/70299.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.shnenglu.com/jans2002/comments/commentRss/70299.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/jans2002/services/trackbacks/70299.html</trackback:ping><description><![CDATA[<p>虽然|上关于boost~译问题的文章一堆一堆的Q但是到我用的时候怎么׃行呢Q我的编译器是vc7.1Q本来不想用boostQ只是ؓ(f)?jin)编译asio的例子,引用?/p> <p>#include <boost/date_time/posix_time/posix_time.hpp></p> <p>q个头文Ӟ招来了(jin)一堆的问题</p> <p>提示链接错误Q?/p> <p>文glibboost_date_time-vc71-mt-sgd-1_37.lib找不?/p> <p>然后开始了(jin)漫长的boost库编译?/p> <p>但是~译完了(jin)Q提C是找不到Q我晕。查?jin)查sgd的意?/p> <p>s:代表static</p> <p>gd:代表调试?/p> <p><a >|上的说?/a>我照着做了(jin)Q根本就不行Q不知道是笔误呢Q还是bjam版本已经更新?jin)。只好根据错误提C,在boost的Jam文g中来揣测~译开?/p> <p>在X:\boost_1_37_0\tools\build\v2\build目录中的build-request.jam文g?48行有</p> <p>feature toolset : gcc msvc borland : implicit ;{内?/p> <p>哦,q个大概是~译开关了(jin)</p> <p>下面是编译出?rn)态链接的release版本</p> <p>bjam toolset=msvc-7.1   runtime-link=static stage </p> <p>下面是编译出?rn)态链接的debug版本</p> <p>bjam toolset=msvc-7.1   debug runtime-link=static stage </p> <p>q个stage开兛_Q可能就是把~译出来的文件复制到目录</p> <p>X:\boost_1_37_0\stage\lib </p> <p>其它的开?/p> <p>rtti:on off</p> <p>optimization: on off</p> <p>{等Q?/p><img src ="http://www.shnenglu.com/jans2002/aggbug/70299.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/jans2002/" target="_blank">jans2002</a> 2008-12-25 10:08 <a href="http://www.shnenglu.com/jans2002/archive/2008/12/25/70299.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>复合H口的ActiveX控g全屏?qing)键盘消息处理问?/title><link>http://www.shnenglu.com/jans2002/archive/2008/12/18/69714.html</link><dc:creator>jans2002</dc:creator><author>jans2002</author><pubDate>Thu, 18 Dec 2008 02:29:00 GMT</pubDate><guid>http://www.shnenglu.com/jans2002/archive/2008/12/18/69714.html</guid><wfw:comment>http://www.shnenglu.com/jans2002/comments/69714.html</wfw:comment><comments>http://www.shnenglu.com/jans2002/archive/2008/12/18/69714.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.shnenglu.com/jans2002/comments/commentRss/69714.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/jans2002/services/trackbacks/69714.html</trackback:ping><description><![CDATA[<p>最q在开发一个ActiveX视频控gQ需要有全屏功能Q因为用到好几层H口Q在全屏的时候费?jin)很多周折,最后瞎凑ȝ凑好?jin),写下来与大家׃n?/p> <p>让应用程序全屏显C其实思\很简单:(x)</p> <p>1.先保存要全屏的窗口的父窗?/p> <p>2.如果要全屏的H口不是子窗口,讄光gؓ(f)WS_CHILD</p> <p>3.讄H口的父H口为桌?::GetDesktopWindow())</p> <p>4.UdH口臛_屏,q将H口设ؓ(f)d最上HWND_TOPMOST</p> <p> </p> <p>m_videoMgr是我控g里创建的视频H口Q它的父H口是控件窗?CameraControl)控g本n的窗口不直接昄Q被q个m_videoMgrH口完全覆盖。在全屏的时候,如果直接更改CameraControl的父H口Q它的子H口m_videoMgrH口L不能正确的设|ؓ(f)全屏Q可能在控g试容器里正常,但是C(jin)IE里就不正怺(jin)。于是我改ؓ(f)更改m_videoMgrH口的父H口Q保留控件本w窗口,但是改变H口大小的时候,改变父窗口的大小Q也许m_videoMgrH口可能和控件本w窗口的大小有关联,q样成功的进行了(jin)全屏Q而且不管是在IE和控件测试容器里都可以正常的全屏和恢复?/p> <p> </p><pre> <span style="color: #0000ff">if</span>(bFullScreen) { <span style="color: #008000">//获取控gH口的绝对位|?/span></pre><pre><span style="color: #008000"> </span>GetWindowRect(m_rcCtrlRect); ::SetParent(m_videoMgr.GetSafeHwnd(),::GetDesktopWindow()); <span style="color: #0000ff">int</span> cx = ::GetSystemMetrics(SM_CXSCREEN); <span style="color: #0000ff">int</span> cy = ::GetSystemMetrics(SM_CYSCREEN); MoveWindow(0, 0, cx, cy); ::SetWindowPos(m_videoMgr.GetSafeHwnd(),HWND_TOPMOST,0,0,cx,cy,SWP_FRAMECHANGED|SWP_DEFERERASE); m_bFullScreen = TRUE; } <span style="color: #0000ff">else</span> { ::SetParent(m_videoMgr.GetSafeHwnd(),m_hWnd); </pre><pre> <span style="color: #008000">//MoveWindow使用相对H口坐标Q所以必d转化为相对坐?/span></pre><pre><span style="color: #008000"></span> CPoint LeftTop(m_rcCtrlRect.TopLeft()); CPoint BottomRight(m_rcCtrlRect.BottomRight()); ::ScreenToClient(m_hWnd,&LeftTop); ::ScreenToClient(m_hWnd,&BottomRight); ::MoveWindow(m_hWnd,LeftTop.x,LeftTop.y,m_rcCtrlRect.Width(),m_rcCtrlRect.Height(),TRUE); ::SetWindowPos(m_videoMgr.GetSafeHwnd(),HWND_NOTOPMOST,0,0,0,0,SWP_NOMOVE|SWP_NOSIZE); m_bFullScreen = FALSE; } </pre> <p>解决?jin)上面的问题(sh)后Q又发现?jin)一个新的问题,是全屏以后想用Esc键退出全屏时Q根本不响应键盘消息Q后来发现MFC也有控g不处理键盘消息的问题Q想惛_能跟控g的焦Ҏ(gu)关系Q于是在FullScreen的之前,加一个SetFocus()</p><pre> <span style="color: #0000ff">if</span>(FullScreen&&!IsFullScreen()) { SetFocus(); OnFullScreen(TRUE); }</pre><pre>然后发现键盘消息处理正常?jin),问题解决?/pre><pre> </pre><img src ="http://www.shnenglu.com/jans2002/aggbug/69714.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/jans2002/" target="_blank">jans2002</a> 2008-12-18 10:29 <a href="http://www.shnenglu.com/jans2002/archive/2008/12/18/69714.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss> <footer> <div class="friendship-link"> <p>лǵվܻԴȤ</p> <a href="http://www.shnenglu.com/" title="精品视频久久久久">精品视频久久久久</a> <div class="friend-links"> </div> </div> </footer> <a href="http://www.lntyzx.com.cn" target="_blank">þҹۺϾþ</a>| <a href="http://www.uuu9com.cn" target="_blank">Ӱһþþþó˾Ʒۺ</a>| <a href="http://www.idqs.cn" target="_blank">þþþùƷ</a>| <a href="http://www.myjhy.cn" target="_blank">ձþĻ</a>| <a href="http://www.vz82.cn" target="_blank">޾ƷҹVAþó</a>| <a href="http://www.hfpump.com.cn" target="_blank">þþƷAV㽶</a>| <a href="http://www.122797929.cn" target="_blank">þùѾƷ</a>| <a href="http://www.78cbg.cn" target="_blank">99þùۺϾƷӰԺ</a>| <a href="http://www.wushuichulisb.cn" target="_blank">99þۺϺݺۺϾþ</a>| <a href="http://www.cnpump.com.cn" target="_blank">޹˾Ʒþþùһ </a>| <a href="http://www.debtee.cn" target="_blank">þþҹƷ</a>| <a href="http://www.2pt.com.cn" target="_blank">þþþAVվ</a>| <a href="http://www.ktqcc.cn" target="_blank">Ʒvaþþþþþ</a>| <a href="http://www.e-ben.cn" target="_blank">18պҹþó</a>| <a href="http://www.waterbirds.cn" target="_blank">Ʒѿþþ</a>| <a href="http://www.gongyeyongbu.com.cn" target="_blank">ۺۺϾþ69</a>| <a href="http://www.dg-rx.cn" target="_blank">þֻоƷ18</a>| <a href="http://www.jlxrc.cn" target="_blank">þùƷһ</a>| <a href="http://www.uyqr.cn" target="_blank">þþƷ</a>| <a href="http://www.zjhongfeng.cn" target="_blank">˾þô߽Ʒ</a>| <a href="http://www.yunva.cn" target="_blank">ۺϾƷ㽶þ</a>| <a href="http://www.szbomeidisplays.cn" target="_blank">޹ƷȾþ</a>| <a href="http://www.swd5.cn" target="_blank">ɫۺϾþ</a>| <a href="http://www.fd-tex.cn" target="_blank">AƷһþ </a>| <a href="http://www.kxtravel.com.cn" target="_blank">ŷ˾þƬ</a>| <a href="http://www.lianliankan123.cn" target="_blank">þþþۺĻ</a>| <a href="http://www.gitscm.com.cn" target="_blank">99þþƷձһ</a>| <a href="http://www.gx263.cn" target="_blank">þֻǾƷ66</a>| <a href="http://www.dztsc.cn" target="_blank">ݺ޾þþþþۺ</a>| <a href="http://www.caribbeanlagoon.com.cn " target="_blank">þۺɫˮ99ž </a>| <a href="http://www.6922215.cn" target="_blank">ŷƷþø</a>| <a href="http://www.zesf.com.cn" target="_blank">ƷþòҰ</a>| <a href="http://www.unnk.cn" target="_blank">þAV뾫Ʒɫҹ </a>| <a href="http://www.hlpswa.cn" target="_blank">ŷ޾ƷþþavӰ</a>| <a href="http://www.the-music-cable.cn" target="_blank">þ99ƷþþþþҰ</a>| <a href="http://www.b42k.cn" target="_blank">99þù¶Ʒ</a>| <a href="http://www.gybyz.cn" target="_blank">þþþþþþƷŮ99 </a>| <a href="http://www.fangongdi.cn" target="_blank">avþþþþòվ </a>| <a href="http://www.donglianggc.cn" target="_blank">þþƷŷպ99</a>| <a href="http://www.369live.cn" target="_blank">Ʒþþþþù</a>| <a href="http://www.qdjybj.cn" target="_blank">Ʒ޾þþþþ888</a>| <script> (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })(); </script> </body>