Results 1 to 7 of 7

Thread: can anyone tell me why code such as this avoids access violation on write..

  1. #1
    |< x != '+' BanMe's Avatar
    Join Date
    Oct 2008
    Location
    Farmington NH
    Posts
    510
    Blog Entries
    4

    can anyone tell me why code such as this avoids access violation on write..

    The write is to USER_SHARED_SPACE I believe..
    Code:
    7C812DBB   . 64:A1 18000000 MOV EAX,DWORD PTR FS:[18]
    7C812DC1   . 8B70 30        MOV ESI,DWORD PTR DS:[EAX+30]
    7C812DC4   . 64:A1 18000000 MOV EAX,DWORD PTR FS:[18]
    7C812DCA   . 8945 E0        MOV DWORD PTR SS:[EBP-20],EAX
    7C812DCD   . FF15 BC10807C  CALL DWORD PTR DS:[<&ntdll.RtlAcquirePeb>;  ntdll.RtlAcquirePebLock
    7C812DD3   . 8365 FC 00     AND DWORD PTR SS:[EBP-4],0
    7C812DD7   . 6A 00          PUSH 0
    7C812DD9   . 6A 01          PUSH 1
    7C812DDB   . FF76 40        PUSH DWORD PTR DS:[ESI+40]
    7C812DDE   . 8B3D 1815807C  MOV EDI,DWORD PTR DS:[<&ntdll.RtlFindCle>;  ntdll.RtlFindClearBitsAndSet
    7C812DE4   . FFD7           CALL EDI                                 ;  ntdll.7C910228; <&ntdll.RtlFindClearBitsAndSet>
    7C812DE6   . 8BD8           MOV EBX,EAX
    7C812DE8   . 895D E4        MOV DWORD PTR SS:[EBP-1C],EBX
    7C812DEB   . 83FB FF        CMP EBX,-1
    7C812DEE   . 0F84 8A1A0300  JE kernel32.7C84487E
    7C812DF4   . 8B45 E0        MOV EAX,DWORD PTR SS:[EBP-20]
    7C812DF7   . 83A498 100E000>AND DWORD PTR DS:[EAX+EBX*4+E10],0
    7C812DFF   > 834D FC FF     OR DWORD PTR SS:[EBP-4],FFFFFFFF
    7C812E03   . E8 19000000    CALL kernel32.7C812E21
    7ffde000+e10 + index 1 * 4 ...so what checks the TlsBitmap...in order to avoid this occurance o0.
    No hate for the lost children;
    more love for the paths we walk,
    'words' shatter the truth we seek.
    from the heart and mind of Me
    me, to you.. down and across

    No more words from me, to you...
    Hate and love shatter the heart and Mind of Me.
    For the Lost Children;For the paths we walk; the real truth we seek!

  2. #2
    BanMe
    7ffde000 - TEB(applied ASLR, R/W). USER_SHARED_DATA this is the last page in address space, ie address 7ffe0000(R/E).

    Code:
    7C812DC4   . 64:A1 18000000 MOV EAX,DWORD PTR FS:[18]
    7C812DCA   . 8945 E0        MOV DWORD PTR SS:[EBP-20],EAX
    This is a reference to itself, ie TEB.Tib.Self

    Offset 0xE10 - this field TlsExpansionSlots in TEB.

    Code:
    DWORD
    APIENTRY
    TlsAlloc(
        VOID
        )
    
    /*++
    
    Routine Description:
    
        A TLS index may be allocated using TlsAlloc.  Win32 garuntees a
        minimum number of TLS indexes are available in each process.  The
        constant TLS_MINIMUM_AVAILABLE defines the minimum number of
        available indexes.  This minimum is at least 64 for all Win32
        systems.
    
    Arguments:
    
        None.
    
    Return Value:
    
        Not-0xffffffff - Returns a TLS index that may be used in a
            subsequent call to TlsFree, TlsSetValue, or TlsGetValue.  The
            storage associated with the index is initialized to NULL.
    
        0xffffffff - The operation failed. Extended error status is available
            using GetLastError.
    
    
    --*/
    
    {
        PPEB Peb;
        PTEB Teb;
        DWORD Index;
    
        Peb = NtCurrentPeb();
        Teb = NtCurrentTeb();
    
        RtlAcquirePebLock();
        try {
    
            Index = RtlFindClearBitsAndSet((PRTL_BITMAP)Peb->TlsBitmap,1,0);
            if ( Index == 0xffffffff ) {
                Index = RtlFindClearBitsAndSet((PRTL_BITMAP)Peb->TlsExpansionBitmap,1,0);
                if ( Index == 0xffffffff ) {
                    BaseSetLastNTError(STATUS_NO_MEMORY);
                    }
                else {
                    if ( !Teb->TlsExpansionSlots ) {
                        Teb->TlsExpansionSlots = RtlAllocateHeap(
                                                    RtlProcessHeap(),
                                                    MAKE_TAG( TMP_TAG ) | HEAP_ZERO_MEMORY,
                                                    TLS_EXPANSION_SLOTS * sizeof(PVOID)
                                                    );
                        if ( !Teb->TlsExpansionSlots ) {
                            RtlClearBits((PRTL_BITMAP)Peb->TlsExpansionBitmap,Index,1);
                            Index = 0xffffffff;
                            BaseSetLastNTError(STATUS_NO_MEMORY);
                            return Index;
                            }
                        }
                    Teb->TlsExpansionSlots[Index] = NULL;
                    Index += TLS_MINIMUM_AVAILABLE;
                    }
                }
            else {
                Teb->TlsSlots[Index] = NULL;
                }
            }
        finally {
            RtlReleasePebLock();
            }
    #if DBG
        Index |= TLS_MASK;
    #endif
        return Index;
    }
    
    LPVOID
    APIENTRY
    TlsGetValue(
        DWORD dwTlsIndex
        )
    
    /*++
    
    Routine Description:
    
        This function is used to retrive the value in the TLS storage
        associated with the specified index.
    
        If the index is valid this function clears the value returned by
        GetLastError(), and returns the value stored in the TLS slot
        associated with the specified index.  Otherwise a value of NULL is
        returned with GetLastError updated appropriately.
    
        It is expected, that DLLs will use TlsAlloc and TlsGetValue as
        follows:
    
          - Upon DLL initialization, a TLS index will be allocated using
            TlsAlloc.  The DLL will then allocate some dynamic storage and
            store its address in the TLS slot using TlsSetValue.  This
            completes the per thread initialization for the initial thread
            of the process.  The TLS index is stored in instance data for
            the DLL.
    
          - Each time a new thread attaches to the DLL, the DLL will
            allocate some dynamic storage and store its address in the TLS
            slot using TlsSetValue.  This completes the per thread
            initialization for the new thread.
    
          - Each time an initialized thread makes a DLL call requiring the
            TLS, the DLL will call TlsGetValue to get the TLS data for the
            thread.
    
    Arguments:
    
        dwTlsIndex - Supplies a TLS index allocated using TlsAlloc.  The
            index specifies which TLS slot is to be located.  Translating a
            TlsIndex does not prevent a TlsFree call from proceding.
    
    Return Value:
    
        NON-NULL - The function was successful. The value is the data stored
            in the TLS slot associated with the specified index.
    
        NULL - The operation failed, or the value associated with the
            specified index was NULL.  Extended error status is available
            using GetLastError.  If this returns non-zero, the index was
            invalid.
    
    --*/
    {
        PTEB Teb;
        LPVOID *Slot;
    
    #if DBG
        // See if the Index passed in is from TlsAlloc or random goo...
        ASSERTMSG( "BASEDLL: Invalid TlsIndex passed to TlsGetValue\n", (dwTlsIndex & TLS_MASK));
        dwTlsIndex &= ~TLS_MASK;
    #endif
    
        Teb = NtCurrentTeb();
    
        if ( dwTlsIndex < TLS_MINIMUM_AVAILABLE ) {
            Slot = &Teb->TlsSlots[dwTlsIndex];
            Teb->LastErrorValue = 0;
            return *Slot;
            }
        else {
            if ( dwTlsIndex >= TLS_MINIMUM_AVAILABLE+TLS_EXPANSION_SLOTS ) {
                BaseSetLastNTError(STATUS_INVALID_PARAMETER);
                return NULL;
                }
            else {
                Teb->LastErrorValue = 0;
                if ( Teb->TlsExpansionSlots ) {
                    return  Teb->TlsExpansionSlots[dwTlsIndex-TLS_MINIMUM_AVAILABLE];
                    }
                else {
                    return NULL;
                    }
                }
            }
    }
    
    BOOL
    APIENTRY
    TlsSetValue(
        DWORD dwTlsIndex,
        LPVOID lpTlsValue
        )
    
    /*++
    
    Routine Description:
    
        This function is used to store a value in the TLS storage associated
        with the specified index.
    
        If the index is valid this function stores the value and returns
        TRUE. Otherwise a value of FALSE is returned.
    
        It is expected, that DLLs will use TlsAlloc and TlsSetValue as
        follows:
    
          - Upon DLL initialization, a TLS index will be allocated using
            TlsAlloc.  The DLL will then allocate some dynamic storage and
            store its address in the TLS slot using TlsSetValue.  This
            completes the per thread initialization for the initial thread
            of the process.  The TLS index is stored in instance data for
            the DLL.
    
          - Each time a new thread attaches to the DLL, the DLL will
            allocate some dynamic storage and store its address in the TLS
            slot using TlsSetValue.  This completes the per thread
            initialization for the new thread.
    
          - Each time an initialized thread makes a DLL call requiring the
            TLS, the DLL will call TlsGetValue to get the TLS data for the
            thread.
    
    Arguments:
    
        dwTlsIndex - Supplies a TLS index allocated using TlsAlloc.  The
            index specifies which TLS slot is to be located.  Translating a
            TlsIndex does not prevent a TlsFree call from proceding.
    
        lpTlsValue - Supplies the value to be stored in the TLS Slot.
    
    Return Value:
    
        TRUE - The function was successful. The value lpTlsValue was
            stored.
    
        FALSE - The operation failed. Extended error status is available
            using GetLastError.
    
    --*/
    
    {
        PTEB Teb;
    
    #if DBG
        // See if the Index passed in is from TlsAlloc or random goo...
        ASSERTMSG( "BASEDLL: Invalid TlsIndex passed to TlsSetValue\n", (dwTlsIndex & TLS_MASK));
        dwTlsIndex &= ~TLS_MASK;
    #endif
    
        Teb = NtCurrentTeb();
    
        if ( dwTlsIndex >= TLS_MINIMUM_AVAILABLE ) {
            dwTlsIndex -= TLS_MINIMUM_AVAILABLE;
            if ( dwTlsIndex < TLS_EXPANSION_SLOTS ) {
                if ( !Teb->TlsExpansionSlots ) {
                    RtlAcquirePebLock();
                    if ( !Teb->TlsExpansionSlots ) {
                        Teb->TlsExpansionSlots = RtlAllocateHeap(
                                                    RtlProcessHeap(),
                                                    MAKE_TAG( TMP_TAG ) | HEAP_ZERO_MEMORY,
                                                    TLS_EXPANSION_SLOTS * sizeof(PVOID)
                                                    );
                        if ( !Teb->TlsExpansionSlots ) {
                            RtlReleasePebLock();
                            BaseSetLastNTError(STATUS_NO_MEMORY);
                            return FALSE;
                            }
                        }
                    RtlReleasePebLock();
                    }
                Teb->TlsExpansionSlots[dwTlsIndex] = lpTlsValue;
                }
            else {
                BaseSetLastNTError(STATUS_INVALID_PARAMETER);
                return FALSE;
                }
            }
        else {
            Teb->TlsSlots[dwTlsIndex] = lpTlsValue;
            }
        return TRUE;
    }
    
    BOOL
    APIENTRY
    TlsFree(
        DWORD dwTlsIndex
        )
    
    /*++
    
    Routine Description:
    
        A valid TLS index may be free'd using TlsFree.
    
    Arguments:
    
        dwTlsIndex - Supplies a TLS index allocated using TlsAlloc.  If the
            index is a valid index, it is released by this call and is made
            available for reuse.  DLLs should be carefull to release any
            per-thread data pointed to by all of their threads TLS slots
            before calling this function.  It is expected that DLLs will
            only call this function (if at ALL) during their process detach
            routine.
    
    Return Value:
    
        TRUE - The operation was successful.  Calling TlsTranslateIndex with
            this index will fail.  TlsAlloc is free to reallocate this
            index.
    
        FALSE - The operation failed. Extended error status is available
            using GetLastError.
    
    --*/
    
    {
        PPEB Peb;
        BOOLEAN ValidIndex;
        PRTL_BITMAP TlsBitmap;
        NTSTATUS Status;
        DWORD Index2;
    
    #if DBG
        // See if the Index passed in is from TlsAlloc or random goo...
        ASSERTMSG( "BASEDLL: Invalid TlsIndex passed to TlsFree\n", (dwTlsIndex & TLS_MASK));
        dwTlsIndex &= ~TLS_MASK;
    #endif
    
        Peb = NtCurrentPeb();
    
        RtlAcquirePebLock();
        try {
    
            if ( dwTlsIndex >= TLS_MINIMUM_AVAILABLE ) {
                Index2 = dwTlsIndex - TLS_MINIMUM_AVAILABLE;
                if ( Index2 >= TLS_EXPANSION_SLOTS ) {
                    ValidIndex = FALSE;
                    }
                else {
                    TlsBitmap = (PRTL_BITMAP)Peb->TlsExpansionBitmap;
                    ValidIndex = RtlAreBitsSet(TlsBitmap,Index2,1);
                    }
                }
            else {
                TlsBitmap = (PRTL_BITMAP)Peb->TlsBitmap;
                Index2 = dwTlsIndex;
                ValidIndex = RtlAreBitsSet(TlsBitmap,Index2,1);
                }
            if ( ValidIndex ) {
    
                Status = NtSetInformationThread(
                            NtCurrentThread(),
                            ThreadZeroTlsCell,
                            &dwTlsIndex,
                            sizeof(dwTlsIndex)
                            );
                if ( !NT_SUCCESS(Status) ) {
                    BaseSetLastNTError(STATUS_INVALID_PARAMETER);
                    return FALSE;
                    }
    
                RtlClearBits(TlsBitmap,Index2,1);
                }
            else {
                BaseSetLastNTError(STATUS_INVALID_PARAMETER);
                }
            }
        finally {
            RtlReleasePebLock();
            }
        return ValidIndex;
    }

  3. #3
    |< x != '+' BanMe's Avatar
    Join Date
    Oct 2008
    Location
    Farmington NH
    Posts
    510
    Blog Entries
    4
    No, my description was inaccurate and my insanity got to me that late at night.

    What I meant in my ramblings, I set the _tls_data DWORD in the TLS SEGMENT to equal this TlsExpansionSlot,but without this call to TlsAlloc the area generates a access violation, which area of the ldr or event triggers causes this effect? it certainly is not in TlsAlloc and associates.. ;D

    regards BanMe
    No hate for the lost children;
    more love for the paths we walk,
    'words' shatter the truth we seek.
    from the heart and mind of Me
    me, to you.. down and across

    No more words from me, to you...
    Hate and love shatter the heart and Mind of Me.
    For the Lost Children;For the paths we walk; the real truth we seek!

  4. #4
    It seems to me that you do not understand what you say. Probably the reason for this - the new year

  5. #5
    |< x != '+' BanMe's Avatar
    Join Date
    Oct 2008
    Location
    Farmington NH
    Posts
    510
    Blog Entries
    4
    oh i see what u mean, my error was I assumed the index was 0.. o0

    Code such as this does work..

    Code:
    OPTION DOTNAME
    .TLS	SEGMENT DWORD FLAT PUBLIC 'TLS'
    	_tls_start LABEL DWORD
    	_tls_data DWORD   07FFDEE10h
    	_tls_end LABEL DWORD
    .TLS	ENDS
    OPTION NODOTNAME
    Code:
    TlsWrite:
    	push ecx
    	mov ecx,TLS_ENGINE.TlsData[edx];_tls_data address to pointer
    	mov ecx,[ecx];read address to get Pointer
    	mov ebx,TLS_ENGINE.TlsIndex[edx] ; get 0 Index from self
    	mov ebx, dword ptr [ebx]
    	inc ebx ;inc index to write to ExpansionSlot..
    	mov dword ptr [ecx+ebx*4], eax
    	mov ecx,TLS_ENGINE.TlsIndex[edx]
    	mov dword ptr [ecx],ebx
    	pop ecx
    	mov eax,ecx
    	jmp TlsReturn
    TlsRead:
    	push ecx
    	mov ecx,TLS_ENGINE.TlsData[edx]
    	mov ecx,[ecx]
    	mov eax,TLS_ENGINE.ReadIndex[edx]
    	mov ebx,TLS_ENGINE.TlsIndex[edx]
    	mov ebx,dword ptr [ebx]
    	cmp eax,ebx
    	jge TlsReturn
    	mov eax,dword ptr [ecx+eax*4]
    	pop ecx
    but then my question is why is the TlsBitmap modified. what uses this...

    wait alex!!! my real answer is, what is 'LdrpTlsCount'!! and the address please.. for 200$...xD

    It is new years and I was searching this functionality in reactos, but wanted to find it in my own ntdll, i started by looking for code sequences, that i thought might be in this. that did work, then I got the idea instead of looking for that look for something that 'has' to be there.. ie..
    Code:
    7C9227AE   . 50             PUSH EAX
    7C9227AF   . 6A 09          PUSH 9
    7C9227B1   . 6A 01          PUSH 1
    7C9227B3   . FF77 18        PUSH DWORD PTR DS:[EDI+18]
    7C9227B6   . E8 8BDBFEFF    CALL ntdll.RtlImageDirectoryEntryToData
    So I searched for this call and had many hits some interesting ones.. but tls was my main goal so I looked for IMAGE_DIRECTORY_ENTRY_TLS or the 9 u see above..

    there are 2.. so this cut it down o0.. so there 2 occurances in ntdll access trying to 'access' the .tls section of a module.

    But the one I am interested in is the one That is called LdrpInitializeTlsForProcess...to make sure of what happens when my exe with emulated tls gets handled correctly and what can be done if it does not get handled correctly..

    *side note to niaren* What happens if the image has tls functions and these are not included in the reloc section.. I saw a function that relocs Tls as well somewhere but just noted it for interest..
    Last edited by BanMe; January 1st, 2011 at 03:36.
    No hate for the lost children;
    more love for the paths we walk,
    'words' shatter the truth we seek.
    from the heart and mind of Me
    me, to you.. down and across

    No more words from me, to you...
    Hate and love shatter the heart and Mind of Me.
    For the Lost Children;For the paths we walk; the real truth we seek!

  6. #6
    BanMe

    Optimal search using the message logger. Logger prints messages if ntdll!ShowSnaps. In this case, you need two messages:
    LdrpInitializeTls: ASCII "LDR: Tls Found in %wZ at %p",LF
    LdrpAllocateTls: ASCII "LDR: TlsVector %x Index %d = %x copied from %x to %x",LF

    LdrpCallTlsInitializers: ASCII "LDR: Tls Callbacks Found. Imagebase %p Tls %p CallBacks %p",LF

    Possible find the code references to these lines, ie a reference to the body of the required procedure. To determine the beginning of the procedure is acceptable to use the analysis of the graph. When using the GPE pseudocode as follows:
    Code:
    PARSE_CALLBACK_ROUTINE(GE:PGRAPH_ENTRY, CallList:PCALL_ENTRY):
       if GE.Type = TYPE_CALL
          if GE.BranchAddress = @DbgPrint()
             GE = GE.Blink
             if GE.Type = TYPE_LINE
                if BYTE[GE.Address] = 0x68
                      if StrCmp(TargetMessage, DWORD[GE.Address + 1])
                         Routine = CallList[0]
    Code for it:
    Code:
    .data
    NtBase    PVOID ?
    NtLimit    PVOID ?
    gRef1    PCALL_HEADER ?
    gRef2    PCALL_HEADER ?
    
    .code
    $Fn1    CHAR "Tls Found in %wZ",0    ; LdrpInitializeTls()
    $Fn2    CHAR "TlsVector %x",0        ; LdrpAllocateTls()
    
    ; o GCBE_PARSE_OPENLIST
    ;
    PARSE_CALLBACK_ROUTINE proc uses ebx Graph:PVOID,
     GraphEntry:PVOID,
     SubsList:PVOID,
     SubsCount:ULONG,
     PreOrPost:BOOLEAN,
     Context:PVOID
        mov ebx,GraphEntry
        mov eax,dword ptr [ebx + EhEntryType]
        and eax,TYPE_MASK
        cmp eax,HEADER_TYPE_CALL
        jne @f
    ; (!BRANCH_DEFINED_FLAG)
        mov ecx,dword ptr [ebx + EhAddress]
        cmp byte ptr [ecx],0E8H
        jne @f
        mov eax,dword ptr [ebx + EhBranchAddress]
        cmp dword ptr [_imp__DbgPrint],eax
        jne @f
        cmp byte ptr [ecx - 5],68H
        jne @f
        mov ebx,dword ptr [ecx - 4]
        cmp NtBase,ebx
        jnb @f
        cmp NtLimit,ebx
        jbe @f
        cmp gRef1,NULL
        jne Check2
        invoke InString, 1, Ebx, addr $Fn1
        test eax,eax
        jle Check2
        mov eax,SubsList
        mov eax,dword ptr [eax]
        mov gRef1,eax
    @@:
        xor eax,eax
    Exit:
        ret
    xBreak:
        mov eax,STATUS_WAIT_1
        jmp Exit
    Check2:
        cmp gRef2,NULL
        jne xBreak
        invoke InString, 1, Ebx, addr $Fn2
        test eax,eax
        jle @b
        mov eax,SubsList
        mov eax,dword ptr [eax]
        mov gRef2,eax
        jmp @b
    PARSE_CALLBACK_ROUTINE endp
    Graph is created for LdrInitializeThunk().

    With dynamic initialization TLS directory is added to the module, as I can remember at this address range is not checked, so the directory can be outside of the module. You can hide a directory of destroying the module and processed #AV, but this is unnecessary.

  7. #7
    |< x != '+' BanMe's Avatar
    Join Date
    Oct 2008
    Location
    Farmington NH
    Posts
    510
    Blog Entries
    4
    lol I missed this, somehow, ty for the examples :].
    No hate for the lost children;
    more love for the paths we walk,
    'words' shatter the truth we seek.
    from the heart and mind of Me
    me, to you.. down and across

    No more words from me, to you...
    Hate and love shatter the heart and Mind of Me.
    For the Lost Children;For the paths we walk; the real truth we seek!

Similar Threads

  1. access violation in olly
    By icegood in forum OllyDbg Support Forums
    Replies: 1
    Last Post: March 16th, 2012, 03:46
  2. Handling access violation exceptions
    By leakymingebox in forum Advanced Reversing and Programming
    Replies: 3
    Last Post: March 7th, 2010, 02:35
  3. How to write spaghetti code
    By corus-corvax in forum Advanced Reversing and Programming
    Replies: 13
    Last Post: August 26th, 2005, 01:11
  4. Ollydebug access violation
    By Quell in forum Tools of Our Trade (TOT) Messageboard
    Replies: 4
    Last Post: December 30th, 2004, 18:24
  5. Need Help with "access violation...."
    By zambuka42 in forum Advanced Reversing and Programming
    Replies: 16
    Last Post: May 5th, 2004, 17:53

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •