InvokeClearTracks () at INETCPL.cpl in IE7

2010/02/01 14:56

Internet Explorer의 "검색 기록 삭제" 기능에 대해 조사할 일이 있어서 리버싱을 해보았습니다. 이 분석은 Windows XP SP3에서 IE7에 대하여 행하였습니다.

INETCPL.cpl


사용자 삽입 이미지

IE7에서 "검색 기록 삭제" 기능은 "도구 -> 인터넷 옵션 -> 일반" 탭에 있거나 "인터넷 등록 정보"에 있습니다. 다들 아시다시피 여기에서는 IE로 접속했던 웹사이트에서 내려받은 임시 파일, 쿠키나 히스토리(기록), 저장된 암호 등을 삭제할 수 있습니다.

사용자 삽입 이미지

"검색 기록 삭제"는 Rundll32.exe에 의해 실행되는데, 프로세스를 띄운 후, Process Explorer로 안을 들여다 보면, INERCPL.cpl 이라는 파일이 들어 있습니다. cpl 파일에 대해서 모르는 분들이 의외로 많이 계시던데, Control Panel, 즉 제어판의 기능을 실행하는 실행 파일입니다. exe나 dll과 같이 PE 파일이죠. Windows OS에는 여러 cpl 파일들이 system32 폴더 아래에 존재하는데, 이것들이 Windows의 제어판입니다. 파일, 드라이브, 레지스트리 등을 관리하죠. 그 중에서 INETCPL.cpl은 인터넷과 관련된 설정을 맡고 있습니다. WIndows에서 인터넷이라 하면은 기본적으로 IE이므로, 결국은 IE에 대한 설정들입니다.

InvokeClearTracks ()

Olly(이제는 친한 친구의 이름 같습니다)의 Back to User 모드를 이용하여 임시 인터넷 파일 삭제 버튼을 누른 상태에서부터 분석을 시작하면, 창 객체의 클래스와 ID를 확인하는 루틴을 거칩니다. 이 부분은 중요하지 않습니다. 단순히 마우스가 어떤 버튼에서 릴리즈 되었는지를 확인하는 거니까요. 중요한 부분은 INETCPL.cpl에 들어가고서 부터입니다.

INETCPL.cpl에 들어가면 제일 처음 위치는 0x42A1E68B, InitClearTracksProcess () 함수 안입니다. 여기서 초기화 작업을 수행합니다. 그리고 스텝라인으로 한 줄씩 실행 해나가다 보면, 0x42A1E260 을 호출하는 명령문을 만납니다. 바로 이 함수가 InvokeClearTracks () 함수입니다. 이 함수가 중요한 이유는 IE의 "검색 기록 삭제" 기능을 여기에서 제어하기 때문이죠.

    42A1E260  /$  8BFF          mov edi,edi
