본문 바로가기

5. 방학 활동/Write UP

[2023.08.13] 워게임 문제풀이(2) - 5

목차

  • 포렌식
  • 리버싱
  • 웹해킹

포렌식

  • 써니나타스 포렌식 14번
  • 써니나타스 포렌식 15번

써니나타스 포렌식 14번

먼저 문제를 다운로드 받는다.

 

확장자가 없는 파일 2개가 있다.

 

 

(좌) shadow (우) passwd

리눅스에는 /etc/passwd와 /etc/shadow 파일이 있다.

유닉스를 기반으로 한 모든 리눅스 시스템은 사용자 계정 정보와 그 비밀번호(암호화)를 위 파일에 저장한다.

이 파일들은 수정할 수 없지만, 누구나 볼 수 있어 john과 같은 크랙 툴을 이용하면 패스워드를 알아낼 수 있다.

참고 : https://y30ni.tistory.com/51

 

passwd 파일에는 사용자에 대한 내용들이 기록되어 있고, shadow 파일에는 패스워드에 대한 내용들이 기록되어 있다. shadow 파일 마지막에 suninatas 사용자의 패스워드가 해시로 암호화 되어 존재 한다.

 

john the ripper 프로그램을 이용해 shadow 파일의 써니나타스 부분을 크랙하겠다.

 

suninatas 사용자명과 암호화된 값이 담긴 텍스트 파일을 만들었다.

 

 

써니나타스 포렌식 15번

Do you like music?

Hint : AuthKey is in this file.

 

Play the Music을 누르니 이런 화면이 떴다.

 

다운로드하자.

리버싱

  • DreamHack : rev-basic-5

 

DreamHack : rev-basic-5

 

rev-basic-5 문제는 “Correct” 문자열을 출력하는 입력 값을 알아내면 된다.

 

처음 프로그램을 실행하면 Input에 값을 입력하도록 되어있고, “Wrong” 문자열이 출력된다.

 

x64dbg를 이용해 코드를 확인해보면, [00007FF67136151F] 주소에서 “Input :” 문자열이 출력되는 것을 확인할 수 있다.

즉, [chall5.7FF671361130] 주소에 “Correct”와 “Wrong” 문자열 또한 같이 존재할 것이다.

 

[00007FF671361130] 주소의 모습이다. “Input :”, “Correct”, “Wrong” 문자열이 존재한다.

 

[00007FF67136117E] 주소에서 두 문자열을 비교하므로 [chall5.7FF671361000] 주소에 “Correct”를 출력하는 문자열이 있을 것이다.

 

[00007FF671361000] 주소의 모습이다. 문자열을 비교하는 반복문이 존재하므로 이를 자세히 확인한다.

 

0X18(10진수 24)번 반복문이 실행되며 입력된 문자열 값을 암호화하고, 비교하는 것을 알 수 있다. 어셈블리를 해석해보면, 다음과 같은 내용을 얻을 수 있다.

  • 사용자 입력 문자열 : arr[i], 암호화 검증 문자열 : str[i]라 가정.
  • str[i] = arr[i] + arr[i+1]

즉, 사용자가 입력한 i번째 문자와 i+1번째 문자를 더해 암호화를 진행한다는 것을 알 수 있다.

 

그러므로, 암호화 검증 문자열이 무엇인지 알기 위해 [7FF671363000] 주소의 값을 확인한다.

 

[7FF671363000] 주소의 값을 확인해보니 위와 같은 값이 저장되어 있다.

  • 16진수 : AD D8 CB CB 9D 97 CB C4 92 A1 D2 D7 D2 D6 A8 A5 DC C7 AD A3 A1 98 4C 00
  • 10진수 : .ØËË..ËÄ.¡Ò×ÒÖ¨¥ÜÇ.£¡.L.

필요한 정보를 다 구했으므로, 위에서 찾은 식을 바탕으로 암호화를 만족하는 문자열을 구한다.

  • str[i] = arr[i] + arr[i+1]
  • arr[i] = str[i] - arr[i+1]

즉, [7FF671363000] 주소에 저장된 문자열에서 사용자가 입력한 문자열의 i+1번째 문자를 빼면 조건을 충족하는 문자열이 출력될 것이다.

위의 식을 C언어로 코드를 작성하면 다음과 같다.

 

#include <stdio.h>
#include <string.h>

int main(void) {

    int arr[24] = { 0xAD, 0xD8, 0xCB, 0xCB, 0x9D, 0x97, 0xCB, 0xC4, 0x92, 0xA1, 0xD2, 0xD7, 0xD2, 0xD6, 0xA8, 0xA5, 0xDC, 0xC7, 0xAD, 0xA3, 0xA1, 0x98, 0x4C, 0x00};
    int flag[24] = {'\0'};

    for (int i = 22; i >= 0; i--) {

        flag[i] = arr[i] - flag[i+1];

    }

    for (int j = 0; j < 24; j++) {
        printf("%c", flag[j]);
    }

    return 0;

}

