Basic Concept on RTC

Doing a research on internet, and summarize as below:  

    //

      // Runtime Checking

      // Small Type Check (/RTCc)

      //

      /*

           003A11F4  jmp         _RTC_Check_2_to_1 (3A14A0h)

           003A11F9  jmp         _RTC_Check_8_to_1 (3A1600h)

           003A11FE  jmp         _RTC_Check_8_to_2 (3A1670h)

           003A1203  jmp         _RTC_Check_8_to_4 (3A16B0h)

           003A1208  jmp         _RTC_Check_4_to_1 (3A15D0h)

           003A120D  jmp         _RTC_Check_4_to_2 (3A1640h)

      */

      char ch = 0;

      short s = 0x101;

      ch = s;

[Note]: RTCc is used to check if a data loss is happened when doing a built-in type cast. The above 6 RTC functions do the real job.

 

      //

      // Uninitialized Variables (/RTCu)

      //

      /*

           000D14A9  mov         byte ptr [ebp-46h],0

           000D14AD  lea         eax,[ch]

           000D14B0  push        eax 

           000D14B1  push        offset string "%c" (0D5748h)

           000D14B6  call        dword ptr [__imp__scanf (0D82C0h)]

           000D14BC  add         esp,8

           000D14BF  movsx       eax,byte ptr [ch]

           000D14C3  cmp         eax,79h

           000D14C6  jne         wmain+33h (0D14D3h)

           000D14C8  mov         byte ptr [ebp-46h],1

           000D14CC  mov         dword ptr [a],0Ah

           000D14D3  cmp         byte ptr [ebp-46h],0

           000D14D7  jne         wmain+46h (0D14E6h)

           000D14D9  push        offset  (0D1501h)

           000D14DE  call        @ILT+170(__RTC_UninitUse) (0D10AFh)

      */

      int a;

      char ch;

      scanf("%c", &ch);

      if (ch == ‘y’)

           a = 10;

      printf("%d", a);

[Note]: RTCu is used to check if there exists some local variable without initializing before its usage. The principle is directly easy. Set a flag (a hidden local variable) to 0 at the first, and set it to 1 as soon as the variable it watches being initialized. Before using this variable, use cmp to compare the flag with 0. If not equals, __RTC_UninitUse will report to us.

 

      //

      // Stack Check (/RTCs)

      // Initialize local variables with 0xcc (int 3), if run as code, breakpoint exception will be raised

      /*

           009314AC  lea         edi,[ebp-0E4h]

           009314B2  mov         ecx,39h

           009314B7  mov         eax,0CCCCCCCCh

           009314BC  rep stos    dword ptr es:[edi]

      */

      int a;

      int b;

      int c;

 

      // Check if esp is messed up

      // Check buffer overrun issue

      // Using buffer’s location and its length to do the checking. Check if the head and tail of buffer is still 0xcc.

      /*

           0012154E  mov         esi,esp

           00121550  lea         eax,[buffer]

           00121553  push        eax 

           00121554  push        offset string "%s" (125744h)

           00121559  call        dword ptr [__imp__scanf (1282C4h)]

           0012155F  add         esp,8

           00121562  cmp         esi,esp

           00121564  call        @ILT+345(__RTC_CheckEsp) (12115Eh)

           00121569  xor         eax,eax

           0012156B  push        edx 

           0012156C  mov         ecx,ebp

           0012156E  push        eax 

           0012156F  lea         edx,[ (121590h)]

           00121575  call        @ILT+140(@_RTC_CheckStackVars@8) (121091h)

      */

      char buffer[10];

      scanf("%s", buffer);

[Note]: cmp is very important here. It checks if stack is balance after calling an extern function. __RTC_CheckEsp will check the result of cmp, if they are not same, __RTC_CheckEsp will use a simple jmp instruction to report the error to us. (prompt a dialog)

/SAFESEH

Recall two most famous scenarios of Stack Overrun in x86 platfrom:
  1. Buffer overrun, and return address pushed by CALL is modified by the malicious code.
  2. Buffer overrun, and address of SEH callback function (exception handler) is modified by the malicious code.