42A1E262 |. 55 push ebp
42A1E263 |. 8BEC mov ebp,esp
42A1E265 |. 81EC 80060000 sub esp,680
42A1E26B |. A1 38A2A342 mov eax,dword ptr ds:[42A3A238]
42A1E270 |. 33C5 xor eax,ebp
42A1E272 |. 8945 FC mov dword ptr ss:[ebp-4],eax
42A1E275 |. 53 push ebx
42A1E276 |. 8B5D 08 mov ebx,dword ptr ss:[ebp+8]
42A1E279 |. 56 push esi
42A1E27A |. 57 push edi
42A1E27B |. BE 04010000 mov esi,104
42A1E280 |. 56 push esi "/BufSize = 104 (260.)"
42A1E281 |. 8D85 F4FDFFFF lea eax,dword ptr ss:[ebp-20C]"|"
42A1E287 |. 50 push eax "|Buffer = 0007E728"
42A1E288 |. FF15 B8119D42 call dword ptr ds:[<&KERNEL32.GetSystemDirect>"₩GetSystemDirectoryW"
===================================================================================
<stack>
0007E728 43 00 3A 00 5C 00 57 00 49 00 4E 00 44 00 4F 00 C.:.₩.W.I.N.D.O.
0007E738 57 00 53 00 5C 00 73 00 79 00 73 00 74 00 65 00 W.S.₩.s.y.s.t.e.
0007E748 6D 00 33 00 32 00 00 00 00 00 00 00 00 00 00 00 m.3.2...........


InvokeClearTracks () 함수에 들어가면, 먼저 GetSystemDirectory (LPTSTR lpBuffer, UINT uSize) 함수에 의해 미리 준비된 버퍼 0x7E728에 시스템 폴더의 경로가 저장됩니다. "C:₩WINDOWS₩system32", 이 경로를요.

    42A1E28E  |.  33FF          xor edi,edi
42A1E290 |. 397D 10 cmp dword ptr ss:[ebp+10],edi
42A1E293 |. 8985 D4F9FFFF mov dword ptr ss:[ebp-62C],eax
42A1E299 |. 89BD D8F9FFFF mov dword ptr ss:[ebp-628],edi
42A1E29F |. 89BD E0F9FFFF mov dword ptr ss:[ebp-620],edi
42A1E2A5 |. 89BD DCF9FFFF mov dword ptr ss:[ebp-624],edi
42A1E2AB |. 74 22 je short INETCPL.42A1E2CF
42A1E2AD |. 8D85 DCF9FFFF lea eax,dword ptr ss:[ebp-624]
42A1E2B3 |. 50 push eax
42A1E2B4 |. 8D85 E0F9FFFF lea eax,dword ptr ss:[ebp-620]
42A1E2BA |. 50 push eax
42A1E2BB |. 8D85 D8F9FFFF lea eax,dword ptr ss:[ebp-628]
42A1E2C1 |. 50 push eax
42A1E2C2 |. E8 F0FBFFFF call INETCPL.42A1DEB7
42A1E2C7 |. 85C0 test eax,eax
42A1E2C9 |. 0F8C 7C010000 jl INETCPL.42A1E44B
42A1E2CF |> 39BD D4F9FFFF cmp dword ptr ss:[ebp-62C],edi
42A1E2D5 |. 0F84 A6000000 je INETCPL.42A1E381
42A1E2DB |. 39B5 D4F9FFFF cmp dword ptr ss:[ebp-62C],esi
42A1E2E1 |. 0F87 9A000000 ja INETCPL.42A1E381
42A1E2E7 |. 68 18E5A142 push INETCPL.42A1E518 "/FileName = 42A1E518"
42A1E2EC |. 56 push esi "|BufSize = 00000104"
42A1E2ED |. 8D85 F4FDFFFF lea eax,dword ptr ss:[ebp-20C]"|"
42A1E2F3 |. 50 push eax "|Buffer = 0007E728"
42A1E2F4 |. E8 D48CFFFF call INETCPL.42A16FCD "₩INETCPL.42A16FCD"
42A1E2F9 |. 8BF0 mov esi,eax
42A1E2FB |. 3BF7 cmp esi,edi
42A1E2FD |. 7C 66 jl short INETCPL.42A1E365
===================================================================================
<stack>
0007E728 43 00 3A 00 5C 00 57 00 49 00 4E 00 44 00 4F 00 C.:.₩.W.I.N.D.O.
0007E738 57 00 53 00 5C 00 73 00 79 00 73 00 74 00 65 00 W.S.₩.s.y.s.t.e.
0007E748 6D 00 33 00 32 00 5C 00 69 00 6E 00 65 00 74 00 m.3.2.₩.i.n.e.t.
0007E758 63 00 70 00 6C 00 2E 00 63 00 70 00 6C 00 00 00 c.p.l...c.p.l...


그리고 방금 전에 시스템 폴더의 경로를 저장했던 버퍼에 inetcpl.cpl 파일의 경로를 이어 붙입니다. FileName의 값, 0x42A1E518 은 inetcpl.cpl 파일의 이름이 저장되어 있는 곳의 주소입니다.

    42A1E365  |>  8BC6          mov eax,esi
42A1E367 |. 25 0000FF1F and eax,1FFF0000
42A1E36C |. 3D 00000700 cmp eax,70000
42A1E371 |. 0FB7C6 movzx eax,si
42A1E374 |. 74 02 je short INETCPL.42A1E378
42A1E376 |. 8BC6 mov eax,esi
42A1E378 |> 50 push eax "/Error = ERROR_INSUFFICIENT_BUFFER"
42A1E379 |. FF15 70109D42 call dword ptr ds:[<&KERNEL32.SetLastError>] "₩SetLastError"
42A1E37F |. EB 05 jmp short INETCPL.42A1E386
42A1E381 |> BE 05400080 mov esi,80004005
42A1E386 |> 3BF7 cmp esi,edi
42A1E388 |. 0F8C 96000000 jl INETCPL.42A1E424

42A1E424 |> 397D 10 cmp dword ptr ss:[ebp+10],edi
42A1E427 |. 74 22 je short INETCPL.42A1E44B
42A1E429 |. FFB5 D8F9FFFF push dword ptr ss:[ebp-628]
42A1E42F |. 8B35 70119D42 mov esi,dword ptr ds:[<&KERNEL32.CloseHandle>>
42A1E435 |. FFD6 call esi
42A1E437 |. FFB5 E0F9FFFF push dword ptr ss:[ebp-620]
42A1E43D |. FFD6 call esi
42A1E43F |. FFB5 DCF9FFFF push dword ptr ss:[ebp-624]
42A1E445 |. FF15 A0119D42 call dword ptr ds:[<&KERNEL32.LocalFree>]
42A1E44B |> 8B4D FC mov ecx,dword ptr ss:[ebp-4]
42A1E44E |. 5F pop edi
42A1E44F |. 5E pop esi
42A1E450 |. 33CD xor ecx,ebp
42A1E452 |. 5B pop ebx
42A1E453 |. E8 BD32FBFF call INETCPL.429D1715
42A1E458 |. C9 leave
42A1E459 ₩. C2 0C00 ret 0C


만약 0x42A16FCD () 함수의 작업이 실패하면, 0x8007007A가 반환되어서 SetLastError (DWORD dwErrCode) 함수를 호출한 후, 루틴이 종료됩니다. 0x42A1E424 부터는 InvokeClearTracks () 함수가 작업을 끝내고 루틴을 종료하는 과정입니다.

    42A1E2FF  |.  8D85 C4F9FFFF lea eax,dword ptr ss:[ebp-63C]
42A1E305 |. 50 push eax
42A1E306 |. 53 push ebx
42A1E307 |. FF15 94129D42 call dword ptr ds:[<&USER32.GetWindowRect>]
42A1E30D |. 85C0 test eax,eax
42A1E30F |. 8D85 F4FDFFFF lea eax,dword ptr ss:[ebp-20C]
42A1E315 |. 74 2B je short INETCPL.42A1E342
42A1E317 |. FFB5 C8F9FFFF push dword ptr ss:[ebp-638]
42A1E31D |. FFB5 C4F9FFFF push dword ptr ss:[ebp-63C]
42A1E323 |. FF75 0C push dword ptr ss:[ebp+C]
42A1E326 |. 50 push eax
42A1E327 |. 68 B8E4A142 push INETCPL.42A1E4B8 "UNICODE "rundll32.exe %s,ClearMyTracksByProcess %u %u %u""
42A1E32C |. 8D85 E4F9FFFF lea eax,dword ptr ss:[ebp-61C]
42A1E332 |. 68 08020000 push 208
42A1E337 |. 50 push eax
42A1E338 |. E8 0043FBFF call INETCPL.429D263D
42A1E33D |. 83C4 1C add esp,1C
42A1E340 |. EB 1D jmp short INETCPL.42A1E35F
42A1E342 |> FF75 0C push dword ptr ss:[ebp+C]
42A1E345 |. 50 push eax
42A1E346 |. 68 60E4A142 push INETCPL.42A1E460 "UNICODE "rundll32.exe %s,ClearMyTracksByProcess %u""
42A1E34B |. 8D85 E4F9FFFF lea eax,dword ptr ss:[ebp-61C]
42A1E351 |. 68 08020000 push 208
42A1E356 |. 50 push eax
42A1E357 |. E8 E142FBFF call INETCPL.429D263D
42A1E35C |. 83C4 14 add esp,14
42A1E35F |> 8BF0 mov esi,eax
42A1E361 |. 3BF7 cmp esi,edi
42A1E363 |. 7D 29 jge short INETCPL.42A1E38E
===================================================================================
<stack>
0007E318 72 00 75 00 6E 00 64 00 6C 00 6C 00 33 00 32 00 r.u.n.d.l.l.3.2.
0007E328 2E 00 65 00 78 00 65 00 20 00 43 00 3A 00 5C 00 ..e.x.e. .C.:.₩.
0007E338 57 00 49 00 4E 00 44 00 4F 00 57 00 53 00 5C 00 W.I.N.D.O.W.S.₩.
0007E348 73 00 79 00 73 00 74 00 65 00 6D 00 33 00 32 00 s.y.s.t.e.m.3.2.
0007E358 5C 00 69 00 6E 00 65 00 74 00 63 00 70 00 6C 00 ₩.i.n.e.t.c.p.l.
0007E368 2E 00 63 00 70 00 6C 00 2C 00 43 00 6C 00 65 00 ..c.p.l.,.C.l.e.
0007E378 61 00 72 00 4D 00 79 00 54 00 72 00 61 00 63 00 a.r.M.y.T.r.a.c.
0007E388 6B 00 73 00 42 00 79 00 50 00 72 00 6F 00 63 00 k.s.B.y.P.r.o.c.
0007E398 65 00 73 00 73 00 20 00 38 00 20 00 35 00 35 00 e.s.s. .8. .5.5.


inetcpl.cpl 파일의 경로가 성공적으로 저장되었다면, 또 다른 버퍼인 0x7E318에 명령 코드를 저장합니다. 명령 코드의 형태는 0x42A1E4B8에 저장되어 있고, "rundll32.exe %s,ClearMyTracksByProcess %u %u %u", 이와 같습니다. 0x429D263D () 함수 내부를 보면, msvcrt._vsnwprintf (wchar_t *buffer, size_t count, const wchar_t *format, va_list argptr) 함수를 이용합니다. 명령 코드의 1번 째 인자에는 inetcpl.cpl 파일의 경로가 들어가고, 나머지 인자들은 InitClearTracksProcess () 함수가 호출되기 이전에 결정됩니다. 그리고 여기서 2번 째 인자의 값에 따라 임시 인터넷 파일, 쿠키, 기록, 양식 데이터, 암호 중에서 어떤 것이 삭제될 지 결정됩니다.

    42A1E378  |> ₩50            push eax                                      "/Error = ERROR_SUCCESS"
42A1E379 |. FF15 70109D42 call dword ptr ds:[<&KERNEL32.SetLastError>] "₩SetLastError"
42A1E37F |. EB 05 jmp short INETCPL.42A1E386
42A1E381 |> BE 05400080 mov esi,80004005
42A1E386 |> 3BF7 cmp esi,edi
42A1E388 |. 0F8C 96000000 jl INETCPL.42A1E424


그리고 만약 명령 코드를 생성하는데 실패한다면, SetLastError (DWORD dwErrCode) 함수가 호출되고 루틴은 종료됩니다.

    42A1E38E  |>  6A 44         push 44
42A1E390 |. 5E pop esi
42A1E391 |. 56 push esi "/size = 44 (68.)"
42A1E392 |. 8D85 80F9FFFF lea eax,dword ptr ss:[ebp-680]"|"
42A1E398 |. 57 push edi "|value = 00"
42A1E399 |. 50 push eax "|lpProcessInformation = 0007E2B4"
42A1E39A |. E8 0943FBFF call <jmp.&msvcrt.memset> "₩memset"


명령 코드도 성공적으로 만들어지면, 0x7E2B4를 0으로 초기화합니다. 이 공간은 나중에 lpProcessInformation가 저장될 메모리입니다.

    42A1E39F  |.  83C4 0C       add esp,0C
42A1E3A2 |. 33C0 xor eax,eax
42A1E3A4 |. 40 inc eax
42A1E3A5 |. 397D 10 cmp dword ptr ss:[ebp+10],edi
42A1E3A8 |. 8985 ACF9FFFF mov dword ptr ss:[ebp-654],eax
42A1E3AE |. 66:8985 B0F9F>mov word ptr ss:[ebp-650],ax
42A1E3B5 |. 8D85 C4F9FFFF lea eax,dword ptr ss:[ebp-63C]
42A1E3BB |. 50 push eax
42A1E3BC |. 8D85 80F9FFFF lea eax,dword ptr ss:[ebp-680]
42A1E3C2 |. 50 push eax
42A1E3C3 |. 57 push edi
42A1E3C4 |. 57 push edi
42A1E3C5 |. 57 push edi
42A1E3C6 |. 57 push edi
42A1E3C7 |. 57 push edi
42A1E3C8 |. 57 push edi
42A1E3C9 |. 8D85 E4F9FFFF lea eax,dword ptr ss:[ebp-61C]
42A1E3CF |. 50 push eax
42A1E3D0 |. 89B5 80F9FFFF mov dword ptr ss:[ebp-680],esi
42A1E3D6 |. 57 push edi
42A1E3D7 |. 74 0E je short INETCPL.42A1E3E7
42A1E3D9 |. FFB5 E0F9FFFF push dword ptr ss:[ebp-620]
42A1E3DF |. FF15 20159D42 call dword ptr ds:[<&ADVAPI32.CreateProcessAs>
42A1E3E5 |. EB 06 jmp short INETCPL.42A1E3ED
42A1E3E7 |> FF15 6C119D42 call dword ptr ds:[<&KERNEL32.CreateProcessW>>"₩CreateProcessW"
42A1E3ED |> 3BC7 cmp eax,edi
42A1E3EF |. 74 33 je short INETCPL.42A1E424
===================================================================================
<stack>
0007E280 00000000 |ModuleFileName = NULL
0007E284 0007E318 |CommandLine = "rundll32.exe C:₩WINDOWS₩system32₩inetcpl.cpl,ClearMyTracksByProcess 8 545 85"
0007E288 00000000 |pProcessSecurity = NULL
0007E28C 00000000 |pThreadSecurity = NULL
0007E290 00000000 |InheritHandles = FALSE
0007E294 00000000 |CreationFlags = 0
0007E298 00000000 |pEnvironment = NULL
0007E29C 00000000 |CurrentDir = NULL
0007E2A0 0007E2B4 |pStartupInfo = 0007E2B4
0007E2A4 0007E2F8 ₩pProcessInfo = 0007E2F8


이제 다 끝나 갑니다. InvokeCLearTracks () 함수는 마지막으로 CreateProcess () 함수를 호출합니다. 방금 전 초기화되었던 0x7E2B4는 이 함수에서 쓰이기 위함이었지요. CreateProcess () 함수가 호출되는 이유는 아까 만들어진 명령 코드를 실행하기 위해서입니다. 즉, 지금 실행 중인 Rundll32.exe 프로세스 아래에 Rundll32.exe 프로세스가 하나 더 실행되면서 "rundll32.exe C:₩WINDOWS₩system32₩inetcpl.cpl,ClearMyTracksByProcess 8 545 85" 이와 같은 명령이 수행되는 겁니다. 알고봤더니 이 명령은 cmd 창에서 임시 인터넷 파일을 삭제하는 명령이더라구요.

임시 인터넷 파일을 삭제할 때는 명령 코드의 2번 째 인자 값으로 8이 들어갑니다. 이 외의 다른 것에 대해서도 정리하자면 아래와 같습니다.

사용자 삽입 이미지

    42A1E3F1  |.  68 88130000   push 1388                     "/Timeout = 5000. ms"
42A1E3F6 |. FFB5 C4F9FFFF push dword ptr ss:[ebp-63C] "|hProcess = 00000278 (window)"
42A1E3FC |. FF15 14129D42 call dword ptr ds:[<&USER32.WaitForInputIdle>>"₩WaitForInputIdle"
42A1E402 |. 83F8 FF cmp eax,-1
42A1E405 |. 74 07 je short INETCPL.42A1E40E
42A1E407 |. 57 push edi
42A1E408 |. FF15 70109D42 call dword ptr ds:[<&KERNEL32.SetLastError>]
42A1E40E |> ₩FFB5 C4F9FFFF push dword ptr ss:[ebp-63C] "/hObject = 00000278 (window)"
42A1E414 |. 8B35 70119D42 mov esi,dword ptr ds:[<&KERNEL32.CloseHandle>>"|kernel32.CloseHandle"
42A1E41A |. FFD6 call esi "₩CloseHandle"
42A1E41C |. FFB5 C8F9FFFF push dword ptr ss:[ebp-638] "/hObject = 00000280"
42A1E422 |. FFD6 call esi "₩CloseHandle"


CreateProcess () 함수가 수행되고나서 뒷정리를 합니다. 그리고는 0x42A1E422의 종료 루틴으로 넘어갑니다.

지금까지 보아온 것처럼, InvokeClearTracks () 함수는 cmd 창에서 명령을 입력하여 IE의 사용 흔적을 지우는 것과 같습니다. 즉, 인터넷 옵션창에 들어가서 버튼을 누르나, cmd 창에서 명령을 치나, bat 파일로 만들어 실행하나, ShellExecute () 함수나 CreateProcess () 함수를 이용해서 명령을 실행하나 다 똑같다는 것이죠.

그러면 저 명령어는 어떤 루틴을 거칠까요? (사실, 이게 진짜 목적이었는데...) 뭐, 어느 정도 감이 오기는 합니다만, 일단 다음으로 미루지요. 여기까지 읽어주셔서 고맙습니다.

참고 문헌

Windows XP의 제어판에 대한 설명 :: http://support.microsoft.com/kb/313808/ko
[VC++] CreateProcess Flow(흐름) :: http://kaludin.egloos.com/2389733
명령행으로 IE7 검색 기록 삭제하기 :: http://loser.miniwini.com/wp/archives/1535
크리에이티브 커먼즈 라이센스
Creative Commons License

6l4ck3y3 0x02 Windows RCE , , , , , ,

Trackback Address:이 글에는 트랙백을 보낼 수 없습니다
[로그인][오픈아이디란?]