http://skypher.com/wiki/index.php/Hacking/Shellcode/GetPC
GetPC (get Program Counter, also known as GetEIP on x86) code is code that determines its own location in a process' address space. It is commonly used in code that needs to reference itself, for instance in self-decoding and self-modifying code.
CALL GetPC
The easiest way to implement GetPC code on x86 is using the CALL
instruction, like so:
$+0: E8 00000000 CALL $+5 ; PUSH $+5 onto the stack
$+5: 59 POP ECX ; ECX = $+5
$+6: ...shellcode...
Because the argument to the CALL instruction is the offset of the code to call, in this case 0, this code contains null
bytes. Unfortunately, it is often not possible or practical to inject
null bytes into a target process during exploitation. A common trick to
get around this is to make the CALL
point to a lower address address, making the offset negative, like so:
$+0 EB XX JMP SHORT $+N ; Jump to the call instruction
$+5: 59 POP ECX ; ECX = $+N+5
$+6: ...shellcode...
$+N: E8 FFFFFFXX CALL $+5 ; PUSH $+N+5 onto the stack and jump back to $+5
As you can see, this code is null free but this code has two drawbacks:
- It is 2 bytes larger than the first example.
- The shellcode between the POP and CALL instruction can only be
126 bytes, if you need more room, you will have to jump over the call
and put the remainder after it.
There is a second trick to get around these two problems:
$+0 EB FFFFFFFF CALL $+4 ; PUSH $+5 onto the stack and jump to $+4
$+5: C8 59XX XX ENTER XX59,XX ; Does not get executed like this; see below.
When this code executes, the CALL will jump to the last byte of its
own instruction. The code executed after the CALL will therefore be:
$+4: FFC8 DEC ECX ; Does nothing useful; can be considered a NOP.
$+6: 59 POP ECX ; ECX = $+5
$+7: ...shellcode...
The above code is only 1 byte larger than the first GetPC and puts no constraints of the shellcode following it.
FSTENV GetPC
[todo:References]
A way to retrieve the value of EIP on x86 systems is to use the x87 FSTENV
instruction to store the state of the x87 floating point chip after issuing a FLDZ
instruction. The structure store in memory by FSTENV
will then contain the address of the FLDZ
instruction at offset 0x0C of the structure:
$+0 D9EE FLDZ ; Floating point stores $+0 in its environment
$+2 D974E4 F4 FSTENV SS:[ESP-0xC] ; Save environment at ESP-0xC; now [ESP] = $+0
$+6 59 POP ECX ; ECX = $+0
This method is also null free and uses the same amount of bytes as the last CALL
example.
SEH GetPC
[todo:References]
A third way to write GetPC code is to use the Windows specific
Structure Exception Handler (SEH). When an exception happens in a
process on Windows, a structured exception is created by the operating
system and passed to the first SEH handler to see if it can handle it.
If not, the second SEH handler is asked, etc... if no SEH handler
handles the exception, the program is terminated because of an unhandled
exception. Whenever a structure exception handler is called, it is
passed (pointers to) information about the exception on the stack. This
information includes the address in memory of the instruction that
caused the exception.
It is relatively simple to register a structured exception
handler with the OS. If a shellcode can generate a small structured
exception handler at a known location in memory and register it before
causing an exception, this small structured exception handler would get
executed. It could determine the address of the instruction that caused
the exception and jump back to the next instruction (the one immediately
following it). The code would then continue as normal, only now knowing
exactly where it is.[todo:Write an example]
Because the SEH was abused heavily by exploits for various
purposes, Microsoft has introduced additional checks on the SEH as
mitigation against this abuse with each service pack of Windows XP.
These have made writing working SEH GetPC increasingly harder. On
Windows Vista, it seems these mitigation make it impractical of not
impossible to write working SEH GetPC code. However, it is still
possible to write SEH GetPC code on Windows XP sp3. It's even possible
to do so using only alphanumeric instructions, which is used in ALPHA3 to create alphanumeric SEH GetPC code.