Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "WinAPI";
Текущий архив: 2005.01.23;
Скачать: [xml.tar.bz2];

Вниз

Поток без длл или самодостаточный код   Найти похожие ветки 

 
kaZaNoVa ©   (2004-11-15 16:52) [40]

я хотел все адреса (Pointer"ы) - преобразовать в стринги и вывести мессагебоксом .. - в целях отладки ...


 
kaZaNoVa ©   (2004-11-15 16:53) [41]

так при  I(5) к примеры - выдаётся исключение .. прога завершается .. странно ..


 
Digitman ©   (2004-11-15 17:00) [42]


> мне надо отладить


на то есть, к примеру, оч даже неплохой дебаггер OllyDbg


> хотел все адреса (Pointer"ы) - преобразовать в стринги и
> вывести мессагебоксом .. - в целях отладки ...


для использования станд.ф-ций "преобразования" в АП "чужого" процесса должны присутствовать как минимум модули System, SysUtils

жми F1 на фразе "Str" - в справке черным по белому написано, что декларация и реализация этой проц-ры находится в модуле system.pas


> выдаётся исключение .. прога завершается .. странно


ничего странного.


 
kaZaNoVa ©   (2004-11-15 17:09) [43]

Digitman ©   (15.11.04 17:00) [42]

> для использования станд.ф-ций "преобразования" в АП
> "чужого" процесса должны присутствовать как минимум
> модули System, SysUtils

так я же его (екзешник) полностью копирую, функции из System должны быть ..
функции из SysUtils не использую ...

- как можно тогда преобразовать ?


 
kaZaNoVa ©   (2004-11-15 21:00) [44]

любопытно, что о сабже много в нете упоминаний, но дальше теории почти нигде ничего нет ..  ;)

по теме - при попытке вызвать какие-нить API-функции, могут возникнуть исключения - как можно обработать ?


 
Digitman ©   (2004-11-16 08:09) [45]


> как можно тогда преобразовать


ручками !


> при попытке вызвать какие-нить API-функции, могут возникнуть
> исключения


какие конкретно ?


 
kaZaNoVa ©   (2004-11-16 17:16) [46]

Digitman ©   (16.11.04 8:09) [45]
а ручками - это как ?
string(переменная типа cardinal) - ерунда получается ... ;(


 
Digitman ©   (2004-11-16 17:25) [47]


> string(переменная типа cardinal) - ерунда получается


разумеется ерунда ... ибо в дан.случае преобразование к неявному вызову п/программ, расположенных в system.pas


 
Игорь Шевченко ©   (2004-11-16 17:43) [48]

kaZaNoVa ©   (16.11.04 17:16) [46]


> string(переменная типа cardinal) - ерунда получается ...
> ;(


Я очень извиняюсь, но не рано ли с такими знаниями браться за "Поток без длл или самодостаточный код " ?


 
kaZaNoVa ©   (2004-11-16 18:53) [49]

Игорь Шевченко ©   (16.11.04 17:43) [48]
признаюсь ..  что некоторые вещи я вообще не знаю ..
- все мы специалисты в какой-то своей области ....


 
kaZaNoVa ©   (2004-11-16 19:06) [50]

Игорь Шевченко ©   (16.11.04 17:43) [48]
также, по поводу "рано ли":
можно годами изучать "основы", и изучить их в совершенстве, и топтаться на месте ...

можно изучить основы, а потом и всё более сложное- идеальный вариант, но не всегда для этого есть время и желание ...

а можно так -  поставить задачу, изучить быстро всё, что нужно именно для этой задачи - и выполнит её ! - пусть не будет глубоких систематических знаний, НО задача будет решена - а это главное !!!

п.с. раньше я всегда боялся "спросить что-нить простое" - так как боялся выглядеть некомпетентным ..
и этот подход мне принёс в своё время массу проблем ..
Теперь я считаю - лучше раз спросить что-то из азов, и , возможно, показаться "ламаком", но, при полученном грамотном ответе - понять это, и решить задачу более грамотно ..

по поводу "читай справку", "есть в FAQ" - не спорю, важно .. НО почему-то во всех университетах есть консультации с преподавателями - так как не каждая задача есть в справке, и не каждый сможет найти быстро ответ ..  а иначе бы никаких "консультаций" не существовало бы - всех бы отсылали  к энциклопедиям .. ;)

//извиняюсь за оффтоп - но это была моя самая главная мысль по поводу "внешне глупых вопросов" ...


 
Digitman ©   (2004-11-17 08:09) [51]


> kaZaNoVa


без отладчика и хотя бы элементарного знания ассемблера решить подобную задачу надежно и эффективно вряд ли получится .. по кр.мере на первых порах

можно долго и нужно выспрашивать здесь "азы" (коих ой как немало), но толку от этого будет с гулькин нос .. для "толка" будет крайне полезно запустить под отладчиком целевой процесс, записать код внедряемого трэда в целевое АП, поставить брейкпойнт на точке входа в трэд-функцию и далее шаг за шагом пройти тело трэда, внимательно контролируя всякий раз обращения мащ.инструкций к памяти и сравнивая ожидаемое с действительным .. это лучший способ понять, "чего в супе не хватает" или чего там явно лишнего


 
kaZaNoVa ©   (2004-11-17 18:42) [52]

Digitman ©   (17.11.04 8:09) [51]
ок, спасибо огромное, попробую под отладчиком всесторонне изучить :)


 
kaZaNoVa ©   (2004-11-19 12:18) [53]

Кто-нить пробовал реализовать сабж ?
- постите, плиз ..


 
Digitman ©   (2004-11-19 13:03) [54]


> kaZaNoVa ©   (19.11.04 12:18) [53]
> Кто-нить пробовал реализовать сабж ?


ты о чем ?


 
Cobalt ©   (2004-11-19 15:43) [55]

> по кр.мере на первых порах
Я бы сказал "на первых годах" :)


 
kaZaNoVa ©   (2004-11-19 15:48) [56]

