Skip to main content

Deep Dive to Windows, Part 4



Launched a process sample_Hello through WinDbg and observed following events:

ModLoad: 00400000 0041c000   Sample_Hello.exe
ModLoad: 77980000 77b00000   ntdll.dll
ModLoad: 76b10000 76c20000   C:\Windows\syswow64\kernel32.dll
ModLoad: 76d20000 76d67000   C:\Windows\syswow64\KERNELBASE.dll
ModLoad: 67fd0000 680ce000   C:\Windows\WinSxS\x86_microsoft.vc80.debugcrt_1fc8b3b9a1e18e3b_8.0.50727.6195_none_e4a70117006762dd\MSVCP80D.dll
ModLoad: 670e0000 67201000   C:\Windows\WinSxS\x86_microsoft.vc80.debugcrt_1fc8b3b9a1e18e3b_8.0.50727.6195_none_e4a70117006762dd\MSVCR80D.dll
ModLoad: 77050000 770fc000   C:\Windows\syswow64\msvcrt.dll
(3c0.1324): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=00000000 ecx=fb480000 edx=0008e3c8 esi=fffffffe edi=00000000
eip=77a20fab esp=0018fb08 ebp=0018fb34 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
ntdll!LdrpDoDebuggerBreak+0x2c:
77a20fab cc              int     3

Process launched but execution halted with a Break instruction exception (please see highlighted line above). Why this happened?

This is due to the fact called “breaking into the debugger”.  We will see this later. Now let’s see how many threads are there in this state. I’m expecting 1 since my application is a single threaded application.

So, I’ve executed the command ~* on windbg.

0:000> ~*
.  0  Id: 3c0.1324 Suspend: 1 Teb: 7efdd000 Unfrozen
      Start: *** WARNING: Unable to verify checksum for Sample_Hello.exe
Sample_Hello!ILT+145(_wmainCRTStartup) (00411096)
      Priority: 0  Priority class: 32  Affinity: 3

Indeed I’ve a thread.  Let’s see the stack of the thread:

0:000> ~*kb

.  0  Id: 3c0.1324 Suspend: 1 Teb: 7efdd000 Unfrozen
ChildEBP RetAddr  Args to Child             
0018fb34 77a01383 7efdd000 7efde000 77a8206c ntdll!LdrpDoDebuggerBreak+0x2c
0018fcb0 779c52d6 0018fd24 77980000 7b14b7c0 ntdll!LdrpInitializeProcess+0x12cc
0018fd00 779b9e79 0018fd24 77980000 00000000 ntdll!_LdrpInitialize+0x78
0018fd10 00000000 0018fd24 77980000 00000000 ntdll!LdrInitializeThunk+0x10

So, after initialize process call there is a DebuggerBreak call.

Now I’ve executed the ‘g’ (go) and debugee will start running. Lets’s see:

Yes, Debugee is in running state:
Debuggee is running...

Since my program uses for user input to terminate so program is waiting for input. It is going to help me to see the state of the process.

Again I’ve used debugger break point to halt the application and now would like to see how many threads are there:

0:001> ~*
   0  Id: 3c0.1324 Suspend: 1 Teb: 7efdd000 Unfrozen
      Start: Sample_Hello!ILT+145(_wmainCRTStartup) (00411096)
      Priority: 0  Priority class: 32  Affinity: 3
.  1  Id: 3c0.14c4 Suspend: 1 Teb: 7efda000 Unfrozen
      Start: ntdll!DbgUiRemoteBreakin (77a1f85a)
      Priority: 0  Priority class: 32  Affinity: 3

Now we’ve two threads but my application is a single threaded application, so what’s the other thread?

Let’s see the stack:

   0  Id: 3c0.1324 Suspend: 1 Teb: 7efdd000 Unfrozen
