카테고리 없음

리버싱 1

미숫가루빙수 2024. 3. 19. 17:17

 

 

엔지니어링 <-> 리버스 엔지니어링

엔지니어링- 완성품과 이를 구성하는 부품들의 기능과 설계를 고안 및 제작
리버스 엔지니어링- 완성된 제품을 해체 및 분석, 디자인을 파악

리버스 엔지니어링=리버싱=역공학


현재 내가 배우는 것= 소프트웨어를 대상으로 한 리버싱

 

 

 

리버싱의 용도

Good Case- 개발이 중단된 프로그램에 대한 해치가 필요할 때 사용
Bad Case- 시리얼 넘버 생성기, 크랙 등의 불법 프로그램에 사용

리버싱으로 저작권을 침해하는 행위는 법적인 문제로 이어짐

 

 


관련 저작권법

 

저작권법 제35조의3 (저작물의 공정한 이용) 제1항 제23조부터 제35조의2까지, 제101조의3부터 제101조의5까지의 경우 외에 저작물의 통상적인 이용 방법과 충돌하지 아니하고 저작자의 정당한 이익을 부당하게 해치지 아니하는 경우에는 보도ㆍ비평ㆍ교육ㆍ연구 등을 위하여 저작물을 이용할 수 있다.

 

저작권법 제101조의3 (프로그램의 저작재산권의 제한) 제1항 제6호 프로그램의 기초를 이루는 아이디어 및 원리를 확인하기 위하여 프로그램의 기능을 조사ㆍ연구ㆍ시험할 목적으로 복제하는 경우(정당한 권한에 의하여 프로그램을 이용하는 자가 해당 프로그램을 이용 중인 때에 한한다)

 

 

 

 

 

프로그램과 컴파일

프로그램- 연산 장치가 수행해야 하는 동작을 정의한 일종의 문서

현대 컴퓨터- programmable 연산 장치
일반 계산기- non-programmable 연산 장치

과거에는 전선을 직접 연결, 천공 카드를 이용하여 프로그램을 기록 (에니악)
->비효율적

 

 

 


stored-program computer 등장!!

프로그램=바이너리
-> 프로그램이 이진 형태로 저장되기 때문

 

 

 


컴파일러와 인터프리터

프로그래밍 언어- 프로그램을 개발하기 위해 사용하는 언어 (저급 언어/ 고급 언어)
소스 코드- CPU가 수행해야 할 명령들을 프로그래밍 언어로 작성
컴파일- 소스코드를 컴퓨터가 이해할 수 있도록 기계어로 번역
컴파일러- 컴파일을 해주는 소프트웨어 (GCC, Clang)

 


파이썬과 자바스크립트는 컴파일 필요 x 
인터프리팅- 그때그때 번역되어 CPU에 전달
인터프리터- 이를 처리해주는 프로그램

 

 

 


컴파일 과정

C언어로 작성된 코드-> 전처리, 컴파일, 어셈블, 링크-> 바이너리로 번역

컴파일의 정확한 의미- 어떤 언어로 작성된 소스 코드를 다른 언어의 목적 코드로 번역
소스 코드를 어셈블리어, 소스 코드를 기계어로 번역하는 것 모두 컴파일

 

 


전처리

전처리- 컴파일러가 소스 코드를 어셈블리어로 컴파일하기 전에 필요한 형식을 가공

1. 주석 제거


2. 매크로 치환
-> #define으로 정의한 매크로는 자주 쓰이는 코드나 상숫값으로 단어를 정의


3. 파일 병합
-> 여러 개의 소스와 헤더 파일을 합침

 

 



컴파일

컴파일- C로 작서오딘 소스 코드를 어셈블리어로 번역, 중간에 오류가 있다면 에러를 출력
이 과정에서 어셈블리어가 만들어짐


// Name: opt.c
// Compile: gcc -o opt opt.c -O2

#include <stdio.h>

int main() {
  int x = 0;
  for (int i = 0; i < 100; i++) x += i; // x에 0부터 99까지의 값 더하기
  printf("%d", x);
}



