見出し画像

Houseplant CTF 2020 write-up

4月25日(土) 4:00〜4月27日(月) 4:00 (JST)に開催されたHouseplant CTF 2020にソロで参加しました。今回は650points取れました。

以下、write-upです。

---------- Beginner -----------

* Beginner 1 [25 Points]

When Bob and Jia were thrown into the world of cybersecurity, they didn't know anything- and thus were very overwhelmed. They're trying to make sure it doesn't happen to you.
Let's cover some bases first.
cnRjcHt5b3VyZV92ZXJ5X3dlbGNvbWV9

Base64でデコードする。

import base64
s = b'cnRjcHt5b3VyZV92ZXJ5X3dlbGNvbWV9'
print((base64.b64decode(s)).decode())

Flag: rtcp{youre_very_welcome}

* Beginner 2 [25 Points]

Bob wanted to let you guys know that "You might not be a complete failure."
Thanks, Bob.
72 74 63 70 7b 62 6f 62 5f 79 6f 75 5f 73 75 63 6b 5f 61 74 5f 62 65 69 6e 67 5f 65 6e 63 6f 75 72 61 67 69 6e 67 7d

各16進数がそれぞれascii文字になっているので、変換すればよい。

s = "72 74 63 70 7b 62 6f 62 5f 79 6f 75 5f 73 75 63 6b 5f 61 74 5f 62 65 69 6e 67 5f 65 6e 63 6f 75 72 61 67 69 6e 67 7d"
s = list(map(str, s.split()))
for i in s:
   print(chr(int(i, 16)), end="")6e 67 5f 65 6e 63 6f 75 72 61 67 69 6e 67 7d"

Flag: rtcp{bob_you_suck_at_being_encouraging}

* Beginner 3 [25 Points]

Beginner 2とほぼ同じだが、8進数になっている。

s = "162 164 143 160 173 163 165 145 137 155 145 137 151 137 144 151 144 156 164 137 153 156 157 167 137 167 150 141 164 137 157 143 164 141 154 137 167 141 163 137 157 153 141 171 77 41 175"
s = list(map(str, s.split()))
for i in s:
   print(chr(int(i, 8)), end="")

Flag: rtcp{sue_me_i_didnt_know_what_octal_was_okay?!}

* Beginner 4 [25 Points]

Caesar was stabbed 23 times by 60 perpetrators... sounds like a modern group project
egpc{lnyy_orggre_cnegvpvcngr}

シーザー暗号で13文字ずらせばよい。CyberChefを使うと答えを得られる。

Flag: rtcp{yall_better_participate}

* Beginner 5 [25 Points]

beep boop
-- .- -. -.-- ..--.- -... . . .--. ... ..--.- .- -. -.. ..--.- -... --- --- .--. ...
Remember to wrap the flag in the flag format rtcp{something}

モールス信号になっているので、こういうサイトで変換するとよい。単語のつなぎがちゃんと出ないが、アンダーバーにしたらフラグになった。

Flag: rtcp{MANY_BEEPS_AND_BOOPS}

* Beginner 6 [25 Points]

i'm so tired...
26 26 26 26 26 26 26 26 19 12 5 5 16 9 14 7 9 14 16 8 25 19 9 3 19
*disclaimer: DON'T DO THIS KIDS. only sleep in math.
Remember to wrap the whole thing in the flag format rtcp{}
Hint! this isn't a hint; this is just us expressing our regret for taking 8AM physics

並んでいる数字は、アルファベットの文字順になっている。

Flag: rtcp{ZZZZZZZZSLEEPINGINPHYSICS}

---------- Misc ----------

* Rules [50 Points]

Please read the rules.

Flag: rtcp{this_is_not_a_flag_i_think}

* Spilled Milk [50 Points]

oh no! i'm so clumsy, i spilled my glass of milk! can you please help me clean up?
Dev: Daphne

png画像があたえられるが、よく見るとうっすら何か見える。

画像1

