본문 바로가기

Reversing/DreamHack

[DreamHack_wargame] rev_basic_3번

문제 : 이 문제는 사용자에게 문자열 입력을 받아 정해진 방법으로 입력값을 검증하여 correct 또는 wrong을 출력하는 프로그램이 주어집니다. 해당 바이너리를 분석하여 correct를 출력하는 입력값을 찾으세요.

 

<풀이>

 

1. main 함수 

문자열 찾기를 통해 main 함수를 찾는다.

3번도 main 함수는 rev-basic-0,1,2번과 동일하다.

‘Input:’을 출력하는 함수와, 입력 값을 입력 받는 함수, 그리고 입력 받은 값과 정해진 값을 비교하는 함수 순서로 호출되며, 해당 문제를 풀기 위해서는 입력 받은 값과 정해진 값을 비교하는 함수를 살펴봐야 하므로, 해당 함수 내부로 들어가야 한다.

-     비교 함수 내부로 들어가기 전에, 주어진 인자는 rcxrdx이며, rcx에 입력값이 저장됨을 알 수 있다.

 

2. 비교 함수

입력 받은 값과 정해진 값을 비교하는 함수는 아래와 같다. (앞으로 편의상 비교 함수라고 칭함)

<알아야 할 요소>

: main 함수에서 eax값이 0이 아니어야 하므로, 6번 블록으로 진행되면 안됨.

(6번 블록에서 eax값이 0이 되기 때문에)

: 2번 블록에서 값을 16진수로 18, 10진수로 24번 비교하는 것을 알 수 있음.

: rcx에 입력 값 저장

: [rsp]는 비교를 진행한 횟수를 나타냄.

 

 

< ①번 블록 >

1.    | mov qword ptr ss:[rsp+8],rcx            |

:  [rsp+8] 위치의 값에 rcx 저장

2.    | sub rsp,18                              |

:  rsp = rsp – 0x18

3.    | mov dword ptr ss:[rsp],0                |

:  [rsp]0저장 (처음에는 0으로 시작)

4.    | jmp chall3.7FF720D6101A                 |

 

 

< ②번 블록 >

1. | movsxd rax,dword ptr ss:[rsp]           |

   : rax[rsp]가 참조하는 주소의 값을 저장

    : 1번 블록에서 [rsp]0을 저장했으므로, rax0이 저장된다.

2. | cmp rax,18                              |

   :  rax0x18을 비교하여

         rax = 0x18  이면  ZF=1, CF=0

         rax != 0x18  이면 ZF=0,

         rax < 0x18  이면  ZF=1, CF=1

         rax > 0x18  이면  ZF=0, CF=0

    : 위에서 rax값이 0이므로, rax < 0x18에 해당한다.

3. | jae chall3.7FF720D61053                 |

    :  jae>= 일때 점프하는데, 위에서 rax0x18보다 작으므로, 점프하지 않고

4번 블록으로 진행한다.

 

 

< ④번 블록 >

  [ 블록의 끝부분에서 eax와 ecx를 비교 ]

1. | movsxd rax,dword ptr ss:[rsp]           |

   : rax[rsp]이 참조하는 부분의 값 저장

2. | lea rcx,qword ptr ds:[7FF720D63000]     |

   : rcx[7FF720D63000]주소값 저장

3. | movzx eax,byte ptr ds:[rcx+rax]         |

4. | movsxd rcx,dword ptr ss:[rsp]           |

5. | mov rdx,qword ptr ss:[rsp+20]           |

6. | movzx ecx,byte ptr ds:[rdx+rcx]         |

7. | xor ecx,dword ptr ss:[rsp]              |

: ecx = ecx ^ [rsp]   (입력값 ^ 반복횟수)

8. | mov edx,dword ptr ss:[rsp]              |

: edx[rsp]저장 (edx에 반복 횟수 저장)

9. | lea ecx,qword ptr ds:[rcx+rdx*2]        |

   : ecx = [rcx+rdx*2]  (입력값 ^ 반복횟수)+(반복횟수*2)

10. | cmp eax,ecx                             |

: (입력값 ^ 반복횟수)+(반복횟수*2)와 정답 비교

11. | je chall3.7FF720D61051                  |

    : eaxecx에 저장된 값이 같으면 5-> 7번 블록으로 점프

 

------------------------------------ ecx에 저장된 값 -------------------------------------

       위의 4번 블록 2번째 줄에서 ecx[7FF720D63000] 주소 값을 저장함.

따라서 해당 주소를 따라서 들어가면 아래의 그림과 같은 값들이 저장되어

있는 것을 확인할 수 있다.

: 49  60  67  74  63  67  42  66  80  78  69  69  7B  99  6D  88  68 

94  9F  8D  4D  A5  90  45

 

< -> ⑦번 블록 >

1. | mov eax,dword ptr ss:[rsp]              |

2. | inc eax                                 |

3. | mov dword ptr ss:[rsp],eax              |

 : [rsp] 값을 증가시켜서 다시 2번 블록으로 back.

    다시 2-4-5-7-2-…을 반복함.

 

 

 

 

< 역연산 과정>

 : 역연산을 통해 답을 찾기 위해서는 다음을 통해 코드를 작성하면 된다.

1.    (입력값 ^ 반복횟수)

2.    (입력값 ^ 반복횟수)-(반복횟수*2)

3.    (입력값 ^ 반복횟수)+(반복횟수*2) ecx 값 비교

4.    ecx :

 49  60  67  74  63  67  42  66  80  78  69  69  7B  99  6D 

88  68  94  9F  8D  4D  A5  9D  45

 

-       파이썬 코딩

: 입력값을 x, 반복횟수를 y라고 했을 때,

ecx 내부 값과 (x^y)+(y*2)를 비교하는 것임.

, 문제를 해결하기 위해서는 문제의 함수가 실행되는 거꾸로 코드를 작성하면 되므로,  {ecx[ ] – (y*20)} ^ y = x를 수행하여 x 값을 구한다.

 

 

 

정답 : I_am_X0_xo_Xor_eXcit1ng

 

'Reversing > DreamHack' 카테고리의 다른 글

[DreamHack_wargame] rev_basic_5번  (0) 2021.05.15
[DreamHack_wargame] rev_basic_4번  (0) 2021.04.13
[DreamHack_wargame] rev_basic_2번  (0) 2021.04.12
[DreamHack_wargame] rev_basic_1번  (0) 2021.04.12
[DreamHack_wargame] rev_basic_0번  (0) 2021.04.12