For the first case, we already have /GS to work it around. But how about the second one? We have /SAFESEH (Linker Option).
A quick searching on /SAFESEH in MSDN, you will find /SAFESEH is only supported on x86, while not on x64 & IA64. Because of their proprietary calling convetion, the above two cases will not make sense on these two platform. /SAFESEH is totally not neccassary for them:D
 
How /SAFESEH comes to work?
Hmm~~it’s quite easy, and it introduces nothing, just gethering all the addresses of those exception handler created for SEH, and put them into a table. OS will check if the address of a exception handler is within the boundary of the table when calling it. So if an arbitary address is specified by the malicious code, it will not come to work. OK, that’s it.
 
Just like /GS, /SAFESEH also need help from CRT. [We need to supply a load config struct (such as can be found in loadcfg.c CRT source file) that contains all the entries defined for Visual C++MSDN] After buiding the programe, use dumpbin /loadconfig <programe name>, we can get list of all exception handlers in the table:
 
Dump of file SafeSEH.exe
File Type: EXECUTABLE IMAGE
  Section contains the following load config:
            00000048 size
                   0 time date stamp
                0.00 Version
                   0 GlobalFlags Clear
                   0 GlobalFlags Set
                   0 Critical Section Default Timeout
                   0 Decommit Free Block Threshold
                   0 Decommit Total Free Threshold
            00000000 Lock Prefix Table
                   0 Maximum Allocation Size
                   0 Virtual Memory Threshold
                   0 Process Heap Flags
                   0 Process Affinity Mask
                   0 CSD Version
                0000 Reserved
            00000000 Edit list
            00407000 Security Cookie // for /GS
            004064F0 Safe Exception Handler Table
                   1 Safe Exception Handler Count
    Safe Exception Handler Table
          Address
          ——–
          00401100  __except_handler4
 
Actually, if we don’t define our own raw exception handler, there will always only one entry (__except_handler4) in the table, because, VC++ does the emcapsulation for us. In FS:[0] chain, all the _EXCEPTION_REGISTRATION struct contain the same handler, __except_handler4, which do the real job calling our code, usually defined in __except filter and __except block.

Programming Tips 3

Hi Seema,

 

We have worked around how to deploy backend for resolving .NET x64 issue, and made it work on Stephen’s local x64 machineJ

 

The solution is as below:

·         Use 32-bit StackGenerator (running on 64-bit IIS, but configured it in 32-bit mode)

·         Use 32-bit Oracle Client

·         Use 64-bit Debugging tools for Windows

 

Use 32-bit StackGenerator

 

Jimmy is so smart to find that great solution, which we can use to twist 64-bit IIS running in 32-bit mode with the Admin Script provided by IIS installation.

1.       Configure 64-bit IIS running in 32-bit mode:

cscript %SystemDrive%\inetpub\AdminScripts\adsutil.vbs set w3svc/AppPools/Enable32bitAppOnWin64 1

 

2.       Configure 64-bit IIS back to 64-bit mode:

cscript %SystemDrive%\inetpub\AdminScripts\adsutil.vbs set w3svc/AppPools/Enable32bitAppOnWin64 0

 

Use 32-bit Oracle Client component

 

Stephen also help to point out a key spot, that 64-bit Oracle Client provides us 32-bit DB Provider (msdaora.dll), instead of 64-bit oneL (We got cheated by OracleJ) So, using 32-bit StackGenerator and 32-bit Oracle Client is the only choice.

 

Use 64-bit Debugging tools for Windows

 

CDB is running as expected, but there’s still a known issue of Symbol Downloading from MS Symbol Server. That is because we do not have the 64-bit symsrv.dll (non-official version) provided by Microsoft.

 

Thanks,

Austin

Programming Tips 2

Using Index file to seperate the symbol store generation into 2 phases.
 
[Assumption]
Directories are all on my local machine, no network path and share are needed.
 
