Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie
Hi there,
There is an issue with role permissions that is being worked on at the moment.
If you are having trouble with access or permissions on regional forums please post here to get access: https://www.boards.ie/discussion/2058365403/you-do-not-have-permission-for-that#latest

Subtle SEH

  • 18-07-2009 1:35am
    #1
    Closed Accounts Posts: 1,567 ✭✭✭


    rgb wrote simple and sweet article about SEH here

    What is it?

    Everyone knows about Structured Exception Handling these days. First demonstrated in the Cabanas virus in 1998 by jqwerty, now many viruses and other applications use it for obfuscating code and anti-debugging tricks. It usually looks something like this:

    [PHP]
    call set_seh
    ;handler code would go here
    set_seh:
    push dword ptr fs:[0]
    mov dword ptr fs:[0], esp
    ;code to produce exception would go here [/PHP]

    So now if we see such a code sequence we know to expect an anti-debugging trick is coming soon. Probably some emulators have recogniser code for this thing and trigger some heuristics, too. So I tried to think of a way to register a Structured Exception Handler without obvious write to fs:0. Here are some of those ways. First way gets base of fs from TIB.

    [PHP]
    mov eax, dword ptr fs:[tibSelf]
    call set_seh
    ;handler code would go here
    set_seh:
    push dword ptr ds:[eax]
    mov dword ptr ds:[eax], esp
    int 3 ;cause exception[/PHP]

    Second way gets base of fs from descriptor table.

    [PHP]
    lea eax, dword ptr [esp - 2]
    push eax
    push fs
    push -2 ;GetCurrentThread()
    call GetThreadSelectorEntry
    pop eax ;bits 00-23 of base
    bswap eax
    mov al, byte ptr [esp + 1] ;bits 24-31 of base
    bswap eax
    call set_seh
    ;handler code would go here
    set_seh:
    push dword ptr ds:[eax]
    mov dword ptr ds:[eax], esp
    int 3 ;cause exception[/PHP]

    Third way gets base of fs from descriptor table, using hard-coded fs value, so there is no fs reference.

    [PHP]
    call skip_k32
    db "kernel32", 0
    skip_k32:
    call GetModuleHandleA
    call skip_iswow
    db "IsWow64Process", 0
    skip_iswow:
    push eax
    call GetProcAddress
    xchg ecx, eax
    jecxz not_xp ;XP and later only
    push eax
    push esp
    push -1
    call ecx
    pop ecx
    not_xp:
    lea eax, dword ptr [esp - 2]
    push eax
    push 3bh ;all 32-bit Windows
    jecxz not_v64
    pop eax
    push 53h ;Vista64
    not_v64:
    push -2 ;GetCurrentThread()
    call GetThreadSelectorEntry
    pop eax
    bswap eax
    mov al, byte ptr [esp + 1]
    bswap eax
    call set_seh
    ;handler code would go here
    set_seh:
    push dword ptr ds:[eax]
    mov dword ptr ds:[eax], esp
    int 3 ;cause exception[/PHP]

    but all of these ways have obvious push and mov using esp. There are some other ways, too, such as NtSetLdtEntries(), but I was told that it does not work on 64-bit Windows. Anyway, altering fs or gs introduces race condition against thread switch. When switch occurs, fs and gs values are restored to their proper values. Then I found another way. This way writes to fs using ss:esp. The code must be in writable memory because it is also used for stack. Altering ss has no race condition because only an exception (including debugger single-step, heh!) will change the value back.

    [PHP]
    push 8 ;replaced by "previous SEH"
    pop eax ;replaced by "previous SEH"
    call delta ;instruction must end on dword-aligned offset
    ;replaced by handler address
    ife DEP ;you must define this variable 0 or 1
    push -1 ;set "previous SEH"
    ;if hardware DEP is not enabled by Windows for process, then stack chain is checked
    ;all entries must be on stack, and finish with -1 entry
    else
    push eax ;set "previous SEH", just saves one byte, no other effect
    ;if hardware DEP is enabled by Windows for process, then stack chain is not checked
    ;Windows assumes that data execution will cause exception
    endif
    mov ecx, fs ;push would require extra dword before previous SEH
    mov ss, ecx ;emulator killer, and anti-single-step, too ;)
    xchg esp, eax ;fs:8
    call set_seh ;change stack limit so our code looks like stack
    set_seh:
    push eax ;set new SEH
    ;cannot appear after actual handler, otherwise handler looks like is on stack
    ;can restore ss here if you want to delay exception
    mov esp, ebp ;esp must be valid on except. Windows will restore ss for us
    ;cannot use leave to pop from stack because current ss limit is too small
    ;to delay exception, add jmp here to somewhere else
    delta:
    pop esp ;cause exception on second pass
    call esp ;set handler address
    ;handler code would go here[/PHP]

    No obvious memory writes.

    Using the SS segment will allow us to POP the previous SEH value off stack when ESP is set to 0

    [PHP]
    push fs ; save fs
    pop ss ; ss = fs ; no race condition
    xor esp,esp ; esp = fs:[0]
    pop eax ; eax = previous SEH[/PHP]

    What about using STOSD or MOVSD?

    These opcodes perform write operations, which if using another selector is disallowed.

    You may read of course using LODSD, so its not absolutely useless... you just need to remember unless its ES or DS default selectors, a write is illegal.

    The same is true for atomic operations using CMPXCHG or XCHG either with or without LOCK prefix.


Advertisement