Digitman ©   (19.11.04 13:03) [54]
мне просто некогда щас более заниматься этой идеей ..

- и хотел спросить - может кто уже пробовал .. - поучиться на примерах .. (так хочется "готовое решение" найти ..)

:)


 
Digitman ©   (2004-11-19 15:56) [57]


> мне просто некогда щас более заниматься этой идее


а это твои проблемы.


> хотел спросить - может кто уже пробовал .. - поучиться на
> примерах .. (так хочется "готовое решение" найти


готовых нет, не будет и быть не может по определению.
хочешь быстрое и беспроблемное решение ?
его ты уже знаешь - внедрение ДЛЛ ... и это решение - далеко не самое худшее.


 
kaZaNoVa ©   (2004-11-19 16:05) [58]

Digitman ©   (19.11.04 15:56) [57]
ок ;))
спасибо за совет .. :))

> внедрение ДЛЛ

эх .. старое решение ..  но надёжное :))


 
kaZaNoVa ©   (2004-11-19 16:08) [59]

Digitman ©   (19.11.04 15:56) [57]

> готовых нет, не будет и быть не может по определению.

я нашёл одно (оно в самом первом посте .. ) но оно, как я уже убедился в общем случае неверное ....

п.с. буду ждать примеры %)))


 
kaZaNoVa ©   (2004-11-19 16:09) [60]

а так я понял, что полностью грамотно пока сделать не могу ..  ;(


 
Игорь Шевченко ©   (2004-11-19 16:23) [61]

Если пустые сообщения не прекратятся ветка будет закрыта.

С уважением,
Ко-модератор


 
kaZaNoVa ©   (2004-11-20 15:40) [62]

Я проанализировал работу кода в "целевом" процессе и пришёл к выводу что "позиционно-независимый" код стандартными средствами Delphi создать крайне сложно и практически неприемлимо (как и драйвер).

После многочисленных экспериментов я пришёл к выводу , что единственный способ _достаточно простой и работоспособный_ - это способ с ImageBase.

Мой "финальный демонстрационный код" (итог моих "изысканий") :

program loader;
{$IMAGEBASE $70000000}
uses
 Windows;

Var
hProcess, hTh: THandle;
MemPtr: Pointer;
PID,ExitCode,Size,BytesWritten,ThreadID: Cardinal;

function Main(dwEntryPoint: Pointer): longword; stdcall;
begin
LoadLibrary("kernel32.dll");
LoadLibrary("user32.dll");
MessageBox(0,"Fantastika !!!", "Hijacked Process", 0);
Result:=0;
end;

begin
GetWindowThreadProcessId(FindWindow("Progman", nil), @PID);
if PID = 0 then Exit;

MemPtr:= Pointer(GetModuleHandle(nil));

Size := PImageOptionalHeader(Pointer(integer(MemPtr) + PImageDosHeader(MemPtr)._lfanew + SizeOf(dword) + SizeOf(TImageFileHeader))).SizeOfImage;

hProcess := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE,true,PID);

