Author Topic: Embarrassingly Simple Problem  (Read 7170 times)

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Embarrassingly Simple Problem
« on: August 01, 2014, 05:32:23 AM »
...This has GOT TO BE one of those "Check Line 42" situations,...but, I've tried a number of what I considered,...obvious,...solutions to the code syntax,...and, every one of them FAILS.
What I'm trying to do is obtain a Pointer to a structure member (that resides at a location in memory allocated by a Win32 API), but, is not in the DATA section of my app.
Basically, I'm reading and printing the details of all the ACEs (Access Control Entry) in a Security Descriptor. Most of it is quite simple.
I have a valid pointer to the WMI Namespace Security Descriptor, and I have called GetSecurityDescriptorDacl, and, then, GetAclInformation. This works correctly.
Then I want to iterate through the ACEs, and print out the relevant data to file, as a check. So, I'm invoking GetAce (in a loop),...and, using the pointer to the ACE (which is returned from GetAce), to retrieve information about the ACE and print this info to file. It all works great (I've already used the ACE pointer to retrieve data from the ACE_HEADER structure), until I get to the point where I'm trying to retrieve a pointer to the SID that is embedded in an ACCESS_ALLOWED_ACE structure, and use it in a call to: LookupAccountSid. The concept is simple, really,...but, then when I try to use the obtained SID pointer in a call to IsValidSid, the function FAILS.
Here is what I've tried,...

Code: [Select]
        mov ecx, dwptrACE    ;    dwptrACE is a valid pointer to the ACE returned from GetAce.   
        ASSUME ecx: PTR ACCESS_ALLOWED_ACE   
        mov edx, OFFSET [ecx].SidStart    ;    Internal Assembly Error.     
        ASSUME ecx: NOTHING
        mov dwptrAceSID, edx    ;    dwptrAceSID is a pointer to the SID enclosed in an ACE.   
        invoke IsValidSid, dwptrAceSID
 

Code: [Select]
        mov ecx, dwptrACE    ;    dwptrACE is a valid pointer to the ACE returned from GetAce.   
        ASSUME ecx: PTR ACCESS_ALLOWED_ACE   
        mov edx, [ecx].SidStart    ;    Compiles, but, IsValidSid FAILS.     
        ASSUME ecx: NOTHING
        mov dwptrAceSID, edx    ;    dwptrAceSID is a pointer to the SID enclosed in an ACE.   
        invoke IsValidSid, dwptrAceSID

Code: [Select]
        mov ecx, dwptrACE    ;    dwptrACE is a pointer to the ACE returned from GetAce.   
        ASSUME ecx: PTR ACCESS_ALLOWED_ACE   
        mov edx, DWORD PTR [ecx+8]    ;    IsValidSid FAILED.
        ASSUME ecx: NOTHING
        mov dwptrAceSID, edx    ;    dwptrAceSID is a pointer to the SID enclosed in an ACE.   
        invoke IsValidSid, dwptrAceSID

Code: [Select]
        mov ecx, dwptrACE    ;    dwptrACE is a valid pointer to the ACE returned from GetAce.   
        mov ebx, SIZEOF ACE_HEADER    ;    DWORD
        mov eax, SIZEOF ACCESS_MASK    ;    DWORD
        ADD ebx, eax
        ADD ecx, ebx
        mov dwptrAceSID, ecx    ;    Program malfunctioned.   
        invoke IsValidSid, dwptrAceSID

In the ACCESS_ALLOWED_ACE structure, the member StartSid is the first DWORD of the SID, it's NOT a pointer to the SID. What I need is a pointer to that SID. I need the address of ACCESS_ALLOWED_ACE.StartSid.
Thanks for any ideas,... :biggrin:
« Last Edit: August 03, 2014, 05:30:09 AM by Zen »
Zen

qWord

  • Member
  • *****
  • Posts: 1473
  • The base type of a type is the type itself
    • SmplMath macros
