본문 바로가기

카테고리 없음

기본 ASM

이제부터 나올 내용을 시스템에 해킹 공부에서 필수적인 부분이다. GDB 를 이용해 리턴
어드레스를 찾고, 쉘코드를 작성할 때 등등 반드시 알고 있어야 한다. 이 부분을 모르고
있다면 시스템 해킹 공부는 거의 불가능할 것이다. 하지만 그렇게 어려운 것은 아니므로
겁먹지 말고 알아보자. 아마 ‘이렇게 쉬었단 말인가’라고 외칠지도 모르겠다. 혹시라도
외치지 못하면 외칠 수 있을 때까지 공부해야 한다. 먼저 기본적인 레지스터 조작에 대해
알아보자.
우리는 앞에서 레지스터가 무엇인지 알아보았고, 이제 그 레지스터를 수정하는 방법에
대해 알아볼 것이다. 먼저 MOV 연산자의 사용법에 대해 알아보자. 레지스터에 어떤 값을
부여하기 위해 다음과 같이 한다.
MOV 목적지, 값
몇 가지 예를 들어보자.
AX 를 56h 과 같게 하려면:
MOV AX,56h ;AX 의 값이 56h 이 되었다.
값으로 다른 레지스터를 사용하려면:
MOV AX,BX ;AX 의 값이 BX 의 값으로 대체 되었다.
;만약 BX 의 값이 45h 라면 AX 의 값은 45h 가 된다.
이제 XCHG 연산자의 용법에 대해 알아보자. XCHG 는 단순히 두 레지스터를 서로 바꾼다.
XCHG 라는 말은 영어 단어 exchange 에서 나온 것이다. 용법은 다음과 같다.
XCHG 레지스터 1, 레지스터2
예를 보자.
MOV DX,56h
MOV AX,3Fh
XCHG DX,AX
이 예에서 DX 는 56h 이고, AX 는 3Fh 인데, 서로의 값을 교환함으로써(XCHG) DX 는 3Fh 가
되었으며, AX 는 56h 가 되었다.
참고: 8 비트(h/l) 레지스터와 16 비트(X)와 교환하지 않도록 해야 한다. 다음 코드는
무효이다.
XCHG AH,BX
다음은 INC 와 DEC 에 대해 알아보자. 눈치가 빠른 사람은 벌써 알 수 있을 것이다. INC 는
영어 단어 increase 에서, DEC 는 decrease 에서 나온 것이다. 예를 보자.
MOV DX,50h ;DX 의 값은 50h 으로 설정
INC DX ;DX 의 값을 증가시켜 이제 51h 가 되었다. 즉, DX++
MOV DX,50h ;DX 의 값은 50h 로 설정
DEC DX ;DX 의 값을 감소시켜 4F 가 되었다.(50h – 1h = 4Fh) 즉, DX--
이제 스택 조작에 대해 알아보자. 스택 조작에 사용되는 스택 연산자에는 6 개가 있으며,
그 중 2 개가 가장 많이 사용된다. 그것은 POP 과 PUSH 이다. 이것들의 문법은 다음과 같다.
POP 레지스터
PUSH 레지스터
나중에 사용하기 위해 스택에 있는 AX 에 값을 일시적으로 저장하고자 한다고 가정하자.
이럴 경우 간단히 다음과 같이 하면 된다.
PUSH AX
그리고 원래의 값을 회복하고자 한다면 POP 을 사용하면 된다.
POP AX
주목할 것은 스택이 단지 16 비트 레지스터만 받아들인다는 것이다.
이제 여태까지 언급한 것을 다음 예를 통해 연습해보자. 최종 AX 와 BX 값이 얼마인지
확인해보아라.
MOV AX,51h
MOV BX,4Fh
XCHG AX,BX
PUSH AX
MOV AX,34h
POP BX
PUSH BX
POP AX
값이 얼마 나오는가? AX 는 4Fh, BX 는 4Fh 가 나와야 한다. 다시 확인해보자.
MOV AX,51h ;AX 의 값이 51h 이 되었다.
MOV BX,4Fh ;BX 의 값이 4Fh 가 되었다.
XCHG AX,BX ;AX 의 값과 BX 의 값이 변경되었다. AX=4Fh 로, BX 의 값이 51h
PUSH AX ;AX 의 값을 저장
MOV AX,34h ;AX 의 값에 34h 를 넣어둠
POP BX ;BX 의 원래 값을 회복. 즉, BX = 4Fh
PUSH BX ;BX 의 값이 4Fh
POP AX ;AX = 34h 에서 이전의 값을 회복. 즉, 다시 4Fh 가 됨.
이제 수학 연산자 조작에 대해 알아보자. 수학 연산자에 기본 4 가지 ADD, SUB, MUL, DIV 가
있다. 먼저 ADD 에 대해 알아보자. ADD 의 문장 구조는 다음과 같다.
ADD 레지스터 1, 레지스터 2
ADD 레지스터, 값
MOV AX,5h ;AX 의 값은 5h
MOV BX,4h ;BX 의 값은 4h
ADD AX,BX ;AX 에 BX 를 더하고, 그 값을 AX 에 저장(5h + 4h = 9h = AX)
다른 예를 들어보자.
MOV AX,5h
ADD AX,4h ;AX = 5h, 여기에 4h 를 더함. 결국 AX 의 값은 5h + 4h 가 된다.
이제 SUB 에 대해 알아보자. 문장 구조는 다음과 같다.
SUB 레지스터 1, 레지스터 2
SUB 레지스터, 값
MOV BX,4Fh ;BX 의 값은 4Fh
SUB BX,5h ;BX 의 값에서 5h 를 뺌. 결국 4A 가 됨.
혹시 이 계산이 아직 어려운 사람은 다음과 같이 각 수를 먼저 10 진수로 전환한 후 그
10 진수를 계산하고, 그런 다음 16 진수로 전환해본다. 16 진수, 10 진수 전환이 가능한
간단한 계산기가 옆에 있으면 좋을 것이다.
4F16 = 7910, 516 = 510, 7910 – 510 = 7410 = 4A16
4Fh - 5h = 4A
이제 MUL 에 대해 알아보자. 문장 구조는 다음과 같다. 여기서는 단지 하나의 operand 만
필요하다. 이것은 프로세스가 주어진 레지스터를 AX 또는 AH 로 곱하기를 원한다고
추정하기 때문이다.
MUL 레지스터
MOV AX,5h
MOV BX,4Fh
MUL BX
이것은 AX 의 값을 결국 18B(4Fh x 5h = 18B)가 되게 한다.
마지막으로 DIV 연산자에 대해 알아보자. 문장 구조는 다음과 같다.
DIV 레지스터
MUL 과 마찬가지로 하나의 operand 가 있다. 예를 들어 보자.
MOV AX,5h
MOV BX,4Fh
DIV BX
이제 AX 의 값은 Fh 가 되었다(4Fh / 5h = Fh) 아래는 값이 나온 과정이다.
4Fh = 79
5h = 5
79 / 5 = 15.8
15 = Fh
이제 Bit 연산자들 AND, OR, XOR, NOT 에 대해 알아보자. 이 연산자들이 하는 것은 두 값을
bit 단위로 비교를 하는 것이다. 유용하니 꼭 알아두자. 혹시 오버플로우 공격을 위해
쉘코드를 만들어 본 사람이면 지금 이 부분이 얼마나 중요한지 알 것이다.
AND 의 문장 구조:
AND 레지스터 1, 레지스터 2
AND 레지스터, 값
AND 는 만약 두 오퍼랜드가 1 일 경우만 1 을 리턴한다. 이게 무슨 말인가? 다음 예를
들어보자.
MOV AX,5h
MOV BX,6h
AND AX,BX ;AX 의 값이 4 가 됨.
AX 의 값이 최종 4 가 된 것은 다음과 같은 이유에서이다. 먼저 16 진수를 bit 단위로
비교하기 위해 2 진수로 변환한다.
5h = 101b
6h = 110b
101b
110b
---
100b = 4h
이것은 아래의 AND truth 테이블을 보면 쉽게 알 수 있을 것이다. 앞에서도 말했듯이
오퍼랜드가 둘 다 1 일 때만 1 을 리턴 한다고 했었다.
AND truth table:
0 AND 0 = 0
1 AND 0 = 0
0 AND 1 = 0
1 AND 1 = 1
OR 문장구조:
OR 레지스터 1, 레지스터2
OR 레지스터, 값
OR 는 오퍼랜드 중 어느 하나라도 1 이면 1 을 리턴한다. 예를 보자.
MOV AX,5h
MOV BX,6h
OR AX,BX
AX 의 값은 이제 7h 가 되었다.
5h = 101b
6h = 110b
101b
110b
----
111b
111b = 7h
OR truth table:
0 OR 0 = 0
1 OR 0 = 1
0 OR 1 = 1
1 OR 1 = 1
XOR 문장 구조:
XOR 레지스터 1, 레지스터 2
XOR 레지스터, 값
XOR 는 오퍼랜드가 만약 어느 하나가 1 이면 1 을 리턴하고, 둘 다 1 이면 0 을 리턴한다.
예를 보자.
MOV AX,5h
MOV BX,6h
XOR AX,BX
최종 값이 나오는 과정을 보자.
5h = 101b
6h = 110b
101b
110b
----
011b
11b = 3h
XOR truth table:
0 XOR 0 = 0
1 XOR 0 = 1
0 XOR 1 = 1
1 XOR 1 = 0
이제 마지막으로 NOT 에 대해서 알아보자. NOT 은 값을 역전시킨다. 아주 쉬운 것이다. 문장
구조는 다음과 같다.
NOT 레지스터
NOT 값
예를 보자.
MOV AX,F0h
NOT AX
AX 는 F 가 되었다. F0h = 11110000 이고, 이것을 거꾸로 하면 00001111 가 될 것이고, 결국
F 가 된 것이다.
NOT truth table:
NOT 1 = 0
NOT 0 = 1