The MASM Forum

General => The Workshop => Topic started by: jj2007 on February 22, 2016, 10:04:38 PM

Title: DbgPrint
Post by: jj2007 on February 22, 2016, 10:04:38 PM
Sometimes I see this in Olly, typically inside HeapFree or HeapRealloc:

0038F8A1  65 61 70 20|62 6C 6F 63|6B 20 61 74|20 30 30 33| eap block at 003
0038F8B1  45 42 30 38|30 20 6D 6F|64 69 66 69|65 64 20 61| EB080 modified a
0038F8C1  74 20 30 30|33 45 43 30|38 38 20 70|61 73 74 20| t 003EC088 past
0038F8D1  72 65 71 75|65 73 74 65|64 20 73 69|7A 65 20 6F| requested size o
0038F8E1  66 20 31 30|30 30 0A 00|00 3E 00 00|00 00 00 DC| f 1000


Apparently, DbgPrint sents it to the VS debugger output window. My question: Can we use this feature in MASM, e.g. by enabling debug mode, redirecting that stream to the console, ...?
Title: Re: DbgPrint
Post by: GoneFishing on February 22, 2016, 10:18:08 PM
Maybe link against debug version of crt as MS VC does?

Quote from: jj2007 on February 22, 2016, 10:04:38 PM
...
redirecting that stream to the console, ...?
Use DbgView instead
Title: Re: DbgPrint
Post by: sinsi on February 22, 2016, 11:35:12 PM
Use a combination of OutputDebugString (https://msdn.microsoft.com/en-us/library/windows/desktop/aa363362(v=vs.85).aspx) and DebugView (https://technet.microsoft.com/en-us/sysinternals/debugview)?
Title: Re: DbgPrint
Post by: jj2007 on February 23, 2016, 12:38:51 AM
Thanks. So far no luck, can't see that output in DebugView. Linking against debug CRT doesn't make sense, as this is not CRT but rather Win32 standard API calls like HeapAlloc etc :(
Title: Re: DbgPrint
Post by: GoneFishing on February 23, 2016, 01:13:38 AM
Quote from: jj2007 on February 23, 2016, 12:38:51 AM
Thanks. So far no luck, can't see that output in DebugView. Linking against debug CRT doesn't make sense, as this is not CRT but rather Win32 standard API calls like HeapAlloc etc :(
Interesting . I'd look which module does that DbgPrint . Could you upload simple example (for Windows XP) reproducing it?

P.S.: In my first reply I mistakenly named SysInternals' DebugView ( really what I meant)  as DbgView
Title: Re: DbgPrint
Post by: jj2007 on February 23, 2016, 01:23:44 AM
Here it is. Uncomment the ; int 3 to see the difference.

include \masm32\include\masm32rt.inc

.code
start:
  mov esi, rv(GetProcessHeap)
  invoke HeapAlloc, esi, 0, 20
  push eax
  xchg eax, edi
  m2m ecx, 20+1      ; FOUL!!
  rep stosb
  ; int 3
  invoke HeapValidate, esi, 0, 0
  print LastError$()
  pop eax
  invoke HeapFree, esi, 0, eax
  print LastError$()
  exit
end start


Here is the relevant bit when using the int 3:
77CF0B09           Ú$  8BFF               mov edi, edi                  ; ntdll.77CF0B09(guessed Arg1)
77CF0B0B           ³.  55                 push ebp
77CF0B0C           ³.  8BEC               mov ebp, esp
77CF0B0E           ³.  64:A1 18000000     mov eax, fs:[18]
77CF0B14           ³.  8B40 30            mov eax, [eax+30]
77CF0B17           ³.  8078 02 00         cmp byte ptr [eax+2], 0
77CF0B1B           ³. 74 17              je short 77CF0B34
77CF0B1D           ³.  8B45 08            mov eax, [ebp+8]
77CF0B20           ³.  C605 8582D277 01   mov byte ptr [77D28285], 1
77CF0B27           ³.  A3 8082D277        mov [77D28280], eax
77CF0B2C           ³.  CC                 int3
77CF0B2D           ³.  C605 8582D277 00   mov byte ptr [77D28285], 0
77CF0B34           ³>  5D                 pop ebp
77CF0B35           À.  C2 0400            retn 4


Register edx points to:
0018FC11  65 61 70 20|62 6C 6F 63|6B 20 61 74|20 30 30 35| eap block at 005
0018FC21  30 33 44 35|30 20 6D 6F|64 69 66 69|65 64 20 61| 03D50 modified a
0018FC31  74 20 30 30|35 30 33 44|36 43 20 70|61 73 74 20| t 00503D6C past
0018FC41  72 65 71 75|65 73 74 65|64 20 73 69|7A 65 20 6F| requested size o
0018FC51  66 20 31 34|                                     f 14

Title: Re: DbgPrint
Post by: GoneFishing on February 23, 2016, 01:25:23 AM
Thanks .I'll go and play with it now
Title: Re: DbgPrint
Post by: GoneFishing on February 23, 2016, 02:49:27 AM
After some playing  my guess is that we may simulate a debugger in order to intercept debugging messages.
What if create a simple launcher which will create process  for your test app with DEBUG flags ?

[EDIT] That is we might write a small debugger like this Writing the Debugger's Main Loop (https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms681675%28v=vs.85%29.aspx) and handle only OUTPUT_DEBUG_STRING_EVENT (https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms679308%28v=vs.85%29.aspx)
Title: Re: DbgPrint
Post by: jj2007 on February 23, 2016, 03:45:34 AM
Ehm, that looks like a bit of work ::)
Title: Re: DbgPrint
Post by: GoneFishing on February 23, 2016, 04:07:56 AM
Use C++  :biggrin:
Creating Processes (https://msdn.microsoft.com/ru-ru/library/windows/desktop/ms682512%28v=vs.85%29.aspx)
Title: Re: DbgPrint
Post by: jj2007 on February 23, 2016, 04:27:21 AM
C++? Too simple - try this one :biggrin:

include \masm32\MasmBasic\MasmBasic.inc      ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  int 3   ; somewhere down there is a CreateProcess call...
  Launch "Notepad.exe"
EndOfCode
Title: Re: DbgPrint
Post by: GoneFishing on February 23, 2016, 06:59:42 AM
I compiled quick and dirty example from mentioned above C++ snippets.
CreateProcess.exe - launcher for DbgPrint.exe ( compiled from your source ).
I get 2  error messages from  MS VC++  Debug Library and WER window ( see screenshots in attachment) and some promising output :
QuoteHEAP[DbgPrint.exe]:

[EDIT] Note that when I start CALC.EXE with my launcher I don't get any error message boxes .

Weird problems with my keyboard didn't let me accomplish the task in single evening  :(
To be continued
Title: Re: DbgPrint
Post by: sinsi on February 23, 2016, 07:48:46 AM
Works for me  :biggrin:
Title: Re: DbgPrint
Post by: GoneFishing on February 23, 2016, 08:09:04 AM
BINGO!
run:
CreateProcess DbgPrint.exe
get:
Quote
HEAP[DbgPrint.exe]:
Heap block at 001429B8 modified at 001429D4 past requested size of 14

The operation completed successfully.
HEAP[DbgPrint.exe]:
Heap block at 001429B8 modified at 001429D4 past requested size of 14

HEAP[DbgPrint.exe]:
Invalid Address specified to RtlFreeHeap( 00140000, 001429C0 )

The operation completed successfully.

Enjoy

**** NOTICE: Tested on Windows XP 32 ****
Title: Re: DbgPrint
Post by: jj2007 on February 23, 2016, 12:46:03 PM
Quote from: GoneFishing on February 23, 2016, 08:09:04 AM
**** NOTICE: Tested on Windows XP 32 ****

**** NOTICE: Tested on Windows 7 64 ****

Thanks :t

(your version choked with side by side error (http://answers.microsoft.com/en-us/windows/forum/windows_7-pictures/error-the-application-has-failed-to-start-because/df019c0d-746e-42d0-ad68-465e18e3f3ef?auth=1); so I recompiled it for Win7-64)
Title: Re: DbgPrint
Post by: TWell on February 23, 2016, 08:23:16 PM
**** NOTICE: Tested on Windows 10 64 ****

With msvcrt.dll, 32bit and 64bit versions.
Title: Re: DbgPrint
Post by: jj2007 on February 23, 2016, 10:02:47 PM
Quote from: TWell on February 23, 2016, 08:23:16 PM
**** NOTICE: Tested on Windows 10 64 ****

Works fine on Win7-64. The 64-bit version shows some extra non-identified events, though.
Title: Re: DbgPrint
Post by: GoneFishing on February 23, 2016, 10:13:56 PM
Quote from: jj2007 on February 23, 2016, 10:02:47 PM
The 64-bit version shows some extra non-identified events, though.

And what are they?
Title: Re: DbgPrint
Post by: TWell on February 23, 2016, 10:26:55 PM
some other exception 4000001F STATUS_WX86_BREAKPOINT ?
Quote0x4000001F
STATUS_WX86_BREAKPOINT
An exception status code that is used by the Win32 x86 emulation subsystem.
Title: Re: DbgPrint
Post by: GoneFishing on February 23, 2016, 11:04:47 PM
It makes sense.
It's x64 specific:
Using the Windows debugging API on Windows 64 (http://www.howzatt.demon.co.uk/articles/DebuggingInWin64.html) :
Quote
However some of the output produced is a little unexpected! After all, we are debugging exactly the same process that we debugged earlier under "Next step - running the 32-bit code on 64-bit" but we are getting much more output and a very different call stack on program exit. What is going on?

The first change when using the 64-bit debug API is that the debugger is notified about additional DLLs loaded into the process address space. The first DLL loaded, ntdll.dll, is in fact the 64-bit version of the DLL and it is followed by the 32-bit ntdll32.dll. Note that the 32-bit mode debugger doesn't see the 64-bit DLL, only the 32-bit one.

The next few DLLs are the WOW64 implementation - these are 64-bit DLLs loaded into the target process. Again, the 32-bit mode debugger does not receive any notification when these DLLs are loaded into the process. Notice however that, probably through an oversight in the implementation of the 32-bit debug interface, the 32bit debugger sees the UNLOAD DLL messages for the special WOW64 DLLs.

We then receive an unexpected exception - code 0x4000001f - which turns out to be a new value, STATUS_WX86_BREAKPOINT. This exception code is barely documented but it appears to be a 'start up' breakpoint much like the initial breakpoint that the debugger always receives.  On older versions of Windows the default processing for this exception code terminates the process, on Windows 7 it is ignored.

The author of the article fixed this problem like this:

case EXCEPTION_DEBUG_EVENT:
    if (!attached)
    {
      // First exception is special
      attached = true;
    }
#ifdef _M_X64
    else if (DebugEvent.u.Exception.ExceptionRecord.ExceptionCode ==
             STATUS_WX86_BREAKPOINT)
    {
      std::cout << "WOW64 initialised" << std::endl;
    }
#endif // _M_X64
    else
    {
      OnException(DebugEvent.dwThreadId,
        DebugEvent.u.Exception.dwFirstChance,
        DebugEvent.u.Exception.ExceptionRecord);
      continueFlag = (DWORD)DBG_EXCEPTION_NOT_HANDLED;
    }
    break;


I'll add it to the code of the Launcher
Should I use _M_X64 define for Windows 7 64 /Windows 10 64 ?
Title: Re: DbgPrint
Post by: GoneFishing on February 23, 2016, 11:12:37 PM
Does it heart that you have to terminate it by pressing Ctrl-C ?
Title: Re: DbgPrint
Post by: jj2007 on February 23, 2016, 11:37:03 PM
Quote from: GoneFishing on February 23, 2016, 11:12:37 PM
Does it heart that you have to terminate it by pressing Ctrl-C ?

Yes it hurts, but that is easy to fix:

         case EXIT_PROCESS_DEBUG_EVENT:
         // Display the process's exit code.

                     //MessageBox(0, "Bye", "Debugger:", MB_OK);
                     return;
         //   dwContinueStatus = OnExitProcessDebugEvent(DebugEv);
            break;
Title: Re: DbgPrint
Post by: GoneFishing on February 23, 2016, 11:46:21 PM
Ok , it'll be fixed
Also make  change in  default case of exception handling switch:
   default:
               // Handle other exceptions.
                  printf("-- other exception with code 0x%08X \n", DebugEv->u.Exception.ExceptionRecord.ExceptionCode);
                  break;

You won't see non-identified events any more

[EDIT] Fixed version attached,  STATUS_WX86_BREAKPOINT is not handled  - I still don't know how to ifdef it for x64 target
Title: Re: DbgPrint
Post by: jj2007 on March 01, 2016, 01:06:26 AM
Hi GoneFishing,

Based on your source, I've written a plain assembler version. The exe is 1536 bytes and handles only debug string messages, i.e. if there are no problems, the target exe will behave as if it was not debugged at all.

Test it with this snippet:
include \masm32\include\masm32rt.inc
.code
start:
  mov ebx, rv(GetProcessHeap)
  invoke HeapAlloc, ebx, 0, 20
  xchg eax, esi
  mov byte ptr [esi+48], "x"    ; <<<<<<<<<<< ILLEGAL!!!
  invoke HeapValidate, ebx, 0, 0
  print LastError$()
  invoke HeapFree, ebx, 0, esi
  print LastError$()
  exit
end start


EDIT: Attachment removed, an improved version is now at \Masm32\MasmBasic\Res\DebugHeap.exe; see
HeapValidate doesn't find any problems (http://masm32.com/board/index.php?topic=94.msg55745#msg55745)