Exeinfo PE

    패킹되어있지 않다.

    아무 패스워드를 입력하고 “Check” 버튼을 누르면 충돌이 발생한다.

    한번 분석해보자.

    Analysis

    단순히 충돌 원인에 대해서만 살펴보자면, 1234를 입력하고 Check 버튼을 눌렀을때
    60160A9D 메모리 주소에 데이터를 쓸려고보니 유효하지 않은 주소여서 크래시가 발생한다.

    0x401060에 브레이크포인트를 걸어 확인했을때, eax 레즈스터값에 사용자 입력값인 1234(=0x4D2)가 들어가고,
    그 값이 dword_4084D0에 저장된다.
    그리고, .text:00401065 call loc_40466F에 의해 loc_40466F을 호출한다.

    .text:0040467A mov dword ptr unk_406016, 619060EBh
    0x406016에는 0x619060EB (EB 60 90 61) 값이 저장된다.

    .text:00404689 inc dword_4084D0
    dword_4084D0에 저장되었던 1234(=0x4D2) 값은 inc 명령어에 의해 1증가하여,
    dword_4084D0는 0x4D3이 된다.

    한번 더 수행되어 1 증가하므로
    dword_4084D0는 0x4D4 된다.

    .text:00404674 add dword_4084D0, 601605C7h
    dword_4084D0에 저장되었던 0x4D4값은 0x601605C7가 더해져
    dword_4084D0는 0x60160a9b 값이 된다.

    .text:0040467E inc eax
    GetDlgItemInt로부터 가져온 사용자 인풋값 eax에는 0x4D2(=1234)였는데,
    이제 inc 명령어에 의해 1증가하여 0x4D3이 된다.

    .text:00404689 inc dword_4084D0
    dword_4084D0에 1이 증가하여 0x60160A9B + 1 = 0x60160A9C가 된다.

    한번 더 증가하여 dword_4084D0는 0x60160A9D가 된다.

    .text:00404690 mov eax, dword_4084D0
    eax는 이제 dword_4084D0에서 가져온 0x60160A9D 값이 되고,

    .text:00404689 inc dword_4084D0
    dword_4084D0에 1이 증가하여 0x60160A9D + 1 = 0x60160A9E가 된다.

    .text:0040469F mov dword ptr ds:loc_40466F, 0C39000C6h
    0x40466F 주소에 있던 opcode가 수정된다.

    보다시피 call이었던 명령어가

    .text:0040466F mov byte ptr [eax], 90h
    .text:00404672 retn

    위와 같이 변경된다.

    여기가 바로 충돌이 발생했던 코드이다.
    eax인 0x60160A9D에 0x90 바이트를 쓰려고하는데,
    0x60160A9D는 유효하지 않은 주소여서 크래시가 발생한다.

    여기서 0x90은 nop 명령어를 의미하는데,

    eax를 0x401071로 수정해서 0x401071 주소를 nop으로 opcode를 수정해보자.

    방금 수정해주었던 eax값은 0x401071이었기에, 1증가해서
    eax값은 0x401072가 된다.

    0x401072 주소에도 nop으로 opcode가 패치된다.

    그러면 0x401071, 0x401072 주소에 있던 명령어가 nop으로 패치되었기 때문에,
    “Correct!”라는 창을 띄우게 된다.

    Solution

    이렇게 eax를 통해 2개의 메모리 주소에 nop 패치되는 것을 확인할 수 있었다.

    그렇다면 어떻게 eax를 0x401071로 컨트롤할 수 있을까에 대해 살펴보자면,
    사용자 인풋값 = 1234를 예로 들고, 전 과정을 다시 살펴봤을때,

    0x4D2 (=1234) + 1 + 1 + 0x601605C7 + 1 + 1 = 0x60160A9D
    [사용자 인풋값] + 1 + 1 + 0x601605C7 + 1 + 1 = [nop 패치할 메모리 주소]

    [nop 패치할 메모리 주소]는 0x401071이여야 하므로,
    0x401071 – 1 – 1 – 0x601605C7 – 1 – 1 = [사용자 인풋값]

    >>> (0x401071 – 1 – 1 – 0x601605C7 – 1 – 1) & 0xffffffff
    2687109798

    [사용자 인풋값] = 2687109798

    Result

    답글 남기기

    이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다