Сейчас на форуме: (+8 невидимых)

 eXeL@B —› Вопросы новичков —› Выполнить копию кода из библиотеки в С++ функции
Посл.ответ Сообщение

Ранг: 2.0 (гость)
Активность: 0.010
Статус: Участник

Создано: 11 ноября 2013 20:37 · Поправил: Kadet89
· Личное сообщение · #1

Имеется dll библиотека, в ней выполняется кусок кода, после чего выполняется прыжок в функцию func1

Code:
  1. 1012313D 8B 07               mov     eax, [edi]
  2. 1012313F 8B 50 2C            mov     edx, [eax+2Ch]
  3. 10123142 6A 00               push    0
  4. 10123144 8D 4D FF            lea     ecx, [ebp+var_1]
  5. 10123147 51                  push    ecx
  6. 10123148 68 C4 26 32 10      push    offset aSurfaceprop ; "$surfaceprop"
  7. 1012314D 8B CF               mov     ecx, edi
  8. 1012314F FF D2               call    edx
  9. 10123151 80 7D FF 00         cmp     [ebp+var_1], 0
  10. 10123155 74 33               jz      short loc_1012318A
  11. 10123157 8B 10               mov     edx, [eax]
  12. 10123159 8B C8               mov     ecx, eax
  13. 1012315B 8B 42 18            mov     eax, [edx+18h]
  14. 1012315E FF D0               call    eax
  15. 10123160 8B 0D B0 70 61 10   mov     ecx, dword_106170B0
  16. 10123166 8B 11               mov     edx, [ecx]
  17. 10123168 89 45 D8            mov     [ebp+var_28], eax
  18.                              jmp func1


В функции я получаю результат выполнения этого кода, и дублирую его для выполнения с другим параметром.
func1:

Code:
  1. __declspec(naked) void __cdecl function() { 
  2.     char *surfaceprop;
  3.     _asm mov surfaceprop, eax;
  4.     printf("pProps surfaceprop %s\n", surfaceprop);
  5.  
  6.     char *basetexture;
  7.     _asm {
  8.         mov     eax, [edi]
  9.         mov     edx, [eax+2Ch]
  10.         push    0
  11.         lea       ecx, [ebp+var_1]
  12.         push    ecx
  13.         push    offset aSurfaceprop ; "$basetexture"
  14.         mov     ecx, edi
  15.         call       edx
  16.         //cmp     [ebp+var_1], 0
  17.         //jz      short loc_1012318A
  18.         mov     edx, [eax]
  19.         mov     ecx, eax
  20.         mov     eax, [edx+18h]
  21.         call       eax
  22.         mov     ecx, dword_106170B0
  23.         mov     edx, [ecx]
  24.         mov     [ebp+var_28], eax
  25.         mov     basetexture, eax;
  26.     }
  27.     printf("pProps basetexture %s\n", basetexture);
  28. }


В этом коде pProps surfaceprop выводится корректно, но дальше выполнить код не получается т.к. не заданы параметры и выводятся ошибки:

error C2094: label "var_28" was undefined
error C2094: label "dword_106170B0" was undefined
error C2094: label "aSurfaceprop" was undefined
error C2094: label "var_1" was undefined

Как задать эти параметры, не представляю, есть ли способ получить их подобно тому, как я получаю указатель на строку, или же надо хукать каждую строку отдельно и вынимать значения?

Согласно данным в IDA, вары имеют следующие значения:
var_28 = dword ptr -28h
var_1 = byte ptr -1

Также имеется исходный код (кусок кода от очень старой версии библиотеки):
Code:
  1. IMaterialVar *pVar;
  2. bool bVarFound;
  3. pVar = pMaterial->FindVar( "$surfaceprop", &bVarFound, false );
  4. if ( bVarFound ) {
  5.     const char *pProps = pVar->GetStringValue();
  6.     pDispTree->SetSurfaceProps( physprop->GetSurfaceIndex( pProps ) );
  7. }


