Web 50

편지를 쓰다 말고 훈련소에 끌려 갔다고 해서 .swp 파일인 것을 짐작 할 수 있었다.

http://218.158.141.133/.index.php.swp이 링크로 들어가면 서버 사이드 스크립트가 노출된다.

Magic hash 문제다.

입력한 한 문자열 + “S@L7”을 md5 encrypt 한 값과 0e123142351이 같으면 된다.

그러므로 입력한 문자열 + “S@L7” 의 md5 hash 값은 0e + 숫자 30바이트이면 된다.

import hashlib
import re
import string
ALLOWED_CHARACTERS = string.hexdigits
NUMBER_OF_CHARACTERS = len(ALLOWED_CHARACTERS)
def characterToIndex(char):
return ALLOWED_CHARACTERS.index(char)
def indexToCharacter(index):
if NUMBER_OF_CHARACTERS <= index:
raise ValueError("Index out of range.")
else:
return ALLOWED_CHARACTERS[index]
def next(string):
if len(string) <= 0:
string.append(indexToCharacter(0))
else:
string[0] = indexToCharacter((characterToIndex(string[0]) + 1) % NUMBER_OF_CHARACTERS)
if characterToIndex(string[0]) is 0:
return list(string[0]) + next(string[1:])
return string
def main():
sequence = list()
while True:
sequence = next(sequence)
tmp = ''.join(i for i in sequence)
tmp += 'S@L7'
m = hashlib.md5()
m.update(tmp)
md5string=m.hexdigest()
if md5string[2:].isdigit() == True and md5string[:2] == '0e':
print md5string + " : " + tmp
if __name__ == "__main__":
main()

이렇게 문자열Brute Force Attack 해서 입력한 값의 hash 값이 0e + 숫자가 나올 때까지 돌렸다.

한 2분정도 지나니까 403a8b가 나왔다. 이거 넣어주면 된다.

FLAG : YISF{Ma9ic_L3t7er_fr0m_Pr1v4te}


Reversing 50

현재 경로 가져와서 경로를 저장한다. 프로그램의 경로를 strncmp 분기 다 맞춰주면 된다.

그러면 /aaaaaYISF/TOP_SECRET/TOP_SEflag 이런 경로까지 가면 id, password를 입력할 수 있는 창이 나오게된다.

__int64 __fastcall main(__int64 a1, char **a2, char **a3)
{
  char *v3; // ST20_8
  signed __int64 v4; // rdi
  char *v6; // [rsp+18h] [rbp-A8h]
  char buf; // [rsp+30h] [rbp-90h]
  unsigned __int64 v8; // [rsp+B8h] [rbp-8h]

  v8 = __readfsqword(0x28u);
  memset(&buf, 0, 0x80uLL);
  v6 = strrchr(*a2, 47) + 1;
  v3 = getcwd(&buf, 0x80uLL);
  printf("path : %s\nfilename : %s\n\n", v3, v6, a2);
  sub_B2F(v3, v6);
  if ( dword_20240C == 1 )
  {
    v4 = (signed __int64)(v6 + 6);
    if ( !strncmp(v6 + 6, "flag", 4uLL) )
    {
      ++dword_20240C;
      sub_DE7(v4, "flag");
    }
    sub_D64(v4, "flag");
  }
  return 0LL;
}

id는The_World_Best_Programmer인지 비교하고 password는 qwe123 이면 success!!가 뜬다. 그리고 어떠한 변수 값이 증가하면서 어떤 if문에 들어가서v6+6의 값이 flag인지 비교한다.

이건 동적디버깅해서 위치 어디인지 가져와서 그 위치에 맞게 파일 이름을 변경했다. 또 어떤 변수 값 하나를 증가시켜서 함수에서 플래그를 생성해준다.