if hProcess = 0 then Exit;

BytesWritten:=0;
VirtualFreeEx(hProcess,MemPtr, 0, MEM_RELEASE);
 MemPtr := VirtualAllocEx(hProcess,MemPtr, Size , MEM_COMMIT or MEM_RESERVE, PAGE_EXECUTE_READWRITE );

 if MemPtr <> nil then
 begin
   if WriteProcessMemory(hProcess, MemPtr,MemPtr, Size, BytesWritten) then
   begin
   hTh := CreateRemoteThread(hProcess, nil, 0,@Main,MemPtr, 0, ThreadID);
     if hTh <> 0 then
     begin
       if (WaitForSingleObject(hTh,INFINITE) = WAIT_OBJECT_0) and
         GetExitCodeThread(hTh, ExitCode) then CloseHandle(hTh);
     end;
   end ;
   VirtualFreeEx(hProcess, MemPtr, 0, MEM_RELEASE);  //?
 end;
 CloseHandle(hProcess);
end.


Игорь Шевченко ©   (19.11.04 16:23) [61]
Со своей стороны считаю тему "закрытой" ;)


 
n0name   (2004-11-20 18:14) [63]

Я со своей стороны считаю что позиционно-независимый(так как я понимаю) создать в Delphi возможно. Основная трабла с определением API. Так вот алт. код GetProcAddress и GetModuleHandle.


unit xFuncs;

interface

uses
DrvTypes;

function xGetModuleHandle(ModuleName: PChar): HMODULE;
function xGetProcAddress(hMod: HMODULE; ProcName: PChar): Pointer;

implementation

function GetCurrentPEB: PPEB;
asm
mov eax, fs:[30h]
mov result, eax
end;

