Ezúttal evezzünk más vizekre.
Egyszer iTunes-t debug-oltam és a felugró ablak helyét akartam elkapni a programkódban, de nem találtam rá, mert nem MessageBox metódust használt, hanem egy teljesen egyedi megoldást.
Mielőtt munkához látnánk hatástalanítsuk a debugger detektálást a programban, mert jelen állapotában az OllyDbg-t valamint társait észreveszi és nem hajlandó elindulni megfigyelt környezetben. Szerencsére előttünk már megtalálták a megfelelő helyet, ahol valamit kell tennünk. Leírások szerint a 84 C0 74 08 6A 00 byte sorozatot kell megkeresnünk az iTunes.exe-ben, amit a 7.5.0.20-as verzió .004F4B1C offszetén találtam meg. Itt egy függvényhívás található.
.text:004F4B1C test al, al
.text:004F4B1E jz short loc_4F4B28
.text:004F4B20 push 0 ; uExitCode
.text:004F4B22 call ds:ExitProcess
Láthatjuk, hogy ha a visszatérési érték nem nulla értékű, akkor a futás befejeződik. Ennek megfelelően módosítottam a rutint, hogy minden esetben nulla értéket adjon vissza.
.text:00418D30 debuggerCheck proc near ; CODE XREF: sub_4F4B00+17p
.text:00418D30 call sub_418B00
.text:00418D35 test al, al
.text:00418D37 jz short loc_418D3C
.text:00418D39
.text:00418D39 loc_418D39: ; CODE XREF: debuggerCheck+13j
.text:00418D39 jmp short loc_418D4B
.text:00418D39 ; ---------------------------------------------------------------------------
.text:00418D3B db 0C3h ; +
.text:00418D3C ; ---------------------------------------------------------------------------
.text:00418D3C
.text:00418D3C loc_418D3C: ; CODE XREF: debuggerCheck+7j
.text:00418D3C call sub_418B80
.text:00418D41 test al, al
.text:00418D43 jnz short loc_418D39
.text:00418D45 call ds:IsDebuggerPresent
.text:00418D4B
.text:00418D4B loc_418D4B: ; CODE XREF: debuggerCheck:loc_418D39j
.text:00418D4B xor eax, eax
.text:00418D4D nop
.text:00418D4E nop
.text:00418D4F nop
.text:00418D50 retn
.text:00418D50 debuggerCheck endp
Keresgélés és file-ok nézegetése után megtaláltam, hogy a regionalizált üzenetek egy sajátos erőforrásfile-ban találhatók a iTunes\iTunes.Resources\en.lproj\Localizable.strings file-ban. A könyvtárban még található egy iTunesLocalized.dll is, ami az előbb említett file-t tölti be. Tehát azt a pontot kell megtalálnunk, hogy mely ponton töltődik be a DLL.
A nyomkövetés kalandjait nem említem meg, hanem csak az eredményeket mutatom meg. Az "iTunesLocalized" szöveget unicode formátumban a .00FBE7F0 offszeten találtam meg, amire .01099AB0 címet találhatunk hivatkozást. Ezt a mutatót a .004F87A6 címen levő kód olvassa be.
.text:004F87A6 mov eax, module3 ; iTunesLocalized
.text:004F87AB mov ecx, module2 ; iTunes
.text:004F87B1 push edx ; module4
.text:004F87B2 mov edx, iTunesModuleName ; iTunes
.text:004F87B8 push eax ; module3
.text:004F87B9 push ecx ; module2
.text:004F87BA push edx ; module1
.text:004F87BB call initResourceModules
Némi alakítgatás ereményeként látható, hogy egy erőforrás inicializáló eljárás kapja meg néhány másik modul neve társaságában (iTunesRegistry, iTunesLocalized, iTunes).
.text:0047BABD mov ebp, ds:LoadLibraryW
.text:0047BAC3 mov eax, esi
.text:0047BAC5 push eax ; lpLibFileName
.text:0047BAC6 call ebp ; LoadLibraryW
.text:0047BAC8 test eax, eax
.text:0047BACA mov addrITunesRegistry, eax
.text:0047BACF jz short failedInitialization
Az iTunesRegistry.dll-t az iTunes.Resources könyvtárban keresi és próbálja betölteni.
.text:0047BAD8 mov edi, [esp+224h+var_210]
.text:0047BADC push ecx
.text:0047BADD xor ecx, ecx ; int
.text:0047BADF mov eax, ebx
.text:0047BAE1 call getLocalizedDLLName
.text:0047BAE6 add esp, 4
.text:0047BAE9 mov edx, esi
.text:0047BAEB push edx ; lpLibFileName
.text:0047BAEC call ebp ; LoadLibraryW
.text:0047BAEE test eax, eax
.text:0047BAF0 mov addrITunesLocalized, eax
.text:0047BAF5 jz short failedInitialization
Lokalizált erőforrás-könyvtárból próbálja meg betölteni az iTunesLocalized.dll-t (iTunes.Resources\en.lproj).
.text:0047BB02 mov eax, esi
.text:0047BB04 push eax ; lpLibFileName
.text:0047BB05 call ebp ; LoadLibraryW
.text:0047BB07 test eax, eax
.text:0047BB09 mov addrITunesDLL, eax
.text:0047BB0E jnz short loc_47BB2E
Szintén az iTunes.Resources könyvtárból próbálja meg betölteni az iTunes.dll file-t. Emlékezzünk vissza, hogy a betöltött modulok címét hova töltöttük be.
.data:013B2720 ; sub_47B370+9r ...
.data:013B2724 addrITunesDLL dd ? ; DATA XREF: initResourceModules+C9
.data:013B2728 addrITunesEXE dd ? ; DATA XREF: initResourceModules+F6
.data:013B272C dword_13B272C dd ? ; DATA XREF: initResourceModules+FB
Az első elem keresztreferenciái között egy kis függvény érdekes a számunka.
.text:0047B370 getITunesLocalizedModuleBase proc near ; CODE XREF: sub_41E930+CCp
.text:0047B370 ; sub_41EAD0+14p ...
.text:0047B370 mov al, byte_13B271D
.text:0047B375 neg al
.text:0047B377 sbb eax, eax
.text:0047B379 and eax, addrITunesLocalized
.text:0047B37F retn
.text:0047B37F getITunesLocalizedModuleBase endp
Az eljárás jól láthatóan az iTunesLocalized.dll báziscímét adja vissza abban az esetben, ha megtörtént már az inicializáció ezelőtt. Ezt az eljárást több másik is hívjak, amelyek lokalizált erőforrásokat akarnak elérni. A báziscímet handlerként használják fel olyan rendszerhívásokhoz, amelyek dialógusokat vagy bármi mást próbálnak betölteni.
Ez a rutin mellett egy másikra is érdemes odafigyelni, amit ugyancsak az addrITunesLocalized referenciái között találhatunk meg.
.text:0047B350 getResourceModulAddress proc near ; CODE XREF: LoadStringWLocalized+4Fp
.text:0047B350 ; LoadStringALocalized+3Cp ...
.text:0047B350
.text:0047B350 counter= byte ptr 4
.text:0047B350
.text:0047B350 cmp byte_13B271D, 0
.text:0047B357 jz short loc_47B36C
.text:0047B359 mov al, [esp+counter]
.text:0047B35D cmp al, 4
.text:0047B35F jnb short loc_47B36C
.text:0047B361 movzx eax, al
.text:0047B364 mov eax, addrITunesLocalized[eax*4]
.text:0047B36B retn
.text:0047B36C ; ---------------------------------------------------------------------------
.text:0047B36C
.text:0047B36C loc_47B36C: ; CODE XREF: getResourceModulAddress+7
.text:0047B36C ; getResourceModulAddress+Fj
.text:0047B36C xor eax, eax
.text:0047B36E retn
.text:0047B36E getResourceModulAddress endp
Annyival tud többet, hogy a tábla paraméter által meghatározott elemének báziscímét adja vissza. A kép akkor áll össze, ha tovább lépünk a hivatkozó eljárásokra, ahol azt látjuk, hogy LoadStringA, LoadStringW, LoadMenuA, LoadIconA, LoadCursor, LoadImage és még hasonló eljárások segítségével keres egy erőforrást és amint sikerül betöltetni, megszakítja a keresést.
Megpróbáltatásaink itt koránt sem érnek véget. Vizsgáljuk tovább a getITunesLocalizedModuleBase függvényt hívó eljárásokat. Találni fogunk egy .0041E9FC hivatkozást, ami dialógus ablak megjelenítésének a programja. Mivel ez a függvény generikusnak néz ki (paraméterei: template név, dialógus callback függvény, üzenet), ezért az ő hívói között kell kutatnunk, amig rá nem találunk a .004A1306 címre, ami már sokkal szimpatikusabb, de még mindig nem az igazi. Ugyan látható, hogy paraméterezéshez fix callback függvény címet és sablonnevet ad át (GenericUserMessageDlg), de az üzenet konkretizálása még mindig nincs meg. Hol kapja akkor meg ezt a paramétert, mert a jelent eljárás paraméterei között nem. Figyelmesen vizsgálva ráakadhatunk az EDI regiszterre, amit egy buffer átalakító eljárásnak ad át és előzőleg nem inicializálta sehol sem. Nézzük meg, honnan kerül ide a vezérlés.
.text:004A1370 showGenericUserMessageDlg proc near ; CODE XREF: sub_49EF60+3Dp
.text:004A1370 ; sub_4AD0C0+45p ...
.text:004A1370
.text:004A1370 message= dword ptr 4
.text:004A1370 arg_4= dword ptr 8
.text:004A1370
.text:004A1370 push esi
.text:004A1371 mov esi, [esp+4+arg_4]
.text:004A1375 push edi
.text:004A1376 mov edi, [esp+8+message]
.text:004A137A push 7F04h
.text:004A137F push 0
.text:004A1381 call innerGenericUserMessageDlg
.text:004A1386 add esp, 8
.text:004A1389 pop edi
.text:004A138A pop esi
.text:004A138B retn
.text:004A138B showGenericUserMessageDlg endp
így már érthetőbb, azonban még ez sem legyen elég. Sok helyről hívják, de minden referencia környezetében egyvalami közös; mindenütt egy függvényhívás szerepel előtte, aminek a címe .00490720 és furcsa módon két konstans értéket ad át.
.text:00490720 getLocalizedMessageByResourceID proc near ; CODE XREF: sub_4116D0+122p
.text:00490720 ; sub_4116D0+143p ...
.text:00490720
.text:00490720 returnBuffer= dword ptr 4
.text:00490720 majorResourceID= word ptr 8
.text:00490720 minorResourceID= dword ptr 0Ch
Ez a függvény felelős az erőforrás azonosítók alapján történő szövegek kifejtéséért.
Most játszunk egy kicsit. Tegyünk le ennek a függvénynek az elejére egy megszakítást és adjuk meg a következő feltételt:
Word(esp+8) == 0xA3 && Word(esp+0xC) == 0x58
Most válasszunk ki a listából egy dalt, jobb katt és "Create ringtone...". A futásnak meg kell állni a .00490720 címen, ha mindent jól csináltunk. A Localizable.string file-ban pedig keressük meg az alábbi sort.
Igen, ez fog megjelenni és ez az eljárás kereste elő (163 = 0xA3, 088 = 0x58).
Hadd jegyezzem még itt meg, hogy nagyon sok függvény és változónév nem adott a visszafejtés során. Nagy segítségemre volt az IDA Pro 5.2 abban, hogy én adjam meg a neveket, illetve a már értelmezett eljárásoknak C szintakszisú szignaturákat definiáljak és ezek szerte a kódban úgy jelenjenek meg.