И псевдокод:
Code:
  1. v64 = (*(int (__thiscall **)(int, _DWORD, char *, _DWORD))(*(_DWORD *)v63g + 44))(v63g, "$surfaceprop",&v140, 0); //10123157 mov edx, [eax] ; edx -> v64, after executing this instruction
  2. if ( v140 )
  3. {
  4.     v65 = (*(int (__thiscall **)(int))(*(_DWORD *)v64 + 24))(v64); //10123168 mov [ebp+var_28], eax ; eax -> v65
  5.     v66 = *(_DWORD *)dword_106170B0;
  6.     *(_WORD *)(v54 + 108) = (*(int (__stdcall **)(int))(v66 + 12))(v65);
  7.     *(_WORD *)(v54 + 110) = (*(int (__stdcall **)(int))(v66 + 12))(v65);
  8. }


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




Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 11 ноября 2013 21:03
· Личное сообщение · #2

не не смогли а не захотели, вопрос потому что детский

вас заставили в этом разбиратся? на лицо ксерокопирования без вникания что это и как работает

var_1 это ваша bVarFound
aSurfaceprop это строка, ее задавать надо

var_28 это ваша basetexture
зачем ее по два раза?

dword_106170B0 это вообще статик через ds к сегменту



Ранг: 2.0 (гость)
Активность: 0.010
Статус: Участник

Создано: 11 ноября 2013 23:05 · Поправил: Kadet89
· Личное сообщение · #3

Вопрос не детский, просто не все хорошо шарят в ассемблере. Что код на с++ делает - я знаю,и знаю что эти вары означают . Вопрос был в другом - как передать их значения в ассемблерную вставку?. Уверен, дело не хитрое, но с таким не приходилось еще сталкиваться. Насчет последней строки с вар28, соглашусь, она лишняя.



Ранг: 53.9 (постоянный), 33thx
Активность: 0.050
Статус: Участник

Создано: 11 ноября 2013 23:12 · Поправил: deniskore
· Личное сообщение · #4

Kadet89 пишет:
Вопрос был в другом - как передать их значения в ассемблерную вставку?

Если вы разбираетесь в с++, то сделайте приведение согласно вашему прототипу, можно узнать чит пишите для игры?




Ранг: 72.3 (постоянный), 133thx
Активность: 0.380
Статус: Участник

Создано: 12 ноября 2013 13:24 · Поправил: Модератор
· Личное сообщение · #5

> дублирую его для выполнения с другим параметром.

Зачем, если он уже есть в памяти ?

Бинарный код тупо копипастой не копируется. Есть переменные, фиксапы, относительные смещения етц.



Ранг: 2.0 (гость)
Активность: 0.010
Статус: Участник

Создано: 12 ноября 2013 19:26 · Поправил: Kadet89
· Личное сообщение · #6

deniskore, нет, это серверный плагин для сорса. Код определяет название текстуры дисплейсмента.
"Приведение по прототипу" пробовал делать, но сервак падает. Не знаю, быть может я ошибся где... сложно сказать.

Как я понимаю
Code:
  1. 1012313F 8B 50 2C            mov     edx, [eax+2Ch]

- в edx указатель на функцию FindVar(...)
Прототип функции:
typedef IMaterialVar *(*FindVar)(char*, bool*, bool);
Но судя по псевдокоду, возможно, он некорректен.

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




Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 12 ноября 2013 19:37 · Поправил: reversecode
· Личное сообщение · #7

конечно некорректный, вы обьявили простую функцию, а нужно функцию указатель на класс
потому что в mov ecx, edi
указатель на this
без него конечно будет валится все

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

Ранг: 2.0 (гость)
Активность: 0.010
Статус: Участник

Создано: 15 ноября 2013 22:20 · Поправил: Kadet89
· Личное сообщение · #8

Переместил джамп на строчку 10123151
Получаю указатель на класс и на метод:
IMaterial *c;
FindVar f;
_asm mov c, edi; //ecx
_asm mov f, edx;
Меняю прототип функции на
typedef IMaterialVar *(IMaterial::*FindVar)(char*, bool*, bool);