function CompareMultibyteWithAnsi(str1: PWChar; str2: PChar): boolean;
var
i: DWORD;
begin
result:=false;
i:=0;
while (PChar(DWORD(str1)+i*2)^<>#0) and (str2[i]<>#0) do
 begin
  if PChar(DWORD(str1)+i*2)^<>str2[i] then
   exit;
  inc(i);
 end;
result:=true;
end;

function GetPCharLength(str1: PChar): DWORD;
begin
result:=0;
while (str1[result]<>#0) do
 inc(result);
end;

function ComparePCharStrings(str1, str2: PChar): boolean;
var
i: DWORD;
begin
result:=false;
i:=0;
if GetPCharLength(str1)<>GetPCharLength(str2) then
 exit;
while (str1[i]<>#0) do
 begin
  if str1[i]<>str2[i] then
   exit;
  inc(i);
 end;
result:=true;
end;

function xGetModuleHandle(ModuleName: PChar): HMODULE;
var
FirstMod: Pointer;
CurrentMod: TLdrDataTableEntry;
begin
result:=0;

FirstMod:=GetCurrentPEB.Ldr.InLoadOrderModuleList.FLink;
CurrentMod:=PLdrDataTableEntry(FirstMod)^;
repeat
 if FirstMod=CurrentMod.InLoadOrderLinks.FLink then
  exit;
 if CompareMultibyteWithAnsi(CurrentMod.BaseDllName.Buffer, ModuleName) then
  begin
   result:=DWORD(CurrentMod.DllBase);
   exit;
  end;
 CurrentMod:=PLdrDataTableEntry(CurrentMod.InLoadOrderLinks.Flink)^;
until (not true);
end;

function xGetProcAddress(hMod: HMODULE; ProcName: PChar): Pointer;
var
ExportDir: PImageExportDirectory;
dwAddressOfNames: DWORD;
dwAddressOfFunctions: DWORD;
i: DWORD;
begin
result:=nil;
ExportDir:=PImageExportDirectory(PImageNtHeaders(hMod+DWORD(PImageDosHeader(hMod)._lfanew)).OptionalHeader.
 DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress+hMod);
dwAddressOfNames:=DWORD(ExportDir.AddressOfNames);
dwAddressOfFunctions:=DWORD(ExportDir.AddressOfFunctions);
for i:=0 to ExportDir.NumberOfNames-1 do
 if ComparePCharStrings(PChar(PDWORD(dwAddressOfNames+hMod+i*4)^+hMod), ProcName) then
  result:=Pointer(PDWORD(dwAddressOfFunctions+hMod+i*4)^+hMod);
end;

end.


PS: Весь код написан мною.


 
kaZaNoVa ©   (2004-11-20 18:27) [64]

n0name   (20.11.04 18:14) [63]
огромное спасибо :)

можно ещё

>unit xFuncs;
>
>interface
>
>uses
> DrvTypes;

- можно ещё на юнит DrvTypes посмотреть  ?


 
Игорь Шевченко ©   (2004-11-20 18:39) [65]


> PS: Весь код написан мною.


А кажется таким знакомым...отдельные места.

Кстати, совет - в процедуре GetModuleHandle блокируй загрузчик, а по выходе разблокируй.


 
n0name   (2004-11-21 18:27) [66]

Игорь Шевченко ©   (20.11.04 18:39) [65]    
Не знаю почему он тебе кажется знакомым.
Писал полностью я. Без привлечения сторонних исходников и документации. Корме ,пожалуй, описания PE-формата.

Про какой загрузчик ты говоришь?
Если ты насчёт того, что во время перебора TLdrDataTableEntry могут загрузиться новые модули, то я не знаю какой функцией это выполняется. Можешь подсказать? (Мне неохота заниматься дизасмингом GetModuleHandle).

kaZaNoVa ©   (20.11.04 18:27) [64]
Весь DrvTypes я выкладывать не буду(47,7 KB   1831 строк кода).
Скажи нужные тебе типы и константы.


 
n0name   (2004-11-21 19:21) [67]

n0name   (21.11.04 18:27) [66]

Я не вытерпел и дизасмил всё-таки GetModuleHandle :)
Нашёл эти функции - LdrLockLoaderLock и LdrUnlockLoaderLock.
Пока искал их прототипы нашёл для себя много интересного. Например предпологаемый код некоторых фунций, используемых загрузчиком(т.е. LdrLoadDll, LdrUnloadDll, etc).

Если интересно, вот ковая версия xGetModuleHandle(greet Игорь Шевченко):

function LdrLockLoaderLock(Flags: DWORD; result, Magic: PDWORD): NTSTATUS; stdcall; external "ntdll.dll";
function LdrUnlockLoaderLock(Flags, Magic: DWORD): NTSTATUS; stdcall; external "ntdll.dll";
....
function xGetModuleHandle(ModuleName: PChar): HMODULE;
var
FirstMod: Pointer;
CurrentMod: TLdrDataTableEntry;
LdrLockMagic: DWORD;
begin
result:=0;

LdrLockLoaderLock(0, nil, @LdrLockMagic);

FirstMod:=GetCurrentPEB.Ldr.InLoadOrderModuleList.FLink;
CurrentMod:=PLdrDataTableEntry(FirstMod)^;
repeat
 if FirstMod=CurrentMod.InLoadOrderLinks.FLink then
  exit;
 if CompareMultibyteWithAnsi(CurrentMod.BaseDllName.Buffer, ModuleName) then
  begin
   result:=DWORD(CurrentMod.DllBase);
   exit;
  end;
 CurrentMod:=PLdrDataTableEntry(CurrentMod.InLoadOrderLinks.Flink)^;
until (not true);

LdrUnlockLoaderLock(0, LdrLockMagic);
end;


 
Игорь Шевченко ©   (2004-11-21 20:01) [68]


> Не знаю почему он тебе кажется знакомым.


Где-то видел, может, аналогичный. Что-то сам писал пару лет назад, только идентификаторы брались из WinDbg, а они там несколько иные в структуре LDR_DATA_TABLE_ENTRY


 
n0name   (2004-11-22 11:11) [69]

Не знаешь, всегда ли ntdll.dll загружается первым?(не в драйверах). Мне просто лучше использовать дин. загрузку.


 
Игорь Шевченко ©   (2004-11-22 11:17) [70]

n0name   (22.11.04 11:11) [69]

Всегда. Там же находится загрузчик, который загружает все-все остальное.


 
Xaker ©   (2004-11-22 11:26) [71]

n0name   (20.11.04 18:14) [63]
ловко ты придумал
а что такое TLdrDataTableEntry ?


 
n0name   (2004-11-22 11:57) [72]

Xaker ©   (22.11.04 11:26) [71]

TLdrDataTableEntry=packed record
 InLoadOrderLinks: TListEntry;                  //+0
 InMemoryOrderLinks: TListEntry;                //+8
 InInitializationOrderLinks: TListEntry;        //+16
 DllBase: Pointer;                              //+24
 EntryPoint: Pointer;                           //+28
 SizeOfImage: Cardinal;                         //+32
 FullDllName: UNICODE_STRING;                   //+36
 BaseDllName: UNICODE_STRING;                   //+44
 Flags: cardinal;                               //+52
 LoadCount: word;                               //+56
 TlsIndex: word;                                //+58
 HashLinks: TListEntry;                         //+60
 SectionPointer: Pointer;                       //+68
 CheckSum: Cardinal;                            //+72
 TimeDateStamp: Cardinal;                       //+76
 LoadedImports: Pointer;                        //+80
end;                                            //Size: 84
PLdrDataTableEntry=^TLdrDataTableEntry;

TLdrListEntry=packed record
 ListEntry: TListEntry;
 LdrDataTableEntry: TLdrDataTableEntry;
end;
PLdrListEntry=^TLdrListEntry;

TPebLdrData=packed record
 length: Cardinal;    
 initialized: Cardinal;    
 SsHandle: Pointer;    
 InLoadOrderModuleList: TListEntry;  
 InMemoryOrderModuleList: TListEntry;
 InInitializationOrderModuleList: TListEntry;
end;
PPebLdrData=^TPebLdrData;



Игорь Шевченко ©   (22.11.04 11:17) [70]
Я так и думал :)


 
Xaker ©   (2004-11-22 12:17) [73]

