eXeLab
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 10 декабря!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

Русский / Russian English / Английский

Сейчас на форуме:
 · Начало · Статистика · Регистрация · Поиск · ПРАВИЛА ФОРУМА · Язык · RSS · SVN ·

 eXeL@B —› Программирование —› Как получить аргумент из функции в памяти
. 1 . 2 . >>
Посл.ответ Сообщение

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 04:29 New!
Цитата · Личное сообщение · #1

Есть хук который цепляется к опр адресу в ехешнике, цепляется он к одному из методов класса, вот он
Code:
  1. .text:00749350 ; public: class oCItem * __thiscall oCNpc::PutInInv(class oCItem *)

И вот вопрос, собственно нужно получить аргумент, и собственно указатель на oCNpc, как это сделать?

P.s. Знания относительно реверса, крайне скудны, так что прошу ногами не пинать сразу, занимаюсь модингом одной игры.

Ранг: 488.4 (мудрец)
Статус: Участник

Создано: 17 ноября 2014 07:46 · Поправил: VodoleY New!
Цитата · Личное сообщение · #2

Saturas 1. зависит от самого класса. статический или динамический. 2. сильно зависит от языка программирования, в каждом свои ньюансы. Если ВООБЩЕМ. то ваш класс, это указатель на область памяти, в которой список указателей, структур , переменных . Чтоб узнать какой указатель на что указывает (в классе) надо рыть в проге описание класса oCItem и сопостовлять указатели со структурой класса

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 10:40 New!
Цитата · Личное сообщение · #3

класс динамический, описание есть, язык С++, более того функция которая создает хуки, может так же ловить некоторые аргументы, конкретно если они не являются указателями, а вот с указателями есть пара проблем.


Ранг: 994.1 (! ! !)
Статус: Участник

Создано: 17 ноября 2014 11:11 New!
Цитата · Личное сообщение · #4

указатель в ecx, какие еще вопросы?


Ранг: 307.4 (мудрец)
Статус: Участник

Создано: 17 ноября 2014 11:38 · Поправил: Vamit New!
Цитата · Личное сообщение · #5

reversecode пишет:
указатель в ecx, какие еще вопросы?

Ну не всегда так, зависит от версии VS компилятора и типа функи, может передаваться как через регистры так и через стек. Всегда нужно смотреть конкретную реализацию в коде.


Ранг: 994.1 (! ! !)
Статус: Участник

Создано: 17 ноября 2014 11:44 New!
Цитата · Личное сообщение · #6

Vamit
в его случае ecx
Saturas пишет:
.text:00749350 ; public: class oCItem * __thiscall oCNpc::PutInInv(class oCItem *)


vc всегда по стандарту ecx,
что бы был через стек, нужно специально vc ломать опциями
а вот gcc в зависимости от версии, в ранних был стек, сейчас по разному

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 12:03 New!
Цитата · Личное сообщение · #7

Вопрос, как его из ecx получить? И аргумент, вот.

Ранг: 488.4 (мудрец)
Статус: Участник

Создано: 17 ноября 2014 12:05 New!
Цитата · Личное сообщение · #8

(я ушел рыдать, не беспокоить)


Ранг: 994.1 (! ! !)
Статус: Участник

Создано: 17 ноября 2014 12:13 New!
Цитата · Личное сообщение · #9

Saturas
пользуйтесь гуглом, ваши вопросы в нем уже решены

| Сообщение посчитали полезным: Saturas


Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 12:17 New!
Цитата · Личное сообщение · #10

reversecode пишет:
пользуйтесь гуглом, ваши вопросы в нем уже решены

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


Ранг: 994.1 (! ! !)
Статус: Участник

Создано: 17 ноября 2014 12:29 New!
Цитата · Личное сообщение · #11

у нас видимо какой то разный гугл?
http://stackoverflow.com/questions/6979558/hooking-hot-patching-class-member-functions-modifying-vtable-entries
http://stackoverflow.com/questions/14069467/hooking-non-virtual-member-functions-in-c
итд

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 13:48 New!
Цитата · Личное сообщение · #12

