DES란 Data Encryption Standard의 약자로 데이터 암호화의 표준이라는 뜻을 가지고 있습니다. 

일단 알아보기 앞서서 역사를 말씀드리자면...

 

1973년에 미국 국립표준국(NBS, National Bureau of Standards)에서 1차적으로 공모를 하였습니다.

하지만 아무도 지원을 하지 않았습니다. 

 

1974년에 NBS가 미국 국립표준 연구소(NIST,National Institute of Standards and Technology)로 명칭을 변경

이후에 2차로 공모를 하여 국제적인 표준으로 만들고자 하였고, 이때 제출된 암호가 표준으로 사용되게 되었습니다.

그럼 바로 사용이 가능했던 것은 아니고 NIST에서 약간의 검증과정을 거쳐서  1977년 암호화 모듈에 대한 보안요구

사항을 규정하는 미국 연방 정보처리 표준의 FIPS-46(Federal Information Processing Standardization)록이 되

어 현재의 DES가 사용이 시작되었고 5년마다 DES에 대한 안정성을 검토하고 있습니다.

 

공모조건은 다음과 같습니다.

1. 높은 안전성

2. 알고리즘 간단

3. 안전성이 키에만 의존

4. 응용이 다양

5. 제작자 및 사용자가 이용 가능

6. 전자장치 간단

7. 제작자의 알고리즘 타당성 검토 협력

8. 수출가능

 

이러한 공모조건을 가지고 탄생한 DES암호는 어떠한 특징을 가지고 있냐하면\

첫번째로 DES는 64bit의 블록암호이기 때문에 어떠한 긴 평문이 있다고 하더라도 64bit씩 블록단위로 암호화를 합니다.

그리고 이 암호는 표준화가 되었고 30년동안 사용되었습니다. 왜냐하면 컴퓨팅 능력과 기술이 발전하면서 더이상 안전

하지 않다고 판단이 되어서 지금은 사용하지 않지만 지금도 연구가 활발히 되고있으며 DES를 변형시킨 3DES라는 이름

으로 오늘날 널리 사용되는 안전한 암호가 있습니다.

 

암호화 과정

 

64bit의 블록암호이기 때문에 64bit 단위로 암호화가 되고 키는 64bit이지만 나머지 8bit는 패리티 비트(오류발생 방지)로

사용이되어 실질적으로는 56bit가 사용이됩니다. 그렇게 평문과 키를 연산하여 나오는 64bit 길이의 암호문이 완성됩니다. 

키에서 사용되는 8bit의 패리티비트는 키를 전송하는 과정에서 오류가 발생했을 시에 확인하는 용도로 사용됩니다.

 

그럼 암호화된 암호문을 복호화할때도 동일하겠죠?

 

암호기술 분야에서의 DES 

 

위의 그림에서 볼 수 있듯이 DES는 대칭키 암호이면서 블록암호이기 때문에 64bit씩 블록단위로 암호화가 됩니다.

반대로 스트림암호는 블록암호와 다르게 블록단위로 암호화를 진행하지 않고 한번에 암호화를 하는 암호방식 입니다.

 

블록암호의 특징

 

1. 혼동 (Confusion)

    - 키와 암호문의 관련성을 모호하게 하는 암호화 연산

    - 일반적인 혼동요소는 환자(Substitution)이고 DES와 AES에서 발견  

2. 확산 (Diffusion)

    - 평문의 통계적 특성을 숨기기 위한 목즉으로 하나의 평문기호의 영향이 많은 암호문 기호에 퍼지도록 하는 연산 

    - 단순환 확산요소는 비트 전치(Bit Permutation)으로 DES에서 많이 사용된다. 

 

위의 두가지 방식이 있지만 혼동만 수행하는 환자암호, 확산만 수행하는 전치 암호만으로는 안전성을 만족하지 못합니다.

왜냐하면 결국 경우의 수가 존재하기 때문이죠 그래서 확률을 높이기 위해서 두연산을 혼합하게 되는데 이것을 곱 암호

(Product ciphers) 라고 합니다.

 

 

저번 포스팅에 이어서 이번에는 Basic Program Excution Register (BPER) 을 조금 더 심화적으로 알아보도록 할겁니다.

 

1.  Basic Purpose Register - 범용레지스터 (32 bit, 8개)

    - 산술연산 (ADD, SUB, XOR , OR 등) 명령어에서 상수 / 변수의 값을 저장하는 용도로 사용

 

1-2. 종류     

    - EAX : Accumulator for operands and result datas -> 일반적으로 함수의 리턴값에 사용
    - EBX : Pointer to data in the DS segment
    - ECX : Counter for String and Loop operations -> 반복문 명령어에서 반복 카운터로 사용
    - EDX : I/O Pointer

 

지금현재 8개의 레지스터중 4개를 살펴보았습니다. (그럼 나머지 4개는?)

4개는 아래와 같으며 4개씩 따로 살펴보는 이유는 주로 연산과 관련된 레지스터와 메모리의 주소를 저장하는

포인터로 사용되는 레지스터이기 때문에 기능적인 부분에서 차이가 있습니다.

 

