Ways of Achieving Portability

The technique of creating relocatable code is closely related to the architecture of the specific microprocessor. In particular, the x86 line supports the following relative commands: push/pop, call , and jx . Good old PDP-11 was considerably richer in this respect. Most pleasantly, it allowed the instruction-pointer register to be used in address expressions, thus considerably simplifying tasks of hackers. Unfortunately, however, we do not choose processors. It is the processor that chooses us.

The conditional jump commands, jx , are always relative, because the command operand specifies the difference between the target address and the address of the next command . Because of this, jumps are always relocatable. Two types of operands are supported: BYTE and WORD/DWORD . Both types are signed, which means that it is possible to jump both forward and backward (in the latter case, the operand becomes negative).

Unconditional jump command, jmp , can be both absolute and relative. Relative commands start from the EBh opcode (operand of the BYTE type) or from the E9h opcode (operand of the WORD/DWORD type). Absolute unconditional jumps start from EAh , and the operand is written in the following format: segment: offset . There are also indirect commands that pass control to the pointer located at an absolute address, or to the register. The latter is the most convenient and can be carried out approximately as follows : mov eax, absolute address/jmp eax .

The command for calling the call subroutine behaves the same way as jmp except that it is encoded by different opcodes ( E8h is the relative WORD/DWORD operand, and FFh /2 is the indirect call). Before passing control to the target address, this command pushes the return address onto the top of the stack. This return address represents the address of the command directly following the call command.

Provided that the shellcode is located in the stack (and if the local buffers overflow, it falls exactly there), the hacker can use the ESP register as a base. However, for this purpose, the current ESP value must be known, and this is not always the case. To determine the current value of the instruction pointer register, it is enough to issue the near call command and retrieve the address using the pop command. Usually, the code that achieves this goal appears as shown in Listing 11.1.

Listing 11.1: Determining the location of the shellcode B memory
image from book
 00000000: E800000000 CALL  000000005 ; Push EIP + sizeof(call)                                      ; into the stack. 00000005: 5D         POP   EBP       ; Now the EBP register contains                                      ; the current EIP. 
image from book
 

The code provided in Listing 11.1 contains zeros, which, as you recall, are not tolerable in most cases in the shellcode. Therefore, to eliminate them, it is necessary to redirect call "backward" (Listing 11.2).

Listing 11.2: Eliminating parasitic zeros from the shellcode
image from book
 00000000  EB04       JMPS 000000006 ; Short jump to call 00000002  5D         POP  EBP       ; EBP contains the address                                     ; next to call. 00000003  90         NOP            ; \ 00000004  90         NOP            ;  +- Actual shellcode 00000005  90         NOP            ; / 00000006  E8F7FFFFFF CALL 000000002 ; Push the address                                     ; of the next command                                     ; into the stack. 
image from book
 


Shellcoder's Programming Uncovered
Shellcoders Programming Uncovered (Uncovered series)
ISBN: 193176946X
EAN: 2147483647
Year: 2003
Pages: 164

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net