워게임 문제 풀이에 앞서서, Dreamhack의 Dream Beginners 강의를 보고 워게임 풀이를 위한 준비를 했다.
목차
- 해킹에 대해서
- 워게임
- 컴퓨터 과학 기초
1. 해킹에 대해서
해킹이란? 타인의 컴퓨터 시스템에 무단으로 침입해서 정보 또는 권한을 탈취하거나, 시스템을 파괴하는 것을 의미하며, 컴퓨터 시스템에 취약한 부분을 찾아내는 단계 / 이를 공격하는 단계로 이루어진다.
이러한 해킹을 배우기 위해서는 컴퓨터 과학을 공부하는 것이 학습에 유리하다. 그리고 컴퓨터 과학 학습의 첫 스텝으로, 프로그래밍 언어로 코딩하는 기술을 익히는 것이 우선이다. C언어와 파이썬을 우선 익히는 것을 권장한다.
해킹의 주요 3가지 분야에 대해서만 간략히 소개하겠다.
1) 웹 해킹
웹을 대상으로 하는 해킹 관련 기술을 가리킨다.
웹과 관련된 기술이 고도화되고 웹 기반의 소프트웨어 및 서비스들이 널리 쓰임. -> 웹 해킹의 적용 범위도 넓어짐. 웹 사이트부터 모바일을 타겟으로 한 하이브리드 웹 앱 및 게임에 관한 것까지...
드림핵 웹 해킹 로드맵 : 웹과 관련된 다양한 기술 지식들을 설명, 웹 취약점 및 공격 기법들을 다룸.
2) 시스템 해킹(=Pwnable=시스템 해킹)
소프트웨어의 취약점을 찾아 이를 공격하는 해킹 분야이다.
많은 사회 기반 시설들이 소프트웨어로 제어되고 있으며, 개인의 일상 또한 소프트웨어에 의존하고 있음. -> 시스템 해킹의 위협이 커짐.
드림핵 시스템 해킹 로드맵 : 배경지식, 소프트웨어에서 발생할 수 있는 취약점과 공격 기법들을 다룸.
3) 리버스 엔지니어(리버싱)
프로그램을 역으로 분석하여 작동 원리를 알아내는 기술이며, 시스템 해킹을 공부할 때 필수적으로 다뤄야 하는 기술이다.
리버싱을 위해서는 기본적으로 많은 배경지식과 환경이 필요하다.
드림핵 리버싱 로드맵 : 배경지식 소개, 예제들로 훈련함.
2. 워게임
워게임이란? 의도적으로 취약점이 존재하도록 설계된 모의 해킹 환경이다.
일종의 시험 문제라고 볼 수도 있는데, 제작자가 설계한 취약점을 찾아내고 그것을 이해해서 해결책을 찾아내는 과정을 거쳐 플래그를 찾아내는 문제이다.
*플래그(flag) : 흔히 볼 수 있는 해킹 방어 대회의 일반적인 형식은 CTF, 즉 Capture The Flag이다. 이는 공격 대상인 시스템에 존재하는 파일을 Flag라고 칭하며, 이 파일의 내용이 공격자가 제출해야 하는 답안이 된다.
CTF와 같은 대회에서는 문제를 풀었음을 증명하기 위한 수단으로 플래그를 사용하며, 드림핵에서 사용하는 플래그는 보통 DH{} 형식의 중괄호 사이에 해시값이 들어있는 형태이다.
워게임의 카테고리 : 포너블(pwnable/system hacking), 웹(web), 리버스 엔지니어링(reversing), 암호학(crypto), 포렌식(forensics), 특정 카테고리에 포함되지 않는 miscellaneous(misc) 등
실습
준비물 : Ubuntu Linux 환경, nc(netcat)
+보다 자세한 준비 과정은 Dream Beginners강의-Environment Setup-Virtual Machine에 나와있다.
간단한 실습 전, wsl2를 설치해서 실습을 위한 세팅을 마쳤다.
*vm을 사용하는 문제의 경우, VirtualBox의 오류가 존재해서 추후 다시 시도해볼 예정이다.
실습 문제 링크 : https://dreamhack.io/wargame/challenges/812
해당 문제에서 nc로 접속하여 주어진 명령어를 입력하였다.
주어진 명령어를 복사 붙여넣기 하면 Enter "Dreamhack"이라는 글자와 입력창이 뜬다. 입력창에 그대로 Dreamhack을 써넣으면 플래그가 출력된다.
3. 컴퓨터 과학 기초
1byte = 8bit
최상위 비트(MSB) : 여러 개의 비트로 구성된 이진 데이터에서 가장 왼쪽에 있는 비트를 Most Significant Bit(MSB)라고 한다. 부호가 있는 데이터의 경우, MSB가 부호의 의미를 가지게 되기도 한다.
최하위 비트(LSB) : 여러 개의 비트로 구성된 이진 데이터에서 가장 오른쪽에 있는 비트를 Least Significant Bit(LSB)라고 한다.
바이트 오더링(Byte Ordering)이란? 2바이트 이상의 데이터는 메모리에 연속적으로 저장된다. 이때 각 바이트가 메모리에 저장되는 방식을 바이트 오더링이라고 부른다.
바이트 오더링의 두 가지 방식으로 빅 엔디안(Big Endian)과 리틀 엔디안(Little Endian)이 있다.
두 개념을 쉽게 설명하기 위해 가장 왼쪽에 있는 바이트일수록 "크다"고 표현하겠다. 0x01234567과 같은 데이터가 있을 때, 0x01이 가장 큰 바이트이고 0x67이 가장 작은 바이트이다.
*빅 엔디안 : 가장 큰(=왼쪽에 있는) 바이트부터 낮은 주소에 저장된다. -> 0x01이 낮은 주소에 먼저 저장됨.
*리 엔디안 : 가장 작은(=오른쪽에 있는) 바이트부터 낮은 주소에 저장된다. -> 0x67이 낮은 주소에 먼저 저장됨.
리틀 엔디안은 주로 Intel의 x86, x86-64 CPU에서 사용된다. 그리고 대다수의 개인용 컴퓨터 및 서버 환경에서는 x86-64 CPU 아키텍처를 사용한다. -> 리틀 엔디안이 특히 중요함.
문자열을 메모리에 저장할 때 : 바이트 오더링 고려X, 문자 순서 그대로 저장됨.
문자열이 아닌 데이터를 메모리에 저장할 때 : 바이트 오더링 고려O, 리틀 엔디안 방식으로 저장됨.
비트 연산이란? 피연산자를 2진수로 표현하여 비트 단위로 연산하는 것을 말한다.
비트 연산자
비트 연산자 | 설명 |
x | y | 두 비트 중 하나라도 1이면 결과는 1이다. (OR) |
x & y | 두 비트 모두 1이면 결과는 1이다. (AND) |
x ^ y | 두 비트가 같으면 결과는 0, 다르면 결과는 1이다. (XOR) |
~x | 비트가 0이면 결과는 1, 1이면 결과는 0이다. (NOT) |
시프트 연산자
시프트 연산자 | 설명 |
x << n | 비트를 n만큼 왼쪽으로 이동한다. 오른쪽 빈 칸은 모두 0으로 채웁니다. == x * 2^n |
x >> n (산술 시프트) |
비트를 n만큼 오른쪽으로 이동한다. 왼쪽 빈 칸은 가장 왼쪽에 있던 비트(MSB)와 동일한 비트 값으로 채운다. (양수는 양수, 음수는 음수로 부호 유지) == x / 2^n |
x >>> n (논리 시프트) |
비트를 n만큼 오른쪽으로 이동한다. 왼쪽 빈 칸은 모두 0으로 채운다. (음수는 부호가 유지X) |
비트 연산 활용
<AND(&) 연산을 활용한 비트 마스킹>
*비트 마스킹 : 어떤 데이터가 존재할 때, 특정 위치의 비트만 표시하거나 가리는 연산을 말한다.
AND 연산의 특징을 활용한 비트 마스킹의 예를 살펴보자.
2바이트 크기의 데이터인 0xABCD가 존재할 때, AND 연산을 활용하면 상위 8비트인 0xAB는 없애고 0xCD만 남길 수 있다.
사진과 같이 0x00FF를 연산하면 된다. AND 연산자는 비트 모두가 1이어야 1이 나오므로, 0(0000)은 어떤 값과 연산해도 0이 나온다. 마스킹하고 싶은 값에 0을 입력하면 된다.특정 위치의 비트의 값을 표시하고 싶을 때는 F(1111)을 활용하면 된다. 기존 값과 동일한 결과가 나오기 때문이다.
<AND(&) 연산과 시프트 연산을 활용하여 특정 비트/바이트 가져오기>
AND 연산과 시프트 연산을 함께 활용하면 특정 위치의 비트를 가져올 수 있다.
다음의 예시를 살펴보자.
- 하위 1 바이트만 가져오기 : 0x000000FF와 AND 연산한다.
0x12345678 & 0x000000FF = 0x00000078 (0000 0000 0000 0000 0000 0000 0111 1000) |
- 상위 1 바이트만 가져오기 : 24번 우측으로 논리 시프트를 수행한다. 또는, 24번 우측으로 산술 시프트한 후 0x000000FF와 AND연산한다.
0x12345678 >>> 24 = 0x00000012 (0000 0000 0000 0000 0000 0000 0001 0010) | |
0x12345678 >> 24 & 0x000000FF = 0x00000012 (0000 0000 0000 0000 0000 0000 0001 0010) |
- 상위에서 두 번째 바이트 가져오기: 16번 우측으로 시프트 후 0x000000FF와 AND 연산한다.
0x12345678 >> 16 & 0x000000FF = 0x00000034 (0000 0000 0000 0000 0000 0000 0011 0100) |
- 하위 1바이트의 상위 4비트 가져오기 : 4번 우측으로 시프트한 후 0x0000000F와 AND 연산한다.
0x12345678 >> 4 & 0x0000000F = 0x00000007 (0000 0000 0000 0000 0000 0000 0000 0111) |
<XOR 연산을 활용한 비교와 암호화>
자기 자신과 XOR 연산하면 결과 0이 된다. 두 변수에 저장된 값끼리 XOR 연산하여 결과가 0인지 확인하면 두 값이 같은지 비교할 수 있다.
같은 값에 어떤 값을 2번 XOR 연산하면 원래의 값과 동일해진다. 이런 특성을 활용해 간단한 암호화, 복호화가 가능하다. 예를 들어 x ^ y의 결과가 z일때 z ^ y = x ^ y ^ y = x이다. (y를 key로 설정)
이러한 특성은 어셈블리 코드나 암호 기법에 자주 등장한다.
<시프트 연산을 활용한 곱셉, 나눗셈>
시프트 연산은 2^n을곱하거나 나눈 결과와 동일하다. 따라서 곱셉이나 나눗셈 연산자 대신 시프트 연산자를 사용하여 간단한 산술 연산을 수행할 수 있다. 비트 레벨에서 연산을 하므로 더 효율적이고 속도가 빠르다.
*인코딩(Encoding) : 데이터를 특정한 형식으로 변환하는 것을 말한다. 데이터의 크기를 줄이거나, 컴퓨터가 이해하기 쉽게 변환할 때 사용한다.
*디코딩(Decoding) : 인코딩된 데이터를 디코딩하여 원래의 값을 구할 수 있다.
인코딩 <-> 암호화
암호화는 비밀키가 있어야 원문을 복구할 수 있지만, 인코딩은 누구나 표준화된 방식을 사용해서 디코딩하여 원문을 복구할 수 있다.
<URL 인코딩(퍼센트 인코딩)>
웹에서 사용되는 URL은 특정한 형식의 문자열만 허용한다. 웹 브라우저로부터 받은 URL 문자열을 유효한 형식으로변환하는 것을 URL 인코딩이라 한다.
인코딩이 필요한 문자(허용되지 않는 문자)는 :/?#[]@!$&'()*+,;=%공백 이다.
<Base64 인코딩>
Base64 인코딩은 이진 데이터를 아스키 문자로 구성된 텍스트로 변환하는 인코딩 방식이다. 총 64개의 아스키 문자가 인코딩에 사용되기 때문에 64진법(Base 64)라는 의미에서 이름이 붙었다. 64개의 아스키 문자는 알파벳 대소문자(52자), 숫자(10자), +, /이다.
Base64 인코딩은 이진 데이터를 그대로 포함할 수 없이 텍스트만 허용되는 환경에서 이진 데이터를 텍스트 형식으로 나타내기 위해 사용된다.
Base64 인코딩 방식
1. 원본 이진데이터를 비트 나열로 표현하고, 이를 6비트씩 끊어서 묶는다. 비트의 개수가 6의 배수가 아닐 경우, 0을 뒤에 추가하여 6의 배수로 만든다.
2. 각 6비트 묶음을 수로 변환한 뒤, base64 테이블에서 해당하는 문자를 찾아 이로 치환한다.
3. 이렇게 치환 과정을 거친 뒤, 글자의 수가 4의 배수가 되도록 문자 '='를 반복해 뒤에 추가한다. 이를 패딩(Padding)이라고 한다.
아래 그림은 문자열 dream을 base64 인코딩한 예시이다.
<인코딩 도구>
문자열을 특정 형식으로 인코딩, 디코딩할 수 있는 도구는 매우 다양하다. 아래는 몇 가지 도구이다.
해당 글은 아래의 Dream Beginners 강의를 보고 개인 공부 목적으로 작성되었음.
https://dreamhack.io/lecture/roadmaps/34
'슈포스 > 워게임' 카테고리의 다른 글
[web]Dreamhack_Flying Chars (0) | 2024.10.31 |
---|---|
[misc]Dreamhack_64se64 (0) | 2024.10.08 |
[web]Dreamhack_Carve party (0) | 2024.10.08 |
[web]Dreamhack_file-download-1 (2) | 2024.09.30 |
[web]Dreamhack_cookie (1) | 2024.09.29 |