1-3. 종류

    - EBP : Pointer to data on the stack (in the SS segment)

      함수가 호출되었을때 ESP를 저장하고 있다가 함수가 리턴하기 직전에 ESP에 값을 되돌려줌

    - ESI : Source Pointer for String operands

    - EDI : Destination Pointer for String operands

    - ESP : Stack Pointer (in the SS segment) 

     스택 메모리의 주소

 

2. Segment Register - 세그먼트 레지스터 (16 bit, 6개) 

- 세그먼트라는 메모리의 한 영역의 주소를 지정하는 레지스터

- 세그먼트 : 프로그램에 정의된 코드나 데이터 및 특정 영역을 저장하는 곳

 

2-2. 종류

보시면 여러가지의 세그먼트 들이 존재합니다만, 처음에 중요하게 살펴봐야 할 세그먼트 레지스터는  DS 입니다. 

먼저 종류들을 살펴보겠습니다. 

 

CS - Code Segment 실행될 기계 명령어를 포함하는 영역   

      - EIP가 있기때문에 직접적으로 볼 일이 많이 없음 

DS - Data Segment 프로그램의 정의된 데이터나 상수, 작업영역을 포함

      - 레지스터에서 프로그램에 저장된 데이터나, 상수, 변수 등을 읽어올때 접근

SS - Stack Segment 스택 세그먼트

     - 컴파일 과정에서 데이터가 스택에 쌓이게 되는데 EBP / ESP가 있기때문에 볼 일이 많지 않음

ES - Extra Segment 메모리의 주소를 다루는 스트링(문자열 연산)에 사용

 

자세한건 여기를 참고하시면 좋을 것 같습니다.

 

https://ko.wikipedia.org/wiki/X86_%EB%A9%94%EB%AA%A8%EB%A6%AC_%EB%B6%84%ED%95%A0

 

x86 메모리 분할 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. x86 메모리 분할(x86 memory segmentation)은 인텔 x86 명령어 구조를 사용하는 컴퓨터에서 구현된 메모리 분할기법을 말한다. 메모리 분할은 1978년 발표된 인텔 8086에서

ko.wikipedia.org

 

3. Program Status and Control Registers - 프로그램의 제어/ 상태 (플래그 레지스터, 32bit, 1개)

산술 연산 결과의 상태를 보여주는 flag bit들이 모인 레지스터
산술 연산시 CPU에 의해 자동적으로 세팅되며 , 프로세서의 현재 상태를 결정

 

지금 보이는 그림은 Flag 레지스터에서 확장된 버전인 EFlag 레지스터 입니다.

여기에서 발생하는 플래그들의 내부적인 부분을 알아보겠습니다.

 

중요하게 봐야할 부분은 3가지 입니다. 

 

ZF - Zero Flag

- 연산결과가 0이면 1로 설정 -> ZF = 1

OF - Overflow Flag

- 부호가 있는 수(Signed integer)의 오버플로우가 발생하면 1로 설정

- MSB(최상위 비트)가 변경이되면 1로 설정

CF - Carry Flag

- 부호가 없는 수 (Unsigned integer)의 오버플로우가 발생하면 1로 설정 

 

4. Instruction Pointer - 명령어 포인터 레지스터

CPU가 처리할 명령어의 주소를 나타내는 레지스터

CPU는 EIP/IP에 저장되어있는 주소의 명령을 수행한 후, 명령어의 길이만큼 값을 증가

사용자가 직접 수정할 수 없음 

-> 다른 명령어를 사용하여 간접적으로 변경 (JMP, CALL, RET...etc) 

 

이번에는 레지스터에 대해서 알아보았습니다. 

이번 포스팅에 언급한 레지스터 말고도 FS, GS, PF. TF 등등 아직 봐야할 레지스터들이 있지만 

종류가 많고, 봐야할것도 많기 때문에 한번에 전부다 알지는 못할 것입니다. 따라서 이것들을 이해하기 위해서는

직접 예제들을 분석해보는 시간을 가지면서 익숙해지다 보면 알게 될 거라고 생각합니다.

이번에는 레지스터에 대해서 알아보았습니다. 

다음 포스팅에서는 스택에 대해서 알아보도록 하겠습니다.

 

이번시간에는 저번 포스팅에 이어서 리버싱에서 필수적으로 알아야할 레지스터에 대해서 알아보도록 하겠습니다.

먼저, 레지스터란 무엇일까요?

 

CPU 레지스터 ???

- CPU 내부에 존재하는 다목적 저장공간 

- CPU 내부에 존재하여, RAM에 비해 고속의 데이터 처리가 가능

 

설명하기에 앞서 레지스터의 종류가 많이 있습니다만,  알아볼 것은 분석하는데 필요로하는 레지스터를 알아보겠습니다.

 

여기서 알아볼 것은 프로그램을 동작시키는데 필요한 레지스터인 Basic Program Execution Registers 입니다. 

 

Basic Program Execution Registers - 4개의 그룹으로 구성

1. General Purpose Registers - 32 bit, 8개 

    - 일반적으로 사용하는 레지스터 

