리버싱 1
엔지니어링 <-> 리버스 엔지니어링
엔지니어링- 완성품과 이를 구성하는 부품들의 기능과 설계를 고안 및 제작
리버스 엔지니어링- 완성된 제품을 해체 및 분석, 디자인을 파악
리버스 엔지니어링=리버싱=역공학
현재 내가 배우는 것= 소프트웨어를 대상으로 한 리버싱
리버싱의 용도
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