본문 바로가기

Reversing/DreamHack

[DreamHack_wargame] rev_basic_0번

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

 

 

< 전체 진행 방향 >

1. ‘문자열찾기로 메인 함수 찾기

: 입력받는 "Input:" 부분을 통해 메인함수를 찾을 수 있음.

 

2. 메인함수

 

3. 메인 함수(그래프)

: 첫번째 블록 아래의 두 블록을 보면, 첫번째 블록의 조건이 만족되면 왼쪽 블록(Wrong)으로

점프하고, 만족되지 않으면 오른쪽 블록(Correct)로 진행됨을 알 수 있음.

아래의 메인 함수 8, 9번째 줄을 보면 eax 값을 확인한 후, eax값이 0이면 chall0.7FF6576F1166

주소로 점프하는 것을 알 수 있음. (chall0.7FF6576F1166 wrong)

따라서 test 위의 7번째 줄의 함수가, 입력받은 문자열이 맞는지 비교하는 함수라고 예측할 수 있음.


< main 함수 >

1. | lea rcx,qword ptr ds:[7FF6576F2238] | 00007FF6576F2238:"Input : "

2. | call <chall0.sub_7FF6576F1190> |

3. | lea rdx,qword ptr ss:[rsp+20] |

4. | lea rcx,qword ptr ds:[7FF6576F2244] | 00007FF6576F2244:"%256s"

5. | call <chall0.sub_7FF6576F11F0> |

6. | lea rcx,qword ptr ss:[rsp+20] |

7. | call <chall0.sub_7FF6576F1000> |

8. | test eax,eax |

9. | je chall0.7FF6576F1166 |

10. | lea rcx,qword ptr ds:[7FF6576F2250] | 00007FF6576F2250:"Correct"

11. | call qword ptr ds:[<&puts>] |

12. | jmp chall0.7FF6576F1173 |

13. | lea rcx,qword ptr ds:[7FF6576F2258] | 00007FF6576F2258:"Wrong"

14. | call qword ptr ds:[<&puts>] |

15. | xor eax,eax |

16. | mov rcx,qword ptr ss:[rsp+120] |

17. | xor rcx,rsp |

18. | call chall0.7FF6576F12E0 |

19. | add rsp,130 |

20. | pop rdi |

21. | ret |


4. 비교 함수 내부(그래프)

: 메인 함수 7번째 줄의 call을 따라가면 아래의 그림과 같은 비교 함수가 나온다.

이곳에서 test의 조건이 만족되지 않으면 wrong으로 점프, 만족되면 correct로 진행되는 것을 알 수 있다.


< 비교 함수>

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

2. | sub rsp,38 |

3. | lea rdx,qword ptr ds:[7FF6576F2220] | 00007FF6576F2220:"Compar3_the_str1ng"

4. | mov rcx,qword ptr ss:[rsp+40] |

5. | call <JMP.&strcmp> |

6. | test eax,eax |

7. | jne chall0.7FF6576F1028 |

8. | mov dword ptr ss:[rsp+20],1 |

9. | jmp chall0.7FF6576F1030 |

10. | mov dword ptr ss:[rsp+20],0 |

11. | mov eax,dword ptr ss:[rsp+20] |

12. | add rsp,38 |

13. | ret |


< 풀이 >

 

main 함수 8번째 줄을 보면, eax0인지 아닌지 검사하는 과정이 있음.

8, 9번째 줄을 통해, (je: equl, ZF=1) eax0이면 wrong으로 점프, eax0이 아니면 correct로 가는 것을 알 수 있다.

(초록선 : jcc 명령어에서 분기를 취할 경우 / 빨간 : jcc 명령어에서 분기 취하지 않는 경우)

 

이때 main 함수 7번째 줄의 call(비교 함수)을 따라가면, 비교 함수 6번째 줄에서 다시 eax0인지 아닌지 검사를 하고 있으며, 이때 (jne : not equl, ZF=0) eax0이면 [rsp+20]1을 담고, eax0이 아니면 [rsp+20]0을 담는다. 그 후, 마지막에 공통으로 eax[rsp+20] 값을 저장한다.

 

, 비교 함수에서 [rsp+20]1이 담겨야, 비교 함수의 마지막에 eax1이 담기게 되고, main 함수에서 correct로 점프할 수 있다.

 

마지막으로, 비교 함수 5번째 줄의 call 하는 함수는 두 문자열을 비교하여 동일하면 0, 다르면 1eax에 저장하는 함수인데, 결론적으로 correct로 가기 위해서는 비교 함수에서 [rsp+20]1을 담아야 하며, 그러기 위해서는 eax0이어야 한다. , call 함수에서 비교하는 rdxrcx가 같은 문자열이어야 하므로, 정답은 "Compar3_the_str1ng"가 되어야 한다.

 

 

정답 : "Compar3_the_str1ng"

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

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