2. Segment Registers - 16 bit 6개 

    - 세그먼트를 저장하는데 사용하는 레지스터

3. Program Status and Control Registers - 32 bit, 8개 

    - 프로그램의 상태와 제어를 담당하는 레지스터

4. Instruction Pointer - 32 bit 1개

    - 명령의 실행을 위해서 명령어의 위치가 저장되는 레지스터 

 

총 4개로 구성이 되어있는데 한번에 다 서술을 하려고 하니까 양이 많아서 나눠야 할 것 같습니다.

다음 포스팅에서는 이것을 조금 더 심화적으로 다뤄보도록 하겠습니다.

 

지난 포스팅에서는 Helloword 프로그램을 분석해보면서 메인함수를 찾아보고,

메세지박스의 값을 변조하는 메모리 변조방법에 대해 알아보았습니다. 

 

이번 포스팅에서는 디버깅의 기초개념을  사용되는 바이트 오더링에 대해서 알아보도록 하겠습니다. 

 

Byte Odering? 

컴퓨터가 데이터를 저장하는 방식으로 리틀엔디언과 빅엔디언으로 나뉘게 됩니다. 

저장되는 방식은 아래의 표와 같습니다.

Type Name Size Big Endian Little Endian
Byte a 1 [12] [12]
WORD b 2 [12][34] [34][12]
DWORD ab 4 [12][34][56][78] [78][56][34][12]
char[] str 4 [12] [12] [12][00] [12] [12] [12][00]

 

정리를 해보면 다음과 같습니다.

 

Little Endian -> 데이터를 역순으로 저장 (역방향)

- 직관적이지 않음 (사람이 보기 힘듬)  / 데이터를 효울적으로 저장 / Windows에서 사용됨

 

Big Endian -> 데이터를 순차적으로 저장 (정방향)

- 사람에게 직관적  / Windows intel 에서 사용하지 않음 / 서버용 CPU에서 사용됨 

 

하지만 여기서도 예외는 존재하는데요, 보시면 byte와 char부분은 리틀엔디언과 빅엔디언이 일치합니다.

이것은 멀티바이트만 리틀엔디언이 적용된다는 말이됩니다.

 

윈도우에서는 리틀엔디언 방식을 사용하기 때문에 리틀엔디언 방식이 사용되는지 한번 확인해보겠습니다.

확인을 해보기 위해서 아래와 같은 코드를 작성하였습니다.

#include<windows.h>
#include<stdio.h>

BYTE a = 0X12;
WORD b = 0x1234;
DWORD ab = 0x12345678;
char str[] = "abcde";

int main(void)
{
	BYTE lb = a;
	WORD lw = b;
 	DWORD lwd = ab;
 	char* lstr = str;
 	printf("리틀엔디언 저장방식");
    
    while(TRUE){}
    
    return 0;
}

 

이제 해당 프로그램을 분석 해보겠습니다. 먼저, 디버거를 열어서 확인해 보았습니다.

 

저번처럼 일일히 분석해도 되지만 그것은 간단한 프로그램일 경우 가능한것이고 (물론 지금도 가능하긴합니다)

프로그램들의 로직이 복잡해지면 하나씩 분석하기가 힘들어질 것입니다. 그래서 중단점 (Break Point)를 활용하였습니다. 

일단 프로그램이 실행이 되어야 하기때문에 Main 함수로 이동하는 코드가 있을것 입니다.

 

생각했던것 처럼, 프로그램이 실행되는 부분으로 이동하는 코드에 BP가 설정되어있었습니다. 내부로 들어가보겠습니다.

 

함수이름이 jmp MainStartup이라고 되어있는것으로 봐서 메인함수를 시작하는 곳으로 점프하는 구문인것 같습니다.

.

들어가보면 Main 함수로 추정되는 곳이 보입니다. 한번 더 들어가서 확인해 보겠습니다.

 

한번 더 들어가보니 Main 함수를 호출하는부분이 또 보입니다.  더 들어가서 확인해 봐야할 것 같습니다.

 

계속 들어가서 확인해보니 드디어 찾고있던 Main 함수 부분에 도달한 것 같습니다. 

 

이렇게 프로그램도 정상적으로 작동하는 것을 확인했습니다. 

그리고 BP를 걸고 메인함수의 어셈블리 코드를 보면서 분석을 해보겠습니다. 

 

바로 이부분인데,  C언어로 작성한 코드를 생각하면 여기에 작성한 소스코드에 따라서 특정한 주소에 값들이 들어가

있을것입니다. 한번 저장된 값들을 확인해보겠습니다.

 

0x00007FF7EC21C000 주소에 BYTE의 값이 들어가 있는것 같습니다. 확인해보도록 합시다.

ctrl +G로 주소에 저장된 값을 검색해 보았습니다.

 

검색을 해보면....

 

검색을해서 찾아보니 정확하게 값이 코드에서 작성한 값이랑 동일하게 들어간 것을 확인할 수 있었습니다.

그리고 리틀엔디언은 멀티바이트만 역순으로 저장을 한다고 하였습니다.

byte의 값인 12와 문자열의 값인 abcde는 그대로 순차적으로 저장이되었습니다.