Windows10のフォトで全体を暗くしたら、フラグが見えた。

画像2

Flag: rtcp{Th4nk$_f0r_h3LP1nG!}

---------- OSINT ----------

* What a Sight to See! [50 Points]

What Google Search Operator can I use to find results from a single website?
Hint! This flag is NOT flag format

Flag: site:

---------- Reverse Engineering ----------

* Fragile [50 Points]

Can you help me move my stuff? This one's fragile!
Dev: Sri

Javaのプログラムが与えられる。

import java.util.*;

public class fragile
{
   public static void main(String args[]) {
       Scanner scanner = new Scanner(System.in);
       System.out.print("Enter flag: ");
       String userInput = scanner.next();
       String input = userInput.substring("rtcp{".length(),userInput.length()-1);
       if (check(input)) {
           System.out.println("Access granted.");
       } else {
           System.out.println("Access denied!");
       }
   }
   
   public static boolean check(String input){
       boolean h = false;
       String flag = "h1_th3r3_1ts_m3";
       String theflag = "";
       if(input.length() != flag.length()){
           return false;
       }
       for(int i = 0; i < flag.length(); i++){
           theflag += (char)((int)(flag.charAt(i)) + (int)(input.charAt(i)));
       }
       return theflag.equals("ÐdØÓ�§å�ÍaèÒÁ¡�");
   }
}

入力された値とflag(h1_th3r3_1ts_m3)の各文字を足してtheflagを生成しているようなので、逆にすれば答えを得られる。

import java.util.*;

public class Main {
   public static void main(String[] args) throws Exception {
       String flag = "h1_th3r3_1ts_m3";
       String theflag = "ÐdØÓ�§å�ÍaèÒÁ¡�";
       String ans = "";
       for(int i = 0; i < flag.length(); i++){
           ans += (char)((int)theflag.charAt(i) - (int)(flag.charAt(i)));
       }
       System.out.println(ans);
   }
}

Flag: rtcp{h3y_1ts_n0t_b4d}

* Breakable [50 Points]

Fragileを解くと問題に挑戦できる。今回のJavaコードは以下の通り。

import java.util.*;

public class breakable
{
   public static void main(String args[]) {
       Scanner scanner = new Scanner(System.in);
       System.out.print("Enter flag: ");
       String userInput = scanner.next();
       String input = userInput.substring("rtcp{".length(),userInput.length()-1);
       if (check(input)) {
           System.out.println("Access granted.");
       } else {
           System.out.println("Access denied!");
       }
   }
   
   public static boolean check(String input){
       boolean h = false;
       String flag = "k33p_1t_in_pl41n";
       String theflag = "";
       int i = 0;
       if(input.length() != flag.length()){
           return false;
       }
       for(i = 0; i < flag.length()-2; i++){
           theflag += (char)((int)(flag.charAt(i)) + (int)(input.charAt(i+2)));
       }
       for(i = 2; i < flag.length(); i++){
           theflag += (char)((int)(flag.charAt(i)) + (int)(input.charAt(i-2)));
       }
       String[] flags = theflag.split("");
       for(; i < (int)((flags.length)/2); i++){
           flags[i] = Character.toString((char)((int)(flags[i].charAt(0)) + 20));
       }
       return theflag.equals("Ò�dݾ¤¤¾Ùà�åÐ�cÝÆ�¥ÌÈá�Ïܦaã");
   }
}

今回も順に戻していくと答えを得られる。

import java.util.*;

public class Main {
   public static void main(String[] args) throws Exception {
       String flag = "k33p_1t_in_pl41n";
       String theflag = "Ò�dݾ¤¤¾Ùà�åÐ�cÝÆ�¥ÌÈá�Ïܦaã";
       String ans = "";
       
       for(int i = 0; i < 2; i++){
           ans += (char)((int)(theflag.charAt(i+14)) - (int)(flag.charAt(i+2)));
       }
       for(int i = 0; i < flag.length()-2; i++){
           ans += (char)((int)(theflag.charAt(i)) - (int)(flag.charAt(i)));
       }
       
       System.out.println(ans);
   }
}

