ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [reversing.kr] Easy ELF 풀이
    Wargame/reversing.kr 2021. 1. 5. 13:29

    본래는 dreamhack.io의 hash-browns 문제를 풀려고 했는데 리눅스 환경에서의 리버싱은 익숙하지 않다. 문득 reversing.kr의 100점짜리 문제인 Easy ELF가 떠올랐고, 풀기 위해 다양한 방법을 시도해보았다.

     

    - gdb로 접근

    많은 사람들이 리눅스 환경에서 gdb를 이용하여 디버깅을 한다고 하였다. 보통 file (filename) 명령어로 symbol 테이블 정보를 받아오고 disas main과 같은 명령어를 통해 바로 main 함수 쪽 어셈블리 코드를 확인하는데 symbol table이 없다는 문구가 나왔다. 알고 보니 gcc compile 옵션에 -s를 추가하면 symbol table이 제거되는 효과가 있다고 한다. readelf 명령어를 통해 EP를 찾은 후 해당 주소를 disas 하는 방식도 있는데 익숙지 않아서 다른 방법을 찾아보기로 했다.

     

    - Ghidra로 접근

    gdb뿐만 아니라 ELF 리버싱 문제를 정적 분석 도구인 IDA의 remote debugging이라는 기능을 이용해서 해결하는 분들이 많이 보였는데, 뭔가 이와 같은 방식으로 문제를 해결해보고 싶었다. (새로운 툴도 익힐 겸) 하지만 IDA가 없기도 하고, 얼마 전에 대중들에게 공개되어 호평을 받고 있는 Ghidra를 체험해보고 싶어서 Ghidra를 이용해 문제를 풀어보았다. 첫 정적 분석 도구의 이용이라 많이 서툴고 오래 걸렸지만, 앞으로 자주 이용할 것 같다.

     

     

    1. 프로그램 실행

    ELF 파일이라서 virtual box의 ubuntu를 이용해 프로그램을 실행시켜보았다.

    실행화면 1
    실행화면 2

    뭔가 적절한 input을 받았을 때 Correct와 같은 문자열을 출력할 것 같다.

     

    2. Debugging(with Ghidra)

    Ghidra는 windows 환경에서도 리눅스 파일 분석이 가능하므로, 프로젝트를 만들고 바로 Easy_ELF 파일을 열어보았다.

    초기 실행화면

    문자열 입력에 따라 Wrong 문자열을 출력하므로 해당 문자열이 어디서 참조되는지 확인해보면 입력에 따른 조건 검사 문을 찾을 수 있을 것이다. 상단의 다음 메뉴를 이용하여 문자열을 검색해보자.

    문자열 검색1
    문자열 검색2

    위와 같이 "Correct!\n"라는 문자열이 있는 것을 확인할 수 있다. 더블클릭하여 해당 문자열이 있는 주소로 이동해보자.

    Correct! 문자열의 주소

    위와 같이 08048652 주소에 Correct! 문자열이 있는 것을 확인할 수 있다. 그리고 처음에는 몰랐는데 저 XREF[1] 부분은 이 문자열을 어디서 참조하는지 나타내 준다. 더블클릭하면 해당 문자열을 참조하는 부분으로 이동할 수 있다.

     

    Correct 문자열 참조 함수

    오른쪽의 decompile 뷰와 비교해보자. 해당 함수에서는 단순히 Correct! 문자열을 출력해주는 기능만을 담당한다. 파란색 별 표시는 이 함수가 호출되는 위치를 나타낸다. 해당 부분을 더블클릭하여 이동해보자.

     

    main 함수

    오른쪽의 decompile  뷰를 보면 해당 위치는 main함수임을 직감할 수 있다. FUN_0804851()이 호출되고 그 결과가 1인 경우 Correct! 를 출력하고, 아닐 경우 Wrong! 을 출력하는 구조다. 이제 FUN_0804851()을 더블클릭하여 함수 내부 구조를 살펴보자.

     

    FUN_0804851의 decompile 뷰

    위 코드를 통해 입력받은 문자열은 다음과 같은 조건을 만족해야 하는 것을 알 수 있다.

     

    #1 : input[1] =  '1'

    #2 : input[0] ^ 0x34 == 0x78

    #3 : input[2] ^ 0x32 == 0x7c

    #4 : input[3] ^ 0x88 == 0xdd

    #5 : input[4] == 'X'

    #6 : input의 길이는 5이다.

     

    위 조건들을 이용하여 python 코드를 다음과 같이 작성해보았다.

    a = [0x78, 0x31, 0x7c, 0xdd, ord('X')]
    
    a[0] = a[0] ^ 0x34
    a[2] = a[2] ^ 0x32
    a[3] = a[3] ^ 0x88
    
    for i in range(len(a)):
        print(chr(a[i]), end="")

     

    출력 결과

    딱 봐도 flag 냄새 풍기는 문자열이 출력되었다. 마지막으로 ubuntu에서 해당 input 값을 집어넣고 실행시켜보자.

    크랙 성공!

     

    3. Comment

    처음 사용해보는 정적 분석 도구라 굉장히 시간이 오래 걸렸지만 많은 것을 배울 수 있는 문제였다. Ghidra는 많은 사람들에게 호평을 받는 정적 분석도구이니, 앞으로도 익숙해지게 종종 사용할 것 같다. 좀 복잡한 리눅스 리버싱의 경우 기드라로 정적 분석을 하고 gdb로 동적 분석을 하면 좋을 것 같다.

     

    반응형

    'Wargame > reversing.kr' 카테고리의 다른 글

    [reversing.kr] Music Player 풀이  (0) 2021.02.09
    [reversing.kr] ransomware 풀이  (0) 2021.01.08
    [reversing.kr] Easy Unpack 풀이  (0) 2020.12.13
    [reversing.kr] Easy Keygen 풀이  (0) 2020.12.09
    [reversing.kr] Easy Crack 풀이  (0) 2020.12.07

    댓글

Designed by Tistory.