Code:
  1.          void* uAddr = 0;
  2.          void* uItem = 0;
  3.          //Get npc ptr
  4.          __asm mov EAX, DWORD PTR SS:[EBP + 0x08]  //<<-- PTR from stack to EAX
  5.     __asm mov  DWORD PTR DS:[uAddr], EAX       //<<-- EAX to var
  6.          //Get item ptr
  7.          __asm mov EAX, DWORD PTR SS:[EBP + 0x0C]
  8.     __asm mov  DWORD PTR DS:[uItem], EAX
  9.          oCNpc* npc = (oCNpc*)uAddr;
  10.          oCItem* item = (oCItem*)uItem;
  11.  

Сделал таким образом, 0x08 - адресс указателя this, 0x0C - аргумент


Ранг: 994.1 (! ! !)
Статус: Участник

Создано: 17 ноября 2014 13:52 New!
Цитата · Личное сообщение · #13

не видя реального кода ничего нельзя прокомментировать
работает? ну и ладно


Статус: Пришелец

Создано: 17 ноября 2014 14:11 New!
Цитата #14

Весь ваш код легко заменяется на Си++ и все ассемблерные ставки идут лесом.

Стандартные соглашения о связях гласят, что в начале процедуры будет такой код:
Code:
  1. push ebp
  2. mov ebp, esp


После чего можно брать значения:
ebp[0] = ebp_old
ebp[4] = return_address
ebp[8] = Arg1
ebp[0xC] = Arg2

Ваш код работает в случае, если this лежит в первом аргументе, но стек это медленная штука и обычно используют регистр ecx. Если ваш код правильный и this действительно в стеке:
Code:
  1. class oCItem * oCNpc__PutInInv(class oCNpc *Arg1, class oCItem *Arg2) {
  2.     oCNpc* npc = (oCNpc*)Arg1;
  3.     oCItem* item = (oCItem*)Arg2;
  4. }

Если же, все-таки ecx
Code:
  1. struct oCNpc {
  2.    class oCItem *__thiscall PutInInv();
  3. };
  4. class oCItem * oCNpc::PutInInv(class oCItem *Arg2) {
  5.     oCNpc* npc = this;
  6.     oCItem* item = (oCItem*)Arg2;
  7. }

Второй случай это грустная история, ибо требует полное восстановление структуры данных в своем коде структуры/класса oCNpc (с учетом всех наследований и типов). Хотя, скорее всего, раз вы его у себя объявили, значит он где-то есть в исходных кодах.

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 17:47 New!
Цитата · Личное сообщение · #15

Чет не совсем понимаю, что есть ebp_old, и если вы пишите что вставки идут лесом, тогда как быть с этим кодом, или я что то не так понял?
Code:
  1. push ebp
  2. mov ebp, esp


Ранг: 994.1 (! ! !)
Статус: Участник

Создано: 17 ноября 2014 17:49 New!
Цитата · Личное сообщение · #16

предоставте листинг вашей процедуры куда вы там вклиниваетесь

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 17:52 New!
Цитата · Личное сообщение · #17

