Gn3po4g / OrbWalker

A script for League of Legends.
MIT License
86 stars 16 forks source link

Questions about the operation of this internal mechanism. #15

Closed vacnex closed 10 months ago

vacnex commented 1 year ago

Hello, I have a question. As far as I know, internal cheats usually require injection, but your project only requires placing the dll file in the same folder as the game. What are the advantages and disadvantages of this method compared to injection?

Gn3po4g commented 1 year ago

League will load HID.DLL itself but it locate at system directory, so if you put a hid.dll in league.exe's root directory, league will load the dll you put instead of the one at system directory. I think it will not be detected by league.

vacnex commented 1 year ago

Hmm... I'm new to C++ and I have some noob questions to ask.

  1. How can you determine which DLL League of Legends will load?
  2. I have consulted information on unknowncheats, is it true that directly calling the IssueOrder function of League of Legends can be detected?
  3. Is it safe to use sendinput?
  4. I read some of your answers on GUI, you think it is easy to detect, can you explain your reasoning? Because I plan to use ImGui-DirectX-11-Kiero-Hook to add imgui.
  5. I am only familiar with making external cheats with typescript, and I have also learned basic C++, so are you writing a static library? How can you determine which function corresponds to the int main() function in C++?
  6. I read your code and saw that you wrote something like replacing the present function of d3d11 with the hkpresent function, so what happens to the old code of the present function, does it disappear or something else?
  7. I understand that C++ stores strings like this char str[] = "somestring", and I see that you use the string() function and it throws an error when Visual Studio is in debug mode and doesn't have an error when switched to release mode, can you explain this issue to me? Thank you, it's the most understandable C++ project I've ever seen. For LView, I only understand a very small part and almost cannot write it myself.
Gn3po4g commented 1 year ago
  1. You can use some software like reclass
  2. Calling old IssueOrder will be detected. And its function is order you to attack or move. but the issueorder in code is going to click at somewhere or an object like mouse_event.
  3. I guess yes because when you click your mouse or keyboard system will call it.
  4. GUI will not be detected, I mean when a lot of people use same code, it will call game to detect it.
  5. It is an dynamic library so its postfix is .dll, and dll has its own "main" function called DllMain. You can learn it from Microsoft
  6. You can see that the hkpresent call original present function at last line. So it just add some code to original present function before every calling.
  7. Most of time string() will not throw an error. It gets an error just like char str[] = "somestring" gets an error. And if you use char str[] = "somestring", the type of str is const char, but libmem needs char, so i use string().data() to get char* type.
vacnex commented 1 year ago

hmm im still confuse when you said

issueorder in code is going to click at somewhere or an object like mouse_event

But when I looked at your code, I saw that you created a type similar to an interface like this fnIssueOrder = int(__fastcall*)(uintptr_t, int, int, int, int, int, int);

I understand that you declared the parameters according to the structure of IssueOrder in League. And then you called IssueOrder with pos.x and pos.y parameters as the position of the enemy void Attack(Object const* obj) { const auto pos = Renderer::WorldToScreen(obj->position()); Functions::IssueOrder(hud_input, 0, 0, 1, pos.x, pos.y, 0); } And I only understand that the 5th and 6th parameters are the x,y coordinates of the enemy, while I don't know the other parameters.

So does that mean you are using League's IssueOrder to perform the attack? Please correct me if I'm wrong.

Gn3po4g commented 1 year ago

Other parameter is attack_move attack_command and state(press | release)

You know Shift+RightClick is attack_move command right? and A+LeftClick also is. That's what those parameters are for. And we just need attack so other parameters are useless.

vacnex commented 1 year ago

So does it mean that if we pass those 2 parameters to IssueOrder, League will understand that we are using it to attack Champ and detect that we are using their function. And if we don't need to pass those 2 parameters, IssueOrder simply performs a click at the specified location (in this case, the enemy's position), and League will not see this as a "threat" so it will not detect it, right?

Gn3po4g commented 1 year ago

This has nothing to do with the passing of parameters, the parameters only change click mode This function will not be detected. Only the previous IssueOrder, which is a different function with 5 parameters, will be detected.