Re: Embarrassingly Simple Problem
« Reply #1 on: August 01, 2014, 06:40:09 AM »
Code: [Select]
        mov ecx, dwptrACE    ;    pointer to the ACE   
        lea edx,[ecx].ACCESS_ALLOWED_ACE.SidStart
        mov dwptrAceSID, edx    ;    dwptrAceSID is a pointer to the SID   
        invoke IsValidSid, edx
MREAL macros - when you need floating point arithmetic while assembling!

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Re: Embarrassingly Simple Problem
« Reply #2 on: August 01, 2014, 06:46:50 AM »
QWORD,
Thanks you. I tried something similar in my code (it seems so simple),...but the app malfunctioned (it just stopped working, although it compiled).
When I commented out that block, it compiled, functioned OK,...except that the info returned from LookupAccountSid wasn't written to the file.
« Last Edit: August 03, 2014, 05:17:24 AM by Zen »
Zen

dedndave

  • Member
  • *****
  • Posts: 8825
  • Still using Abacus 2.0
    • DednDave
Re: Embarrassingly Simple Problem
« Reply #3 on: August 01, 2014, 07:35:57 AM »
let's say you are using a WIN32_FIND_DATAW structure
Code: [Select]
wfd WIN32_FIND_DATAW <>
; dwFileAttributes   DWORD    ?
; ftCreationTime     FILETIME <>
; ftLastAccessTime   FILETIME <>
; ftLastWriteTime    FILETIME <>
; nFileSizeHigh      DWORD    ?
; nFileSizeLow       DWORD    ?
; dwReserved0        DWORD    ?
; dwReserved1        DWORD    ?
; cFileName          WORD     MAX_PATH dup (?)  ;MAX_PATH = 260
; cAlternateFileName WORD     14 dup (?)

the offset of any member can be found with StructName.MemberName
Code: [Select]
    add     eax,WIN32_FIND_DATAW.ftCreationTime
because ftCreationTime is at offset 4 of the WIN32_FIND_DATAW structure, that code adds 4 to EAX

you can do the same using LEA
Code: [Select]
    lea     edx,[eax].WIN32_FIND_DATAW.ftCreationTime

jj2007

  • Member
  • *****
  • Posts: 10113
  • Assembler is fun ;-)
    • MasmBasic
Re: Embarrassingly Simple Problem
« Reply #4 on: August 01, 2014, 07:37:29 AM »
Hi Zen,

lea is the way to go - it IS so simple. Difficult to say why your app crashes, but Olly could surely tell you a story ;-)

P.S.: Dave's solution may work, too - why don't you post your code, so that we can play around a little bit?

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Re: Embarrassingly Simple Problem
« Reply #5 on: August 01, 2014, 09:09:38 AM »
QWORD, DAVE, and, JOCHEN,
Yeah,...on further inspection of my code, something else is going wrong (and, at this point, I'm not sure what). :dazzled:
EDIT: I found and fixed the error,...it is unrelated to the SID Address problem.
I'm certain that you guys are correct. Everything you said makes perfect sense. Like I said, it's a simple operation.
THANKS FOR YOUR HELP !!!
I'll mess with my code and see if I can't figure out (what is NO DOUBT and incredibly dumb mistake), and, get back to your with the solution.

...By the way, I found some source code in the Windows SDK for Windows Seven that demonstrates how to access the Security Descriptor for the WMI Namesapce (it's written in C++),...and, this is what I'm trying to translate into MASM assembly, so that I can access WMI data,...
« Last Edit: August 03, 2014, 05:18:50 AM by Zen »
Zen

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Re: Embarrassingly Simple Problem
« Reply #6 on: August 03, 2014, 04:20:37 AM »
Well, I figured out what the problem is: it's a name collision.  :dazzled:
What the heck is MASK ??? It's either a directive or an operative.
This is the definition of the ACCESS_ALLOWED_ACE in MASM's windows.inc

Code: [Select]
ACCESS_ALLOWED_ACE STRUCT
  Header    ACE_HEADER <>
  imask     DWORD      ?     ;    Should be Mask     DWORD      ?
  SidStart  DWORD      ?
ACCESS_ALLOWED_ACE ENDS
...For some odd reason, the MASM compiler chokes on this definition, when using the LEA instruction to return the address of StartSid,...

This code compiles and works (but, accesses a member of the ACE_HEADER structure):
Code: [Select]
        mov ecx, dwptrACE    ;    dwptrACE is a pointer to the ACE returned from GetAce.   
        ASSUME ecx: PTR ACE_HEADER
        LEA edx, [ecx].AceSize   
        ASSUME ecx: NOTHING
...Of course, this is not the correct address of the SID,...but, it demostrates that QWORD's approach (using LEA) works correctly,...

...This code compiles,...but the app hangs and fails at line containing the LEA instruction,...
Code: [Select]
mov ecx, dwptrACE    ;    dwptrACE is a pointer to the ACE returned from GetAce.   
        ASSUME ecx: PTR ACCESS_ALLOWED_ACE
        LEA edx, [ecx].ACCESS_ALLOWED_ACE.SidStart 
        ASSUME ecx: NOTHING
« Last Edit: August 03, 2014, 09:34:09 AM by Zen »
Zen

jj2007

  • Member
  • *****
  • Posts: 10113
  • Assembler is fun ;-)
    • MasmBasic
Re: Embarrassingly Simple Problem
« Reply #7 on: August 03, 2014, 04:28:20 AM »

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Re: Embarrassingly Simple Problem
« Reply #8 on: August 03, 2014, 04:31:51 AM »
JOCHEN,
AHhhhhhhhhhhhh,...HAH,...of course,...the MASK operator,... :dazzled:
...So, the problem NOW is how to correctly define the ACCESS_ALLOWED_ACE structure,...
...Or,...to find an incredibly complicated, but, foolproof method of obtaining the SID pointer for the specified ACE,...:icon_mrgreen:
One thing that I tried, was to write a fake structure definition that contains 3 DWORDs (using LEA with the last DWORD would give me the correct offset to the SID). This compiles, but the program hangs at the LEA instruction.

Thanks,...by the way,...:biggrin:
...And, seriously,...why is QWORD always at the center of these weirdly esoteric, nearly incomprehensible MASM mysteries ???

EDIT: I tried a TEXTEQU, but it didn't work:
Code: [Select]
imask TEXTEQU <Mask>
« Last Edit: August 03, 2014, 08:47:59 AM by Zen »
Zen

dedndave

  • Member
  • *****
  • Posts: 8825
  • Still using Abacus 2.0
    • DednDave
Re: Embarrassingly Simple Problem
« Reply #9 on: August 03, 2014, 05:03:58 AM »
Code: [Select]
ACE_HEADER STRUCT
  AceType  BYTE ?
  AceFlags BYTE ?
  AceSize  WORD ?
ACE_HEADER ENDS

ACCESS_ALLOWED_ACE STRUCT
  Header   ACE_HEADER <>
  dwMask   DWORD ?
  SidStart DWORD ?
ACCESS_ALLOWED_ACE ENDS

    .DATA?

aaas ACCESS_ALLOWED_ACE <>

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Re: Embarrassingly Simple Problem
« Reply #10 on: August 03, 2014, 05:05:49 AM »
DAVE !!!
I don't think it will work, for the same reason that (the ACCESS_ALLOWED_ACE member name) iMask didn't work,...
...But, at this point,...I WILL TRY ANYTHING,...

Code: [Select]
ACCESS_ALLOWED_ACE_REDEF STRUCT
  Header    ACE_HEADER <>
  dwMask     DWORD      ?    ;    was Mask, name collision, MASK is a MASM operator.   
  SidStart  DWORD      ?
ACCESS_ALLOWED_ACE_REDEF ENDS

...Sorry,...it didn't work,...I will redefine in windows.inc,...no,...that didn't work, either,...:dazzled:
...This is evolving into Mission Impossible,...

...I may have to just skip this section (it's unnecessary for the program functionality,...it's just a nice to have the information),...
Zen

dedndave

  • Member
  • *****
  • Posts: 8825
  • Still using Abacus 2.0
    • DednDave
Re: Embarrassingly Simple Problem
« Reply #11 on: August 03, 2014, 08:27:49 AM »
didn't know they were already defined in windows.inc   :P

all you need is
Code: [Select]
        .DATA?

aaas ACCESS_ALLOWED_ACE <>

Zen

  • Member
  • ****
  • Posts: 962
  • slightly red-shifted
Re: Embarrassingly Simple Problem
« Reply #12 on: August 03, 2014, 08:48:56 AM »
Ha,...Ha,...Ha,...
Jesus, DAVE,...:dazzled:

...I know,...it doesn't make alot of sense to you guys, since I have not given you the code,...
Hell,...it doesn't really make sense to me,...I'm basically guessing,...
QWORD's original suggestion of using the LEA insrtruction is correct,...but, because of the name collision, LEA FAILS in this instance,...
...I'm very certain of this, because I've tried a number of syntax variations,...and, they all work, except, when I try to call LEA for a member of the ACCESS_ALLOWED_ACE structure,...(the ACE_HEADER structure is a member of the  ACCESS_ALLOWED_ACE structure),...
Look Up, to this message: MASK

Microsoft defines the ACCESS_ALLOWED_ACE structure like this:
Code: [Select]
C++

typedef struct _ACCESS_ALLOWED_ACE {
  ACE_HEADER  Header;
  ACCESS_MASK Mask;
  DWORD       SidStart;
} ACCESS_ALLOWED_ACE, *PACCESS_ALLOWED_ACE;

The structure ACCESS_ALLOWED_ACE as defined in MASM's windows.inc, is slightly different (because MASK is a MASM keyword),...
Really, all I need is the SID that is included in the ACE,...it can be done in other, less convenient ways,...as, I said, I want to call LookupAccountSid, which requires a pointer to a SID,...returning the Account Name and Domain Name,...that the ACE either allows access to or denies access to (the WMI namespace).

This program contains a HUMONGEOUS amount of code,...it's incredibly bloated, and has an awful lot of extraneous (but, useful) data,...and, crap that didn't work that I commented out,...it's an ugly mess,...but, most of it works quite well,...when compiled,...
I'm basically trying to save you the trouble of reading through all of it (the vast majority of the code is not relevant to the current problem),...
I wanted to get the whole thing working correctly, and, then, revise it so that it is readable,...and, easily modified,...
I'll work on it some more (I still have some ideas),...and. then,...I'll release the whole thing in all it's way-too-complex COM glory,...

...And, of course,...I'll expect DEATH THREATS,...lots of Death Threats,...:dazzled:
Zen

dedndave

  • Member
  • *****
  • Posts: 8825
  • Still using Abacus 2.0
    • DednDave
Re: Embarrassingly Simple Problem
« Reply #13 on: August 03, 2014, 09:46:33 AM »
i have no problem assembling this
Code: [Select]
        INCLUDE    \Masm32\Include\Masm32rt.inc

;###############################################################################################

        .DATA?

aaas ACCESS_ALLOWED_ACE <>

;###############################################################################################

        .CODE

;***********************************************************************************************

_main   PROC

        lea     edx,aaas

        print   chr$(13,10)
        inkey
        INVOKE  ExitProcess,0

_main   ENDP

;###############################################################################################

        END     _main

dedndave

  • Member
  • *****
  • Posts: 8825
  • Still using Abacus 2.0
    • DednDave
Re: Embarrassingly Simple Problem
« Reply #14 on: August 03, 2014, 09:49:38 AM »
so - start with a small file like that and add to it to discover what the issue is

one thing to remember is that INVOKE xxxx,ADDR yyyy uses EAX to LEA the address
so, if you have
Code: [Select]
    lea     eax,aaas
    INVOKE  SomeFunc,eax,addr Something
you will get an error

that's because the assembler uses EAX in the INVOKE code
Code: [Select]
    lea     eax,Something
this will work ok
Code: [Select]
    lea     edx,aaas
    INVOKE  SomeFunc,edx,addr Something