0x0000000000000560 <+0>:     lea    rsi,[rip+0x1bd]        ; 0x724
0x0000000000000567 <+7>:     sub    rsp,0x8
0x000000000000056b <+11>:    mov    edx,0x1356  ; hex((0+99)*50) = '0x1356' = sum(0,1,...,99) 
0x0000000000000570 <+16>:    mov    edi,0x1
0x0000000000000575 <+21>:    xor    eax,eax
0x0000000000000577 <+23>:    call   0x540 <__printf_chk@plt>
0x000000000000057c <+28>:    xor    eax,eax
0x000000000000057e <+30>:    add    rsp,0x8
0x0000000000000582 <+34>:    ret

 

어셈블리어

$ gcc -S add.i -o add.S
$ cat add.S
 
        .file   "add.c"
        .intel_syntax noprefix
        .text
        .globl  add
        .type   add, @function
add:
.LFB0:
        .cfi_startproc
        push    rbp
        .cfi_def_cfa_offset 16
        .cfi_offset 6, -16
        mov     rbp, rsp
        .cfi_def_cfa_register 6
        mov     DWORD PTR -4[rbp], edi
        mov     DWORD PTR -8[rbp], esi
        mov     edx, DWORD PTR -4[rbp]
        mov     eax, DWORD PTR -8[rbp]
        add     eax, edx
        add     eax, 3
        pop     rbp
        .cfi_def_cfa 7, 8
        ret
        .cfi_endproc
.LFE0:
        .size   add, .-add
        .ident  "GCC: (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0"
        .section        .note.GNU-stack,"",@progbits

 

어셈블리어를 컴파일


 

 

 


어셈블


컴파일로 생성된 어셈블리어 코드를 ELF형식의 목적 파일로 변환

 


ELF는 리눅스의 실행파일 형식
PE형식은 윈도우에서 어셈블할 경우의 목적 파일

 

$ gcc -c add.S -o add.o
$ file add.o
add.o: ELF 64-bit LSB relocatable, x86-64, version 1 (SYSV), not stripped
$ hexdump -C add.o
00000000  7f 45 4c 46 02 01 01 00  00 00 00 00 00 00 00 00  |.ELF............|
00000010  01 00 3e 00 01 00 00 00  00 00 00 00 00 00 00 00  |..>.............|
00000020  00 00 00 00 00 00 00 00  10 02 00 00 00 00 00 00  |................|
00000030  00 00 00 00 40 00 00 00  00 00 40 00 0b 00 0a 00  |....@.....@.....|
00000040  55 48 89 e5 89 7d fc 89  75 f8 8b 55 fc 8b 45 f8  |UH...}..u..U..E.|
00000050  01 d0 5d c3 00 47 43 43  3a 20 28 55 62 75 6e 74  |..]..GCC: (Ubunt|
00000060  75 20 37 2e 35 2e 30 2d  33 75 62 75 6e 74 75 31  |u 7.5.0-3ubuntu1|
00000070  7e 31 38 2e 30 34 29 20  37 2e 35 2e 30 00 00 00  |~18.04) 7.5.0...|
00000080  14 00 00 00 00 00 00 00  01 7a 52 00 01 78 10 01  |.........zR..x..|
00000090  1b 0c 07 08 90 01 00 00  1c 00 00 00 1c 00 00 00  |................|
000000a0  00 00 00 00 14 00 00 00  00 41 0e 10 86 02 43 0d  |.........A....C.|
000000b0  06 4f 0c 07 08 00 00 00  00 00 00 00 00 00 00 00  |.O..............|
...


목적파일로 변환한 뒤 나온 16진수

 

 




링크

여러 목적 파일들을 연결하여 실행 가능한 바이너리로 만드는 과정

 

 

 



디스어셈블

어셈블의 역과정

$ objdump -d ./add -M intel
...
000000000000061a <add>:
 61a:   55                      push   rbp
 61b:   48 89 e5                mov    rbp,rsp
 61e:   89 7d fc                mov    DWORD PTR [rbp-0x4],edi
 621:   89 75 f8                mov    DWORD PTR [rbp-0x8],esi
 624:   8b 55 fc                mov    edx,DWORD PTR [rbp-0x4]
 627:   8b 45 f8                mov    eax,DWORD PTR [rbp-0x8]
 62a:   01 d0                   add    eax,edx
 62c:   5d                      pop    rbp
 62d:   c3                      ret
 62e:   66 90                   xchg   ax,ax
...


다음 명령어로 디스어셈블된 결과 확인 가능

 

 

 

 

 

 

 


디컴파일


어셈블리어보다 고급 언어로 바이너리를 번역

이 과정에서 사용하는 것- IDA Freeware