__cdecl calling convention

int fun(int a, int b) { return a + b; } // 在VC++ project properties中默认设置为__cdecl调用规范

int _tmain(int argc, _TCHAR* argv[]) { fun(0x8899, 0x1100); return 0;}产生的汇编代码如下:
00411A3E  push        1100h
00411A43  push        8899h
00411A48  call        fun (4112F3h)
00411A4D  add         esp,8

前面两个push是参数压栈,由于__cdecl是倒续压栈,所以先进栈的是1100h。然后是call指令。call指令在调用fun函数时,会保存下一条指令的地址,即,00411A4D,改指令是在释放fun函数调用结束后的栈,记得__cdecl规范是由调用者来释放栈的。这时的栈结构内容如下:

0x0012FE6C  48 ff 12 00  | 4d 1a 41 00  H…M.A.
0x0012FE74  99 88 00 00 | 00 11 00 00  ??…… // 参数在栈上的内存结构

0012ff48是fun函数开始时所压入的栈帧 (stack frame pointer),它右边的那个就是返回地址,同样是保存在栈上。

fun 4112F3h并不是函数fun的真正地址,是增量连接中的一个表项:004112F3  jmp         fun (411980h)

fun函数中,a加b的返回结构将会被存放在eax中返回:
0041199E  mov         eax,dword ptr [a]
004119A1  add         eax,dword ptr [b]

OK。就分析这么多。看清事物本质,刨根问底其实也是一件很令人愉悦的事情。其实按部就班的话,还是挺简单的。另,MC3快Feature Complete了,接踵而至的就是大量的CER bucket。以上所述的皮毛,也算是踏入Crash Dump Analysis的最低门槛了。要学的东西还是很多的!!Software Developer本身就是一个工作中学习,学习中工作的工作啊(很明显是废话|||)。

The truth under a simple function definition

[Note: Make sure your compiler is configured with debug mode. Otherwise, you will not get the right result described as below, in that some optimizations emitted by VC++ compiler in release mode. Shutdown Enable Incremental Linking switch, which will make a table list for the function called. It will set the address of the entry in this table instead of the real address.]

1. Try to define a simple function as following, with empty execute body definition:

void bar() { }

Press F5 and step into the function body, disassembly it and try to fetch the accordant asm code.

00411950  push        ebp  // Save current frame pointer on stack.
00411951  mov         ebp,esp  //Activate the new frame for callee.
00411953  sub         esp,0C0h  // 0C0h (192) Set ESP at the end of the frame.
00411959  push        ebx 
0041195A  push        esi 
0041195B  push        edi 
// The above three assembly code is used to save current register.
0041195C  lea         edi,[ebp-0C0h]  // edi is now pointing to the end of the stack frame.
00411962  mov         ecx,30h  // 30h = 0C0h/4, ‘rep stos’ will be executed 48 times.
00411967  mov         eax,0CCCCCCCCh  // Set parameter of ‘rep stos’ instrument.
0041196C  rep stos    dword ptr es:[edi]  // Use the value of eax (0CCCCCCCCh) to initialize stack.
0041196E  pop         edi 
0041196F  pop         esi 
00411970  pop         ebx 
// The above three assembly code is used to restore the register.
00411971  mov         esp,ebp
00411973  pop         ebp  // Activate caller’s stack frame.
00411974  ret       // Return to the caller.

2. Try to define a simple function as following, with a try/catch block in its execute body:

void foo(){
    try { }
    catch ( … ) { }
}

00411890  push        ebp 
00411891  mov         ebp,esp  // Activate the new frame for callee.
00411893  push        0FFFFFFFFh // id, member of EXCEPTION_REGISTRATION.
00411895  push        offset __ehhandler$?foo@@YAXXZ (415D60h)  // Address of exception handler.
0041189A  mov         eax,dword ptr fs:[00000000h]  // FS:[0] stores the current exception handler.
004118A0  push        eax  // Save the previous exception handler in the chain.
004118A1  mov         dword ptr fs:[0],esp  // Register the EXCEPTION_REGISTRATION with OS.
004118A8  push        ecx 
004118A9  sub         esp,0C0h
004118AF  push        ebx 
004118B0  push        esi 
004118B1  push        edi 
004118B2  lea         edi,[ebp-0D0h]
004118B8  mov         ecx,30h
004118BD  mov         eax,0CCCCCCCCh
004118C2  rep stos    dword ptr es:[edi]
004118C4  mov         dword ptr [ebp-10h],esp
004118C7  mov         dword ptr [ebp-4],0
004118CE  jmp         __catch$?foo@@YAXXZ$0+0Dh (4118DDh)
004118D0  mov         dword ptr [ebp-4],0FFFFFFFFh
004118D7  mov         eax,offset $LN2 (4118E4h)
004118DC  ret             
004118DD  mov         dword ptr [ebp-4],0FFFFFFFFh
004118E4  mov         ecx,dword ptr [ebp-0Ch]
004118E7  mov         dword ptr fs:[0],ecx
004118EE  pop         edi 
004118EF  pop         esi 
004118F0  pop         ebx 
004118F1  mov         esp,ebp
004118F3  pop         ebp 
004118F4  ret
 

VC++ creates EXCEPTION_REGISTRATION structure for every function as its local variable. Function’s prologue creates this structure on its stack frame and register it with operating system.

What is __ehhandler$?foo@@YAXXZ (415D60h)?

Since it’s not readable, let’s unmangling it with UnDecorateSymbolName API provided by Dbghelp.dll:

?foo@@YAXXZ  to void __cdecl foo(void). The dollar ‘$’ here is just used to join __ehhanlder with foo.

So, we can get a conclusion that, __ehhandler$?foo@@YAXXZ is the exception handler generated automatically by VC++ compiler. As the same, you can find a catch handler __catch$?foo@@YAXXZ in the following assembly.

Then you will see what we are already familiar with. Compare it with the following code, you will got it:

_asm {
move EAX, FS : [0]
move prev, EAX }

What is the usage of __ehhandler$?foo@@YAXXZ (415D60h)?

415D60h here is the offset, where __ehhandler$?foo@@YAXXZ is located. Navigate to this address:

00415D60  mov         eax,offset ___rtc_tzz+13Ch (418F24h)
00415D65  jmp         @ILT+595(___CxxFrameHandler3) (411258h)

Obviously, this function just pass a parameter to another function ___CxxFrameHandler3.

What is ___CxxFrameHandler3?

It just inspects the EXCEPTION_REGISTRATION on the stack to see if there is any catch block in the function interested in catching the current exception. If it does not find any, it returns ExceptionContinueSearch value back to the operating system.

Hope this can help.

Native Image Cache

Where is Native Image Cache?

The question above nearly drove me crazy recently. Whenever compiling the managed code with ngen.exe (Native Image Generator), I will usually be confused with where the output of the compiler is stored.

According to the MSDN, it says Native Image Cache is a special area in GAC (Global Assembly Cache). But, I’m sure you can not find it when using explorer and navigating to the C:\Windows\Assembly. Yes, of course. It’s invisible within the shell explorer.

One day, I just activated my imagination and do ‘dir’ operation under the path above in the command line. Then, I found something interesting as following (My Operating System is Windows Vista Ultimate):

2007/09/22  17:47    <DIR>          GAC
2007/03/26  00:45    <DIR>          GAC_32
2007/10/16  01:28    <DIR>          GAC_MSIL
2007/09/12  23:05    <DIR>          NativeImages_v2.0.50727_32
2007/08/26  11:09    <DIR>          temp
2007/10/16  01:28    <DIR>          tmp
               0 File(s)              0 bytes
               6 Dir(s)  17,008,558,080 bytes free

Well, NativeImages_v2.0.50727_32 is that one I have been looking for. You can browse the folder with another pair of cd and dir command, and eventually get what you want —- Native Image. All of Them are orgnized with its display name. For example WindowsBase, its native one is usually WindowsBase.ni.dll (ni, Native Image).

Directory of C:\Windows\assembly\NativeImages_v2.0.50727_32\WindowsBase

2006/11/02  20:54    <DIR>          .
2006/11/02  20:54    <DIR>          ..
2006/11/02  20:54    <DIR>          3b53dcf335a24dff03c7354dfebcb049
               0 File(s)              0 bytes
               3 Dir(s)  17,008,361,472 bytes free

C:\Windows\assembly\NativeImages_v2.0.50727_32\WindowsBase>cd 3b53dcf335a24dff03
c7354dfebcb049

C:\Windows\assembly\NativeImages_v2.0.50727_32\WindowsBase\3b53dcf335a24dff03c73
54dfebcb049>dir
Volume in drive C has no label.
Volume Serial Number is 5A7C-2712

Directory of C:\Windows\assembly\NativeImages_v2.0.50727_32\WindowsBase\3b53dcf
335a24dff03c7354dfebcb049

2006/11/02  20:54    <DIR>          .
2006/11/02  20:54    <DIR>          ..
2006/11/02  20:54         3,272,704 WindowsBase.ni.dll
               1 File(s)      3,272,704 bytes
               2 Dir(s)  17,008,361,472 bytes free

Summary of the recenly studying on UAC