그리고 나머지 값들은 역순으로 저장이되어 있는데, 리틀엔디안 방식으로 저장된 것을 확인할 수 있었습니다.

 

이번에는 이렇게 바이트 오더링에 대해서 공부해보았습니다. 

다음 포스팅에서는 레지스터와 스택에대해서 한번 알아보도록 하겠습니다.

저번 포스팅에서는 리버싱이 무엇인지와 분석 방법 및 분석 도구들을 알아보았습니다.

그래서 이번에는 직접 프로그램을 분석해보는 시간을 가져보도록 하겠습니다.

(이번 포스팅에 사용된 리버싱도구(디버거)는 x64dbg 입니다.) 참고하시면 될 거 같습니다.

 

일단 그럼 먼저 분석을하기 위해서는 hello world 프로그램이 있어야 분석을 할 수 있겠죠?

#include <windows.h>
#include <tchar.h> 

int main(int argc, TCHAR *argv[])
{
	MessageBox(NULL, L"Hello world",L"Reverse start", MB_OK);
}

 

위와 같이 hello world를 출력하는 프로그램을 한번 작성을 해보았습니다.(win32API를 사용했습니다.)

그럼 빌드를하고 실행을 하면 아래와 같이 나오게 됩니다. 

 

빌드의 과정은 아래의 글을 참고하시면 좋을 것 같습니다. (설명이 많기에..)

https://st-lab.tistory.com/176

 

프로그래밍 언어와 빌드 과정 [Build Process]

안녕하세요. 제가 이 시리즈를 작성할 때 처음 계획했던 것이 있습니다. 최소한의 프로그래밍언어에 대한 작성 방법은 알고 있다는 전제하에 프로그래밍 전반에 관한 내용을 다뤄본다고 했죠.

st-lab.tistory.com

 

자,  빌드의 과정을 알았다면, 이전해도 이야기 했듯이 리버싱은 빌드의 과정을 반대로 하는 것 입니다. 

코드를 작성하였으니 실행을 해봅시다.

 

이렇게 제목은 Reverse start 고  Hello world라는 메세지가 메세지 박스에서 출력되는 프로그램을 제작하였습니다.

이 프로그램을 한번 분석해보겠습니다.

 

x64dbg 를 실행하고 파일을 열어주면 이러한 화면이 나오게 되는데, 아직은 초보단계이니,

자세한건 나중에 설명드리도록 하겠습니다. (우리가 알아야 할것은 메인함수를 찾는 것 입니다.)

메인함수에 코드를 작성했으니 메인함수를 찾으면 프로그램의 동작원리를 알 수 있을것 입니다.

 

1. 어셈블리 (기계어) 코드가 나와있고 직접 코드를 따라가보면서 디버깅을 할 수 있는 창입니다

2. 디버깅을 하면서 현재 레지스터에 무슨 값이 들어가있는지 볼 수 있는 레지스터를 표시해주는 창입니다.

3. Hex 값을 볼 수 있는 Hex dump 창 입니다.

4. 현재 스택이 어떻게 쌓이는지 볼 수 있는 스택 창 입니다.

 

지금부터 분석을 해 볼 것인데.. 제일 처음알아야 하는것은 EP - Entry Point가 될 것입니다 .

쉽게 말해서 처음시작하는 메모리의 주소라고 보시면 됩니다.

 

그렇다면 00007FFB0F572B785가 Entrypoint가 되겠네요 분석을 한번 시작해 봅시다. 

혹시나 만약에 궁금증이 생길 수도 있으니 (아님 말고) 한번 설명을 해드리도록 하겠습니다.

작성한 코드는 몇개 없지만  왜 이렇게 많은 어셈블리어 코드들이 있는것인가 라고 생각하신다면 그것은

프로그램의 빌드과정에서 일어난 일이라고 생각하시면 됩니다. 

 

그럼 한번 분석을 해봅시다.

F8을 누르게되면 함수를 한줄 한줄 실행 할 수 있습니다. 

일단 프로그램의 의도대로 메세지 박스가 나올때 까지 실행을 해보겠습니다.

r

계속 실행을 하던 중 작성했던 코드대로 메세지 박스를 띄어주는 부분을 찾았습니다.

call hello_world ( 00007FF6AFB71D09)부분에서 F8을 눌러 실행했더니 메세지 박스가 나왔습니다.

그럼 해당 주소가 아직은 잘 모르겠지만 메인함수와 관련이 있다는 것을 짐작 해볼 수 있을것입니다.

그래서 F2를 눌러 가까운 지점에 브레이크 포인트(중단점)을 설정해뒀습니다. (00007FF6AFB71D00)

브레이크 포인트를 설정하게 되면 나중에 한번에 이동 할 수 도 있고 내가 원하는 지점에서 일시정지를 할 수 있습니다.

확인을 누르면 프로그램이 종료가 되니 확인을 누른 뒤에 다시한번 실행해보겠습니다.

 

다시 실행한 뒤에 빨간색으로 표시된 부분을 클릭하면 설정해둔 브레이크 포인트로 바로 이동이 가능합니다.