ChildEBP RetAddr  Args to Child             
0018fa24 76bc7379 00000003 671f4aa0 00001000 kernel32!ReadConsoleInternal+0x15
0018faac 76b4f1b2 00000003 671f4aa0 00001000 kernel32!ReadConsoleA+0x40
0018faf4 67151b6a 00000003 671f4aa0 00001000 kernel32!ReadFileImplementation+0x75
0018fb88 671514c7 00000000 671f4aa0 00001000 MSVCR80D!_read_nolock+0x62a [f:\dd\vctools\crt_bld\self_x86\crt\src\read.c @ 233]
0018fbd8 67177da1 00000000 671f4aa0 00001000 MSVCR80D!_read+0x217 [f:\dd\vctools\crt_bld\self_x86\crt\src\read.c @ 93]
0018fc00 67180a7b 671f1d08 489faa4c 0018ff30 MSVCR80D!_filbuf+0x111 [f:\dd\vctools\crt_bld\self_x86\crt\src\_filbuf.c @ 136]
0018fc54 67fe6b2e 671f1d08 0018fd3f 0018fd4c MSVCR80D!fgetc+0x24b [f:\dd\vctools\crt_bld\self_x86\crt\src\fgetc.c @ 49]
0018fc64 67fe67c5 0018fd3f 671f1d08 489daae2 MSVCP80D!std::_Fgetc+0xe [f:\dd\vctools\crt_bld\self_x86\crt\src\fstream @ 37]
0018fd4c 67fe66ce 0018fe58 680c4950 00000000 MSVCP80D!std::basic_filebuf >::uflow+0xb5 [f:\dd\vctools\crt_bld\self_x86\crt\src\fstream @ 362]
0018fd64 67fe1018 00000000 680c4950 0018fdd0 MSVCP80D!std::basic_filebuf >::underflow+0x4e [f:\dd\vctools\crt_bld\self_x86\crt\src\fstream @ 341]
0018fd74 67fe1cb2 489daa7e 0018ff30 0018fe58 MSVCP80D!std::basic_streambuf >::sgetc+0x38 [f:\dd\vctools\crt_bld\self_x86\crt\src\streambuf @ 113]
0018fdd0 67fe0f57 00001300 489daa5e 0018fe2c MSVCP80D!std::basic_istream >::_Ipfx+0x102 [f:\dd\vctools\crt_bld\self_x86\crt\src\istream @ 113]
0018fdf0 68040f31 680c49a4 00000000 489da9e6 MSVCP80D!std::basic_istream >::sentry::sentry+0x47 [f:\dd\vctools\crt_bld\self_x86\crt\src\istream @ 86]
0018fe48 004115e6 680c49a4 0018ff2b 00000000 MSVCP80D!std::operator>> >+0x41 [f:\dd\vctools\crt_bld\self_x86\crt\src\istream @ 997]
0018ff30 004125b6 00000001 007d4778 007d57f0 Sample_Hello!wmain+0x66 [f:\fordebugging\sample_hello\sample_hello\sample_hello.cpp @ 28]
0018ff80 004123fd 0018ff94 76b233aa 7efde000 Sample_Hello!__tmainCRTStartup+0x1a6 [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 594]
0018ff88 76b233aa 7efde000 0018ffd4 779b9ef2 Sample_Hello!wmainCRTStartup+0xd [f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 414]
0018ff94 779b9ef2 7efde000 7b14b514 00000000 kernel32!BaseThreadInitThunk+0xe
0018ffd4 779b9ec5 00411096 7efde000 00000000 ntdll!__RtlUserThreadStart+0x70
0018ffec 00000000 00411096 7efde000 00000000 ntdll!_RtlUserThreadStart+0x1b

#  1  Id: 3c0.14c4 Suspend: 1 Teb: 7efda000 Unfrozen
ChildEBP RetAddr  Args to Child             
0051ff58 77a1f896 7b5db548 00000000 00000000 ntdll!DbgBreakPoint
0051ff88 76b233aa 00000000 0051ffd4 779b9ef2 ntdll!DbgUiRemoteBreakin+0x3c
0051ff94 779b9ef2 00000000 7b5db514 00000000 kernel32!BaseThreadInitThunk+0xe
0051ffd4 779b9ec5 77a1f85a 00000000 00000000 ntdll!__RtlUserThreadStart+0x70
0051ffec 00000000 77a1f85a 00000000 00000000 ntdll!_RtlUserThreadStart+0x1b