Flag: rtcp{0mg_1m_s0_pr0ud_}

* EZ [50 Points]

I made a password system, bet you can't get the flag
Dev: William

与えられたPythonコードを確認すると、コメントにフラグが書いてある。

print("rtcp{tH1s_i5_4_d3c0Y_fL4g_s0_DoNt_sUbm1T_1t!}")

##they will never suspect a thing if i hide it here :)
##print("rtcp{tH1s_i5_4_r3aL_fL4g_s0_Do_sUbm1T_1t!}")

print("…………………………………………. ………………………………….,-~~''''''’~~–,,_")
print("………………………………………….. …………………………….,-~''-,:::::::::::::::::::''-,")
print("………………………………………….. ………………………..,~''::::::::’,::::::: :::::::::::::|’,")
print("………………………………………….. ………………………..|::::::,-~''’___''''~~–~''’:}")
print("………………………………………….. ………………………..’|:::::|: : : : : : : : : : : : : :")
print("………………………………………….. ………………………..|:::::|: : :-~~—: : : —–: |")
print("………………………………………….. ……………………….(_''~-’: : : : : : : : :")
print("………………………………………….. ………………………..''’~-,|: : : : : : ~—’: : : :,’–get rickrolled")
print("………………………………………….. ……………………………|,: : : : : :-~~–: : ::/ ")
print("………………………………………….. ……………………….,-''\’:\: :’~,,_: : : : : _,-’")
print("………………………………………….. ………………….__,-’;;;;;\:''-,: : : :’~—~''/|")
print("………………………………………….. ………….__,-~'';;;;;;/;;;;;;;\: :\: : :____/: :’,__")
print("………………………………………….. .,-~~~''''_;;;;;;;;;;;;;;;;;;;;;;;;;’,. .''-,:|:::::::|. . |;;;;''-,__")
print("…………………………………………../;;;;;;;;;;;;;;;;;;;;;;;;;;;;,;;;;;;;;;\. . .''|::::::::|. .,’;;;;;;;;;;''-,")
print("…………………………………………,’ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;|;;;;;;;;;;;\. . .\:::::,’. ./|;;;;;;;;;;;;;|")
print("………………………………………,-'';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\;;;;;;;;;;;’,: : __|. . .|;;;;;;;;;,’;;|")
print("…………………………………….,-'';;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;’,;;;;;;; ;;;; \. . |:::|. . .'',;;;;;;;;|;;/")
print("……………………………………/;;;;;;;;;;;;;;;;;;;;;;;;;;|;;;;;;;;;;;;;;\;;;;;;;; ;;;\. .|:::|. . . |;;;;;;;;|/")
print("…………………………………./;;,-’;;;;;;;;;;;;;;;;;;;;;;,’;;;;;;;;;;;;;;;;;,;;;;;;; ;;;|. .\:/. . . .|;;;;;;;;|")
print("…………………………………/;;;;;;;;;;;;;;;;;;;;;;;;;;,;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;'',: |;|. . . . \;;;;;;;|")
print("………………………………,~'';;;;;;;;;; ;;;;;;;;;;;,-'';;;;;;;;;;;;;;;;;;;;;;;;;;\;;;;;;;;|.|;|. . . . .|;;;;;;;|")
print("…………………………..,~'';;;;;;;;;;;;;; ;;;;;;;;,-’;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;’,;;;;;;| |:|. . . . |\;;;;;;;|")
print("………………………….,’;;;;;;;;;;;;;;;;; ;;;;;;;/;;;,-’;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,;;;;;| |:|. . . .’|;;’,;;;;;|")
print("…………………………|;,-’;;;;;;;;;;;;;;;;;;;,-’;;;,-’;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;,;;;;| |:|. . .,’;;;;;’,;;;;|_")
print("…………………………/;;;;;;;;;;;;;;;;;,-’_;;;;;;,’;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;|;;; ;|.|:|. . .|;;;;;;;|;;;;|''''~-,")
print("………………………./;;;;;;;;;;;;;;;;;;/_'',;;;,’;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ,;;| |:|. . ./;;;;;;;;|;;;|;;;;;;|-,,__")
print("……………………../;;;;;;;;;;;;;;;;;,-’…|;;,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;| |:|._,-’;;;;;;;;;|;;;;|;;;;;;;;;;;''’-,_")
print("……………………/;;;;;;;;;;;;;;;;,-’….,’;;,;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;|.|:|::::''’~–~''’||;;;;;|;;;;;;;;;;,-~''''~–,")
print("………………….,’;;;;;;;;;;;;;;;;,’……/;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;|.|:|::::::::::::::|;;;;;’,;;;;;;;;;''-,: : : : : :''’~-,:''’~~–,")
print("…………………/;;;;;;;;;;;;;;;,-’……,’;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;|:|:|::::::::::::::’,;;;;;;|_''''~–,,-~—,,___,-~~''’__''~-")
print("………………,-’;;;;;;;;;;;;;;;,’……../;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;|:|:|:::::::::::::::|;;;;;;|……………… …''-,\_''-,''-,''~")
print("………………/;;;;;;;;;;;;;;;;/…….,-’;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;|:|:|:::::::::::::::|;;;;;|…………….")

Flag: rtcp{tH1s_i5_4_r3aL_fL4g_s0_Do_sUbm1T_1t!}

* PZ [50 Points]

Ok, I think I made it slightly better. Now you won't get the flag this time!
Dev: William

EZを解くと問題が現れる。Pythonコードは以下の通り。

def catchecKpass():
 userinput = input("pwease enter youwr password... uwu~ nya!!: ")
 if userinput == "rtcp{iT5_n0T_s1mPlY_1n_tH3_C0d3}":
     return True
 else:
     return False

def checkpasss():
 userinput = input("Enter the password: ")
 if userinput == "rtcp{wH4t_aR3_y0u_SaY1nG?}":
     return True
 else:
     return False

def acheckpass():
 userinput = input("Enter the password: ")
 if userinput == "rtcp{1_cAnt_QuiT3_hE@r_Y0u!}":
     return True
 else:
     return False

def ccheckpass():
 userinput = input("Enter the password: ")
 if userinput == "rtcp{sPe4k_Up_4_b1T}":
     return True
 else:
     return False

def checkpass():
 userinput = input("Enter the password: ")
 if userinput == "rtcp{iT5_s1mPlY_1n_tH3_C0d3}":
     return True
 else:
     return False

def bcheckpass():
 userinput = input("Enter the password: ")
 if userinput == "rtcp{tH1s_i5_4_R3aL_fLaG_t0TalLy}":
     return True
 else:
     return False
   
def catcheckpass():
 userinput = input("pwease enter youwr password... uwu~ nya!!: ")
 if userinput == "rtcp{iT5_s1mPlY_1n_tH3_C0d3}":
     return True
 else:
     return False

def main():
   access = checkpass()
   if access == True:
       print("Unlocked. The flag is the password.")
       print("b-but i wunna show off my catswpeak uwu~... why wont you let me do my nya!!")
       exit()
   else:
       print("Incorrect password!")
       print("sowwy but now you gunnu have to listen to me spweak in cat giwrl speak uwu~")
       catmain()

def catmain():
   access = catcheckpass()
   if access == True:
       print("s-senpai... i unwocked it fowr you.. uwu~")
       print("t-the fwlag is... the password.. nya!")
       exit()
   else:
       print("sowwy but that wasnt quite rwight nya~")
       catmain()


access = False
main()

無駄に長いが、main関数が呼ばれて、checkpass関数が呼ばれているだけなので、checkpass関数を見ればフラグが書いてある。

Flag: rtcp{iT5_s1mPlY_1n_tH3_C0d3}

* LEMON [50 Points]

Fine. I made it a bit more secure by not just leaving it directly in the code.
Dev: William

PZを解くと問題が現れる。今回のコードは以下の通り。

def checkpass():
 userinput = input("Enter the password: ")
 if userinput[0:4] == "rtcp":
       if userinput[10:13] == "tHi":
           if userinput[22:25] == "cuR":
               if userinput[4:7] == "{y3":
                   if userinput[16:19] == "1nT":
                       if userinput[7:10] == "4H_":
                           if userinput[13:16] == "S_a":
                               if userinput[19:22] == "_sE":
                                   if userinput [25:27] == "3}":
                                       return True
 else:
   return False
def main():
   access = checkpass()
   if access == True:
       print("Unlocked. The flag is the password.")
       print("b-but i wunna show off my catswpeak uwu~... why wont you let me do my nya!!\noh well... good luck with the rest of the ctf :/\nbut I WANT TO SPWEAK CATGIRL NEXT TIME SO YOU BETTER LET ME >:(")
       exit()
   else:
       print("Incorrect password!")
       print("sowwy but now you gunnu have to listen to me spweak in cat giwrl speak uwu~")
       catmain()

def catmain():
   access = catcheckpass()
   if access == True:
       print("s-senpai... i unwocked it fowr you.. uwu~")
       print("t-the fwlag is... the password.. nya!")
       exit()
   else:
       print("sowwy but that wasnt quite rwight nya~")
       catmain()

def catcheckpass():
 userinput = input("pwease enter youwr password... uwu~ nya!!: ")
 if userinput[0:4] == "rtcp":
       if userinput[10:13] == "tHi":
           if userinput[22:25] == "cuR":
               if userinput[4:7] == "{y3":
                   if userinput[16:19] == "1nT":
                       if userinput[7:10] == "4H_":
                           if userinput[13:16] == "S_a":
                               if userinput[19:22] == "_sE":
                                   if userinput [25:27] == "3}":
                                       return True
 else:
   return False

access = False
main()

PZと同じくmain関数からcheckpass関数が呼ばれている。フラグが分割されていてわかりにくいので、元のコードを利用してフラグを出力させる。

userinput = [""]*27
userinput[0:4] = "rtcp"
userinput[10:13] = "tHi"
userinput[22:25] = "cuR"
userinput[4:7] = "{y3"
userinput[16:19] = "1nT"
userinput[7:10] = "4H_"
userinput[13:16] = "S_a"
userinput[19:22] = "_sE"
userinput[25:27] = "3}"
print("".join(userinput))

Flag: rtcp{y34H_tHiS_a1nT_sEcuR3}

* SQUEEZY [50 Points]

Ok this time, you aren't getting anywhere near anything.
Dev: William

上のLEMONを解くと問題が現れる。今回のコードは以下の通り。

import base64
def checkpass():
 userinput = input("Enter the password: ")
 key = "meownyameownyameownyameownyameownya"
 a = woah(key,userinput)
 b = str.encode(a)
 result = base64.b64encode(b, altchars=None)
 if result == b'HxEMBxUAURg6I0QILT4UVRolMQFRHzokRBcmAygNXhkqWBw=':
     return True
 else:
     return False

def main():
   access = checkpass()
   if access == True:
       print("Unlocked. The flag is the password.")
       print("pwease let me do my nya~ next time!!")
       exit()
   else:
       print("Incorrect password!")
       print("sowwy but now you gunnu have to listen to me spweak in cat giwrl speak uwu~")
       catmain()

def catmain():
   access = catcheckpass()
   if access == True:
       print("s-senpai... i unwocked it fowr you.. uwu~")
       print("t-the fwlag is... the password.. nya!")
       exit()
   else:
       print("sowwy but that wasnt quite rwight nya~... pwease twy again")
       catmain()

def catcheckpass():
 userinput = input("pwease enter youwr password... uwu~ nya!!: ")
 key = "meownyameownyameownyameownyameownya"
 a = woah(key,userinput)
 b = str.encode(a)
 result = base64.b64encode(b, altchars=None)
 if result == b'HxEMBxUAURg6I0QILT4UVRolMQFRHzokRBcmAygNXhkqWBw=':
     return True
 else:
     return False