char *__fastcall sub_B2F(__int64 a1, __int64 a2)
{
  char *dest; // [rsp+18h] [rbp-98h]
  char s[8]; // [rsp+20h] [rbp-90h]
  __int64 v5; // [rsp+28h] [rbp-88h]
  __int64 v6; // [rsp+30h] [rbp-80h]
  __int64 v7; // [rsp+38h] [rbp-78h]
  __int64 v8; // [rsp+40h] [rbp-70h]
  __int64 v9; // [rsp+48h] [rbp-68h]
  __int64 v10; // [rsp+50h] [rbp-60h]
  __int64 v11; // [rsp+58h] [rbp-58h]
  char v12[8]; // [rsp+60h] [rbp-50h]
  __int64 v13; // [rsp+68h] [rbp-48h]
  __int64 v14; // [rsp+70h] [rbp-40h]
  __int64 v15; // [rsp+78h] [rbp-38h]
  __int64 v16; // [rsp+80h] [rbp-30h]
  __int64 v17; // [rsp+88h] [rbp-28h]
  __int64 v18; // [rsp+90h] [rbp-20h]
  __int64 v19; // [rsp+98h] [rbp-18h]
  unsigned __int64 v20; // [rsp+A8h] [rbp-8h]

  v20 = __readfsqword(0x28u);
  *s = 0LL;
  v5 = 0LL;
  v6 = 0LL;
  v7 = 0LL;
  v8 = 0LL;
  v9 = 0LL;
  v10 = 0LL;
  v11 = 0LL;
  *v12 = 0LL;
  v13 = 0LL;
  v14 = 0LL;
  v15 = 0LL;
  v16 = 0LL;
  v17 = 0LL;
  v18 = 0LL;
  v19 = 0LL;
  dest = malloc(0x40uLL);
  if ( !strncmp((a1 + 6), "YISF", 4uLL) )
  {
    puts("\nHmm...?\n");
    if ( !strncmp((a1 + 11), "TOP_SECRET", 0xAuLL) )
    {
      puts("Please enter your ID and Password...\n");
      printf("ID : ", "TOP_SECRET", a2);
      fgets(s, 64, stdin);
      printf("PW : ", 64LL);
      fgets(v12, 64, stdin);
      strcpy(dest, v12);
      if ( strncmp(s, aTheWorldBestPr, 0x19uLL) || strncmp(v12, aQwe123, 6uLL) )
      {
        puts("\nYou don't have permission!!\n");
        exit(0);
      }
      puts("\nsuccess!!\n");
      ++dword_20240C;
    }
    else
    {
      puts("Invalid Directory Name\n");
    }
  }
  else
  {
    puts("Ivalid Directory Name\n");
  }
  return dest;
}

FLAG : YISF{5252~~_I_6eliev3d!!!}


Reversing 100

어차피 마지막에 플래그 출력해줄 것 같았다.

FLAG 출력해줄 인코딩된 테이블을 가져와서 XOR Brute Force Attack 했더니 플래그가 나왔다.

a=[0xc8,0xd8,0xc2,0xd7,0xea,0xa5,0xe3,0xf4,0xce,0xc8,0xa1,0xe4,0xce,0xf0,0xce,0xd2,0xf9,0xa2,0xf0,0xa6,0xf4,0xe3,0xae,0xae,0xec]
print ''.join(chr(i^145) for i in a)

FLAG : YISF{4re_Y0u_a_Ch3a7er??}


Misc 50

Introduce 들어가서 보면 된다.

확인을 누르면 alert 띄워서FLAG 준다.

FLAG : YISF{G00D_LUCK_3V3RY01V3}


Misc 100

주어진 nc로 들어가게되면 아래처럼 직선방정식으로 삼각형 넓이를 구하라고 x,y 값을 준다.

x,y값을 구한후 일명 신발끈 공식을 이용해 삼각형의 넓이를 구했다.

참고 : 신발끈 공식