n0name   (22.11.04 11:57) [72]
big thanks ещё проблема с FirstMod:=GetCurrentPEB.Ldr.InLoadOrderModuleList.FLink; - где там Ldr и  InLoadOrderModuleList  ?
(интересует PPEB)


 
n0name   (2004-11-22 13:30) [74]

Xaker ©   (22.11.04 12:17) [73]


TPEB=packed record
 InheritedAddressSpace: boolean;
 ReadImageFileExecOptions: boolean;
 BeingDebugged: boolean;
 b003: byte;
 d004: DWORD;
 SectionBaseAddress: Pointer;
 Ldr: PPebLdrData;
 ProcessParameters: PPROCESS_PARAMETERS;
 SubSystemData: DWORD;
 ProcessHeap: THandle;
 FastPebLock: PCRITICAL_SECTION;
 AcquireFastPebLock: Pointer;
 ReleaseFastPebLock: Pointer;
 d028: DWORD;
 User32Dispatch: PPointer;
 d030: DWORD;
 do34: DWORD;
 d038: DWORD;
 TlsBitMapSize: DWORD;
 TlsBitMap: PRTL_BITMAP;
 TlsBitMapData: array [0..1] of DWORD;
 p04C: Pointer;
 p050: Pointer;
 TextInfo: Pointer;
 InitAnsiCodePageData: Pointer;
 InitOemCodePageData: Pointer;
 InitUnicodeCaseTableData: Pointer;
 KeNumberProcessors: DWORD;
 NtGlobalFlag: DWORD;
 d6C: DWORD;
 MmCriticalSectionTimeout: LARGE_INTEGER;
 MmHeapSegmentReserve: DWORD;
 MmHeapSegmentCommit: DWORD;
 MmHeapDeCommitTotalFreeThreshold: DWORD;
 MmHeapDeCommitFreeBlockThreshold: DWORD;
 NumberOfHeaps: DWORD;
 AvailableHeaps: DWORD;
 ProcessHeapsListBuffer: PHandle;
 d094: DWORD;
 d098: DWORD;
 d09C: DWORD;
 LoaderLock: PCRITICAL_SECTION;
 NtMajorVersion: DWORD;
 NtMinorVersion: DWORD;
 NtBuildNumber: WORD;
 CmNtCSDVersion: WORD;
 PlatformId: DWORD;
 Subsystem: DWORD;
 MajorSubsystemVersion: DWORD;
 MinorSubsystemVersion: DWORD;
 AffinityMask: KAFFINITY;
 ad0C4: array [0..34] of DWORD;
 p150: Pointer;
 ad154: array [0..31] of DWORD;
 Win32WindowStation: THandle;
 d1D8: DWORD;
 d1DC: DWORD;
 CSDVersion: PWORD;
 d1E4: DWORD;