LeonardoFBR commented 1 year ago

Sorry for the question, but have you figured out how to cast skills from a function?

vacnex commented 1 year ago

hmm if I have offset then can i skip scan sig ? like this

tuple<uintptr_t *, string, uintptr_t, intptr_t> sig_to_scan[] = {
    {&offsets.oGameTime, "F3 0F 5C 35 ? ? ? ? 0F 28 F8", 4, 0x51b8c10},
}

then

void Scan()
{
    for (auto& [what, pattern, addition, offset] : sig_to_scan)
    {
        if (offset != NULL)
        {
            *what = offset;
            continue;
        }

        uintptr_t address = FindAddress(pattern);
        while (address == LM_ADDRESS_BAD)
        {

            this_thread::sleep_for(100ms);
            address = FindAddress(pattern);
        }
        *what = std::to_string(address + addition + 4 + *(int32_t*)(address + addition)); // Chuyển đổi giá trị thành chuỗi string
    }
}

i had tried but game frozen, maybe i dont understand the pointer work and wrong assign to *what

Gn3po4g commented 1 year ago

Of course yes

Gn3po4g commented 1 year ago

maybe you can use latest version, i update sigs

vacnex commented 1 year ago

maybe you can use latest version, i update sigs

I had updated the sig from your repo, but when i change my code to add check offset like above, the offset which i get from UC forum is lastest patch The game freeze immediately when in game. can you try it?

Gn3po4g commented 1 year ago

Did you forget to add the base address? You can get it from GetModuleHande(nullptr) in and convert it to uintptr_t or some other type.

vacnex commented 1 year ago

Did you forget to add the base address? You can get it from GetModuleHande(nullptr) in and convert it to uintptr_t or some other type.

oops forgot look FindAddress function I did it many thanks

by the way i'm trying to read the player's name and the champion's name for player's name, this code can print the name even though it can't print unicode characters but that's ok for me

string Entity::Name() {
    return (*(string*)((uintptr_t)this + 0x60)).c_str();
}

but when use with championname offset 0x38A0

string Entity::Name() {
    return (*(string*)((uintptr_t)this + 0x38A0  )).c_str();
}

this make game crash already when in game. I have seen through LolString class but really I don't know how to use this class to get the name string

class LolString
{
    char content[0x10]; // 0x0
    int len = 0; // 0x10
    int max = 0; // 0x14

public:

    operator const char* (void)
    {
        return c_str();
    }
    operator std::string(void)
    {
        return std::string(c_str());
    }

    std::string str()
    {
        return std::string(c_str());
    }

private:
    char* c_str(void)
    {
        if (uintptr_t(this) <= 0x1000)
            return (char*)"";

        return max >= 0x10
            ? *reinterpret_cast<char**>(content)
            : content;
    }
};
1nteg3r commented 1 year ago

Did you forget to add the base address? You can get it from GetModuleHande(nullptr) in and convert it to uintptr_t or some other type.

oops forgot look FindAddress function I did it many thanks

by the way i'm trying to read the player's name and the champion's name for player's name, this code can print the name even though it can't print unicode characters but that's ok for me

string Entity::Name() {
    return (*(string*)((uintptr_t)this + 0x60)).c_str();
}

but when use with championname offset 0x38A0

string Entity::Name() {
    return (*(string*)((uintptr_t)this + 0x38A0  )).c_str();
}

this make game crash already when in game. I have seen through LolString class but really I don't know how to use this class to get the name string

class LolString
{
  char content[0x10]; // 0x0
  int len = 0; // 0x10
  int max = 0; // 0x14

public:

  operator const char* (void)
  {
      return c_str();
  }
  operator std::string(void)
  {
      return std::string(c_str());
  }

  std::string str()
  {
      return std::string(c_str());
  }

private:
  char* c_str(void)
  {
      if (uintptr_t(this) <= 0x1000)
          return (char*)"";

      return max >= 0x10
          ? *reinterpret_cast<char**>(content)
          : content;
  }
};

champion name is at 0x38D0, no?

vacnex commented 1 year ago

champion name is at 0x38D0, no?

Oops let me try again thank you

1nteg3r commented 1 year ago

how would I implement a getping function in the orbwalker?

vacnex commented 1 year ago

I think you should add imgui into it then use imgui slider bar as ping adjustment

1nteg3r commented 1 year ago

i already added imgui, if u wanna collab pass me ur discord, also improved the move function, it doesnt stutter at all now, no longer using windows mouse events void Move() { POINT cursor; if (GetCursorPos(&cursor)) { Functions::IssueOrder(hud_input, 0, 0, 1, cursor.x, cursor.y, 0); Functions::IssueOrder(hud_input, 1, 0, 1, cursor.x, cursor.y, 0); } }

vacnex commented 1 year ago

Hey guys i got a super super weird this is my source code dllmain image LeagueWind::Init image Hook::init image memory.cpp

#include "pch.h"
Offsets offsets;
namespace memory
{
    tuple<uintptr_t*, string, uintptr_t, uintptr_t> sig_to_scan[] = {
        {&offsets.oGameTime, "F3 0F 5C 35 ? ? ? ? 0F 28 F8", 4, 0x51b8c10},
        {&offsets.oLocalPlayer, "48 8B 05 ? ? ? ? 4C 8B D2 4C 8B C1", 3, 0x51c6980},
        {&offsets.oViewProjMatrices, "48 8D 0D ? ? ? ? 0F 10 00", 3, NULL},          // ok
        {&offsets.oHeroList, "48 8B 05 ? ? ? ? 4C 8B 78 08", 3, 0x210def0},               // ok
        {&offsets.oTurretList, "48 8B 1D ? ? ? ? 48 8B 5B 28 48 85 DB", 3, 0x51b4d40},    // ok
        //{ &offsets.oInhibitorList, "A1 ? ? ? ? 53 55 56 8B 70 04 8B 40 08", true },
        {&offsets.oMinionList, "48 8B 0D ? ? ? ? E8 ? ? ? ? EB 07", 3, 0x3968770}, // ok
        {&offsets.oChatClient, "41 FF D1 48 8B 0D ? ? ? ?", 6, 0x51c6b68},
        {&offsets.oHudInstance, "48 8B 0D ? ? ? ? 8B 57 10", 3, 0x210ddd8}, // ok

        {&offsets.oPrintChat, "E8 ? ? ? ? 4C 8B C3 B2 01", 1, 0x813FC0},
        {&offsets.oIssueOrder, "45 33 C0 E8 ? ? ? ? 48 83 C4 48", 4, 0x86a150},        // ok
        {&offsets.oAttackDelay, "E8 ? ? ? ? 33 C0 F3 0F 11 83 ? ? ? ?", 1, 0x3885a0},  // ok
        {&offsets.oAttackCastDelay, "89 83 ? ? ? ? E8 ? ? ? ? 48 8B CE", 7, 0x3884a0}, // ok
        {&offsets.oIsAlive, "48 8B D8 E8 ? ? ? ? 84 C0 74 35", 4, 0x229500},           // ok
        {&offsets.oBonusRadius, "E8 ? ? ? ? 0F 28 F8 48 8B D3 48 8B CE", 1, 0x1e5120},  // ok
    };

    lm_module_t GameModule{};

  uintptr_t FindAddress(string &pattern)
  {
    lm_page_t page{};
    page.end = GameModule.base;
    while (page.end < GameModule.end && LM_GetPage(page.end, &page))
    {
      if (page.prot & LM_PROT_R)
      {
        const auto scan_size = page.size - ranges::distance(pattern | views::split(' '));
        if (const auto address = LM_SigScan(pattern.data(), page.base, scan_size);
            address != LM_ADDRESS_BAD)
        {
          return address;
        }
      }
    }
    return LM_ADDRESS_BAD;
  }

  void it()
  {
    LM_FindModule(string("League of Legends.exe").data(), &GameModule);
    Scan();
  }

  void Scan()
  {
      for (auto& [what, pattern, addition, offset] : sig_to_scan) {
          if (offset != NULL)
          {
              *what = GameModule.base + offset;
          }
          uintptr_t address = FindAddress(pattern);
          while (address == LM_ADDRESS_BAD) {
              this_thread::sleep_for(100ms);
              address = FindAddress(pattern);
          }
          *what = address + addition + 4 + *(int32_t*)(address + addition);
      }
  }

}

The probblem is my imGui only show gui when have memory::it(); when i remove it look like

bool LeagueWind::Hooks::Init() {
    Log::LogToFile(string("Init Memory, Functions"));
    while (kiero::init(kiero::RenderType::D3D11) != kiero::Status::Success ||
    kiero::bind(8, (void**)&oPresent, (void*)LeagueWind::Hooks::Present) != kiero::Status::UnknownError);
    return true;
}

imgui disapear WTF??, but my log still write normaly this is my hook present

#include "pch.h"
#include "LeagueWind.h"

HRESULT PRESENT_CALL LeagueWind::Hooks::Present(IDXGISwapChain* thisptr, UINT SyncInterval, UINT Flags)
{
    //Log::LogToFile(string("Hook Present"));
    if (!Data::InitImGui)
    {
        Log::LogToFile(string("InitImGui"));

        Data::pSwapChain = thisptr;
        if (SUCCEEDED(Data::pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&Data::pDxDevice11)))
        {
            Data::pDxDevice11->GetImmediateContext(&Data::pContext);
            DXGI_SWAP_CHAIN_DESC sd;
            Data::pSwapChain->GetDesc(&sd);
            Data::hWindow = sd.OutputWindow;
            ID3D11Texture2D* pBackBuffer;
            Data::pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
            Data::pDxDevice11->CreateRenderTargetView(pBackBuffer, NULL, &Data::pMainRenderTargetView);
            pBackBuffer->Release();

            Data::oWndProc = (WNDPROC)SetWindowLongPtr(Data::hWindow, GWLP_WNDPROC, (LONG_PTR)WndProc);

            ImGui::CreateContext();
            ImGuiIO& io = ImGui::GetIO();
            ImGui::StyleColorsDark();
            io.ConfigFlags = ImGuiConfigFlags_NoMouseCursorChange;
            ImGui_ImplWin32_Init(Data::hWindow);
            ImGui_ImplDX11_Init(Data::pDxDevice11, Data::pContext);
            Data::InitImGui = true;

        }
    }

    if (!Data::InitImGui) return oPresent(thisptr, SyncInterval, Flags);

    ImGui_ImplDX11_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();

    ImGui::ShowDemoWindow();

    ImGui::EndFrame();
    ImGui::Render();

    Data::pContext->OMSetRenderTargets(1, &Data::pMainRenderTargetView, NULL);
    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
    return oPresent(thisptr, SyncInterval, Flags);

}

with memory::it(); then imgui show normaly, i dont know what happened :|

1nteg3r commented 1 year ago
class LolString
{
  char content[0x10]; // 0x0
  int len = 0; // 0x10
  int max = 0; // 0x14

public:

  operator const char* (void)
  {
      return c_str();
  }
  operator std::string(void)
  {
      return std::string(c_str());
  }

  std::string str()
  {
      return std::string(c_str());
  }

private:
  char* c_str(void)
  {
      if (uintptr_t(this) <= 0x1000)
          return (char*)"";

      return max >= 0x10
          ? *reinterpret_cast<char**>(content)
          : content;
  }
};

-Use std::size_t instead of int for the len and max member variables. std::size_t is the recommended type for representing sizes and counts of objects in memory.

-Add a constructor to initialize the content, len, and max member variables. This will ensure that the object is always in a valid state when it is created.

-Add a destructor to deallocate any memory that was allocated by the object. This will prevent memory leaks.

-Use const qualifiers for member functions that do not modify the object, such as the c_str and str functions.

-Use nullptr instead of 0 or (char*)"" to represent a null pointer.

-Consider using std::string or another standard library container instead of manually managing memory with raw pointers and arrays.

heres my code

class LolString
{
    std::string content;

public:
    LolString() : content() {}

    operator const char* () const
    {
        return c_str();
    }

    operator std::string() const
    {
        return content;
    }

    std::string str() const
    {
        return content;
    }

private:
    const char* c_str() const
    {
        return content.c_str();
    }
};
vacnex commented 1 year ago

if u wanna collab pass me ur discord

VAC#0183 my discord, just wanna ask you some noob question XD

Gn3po4g commented 1 year ago

Hey guys i got a super super weird this is my source code dllmain image LeagueWind::Init image Hook::init image memory.cpp

#include "pch.h"
Offsets offsets;
namespace memory
{
    tuple<uintptr_t*, string, uintptr_t, uintptr_t> sig_to_scan[] = {
        {&offsets.oGameTime, "F3 0F 5C 35 ? ? ? ? 0F 28 F8", 4, 0x51b8c10},
        {&offsets.oLocalPlayer, "48 8B 05 ? ? ? ? 4C 8B D2 4C 8B C1", 3, 0x51c6980},
        {&offsets.oViewProjMatrices, "48 8D 0D ? ? ? ? 0F 10 00", 3, NULL},          // ok
        {&offsets.oHeroList, "48 8B 05 ? ? ? ? 4C 8B 78 08", 3, 0x210def0},               // ok
        {&offsets.oTurretList, "48 8B 1D ? ? ? ? 48 8B 5B 28 48 85 DB", 3, 0x51b4d40},    // ok
        //{ &offsets.oInhibitorList, "A1 ? ? ? ? 53 55 56 8B 70 04 8B 40 08", true },
        {&offsets.oMinionList, "48 8B 0D ? ? ? ? E8 ? ? ? ? EB 07", 3, 0x3968770}, // ok
        {&offsets.oChatClient, "41 FF D1 48 8B 0D ? ? ? ?", 6, 0x51c6b68},
        {&offsets.oHudInstance, "48 8B 0D ? ? ? ? 8B 57 10", 3, 0x210ddd8}, // ok

        {&offsets.oPrintChat, "E8 ? ? ? ? 4C 8B C3 B2 01", 1, 0x813FC0},
        {&offsets.oIssueOrder, "45 33 C0 E8 ? ? ? ? 48 83 C4 48", 4, 0x86a150},        // ok
        {&offsets.oAttackDelay, "E8 ? ? ? ? 33 C0 F3 0F 11 83 ? ? ? ?", 1, 0x3885a0},  // ok
        {&offsets.oAttackCastDelay, "89 83 ? ? ? ? E8 ? ? ? ? 48 8B CE", 7, 0x3884a0}, // ok
        {&offsets.oIsAlive, "48 8B D8 E8 ? ? ? ? 84 C0 74 35", 4, 0x229500},           // ok
        {&offsets.oBonusRadius, "E8 ? ? ? ? 0F 28 F8 48 8B D3 48 8B CE", 1, 0x1e5120},  // ok
    };

    lm_module_t GameModule{};

  uintptr_t FindAddress(string &pattern)
  {
    lm_page_t page{};
    page.end = GameModule.base;
    while (page.end < GameModule.end && LM_GetPage(page.end, &page))
    {
      if (page.prot & LM_PROT_R)
      {
        const auto scan_size = page.size - ranges::distance(pattern | views::split(' '));
        if (const auto address = LM_SigScan(pattern.data(), page.base, scan_size);
            address != LM_ADDRESS_BAD)
        {
          return address;
        }
      }
    }
    return LM_ADDRESS_BAD;
  }

  void it()
  {
    LM_FindModule(string("League of Legends.exe").data(), &GameModule);
    Scan();
  }

  void Scan()
  {
      for (auto& [what, pattern, addition, offset] : sig_to_scan) {
          if (offset != NULL)
          {
              *what = GameModule.base + offset;
          }
          uintptr_t address = FindAddress(pattern);
          while (address == LM_ADDRESS_BAD) {
              this_thread::sleep_for(100ms);
              address = FindAddress(pattern);
          }
          *what = address + addition + 4 + *(int32_t*)(address + addition);
      }
  }

}

The probblem is my imGui only show gui when have memory::it(); when i remove it look like