아니면 아래에있는 빨간점으로 표시된 부분을 클릭하면 현재 설정해둔 모든 브레이크 포인트 지점을 볼 수 있습니다.

보고 클릭하여 이동하시면 됩니다. 그렇게 이동을 하고 나서 보면 call hello_world라는 부분에서 실행을 하면 메세지박스가

실행이되서 화면에 나왔었는데, 세부적인 부분을 확인하기 위해서 call 하는 부분에 F7을 눌러서 함수의 내부로 들어가 

보도록 하겠습니다. 

 

들어왔는데 계속 한번 실행해 보겠습니다.

 

내부에서 계속 실행해보니 메세지 박스를 띄어주는 부분을 찾았습니다. 

그럼 이 부분도 내부적으로 한번 들어가 보도록 하겠습니다. 

 

한번더 내부로 들어왔는데 계속 실행해 보겠습니다.

 

다시한번 메세지 박스를 띄우는 곳을 찾았고, 브레이크 포인트를 걸어뒀는데, 계속해서 살펴보겠습니다.

 

실행을 계속 하던 중 전에 작성했던 코드와 비슷한 부분을 발견했습니다. 아마도 여기가 메인함수 인 것 같습니다. 

문자열을 보면 코드에서 작성했던 부분이랑 일치 하는 것을 볼 수 있습니다.  마지막에 call이라는 부분을 살펴보면

메세지 박스를 호출하는 부분이 있습니다. 그렇다는 것은 지금 보이는 문자열대로 메세지 박스를 띄어준다는 의미가

됩니다. 이렇게 프로그램의 흐름을 한번 따라가 보았습니다.

 

자, 여기서 한번 시도해볼 것이 있는데  코드를 보면 call 부분에 메세지 박스를 띄어주는 함수가 있습니다.

하지만 이부분을 제거해준다면? -> 더이상 메세지 박스가 화면에 나오지 않을것입니다. 

그리고 위에 문자열을 받아오는 부분에서 문자열을 바꿔준다면??  -> 메세지 박스의 문자가 바뀔것 입니다. 

 

한번 해보겠습니다. 

메세지 박스의 제목인 Reverse Start 와 같은 문구로 메세지를 변경 해보도록 하겠습니다.

 

Reverse start 문자열을 받아오는 곳의 주소를 복사한 다음, Hello world 부분에 덮어씌워서 변경을 해보았습니다.

커서를 올린다음, 스페이스바를 누르면 위의 사진처럼 수정이 가능합니다. (주소 부분의 복사를 진행하였습니다.)

 

표시된 부분을 보면 Helloworld 부분에 복사한 주소값을 넣어주니까 문자열이 변경된 것을 볼 수 있습니다.

 

실행을 하면 Helloword 부분이 완전히 Reverse start로 변경이 되었고, 문자열이 메세지박스로 출력이 되었습니다.

이런식으로 프로그램을 분석하는데 그치지 않고 메모리의 주소 값을 이용해서 원하는 값으로 변조를 해보았습니다.

 

이것으로 이번에는 Helloworld를 한번 분석해보고 변조를 해보면서 리버싱의 기본적인 원리를 한번 알아보았습니다.

포너블이라는 카테고리에도  GDB를 이용해서 분석하는 글이 포스팅 되어있는데 궁금하거나 자세한 사항을 알고 싶은 

분들은 한번 참고해봐도 좋을 것 같습니다.

https://nuker3.tistory.com/76

 

찬희의 Pwn 포너블 기초 2주차 1차시 GDB를 사용해보자 1

일단 시작하기 앞서서 GCC와 GDB 설치가 필요하겠죠? apt install GDB apt install GCC 해당 코드를 작성을 해두었습니다 #include void a(char * name, int age){ printf("%s %d\n",name,age); } int main(void){ char name[10] = "shj"; in

nuker3.tistory.com

 

리버싱이란 무엇일까요?

예를 들어서 저희가 스마트폰을 만든다고 가정을 한다면, 설계도를 그려서 재료를 구하고 공장에서 만든 다음,

제품으로 출시를 할 것입니다. 이것을 반대로 한다고 생각하면 되는데, 이해하기 쉽게 구조를 한번 도식화 해보겠습니다.

 

우리가 알고 있는 공학이 정방향이라면 리버싱은 역방향이라고 보시면 됩니다.

1. 앞의 예시처럼 스마트폰을 하나 만든다고 가정했을때, 스마트폰을 만들 설계도가 있어야 할것입니다. 

2. 설계도에서 제시한 스마트폰을 만들수 있는 재료들이 필요할 것입니다. 

3. 재료를 얻었다면 재료들을 이용해서 설계도에 조건에 맞게 스마트폰을 제작을 할 것입니다. 

4. 마지막으로 스마트폰 제조가 완료가 된다면 제품화를 시켜서 시장에 출시를 하게 될것입니다.

--> 여기까지가 우리가 알고 있는 공학 : 엔지니어링 이라는 예시 입니다. 

 

--> 그렇다면 지금부터는 역공학 : 리버스 엔지니어링에 대한 관점에서 한번 이야기 해보도록 하겠습니다.