from z3 import *
from pwn import *
p = remote('218.158.141.199',24763)
s = Solver()
x = [Int('x%i'%i)for i in range(12,130)]
y = [Int('y%i'%i)for i in range(12,130)]
x1 = [Int('x1%i'%i)for i in range(12,130)]
y1 = [Int('y1%i'%i)for i in range(12,130)]
x2 = [Int('x2%i'%i)for i in range(12,130)]
y2 = [Int('y2%i'%i)for i in range(12,130)]
p.recvuntil('<Quiz Start>\n')
for i in range(100):
print "[*]"+str(i)
li = []
print p.recvuntil('Step : ' + str(i+1) + "\n\n")
a = p.recvline()
print a
tmp1 = a.split(' ')
b = p.recvline()
print b
tmp2 = b.split(' ')
c = p.recvline()
print c
tmp3 = c.split(' ')
s.add(int(tmp1[0]) * x[12+i] + int(tmp1[3]) * y[12+i] == int(tmp1[6].replace("\n","")))
s.add(int(tmp2[0]) * x[12+i] + int(tmp2[3]) * y[12+i] == int(tmp2[6].replace("\n","")))
s.check()
m = s.model()
li.append(int(str(m.evaluate(x[i+12]))))
li.append(int(str(m.evaluate(y[i+12]))))
s.add(int(tmp1[0]) * x1[12+i] + int(tmp1[3]) * y1[12+i] == int(tmp1[6].replace("\n","")))
s.add(int(tmp3[0]) * x1[12+i] + int(tmp3[3]) * y1[12+i] == int(tmp3[6].replace("\n","")))
s.check()
m = s.model()
li.append(int(str(m.evaluate(x1[i+12]))))
li.append(int(str(m.evaluate(y1[i+12]))))
s.add(int(tmp2[0]) * x2[12+i] + int(tmp2[3]) * y2[12+i] == int(tmp2[6].replace("\n","")))
s.add(int(tmp3[0]) * x2[12+i] + int(tmp3[3]) * y2[12+i] == int(tmp3[6].replace("\n","")))
s.check()
m = s.model()
li.append(int(str(m.evaluate(x2[i+12]))))
li.append(int(str(m.evaluate(y2[i+12]))))
print li
payload=(abs((li[0]*li[3]+li[2]*li[5]+li[4]*li[1]) - (li[2]*li[1]+li[4]*li[3]+li[0]*li[5])))*0.5
print payload
p.sendlineafter('Input :',str(payload))
p.interactive()

좀 코드가 더럽긴한데.. 자꾸 11번째에서 오류나길래 인덱스 12부터 시작해줬더니 오류가 안나고 풀렸다.

FLAG : YISF{Mathematical_ability_i5_n0t_ru5ty}


Misc 150

주어진 nc 서버를 들어가면 딕셔너리를 주어서 만들 수 있는 경우를 브루트포스해서 문자를 만들어서 보내면 된다.

근데 딕셔너리가 문자로 주어져서 ast 모듈을 사용해서 풀었다.

from pwn import *
from ast import literal_eval
p = remote('218.158.141.182',52387)
for i in range(100):
payload=""
print p.recvuntil('Step : ' + str(i+1) + "\n\n")
text = p.recvline()
text = list(text)
del(text[-1])
heigth = p.recvline()
table = p.recvline()
table = table[9:]
dictionary = literal_eval(table)
value = list(dictionary.keys())
while len(text) != 0:
for i in range(1,5):
tmp = text[:i]
tmp2 = ''.join(i for i in tmp)
for j in range(5):
if tmp2 == dictionary[value[j]]:
payload += value[j]
del text[:i]
print payload
p.sendline(payload)
p.interactive()

FLAG : YISF{Y0u_make_table_WeLL}

'CTF WriteUp' 카테고리의 다른 글

2019 20th Hackingcamp CTF Writeup  (0) 2019.09.01
2019 Inc0gnito CTF Writeup  (0) 2019.08.27
2018 ROOT CTF Reversing Writeup  (0) 2019.08.04
2017 Dimi CTF Final warmup  (0) 2019.08.04
2017 Dimi CTF Final TooEasy  (0) 2019.08.04

+ Recent posts