이 프로그램은 몇 밀리세컨드 후에 종료 되는가
upx packing이 되어있다. 수동언패킹을 진행할려고 했지만 안티 디버깅 탐지 기법이 걸려있어서 그냥 upx.exe로 unpacking을 진행해주었다.
IsDebuggerPresent()로 디버깅을 탐지함
모든 함수를 찾다보니 sub_40AEF0에서 특이한 것을 발견 가능했다.
중간을 보면 시간과 관련되보이는 Sleep과 timeGetTime이라는 함수가 불려지는 것을 알 수 있다.
Sleep(0xA)는 정답이 아니었다.
timeGetTime이라는 함수가 아마 종료와 관련되어 있지않을까? 했는데 찾아야 되는 밀리 세컨드 부분을 못 찾겠고 어떤 방식으로 종료되는지를 찾지 못해서 구글링과 우수보고서를 참고했다. 처음에는 SetTimer인줄 알아 그 함수에 들어가는 인자값이 답인줄 알고 넣어봤지만 아니었다.
모듈간 호출부분을 보면서 모든 부분의 breakpoint를 걸면 딱 444C3E 부분 mov edi,dword ptr ds:[<&timeGetTime>] 에서 멈춰지는 것을 확인 가능하다.
해당 부분을 보면 한번 timeGetTime을 실행한 뒤 esi와 결과값 eax를 비교하고 eax가 더 크거나 같으니 점프를 한다.
그 뒤에 eax-esi 한 값을 ebx+4에 위치한 값 2B70과 비교를 하는데 해당 값이 크거나 같으면 444C71로 점프를 하고 그렇지 않다면 10ms sleep을 한 뒤 (cmp로 1과 0을 비교함) 444C5F로 다시 점프를 한다.
해당 부분에서 edi에는 timeGetTime 주소값이 들어있어서 다시 한번 시간을 가져오고 또다시 esi와 비교후 eax-esi한 값을 ebx+4와 비교한다. 이번에는 해당 값이 더 크기 때문에 444C71으로 점프를 하고 종료가 된다. ebx+4에는 0x2b70(11120)값이 들어있었다. 대다수의 블로그에 적힌 답이 먼저 실행 시간을 저장 후 중간중간에 시간을 가져오면서 종료되는 시간값이 되었을때 종료한다고 추측을 해 이 값이 밀리세컨드라고 추정하여 정답을 맞추었는데 그런 부분이 정확히 이해가 가질 않았다.
MessageBoxW 부분에 breakpoint를 걸고 해당 함수에 진입해 스레드를 보니
없던 6번 스레드가 생김!
이후 메시지 박스가 나오고 messageBoxTimeoutW의 실행 및 6번쓰레드가 없어짐과 종료된다.
우수 보고서에서는 messageboxw이전 명령어만 보면된다고 판단했고 레지스터를 유심히 살펴봤다고함
0x00444D62 mov edi,dword ptr ss:[esp+24] 부분이 밀리세컨드를 저장하는 부분이고
따라서 EDI에 있는 2B70이 밀리세컨드가 된다고 판단했다.
어느정도 코드가 돌아가는 걸 "추정"하면서 문제를 풀어야되는 것 같다.