Recently, I buried myself with some new features coming with Windows Vista. Particularly, with User Account Control (UAC), since I firmly believe in that it’s that root cause of our P1 defect MC3 Machine and User GUID resetting. Significantly, it’s also the right start point for us to migrate our programming to this new operating system.
 
The following link gives us an overview of the most famous features introduced in Vista:
Windows Vista: Kernel Changes – Has anybody seen Gina and what’s a UAC?
 
I just want to point out something important here.
First, what is GINA? A Graphical Identification and Authentication dynamic-link library (DLL), which is going to be replaced with Credential Providers. (MSDN)
Second, keep it in mind, whenever you logon the system with administrator account, you will still own a standard/limited user privilege. Two access tokens will be created for a administrator, one of it is LUA. They both will be associated with the logon session, and LUA will be the token of the shell (explorer.exe).
 
Third, when UAC is needed to elevate an operation, actually, the elevated process is not the current one. System will create a new process with administrator permission. Since, once the process starts, we will no way to change its privilege.
 
Fourth, File and Registry Virtualization will not come up for all areas that your application accesses. For folders, only %Program Files%, %Windows% and %Windows\System32%, etc, will cause the writes redirection. For registry, HKLM\Software register.
 
Furthermore, it’s interesting to know how UAC prompt. It uses the consent.exe application, which will show a dialog on a secure desktop (in Session 0). If you have some knowledge of Windows interactive logon model, you will suddenly recall “secure desktop” is one of the three desktop created for your logon session. If not, it’s better for you to choose your favorite search engine to make up your knowledge base. Since, secure desktop is separated from the requesting session’s desktop, as long as UAC come up to notify for your confirmation, you cannot do anything apart from it. That’s also the right reason why most of malwares cannot work on Vista.
 
OK. Finally, I want to add how we can query elevation for our managed application with Visual Studio 2005. (Orcas has thrown out a better way, search it on internet).
1. Create a temp.rc file and input the following manifest information in it;
#include <winuser.h>
#define IDR_MANIFEST 1 // 2 for a DLL
IDR_MANIFEST RT_MANIFEST MOVEABLE PURE
{
    "<assembly xmlns=""urn:schemas-microsoft-com:asm.v1"" manifestVersion=""1.0"">
       <asmv3:trustInfo xmlns:asmv3=""urn:schemas-microsoft-com:asm.v3"">
         <asmv3:security>
           <asmv3:requestedPrivileges>
             <asmv3:requestedExecutionLevel
               level=""requireAdministrator""
               uiAccess=""false"" />
           </asmv3:requestedPrivileges>
         </asmv3:security>
       </asmv3:trustInfo>
     </assembly>"
}
Note: be careful with asmv3 namespace, if it crashes, it will cause blue screen on Windows XP.
2.  Compile it within the command line: rc.exe temp.rc;
you will find the resource compile will generate a .res file for you. It’s the resource need to be embed into the application, which is used to inform System, you application need to be elevated before going to run.
3.  In the Project Properties dialog->Application Tab, select it in Resource File entry.
4.  Press F6 to build your solution.
 
Hope this can help.大笑

Anti XSS 方法总结

XSS(Cross-site scripting),跨站点脚本攻击,主要就是利用Web Application对于用户输入(也有可能是数据库中的输入)未进行验证的漏洞,通过在输出的HTML包含用户带有潜在危险的输入,在客户端来执行恶意脚本。如果网站是通过受信任域的,这样的脚本甚至可能在一个较高的权限上运行,访问客户端上的资源。
 
Microsoft Anti-Cross Site Scripting Library V1.5是微软去年老里八早发布的一个“编码”库,用来对Input或者Output进行编码。编码的意义在于对脚本的文本内容进行转义,这样编码后的脚本就不再拥有执行的能力了。通常可以结合一些方法论,比如“威胁建模”来找到程序中的漏洞,当然威胁建模一般都用于在开发生命周期的最前沿(SDLC);
  • Review ASP.NET code that generates output.
  • Determine whether output includes untrusted input parameters.
  • Determine the context in which the untrusted input is used as output.
  • Encode output.
Table Schema: Use Case Scenario/Scenario Inputs Input Trusted?/Scenario Outputs/Output Contains Untrusted Input?/Requires Encoding/Encoding Method to Use
 
另一个方法就是从恶意用户Attack的角度去审查应用程序,从而快速的发现问题。从以下两个问题来进行切入:
  • The application is not validating input;
  • The application is not encoding output that contains untrusted inputs.
最后,如果在这个用例场景中需要对输入/输出进行编码的话,就使用Anti XSS库的AntiXss.HtmlEncode等等方法对String进行编码就OK了。