Code:
  1. .text:00749350 ; public: class oCItem * __thiscall oCNpc::PutInInv(class oCItem *)
  2. .text:00749350 ?PutInInv@oCNpc@@QAEPAVoCItem@@PAV2@@Z proc near
  3. .text:00749350                                         ; CODE XREF: oCNpc::OpenTradeContainer(oCItem *,oCNpc *,int)+1AFp
  4. .text:00749350                                         ; oCNpc::CloseTradeContainer(void)+33p ...
  5. .text:00749350
  6. .text:00749350 var_20          = dword ptr -20h
  7. .text:00749350 var_1C          = byte ptr -1Ch
  8. .text:00749350 var_C           = dword ptr -0Ch
  9. .text:00749350 var_4           = dword ptr -4
  10. .text:00749350 arg_0           = dword ptr  4
  11. .text:00749350
  12. .text:00749350                 mov     eax, large fs:0
  13. .text:00749356                 push    0FFFFFFFFh
  14. .text:00749358                 push    offset unknown_libname_1677 ; Microsoft VisualC 2-9/net runtime
  15. .text:0074935D                 push    eax
  16. .text:0074935E                 mov     large fs:0, esp
  17. .text:00749365                 sub     esp, 14h
  18. .text:00749368                 push    ebx
  19. .text:00749369                 push    esi
  20. .text:0074936A                 mov     esi, [esp+28h+arg_0]
  21. .text:0074936E                 test    esi, esi
  22. .text:00749370                 mov     ebx, ecx
  23. .text:00749372                 jnz     short loc_749389
  24. .text:00749374                 pop     esi
  25. .text:00749375                 xor     eax, eax
  26. .text:00749377                 pop     ebx
  27. .text:00749378                 mov     ecx, [esp+20h+var_C]
  28. .text:0074937C                 mov     large fs:0, ecx
  29. .text:00749383                 add     esp, 20h
  30. .text:00749386                 retn    4
  31. .text:00749389 ; ---------------------------------------------------------------------------
  32. .text:00749389
  33. .text:00749389 loc_749389:                             ; CODE XREF: oCNpc::PutInInv(oCItem *)+22j
  34. .text:00749389                 mov     ecx, esi
  35. .text:0074938B                 call    ?GetObjectName@zCObject@@QBEABVzSTRING@@XZ ; zCObject::GetObjectName(void)
  36. .text:00749390                 lea     ecx, [eax+4]
  37. .text:00749393                 mov     eax, dword_AB1F90
  38. .text:00749398                 test    eax, eax
  39. .text:0074939A                 jnz     short loc_7493A1
  40. .text:0074939C                 mov     eax, offset ?_C@?1??_Nullstr@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@CAPBDXZ@4DB ; char const `std::basic_string<char,std::char_traits<char>,std::allocator<char>>::_Nullstr(void)'::`2'::_C
  41. .text:007493A1
  42. .text:007493A1 loc_7493A1:                             ; CODE XREF: oCNpc::PutInInv(oCItem *)+4Aj
  43. .text:007493A1                 mov     edx, dword_AB1F94
  44. .text:007493A7                 push    edi
  45. .text:007493A8                 push    edx
  46. .text:007493A9                 push    eax
  47. .text:007493AA                 mov     eax, [ecx+8]
  48. .text:007493AD                 push    eax
  49. .text:007493AE                 push    0
  50. .text:007493B0                 call    ?compare@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QBEHIIPBDI@Z ; std::basic_string<char,std::char_traits<char>,std::allocator<char>>::compare(uint,uint,char const *,uint)
  51. .text:007493B5                 test    eax, eax
  52. .text:007493B7                 jnz     short loc_749434
  53. .text:007493B9                 mov     cl, byte ptr [esp+2Ch+arg_0]
  54. .text:007493BD                 mov     [esp+2Ch+var_1C], cl
  55. .text:007493C1                 push    eax
  56. .text:007493C2                 lea     ecx, [esp+30h+var_1C]
  57. .text:007493C6                 call    ?_Tidy@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAEX_N@Z ; std::basic_string<char,std::char_traits<char>,std::allocator<char>>::_Tidy(bool)
  58. .text:007493CB                 or      ecx, 0FFFFFFFFh
  59. .text:007493CE                 xor     eax, eax
  60. .text:007493D0                 mov     edi, offset ??_C@_09GDHM@ITLSTORCH?$AA@ ; "ITLSTORCH"
  61. .text:007493D5                 repne scasb
  62. .text:007493D7                 not     ecx
  63. .text:007493D9                 dec     ecx
  64. .text:007493DA                 push    ecx
  65. .text:007493DB                 push    offset ??_C@_09GDHM@ITLSTORCH?$AA@ ; "ITLSTORCH"
  66. .text:007493E0                 lea     ecx, [esp+34h+var_1C]
  67. .text:007493E4                 call    ?assign@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@QAEAAV12@PBDI@Z ; std::basic_string<char,std::char_traits<char>,std::allocator<char>>::assign(char const *,uint)
  68. .text:007493E9                 mov     edi, offset ??_7zSTRING@@6B@ ; const zSTRING::`vftable'
  69. .text:007493EE                 mov     [esp+2Ch+var_20], edi
  70. .text:007493F2                 mov     ecx, ?ogame@@3PAVoCGame@@A ; oCGame * ogame
  71. .text:007493F8                 mov     eax, [ecx]
  72. .text:007493FA                 lea     edx, [esp+2Ch+var_20]
  73. .text:007493FE                 push    edx
  74. .text:007493FF                 push    81h
  75. .text:00749404                 mov     [esp+34h+var_4], 0
  76. .text:0074940C                 call    dword ptr [eax+8Ch]
  77. .text:00749412                 mov     ecx, eax
  78. .text:00749414                 call    ?CreateVob@oCWorld@@QAEPAVoCVob@@W4zTVobType@@ABVzSTRING@@@Z ; oCWorld::CreateVob(zTVobType,zSTRING const &)
  79. .text:00749419                 push    1
  80. .text:0074941B                 lea     ecx, [esp+30h+var_1C]
  81. .text:0074941F                 mov     esi, eax
  82. .text:00749421                 mov     [esp+30h+var_4], 0FFFFFFFFh
  83. .text:00749429                 mov     [esp+30h+var_20], edi
  84. .text:0074942D                 call    ?_Tidy@?$basic_string@DU?$char_traits@D@std@@V?$allocator@D@2@@std@@AAEX_N@Z ; std::basic_string<char,std::char_traits<char>,std::allocator<char>>::_Tidy(bool)
  85. .text:00749432                 jmp     short loc_749437
  86. .text:00749434 ; ---------------------------------------------------------------------------
  87. .text:00749434
  88. .text:00749434 loc_749434:                             ; CODE XREF: oCNpc::PutInInv(oCItem *)+67j
  89. .text:00749434                 inc     dword ptr [esi+4]
  90. .text:00749437
  91. .text:00749437 loc_749437:                             ; CODE XREF: oCNpc::PutInInv(oCItem *)+E2j
  92. .text:00749437                 mov     edi, [esi+0B8h]
  93. .text:0074943D                 test    edi, edi
  94. .text:0074943F                 jz      short loc_749468
  95. .text:00749441                 mov     edx, [edi]
  96. .text:00749443                 mov     ecx, edi
  97. .text:00749445                 call    dword ptr [edx]
  98. .text:00749447                 test    eax, eax
  99. .text:00749449                 jz      short loc_749468
  100. .text:0074944B                 nop
  101. .text:0074944C                 lea     esp, [esp+0]
  102. .text:00749450
  103. .text:00749450 loc_749450:                             ; CODE XREF: oCNpc::PutInInv(oCItem *)+10Cj
  104. .text:00749450                 cmp     eax, offset ?classDef@oCWorld@@0VzCClassDef@@A ; zCClassDef oCWorld::classDef
  105. .text:00749455                 jz      short loc_749460
  106. .text:00749457                 mov     eax, [eax+3Ch]
  107. .text:0074945A                 test    eax, eax
  108. .text:0074945C                 jnz     short loc_749450
  109. .text:0074945E                 jmp     short loc_749468
  110. .text:00749460 ; ---------------------------------------------------------------------------
  111. .text:00749460
  112. .text:00749460 loc_749460:                             ; CODE XREF: oCNpc::PutInInv(oCItem *)+105j
  113. .text:00749460                 mov     eax, [edi]
  114. .text:00749462                 push    esi
  115. .text:00749463                 mov     ecx, edi
  116. .text:00749465                 call    dword ptr [eax+74h]
  117. .text:00749468
  118. .text:00749468 loc_749468:                             ; CODE XREF: oCNpc::PutInInv(oCItem *)+EFj
  119. .text:00749468                                         ; oCNpc::PutInInv(oCItem *)+F9j ...
  120. .text:00749468                 mov     ecx, [esi+340h]
  121. .text:0074946E                 test    ecx, ecx
  122. .text:00749470                 jz      short loc_749477
  123. .text:00749472                 call    ?RemoveVobFromWorld@zCVob@@QAEXXZ ; zCVob::RemoveVobFromWorld(void)
  124. .text:00749477
  125. .text:00749477 loc_749477:                             ; CODE XREF: oCNpc::PutInInv(oCItem *)+120j
  126. .text:00749477                 mov     edx, [ebx+668h]
  127. .text:0074947D                 lea     ecx, [ebx+668h]
  128. .text:00749483                 push    esi
  129. .text:00749484                 call    dword ptr [edx+44h]
  130. .text:00749487                 mov     ecx, [esi+4]
  131. .text:0074948A                 dec     ecx
  132. .text:0074948B                 mov     edi, eax
  133. .text:0074948D                 mov     eax, ecx
  134. .text:0074948F                 test    eax, eax
  135. .text:00749491                 mov     [esi+4], ecx
  136. .text:00749494                 jg      short loc_74949F
  137. .text:00749496                 mov     eax, [esi]
  138. .text:00749498                 push    1
  139. .text:0074949A                 mov     ecx, esi
  140. .text:0074949C                 call    dword ptr [eax+0Ch]
  141. .text:0074949F
  142. .text:0074949F loc_74949F:                             ; CODE XREF: oCNpc::PutInInv(oCItem *)+144j
  143. .text:0074949F                 mov     ecx, [esp+2Ch+var_C]
  144. .text:007494A3                 mov     eax, edi
  145. .text:007494A5                 pop     edi
  146. .text:007494A6                 pop     esi
  147. .text:007494A7                 pop     ebx
  148. .text:007494A8                 mov     large fs:0, ecx
  149. .text:007494AF                 add     esp, 20h
  150. .text:007494B2                 retn    4
  151. .text:007494B2 ?PutInInv@oCNpc@@QAEPAVoCItem@@PAV2@@Z endp
  152. .text:007494B2
  153. .text:007494B2 ; ---------------------------------------------------------------------------

Вот листинг из ИДЫ


Ранг: 994.1 (! ! !)
Статус: Участник

Создано: 17 ноября 2014 17:57 · Поправил: reversecode New!
Цитата · Личное сообщение · #18

вы неправильно ее похучили
как я и говорил this в ecx
.text:00749370 mov ebx, ecx

Добавлено спустя -52 минут
https://exelab.ru/f/index.php?action=vthread&forum=5&topic=22328


Статус: Пришелец

Создано: 17 ноября 2014 18:17 New!
Цитата #19

Saturas пишет:
Чет не совсем понимаю, что есть ebp_old, и если вы пишите что вставки идут лесом, тогда как быть с этим кодом, или я что то не так понял?

ebp_old это значение регистра EBP до выполения команды mov ebp, esp, его запихивает в стек первая команда - push ebp.

Си достаточно низкоуровневый язык, чтобы не использовать __asm вообще. Максимум - оптимизация (кодирование с использованием FPU, SIMD) и ядро ОС/драйвера (низкоуровневые архитектурно специфические команды ассемблера).

Поскольку this лежит в ecx (о чем сразу было понятно). Вам нужно понять все поля структуры/класса oCNpc.

Код будет выглядить как-то так (судя по листингу, файл который вы ковыряете с PDB, т.е. отладочной информацией, из нее можно выдернуть описание класса) - читайте ниже:
Code:
  1. struct oCNpc {
  2.    class oCItem *__thiscall PutInInv();
  3. private:
  4.    int param1;
  5.    int param2;
  6. ...
  7.    oCItem *item1;
  8.    oCItem *item2;
  9. };
  10. class oCItem * oCNpc::PutInInv(class oCItem *item) {
  11.     oCNpc* npc = this; // будет передан в ecx
  12.     oCItem* item = (oCItem*)item;
  13. }

И никакого ассемблера!

P.S. Когда я занимался GameCheating'ом мне приходилось восстанавливать целые классы до состояния, когда они компилировались в исходный код с точностью до каждого байта. Было весело, но работу так и не закончил Это был 64битный ассемблер и HexRays 64 тогда еще не было.

Добавлено:
Берете заголовочный отсюда:
https://code.google.com/p/g2ext/source/browse/trunk/api/g2/ocnpc.h?r=21

И реализовываете методы класса заглушки, которые ничего не делают. Тот метод который перехватываете реализовываете (его может и не быть в силу того, что игра ушла вперед относительно исходных кодов). В таком случае перехватываемый метод получит аргументы правильно и правильно сможет обращаться к членам класса.

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 20:32 New!
Цитата · Личное сообщение · #20

Заголовочники оттуда и есть все, и все уже исправленые/дополненые, ибо там 80% бреда.


Статус: Пришелец

Создано: 17 ноября 2014 20:49 New!
Цитата #21

Тогда в чем проблема? Компилятор сам способен получить нужные аргументы функции)

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 21:00 New!
Цитата · Личное сообщение · #22

Аргументы - да, но вот когда нужно заменить функцию в памяти, и если от thiscall то все плохо, для этого и нужно ловить арги, вот.


Ранг: 994.1 (! ! !)
Статус: Участник

Создано: 17 ноября 2014 21:30 New!
Цитата · Личное сообщение · #23

какие арги? зачем ловить? в какой памяти?
у вас обычная this функция в text сегменте, которая явно в dll/exe


Статус: Пришелец

Создано: 17 ноября 2014 21:43 New!
Цитата #24

Saturas
Запилите в тред ваши хуки (перехват функции как реализован?) и мы поможем вам найти ошибку.

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 22:06 New!
Цитата · Личное сообщение · #25

Хуки сейчас нагло украдены у каких то поляков в виде dllки, и сейчас юзаю ее.

{ Атач доступен только для участников форума } - InjectMage.dll


Ранг: 994.1 (! ! !)
Статус: Участник

Создано: 17 ноября 2014 22:10 New!
Цитата · Личное сообщение · #26

а сами то что сделали?
кстати сколько занимает тот файл который хучите? проще уже реверсните всю игруху
тем более все структуры же вы знаете
Saturas пишет:
Заголовочники оттуда и есть все, и все уже исправленые/дополненые, ибо там 80% бреда.

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 22:19 New!
Цитата · Личное сообщение · #27

Сам что сделал? допилил до болемение рабочего состояния, и продолжаю допиливать. А реверсить всю игру долго, нудно, и отладочная инфа далеко не вся.


Ранг: 994.1 (! ! !)
Статус: Участник

Создано: 17 ноября 2014 22:20 New!
Цитата · Личное сообщение · #28

Saturas пишет:
допилил до болемение рабочего состояния, и продолжаю допиливать.

вот это вас и просили показать в
int пишет:
Запилите в тред ваши хуки (перехват функции как реализован?) и мы поможем вам найти ошибку.


Добавлено спустя -59 минут
вообщем я так понимаю все работает
значит
/thread

Ранг: 5.4 (гость)
Статус: Участник

Создано: 17 ноября 2014 22:29 New!
Цитата · Личное сообщение · #29

Дак, оно и так уже все решено за исключением мелочей, хоть и не без Вашей помощи.
А по сути, это реинкарнация того пакета G2Ext, ибо то как работал тот пакет - лучше не знать, креши на каждом шагу были, вот и пришлось отказаться от него, и сделать по своему, и что характерно по своему таки вышло лучше.
На последок, хотелось спросить где/что почитать по реверсу в целом?


Статус: Пришелец

Создано: 17 ноября 2014 23:01 New!
Цитата #30

Если из русскоязычных - статьи на этом сайте и на васме.

| Сообщение посчитали полезным: Saturas

. 1 . 2 . >>
 eXeL@B —› Программирование —› Как получить аргумент из функции в памяти

Оригинальный DVD-ROM: eXeL@B DVD !

Вы находитесь на форуме сайта EXELAB.RU
Проект ReactOS