end;


 
Игорь Шевченко ©   (2004-11-22 15:04) [75]

n0name   (22.11.04 13:30) [74]

b003: byte;
d004: DWORD;
--------------
   SpareBool        : UChar;
   Mutant           : Ptr32;
==============
d028: DWORD;
--------------
   EnvironmentUpdateCount : Uint4B;
==============
d030: DWORD;
do34: DWORD;
d038: DWORD;
-------------
   SystemReserved   : Uint4B;
   ExecuteOptions   : Uint4B; {Pos 0, 2 Bits, SpareBits  : Pos 2, 30 Bits }
   FreeList         : Ptr32; { _PEB_FREE_BLOCK }
=============
p04C: Pointer;
p050: Pointer;
TextInfo: Pointer;
-----------
   ReadOnlySharedMemoryBase : Ptr32;
   ReadOnlySharedMemoryHeap : Ptr32;
   ReadOnlyStaticServerData : Ptr32;
===========

И так далее.


 
Piter ©   (2004-11-22 15:41) [76]

Извините, а можно вопрос? Зачем вы пишете свой GetModuleHandle? Ведь он находится в kernel, который грузится по одному и тому же адресу. Сори, если я чего-то не понял...


 
n0name   (2004-11-23 19:32) [77]

Игорь Шевченко ©   (22.11.04 15:04) [75]
Спасибо, можешь подсказать, откуда у тебя эти сведения?

Piter ©   (22.11.04 15:41) [76]
Kernel32.dll не всегда грузится по одному адресу. Если ImageBase программы равен адресу ImageBase kernel32.dll, то используются релоки и длл грузится по другому адресу.


 
Piter ©   (2004-11-23 23:26) [78]

>Kernel32.dll не всегда грузится по одному адресу

понятно. Просто я почитал:

Digitman ©   (12.11.04 12:46) [9]
основываясь на достаточно устойчивом факте загрузки kernel32 по фикс.адресу


и понял, что на это фактически можно полагаться...


 
Игорь Шевченко ©   (2004-11-24 00:13) [79]

n0name   (23.11.04 19:32) [77]

Из отладчика WinDbg и символов Windows.
Есть предложение - если тебя интересуют знания потрохов, структур и так далее - пиши на whitefranz@hotmail.com


 
Digitman ©   (2004-11-24 08:18) [80]


> Piter ©   (23.11.04 23:26) [78]


имелся ввиду не какой-то конкретный адрес, а то что в рамках одной и той же сессии ОС образ модуля kernel32 в АП всех использующих его приложениях будет находиться по одному и тому же адресу, поскольку как правило статически загружается одним из первых системных модулей, импортируемых win32-приложениями.



Страницы: 1 2 3 вся ветка

Форум: "WinAPI";
Текущий архив: 2005.01.23;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.64 MB
Время: 0.219 c
1-1105539322
Mishenka
2005-01-12 17:15
2005.01.23
Как из переменной типа TDateTime извлечь отдельно Time и Date?


1-1105157951
Progh
2005-01-08 07:19
2005.01.23
Указатели


4-1100617539
grigory
2004-11-16 18:05
2005.01.23
чтение FAT


1-1105464482
Magic_STI
2005-01-11 20:28
2005.01.23
Вывод ресалтов поиска


14-1104954989
Layner
2005-01-05 22:56
2005.01.23
Приветствую всех! Есть ли в природе переходник USB-COM?





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский