Вопрос Script Functions

Начинающий
Статус
Оффлайн
Регистрация
16 Авг 2022
Сообщения
36
Реакции[?]
4
Поинты[?]
4K
Hi, Is there any tutorial related to how we can find and call script functions?
Пожалуйста, авторизуйтесь для просмотра ссылки.
For example I want to find "IsInRangeOfFountain". I searched for "IsInRangeOfFountain" in IDA. I found a bunch of things but I can't reach to the function.

I would be grateful if anyone could help me.
 
Участник
Статус
Оффлайн
Регистрация
23 Май 2019
Сообщения
779
Реакции[?]
331
Поинты[?]
63K
1679849412999.png
Пожалуйста, авторизуйтесь для просмотра ссылки.
1679849391582.png
Пожалуйста, авторизуйтесь для просмотра ссылки.
1679849466467.png



Код:
function IsInRangeOfFountain(e_idx) //pseudo code
{
    ent = GetEntity(e_idx)
    ent_team = ent?.IsNpc()?.GetTeamNum()
    ent_pos = ent?.IsNpc()?.GetPos()
    fountain = GetEntity(Gamerules.TeamFountains[ent_team])
    return fountain?.GetPos().distance(ent_pos) <= 1250.0
}
 
Последнее редактирование:
Ревёрсер среднего звена
Пользователь
Статус
Оффлайн
Регистрация
24 Ноя 2022
Сообщения
303
Реакции[?]
108
Поинты[?]
57K
There are also huge functions with array-like arrangements of RegisterJSMethod calls
xrefs of most JS functions lead to a lea rcx instruction
This is the "array":
Screenshot_585.png
Function pointers are above xrefs
Best reversed in IDA
Screenshot_587.png
And then the distance checking logic goes as Liberalist explained
Screenshot_586.png
 
Начинающий
Статус
Оффлайн
Регистрация
16 Авг 2022
Сообщения
36
Реакции[?]
4
Поинты[?]
4K
thanks. I find out that there is a dylib file.
from what you said I also found the actual function and how it works:

C++:
__int64 __fastcall C_DOTA_BaseNPC::IsInRangeOfFountain(C_DOTA_BaseNPC *this)
{
  return C_DOTAGamerules::IsInRangeOfFountain((C_DOTAGamerules *)g_pGameRules, this);
}
sig if anybody needs it: "48 8B D1 48 8B 0D ? ? ? ? E9 ? ? ? ? CC 32 C0"

It's outdated a bit, but still helpful

C++:
bool __fastcall C_DOTAGamerules::IsInRangeOfFountain(C_DOTAGamerules *this, C_DOTA_BaseNPC *a2)
{
  unsigned __int64v2; // rbx
  const __m128i *AbsOrigin; // r14
  unsigned int v5; // eax
  __int64v6; // rcx
  __int64v7; // rsi
  C_BaseEntity **v8; // rdx
  C_BaseEntity *v9; // rdi
  __m128iv10; // xmm0
  floatv11; // xmm1_4

  v2 = *((unsigned __int8 *)a2 + 667);
  AbsOrigin = (const __m128i *)C_BaseEntity::GetAbsOrigin(a2);
  if ( v2 > 0xD )
    return 0;
  v5 = *((_DWORD *)this + v2 + 359);
  if ( v5 > 0xFFFFFFFD )
    return 0;
  v6 = *(_QWORD *)(CEntityHandle::gm_pEntityList + 8LL * ((v5 >> 9) & 0x3F) + 8);
  if ( !v6 )
    return 0;
  v7 = 120LL * (v5 & 0x1FF);
  v8 = (C_BaseEntity **)(v7 + v6);
  if ( !(v7 + v6) )
    return 0;
  if ( *(_DWORD *)(v6 + v7 + 16) != v5 )
    return 0;
  v9 = *v8;
  if ( !*v8 )
    return 0;
  if ( !*((_BYTE *)v9 + 1044) )
    return 0;
  v10 = (__m128i)_mm_sub_ps(
                   (__m128)_mm_loadl_epi64(AbsOrigin),
                   (__m128)_mm_loadl_epi64((const __m128i *)C_BaseEntity::GetAbsOrigin(v9)));
  v11 = *(float *)_mm_shuffle_epi32(v10, 1).i32;
  return fsqrt((float)(v11 * v11) + (float)(*(float *)v10.i32 * *(float *)v10.i32)) < 1150.0;
}
 
Последнее редактирование:
Ревёрсер среднего звена
Пользователь
Статус
Оффлайн
Регистрация
24 Ноя 2022
Сообщения
303
Реакции[?]
108
Поинты[?]
57K
thanks. I find out that there is a dylib file.
from what you said I also found the actual function and how it works:

C++:
__int64 __fastcall C_DOTA_BaseNPC::IsInRangeOfFountain(C_DOTA_BaseNPC *this)
{
  return C_DOTAGamerules::IsInRangeOfFountain((C_DOTAGamerules *)g_pGameRules, this);
}
It's outdated a bit, but still helpful


C++:
bool __fastcall C_DOTAGamerules::IsInRangeOfFountain(C_DOTAGamerules *this, C_DOTA_BaseNPC *a2)
{
  unsigned __int64v2; // rbx
  const __m128i *AbsOrigin; // r14
  unsigned int v5; // eax
  __int64v6; // rcx
  __int64v7; // rsi
  C_BaseEntity **v8; // rdx
  C_BaseEntity *v9; // rdi
  __m128iv10; // xmm0
  floatv11; // xmm1_4

  v2 = *((unsigned __int8 *)a2 + 667);
  AbsOrigin = (const __m128i *)C_BaseEntity::GetAbsOrigin(a2);
  if ( v2 > 0xD )
    return 0;
  v5 = *((_DWORD *)this + v2 + 359);
  if ( v5 > 0xFFFFFFFD )
    return 0;
  v6 = *(_QWORD *)(CEntityHandle::gm_pEntityList + 8LL * ((v5 >> 9) & 0x3F) + 8);
  if ( !v6 )
    return 0;
  v7 = 120LL * (v5 & 0x1FF);
  v8 = (C_BaseEntity **)(v7 + v6);
  if ( !(v7 + v6) )
    return 0;
  if ( *(_DWORD *)(v6 + v7 + 16) != v5 )
    return 0;
  v9 = *v8;
  if ( !*v8 )
    return 0;
  if ( !*((_BYTE *)v9 + 1044) )
    return 0;
  v10 = (__m128i)_mm_sub_ps(
                   (__m128)_mm_loadl_epi64(AbsOrigin),
                   (__m128)_mm_loadl_epi64((const __m128i *)C_BaseEntity::GetAbsOrigin(v9)));
  v11 = *(float *)_mm_shuffle_epi32(v10, 1).i32;
  return fsqrt((float)(v11 * v11) + (float)(*(float *)v10.i32 * *(float *)v10.i32)) < 1150.0;
}
Good thing such functions don't change a lot
They can also call virtual functions sometimes, like GetEffectiveCastRange for C_DOTA_BaseAbility, and that's even better because you don't need to reverse the actual function to save time on sigscanning
 
Сверху Снизу