News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Accessing Union elements inside a Structure in MASM64

Started by bluedevil, September 27, 2022, 12:57:21 AM

Previous topic - Next topic

bluedevil

Hello,

There is DEBUG_EVENT structure which describes a debug event.

In MASM32 SDK this structure was defined like this:

DEBUGSTRUCT UNION
  Exception         EXCEPTION_DEBUG_INFO <{?,?,?,?,?,EXCEPTION_MAXIMUM_PARAMETERS dup(?)},?>
  CreateThread      CREATE_THREAD_DEBUG_INFO <?,?,?>
  CreateProcessInfo CREATE_PROCESS_DEBUG_INFO <?,?,?,?,?,?,?,?,?,?>
  ExitThread        EXIT_THREAD_DEBUG_INFO <?>
  ExitProcess       EXIT_PROCESS_DEBUG_INFO <?>
  LoadDll           LOAD_DLL_DEBUG_INFO <?,?,?,?,?,?>
  UnloadDll         UNLOAD_DLL_DEBUG_INFO <?>
  DebugString       OUTPUT_DEBUG_STRING_INFO <?,?,?>
  RipInfo           RIP_INFO <?,?>
DEBUGSTRUCT ENDS

DEBUG_EVENT STRUCT
  dwDebugEventCode  DWORD       ?
  dwProcessId       DWORD       ?
  dwThreadId        DWORD       ?
  u                 DEBUGSTRUCT <>
DEBUG_EVENT ENDS



In MASM64 SDK it was defined like this:

  DEBUG_EVENT STRUCT
    dwDebugEventCode DWORD ?
    dwProcessId   DWORD ?
    dwThreadId   DWORD ?
       DWORD ?
      UNION
       Exception        EXCEPTION_DEBUG_INFO <>
       CreateThread     CREATE_THREAD_DEBUG_INFO <>
       CreateProcessInfo CREATE_PROCESS_DEBUG_INFO <>
       ExitThread       EXIT_THREAD_DEBUG_INFO <>
       ExitProcess      EXIT_PROCESS_DEBUG_INFO <>
       LoadDll          LOAD_DLL_DEBUG_INFO <>
       UnloadDll        UNLOAD_DLL_DEBUG_INFO <>
       DebugString      OUTPUT_DEBUG_STRING_INFO <>
       RipInfo          RIP_INFO <>
      ENDS
  DEBUG_EVENT ENDS


Thanks to MASM32 SDK one can use `.` notation to access union elements inside a structure:

DBEvent.u.Exception.pExceptionRecord.ExceptionCode


But in MASM64 SDK I couldn't manage to use dot notation to access union elements inside a structure(in our case DEBUG_EVENT elements), so I have to manually access the union elements:

mov r15, qword ptr [DBEvent + 16]           ; DBEvent.u.Exception.pExceptionRecord.ExceptionCode
; or another example
mov r15, qword ptr [DBEvent + 16 + 48]      ; DBEvent.u.CreateProcessInfo.lpStartAddress


I wonder If I can still use dot notation in such cases?
..Dreams make the future
But the past never lies..
BlueDeviL // SCT
My Code Site:
BlueDeviL Github

greenozon

Hello bluedevil
I spent some time exploring your code and my suggestions as well as optimisations are attached
one idea is about using ofn struct predefined (thus moved from .data -> .data)
another one - drop using rXX registers and start using directly DBEvent var members...

Are you planning to write a kind of mini-debugger?

bluedevil

@greenozon thanks for your reply. I have updated my code thanks to you. I have attached my latest code.

My code seems working but I have one issue: the image base and entry point values are wrong if i select a 64bit binary. But it is ok if I select a 32 bit binary.

I am filling the buffer with wsprintf

                invoke wsprintf, addr buffer, addr ProcessInfo, \
                        DBEvent.CreateProcessInfo.hFile,\           ; image file handle
                        DBEvent.CreateProcessInfo.hProcess, \       ; process handle
                        DBEvent.CreateProcessInfo.hThread,\         ; thread handle
                        DBEvent.CreateProcessInfo.lpBaseOfImage, \  ; imagebase
                        DBEvent.CreateProcessInfo.lpStartAddress    ; entrypoint
                invoke MessageBox, NULL, addr buffer, addr AppName, MB_OK or MB_I


But the real problem resides in WaitForDebugEvent api. When this function runs, it fills the DEBUG_EVENT structure. And the entrypoint and imagebase values are wrong if the executable is 64bit binary


.data?
    <snip>
    DBEvent             DEBUG_EVENT <>

.code
<snip>
    invoke WaitForDebugEvent, addr DBEvent, INFINITE