bool LeagueWind::Hooks::Init() {
  Log::LogToFile(string("Init Memory, Functions"));
  while (kiero::init(kiero::RenderType::D3D11) != kiero::Status::Success ||
    kiero::bind(8, (void**)&oPresent, (void*)LeagueWind::Hooks::Present) != kiero::Status::UnknownError);
  return true;
}

imgui disapear WTF??, but my log still write normaly this is my hook present

#include "pch.h"
#include "LeagueWind.h"

HRESULT PRESENT_CALL LeagueWind::Hooks::Present(IDXGISwapChain* thisptr, UINT SyncInterval, UINT Flags)
{
  //Log::LogToFile(string("Hook Present"));
  if (!Data::InitImGui)
  {
      Log::LogToFile(string("InitImGui"));

      Data::pSwapChain = thisptr;
      if (SUCCEEDED(Data::pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&Data::pDxDevice11)))
      {
          Data::pDxDevice11->GetImmediateContext(&Data::pContext);
          DXGI_SWAP_CHAIN_DESC sd;
          Data::pSwapChain->GetDesc(&sd);
          Data::hWindow = sd.OutputWindow;
          ID3D11Texture2D* pBackBuffer;
          Data::pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
          Data::pDxDevice11->CreateRenderTargetView(pBackBuffer, NULL, &Data::pMainRenderTargetView);
          pBackBuffer->Release();

          Data::oWndProc = (WNDPROC)SetWindowLongPtr(Data::hWindow, GWLP_WNDPROC, (LONG_PTR)WndProc);

          ImGui::CreateContext();
          ImGuiIO& io = ImGui::GetIO();
          ImGui::StyleColorsDark();
          io.ConfigFlags = ImGuiConfigFlags_NoMouseCursorChange;
          ImGui_ImplWin32_Init(Data::hWindow);
          ImGui_ImplDX11_Init(Data::pDxDevice11, Data::pContext);
          Data::InitImGui = true;

      }
  }

  if (!Data::InitImGui) return oPresent(thisptr, SyncInterval, Flags);

  ImGui_ImplDX11_NewFrame();
  ImGui_ImplWin32_NewFrame();
  ImGui::NewFrame();

  ImGui::ShowDemoWindow();

  ImGui::EndFrame();
  ImGui::Render();

  Data::pContext->OMSetRenderTargets(1, &Data::pMainRenderTargetView, NULL);
  ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
  return oPresent(thisptr, SyncInterval, Flags);

}

with memory::it(); then imgui show normaly, i dont know what happened :|

I don't know how the imgui related code works, but first of all for sig_to_scan, the offset variable is the offset of the actual address relative to the searched address, so if you already have a specific address, you don't need to run the Scan function and can assign a value directly within the offset structure.

Gn3po4g commented 1 year ago
class LolString
{
    char content[0x10]; // 0x0
    int len = 0; // 0x10
    int max = 0; // 0x14

public:

    operator const char* (void)
    {
        return c_str();
    }
    operator std::string(void)
    {
        return std::string(c_str());
    }

    std::string str()
    {
        return std::string(c_str());
    }

private:
    char* c_str(void)
    {
        if (uintptr_t(this) <= 0x1000)
            return (char*)"";

        return max >= 0x10
            ? *reinterpret_cast<char**>(content)
            : content;
    }
};

-Use std::size_t instead of int for the len and max member variables. std::size_t is the recommended type for representing sizes and counts of objects in memory.

-Add a constructor to initialize the content, len, and max member variables. This will ensure that the object is always in a valid state when it is created.

-Add a destructor to deallocate any memory that was allocated by the object. This will prevent memory leaks.

-Use const qualifiers for member functions that do not modify the object, such as the c_str and str functions.

-Use nullptr instead of 0 or (char*)"" to represent a null pointer.

-Consider using std::string or another standard library container instead of manually managing memory with raw pointers and arrays.

heres my code

class LolString
{
    std::string content;

public:
    LolString() : content() {}

    operator const char* () const
    {
        return c_str();
    }

    operator std::string() const
    {
        return content;
    }

