Uninformed: Informative Information for the Uninformed

Vol 1» 2005.May


Index Registers

On the PowerPC platform, immediate values are encoded using all 16 bits. If the assembled value of your immediate contains a NULL, you will need to find another way to load it into the target register. The most common technique is to first load a NULL-free value into a register, then substract that value minus the difference to your immediate.

;;
;; Demonstrate index register usage
;;
main:
	li r7, 1999          ; place a NULL-free value into the index
	subi r5, r7, 1999-1  ; substract our value minus the target
	                     ; the r5 register is now set to 1

If you have a rough idea of the immediate values you will need in your shellcode, you can take this a step further. Set your initial index register to a value, that when decremented by the immediate value, actually results in a character of your choice. If you have two distant ranges (1-10 and 50-60), then consider using two index registers. The example below demonstrates an index register that works for the system call number as well as the arguments, leaving the assembled bytes NULL-free. As you can see, besides the four bytes required to set the index register, this method does not significantly increase the size of the code.

;;
;; Create a TCP socket without NULL bytes
;;
main:
	li r7, 0x3330           ; 0x38e03330 = NULL-free index value
	subi r0, r7, 0x3330-97  ; 0x3807cd31 = system call for sys_socket
	subi r3, r7, 0x3330-2   ; 0x3867ccd2 = socket domain
	subi r4, r7, 0x3330-1   ; 0x3887ccd1 = socket type
	subi r5, r7, 0x3330-6   ; 0x38a7ccd6 = socket protocol
	.long 0x45585037        ; patched 'sc' instruction