위와 같은 exe 파일 하나가 있고 메세지 박스에는 Wrong이 적혀있다. 임의의 값 혹은 아무값을 입력하지 않고도 Check를 누르면 프로그램이 종료되고,
WinDbg로 trace해보면, Access violation 오류로 종료되는 것을 확인할 수 있다.
어떤 함수가 이를 일으키는지 확인해보자.
우선, exe 파일 시작인 winmain에선 DialogBoxParamA를 호출하여, 대화 박스를 호출하고, 4번째 인자는 대화 상자 프로시저에 대한 포인터이므로, 이 부분을 디버깅하면
이와 같은 사실(주석 확인)을 알 수 있었다.
우리가 박스에 입력하여(10진수로) check 버튼을 누르면, 그 값이 dword_4084D0에 16진수 값으로 저장된다.
그리고 함수를 살펴보면,
else if ( (unsigned __int16)a4 == 0x3EB ) // 메세지 입력하면 항상 여기로
{
dword_4084D0 = GetDlgItemInt(hDlg, 1002, 0, 0);
sub_40466F(a1);
sub_404689();
*(_DWORD *)sub_40466F = -1013972794;
sub_40466F(&loc_40469F);
sub_40466F(v6);
*(_DWORD *)sub_40466F = 1768;
return 1;
}
현재, dword_4084d0에 사용자가 입력한 값이 들어간 상태이다.
이후,
1. sub_40466f를 a1을 인자로 실행
edi에 있는 a1은 0x00110F02, 무슨 값인진 모른다.
해당 함수는, 사용자가 입력한 값에 어떠한 hex값을 더한 후, inc 연산까지 하고 return 하는 함수이다.
현재 a1인자가 어떤 역할을 하는지 모르겠고, 이는 ida가 해석한 것이니 잘못 표현됐을 가능성을 열어두고 넘어가자.
2. sub_404689 함수 실행
해당 함수 또한 사용자가 입력한 값을 inc하고 return하는 연산이다.
3. sub_40466f 함수 포인터 지정
sub_40466f 함수 포인터에 0c39000c6 mov 한 후, sub_40466f call, 즉 opcode "c6 00 90 c3"(리틀엔디안에 따라 역순으로) 을 실행하는것이며,
해당 opcode는 eax레지스터에 있는 주소에 0x90 바이트 (nop)를 삽입하고, ret를 한다.
해당 text영역과 stack view를 연동시켜보면,
스택에 이전에 넣은 opcode가 있는것을 확인할 수 있고, opcode 내용대로
eax에 있는 60160a9d 주소에 0x90 바이트 쓰기를 하다 엑세스 위반을 한 것을 알 수 있다.
이제 사용자의 입력이 처리되는 과정을 동적 디버깅으로 확인해보겠다.
사용자 입력에 1을 입력하면,
GetDIgItemInt의 결과값, 즉 사용자 입력값인 1이 eax에 들어있는 것이 보이고, 해당 값을 dword_4084d0에 저장한다.
이후 sub_40466f 함수를 실행하면,
loc_40467a를 호출하고,
현재 eip가 코드로 정의되지 않은(정의는 ida가 함) 부분을 가르키고 있고, 이를 즉각 변환해준다고 한다.
dword_406014+2에 619060eb를 저장하고, inc를 두번 실행하여 (스택에 해당 주소를 넣었는지 두번 실행되는걸 동적 디버깅중 확인하였다) 현재 dword_4084d0의 값이 (사용자 입력 1) + 1 + 1 = 3인걸 확인하였다.
이후 계속 실행하면,
또 함수를 생성해준다고 하고,
위와 같은 연산을 한다. 또한, dword_4084d0 값을 확인해보면
이와 같이 값이 바뀌었는데, ida에서 보여주지 못한 부분이 있다 생각하고 추측하면,
이전에 mov로 dword_406014+2에 저장한 619060eb와 관련이 있다 생각한다.
최종적으로, eax가 사용자가 입력한 1에 601605d0을 더한 값이 되는것을 확인했다.
디버깅을 하면서, ida가 잡지 못한 부분이 있어 (619060eb를 저장하는 부분) 확실하지 않지만, 사용자의 입력이 덧셈으로만 조작된다 가정하면
사용자 입력 + 601605d0 = EAX이다.
최종적으로, 우린 correct의 출력을 막는 401071을 nop로 씌우면 되므로, eax값을 401071로 만들어야 한다.
사용자 입력 + 0x601605d0 = 0x401071
사용자 입력 = 0x401071 - 0x601605d0 = FFFFFFFFA02A0AA1
32비트 프로그램이므로, 뒤의 4바이트만 주소에 들어가면 되므로,
a02a0aa1을 넣어주면, 뒤 4바이트가 401071이 되는것을 확인하였고, 사용자는 정수로 입력해야 하므로 (GetDIgItemInt이므로) 이를 정수로 변환하면,
2687109793 을 입력하면 된다.
'reversing > reversing.kr' 카테고리의 다른 글
[reversing.kr] Music Player (1) | 2024.02.15 |
---|---|
[reversing.kr] Easy Keygen (0) | 2021.04.14 |
[reversing.kr] Easy_CrackMe (0) | 2020.11.29 |