어셈블리어 별찍기 분석

오수진·2024년 9월 25일

시스템 해킹

목록 보기
2/25
section .data
        STAR db '*'
        EMPTY db 0x0a

section .text 
        global _start

_start:
        mov rax, 1  
        mov rdi, 1 
        mov rdx, 1 
        mov r10, 0 
        mov r9, [rsp + 16] 

        cmp r9, 0
        je _done

        mov cl, [r9]
        movzx r9, cl
        sub r9, 0x30

        mov r8, r9 
        xor r9, r9
        call _syscall
        
 _small:
        cmp r10, r9
        je _up;
        mov rsi, STAR ;
        syscall
        mov rax, 1
        inc r10
        jmp _small

_up:
        cmp r9, r8
        je _down
        mov rsi, EMPTY
        syscall
        mov rax, 1
        mov r10, 0
        add r9, 1
        jmp _small

_down:
        cmp r9, 0
        je _done
        mov rsi, EMPTY
        syscall
        mov rax, 1
        mov r10, 0
        sub r9
        jmp _big

_big:
        cmp r10, r9
        je _down
        mov rsi, STAR
        syscall
        mov rax,1
        inc r10
        jmp _big
_done:
        mov rax, 60
        mov rdi, 0
        syscall

_syscall:
        syscall
        ret
section .data
        STAR db '*'
        EMPTY db 0x0a

STAR에는 '*'을 가리키는 포인터가 들어간다.
EMPTY에는 '0x0a'가 들어가는데, 이는 아스키 코드에서 줄바꿈을 의미한다.

section .text 
        global _start

text 세그먼트에서는 _start 함수를 정의한다.

_start:
        mov rax, 1  
        mov rdi, 1 
        mov rdx, 1 
        mov r10, 0 
        mov r9, [rsp + 16] 

mov rax, 1은 write 시스템 콜을 설정한다
rdi에 1을 넣어줌으로써 정상적으로 출력할 수 있게 한다.(기본 출력 모드)
rdx에 1을 넣어줌으로써 출력 길이를 설정한다. '*', 줄바꿈 모드 길이가 1이므로..
r10에는 0을 넣어준다. 인덱스
r9는 현재 입력이 된 문자열을 찾는다.
ex) 사용자가 10을 입력하면, 이는 rsp + 16에 저장되고 r9에 넣어진다.

왜 rsp+16이냐> 스택 구조를 보면 rsp 아래에 ret 아래에 7이 쌓여 있을 거임. 내가 7에 접근하고 싶으면 8*2 = 16을 빼준 주소에 접근해야 하는 것

        cmp r9, 0
        je _done

r9와 0을 비교한다.(입력이 없을 경우, r9에 0이 담김)
r9와 0이 같다면 프로그램 종료

        mov cl, [r9]
        movzx r9, cl
        sub r9, 0x30

cl은 r9가 위치한 문자열에서 오직 한 바이트만을 가져온다. (1-9사이의 층수를 가진 피라미드)
movzx r9, cl
cl에는 하나의 문자가 담겨있다. 이것을 다시 r9에 저장해준다
sub r9, 0x30
16진수 30은 문자 0을 의미한다. 만약 7을 입력했다면 r9에 0x37이 담겼겠지?
그래서 30을 빼주는 거 ㅇㅇ

        mov r8, r9 
        xor r9, r9
        call _syscall

r8에 r9 넣어주고, r9 값 초기화
(높이를 r8에 저장, r9=0)
syscall 불러오기

 _small:
        cmp r10, r9
        je _up;
        mov rsi, STAR ;
        syscall
        mov rax, 1
        inc r10
        jmp _small

피라미드에서 올라가는 부분
n=피라미드 높이=r8
i=큰 반복문=r9
j=작은 반복문=r10

r10과 r9를 비교해서 같을 경우 _up이라는 함수를 불러온다
별을 출력할 수 있도록 rsi에 STAR을 담아준다
syscall(출력)
rax에 1 넣어서 write system call 설정
r10(작은 반복문) 1 증가시킨다
jmp_small 로 자기 자신을 반복한다

_up:
        cmp r9, r8
        je _down
        mov rsi, EMPTY
        syscall
        mov rax, 1
        mov r10, 0
        add r9, 1
        jmp _small

cmp r9, r8
i==n인 경우 _down 함수를 불러온다
아직 i가 n보다 작다면 rsi에 공백 문자를 넣어주고 출력한다
출력을 했으니 다시 rax에 1 넣어서 write system call 설정해준다
r10(작은 반복문)에 0을 넣어주고
r9(큰 반복문)을 1 증가시킨다
_small로 이동한다.(다시 올라가는 피라미드에서 별 찍으려고)

_down:
        cmp r9, 0
        je _done
        mov rsi, EMPTY
        syscall
        mov rax, 1
        mov r10, 0
        sub r9
        jmp _big

r9(큰 반복문)과 0을 비교해서 같으면 _done 함수를 실행시킨다
rsi에 공백 문자를 넣어주고 출력한다
출력을 했으니 다시 rax에 1 넣어서 write system call 설정해준다
r10(작은 반복문)에 0을 넣어주고
r9(큰 반복문)을 1 감소시킨다
_big로 이동한다(다시 내려가는 피라미드에서 별 찍으려고)

_big:
        cmp r10, r9
        je _down
        mov rsi, STAR
        syscall
        mov rax,1
        inc r10
        jmp _big

r10(작은 반복문)과 r9(큰 반복문)을 비교해서 같으면 _down(공백 문자 출력 함수)로 이동한다
별을 출력할 수 있도록 rsi에 STAR을 담아준다
syscall(출력)
rax에 1 넣어서 write system call 설정
r10(작은 반복문) 1 증가시킨다
jmp_big 로 자기 자신을 반복한다

_done:
        mov rax, 60
        mov rdi, 0
        syscall

rax에 60 넣어서 종료 모드 설정
rdi에 0 넣어준다
syscall(프로그램 종료)

_syscall:
        syscall
        ret

syscall 불러오고
return

0개의 댓글