ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Lenas Reversing for Newbies] 17
    Wargame/dreamhack.io 2021. 3. 14. 22:10

    1. 프로그램 실행

     

    실행 화면

    위와 같이 두 개의 에디트 컨트롤이 있고 Check/About 버튼이 존재한다. 임의의 값을 채워 넣고 Check 버튼을 눌러보자.

     

    실행 화면

    위와 같이 임의로 maple19out, maple19out을 입력하고 Check 버튼을 누르자 에러를 나타내는 메시지 박스가 출력된다. 바로 디버깅을 진행해보자.

     

    2. Debugging(with OllyDbg)

    에디트 컨트롤로 부터 값을 읽어 들이는 API로는 GetDlgItemText가 있다. 해당 API의 원형은 다음과 같다.

    UINT GetDlgItemTextA(
      HWND  hDlg,
      int   nIDDlgItem,
      LPSTR lpString,
      int   cchMax
    );

     

    Ctrl+N을 통해 API 탐색을 해보면 다음과 같이 참조되는 부분을 확인할 수 있다.

    디버깅

    모든 지점에 BP를 설정하고 F9를 누르게 되면 입력을 받는 화면이 나타난다. 임의의 값을 입력하고 Check 버튼을 눌러보자.

     

    BP 적중

    위와 같이 004012B0 주소에서 BP에 적중하는 것을 확인할 수 있다. GetDlgItemTextA API는 버퍼에 읽어 들인 문자의 개수를 반환한다. 매번 GetDlgItemTextA API가 호출될 때마다 0과 비교하여 0보다 작거나 같은 경우 JE 004012DF 명령어에 의해 "Give me more material hehe!!"라는 문자열을 출력하는 메시지 박스가 호출되는 코드로 점프하게 된다. F8을 눌러 체크 표시한 부분을 넘어가 보자.

     

    디버깅

    위와 같이 JMP를 통해 "Give me more material hehe!!" 메시지 박스를 건너뛴다. 스크롤을 내려 밑의 코드를 살펴보자.

     

    디버깅

    strlen 함수를 호출 한후, 루프가 나타난다. 복잡해 보이지만 403038 버퍼로부터(첫 번째 에디트 박스에 입력한 값) 특정 알고리즘을 통해 값을 생성한 후, 체크 표시한 00401336 주소의 CMP 명령어를 통해 403138 버퍼(두 번째 에디트 박스에 입력한 값)를 비교하여서 같지 않은 경우 처음에 실행했을 때 나타난 에러 메시지 박스가 나타나고, 일치하는 경우 "That's right...."와 같은 문자열을 나타내는 메시지 박스가 나타난다. keygen routine을 분석하여 python 코드로 옮겨보면 다음과 같은 알고리즘을 사용하는 것을 알 수 있다.

     

    var1 = input()
    var2 = input()
    
    sum = 0
    for i in range(len(var1)):
        temp1 = ord(var1[i])
        sum += temp1 * temp1
    
        temp2 = (temp1 >> 1) + 3
        temp2 *= temp1
        temp2 -= temp1
        
        sum += temp2
        sum *= 2
    
    print(hex(sum))

     

    마지막의 sum 값을 두 번째 input으로 준 값과 비교하여 일치해야 한다. 즉 해당 프로그램은 첫 번째 input으로 key를 생성하고, 생성한 key가 두번째 입력과 일치해야 하는 것이다.

     

    maple19out을 첫 번째 input으로 주었을 때, 작성한 파이썬 코드는 다음과 같은 값을 출력한다.

     

    생성된 key 값

    hex 값이 0x20ba4640인 문자열이 input으로 들어와야 한다. (buffer 주위 공간은 0으로 초기화되어 있어 끝에 0이 붙는다.) 이를 바탕으로 hex 값을 아스키로 변환해주도록 다음과 같이 코드를 수정했다.

     

    import binascii
    
    var1 = input()
    var2 = input()
    
    sum = 0
    for i in range(len(var1)):
        temp1 = ord(var1[i])
        sum += temp1 * temp1
    
        temp2 = (temp1 >> 1) + 3
        temp2 *= temp1
        temp2 -= temp1
        
        sum += temp2
        sum *= 2
    
    sum = str((hex(sum)))
    #홀수 개인 경우 padding으로 0 추가
    if len(sum)%2 != 0:
        sum = sum + '0'
    sum = sum[2:]
    
    print(bytes.fromhex(str(sum)))

    실행해보면 다음과 같은 값이 나타난다.

     

    실행화면

    하지만 위 값을 일반적인 방법으로 input으로 줄 수는 없다... Lenas 강의에서는 실패했을 때 출력되는 메시지 창에 계산이 완료된 버퍼의 주소인 ESI 레지스터에 있는 값을 push 하여 key 값을 알아낸 후, 복사 붙여 넣기를 통해 key 인증에 성공하도록 코드를 패치하였다.

     

    3. Comment

    간단한 Keygen 문제를 해결하는 실습이었다. Lenas 강의와는 다르게 알고리즘을 코드로 옮겨보는 작업을 해보았다.

     

    반응형

    'Wargame > dreamhack.io' 카테고리의 다른 글

    [Lenas Reversing for Newbies] 19  (0) 2021.04.01
    [Lenas Reversing for Newbies] 18  (0) 2021.03.29
    [시스템해킹] basic_exploitation_001  (0) 2021.03.10
    [시스템해킹] basic_exploitation_000  (0) 2021.03.10
    [시스템해킹] out_of_bound  (0) 2021.03.07

    댓글

Designed by Tistory.