    std::string str() const
    {
        return content;
    }

private:
    const char* c_str() const
    {
        return content.c_str();
    }
};

This is perfectly fine if it's a custom class, but if it's a class that needs to use in-game memory, like GameObject or ObjectList, you just need to do a memory layout for the class, since it's managed by the game.

1nteg3r commented 1 year ago

if anyone is using imgui to draw, having a pointonscreen bool so you dont end up rendering unneeded drawings is performant heres my point2screen bool in renderer.cpp

bool PointOnScreen(XMFLOAT3 pos) {
        XMINT2 screenPos = WorldToScreen(pos);
        return screenPos.x >= 0 && screenPos.x < *width && screenPos.y >= 0 && screenPos.y < *height;
    }

im ccurrently implementing the minimap and ill let you guys know how it goes

vacnex commented 1 year ago

Hey guys i got a super super weird this is my source code dllmain image LeagueWind::Init image Hook::init image memory.cpp

#include "pch.h"
Offsets offsets;
namespace memory
{
    tuple<uintptr_t*, string, uintptr_t, uintptr_t> sig_to_scan[] = {
        {&offsets.oGameTime, "F3 0F 5C 35 ? ? ? ? 0F 28 F8", 4, 0x51b8c10},
        {&offsets.oLocalPlayer, "48 8B 05 ? ? ? ? 4C 8B D2 4C 8B C1", 3, 0x51c6980},
        {&offsets.oViewProjMatrices, "48 8D 0D ? ? ? ? 0F 10 00", 3, NULL},          // ok
        {&offsets.oHeroList, "48 8B 05 ? ? ? ? 4C 8B 78 08", 3, 0x210def0},               // ok
        {&offsets.oTurretList, "48 8B 1D ? ? ? ? 48 8B 5B 28 48 85 DB", 3, 0x51b4d40},    // ok
        //{ &offsets.oInhibitorList, "A1 ? ? ? ? 53 55 56 8B 70 04 8B 40 08", true },
        {&offsets.oMinionList, "48 8B 0D ? ? ? ? E8 ? ? ? ? EB 07", 3, 0x3968770}, // ok
        {&offsets.oChatClient, "41 FF D1 48 8B 0D ? ? ? ?", 6, 0x51c6b68},
        {&offsets.oHudInstance, "48 8B 0D ? ? ? ? 8B 57 10", 3, 0x210ddd8}, // ok

        {&offsets.oPrintChat, "E8 ? ? ? ? 4C 8B C3 B2 01", 1, 0x813FC0},
        {&offsets.oIssueOrder, "45 33 C0 E8 ? ? ? ? 48 83 C4 48", 4, 0x86a150},        // ok
        {&offsets.oAttackDelay, "E8 ? ? ? ? 33 C0 F3 0F 11 83 ? ? ? ?", 1, 0x3885a0},  // ok
        {&offsets.oAttackCastDelay, "89 83 ? ? ? ? E8 ? ? ? ? 48 8B CE", 7, 0x3884a0}, // ok
        {&offsets.oIsAlive, "48 8B D8 E8 ? ? ? ? 84 C0 74 35", 4, 0x229500},           // ok
        {&offsets.oBonusRadius, "E8 ? ? ? ? 0F 28 F8 48 8B D3 48 8B CE", 1, 0x1e5120},  // ok
    };

    lm_module_t GameModule{};

  uintptr_t FindAddress(string &pattern)
  {
    lm_page_t page{};
    page.end = GameModule.base;
    while (page.end < GameModule.end && LM_GetPage(page.end, &page))
    {
      if (page.prot & LM_PROT_R)
      {
        const auto scan_size = page.size - ranges::distance(pattern | views::split(' '));
        if (const auto address = LM_SigScan(pattern.data(), page.base, scan_size);
            address != LM_ADDRESS_BAD)
        {
          return address;
        }
      }
    }
    return LM_ADDRESS_BAD;
  }

  void it()
  {
    LM_FindModule(string("League of Legends.exe").data(), &GameModule);
    Scan();
  }

