no. 1251056
<+33> sscanf 입력을 받기 전까지의 스택 상황.
%rcx, %rdx에 입력 받은 값을 저장하기 위해 주소를 할당하는 모습, %esi에는 어떻게 입력을 받을 것인지를 나타낸다.
여기서는 2개의 숫자를 입력받는다.
<+38> cmp $0x2, %eax
둘을 비교하는데 이 둘은 equal 해야 한다. %eax - $0x2를 했을 때 0이 되어야 한다. %eax의 경우 함수의 리턴값을 언제나 가지고 있으니 개수를 가지고 온다고 볼 수 있다.
<+43> cmpl $0xe, (%rsp)
입력 받은 숫자는 in[0], in[1]로 나타내겠다. (%rsp)는 in[0]를 나타낸다. in[0] - 14해서 그 다음 instruction이 [jbe] 이니까 in[0]가 작거나 같은 경우에 분기를 한다.
분기를 해야 폭탄이 안 터지기 때문에
<+67>
func4를 부르기 전의 스택 상황.
<+72> cmp $0x13, %eax
함수의 리턴값이 0x13 == 19랑 동일하지 않아야. 폭탄이 터지지 않는다.
func4의 리턴값은 19여야 한다.
<+77> cmpl $0x13, 0x4(%rsp)
in[1]과 19가 동일해야 폭탄이 터지지 않는다.
[2021.10.07 오후 12:49]
한 번 해보고 다시 보도록 하자....
func4를 뜯어봐야 하는게 아닌가??
그렇다. func4를 보도록 하자.
<+7> shr $0x1f, %ebx
shift right[부호 없이, 논리 연산] 0x1f == 31로 sign 부호로 %ebx를 초기화 한다.
그런데 여기까지 오면서 내가 입력하는 숫자는 없었으니까. 언제나 0으로 초기화 한다고 생각하자.
<+12> sar $eax
디폴트로 1칸을 이동시킨다. sar == shift arithmetic right[부호 포함, 산술연산] 그 뒤에 몇 칸 이동할 지 지정을 안 하면 1칸을 이동 시킨다.
<+14> lea (%rax, %rsi, 1), %ebx
lea는 주솟값을 옮기는 연산을 한다.
%rax + %rsi * 1을 옮기는데 이 때 이 둘의 주솟값을 확인하면 7, 0이다. 그래서 %ebx는 7을 가리킨다.
<+17> cmp %edi, %ebx
%ebx와 %edi를 비교해서 같거나 작은 경우에 <+33>으로 이동을 한다.
그러면 리턴 값으로 %ebx를 저장하고 함수를 종료한다.
이렇게 되면 7을 리턴하는 건가???
in[0]로 7을 입력해보자.
[2021.10.07 오후 13:12]
7이 기저사례인듯 하다. 이렇게 될 경우 리턴이 7이 된다.
우리는 리턴을 0x13 == 19로 만들어야 한다. 함수를 누적 해서 합을 만들려면 어떻게 할 지
다시 func4를 보자.
<+17> cmp %edi, %ebx
%ebx와 %edi를 비교해서 같거나 작은 경우에 <+33>으로 이동을 한다.
<+39> lea 0x1(%rbx), %esi
<+35>에서 분기가 되지 않을 경우에 입력 값을 바꿔서?? 암튼 함수를 부를 때 인자로 사용하는 듯한 값을 바꿔서 다시 func4를 부르는데 어떻게 변화가 생기는 지 보자.
레지스터의 값이 3 11로 변경되었다. 리턴 값을 어떻게 하는지 보도록 하자.
이렇게 하니 in[0]가 저장된 %edi와 %ebx를 비교하는 <+17>을 만족하지 못해 분기를 하지 않는다.
그래서 %rdx에 %rbx - 1의 값을 저장한다.
리턴 되어 나오는 수가 19여야 하는 것은 안다. 그러면 이 조건을 만들어내는 수를 찾으면 된다.. 그래 노가다를 했다.
그렇게 해서 in[0] == 4여야 함을 확인했다.
in[0] == 4
언젠가 찾아둬서인지 이 숫자는 0x13이랑 동일해야 했다.
이로써 phase 4를 완료했다.
기저사례가 자기자신인 재귀 함수이긴 한데... 조건을 찾아 보도록 하자.
0 > : 그냥 터짐.
0 : 0 1 3 7
1 : 1 3 7
2 : 2 1 3 7
3 : 3 7
4 : 4 5 3 7
5 : 5 3 7
6 : 6 5 3 7
7 : 7
8 : 8 9 11 7
9 : 9 11 7
10 : 10 9 11 7
11 : 11 7
12 : 12 13 11 7
13 : 13 11 7
14 : 14 13 11 7
< 15 : 그냥 터짐.
아 7을 기준으로 변위 4, 변위 2, 변위 1로 움직인다.
그리고 비교하는 값이 입력값과 같으면 그게 기저사례이다.
if, input == 2
첫 번째, 7을 기준으로 작다. (-4) -> 3
두 번째, 3를 기준으로 작다. (-2) -> 1
세 번쨰, 1을 기준으로 크다. (+1) -> 2
if, input == 10
첫 번째, 7을 기준으로 크다. (+4) -> 11
두 번째, 11를 기준으로 작다. (-2) -> 9
세 번쨰, 9를 기준으로 크다. (+1)-> 10