코드를 실행하면, 위와 같은 문자열이 출력된다.

 

해당 문자열을 입력하니 “Correct”가 정상적으로 출력된다.

 

웹해킹

  • LORD OF SQLINJECTION사이트의 goblin문제
  • webhacking.kr의 old-3번 문제

LORD OF SQLINJECTION사이트의 goblin문제

1. 문제 살펴보기

  • 이전 문제와 매우 비슷한 코드를 가지고 있다.
  • if(preg_match('/prob|_|\\.|\\(\\)/i', $*GET[no])) exit("No Hack ~*~"); if(preg_match('/\\'|\\"|\\/i', $GET[no])) exit("No Quotes ~~");`
  • php의 preg_match이라는 함수는 get방식으로 전달되는 no의 입력 값에 prob, _, ., (), ‘, ‘’등을 적을 수 없다. 맨 뒤의 /i는 대소문자 구별을 하지 않겠다는 의미이다.
  • preg_match는 문자열 안에서 특정한 정규식 패턴의 존재 여부를 찾는데 유용한 함수이다.
  • 위 두 줄의 코드에서 얻을 수 있는 정보는 no의 입력 값 필터링 규칙으로 위의 문자들을 필터링하여 사용할 수 없다는 것이다.
  • if($result['id'] == 'admin') solve("goblin");
  • 문제를 해결하기 위해서는 id의 값이 admin이어야 한다는 정보 또한 얻을 수 있다.
  • 따라서, 각종 문자들을 우회하여 문제를 해결하고자 한다.

2. 문제 분석하기

  • 페이지에 작성된 쿼리문은 다음과 같다
  • query : select id from prob_goblin where id=’guest’ and no=
  • id가 guest인 상황에서 guest의 no값을 알아보기 위해 아무 숫자나 대입한 결과, id=guest인 경우 no가 1이라는 것을 확인할 수 있었다.

3. 문제 해결하기

  • 해당 문제를 해결하기 위해서는 id가 guest가 아닌 admin이어야 한다.
  • 그러나, id가 guest로 고정되어 있다.
  • 그러므로 쿼리문 no에 1이 아닌 다른 값을 넣어 거짓으로 만든 후 id=admin을 붙여 해결하고자 한다.
  • 또, 주의해야할 점이 싱글쿼터를 사용할 수 없다는 점이다. 이를 우회하기 위해 admin을 16진수로 변환하여 문제를 해결하였다.
  • 문제 해결 코드 no=12 or id=0x61646d696e %20은 공백을 뜻하며 url 인코딩

 

webhacking.kr의 old-3번 문제

1. 문제 살펴보기

해당 문제를 살펴보니 빈칸을 누르면 색이 칠해지며, 주위에 숫자가 있는 것으로 보아 네모네모로직과 비슷하다는 생각이 들었다. 따라서 네모네모 로직 공식을 생각하여 블럭에 색을 칠해보았다.

 

위의 사진처럼 색을 칠하고 solved를 눌렀더니 clear이라며, 로그를 남기기 위해 이름을 입력받는 화면이 보였다.

 

 

2. 문제 분석하기

각종 값을 입력하고 submit을 눌렀더니 name, answerm ip가 나오는 것을 확인할 수 있었다. 입력 내용들이 누적되어 기록되었으며 내가 입력한 name 값만 바뀌고 answer, ip의 값은 동일하게 출력되었다. (ip값은 색처리)

 

 

3. 소스코드 살펴보기

  • <form name=kk method=get action=index.php></form>
  • 위의 코드에서 answer과 id값을 index.php로 get 형식으로 보내는 것을 알 수 있다.
  • <input type=hidden name=answer value=1010100000011100101011111>
  • 위의 코드에서 answer 값은 '1010100000011100101011111'로 고정되어있음을 알 수 있고 hidden상태이다.
  • <type=hidden> 은 사용자에게는 보이지 않는 숨겨진 입력 필드를 정의한다.
  • 따라서 answer을 활용하여 문제를 해결할 수 있을 것이라고 예상하였다.

4. 문제 해결하기

개발자 도구에서 <type=hidden>을 지워보았더니 answer의 vlaue부분이 그대로 화면에 노출되는 것을 볼 수 있다.

 

answerd의 value을 1’ or ‘1’=’1 로 바꿔 submit을 눌렀더니 문제가 해결되었다.