def woah(s1,s2):
   return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2))
access = False
main()

少しずつ複雑になっているが、順に戻していけばフラグをゲットできる。フラグをゲットしたコードは以下。XORは再度XORするともとに戻ることから再利用した。

import base64

def woah(s1,s2):
   return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2))

key = "meownyameownyameownyameownyameownya"
result = 'HxEMBxUAURg6I0QILT4UVRolMQFRHzokRBcmAygNXhkqWBw='
b = base64.b64decode(result, altchars=None)
a = bytes.decode(b)
userinput = woah(key, a)
print(userinput)

Flag: rtcp{y0u_L3fT_y0uR_x0r_K3y_bEh1nD!}

* thedanzman [50 Points]

Fine. I made it even harder. It is now no longer "ez", "pz", "lemon" or "squeezy".
You will never get the flag this time.
Dev: William

SQUEEZYを解くと挑戦できる。今回のコードは以下の通り。

import base64
import codecs
def checkpass():
 userinput = input("Enter the password: ")
 key = "nyameowpurrpurrnyanyapurrpurrnyanya"
 key = codecs.encode(key, "rot_13")
 a = nope(key,userinput)
 b = str.encode(a)
 c = base64.b64encode(b, altchars=None)
 c = str(c)
 d = codecs.encode(c, 'rot_13')
 result = wow(d)
 if result == "'=ZkXipjPiLIXRpIYTpQHpjSQkxIIFbQCK1FR3DuJZxtPAtkR'o":
     return True
 else:
     return False

def main():
   access = checkpass()
   if access == True:
       print("Unlocked. The flag is the password.")
       print("pwease let me do my nya~ next time!!")
       exit()
   else:
       print("Incorrect password!")
       print("sowwy but now you gunnu have to listen to me spweak in cat giwrl speak uwu~")
       catmain()

def catmain():
   access = catcheckpass()
   if access == True:
       print("s-senpai... i unwocked it fowr you.. uwu~")
       print("t-the fwlag is... the password.. nya!")
       exit()
   else:
       print("sowwy but that wasnt quite rwight nya~... pwease twy again")
       catmain()

def catcheckpass():
 userinput = input("pwease enter youwr password... uwu~ nya!!: ")
 key = "nyameowpurrpurrnyanyapurrpurrnyanya"
 key = codecs.encode(key, "rot_13")
 a = nope(key,userinput)
 b = str.encode(a)
 c = base64.b64encode(b, altchars=None)
 c = str(c)
 d = codecs.encode(c, 'rot_13')
 result = wow(d)
 if result == "'=ZkXipjPiLIXRpIYTpQHpjSQkxIIFbQCK1FR3DuJZxtPAtkR'o":
     return True
 else:
     return False

def nope(s1,s2):
   return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2))

def wow(x):
 return x[::-1]

access = False
main()

また少し複雑になったが、順に戻していけばいい。ROT13はもう一度ROT13すれば元に戻ることを知っていると少し楽かもしれない。

import base64
import codecs

def wow(x):
 return x[::-1]
 
def nope(s1,s2):
   return ''.join(chr(ord(a) ^ ord(b)) for a,b in zip(s1,s2))

result = "=ZkXipjPiLIXRpIYTpQHpjSQkxIIFbQCK1FR3DuJZxtPAtkR"
d = wow(result)
c = codecs.encode(d, 'rot_13')
b = base64.b64decode(c, altchars=None)
a = bytes.decode(b)
key = "nyameowpurrpurrnyanyapurrpurrnyanya"
key = codecs.encode(key, 'rot_13')
flag = nope(key, a)
print(flag)

Flag: rtcp{n0w_tH4T_w45_m0r3_cH4lL3NgiNG}

この記事が気に入ったらサポートをしてみませんか?