0. 어샘블리와 디스 어셈블러
1. 어샘블리
컴퓨터는 0과 1로 이루어져 있는 기계어만 알아들을 수 있습니다. 초기에 컴퓨터 공학자들은 0과 1로 코드를 짜다가 현타가 왔는지 어샘블리 언어와 어샘블러를 만들었습니다. 어샘블러는 어샘블리 언어로 코드를 작성하면 기계어로 변환해주는 초기의 코드라고 보시면 됩니다.
2. 디스어샘블리
이제 소프트웨어를 분석해야하는 사람들은 주어진 소프트웨어가 기계어로 이루어져 있으니 그걸 어샘블리 언어로 변환하는 디스어샘블러를 개발했습니다. ( 기계어로 이루어진 프로그램 → 어샘블리 언어 )
1. 어샘블리 명령어
1. 명령어의 종류
설명 | 코드 |
값(데이터) 이동 | mov, lea |
산술연산 | inc, dec, add, sub |
논리연산 | and, or ,xor, not |
비교 | cmp, test |
분기 | jmp, je, jg |
스택 | push, pop |
프로시저 | call, ret, leave |
시스템콜 | syscall |
2. 메모리 피연산자 단위
피연산자 | 설명 |
WORD PTR[rdi] | rdi가 가르키는 주소에서 데이터를 2바이트만큼 참조 |
DWORD PTR [0x12345670] | 0x12345670이 가르키는 주소에서 4바이트만큼 참조 |
QWORD PTR [0x12345670] | 0x12345670이 가르키는 주소에서 8바이트만큼 참조 |
? WORD
WORD라는 자료형이 있습니다. 초기 16Bit 아키텍쳐에서 사용되었던 자료형으로, 크기는 2바이트 입니다.
눈치가 빠르신 분들은 아시겠지만
DWORD, QWORD는 Doble, Quad WORD라고 생각하시면 됩니다.
예시)
mov WORD PTR[rax] , rsi
▶ rsi의 값을 rax가 가르키는 주소 안에 WORD의 크기(2BYTE) 만큼 대입해라
3. 명령어 알아보기
1) mov
mv 목적지, 출발지
☞ 목적지 ◀ 출발지로 출발지에 있는 '값' 을 넣어준다고 생각하면 됩니다.
2) lea
lea 목적지, 출발지
☞ 목적지 ◀ 출발지로 출발지의 '주소 값' 을 넣어준다고 생각하면 됩니다.
3) add
add 목적지, 출발지
☞ 출발지의 값을 목적지에 더해줍니다.
4) sub
sub 목적지, 출발지
☞ 출발지의 값을 목적지에서 빼줍니다.
5) inc
inc 피연산자
☞ 값을 1 증가시킵니다
6) dec
dec 피연산자
☞ 값을 1 감소시킵니다
7) 비트연산자 ( and, or, xor, not)
이름 | and | or | xor | not |
설명 | 둘다 1이여야 1 or 0 | 둘중 하나만 1이면 1 | 둘다 같아야 1(00,11) | 비트 전부 반전 |
값1 | 1011 | 1000 | 1011 | 1001 |
값2 | 1000 | 0111 | 1010 | |
결과 | 1000 | 1111 | 1110 | 0110 |
8) cmp
cmp 피연산자1, 피연산자2
☞ 피연산자 1에서 피연산자 2를 빼서 대소를 비교합니다. 값이 같다면 0이 나오게 되고 플래그 레지스터를 통하여 확인 이 가능합니다. (ZF)
9) test
test 피연산자1, 피연산자2
☞ 피연산자끼리 AND 연산을 취해서 0일경우 플래그 레지스터를 통하여 확인이 가능합니다.(ZF)
10) jmp
jmp 주소
☞ 주소로 rip를 이동시킵니다.
11) je
je 주소
☞ 직전에 비교한 피연산자가 같으면 해당 주소로 rip를 이동합니다. (cmp, test 등등)
12) jg
jg 주소
☞ 직전에 비교한 두 연산자 중 1번 연산자가 더 크면 해당 주소로 rip를 이동합니다.
ex)
cmp 2, 1
jg 주소
// 2가 1보다 크기때문에 jg 뒤에 있는 주소로 이동
4. 스택에 관한 명령어
1) push
push 값
☞ 스택최상단 (rsp) 에 값을 쌓습니다.
2) pop
pop reg
☞ 스택 최상단의 값을 꺼내서 레지스터에 넣습니다. ex( pop reg )
5. 프로시져
프로시져란?
프로시저는 특정 기능을 수행하는 코드라고 보면 됩니다. 프로시저를 사용하면 반복되는 연산을 프로시저 호출로 대체할 수 있고, 프로시저에 이름을 붙여 코드의 가독성을 높일 수 있습니다. ( c언어의 함수와 비슷한 개념이라고 볼 수 있습니다 )
1) call
1. push return_addr
2. jmp addr
☞ 돌아갈 주소를 스택에 push하고 가고자 하는 주소로 이동 ( 이동하고자 하는 함수의 주소 )
addr show_num = 0x1234567
0x000001 : call show_num
0x000005 : mov ebx, 4
call show_num
//해당 동작 수행을 표현하는 프로시져
push 0x000005 // 다음에 돌아올 retrun 주소를 스택에 push
jmp 0x1234567 // 함수로 이동
2) leave
1. mov rsp, rbp ( 스택의 최상단과 최 하단을 반환 )
2. pop rbp
☞ rsp에 rbp주소를 넣어 스택프레임을 정리합니다.
3) ret
1. pop rip
☞ rip를 return address로 설정합니다 (메모리 흐름으로 돌아간다고 생각하면 됩니다)
'System 관련 CS > 시스템 해킹을 위한 기초 지식' 카테고리의 다른 글
[ 시스템 106 ] pwngdb 사용법, gdb 명령어 정리 및 예시 (0) | 2023.08.01 |
---|---|
[ 시스템 105 ] 실행파일의 종류 (PE파일, ELF파일)를 알아보고 gdb, pwndbg 플러그인 설치해보자 (0) | 2023.08.01 |
[시스템 104] System Call (시스템 콜) (0) | 2022.09.07 |
[시스템 102] 레지스터? x86-64 레지스터 분석 (0) | 2022.09.06 |
[시스템 101] Process Memory 프로세스 메모리 분석 (0) | 2022.09.05 |