IMaterialVar *pVar;
bool bVarFound;
pVar = (c->*f)("$basetexture", &bVarFound, false);
printf("surfaceprop %s\n", pVar->GetStringValue());

и... не работает.

Неправильный прототип или указатель на функцию?
Класс IMaterial у меня отсутствует, т.ч. пришлось обойтись просто строчкой:

class IMaterial;

Но, как я понимаю, это не должно влиять на результат?




Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 15 ноября 2013 22:37
· Личное сообщение · #9

работать не будет
потому что метод имеет смещение +2С
mov edx, [eax+2Ch]

а вы вызываете +0
т.е. вы вообще другой метод по указателю вызываете

хоть бы в вижуал студии смотрели какой она код скомпилировала
что +2С там отсутсвует



Ранг: 6.0 (гость), 2thx
Активность: 0.010
Статус: Участник

Создано: 15 ноября 2013 22:45
· Личное сообщение · #10

Можно просто заюзать __fastcall, передавая через первый аргумент ECX, второй аргумент передающий EDX забить нулём, а остальное уже в стек будет уложено



Ранг: 2.0 (гость)
Активность: 0.010
Статус: Участник

Создано: 15 ноября 2013 23:04 · Поправил: Kadet89
· Личное сообщение · #11

Ок, попробую... хотя о таком способе еще не слышал.

reversecode, [eax+2Ch] заносится в edx, а потом я его забираю из edx... или я ошибаюсь ? прыжок ведь в свою функцию я делаю после этой строки. Я прибавил 2С, не помогло.

В моем варианте, если задать FindVar как указатель, начинают вылезать ошибки:
error C2027: использование неопределенного типа "IMaterial"
Использование указателя на тип неполного класса не допускается.
Значит ли это, что не имея класса IMaterial, я так вызвать функцию не смогу?

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



Ранг: 6.0 (гость), 2thx
Активность: 0.010
Статус: Участник

Создано: 15 ноября 2013 23:34
· Личное сообщение · #12

В _fastcall первый аргумент кладётся в ECX, второй в EDX, остальные в стек. Следовательно вам надо перехватить указатель на класс и засунуть его в первый аргумент(т.к. он передаётся в ECX), второй аргумент не используется, в нём можно передавать что угодно(напр. 0), остальные аргументы как и в классе. Например:
Code:
  1. int __fastcall hooked_method(...);
  2. ...
  3. hooked_method(this/*указатель на экземпляр класса*/, 0/*заглушка*/, "$basetexture", &bVarFound, false);

как-то так, детали уточняйте через отладчик.




Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 15 ноября 2013 23:36 · Поправил: reversecode
· Личное сообщение · #13

у вас FindVar нет
это вирутальный метод со смещением +2С
значит нужно обьявлять фейковый класс, и набивать его вирутальными методотами что бы FindVar был метод со смещением +2С
тогда просто кастите ваш edx к классу и вызываете метод FindVar

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

с fastcall запутаетесь еще больще



Ранг: 2.0 (гость)
Активность: 0.010
Статус: Участник

Создано: 16 ноября 2013 12:15 · Поправил: Kadet89
· Личное сообщение · #14

Не думал что всё так плохо... попроще вариантов точно нет?
JKornev, Увы, компилятор ругается на ваш вариант

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




Ранг: 1053.6 (!!!!), 1078thx
Активность: 1.060.81
Статус: Участник

Создано: 16 ноября 2013 14:02
· Личное сообщение · #15

теперь когда работает можете упрощать до любого из двух вариантов
или с fastcall
или с кастом указателя на функцию в +2С


 eXeL@B —› Вопросы новичков —› Выполнить копию кода из библиотеки в С++ функции
:: Ваш ответ
Жирный  Курсив  Подчеркнутый  Перечеркнутый  {mpf5}  Код  Вставить ссылку 
:s1: :s2: :s3: :s4: :s5: :s6: :s7: :s8: :s9: :s10: :s11: :s12: :s13: :s14: :s15: :s16:


Максимальный размер аттача: 500KB.
Ваш логин: german1505 » Выход » ЛС
   Для печати Для печати