[Code]
main:
push rbp ; 현 스택 프레임 저장
mov rbp, rsp ; rbp를 rsp의 위치로 이동
mov esi, 0xf ; esi = 0xf
mov rdi, 0x400500 ; rdi = 0x400500
call 0x400497 <write_n> ; write_n 프로시저 호출
mov eax, 0x0
; eax = 0x0
; read(0x0, 0x400500, 0xf)
pop rbp
; 원래의 스택 프레임으로 되돌아가기
ret
write_n:
push rbp ; 현 스택 프레임 저장
; stack top(rsp)이 0x400497 push
mov rbp, rsp
; rbp를 rsp의 위치로 이동
; rbp = rsp = 0x400497
mov QWORD PTR [rbp-0x8],rdi
; [rbp-0x8] = 0x400500
mov DWORD PTR [rbp-0xc],esi
; [rbp-0xc] = 0xf
xor rdx, rdx
; 본인 스스로를 xor 하면 결과 0
; rdx = 0x00
mov edx, DWORD PTR [rbp-0xc]
; edx = 0xf
mov rsi,QWORD PTR [rbp-0x8]
; rsi = 0x400500
mov rdi, 0x1 ; arg0 = 0x1
mov rax, 0x1 ; rax = 0x1 -> write
syscall
; write(0x1, 0x400500, 0xf)
; stdout에 0x400500에 저장된 것을 0xf 만큼 출력하기
pop rbp
; 원래의 스택 프레임으로 되돌아가기
ret
; 함수 반환
==================================
[Memory]
0x400500 | 0x3037207964343372 ; 07 yd43r
0x400508 | 0x003f367562336420 ; 0?6ub3d
이 문제에서 어려움을 겪었던 점들이 몇가지 있었는데,
코드를 전체적으로 읽어보면, [rbp-0x8]와 [rbp-0xc]의 메모리 위치에 값을 저장했다가 그대로 다른 레지스터에 그 값을 대입하므로 굳이 그 위치를 정확히 계산해서 찾아갈 필요가 없었는데 코드를 전체적인 흐름이 아니라 너무 한줄 한줄 보려고 하다보니까 저 부분에서 애를 많이 먹었다.
앞으로 코드를 볼때, 시야를 넓혀서 필요 없는 부분에 대해 깊게 파고들지 않게 주의 해야겠다.
또한, 마지막에 메모리의 값을 hex에서 ascii로 변환하였을 때, 정답이 없어서 너무 당황했는데, 구글링 하다보니 메모리에 값이 litte-endian 방식으로 저장이 되어있기 때문에 오른쪽에서 왼쪽으로 값을 읽어 주어야 한다는 사실을 간과하고 있었다는 것을 알았다. x86 아키텍처, 즉 인텔에서 사용하는 CPU는 리틀 앤디안 방식을 사용한다고 한다.
(참고글1 - x86 Assembly 2 QUIZ 풀이
참고글2 - 리틀앤디안과 빅앤디안)
역공학 수업 때 배웠음에도 막상 실제로 메모리를 볼 일이 생기니 생각이 나질 않았다 ㅠㅠ 다음에 이에 대해서도 정리 해봐야겠다.