1. Generate Index file, which contains a list of files that need to be uploaded.
[Command-Line]
C:\Users\Weibin Dai>symstore add /o /r /p /g "D:\Visual Studio 2008\ManagedApp" /f "D:\Visual Studio 2008\ManagedApp\Debug\*.*" /x "D:\Visual Studio 2008\index.txt
SYMSTORE MESSAGE: Skipping file D:\Visual Studio 2008\ManagedApp\Debug\HostCLR.ilk – not a known file type.
SYMSTORE MESSAGE: Skipping file D:\Visual Studio 2008\ManagedApp\Debug\HostCLR2.ilk – not a known file type.
SYMSTORE MESSAGE: Skipping file D:\Visual Studio 2008\ManagedApp\Debug\NativeTransaction.ilk – not a known file type.
SYMSTORE: Number of pointers stored = 8
SYMSTORE: Number of errors = 0
SYMSTORE: Number of pointers ignored = 3
 
[Notice]
Some types of file will not be recognized by symstore, so symstore will not upload it. The same thing occurs on .NET _ni_ dll too. I’m wondering how Microsoft uploads those _ni_ dll. e.g. System.ni.dll
 
2. Use Index file to upload symbol files or just file pointer.
[Command-Line]
C:\Users\Weibin Dai>symstore add /o /y "D:\Visual Studio 2008\index.txt" /l /g "D:\Visual Studio 2008\ManagedApp\" /s "D:\SymbolStore" /p /t "Symbol Index Test" /v "Build 1" /c "Sample Add from Index"
SYMSTORE MESSAGE: LastId.txt reported id 0
SYMSTORE MESSAGE: History.txt reported id 0
SYMSTORE MESSAGE: Existing logs reported id 1
SYMSTORE MESSAGE: Final id is 0000000001
SYMSTORE: Number of pointers stored = 8
SYMSTORE: Number of errors = 0
SYMSTORE: Number of pointers ignored = 0

Programming Tips 1

1. Misunderstanding on Native Image generated by ngen.exe
 
So far, more accurately till today’s noon, I believed in that Native Image generated by ngen.exe is a standalone executable file, which we can make it run as double clicking it in the shell. But, it’s obviously wrong. (Thanks Michael to point it out:P)
 
  Why this topic catches my eye?
This morning, I used dumpbin.exe on a Native Image (originaly from managed exe file), and I’m suprised to see that the type of the module displayed as dll, instead of exe. And also, I notice the value of data directory of COM Descriptor Directory in PE file is other than zero, which indicates that the module is a .NET assembly. Oh, it’s amazing because the module indeed has been compiled as CPU-specific machine code.
 
  What should it be?
When we use ngen.exe to generate a Native Image, it will install the output into Native Cache (a no-visiable folder via shell), and then, throughout it life, .NET CLR will take charge of it. So, when we launch .NET application as double clicking it in shell, CLR will try to look for its native version in Native Cache first. Otherwise, if CLR’s assembly loader does not find it, .NET CLR will call JIT to run a Just-In-Time compiling to do the job. That’s it. Native Image is more a compiled MSIL cache than a standalone application. It’s CLR that loads it.
 
2. Microsoft .NET Framework NGEN v2.0.50727_X86 in Services (MMC)
 
I forgot what is the first time I see this background service running in Task Manager. Maybe when my machine suddenly runs slowly:P
It’s just Native Image Service. On X64, it is called Microsoft.NET Framework NGEN v2.0.50727_X64.
 
  What’s the job of it?
The native image service allows the developer to defer the installation and update of native images to periods when the computer is idle.
 
  Why we need it?
Normally, the native image service is initiated by the installation program (installer) for an application or update. For priority 3 actions, the service executes during idle time on the computer. The service saves its state and is capable of continuing through multiple reboots if necessary. Multiple image compilations can be queued. [MSDN]
3. MDA (Managed Debugging Assistant)
 
Managed debugging assistants (MDAs) are debugging aids that work in conjunction with the common language runtime (CLR) to provide information on runtime state. The assistants generate informational messages about runtime events that you cannot otherwise trap. [MSDN]
 
For example, if you want to debug the application at the time of a specific method is being JIT compiled (jitCompilationStart MDA
). MDA can notify you via launching JIT debugger that is set in AeDebug\Debugger registry.
 
According to the MSDN, when there’s no debugger attached, a message box with detailed information (looks like an unhandled exception message box) will prompt, but after thousands of experiments, I still fails to get it done. :S