1. 스마트폰 제품을 확인하고 제품의 조립상태나 디자인, 부품 및 제조사 등의  재료들을 파악해야 할 것입니다.

2. 그 내용을 바탕으로 어떠한 방식으로 만들어졌는지, 어디서 만들어졌는지, 제작과정을 연구를 할 것입니다.

3. 제작과정을 완전히 알아낸다면 똑같은 설계도를 구현할 수 있을 것입니다.

--> 이러한 리버스 엔지니어링(리버싱)을 전문적으로 하는 사람들을 통틀어서 리버서 라고 합니다.

 

소프트웨어 개발자(Software Developer)리버서(Reverser)는 서로 반대되는 입장이라고 생각하면 됩니다.

 

분석방법 

리버스엔지니어링에도 분석방법이 여러가지가 있는데 크게 2가지로 정적분석과 동적분석이 있습니다.

1. 정적분석은 프로그램이나 파일을 실행하지 않은 상태에서 분석하는 방법을 의미합니다.

--> 간단하게 말해서 파일이나 프로그램의 겉모습만 보고 분석을 하는 방법입니다.

 

2. 동적분석은 프로그램이나 파일을 실행한 상태에서 동작들을 분석하는 방법을 의미합니다.

--> 동적분석은 파일이나 프로그램의 깊숙한 곳에 들어가서 동작원리를 관찰하고 분석하는 방법입니다.

 

그렇다면 왜 사용하는 것일까? (동적분석  vs 정적분석) 

분명히 사용하는데에는 이유가 있겠죠? 하나씩 설명해드리겠습니다.

먼저 정적분석의 경우 프로그램을 직접 실행하지 않은 상태에서 분석을 하기 때문에

자세하고 세부적이거나 내부적인 것들을 분석하는데 분명히 한계가 존재합니다.

하지만, 만약에 내가 분석해야할 프로그램이 악성코드나 랜섬웨어 같이 악성 프로그램이라면??

(동적분석 보다는 정적분석이 안전할 것입니다.)

 

자, 그럼 동적분석이 사용되는데에는 어떠한 것들이 있을까요?

동적분석은 프로그램을 실행한 뒤 실행한 상태에서 분석을 하기 때문에 정적분석 보다 해당 프로그램이나 파일에 대해

깊이 파고들어서 내부에서만 실행되는 동작이나 특수한 기능을 하는 동작들을 정적분석 보다 쉽게 파악할 수 있고, 

조금더 정확하게 분석이 가능합니다. 위의 예시처럼 악성코드나 랜섬웨어 같이 악성프로그램은 정적분석이 안전하겠지만,

게임이나 메신저 프로그램 같은 것들을 분석할때는 정적분석보다 동적분석이 정확하게 분석이 가능할 것입니다. 

(정확한 분석이 필요할때 사용을 한다고 생각하면 좋을 것 같습니다.)

 

정적분석과 동적분석이 사용되는 이유와 사용되는 방식을 한번 알아보았습니다.

지금부터는 리버서들이 많이 사용하는 리버싱 도구들을 몇가지 소개해 드리도록 하겠습니다. 

 

1. Ollydbg

정적분석과 동적분석이 모두 가능한 도구라서 리버싱에 기본적으로 사용됩니다.

무료이고 입문할때 많이 사용되는 도구입니다. 하지만 32bit에 국한되는 단점도 존재합니다. 

따라서 리버싱을 입문하는 용도로 많이 사용되고 있습니다.

https://www.ollydbg.de/

 

OllyDbg v1.10

 

www.ollydbg.de

 

2. x64dbg / x32dbg

Ollydbg와 매우 유사한 도구이지만 개인적인 생각으로는 Ollydbg의 단점들을 잘 보완해놓은 도구입니다.

무료이고 Ollydbg 같은경우는 영어로 되어있지만 x64dbg / x32dbg 같은 경우, 한국어로도 사용이 가능합니다.

그리고 Ollydbg는 32bit에서만 사용이 가능하지만 x64dbg는 64bit에서도 사용이 가능합니다. 

 https://sourceforge.net/projects/x64dbg/

 

x64dbg

