서론
스피지 교육의 하이라이트 밤랩교육이 다가왔다.
사실 밤랩은 하다가 울뻔한 몇 안되는 과제이다. 그만큼 어렵고 낯설다. 이번 교육에서 최대한 잘 설명해보고자 노력할 것이긴 하지만 정말 어려울거다. 화이팅!
밤랩에 나오는 어셈블리어들을 전부 다 해석하는 것에는 어려움이 있다. 그래서 나는 이번에 disasemble 한 코드를 보고 어떻게 감을 잡고 정답을 유추할 수 있는지를 중심으로 알려줄 예정이다.
혹시 코드 한줄한줄을 알고싶다! 하시는 분이 계시다면
https://ttl-blog.tistory.com/1009
[시스템 프로그래밍] 2022 BombLab(밤랩) 상세분석
총 74장 분량이고, 전체 코드 한줄한줄 다 상세하게 적어뒀습니다. (화이팅하세요 :))
ttl-blog.tistory.com
갓말랑님의 블로그를 보면 된다. 아마 위 코드랑 내가 앞으로 다룰 코드는 완전히 같지는 않을 것이지만 각 phase별로 유형은 같기 때문에 괜찮을 것이다.
아 참고로 말랑블로그의 시프 글은 정말 정리가 잘 되어있다. 난 아마 이 글들 없었으면 최우수 절대 못했을 것 같다.
환경설정
gdb 설치
아마 이미 실습시간에 다 했을 것 같긴 한데 혹시 몰라서 적어둔다.
우선 우분투를 열고
sudo apt-get install gdb
명령어를 입력한다.
만약 비번을 모르겠다 하는 사람이 있으면
[Linux] 윈도우 10/11 (Ubuntu/wsl) 비밀번호 초기화
바로 방법으로 들어가 보도록 하자.wsl -u rootpasswd 명령어를 이용하여 root 계정의 새로운 암호를 설정.검은색으로 아무것도 안 나오는 것처럼 보이지만, 실제로는 입력이 들어가고 있다.passwd특정
velog.io
여기를 참고하자
BombLab가져오기
나는
https://csapp.cs.cmu.edu/3e/labs.html
CS:APP3e, Bryant and O'Hallaron
Lab Assignments This page contains a complete set of turnkey labs for the CS:APP3e text. The labs all share some common features. Each lab is distributed in a self-contained tar file. You will need a CS:APP account to download the code. To untar foo.tar, t
csapp.cs.cmu.edu
여기 사이트에서 밤랩을 가져왔다. 근데 여기서 밤랩 다운받으면 압축도 풀어야하고 이것저것 귀찮다.
그래서 내가 다운 받은 코드를 내 깃허브에 올려두었다.
https://github.com/alsswl/spg-bomblab.git
GitHub - alsswl/spg-bomblab
Contribute to alsswl/spg-bomblab development by creating an account on GitHub.
github.com
여기 있다. 이 코드를 우분투에 가져오려면
git clone https://github.com/alsswl/spg-bomblab.git
하면 된다.
완료 후 ls명령어를 입력하면
이런식으로 spg-bomblab파일이 생성된 것을 볼 수 있다.
cd명령어를 통해서 파일에 들어가면 README, bomb, bomb.c가 있는데 우리는 여기서 bomb만 사용한다.
bomb 실행
gdb bomb
명령어를 치면
이렇게 시작하는 것을 볼 수 있다.
permission denied 에러가 발생한다면
chmod +x /home/spg/spg-bomblab/bomb
명령어를 친 후 다시 시도하면 된다.
bomblab 설명
자 이제 본격적으로 bomblab을 시작할 것이다!
bomblab은 총 6개의 phase로 구성되어있다. 우리는 각 phase를 분석하여 각각이 원하는 값이 무엇인지 알아내어 모든 폭탄을 해체해야한다.
만약 폭탄을 터트리면
이런 문구가 나온다. 이러면 점수도 터진것이다. 많이는 아니고 나는 2개 터트렸을 때 1점 감점이었다.
감점되면 secret phase를 수행하여 만회할 수 있지만 저건 매우 어렵고, 이번 교육에서 다루지 않는다. 그래서 폭탄은 터트리지 않는게 좋다.
이를 위한 주의사항도 밑에 설명해 둘 것이니 꼭 지키도록 하자!
또한 특이한 점은 대부분의 다른 과제들과 다르게 모든 사람의 코드가 다르다. 기본적인 유형은 비슷한데 답은 각자 찾아야한다! 화이팅
GDB란?
실행가능한 Binary Program 내부를 들여다 볼 수 있고, 디버깅을 할 수 있게 하는 리눅스 프로그램이다. 기본적인 숫자, 주소는 모두 0x00 형태를 가지고 있다.
어셈블리어란?
기계어 일대일 대응 관계를 갖는 명령어로 이루어진 저수준 프로그래밍 언어
하드웨어를 직접 제어를 하거나 속도를 향상시키기 위해 사용
요즘은 컴파일러가 우리보다 머리가 좋아서 이걸로 코딩하지 않는다.
밑에 글을 보기 전에 코드부터 한번 보자!
GDB 사용법
레지스터의 역할
레지스터의 역할은 위와 같다.
여기서 %rax는 리턴값을 보관한다.
%rdi, %rsi...는 함수를 호출할 때 보내는 파라미터값들이 들어있다
%rbx,%r12..%rbp는 호출 된 함수에서 연산을 위해 잠깐 쓰는 레지스터들이다.
%r10,%r11은 호출한 함수에서 보관해야하는 변수값들을 저장하는 역할을 한다.
밤랩을 원활하게 풀기 위해서는 위에 두줄이라도 꼭 외워야한다.(rsi까지만이라도!)
연산
• 코드 영역에 작성된 어셈블리 소스 코드를 명령어(instruction)라고 함.
- 기본 문법 : [instruction] A B
- add A B : 레지스터 B에 A값을 더한다.
- sub A B : 레지스터 B에 A값을 뺀다.
메모리 주소지정모드
D(Rb,Ri,S) 형태이다.
D : 상수
Rb : 베이스 레지스터
Ri : 인덱스 레지스터
S : 스케일값
공식 : Rb + Ri * S + D
8(%rdx,%rcx,4) 이면 %rbx + %rcx * 4 + 8 이다.
lea와 mov
두 명령어 모두 값을 옮기는 역할을 하지만 중요한 차이점이 있다.
mov는 데이터를 복사하는 역할을 한다.
예를 들어
mov %rax, 8(%rbx)
라는 명령어가 있을 때 이는 %rax안에 있는 값에 해당하는 주소의 값을 읽어와서 %rbx +8 에 넣는다는 의미이다.
반면 lea는 메모리 주소를 계산한 값을 그대로 레지스터에 저장한다.
lea %rax, 8(%rbx)
에서는 %rax에 있는 값을 %rbx +8 에 그대로 집어넣는다.
%rax와 %eax
이건 rax뿐만 아니라 다른 레지스터값에도 적용되는 개념이다. %rax는 64비트이다. 그래서 $0x1234567890123456과 같은 값을 갖는다.근데 %eax는 32비트이다. 따라서 하위 32비트에만 접근하고, 상위 32비트는 다 0으로 취급한다. 그래서 만약 위의 값을 %eax로 변환했을 때 $0x0000000090123456이 된다.
%rax와 (%rax)
%rax는 rax내에 있는 값 그 자체를 나타내고, (%rax)는 rax내에 있는 값에 해당하는 주소 내의 값을 의미한다.
예를들어 rax에 10이라는 값이 들어있고, 10번 주소에는 6이라는 값이 들어있다고 가정하자그럼 이 때 %rax값은 10이고, (%rax)값은 6이다.
비교문과 분기문
어셈블리어에서 모든 연산과 비교문을 수행한 후 1비트 특수 레지스터인 Flag값을 변화시킨다.
CF : Unsigned overflow를 판단하는 비트
ZF : t가 0인지 판별
SF : t가 0보다 작은지 판별
OF : 2의 보수 오버플로우가 있는지 판별
어셈블리어에서는 위 특성을 이용하여 분기문을 만든다.
우선 비교를 원하는 두 수를 비교문으로 비교한 후 이로 인해 변화된 레지스터값을 토대로 분기 여부를 결정한다.
비교문부터 살펴보자
cmp
cmp(b,w,l,q,s) A B : A와 B를 비교하는 것이다. cmp 뒤의 문자는 데이터타입이라 신경쓰지 않아도 된다.
test
test A B : A와 B를 AND연산한다.
다음은 분기문이다.
call
call A : A함수로 이동한다. 기존 주소는 큐에 저장한다.
ret
원래 있던 코드로 돌아간다.(큐에 저장된 주소로 돌아간다.)
jmp
jmp A : A코드로 이동한다.
jmp와 call은 같은 기능을 하는 것처럼 보이지만, call은 현재 있는 주소를 저장하고 돌아올 준비를 하지만, jmp는 그런거 상관 안하고 그냥 이동한다.
그래서 주로 call은 함수를 호출할 때 사용되고, jmp는 반복문이나 조건문에 사용된다.
이제 cmp A B 밑에 있는 분기문에 대해서 살펴볼 것이다.
j(n)e C
계산 결과가 같을 경우 C로 이동한다. (n이 붙으면 반대)
ja(=jg) C
A < B 일 경우 C로 이동한다.(e가 붙으면 <= 의미)
jb(=ji) C
A > B 일 경우 C로 이동한다.(e가 붙으면 >= 의미)
push, pop
이건 중요한 내용이 아니라서 설명한다.
코드를 보면 함수 시작할 때 push를 해두고, 리턴할 때 pop하는 것을 볼 수 있다. 위 함수에서는 %rbx,%rbp,%r12를 현재 연산하고 있는 값을 임시로 저장하기 위해 사용했었다. 따라서 함수를 끝낼 때에는 호출자가 원래 저장했던 값들로 되돌려야한다. 이를 위해 스택을 사용한 것이다. 따라서 위 명령어는 우리가 함수를 분석할 때 고려해야 할 필요가 없다.
알아야 할 명령어
- r(un) : 실행 - b(reak) [주소 or 함수 이름] : [주소 or 함수]에 breakpoint를 설정
- c(ontinue) : break 문에 걸렸을 때, 무시하고 현재부터 다음 breakpoint까지 모두 실행
- k(ill) : 실행 중인 프로그램을 종료함.
- disas [함수이름, 생략가능] : 함수의 instruction 리스트를 보여준다. 생략할 경우 현재 함수.
- ni(next instruction) : 다음 instruction으로 넘어가 실행한다.
- x/[출력횟수][옵션] [주소, $레지스터] : 해당 주소의 데이터를 형식에 따라 보여줌
- p/[옵션] [16진수] : 16진수를 형식에 따라 변환한다.
옵션은 아래와 같다.
o : 8진법으로 보여줌
x : 16진법으로 보여줌
u : 10진법으로 보여줌
t : 2진법으로 보여줌
b : 1 byte 단위로 보여줌(byte)
h : 2 byte 단위로 보여줌(half word)
w: 4 byte 단위로 보여줌(word)
g : 8 byte 단위로 보여줌(giant)
i : 역어셈블된 명령어의 명령 메모리를 볼수 있음
c : ASCII 표의 바이트를 자동으로 볼 수 있다.
s : 문자 데이터의 전체 문자열을 보여준다.
이런식으로 사용할 수 있다. 여기서는 rsi레지스터에 있는 값을 문자열 형식으로 출력한 것이다.
주의사항
모두 다 분석하려고 하지 말기
밤랩에서의 코드 양은 어마어마하게 많다. 이걸 다 분석하려고 하면 정말 오래걸릴 것이다. 그래서 자료들을 토대로 각 phase에 대해서 이해하고, 흐름을 파악하여 핵심 instruction에서 register값을 찾는 것이 중요하다.
breakpoint설정하기
정말정말정말정말정말정말정말 중요하다.
무조건 gdb 시작하면 breakpoint를 설정해야한다. breakpoint는 breakpoint가 걸린 함수가 호출되면 실행을 잠시 중단한다. 우리는 이를 통해 해당 시점의 레지스터값을 확인할 수 있고, 또한 explode_bomb에 breakpoint를 걸면 폭탄이 터지기 직전에 break하기 때문에 q명령어를 통해서 빠져나가면 터트리는 것을 방지할 수 있다.
gdb bomb 하자마자
b phase_1
b phase_2
b phase_3
b phase_4
b phase_5
b phase_6
b secret_phase
b explode_bomb
이 명령어 싹 입력해두고 시작해야한다
또한 breakpoint는 실행하며 레지스터 값을 확인할 때에도 유용하다.
b *해당 라인의 주소(ex : *0x40111e) 하면 해당 함수의 해당 번째 줄에 breakpoint가 걸린다.
여기까지가 기본적으로 알아야 할 기본 지식이다!
출처
https://create32.tistory.com/entry/GDB-%EC%82%AC%EC%9A%A9%EB%B2%95-x-%EB%AA%85%EB%A0%B9%EC%96%B4
GDB 사용법 x 명령어
gdb 에서 소스코드를 볼수 있게 하려면 gcc 컴파일시 -g 옵션을 주면 된다.gcc -g test.cgdb -q a.outlist차례로 해보면 소스코드를 보면서 디버깅을 할 수 있다.gdb 는 x 명령어를 사용해 메모리를 조사할
create32.tistory.com
https://csapp.cs.cmu.edu/3e/labs.html
CS:APP3e, Bryant and O'Hallaron
Lab Assignments This page contains a complete set of turnkey labs for the CS:APP3e text. The labs all share some common features. Each lab is distributed in a self-contained tar file. You will need a CS:APP account to download the code. To untar foo.tar, t
csapp.cs.cmu.edu
https://jihyeong-ji99hy99.tistory.com/8
[리버싱] MOV와 LEA의 차이
MOV와 LEA의 차이 먼저 MOV와 LEA의 기능부터 알고 가보면 아래 내용과 같다. 1) MOV - 형식 : MOV dest, src - 기능 : src위치에 있는 데이터를 복사하여 dest위치에 저장 - 원칙 1) 메모리와 레지스터 사이의
jihyeong-ji99hy99.tistory.com
https://ttl-blog.tistory.com/1009
[시스템 프로그래밍] 2022 BombLab(밤랩) 상세분석
총 74장 분량이고, 전체 코드 한줄한줄 다 상세하게 적어뒀습니다. (화이팅하세요 :))
ttl-blog.tistory.com
전 교육부장의 교육자료
'CSE > 시스템프로그래밍' 카테고리의 다른 글
[BombLab] phase_5 해설 (1) | 2024.09.10 |
---|---|
[BombLab] phase_4 해설 (0) | 2024.09.09 |
[BombLab] phase_3 해설 (0) | 2024.09.03 |
[BombLab] phase_2 해설 (0) | 2024.09.02 |
[BombLab] phase_1 해설 (0) | 2024.09.02 |