Thread 0 stack is known to me but what’s the thread 1. Actually the thread 1 is the debugger thread. This injects this (thread 1) thread to target process as part of break in command.  So the call was:

0051ff88 76b233aa 00000000 0051ffd4 779b9ef2 ntdll!DbgUiRemoteBreakin+0x3c

Since thread 1 is the active thread (marked with ‘.’) and ntdll!DbgBreakPoint is the last call in the stack, lets unassembled it:

0:001> uf ntdll!DbgBreakPoint
ntdll!DbgBreakPoint:
7799000c cc              int     3
7799000d c3              ret

Got it; this calls INT 3 (Interrupt 3). Execution freezes here. So we’ve used the term “breaking into the debugger” at the beginning. It says that user mode debugger can interrupt at any point of time to freeze the target process.  In response to this interrupt, OS raises a structured exception (Windows SEH) in the context of break-in thread and as result, first chance exception occurred with exception code 80000003 (first chance).

Happy Debugging...

Comments

Popular posts from this blog

Variadic template class to add numbers recursively during compilation

 The idea of having a class to add numbers (variable parameters) during compilation time recursively. Also wanted to restrict types to a single type while sending parameters to class member function. That said, if we mix int, float and double types to add function shall result in compilation error. How do we achieve this. The below is the code which actually helps to achieve this: <code> #include < fmt/format.h > template < typename T> class MyVarSumClass{     private :         T _sum = 0 ;     public :         template < typename ... TRest>         T add(T num, TRest... nums){             static_assert (std::conjunction<std::is_same<TRest, T>...>{}); /* Assert fails                if types are different */             _sum += num;             return add(nums...); // Next parameter packs gets picked recursively         }         // Base case         T add(T num){             _sum += num;             return _sum;         } }; int main() {     My

A simple approach to generate Fibonacci series via multi-threading

T his is a very simple approach taken to generate the Fibonacci series through multithreading. Here instead of a function, used a function object. The code is very simple and self-explanatory.  #include <iostream> #include <mutex> #include <thread> class Fib { public:     Fib() : _num0(1), _num1(1) {}     unsigned long operator()(); private:     unsigned long _num0, _num1;     std::mutex mu; }; unsigned long Fib::operator()() {     mu.lock(); // critical section, exclusive access to the below code by locking the mutex     unsigned long  temp = _num0;     _num0 = _num1;     _num1 = temp + _num0;     mu.unlock();     return temp; } int main() {     Fib f;          int i = 0;     unsigned long res = 0, res2= 0, res3 = 0;     std::cout << "Fibonacci series: ";     while (i <= 15) {         std::thread t1([&] { res = f(); }); // Capturing result to respective variable via lambda         std::thread t2([&] { res2 = f(); });         std::thread t3(

A concept to a product (Kimidori [ 黄緑]) - Part 2

In the previous part , we have seen KIMIDORI [ 黄緑] detect if a URL is malicious. In this part, we will see the details that KIMIDORI [ 黄緑] fetches out of the URL provided. As an example, provided a safe URL, https://www.azuresys.com/, and let's see what it brings out: As we can see, the link is safe and the link is active, which means we can just click on the link to open it on IE.  Now it's time to look into the URL report (still under development):  We have URLs IP, Location, and HTTP Status code. The Report part is a sliding window, the Show Report button shows as well as hides the report. Show / Hide Report is a toggle button. Let's see if we get the same details for any bad (phishing / malicious) URL: Took an URL example from a phishing link and tested it. The tool detected it as not a good link (Screen Shot Below) & link does not activate unlike a safe URL: Now let's see the report part for more details including domain registration details: It looks like it&