Download x64dbg for free. An open-source x64/x32 debugger for windows. An open-source x64/x32 debugger for windows. Development is done on GitHub (https://github.com/x64dbg/x64dbg).

sourceforge.net

 

3. IDA pro

강력한 기능을 가지고 있는 도구이지만,  유료라는 단점이 있습니다. 

하지만 다른도구들과는 달리 유용한 기능이 정말 많기 때문에 유료이지만 리버서들이 애용하는 도구들 중 하나 입니다.

https://hex-rays.com/ida-pro/

 

Hex Rays - State-of-the-art binary code analysis solutions

Substantial changes Is to be expected in every release: new features, supported processors, etc which are all added after deliberation and discussion.

hex-rays.com

 

4. Ghidra

미국의 국가안보국 (NSA)에서 만든 리버싱 도구 입니다. (IDA의 대체제로 많이 사용되는 것 같습니다.)

위의 IDA pro에 비해 부족한 기능들도 있기는 하지만 무료인점을 감안하면 괜찮은 도구라고 생각합니다.

기존의 IDApro에 적응을 하신 분들이라면 처음에는 불편할 수 있을 것 같습니다.

https://github.com/NationalSecurityAgency/ghidra

 

GitHub - NationalSecurityAgency/ghidra: Ghidra is a software reverse engineering (SRE) framework

Ghidra is a software reverse engineering (SRE) framework - GitHub - NationalSecurityAgency/ghidra: Ghidra is a software reverse engineering (SRE) framework

github.com

 

5. GDB

유닉스기반 운영체제에서 사용되는 도구입니다. 

리눅스에 익숙하신분들은 사용해보셔도 좋을 것 같습니다. 

(GDB 같은경우 거의 리눅스에서 사용을 하고 있어서 자세한 부분은 Pwnable쪽에 업로드 했으니 확인하시면 됩니다.)

sudo apt-get install gdb

힌트를 확인해보도록 하자

The password for the next level can be retrieved

by submitting the password of the current level to port 30000 on localhost.

포트번호는 30000이고 localhost에 기존의 패스워드를 입력하면 나온다고 한다.

그럼 저번 문제처럼 ssh로 접속을하면 되지 않을까 생각해서 접속을 해보았다.

ssh bandit15@localhost -p 30000

 

보안상의 문제로 ssh는 접속이 안되는거 같다. 

그러면 nc나 telnet 명령어를 사용해서 접속을 해봐야 할 거 같다. 

nc localhost 30000

 

접속을 하고 기존의 패스워드였던 bandit14의 패스워드를 입력하면 다음 레벨로 올라가는 패스워드를 얻을 수 있다.

ssh 접속 대신에 nc나 telnet을 이용할 수 있는가에 대한 문제인거 같은데 telnet으로도 풀 수 있는지 한번 시도를 해보았다.

telnet localhost 30000

 

동일하게 풀리는 것을 확인 할 수 있었다.

힌트를 확인해보도록 하자

The password for the next level can be retrieved

by submitting the password of the current level to port 30000 on localhost.

포트번호는 30000이고 localhost에 기존의 패스워드를 입력하면 나온다고 한다.

그럼 저번 문제처럼 ssh로 접속을하면 되지 않을까 생각해서 접속을 해보았다.

ssh bandit15@localhost -p 30000

 

보안상의 문제로 ssh는 접속이 안되는거 같다. 

그러면 nc나 telnet 명령어를 사용해서 접속을 해봐야 할 거 같다. 

nc localhost 30000

 

접속을 하고 기존의 패스워드였던 bandit14의 패스워드를 입력하면 다음 레벨로 올라가는 패스워드를 얻을 수 있다.

ssh 접속 대신에 nc나 telnet을 이용할 수 있는가에 대한 문제인거 같은데 telnet으로도 풀 수 있는지 한번 시도를 해보았다.

telnet localhost 30000

 

동일하게 풀리는 것을 확인 할 수 있었다.

힌트를 확인해 보자 

The password for the next level is stored in /etc/bandit_pass/bandit14 and can only be read by user bandit14.

For this level, you don’t get the next password, but you get a private SSH key that can be used to log into the next level. Note: localhost is a hostname that refers to the machine you are working on

대충 해석해보면 현재레벨에서는 접근이 불가하니 ssh로 접속하여 해당 디렉토리( /etc/bandit_pass/bandit14  경로로 이동한 후 패스워드를 획득하라는 내용이다. 일단 로그인을 한번 해보았다.

 

뭔가 엄청나게 많은 문자가 보이는데 찾아봐야 할 것들이 RSA Private key와 sshkey.private인데  확인을 해보기로 했다.

 

SSH : 텔넷(Telnet)과 용도는 같지만, 보안이 강화원격 접속 서비스이다.

- SSH를 이용하여 원격 접속하면 서버와 클라이언트 사이에 데이터를 전송할 때 암호화를 하게 된다.

- RSA 등 암호화 기법을 사용하며, 압축 기술 또한 제공하고 있다.

- 리눅스에서는 openssh를 통해 SSH를 이용할 수 있다.

- 포트 번호는 22번이다.

 

RSA 공개키 암호

현재 SSL/TLS에 가장 많이 사용되는 공개키 암호화 알고리즘이다.

전세계 대부분의 인터넷 뱅킹(대한민국 포함)이 이 RSA-2048 암호화를 사용한다.

 

- 공개키는 누구나 아는 키이므로, A가 B에게 보낼 때 B의 공개키로 암호화하여 전송

- 이 때, B의 공개키로 암호화했기에 B의 비밀키로 복호화 가능
- 해커가 탈취해도 정보를 알 수 없음 (대칭키의 키값 교환 문제 해결)
- 해커가 파일 탈취하여 B의 공개키로 이상한 파일을 암호화하여 보낼 위험성 존재

 

그럼 우리가 알 수 있는 것은 개인키를 알고 있으니까 개인키를 이용해서 로그인을 하면 되지 않을까 생각해 볼 수 있다.

힌트에서는 localhost로 로그인을 하라고 했으니까 한번 ssh를 이용해서 로그인을 해보면 될거같다. 

ssh 옵션중에는 -i라는 옵션이있는데 이것은 원격에서 네트워크 상의 컴퓨터에 접속할 수 있다.

ssh 는 강력한 보안을 제공하기에 안전하지 못한, 개방된 네트워크에서도 안전하게 통신할 수 있다.

한번 접속을 해보았다 (지금은 그냥 22포트로 접속을하면 에러가 나오기 때문에 2220으로 접속을 해야한다.)

ssh -i sshkey.private bandit14@localhost -p 2220

 

yes를 입력하면 정상적으로 로그인이 된다.

로그인을 한 뒤에 힌트에서 말한 패스워드가 저장되어있는 디렉토리로 이동을 해보았다,

 

여기서 bandit14를 실행하면 되는데 먼저 열 수 있는 권한이 있는지 확인해보았다.

 

읽을 수 있는 권한이 있으니까 확인 후에 읽어보면 될 거 같다.

 

패스워드를 알 수 있었다. 

공개키 암호와 ssh 프로토콜을 잘 알아야 풀 수 있는 문제 같다.

힌트틀 확인해보면 

 

The password for the next level is stored in the file data.txt,

which is a hexdump of a file that has been repeatedly compressed.

For this level it may be useful to create a directory under /tmp in which you can work using mkdir.

For example: mkdir /tmp/myname123.

Then copy the datafile using cp, and rename it using mv (read the manpages!)

 

data.txt 파일안에 패스워드가 있기는 한데 Hex로 덤프가 되어있고, 여러번의 압축이되었다고 한다.

그리고 새로 디렉터리를 만든 다음 해당 디렉터리에 복사해서 문제를 푸는 것이 유용하다고 한다.

그럼 힌트의 취지의 맟춰서 문제를 풀어보았다.

 

일단 들어가면 data.txt가 보인다.

 

그리고 실행해보면 힌트에서 말 했듯이 hex로 덤프가 되어있다.

 

힌트의 의도대로 여기서 디렉터리를 새로 만든다음,  data.txt 파일을 복사를 해보았다.

mkdir /tmp/test_bandit12
cp data.txt /tmp/test_bandit12

 

그리고 hex로 덤프된 파일을 바이너리로 바꾸기 위해서 xxd 명령어를 사용하였다.

xxd -r data.txt data

 

data 파일이 만들어졌고,  분명히 힌트에서는 여러번의 압축이 진행되었다고 했다. 

그래서 압축의 여부를 확인하기 위해서 file 명령어로 해당 파일의 형식과 정보를 알아보았다.

 

gzip으로 압축이 되어있는 것을 볼 수 있다

gzip은 확장자가 .gz로 압축 되어있는 것을 합축 해제 할 수 있기 때문에 확장자를 data -> data.gz로 변경해야 된다.

mv data data.gz

 

확장자가 변경되었으니 압축을 풀어보도록 하겠다. (gzip은 압축해제를 할때  gunzip을 사용한다.)

gunzip -d data.gz

 

다시 압축이 해제 되었는데, 그럼 이대로 실행해도 되는지 아니면 여러번 압축이 되었는지 확인을 해 보았다.

 

이번엔 bzip2로 압축이 되었다. 그럼 해당 압축파일에 맟춰서 확장자를 또 변경해줘야 할 것이다. 

bzip2는 확장자가 .bz2인 압축파일을 해제 할 수 있다.

mv data data.dz2
bzip -d data.bz2

 

다시 해제가 되었는데 파일 형식을 다시 확인해 보았다.

 

이번엔 gzip으로 압축이 되어있었기에 전과 같이 확장자를 바꿔준 다음 해제 해주었다.

 

해제를 해보니 이번에는 tar로 압축이 된 파일이라서 tar로 확장자를 변경 후 해제를 하면 될 거 같다.

mv data data.tar
tar -xvf data.tar

 

압축을 해제 해보니 새로운 파일이 생성되었는데 data5.bin이라는 파일이 생성되었다. 

그럼 bin이라는 확장자는 무엇일까 찾아봐야 하는데 일단 file 명령어로 특징을 확인해보았다.

file data5.bin

 

전과 같이 tar로 압축이 되어있는 것을 확인했으니 전과 같이 tar로 압축된 파일을 해제 하면 될 것이다.

 

똑같이 새로운 파일이 생성되었는데, 전과 같이 계속 진행을 해보았다.

 

계속 진행하다보면 더이상 tar 압축이 풀리지가 않는데 파일을 확인 해 보았다.

file data.tar

 

이번에는 gzip으로 압축이 되어있다. 그래서 gunzip을 통해 압축을 해제 해 주었다.

mv data.tar data.gz
gunzip -d data.gz

 

압축해제를 진행해보니 이제는 압축이 되어있지 않고 text파일로 저장이 되어있는 것 같다. 

그래서 한번 cat으로 실행을 해 보았다.

 

압축풀기와 확장자 변경을 하는 방법에 대해서 숙지하는지 물어보는 문제인거 같다.

사실 지금 생각해보면 그냥 생 노가다였다. 

+ Recent posts