..Dreams make the future
But the past never lies..
BlueDeviL // SCT
My Code Site:
BlueDeviL Github

bluedevil

Folks, If you have time and help me on this issue I will be very happy!

Quote from: bluedevil on October 04, 2022, 08:53:32 AM

But the real problem resides in WaitForDebugEvent api. When this function runs, it fills the DEBUG_EVENT structure. And the entrypoint and imagebase values are wrong if the executable is 64bit binary


.data?
    <snip>
    DBEvent             DEBUG_EVENT <>

.code
<snip>
    invoke WaitForDebugEvent, addr DBEvent, INFINITE


I really dont't get that WaitForDebugEvent API fills DEBUG_EVENT structure true if I open a 32 bit executable, but worng on If i open a 64bit executable.
..Dreams make the future
But the past never lies..
BlueDeviL // SCT
My Code Site:
BlueDeviL Github

zedd151

#4
This is what I get when running the program with TUTE02 as the debugee:
Is this also what you are getting for imagebase and start address?

edit = Removed attached image as it has served its purpose

zedd151

The debugger and debuggee appear to have the same load address and entry point as specified in their PE headers. So, when the debugger (TUTE28) loads the debuggee it must use a different address than that in the PE header (for TUTE02), if my suspicions are correct.
There is a link option that allows to specify the load address, rather than the default iirc. Try changing that for TUTE02 (link option)  to see if it makes a difference.
example:  (I looked it up) where "..." indicates existing part of what you have for link.exe
...  /BASE:0x180000000 ...

TimoVJL

Process Explorer show also same addresses, so it's possible and x64 feature.
Process Explorer v16.43
May the source be with you

bluedevil

@TimoVJL and @zedd151 thank you for your brilliant comments. I have realized that my code actually works normal!

I have double checked by using, Process Explorer and x64dbg, they both gave the same ImageBase and EntryPoint values. Only IDA Pro doesn't; and I think IDA Pro rebases executable to default imagebases.

Also M$ Docs clearly states that:
Quote
For security reasons, Microsoft recommends you use the /DYNAMICBASE option instead of specifying base addresses for your executables. /DYNAMICBASE generates an executable image that can be randomly rebased at load time by using the address space layout randomization (ASLR) feature of Windows. The /DYNAMICBASE option is on by default.

So I have relinked msgbox.exe with /DYNAMICBASE:NO, then I got the default imagebase address!

..Dreams make the future
But the past never lies..
BlueDeviL // SCT
My Code Site:
BlueDeviL Github

zedd151

Ah, ida pro. That's weird.
For me, I could actually care less what M$ says about security reasons. If they knew anything about computer security we would all be happily running Windows xp still. Their best OS, imo.

bluedevil

Quote from: zedd151 on October 08, 2022, 02:02:10 AM
Ah, ida pro. That's weird.
For me, I could actually care less what M$ says about security reasons. If they knew anything about computer security we would all be happily running Windows xp still. Or even Windows 2000.

You are wisdom :eusa_clap:  :eusa_clap:
..Dreams make the future
But the past never lies..
BlueDeviL // SCT
My Code Site:
BlueDeviL Github

jj2007

Quote from: bluedevil on October 08, 2022, 01:31:13 AMAlso M$ Docs clearly states that:
Quote
For security reasons, Microsoft recommends you use the /DYNAMICBASE option instead of specifying base addresses for your executables. /DYNAMICBASE generates an executable image that can be randomly rebased at load time by using the address space layout randomization (ASLR) feature of Windows. The /DYNAMICBASE option is on by default.

/DYNAMICBASE for security reasons is nonsense:
QuoteOur analysis of the results uncovers predictability in the implementation that reduces its effectiveness.

zedd151


hutch--

If its the one I am thinking of, its fundamentally a good idea, randomising the start address of and executable to make hacking it a lot more complicated. I have some time ago done test pieces where you randomly alter ESP (in 32 bit) at the entry point of an executable which made some forms of hacking unreliable but it was never any use to me so I never pursued it.

bluedevil

Quote from: hutch-- on October 08, 2022, 10:19:23 AM
I have some time ago done test pieces where you randomly alter ESP (in 32 bit) at the entry point of an executable which made some forms of hacking unreliable but it was never any use to me so I never pursued it.

You got my attention   :icon_idea:
..Dreams make the future
But the past never lies..
BlueDeviL // SCT
My Code Site:
BlueDeviL Github

hutch--

You basically have to alter ESP right at the entry point. The tests I did some time ago called a random algo within a plus or minus range, modified ESP and then the normal code was run and it seemed to work OK.