diff --git a/SingleFile/SingleFile.vcxproj b/SingleFile/SingleFile.vcxproj index edf10c5..45b33a1 100644 --- a/SingleFile/SingleFile.vcxproj +++ b/SingleFile/SingleFile.vcxproj @@ -38,13 +38,14 @@ Level3 true - WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + _CRT_SECURE_NO_WARNINGS;WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) true stdcpplatest Windows true + minhook.lib;%(AdditionalDependencies) diff --git a/SingleFile/main.cpp b/SingleFile/main.cpp index 95f12ba..63ee226 100644 --- a/SingleFile/main.cpp +++ b/SingleFile/main.cpp @@ -1,17 +1,12 @@ -#define _CRT_SECURE_NO_WARNINGS #include -#include #include -#include -#pragma comment(lib, "minhook") -#define IN_RANGE(x, a, b) (x >= a && x <= b) -#define GET_BITS(x) (IN_RANGE(x,'0','9') ? (x - '0') : ((x&(~0x20)) - 'A' + 0xA)) +#include +#define GET_BITS(x) ((x >= '0' && x <= '9') ? (x - '0') : ((x&(~0x20)) - 'A' + 0xA)) #define GET_BYTE(x) (GET_BITS(x[0x0]) << 0x4 | GET_BITS(x[0x1])) -PVOID client_dll = NULL; PVOID engine_dll = NULL; HMODULE pModule = NULL; +PVOID client_dll = NULL; PVOID engine_dll = NULL; typedef enum MH_STATUS { MH_UNKNOWN = -1, MH_OK = 0, MH_ERROR_ALREADY_INITIALIZED, MH_ERROR_NOT_INITIALIZED, MH_ERROR_ALREADY_CREATED, MH_ERROR_NOT_CREATED, MH_ERROR_ENABLED, MH_ERROR_DISABLED, MH_ERROR_NOT_EXECUTABLE, MH_ERROR_UNSUPPORTED_FUNCTION, MH_ERROR_MEMORY_ALLOC, MH_ERROR_MEMORY_PROTECT, MH_ERROR_MODULE_NOT_FOUND, MH_ERROR_FUNCTION_NOT_FOUND -} -MH_STATUS; // get minhook here: https://github.com/TsudaKageyu/minhook | License for minhook (text of license has not been modified, just newlines removed) : /* MinHook - The Minimalistic API Hooking Library for x64 / x86 * Copyright(C) 2009 - 2017 Tsuda Kageyu. * All rights reserved. * *Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met : * *1. Redistributions of source code must retain the above copyright * notice, this list of conditionsand the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditionsand the following disclaimer in the * documentationand /or other materials provided with the distribution. * *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, *PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * / +} MH_STATUS; // get minhook here: https://github.com/TsudaKageyu/minhook | License for minhook (text of license has not been modified, just newlines removed) : /* MinHook - The Minimalistic API Hooking Library for x64 / x86 * Copyright(C) 2009 - 2017 Tsuda Kageyu. * All rights reserved. * *Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met : * *1. Redistributions of source code must retain the above copyright * notice, this list of conditionsand the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditionsand the following disclaimer in the * documentationand /or other materials provided with the distribution. * *THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A * PARTICULAR PURPOSE ARE DISCLAIMED.IN NO EVENT SHALL THE COPYRIGHT HOLDER * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES(INCLUDING, BUT NOT LIMITED TO, *PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT(INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * / extern "C" { MH_STATUS WINAPI MH_Initialize(VOID); MH_STATUS WINAPI MH_Uninitialize(VOID); @@ -34,7 +29,8 @@ PBYTE PatternScan(PVOID m_pModule, LPCSTR m_szSignature) { if (!pat[0x2]) return first_match; pat += (*(PUSHORT)pat == (USHORT)'\?\?' || *(PBYTE)pat != (BYTE)'\?') ? 0x3 : 0x2; - } else { + } + else { if (first_match != 0x0) current = first_match; pat = m_szSignature; @@ -43,13 +39,13 @@ PBYTE PatternScan(PVOID m_pModule, LPCSTR m_szSignature) { } return NULL; } -#undef DrawText -#undef CreateFont template __forceinline I v(PVOID iface, Args... args) { return (*(I(__thiscall***)(void*, Args...))(iface))[Idx](iface, args...); } #define VIRTUAL_METHOD(returnType, name, idx, args, argsRaw) __forceinline returnType name args { return vargsRaw; } #define OFFSET(type, name, offset) __forceinline type name(VOID) { return *(type*)(this + offset); } #define ROFFSET(type, name, offset) __forceinline type& name(VOID) { return *(type*)(this + offset);} // not sure if there's a better way to do this but whatever +#define PAD(amt) private: char padding_##amt[amt]; public: +#define CLAMP(val, _min, _max) (val > _max) ? _max : (val < _min) ? _min : val using matrix_t = FLOAT[3][4]; using matrix4x4_t = FLOAT[4][4]; BOOLEAN menu_open = TRUE; @@ -71,6 +67,9 @@ struct sconfig { BOOLEAN m_bDisablePostProcess; BOOLEAN m_bRankRevealer; BOOLEAN m_bFlashReducer; + BOOLEAN m_bThirdperson; + INT m_nThirdpersonDistance = 10; + BOOLEAN m_bThirdpersonOnDead; }visuals; struct smisc { BOOLEAN m_bBhop; @@ -82,16 +81,13 @@ struct sconfig { BOOLEAN m_bSpectatorList; BOOLEAN m_bUseSpam; BOOLEAN m_bVoteRevealer; + BOOLEAN m_bClanTag; }misc; }config; class vec3 { public: FLOAT x, y, z; - vec3(FLOAT a = 0, FLOAT b = 0, FLOAT c = 0) { - this->x = a; - this->y = b; - this->z = c; - } + vec3(FLOAT a = 0, FLOAT b = 0, FLOAT c = 0) : x(a), y(b), z(c) { } vec3 operator-=(const vec3& in) { x -= in.x; y -= in.y; z -= in.z; return *this; } vec3 operator+=(const vec3& in) { x += in.x; y += in.y; z += in.z; return *this; } vec3 operator/=(const vec3& in) { x /= in.x; y /= in.y; z /= in.z; return *this; } @@ -105,13 +101,7 @@ class vec3 { }; struct SPlayerInfo { ULONG64 m_ullVersion; - union { - ULONG64 m_ullXUID; - struct { - DWORD m_nXUIDLow; - DWORD m_nXUIDHigh; - }; - }; + ULONG64 m_ullXUID; CHAR m_szName[128]; INT m_nUserID; CHAR m_szGUID[33]; @@ -124,16 +114,17 @@ struct SPlayerInfo { }; class CMatSystemSurface { public: - VIRTUAL_METHOD(VOID, DrawFilledRect, 16, (DWORD x, DWORD y, DWORD w, DWORD h), (this, x, y, x + w, y + h)) - VIRTUAL_METHOD(VOID, SetColor, 15, (USHORT r, USHORT g, USHORT b, USHORT a), (this, r, g, b, a)) - VIRTUAL_METHOD(VOID, SetTextColor, 25, (USHORT r, USHORT g, USHORT b, USHORT a), (this, r, g, b, a)) - VIRTUAL_METHOD(VOID, SetTextPosition, 26, (DWORD x, DWORD y), (this, x, y)) - VIRTUAL_METHOD(VOID, DrawText, 28, (LPCWSTR text, DWORD len), (this, text, len, 0)) - VIRTUAL_METHOD(DWORD, CreateFont, 71, (VOID), (this)) - VIRTUAL_METHOD(BOOLEAN, SetFontGlyphs, 72, (DWORD _font, LPCSTR name, DWORD height, DWORD weight, DWORD font_flags), (this, _font, name, height, weight, 0, 0, font_flags, 0, 0)) - VIRTUAL_METHOD(VOID, SetTextFont, 23, (DWORD _font), (this, _font)) - VIRTUAL_METHOD(VOID, DrawRectOutline, 18, (DWORD x, DWORD y, DWORD w, DWORD h), (this, x, y, x + w, y + h)) - VIRTUAL_METHOD(VOID, GetTextSize, 79, (DWORD _font, LPCWSTR text, DWORD& w, DWORD& h), (this, _font, text, std::ref(w), std::ref(h))) + VIRTUAL_METHOD(VOID, DrawFilledRect, 16, (DWORD x, DWORD y, DWORD w, DWORD h), (this, x, y, x + w, y + h)); + VIRTUAL_METHOD(VOID, SetColor, 15, (USHORT r, USHORT g, USHORT b, USHORT a), (this, r, g, b, a)); + VIRTUAL_METHOD(VOID, SetTextColor, 25, (USHORT r, USHORT g, USHORT b, USHORT a), (this, r, g, b, a)); + VIRTUAL_METHOD(VOID, SetTextPosition, 26, (DWORD x, DWORD y), (this, x, y)); + VIRTUAL_METHOD(VOID, DrawText, 28, (LPCWSTR text, DWORD len), (this, text, len, 0)); + VIRTUAL_METHOD(DWORD, CreateFont, 71, (VOID), (this)); + VIRTUAL_METHOD(BOOLEAN, SetFontGlyphs, 72, (DWORD _font, LPCSTR name, DWORD height, DWORD weight, DWORD font_flags), (this, _font, name, height, weight, 0, 0, font_flags, 0, 0)); + VIRTUAL_METHOD(VOID, SetTextFont, 23, (DWORD _font), (this, _font)); + VIRTUAL_METHOD(VOID, DrawRectOutline, 18, (DWORD x, DWORD y, DWORD w, DWORD h), (this, x, y, x + w, y + h)); + VIRTUAL_METHOD(VOID, GetTextSize, 79, (DWORD _font, LPCWSTR text, DWORD& w, DWORD& h), (this, _font, text, std::ref(w), std::ref(h))); + VIRTUAL_METHOD(VOID, GradientRectangle, 123, (INT x, INT y, INT w, INT h, DWORD dwAlpha1, DWORD dwAlpha2, BOOLEAN bHoriz), (this, x, y, x + w, y + h, dwAlpha1, dwAlpha2, bHoriz)); }; enum EMoveType { NONE = 0, @@ -150,7 +141,7 @@ class CCSClientClass { public: PVOID CreateClassFn; PVOID CreateEventFn; - char* m_szNetworkedName; + LPSTR m_szNetworkedName; PVOID m_pRecvTable; CCSClientClass* m_pNextClass; INT m_nClassID; @@ -184,28 +175,12 @@ class CBaseEntity { OFFSET(FLOAT, FlashDuration, 0xA420); ROFFSET(FLOAT, FlashMaxAlpha, 0xA41C) OFFSET(INT, Ammo, 0x3264); - OFFSET(INT, CrosshairTarget, 0xB3E4); + OFFSET(INT, CrosshairTarget, 0xB3E8); + ROFFSET(INT, ObserverMode, 0x3378); }; class CGlobalVarsBase { -public: - FLOAT m_flRealTime; - INT m_nFrameCount; - FLOAT m_flAbsFrameTime; - FLOAT m_flAbsFrameStart; + PAD(0x10); // PAD resets access level to public FLOAT m_flCurrentTime; - FLOAT m_flFrameTime; - INT m_nMaxClients; - INT m_nTickCount; - FLOAT m_flTickInterval; - FLOAT m_flInteropolationAmount; - INT m_nTicksThisFrmae; - INT m_nNetworkProtocol; - PVOID m_pGameSaveData; - BOOLEAN m_bClient; - BOOLEAN m_bRemoteClient; -private: - DWORD unk1; - DWORD unk2; }; template T RelativeToAbsolute(DWORD m_pAddress) { @@ -226,6 +201,7 @@ class IVEngineClient { VIRTUAL_METHOD(VOID, ClientCmdUnrestricted, 114, (LPCSTR szCommand), (this, szCommand, FALSE)); VIRTUAL_METHOD(LPCSTR, GetVersionString, 105, (VOID), (this)); VIRTUAL_METHOD(INT, GetPlayerIndex, 9, (INT nIndex), (this, nIndex)); + VIRTUAL_METHOD(VOID, GetViewAngles, 18, (vec3& angles), (this, std::ref(angles))); }; class IGameEvent { public: @@ -251,44 +227,67 @@ class ICVar { public: VIRTUAL_METHOD(CConvar*, FindVar, 15, (LPCSTR name), (this, name)); }; -class CRecvProp; -class CClientClass { +class CRay { +public: + CRay(vec3 vecSource, vec3 vecDest) { this->vecStart = vecSource; this->vecDelta = (vecDelta - vecSource); } + vec3 vecStart; + vec3 vecDelta; +}; +struct CTraceFilter { + LPCVOID pSkip; + CTraceFilter(CBaseEntity* pEntity) { this->pSkip = pEntity; } +}; +class CTrace { +public: + vec3 vecStart; + vec3 vecEnd; + PAD(0x14); + FLOAT flFraction; + PAD(0xC); + LPCSTR pszSurfaceName; + PAD(0x0C); + CBaseEntity* pEntity; + INT nHitbox; +}; +class IEngineTrace { public: - PVOID m_pCreateFunction; - PVOID m_pCreateEventFunction; - char* m_szNetworkName; - CRecvProp* m_pRecvPointer; - CClientClass* m_pNextPointer; - int m_nClassID; + VIRTUAL_METHOD(VOID, TraceRay, 5, (const CRay& pRay, DWORD dwMask, const CTraceFilter& pSkip, CTrace& pTrace), (this, std::cref(pRay), dwMask, std::cref(pSkip), std::ref(pTrace))); }; +class CRecvProp; class IClient { public: - VIRTUAL_METHOD(CClientClass*, GetClientClasses, 8, (VOID), (this)) + VIRTUAL_METHOD(CCSClientClass*, GetClientClasses, 8, (VOID), (this)) VIRTUAL_METHOD(BOOLEAN, DispatchUserMessage, 38, (INT m_nMessageType, INT m_nArgument1, INT m_nArgument2, PVOID m_pData), (this, m_nMessageType, m_nArgument1, m_nArgument2, m_pData)) }; +class CInput { +public: + PAD(0xAD); + bool bCameraInThirdperson; + PAD(0x1); + vec3 vecCameraOffset; +}; class IClientModeShared; class IGameEventManager2; class ISound; struct sinterfaces { - IVEngineClient* engine = nullptr; - CMatSystemSurface* surface = nullptr; - CBaseEntityList* entitylist = nullptr; - IPanel* panel = nullptr; - IClient* client = nullptr; - IClientModeShared* client_mode = nullptr; - IGameEventManager2* events = nullptr; - CGlobalVarsBase* globals = nullptr; - ICVar* cvar = nullptr; - ISound* sound = nullptr; + IVEngineClient* engine = NULL; + CMatSystemSurface* surface = NULL; + CBaseEntityList* entitylist = NULL; + IPanel* panel = NULL; + IClient* client = NULL; + IClientModeShared* client_mode = NULL; + IGameEventManager2* events = NULL; + CGlobalVarsBase* globals = NULL; + ICVar* cvar = NULL; + ISound* sound = NULL; + CInput* input = NULL; + IEngineTrace* trace = NULL; }interfaces; HWND csgo_window; WNDPROC orig_proc; struct vec2 { INT x, y; - vec2(INT x = 0, INT y = 0) { - this->x = x; - this->y = y; - } + vec2(INT x = 0, INT y = 0) : x(x), y(y) {} }; VOID load(LPCSTR szConfigName) { FILE* cfg = fopen(szConfigName, "r"); @@ -300,6 +299,11 @@ VOID save(LPCSTR szConfigName) { fwrite(&config, sizeof(config), 1, cfg); fclose(cfg); } +typedef struct TAGrgba { + INT r, g, b, a; + TAGrgba(INT r = 0, INT g = 0, INT b = 0, INT a = 255) : r(r), g(g), b(b), a(a) { } + FLOAT* AsFloat() { FLOAT p[4] = { this->r / 255.f, this->g / 255.f, this->b / 255.f, this->a / 255.f }; return p; } +}RGBA, * PRGBA; namespace menu { struct sctx { BOOLEAN open; INT width; }; std::unordered_map < LPCWSTR, BOOLEAN> item_clicks = {}; @@ -308,10 +312,10 @@ namespace menu { vec2 start_pos, size; BOOLEAN dragging = FALSE, clicked = FALSE, item_active = FALSE, inmove = FALSE; INT x_pos = 0, y_pos = 0, last_mouse_x = 0, last_mouse_y = 0; - BOOLEAN in_region( INT x, INT y, INT w, INT h ) { + BOOLEAN in_region(INT x, INT y, INT w, INT h) { return last_mouse_x >= x && last_mouse_y >= y && last_mouse_x <= x + w && last_mouse_y <= y + h; } - BOOLEAN clicked_at( LPCWSTR n, INT x, INT y, INT w, INT h ) { + BOOLEAN clicked_at(LPCWSTR n, INT x, INT y, INT w, INT h) { if (item_clicks.count(n) == 0) item_clicks[n] = FALSE; if (!in_region(x, y, w, h) && !item_clicks[n] || inmove) return FALSE; item_active = TRUE; @@ -343,7 +347,7 @@ namespace menu { interfaces.surface->SetTextColor(255, 255, 255, 255); static DWORD u, i; interfaces.surface->GetTextSize(menu::font, name, u, i); - interfaces.surface->SetTextPosition( start_pos.x + (size.x / 2) - (u / 2), start_pos.y + 6); + interfaces.surface->SetTextPosition(start_pos.x + (size.x / 2) - (u / 2), start_pos.y + 6); interfaces.surface->DrawText(name, wcslen(name)); x_pos = start_pos.x + 10; y_pos = start_pos.y + 25; @@ -387,7 +391,7 @@ namespace menu { return FALSE; } VOID move(INT x, INT y) { - auto store = [x, y] () -> VOID { menu::last_mouse_x = x; menu::last_mouse_y = y; }; + auto store = [x, y]() -> VOID { menu::last_mouse_x = x; menu::last_mouse_y = y; }; if (!clicked) { menu::dragging = FALSE; return store(); @@ -404,7 +408,7 @@ namespace menu { VOID keybinder(PINT pKey) { // Pints for the low hello Dex. INT x = x_pos + 180 - Keys[pKey].width; INT y = y_pos - 15; - LPCWSTR wszKeyName = pwszVirtualKeys[*pKey]; + LPCWSTR wszKeyName = pwszVirtualKeys[*pKey]; DWORD w, xh, h = 20; interfaces.surface->GetTextSize(menu::font, wszKeyName, w, xh); Keys[pKey].width = w + 16; @@ -426,17 +430,68 @@ namespace menu { interfaces.surface->DrawFilledRect(x + 1, y + 1, Keys[pKey].width - 2, h - 2); interfaces.surface->SetTextPosition(x + (Keys[pKey].width / 2) - 0x6, y + 3); // 0x6 = 12 / 2, 12 is the size of L"..." on the menu. interfaces.surface->DrawText(L"...", 0x3); - INT nState = *pKey; for (INT i = 0; i < 256; i++) { - USHORT nValue = GetAsyncKeyState(i) & 1; - if (nValue && i != nState) { + if (GetAsyncKeyState( i ) & 1 && i != *pKey) { *pKey = i; Keys[pKey].open = FALSE; } } } } -} + VOID slider(LPCWSTR wsz, INT nMin, INT nMax, PINT pnOut) { + interfaces.surface->SetTextPosition(x_pos + 2, y_pos); y_pos += 12; + interfaces.surface->DrawText(wsz, wcslen(wsz)); + WCHAR pwszValue[8]; _itow(*pnOut, pwszValue, 10); DWORD w, h; + interfaces.surface->GetTextSize(menu::font, pwszValue, w, h); + interfaces.surface->SetTextPosition((x_pos + 170) - (w + 2), y_pos - 12); // meh too lazy to change offset + interfaces.surface->DrawText(pwszValue, wcslen(pwszValue)); + interfaces.surface->SetColor(17, 17, 17, 255); + interfaces.surface->DrawRectOutline(x_pos, y_pos, 170, 15); + interfaces.surface->SetColor(37, 37, 37, 255); + interfaces.surface->DrawRectOutline(x_pos + 1, y_pos + 1, 168, 13); + interfaces.surface->SetColor(25, 100, 255, 255); + interfaces.surface->DrawFilledRect(x_pos + 2, y_pos + 2, (166 * ((FLOAT)(*pnOut) / (FLOAT)(nMax - nMin))), 11); + if (in_region(x_pos - 2, y_pos - 2, 172, 17) && GetAsyncKeyState(VK_LBUTTON)) // make the bbox slightly bigger if the mouse is moving quickly + *pnOut = CLAMP((FLOAT)((last_mouse_x - x_pos) / 170.f) * nMax, nMin, nMax); + y_pos += 20; + } + VOID colorpicker(INT x, PRGBA pColor) { // we'll re-use the Keys object for the opened-ness. + interfaces.surface->SetColor(17, 17, 17, 255); + interfaces.surface->DrawRectOutline(x_pos + x, y_pos, 16, 16); + interfaces.surface->SetColor(37, 37, 37, 255); + interfaces.surface->DrawRectOutline(x_pos + x + 1, y_pos + 1, 14, 14); + interfaces.surface->SetColor(pColor->r, pColor->g, pColor->b, pColor->a); + interfaces.surface->DrawFilledRect(x_pos + x + 2, y_pos + 2, 12, 12); + interfaces.surface->SetColor(0, 0, 0, 255); + interfaces.surface->GradientRectangle(x_pos + x + 2, y_pos + 2, 12, 12, 75, 25, FALSE); // give 3d look + if (in_region(x_pos + x, y_pos, 16, 16) && GetAsyncKeyState(VK_LBUTTON)) + Keys[(PINT)(pColor)].open = TRUE; + if (!in_region(x_pos + x, y_pos, 16, 16) && GetAsyncKeyState(VK_LBUTTON) && !in_region(x_pos + x + 5, y_pos + 5, 230, 200)) + Keys[(PINT)(pColor)].open = FALSE; + if (Keys[(PINT)(pColor)].open) { + interfaces.surface->SetColor(42, 42, 42, 255); + interfaces.surface->DrawFilledRect(x_pos + x + 5, y_pos + 5, 230, 200); + interfaces.surface->SetColor(37, 37, 37, 255); + interfaces.surface->DrawRectOutline(x_pos + x + 6, y_pos + 6, 228, 198); + interfaces.surface->SetColor(255, 255, 255, 255); + interfaces.surface->DrawFilledRect(x_pos + x + 7, y_pos + 7, 196, 196); + interfaces.surface->SetColor(1, 1, 1, 255); + interfaces.surface->GradientRectangle(x_pos + x + 7, y_pos + 7, 196, 196, 255, 0, FALSE); + interfaces.surface->SetColor(25, 100, 255, 255); + interfaces.surface->GradientRectangle(x_pos + x + 7, y_pos + 7, 196, 196, 0, 255, TRUE); + const RGBA Hues[7] = { + {255, 0, 0}, {255, 0, 255}, {0, 0, 255}, {0, 255, 255}, {0, 255, 0}, {255, 255, 0}, {255, 0, 0} + }; + for (INT i = 0; i < 6; i++) { + RGBA coly = Hues[i + 1], colx = Hues[i]; + interfaces.surface->SetColor(colx.r, colx.g, colx.b, 255); + interfaces.surface->DrawFilledRect(x_pos + x + 210, y_pos + 2 + (14 * i), 16, 14); + interfaces.surface->SetColor(coly.r, coly.g, coly.b, 255); + interfaces.surface->GradientRectangle(x_pos + x + 210, y_pos + 2 + (28 * i), 16, 28, 0, 255, FALSE); + } + } + } +} VOID SetupFonts() { menu::font = interfaces.surface->CreateFont(); interfaces.surface->SetFontGlyphs(menu::font, "Verdana", 12, 600, 0); @@ -450,7 +505,7 @@ VOID RenderMenu() { once = TRUE; } menu::window(L"singlefile csgo internal"); - menu::checkbox(L"bhop", &config.misc.m_bBhop); + menu::checkbox(L"bhop", &config.misc.m_bBhop); menu::checkbox(L"auto pistol", &config.aimbot.m_bAutoPistol); menu::checkbox(L"hitsound", &config.misc.m_bHitSound); menu::checkbox(L"box esp", &config.visuals.m_bBoxESP); @@ -473,16 +528,20 @@ VOID RenderMenu() { menu::checkbox(L"use spam", &config.misc.m_bUseSpam); menu::checkbox(L"flash reducer", &config.visuals.m_bFlashReducer); menu::checkbox(L"vote revealer", &config.misc.m_bVoteRevealer); - if (menu::button(L"load", {menu::start_pos.x + 10, menu::start_pos.y + 220}, {195, 30})) + if (menu::button(L"load", { menu::start_pos.x + 10, menu::start_pos.y + 220 }, { 195, 30 })) load("singlefile"); - if (menu::button(L"save", {menu::start_pos.x + 215, menu::start_pos.y + 220}, {195, 30})) - save("singlefile"); + if (menu::button(L"save", { menu::start_pos.x + 215, menu::start_pos.y + 220 }, { 195, 30 })) +save("singlefile"); +RGBA pog(20, 100, 255); +menu::colorpicker(170, &pog); +static int nTest = 102; +menu::slider(L"test slider", 0, 200, &nTest); } class CUserCmd { private: BYTE pad_0x0[0x4]; public: - INT m_nCommandNumber; + INT m_nCommandNumber; INT m_nTickCount; vec3 m_vecAngles; vec3 m_vecDirection; @@ -500,6 +559,7 @@ class CUserCmd { private: BYTE pad_0x1[0x18]; }; +VOID(WINAPI* OverrideViewOriginal)(PVOID); BOOLEAN(WINAPI* CreateMoveOriginal)(FLOAT, CUserCmd*); VOID(__thiscall* PaintTraverseOriginal)(IPanel*, DWORD, BOOLEAN, BOOLEAN); BOOLEAN(__thiscall* GameEventsOriginal)(IGameEventManager2*, IGameEvent*); @@ -507,21 +567,13 @@ VOID(WINAPI* EmitSoundOriginal)(PVOID, INT, INT, LPCSTR, DWORD, LPCSTR, FLOAT, I BOOLEAN(__thiscall* DispatchUserMessageOriginal)(PVOID, INT, INT, INT, PVOID); LRESULT CALLBACK Wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { - if (uMsg == WM_KEYDOWN) { - switch (wParam) { - case VK_INSERT: - menu_open = !menu_open; - break; - } - } + if (uMsg == WM_KEYDOWN && wParam == VK_INSERT) + menu_open ^= true; + menu::inmove = uMsg == WM_MOUSEMOVE; menu::clicked = (BOOLEAN)(wParam & MK_LBUTTON); - if (uMsg == WM_MOUSEMOVE) { + if (menu::inmove) menu::move((INT)((SHORT)(LOWORD(lParam))), (INT)((SHORT)(HIWORD(lParam)))); - menu::inmove = TRUE; - } else { - menu::inmove = FALSE; - } - return CallWindowProc(orig_proc, hWnd, uMsg, wParam, lParam); + return CallWindowProcA(orig_proc, hWnd, uMsg, wParam, lParam); } enum { IN_ATTACK = 1 << 0, @@ -530,8 +582,8 @@ enum { IN_SCORE = 1 << 16, IN_COUNT = 1 << 26, }; -namespace colors { unsigned char green[4] = {0, 255, 0, 255}; unsigned char lightgreen[4] = {10, 200, 10, 255}; unsigned char red[4] = {255, 0, 0, 255}; unsigned char lightred[4] = {200, 10, 10, 255}; }; -void(*ColoredMsg)(PUCHAR, LPCSTR, ...); +namespace colors { unsigned char green[4] = { 0, 255, 0, 255 }; unsigned char lightgreen[4] = { 10, 200, 10, 255 }; unsigned char red[4] = { 255, 0, 0, 255 }; unsigned char lightred[4] = { 200, 10, 10, 255 }; }; +VOID(*ColoredMsg)(PUCHAR, LPCSTR, ...); VOID voterevealer(IGameEvent* evt = NULL) { if (!config.misc.m_bVoteRevealer || !interfaces.engine->IsInGame()) return; @@ -568,13 +620,25 @@ VOID autopistol(CUserCmd* cmd) { cmd->m_nButtons &= ~IN_ATTACK; } } +__forceinline constexpr DWORD fnv(LPCSTR szString, DWORD nOffset = 0x811C9DC5) { + return (*szString == '\0') ? nOffset : fnv(&szString[1], (nOffset ^ DWORD(*szString)) * 0x01000193); +} +#define CT_FNV(str) (std::integral_constant::value) VOID autoaccept(LPCSTR sound) { - if (strstr(sound, "UIPanorama.popup_accept_match_beep")) { + if (fnv(sound) == CT_FNV("UIPanorama.popup_accept_match_beep")) { static BOOLEAN(WINAPI * SetLPReady)(LPCSTR) = (decltype(SetLPReady))PatternScan(client_dll, "55 8B EC 83 E4 F8 8B 4D 08 BA ? ? ? ? E8 ? ? ? ? 85 C0 75 12"); if (config.misc.m_bAutoAccept) SetLPReady(""); } } +LPCSTR szClantag = ""; +VOID clantag() { + static VOID(__fastcall * SetClantag)(LPCSTR, LPCSTR) = (decltype(SetClantag))PatternScan(engine_dll, "53 56 57 8B DA 8B F9 FF 15"); + if (config.misc.m_bClanTag && !strstr(szClantag, "SingleFile")) + SetClantag("SingleFile", "SingleFile"); + if (!config.misc.m_bClanTag && strstr(szClantag, "SingleFile")) + SetClantag("\x20", "\x20"); +} VOID flashreducer() { if (!config.visuals.m_bFlashReducer || !interfaces.engine->IsInGame()) return; @@ -586,15 +650,14 @@ VOID flashreducer() { interfaces.engine->GetScreenSize(w, h); interfaces.surface->GetTextSize(6, L"FLASHED!", tw, th); // first 50 built-in vgui fonts: https://cdn.discordapp.com/attachments/634094496300400641/821827439042101258/unknown.png interfaces.surface->SetTextPosition((DWORD)((w * 0.5f) - tw * 0.5f), (DWORD)(h * 0.75f)); - interfaces.surface->SetTextFont(6); + interfaces.surface->SetTextFont(6); interfaces.surface->DrawText(L"FLASHED!", 0x8); } } struct bbox { INT x, y, w, h; }; -BOOLEAN WorldToScreen(const vec3& world, vec3& screen) -{ +BOOLEAN WorldToScreen(const vec3& world, vec3& screen) { matrix4x4_t& view = interfaces.engine->GetViewMatrix(); screen.x = world.x * view[0][0] + world.y * view[0][1] + world.z * view[0][2] + view[0][3]; screen.y = world.x * view[1][0] + world.y * view[1][1] + world.z * view[1][2] + view[1][3]; @@ -613,30 +676,35 @@ BOOLEAN WorldToScreen(const vec3& world, vec3& screen) return TRUE; } #define FL_MAX 3.40282e+038; +#define PI 3.1415927f +#define Radians(x) ((FLOAT)(x)*(FLOAT)(PI / 180.f)) vec3 VectorTransform(vec3 in, matrix_t matrix) { return vec3(in.dot(matrix[0]) + matrix[0][3], in.dot(matrix[1]) + matrix[1][3], in.dot(matrix[2]) + matrix[2][3]); } +vec3 AngleVectors(vec3 vecAngles) { + vec3 vecReturn; + FLOAT p1, p2, p3, p4; + p1 = sinf(Radians(vecAngles.y)); + p2 = cosf(Radians(vecAngles.y)); + p3 = sinf(Radians(vecAngles.x)); + p4 = cosf(Radians(vecAngles.x)); + vecReturn = { p4 * p2, p4 * p1, -p3 }; + return vecReturn; +} BOOLEAN getbbot(CBaseEntity* player, bbox& box) { matrix_t& rgflTransFrame = (matrix_t&)player->GetCoordinateFrame(); const vec3 min = player->CollisonMins(); const vec3 max = player->CollisonMaxs(); vec3 vecTransScreen[8]; vec3 points[] = { - vec3(min.x, min.y, min.z), - vec3(min.x, max.y, min.z), - vec3(max.x, max.y, min.z), - vec3(max.x, min.y, min.z), - vec3(max.x, max.y, max.z), - vec3(min.x, max.y, max.z), - vec3(min.x, min.y, max.z), - vec3(max.x, min.y, max.z) + vec3(min.x, min.y, min.z), vec3(min.x, max.y, min.z), vec3(max.x, max.y, min.z), vec3(max.x, min.y, min.z), vec3(max.x, max.y, max.z), vec3(min.x, max.y, max.z), vec3(min.x, min.y, max.z), vec3(max.x, min.y, max.z) }; for (INT i = 0; i <= 7; i++) { if (!WorldToScreen(VectorTransform(points[i], rgflTransFrame), vecTransScreen[i])) return FALSE; } vec3 vecBoxes[] = { - vecTransScreen[3], vecTransScreen[5], vecTransScreen[0], vecTransScreen[4], vecTransScreen[2], vecTransScreen[1], vecTransScreen[6], vecTransScreen[7] + vecTransScreen[3], vecTransScreen[5], vecTransScreen[0], vecTransScreen[4], vecTransScreen[2], vecTransScreen[1], vecTransScreen[6], vecTransScreen[7] }; FLOAT flLeft = vecTransScreen[3].x, flBottom = vecTransScreen[3].y, flRight = vecTransScreen[3].x, flTop = vecTransScreen[3].y; for (INT i = 0; i <= 7; i++) { @@ -655,15 +723,6 @@ BOOLEAN getbbot(CBaseEntity* player, bbox& box) { box.h = (INT)(flBottom)-(INT)(flTop); return TRUE; } -struct rgba { - INT r, g, b, a; - rgba(INT r = 0, INT g = 0, INT b = 0, INT a = 255) { - this->r = r; - this->g = g; - this->b = b; - this->a = a; - } -}; VOID players() { if (!interfaces.engine->IsInGame()) return; @@ -702,11 +761,11 @@ VOID players() { } } if (config.visuals.m_bHealthBar) { - rgba healthclr; + RGBA healthclr; if (entity->GetHealth() > 100) - healthclr = rgba(0, 255, 0, 255); + healthclr = RGBA(0, 255, 0, 255); else - healthclr = rgba((INT)(255 - entity->GetHealth() * 2.55f), (INT)(entity->GetHealth() * 2.55f), 0, 255); + healthclr = RGBA((INT)(255 - entity->GetHealth() * 2.55f), (INT)(entity->GetHealth() * 2.55f), 0, 255); interfaces.surface->SetColor(0, 0, 0, 255); interfaces.surface->DrawFilledRect(box.x - 10, box.y - 1, 5, box.h + 2); interfaces.surface->SetColor(healthclr.r, healthclr.g, healthclr.b, healthclr.a); @@ -718,7 +777,7 @@ VOID players() { } VOID cvars() { CBaseEntity* localplayer = interfaces.entitylist->GetEntity(interfaces.engine->GetLocalPlayer()); - interfaces.cvar->FindVar("mat_postprocess_enable")->SetValue(config.visuals.m_bDisablePostProcess ? 0 : 1); + interfaces.cvar->FindVar("mat_postprocess_enable")->SetValue(config.visuals.m_bDisablePostProcess ? 0 : 1); interfaces.cvar->FindVar("cl_crosshair_recoil")->SetValue(config.misc.m_bRecoilCrosshair ? 1 : 0); // i'm sure the ? 1 : 0 doesn't matter but this feels better. /shrug interfaces.cvar->FindVar("weapon_debug_spread_show")->SetValue(((config.misc.m_bNoScopeCrosshair) && !localplayer->IsScoped()) ? 2 : 0); } @@ -728,7 +787,7 @@ VOID speclist() { CBaseEntity* localplayer = interfaces.entitylist->GetEntity(interfaces.engine->GetLocalPlayer()); if (!localplayer) return; - static INT b = 0; + INT b = 0; if (config.misc.m_bSpectatorList) { for (INT i = 1; i <= interfaces.engine->GetMaxClients(); i++) { CBaseEntity* entity = interfaces.entitylist->GetEntity(i); @@ -750,7 +809,6 @@ VOID speclist() { b += 12; } } - b = 0; } VOID triggerbot(CUserCmd* cmd) { if (!(config.aimbot.m_bTriggerbot)) @@ -773,18 +831,24 @@ VOID usespam(CUserCmd* cmd) { cmd->m_nButtons &= ~IN_USE; } } +VOID __stdcall _OverrideView(PVOID pArgument) { + return OverrideViewOriginal(pArgument); +} BOOLEAN __fastcall _DispatchUserMessage(PVOID ecx, PVOID edx, INT nMessageType, INT nArgument, INT nArgument2, PVOID pData) { if (nMessageType == 47 && config.misc.m_bVoteRevealer) { - ColoredMsg(colors::green, "[singlefile] Vote Passed!\n"); Beep(670, 50); } + ColoredMsg(colors::green, "[singlefile] Vote Passed!\n"); Beep(670, 50); + } if (nMessageType == 48 && config.misc.m_bVoteRevealer) { - ColoredMsg(colors::red, "[singlefile] Vote Failed!\n"); Beep(343, 50); } + ColoredMsg(colors::red, "[singlefile] Vote Failed!\n"); Beep(343, 50); + } return DispatchUserMessageOriginal(interfaces.client, nMessageType, nArgument, nArgument2, pData); } BOOLEAN WINAPI _CreateMove(FLOAT flInputSampleTime, CUserCmd* cmd) { BOOLEAN SetViewAngles = CreateMoveOriginal(flInputSampleTime, cmd); - if (cmd->m_nCommandNumber % 4 == 1) { + if (cmd->m_nCommandNumber % 10 == 1) { cmd->m_nButtons |= IN_COUNT; // anti-afk kick maybe make it it's own option at some point :P cvars(); // commands that do not to run each tick (i.e don't need usercmd, just dependent on localplayer & being in game) + clantag(); } if (cmd->m_nButtons & IN_SCORE && config.visuals.m_bRankRevealer) interfaces.client->DispatchUserMessage(50, 0, 0, NULL); @@ -798,31 +862,28 @@ VOID WINAPI _EmitSound(void* filter, int entityIndex, int channel, const char* s autoaccept(soundEntry); return EmitSoundOriginal(filter, entityIndex, channel, soundEntry, soundEntryHash, sample, volume, seed, soundLevel, flags, pitch, std::cref(origin), std::cref(direction), utlVecOrigins, updatePositions, soundtime, speakerentity, soundParams); } -DWORD fnv(LPCSTR szString, DWORD nOffset = 0x811C9DC5) { - return (*szString == '\0') ? nOffset : fnv(&szString[1], (nOffset ^ DWORD(*szString)) * 0x01000193); -} BOOLEAN WINAPI _GameEvents(IGameEvent* event) { DWORD dwEventHash = fnv(event->GetName()); - if (config.misc.m_bHitSound && dwEventHash == 0x1B30DDF0) { + if (config.misc.m_bHitSound && dwEventHash == CT_FNV("player_hurt")) { SPlayerInfo player; interfaces.engine->GetPlayerInfo(interfaces.engine->GetLocalPlayer(), &player); if (event->GetInt("attacker") == player.m_nUserID) interfaces.engine->ClientCmdUnrestricted("play buttons/arena_switch_press_02"); } - if (dwEventHash == 0xFDAD5FE5 && config.misc.m_bVoteRevealer) + if (dwEventHash == CT_FNV("vote_cast") && config.misc.m_bVoteRevealer) voterevealer(event); return GameEventsOriginal(interfaces.events, event); } VOID WINAPI _PaintTraverse(DWORD dwPanel, BOOLEAN bForceRepaint, BOOLEAN bAllowRepaint) { DWORD drawing = fnv(interfaces.panel->GetPanelName(dwPanel)); - if (drawing == 0xA4A548AF) { // fnv("MatSystemTopPanel") = 0xA4A548AF + if (drawing == CT_FNV("MatSystemTopPanel")) { players(); speclist(); flashreducer(); if (menu_open) RenderMenu(); } - if (drawing == 0x8BE56F81) { // fnv("FocusOverlayPanel") = 0x8BE56F81 + if (drawing == CT_FNV("FocusOverlayPanel")) { interfaces.panel->SetInputMouseState(dwPanel, menu_open); interfaces.panel->SetInputKeyboardState(dwPanel, menu_open && (config.misc.m_bGameKeyboard)); } @@ -835,6 +896,7 @@ VOID LoadHooks() { MH_CreateHook((*(PVOID**)(interfaces.events))[9], &_GameEvents, (PVOID*)&GameEventsOriginal); MH_CreateHook((*(PVOID**)(interfaces.sound))[5], &_EmitSound, (PVOID*)&EmitSoundOriginal); MH_CreateHook((*(PVOID**)(interfaces.client))[38], &_DispatchUserMessage, (PVOID*)&DispatchUserMessageOriginal); + MH_CreateHook((*(PVOID**)(interfaces.client_mode))[18], &_OverrideView, (PVOID*)&OverrideViewOriginal); MH_EnableHook(NULL); } template @@ -842,13 +904,13 @@ T CreateInterface(PVOID m_pModule, LPCSTR m_szInterface) { return ((T(*)(LPCSTR, DWORD))GetProcAddress((HMODULE)m_pModule, "CreateInterface"))(m_szInterface, 0x0); } INT GetLineCount(); -VOID WINAPI Init (HMODULE mod) { +VOID WINAPI Init(HMODULE mod) { while (!GetModuleHandleA("serverbrowser.dll")) Sleep(250); AllocConsole(); SetConsoleTitleA("singlefile: console"); freopen_s((FILE**)stdout, "CONOUT$", "w", stdout); - printf("singlefile v1.3: loading... (compiled with %d lines of code)\n", GetLineCount()); + printf("singlefile v1.4 beta: loading... (compiled with %d lines of code)\n", GetLineCount()); csgo_window = FindWindowA("Valve001", NULL); orig_proc = (WNDPROC)SetWindowLongA(csgo_window, GWLP_WNDPROC, (LONG)Wndproc); client_dll = GetModuleHandleA("client.dll"); @@ -857,7 +919,7 @@ VOID WINAPI Init (HMODULE mod) { PVOID vgui2_dll = GetModuleHandleA("vgui2.dll"); PVOID vstdlib_dll = GetModuleHandleA("vstdlib.dll"); interfaces.engine = CreateInterface(engine_dll, "VEngineClient014"); - if (!strstr(interfaces.engine->GetVersionString(), "1.37.8.7")) + if (!strstr(interfaces.engine->GetVersionString(), "1.37.8.8")) printf("note: you are using an unknown cs:go client version (%s). if you are experiencing crashes, you may need to update offsets. each offset in the source code has it's netvar name, or you can find it on hazedumper.\n", interfaces.engine->GetVersionString()); interfaces.entitylist = CreateInterface(client_dll, "VClientEntityList003"); interfaces.surface = CreateInterface(surface_dll, "VGUI_Surface031"); @@ -866,8 +928,10 @@ VOID WINAPI Init (HMODULE mod) { interfaces.cvar = CreateInterface(vstdlib_dll, "VEngineCvar007"); interfaces.events = CreateInterface(engine_dll, "GAMEEVENTSMANAGER002"); interfaces.sound = CreateInterface(engine_dll, "IEngineSoundClient003"); + interfaces.trace = CreateInterface(engine_dll, "EngineTraceClient004"); interfaces.client_mode = **(IClientModeShared***)((*(DWORD**)(interfaces.client))[0xA] + 0x5); interfaces.globals = **(CGlobalVarsBase***)((*(DWORD**)(interfaces.client))[0xB] + 0xA); + interfaces.input = *(CInput**)((*(DWORD**)(interfaces.client))[0x10] + 0x1); ColoredMsg = (decltype(ColoredMsg))GetProcAddress(GetModuleHandleA("tier0.dll"), "?ConColorMsg@@YAXABVColor@@PBDZZ"); SetupFonts(); LoadHooks(); @@ -876,8 +940,9 @@ VOID WINAPI Init (HMODULE mod) { Sleep(500); MH_DisableHook(NULL); // NULL = all hooks MH_RemoveHook(NULL); + SetWindowLongA(csgo_window, GWLP_WNDPROC, (LONG_PTR)orig_proc); MH_Uninitialize(); - FreeConsole(); + FreeLibraryAndExitThread(mod, 0x1); } BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID pReserved) { if (dwReason == DLL_PROCESS_ATTACH) @@ -886,4 +951,4 @@ BOOL APIENTRY DllMain(HMODULE hModule, DWORD dwReason, LPVOID pReserved) { } INT GetLineCount() { // must be at bottom obviously :P return (__LINE__ + 0x1); -} +} \ No newline at end of file