기계어는 0과 1로 이루어졌기에, 간단한 프로그램도 코드가 매우길고, 읽기도 힘들다.
코드의 길이를 줄이고, 사람이 읽기 편하게 "어셈블리어"를 만들었다.
👉 어셈블리어
기계어를 사람이 읽기 쉬운 단어와 1대 1로 대응 시킨 것
[ 예시 ] - 설명하기 위한 예시이므로 실제와 다름
기존 기계어 : 0100000000000000000010010 명령어 작성 - 데이터를 전송해라
어셈블리어 : mov 명령어 작성 - 0100000000000000000010010 명령을 실행해라
필요성
우리가 자주사용하는 프로그래밍 언어를, 더 잘 활용할 수 있다 ( 쌉고수 )
주의사항
CPU마다, 다른 언어를 사용한다!! ( 어셈블리어가 다름 )
👉 어셈블러
어셈블리어로 쓰여진 명령들을, 기계어 명령들로 바꿔주는 프로그램
어셈블리 실행파일 생성과정 ( 컴파일과 다름! )
[ 어셈블러 ]
1. test.asm ( 어셈블리 텍스트 ) 로 목적코드 test.obj 파일 생성!
[ 링커 ]
2. test.obj 파일 + 라이브러리 파일을 사용해, 최종 실행 파일을 만든다. ( test.exe .. )
( 컴파일과정에, 어셈블러 작업이 포함되어 있다 )
컴파일과, 어셈블(?)의 차이점
고급언어 프로그램
1. 문법 검사
2. 목적 코드 생성 (obj)
3. 한문장을, 여러개의 기계코드로 변환
어셈블리어 프로그램
1. 기계코드와 바로 대응
👉 어셈블리어 종류
AT&T
UNIX 에서 사용하기 위해 만든 어셈블리어
Intel (x86)
Window 에서 사용하기 위해 만든 어셈블리어
Macro 어셈블리어 , Turbo 어셈블리어
MIPS
👉 레지스터란? ( 일반 == 범용 )
CPU에 들어있는 아주 작은 메모리
- 모든 데이터가 거쳐간다. ( 모든 계산시, 레지스터를 사용해서 데이터를 저장한다 )
( 어셈블리어로, 레지스터를 직접 관리 할 수 있다! )
EAX (AX, AH, AL) (Accumulate)
- 실행할 함수를 저장할 때 사용 ( 시스템 콜 - 아래 설명 있음 )
EBX (BX, BH, BL) (Base)
- 특정 주소를 저장할 때 사용 ( 포인터 )
ECX (CX, CH, CL) (Count)
- 숫자를 1씩 셀때 사용, ( 반복 명령 수행 )
EDX (DX, DHL, DL) (Data)
- 데이터를 저장할 때 사용, ( 입출력 연산에서, 간접 주소 지정 )
EBP (BP) (BasePointer)
- 스택 데이터에 접근하기 위한 주소를 저장? ( 포인터 )
ESP (SP) (StackPointer)
- 현재 스택의 주소를 저장? ( 포인터, 스택 최상위 오프셋 )
ESI (SI) (SouceIndex)
- 읽기 인덱스 ( 어디서 부터 읽을 것인지 - 파일 Read )
- 문자열 전송과 비교에 사용 ( 주로 소스 문자열의 오프셋 )
EDI (DI) (Destination)
- 쓰기 인덱스 ( 어디서 부터 쓸것인지 - 파일 Write )
EIP (Instruction Pointer)
- 명령어 포인터, 실행할 다음 명령어의 주소를 담고 있다!
EFLAGS
- CPU 동작 제어 or CPU 연산 결과 적용
추가 설명
e (a,b,c,d) x 이 4가지 레지스터는 구조가 비슷하다.
- EAX = Extended AX
EAX > AX (16bit) > AH, AL ( High/Low )
일반 명령어
데이터 저장 ( 변수 ) - Intel 기준
# 오른쪽에서 왼쪽으로 복사
# eax 레지스터에 1을 저장
mov eax, 1
# ebx 레지스터에 저장된 값을, eax 레지스터에 저장(복사)
mov eax, ebx
# eax 레지스터에 저장된 값을, 0040200 메모리 주소에 저장(복사)
mov 0040200, eax
CPU별 어셈블리어 비교
# eax -> ebx 데이터 복사
# AT&T
movl %eax, %ebx
# Intel - AT&T와 반대 순서
mov ebx, eax
# Apple Silicon - 레지스터 이름이 다르다!!
# x16 - eax, x0 - ebx
mov x0, x16
MacOS 어셈블리 프로그래밍
호출 규약 이란? ( Calling Convention )
함수 실행 규칙을 적어놓은 파일
( 어떻게 실행할래? - 어셈블리 명령어도 결국 함수 )
# MacOS 호출 규약 syscall.h 파일 위치
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/sys/syscall.h
호출 규약 확인하기
cat 경로/syscall.h
Hello World 프로그램 작성
// hello.s - 어셈블리 파일 생성
// [ 활용할 함수(syscall) & 레지스터 )
// write() - 파일 쓰기, syscall 번호 0x4
// exit() - 프로그램 종료, syscall 번호 0x1
// x16(eax) - 연산용 레지스터
// x0(ebx) - 주소 저장용 레지스터
// mov - 값 저장 (복사)
// adr - 변수 할당, 주소 저장
// svc - OS kernal에게 실행 요청
.global _start // _start 프로그램 진입점 지정, 추후 linker에게 주소 전달
.align 2 // Align the code to 2 bytes
// 문자열 출력하기 위한 변수 설정
_start: mov x0, #1 // 1 = 표준출력(stdout) 저장
adr x1, msg // 문자열 저장할 포인터
mov x2, #13 // 문자열 길이 저장
mov x16, #4 // 4 = 쓰기 시스템 호출 (#4)
svc #0x80 // 시스템 호출 (OS kernel) - 실행해줘.
mov x0, #0 // 0 = 반환 값 (exit code)
mov x16, #1 // 1 = 종료 시스템 호출 (#1)
svc #0x80 // 시스템 호출 (OS kernel)
// msg 변수에 ascii 문자열 주소 저장
msg: .asciz "Hello World!\n"
어셈블리 빌드
# 목적 파일 만들기
as -arch arm64 -o hello hello.s
# 실행 파일 만들기!
ld -arch arm64 -e _start -o hello hello.o -lSystem -syslibroot `xcrun --show-sdk-path --sdk macosx`
# -arch arm64 : arm64 architecture 지정
# -o hello : 출력 파일 이름
# -e _start : 프로그램 진입점! (작성한 _start)
# -lSystem : 시스템 라이브러리 링크하기 (필수아님)
# -syslibroot `xcrun --show-sdk-path --sdk macosx` : libSystem.dylib 경로 설정
실행 파일 실행
# arm64 환경에서 실행
file HelloWorld
# shell에서 실행
./HelloWorld
실행파일 어셈블리로 되돌리기 (디스어셈블)
# Mac에 기본적으로 설치되어 있는 objdump 이용
objdump -D HelloWorld
Shell Script로 디스어셈블
#!/bin/bash
# Mach-O 파일에서 shellcode 추출하기 (C 형식으로 출력)
if [[ $# -ne 1 ]]; then
echo "Usage: $0 <shellcode.macho:shellcode.o>"
exit 1
fi
for c in $(objdump -d $1 | grep -oE '[0-9a-f]{2} ' | tr -d ' '); do
echo -n "\x$c"
done
echo
# shell script
# #!/bin/bash : bash shell로 실행
# if [[ $# -ne 1 ]]; then # 인자개수가($#) 1이 아니면 (not equal)
# echo "Usage: $0 <shellcode.macho:shellcode.o>" # 사용법 출력
# exit 1 # 종료
# fi # if문 끝
# for c in $(objdump -d $1 | grep -oE '[0-9a-f]{2} ' | tr -d ' '); do # objdump로 디스어셈블한 결과에서 16진수 2자리씩 추출
# echo -n "\x$c" # 16진수 2자리를 8진수로 출력
# done # for문 끝
# echo # 개행
4칸(주소) / 1칸(어셈블리어) / 2칸(인자) 단위로 끊어서 보면 된다
Reference
어셈블리어 CheetSheet
https://www.bencode.net/blob/nasmcheatsheet.pdf