어셈블리어로 별 피라미드 만들기

 

nano pyramid.s 로 파일을 만들어주자

 

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

 

STAR 라는 변수를 만들어주고 *이라는 포인터값이 들어가게 만들어주고

 

EMPTY 라는 변수는 0x0a를 넣어주는데 아스키코드에선 줄바꿈을 의미

 

_start라는 하나의 함수 정의하고

 

mov rax, 1 은 write라는 시스템 콜 설정

 

mov rdi, 1 기본 출력 모드

 

mov rdx, 1 출력 길이 설정

 

mov r10, 0 은 인덱스

 

mov r9, [rsp + 16] r9는 현재 입력된 문자열을 찾음 매개변수가 rsp 아래에 위치 즉 프로그램을 실행하여 입력하는 값이 rsp+16 안에 담김

 

cmp r9, 0 은 입력이 없는 경우

 

je_done 프로그램 종료

 

mov cl, [r9] 는 한 바이트만 cl에 저장(1~9층 사이로 할 것이기 때문)

 

movzx r9, cl 문자 형태의 cl을 r9에 저장

 

sub r9, 0x30 r9에 0x30을 빼주기 이렇게 해줌으로써 r9도 인덱스가 됨

 

RSP위치에서 16을 더해준게 입력한 매개변수가 담겨있는 메모리 주소를 가리키는 값

 

16진수로 30은 문자 '0'임

 

7을 넣는다면 16진수로 37 즉 30을 빼줌으로써 실질적인 숫자가 됨

 

r8에 r9를 넣어주고 xor r9, r9 를 해줘서 r9를 초기화해주고 call _syscall 해준다

 

c언어로 피라미드를 만들어보면

 

#include <stdio.h>

int main(void) {
	int n = 7, i, j;
    for(int i = 0; i < n; i++) {
    	for(int j = 0; j <= i; j++) {
        	printf("*");
        }
    }
    for(int i = n-1; i > 0; i--) {
    	for(int j = 0; j < i; j++) {
        	printf("*");
        }
        printf("\n");
    }
    return 0;
}

피라미드 올라가는 부분 내려가는 부분으로 크게 두가지로 나눌 수 있다

 

이것을 어셈블리어로 만들어보자

 

n으로 높이 설정해주고 i는 큰 반복문 j는 작은 반복문

 

n = r8, i = r9, j = r10

 

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 _down;
    mov rsi, EMPTY
    syscall
    mov rax, 1
    mov r10, 0
    add r9, 1;
    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

 

r10과 r9를 비교해서 i번 출력한 경우 _up 함수를 불러오게 함

 

rsi에 STAR를 담아 별을 출력할 수 있게 함

 

syscall로 출력하고 rax 1로 설정하여 write 시스템 콜 설정 왜냐하면 출력된 결과가 rax에 담기기 때문에 다시 출력문으로 바꿔주려면 다시 설정해야함

 

inc r10 으로 j를 1증가시킴 그리고 jmp small 로 자기자신을 다시 불러오는 것

 

_up 함수를 만들고 cmp r9, r8 은 i==n이 된 경우

 

즉 다 채웠다면 다시 내려가는 함수인 _down을 불러준다

 

만약 내려가지않고 i가 n보다 작다면 rsi에 EMPTY를 담아서 줄바꿈을 실행 syscall을 해서 실제로 줄바꿈을 해줄 수 있게 함

 

그 후 다시 rax에 1을 설정해주어서 출력모드로 바꿈

 

j를 0으로 해주고 i에 1을 더해줌 그리고 _small로 점프

 

_done 함수를 만들어주고 rax에 60 rdi에 0을 넣고 syscall해주고

 

_syscall 함수에는 syscall과 ret를 넣는다

 

내려가는 것도 만들어주고 파일을 만들어주고 하면 제대로 동작한다

'Hacking > 시스템 해킹' 카테고리의 다른 글

공부(11)  (0) 2021.09.22
공부(10)  (0) 2021.09.22
공부(8)  (0) 2021.09.21
공부(7)  (0) 2021.09.20
공부(6)  (0) 2021.09.20

+ Recent posts