  void Scan()
  {
      for (auto& [what, pattern, addition, offset] : sig_to_scan) {
          if (offset != NULL)
          {
              *what = GameModule.base + offset;
          }
          uintptr_t address = FindAddress(pattern);
          while (address == LM_ADDRESS_BAD) {
              this_thread::sleep_for(100ms);
              address = FindAddress(pattern);
          }
          *what = address + addition + 4 + *(int32_t*)(address + addition);
      }
  }

}

The probblem is my imGui only show gui when have memory::it(); when i remove it look like

bool LeagueWind::Hooks::Init() {
    Log::LogToFile(string("Init Memory, Functions"));
    while (kiero::init(kiero::RenderType::D3D11) != kiero::Status::Success ||
    kiero::bind(8, (void**)&oPresent, (void*)LeagueWind::Hooks::Present) != kiero::Status::UnknownError);
    return true;
}

imgui disapear WTF??, but my log still write normaly this is my hook present

#include "pch.h"
#include "LeagueWind.h"

HRESULT PRESENT_CALL LeagueWind::Hooks::Present(IDXGISwapChain* thisptr, UINT SyncInterval, UINT Flags)
{
    //Log::LogToFile(string("Hook Present"));
    if (!Data::InitImGui)
    {
        Log::LogToFile(string("InitImGui"));

        Data::pSwapChain = thisptr;
        if (SUCCEEDED(Data::pSwapChain->GetDevice(__uuidof(ID3D11Device), (void**)&Data::pDxDevice11)))
        {
            Data::pDxDevice11->GetImmediateContext(&Data::pContext);
            DXGI_SWAP_CHAIN_DESC sd;
            Data::pSwapChain->GetDesc(&sd);
            Data::hWindow = sd.OutputWindow;
            ID3D11Texture2D* pBackBuffer;
            Data::pSwapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
            Data::pDxDevice11->CreateRenderTargetView(pBackBuffer, NULL, &Data::pMainRenderTargetView);
            pBackBuffer->Release();

            Data::oWndProc = (WNDPROC)SetWindowLongPtr(Data::hWindow, GWLP_WNDPROC, (LONG_PTR)WndProc);

            ImGui::CreateContext();
            ImGuiIO& io = ImGui::GetIO();
            ImGui::StyleColorsDark();
            io.ConfigFlags = ImGuiConfigFlags_NoMouseCursorChange;
            ImGui_ImplWin32_Init(Data::hWindow);
            ImGui_ImplDX11_Init(Data::pDxDevice11, Data::pContext);
            Data::InitImGui = true;

        }
    }

    if (!Data::InitImGui) return oPresent(thisptr, SyncInterval, Flags);

    ImGui_ImplDX11_NewFrame();
    ImGui_ImplWin32_NewFrame();
    ImGui::NewFrame();

    ImGui::ShowDemoWindow();

    ImGui::EndFrame();
    ImGui::Render();

    Data::pContext->OMSetRenderTargets(1, &Data::pMainRenderTargetView, NULL);
    ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
    return oPresent(thisptr, SyncInterval, Flags);

}

with memory::it(); then imgui show normaly, i dont know what happened :|

I don't know how the imgui related code works, but first of all for sig_to_scan, the offset variable is the offset of the actual address relative to the searched address, so if you already have a specific address, you don't need to run the Scan function and can assign a value directly within the offset structure.

Im resolve it because of conflict with MSI Afterbunner overlay, just uninstall it then fine 🤣

hmm I had problem with name has length more than 16 but working fine when name has a length less than 16. I see everyone use LolString class to solve it. but idk how to implement it

Im using these offset

inline uintptr_t Name = 0x60;
inline uintptr_t AiName = 0x38C8;

and read like this

std::string Object::SummnerName() {
    return *(std::string*)((uintptr_t)this + Offsets::game_object::Name);
}
std::string Object::AiName() {
    return *(std::string*)((uintptr_t)this + Offsets::game_object::AiName);
}

ingame show wrong because my name has length 15, so it is pointer image

So if im use LolString class then how can i cast to Lolstring when my string turn to pointer?

Gn3po4g commented 1 year ago

try to use const char* and turn it to string?