* 2022-2 악성코드분석 과제 백업 게시물입니다.
1. 선정한 프로그램과 gcc로 컴파일 한 후 disass main 명령어로 확인할 수 있는 어셈블리 코드
2. ni 명령어로 추적하면서 어셈블리 코드 분석하기
스택 프레임을 형성하는 부분이다. rpb를 스택에 넣어두고 rsp를 rbp에 넣어준다. 어셈블리 코드를 분석할 때 항상 이 두 줄은 등장하니 기억해두면 좋다.
본격적으로 main() 함수가 시작되는 부분이다. 0xa의 값을 rbp에 넣어준다. 이 부분에 해당하는 코드 $0xa, -0xc(%rbp) 중 -0xc가 쓰인 이유는 다음과 같다.
디버거는 변수의 크기를 세서 미리 할당하는 특징이 있다. int는 4바이트의 크기를 갖는데 이 코드에서는 int a, int b, int result 총 세 개의 int 변수가 쓰였으므로 12바이트(hexa, 0xc)가 메모리에 할당된 것이다. 스택은 위에서 아래로 자라므로 그림으로 나타내면 왼쪽 그림과 같다. 같은 이유로 int b는 20의 값을 가지고 있으므로 0x14(20)을 rbp-0x8에 넣고, rbp-0x4에는 int result의 값 0을 넣는다.
mov 명령어는 계산을 위해 값을 옮기는 역할을 한다. 이 때, 코드는 result = a+b 이고 해당 인수들의 주소 값은 &a=-0xc(%rbp), &b=-0x8(%rbp)이다. (%rbp)-0xc 위치에 저장되어 있는 값 10과 (%rbp)-0x8에 들어있는 값 20을 각각 edx, eax 레지스터로 옮겨준다. rbp에서 직접 계산하지 않고 edx나 eax와 같은 레지스터로 옮기는 이유는 값 자체를 보
존하기 위해서 이다.
코드의 result = a+b 부분을 add 명령어로 계산한다. %eax = 20+10이며 %eax에 최종 result 값 30이 할당된다. 그 후, %eax에 있는 값 30을 다시 %rbp0x4로 옮긴다.
원래 여기에는 result 변수가 들어있는 자리였으므로 result 변수 대신 방금 계산한 %eax 레지스터 값 30이 들어가게 된다. 따라서 그림으로 나타내면 왼쪽 그림과 같은 상황이 된다.
3. result = a+b가 정상적으로 값이 들어가는지 breakpoint를 걸고 구체적으로 확인하기
변수 int result 와 int a, int b의 덧셈인 result = a + b에 정상적으로 값이 들어가는지 확인하기 위해 breakpoint를 걸고 디버깅 해 보았다. add 명령어 부분인 main+39에 bp를 설정하고 I b 명령어를 통해 전체 breakpoint를 확인해
보았다. 그 결과 방금 설정한 bp만 존재했음을 알 수 있다. 그 뒤 run을 해보면 bp를 건 main+39에서 멈추는 것을 볼 수 있다. 이 위치까지 실행되었으니 레지스터 값을 확인해보았다. 아직 main+39가 실행되기 직전이므로 rax 레지스터에 int b의 값 20이 저장되어 있는 것을 볼 수 있다. 또한 레지스터 rdx에 int a의 값 10이 저장되어 있는 것도 확인할 수 있었다.
위에서 확인해 본 main+39는 eax 레지스터에 result 값이 저장되기 전이었다. breakpoint 를 걸고 확인할 때 유의점은 화살표(=>)가 가르키는 지점 직전까지 실행된다는 점이다. 따라서 eax레지스터에 result 값이 적절하게 들어갔는지 확인하려면 그 다음 줄은 main+41에 bp를 걸고 확인해야 한다. main+41에 bp를 걸고 레지스터 값을 확인해 본 결과 rax 레지스터에 result 의 결과 값 30이 잘 들어가있음을 최종적으로 확인할 수 있다.
4. ni 명령으로 추적하면서 어셈블리 코드 이어서 확인하기
이 부분에서는 if-else 문 함수 속 루프의 동작과정을 확인할 수 있다. lea 0xe95(%rip),%rdi # 0x402004 라는 어셈블리 코드에 대하여 Mov와의 차이를 알아보았는데, Mov는 단지 레지스터에 값을 넣는 역할을 하고 Lea는 Mov와 다르게 주소값을 가져온다. lea 직후에 breakpoint를 걸어두고 I r명령어를 통해 주소 #0x402004 에 들어있는 값을 확인해보면 4202500이라는 값을 확인할 수 있다.
5. main() 함수의 에필로그
마지막으로 0x0000000000401185 <+79>: leave와 0x0000000000401186 <+80>: ret 부분이다. leave 명령어는 스택에 할당된 크기를 초기화 시키고 ebp의 처음 주소값을 불러오는 역할을 한다. 참고로 leave는 스택을 사용한 경우에만 나타나고 스택을 사용하지 않는 경우에는 pop 명령어가 나타난다. ret는 return의 줄임말로 eip값이 로드 되면서 이전 호출 함수로 돌아가게 한다
'정보보안 공부 > 리눅스' 카테고리의 다른 글
[linux] E: 디렉터리를 잠글 수 없습니다. (0) | 2022.04.05 |
---|---|
[20.09.18] ARP 스푸핑 실습 (0) | 2020.10.02 |
[20.09.11] ARP 스푸핑 (0) | 2020.10.02 |