From 16e450f3baaf5ceced43b412903e7499b8041d80 Mon Sep 17 00:00:00 2001 From: jabbink Date: Wed, 1 Mar 2023 10:25:38 +0100 Subject: [PATCH 1/4] Remove elevated UAC permission --- FLCompanion.vcxproj | 2 -- res/FLCompanion.manifest | 20 -------------------- 2 files changed, 22 deletions(-) diff --git a/FLCompanion.vcxproj b/FLCompanion.vcxproj index d950cec..0c1c782 100644 --- a/FLCompanion.vcxproj +++ b/FLCompanion.vcxproj @@ -85,8 +85,6 @@ true Windows wWinMainCRTStartup - RequireAdministrator - false diff --git a/res/FLCompanion.manifest b/res/FLCompanion.manifest index f158916..c335e3f 100644 --- a/res/FLCompanion.manifest +++ b/res/FLCompanion.manifest @@ -7,24 +7,4 @@ - - - - - - - - - From 00da2445555d2659b6979dbc5e8254ae81694b25 Mon Sep 17 00:00:00 2001 From: jabbink Date: Wed, 1 Mar 2023 18:05:07 +0100 Subject: [PATCH 2/4] Open process with TlHelp32 get base address of mprep.dll --- DynEconDlg.cpp | 85 +++++++++++++++++++++++++++----------------------- DynEconDlg.h | 3 +- 2 files changed, 48 insertions(+), 40 deletions(-) diff --git a/DynEconDlg.cpp b/DynEconDlg.cpp index 10f704e..90e847a 100644 --- a/DynEconDlg.cpp +++ b/DynEconDlg.cpp @@ -2,16 +2,14 @@ // #include "stdafx.h" -#include "FLCompanion.h" #include "FLCompanionDlg.h" #include "DynEconDlg.h" #include "Base.h" -#include "IniFile.h" #include "Datas.h" #include "System.h" #include #include -#include "ScopedPtr.h" +#include #pragma comment(lib, "psapi.lib") #ifdef _DEBUG @@ -231,57 +229,67 @@ LPVOID CGameInspect::TreeFind(FlTree& tree, DWORD id) if (node._Parent == nodeNil) return NULL; return TreeFindRecurse(node._Parent, id, nodeNil); } -DWORD cb = 0; -HANDLE OpenGameProcess() + +HANDLE OpenGameProcess(DWORD* procID) { - if (cb == 0) + const HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (snapshot && snapshot != INVALID_HANDLE_VALUE) { - while (true) + PROCESSENTRY32 pe; + pe.dwSize = sizeof(pe); + if (Process32First(snapshot, &pe)) { - DWORD lpcbNeeded_; - std::unique_ptr _dwProcessIDs(new DWORD[cb]); - if (EnumProcesses(_dwProcessIDs.get(), cb, &lpcbNeeded_) == FALSE) - return NULL; - if (cb == lpcbNeeded_) - { - Log(L"Searching additional processes: %d", cb); - cb += 256; - } - else + do { - break; - } + if (!wcscmp(pe.szExeFile, L"Freelancer.exe")) + { + CloseHandle(snapshot); + *procID = pe.th32ProcessID; + return OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_SET_INFORMATION, FALSE, *procID); + } + } while (Process32Next(snapshot, &pe)); } } - DWORD lpcbNeeded; - std::unique_ptr dwProcessIDs(new DWORD[cb]); - if (EnumProcesses(dwProcessIDs.get(), cb, &lpcbNeeded) == FALSE) - return NULL; - lpcbNeeded /= sizeof(DWORD); - for (size_t idx = 0; idx < lpcbNeeded; idx++) - { - DWORD dwProcessID = dwProcessIDs[idx]; + return nullptr; +} - HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ|PROCESS_SET_INFORMATION, FALSE, dwProcessID); +void* GetModuleBase(const wchar_t* ModuleName, DWORD procID) +{ + MODULEENTRY32 ModuleEntry = { 0 }; + const HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE | TH32CS_SNAPMODULE32, procID); - if (!hProcess) hProcess = OpenProcess(PROCESS_QUERY_INFORMATION|PROCESS_VM_READ, FALSE, dwProcessID); - if (hProcess) + if (!snapshot) return nullptr; + + ModuleEntry.dwSize = sizeof(ModuleEntry); + + if (!Module32First(snapshot, &ModuleEntry)) return nullptr; + + do + { + if (!wcscmp(ModuleEntry.szModule, ModuleName)) { - TCHAR filename[MAX_PATH]; - if (GetModuleBaseName(hProcess, NULL, filename, _countof(filename))) - if (lstrcmpi(filename, L"Freelancer.exe") == 0) - return hProcess; - CloseHandle(hProcess); + CloseHandle(snapshot); + return ModuleEntry.modBaseAddr; } - } - return NULL; + } while (Module32Next(snapshot, &ModuleEntry)); + + CloseHandle(snapshot); + return nullptr; } int CGameInspect::DoTask(DWORD flags) { if (g_triggeredImport) { - m_hflProcess = OpenGameProcess(); + if (m_hflProcess != nullptr) + { + CloseHandle(m_hflProcess); + m_hflProcess = nullptr; + m_mpRepBase = nullptr; + } + DWORD procId; + m_hflProcess = OpenGameProcess(&procId); + m_mpRepBase = GetModuleBase(L"mprep.dll", procId); static BOOL signalAccessDenied = true; if (!m_hflProcess) { @@ -292,7 +300,6 @@ int CGameInspect::DoTask(DWORD flags) } return 0; } - HANDLE hflProcess = m_hflProcess; // Leak! closehandle on function return signalAccessDenied = true; DWORD dwPriorityClass = GetPriorityClass(m_hflProcess); SetPriorityClass(m_hflProcess, IDLE_PRIORITY_CLASS); diff --git a/DynEconDlg.h b/DynEconDlg.h index 747d420..374de2e 100644 --- a/DynEconDlg.h +++ b/DynEconDlg.h @@ -35,9 +35,10 @@ class CGameInspect LPVOID TreeFindRecurse(FlNode* nodePtr, DWORD id, FlNode* nodeNil); LPVOID TreeFind(FlTree& tree, DWORD id); private: - HANDLE m_hflProcess; + HANDLE m_hflProcess = nullptr; CBase* m_base; CMap m_idGoodMap; + void* m_mpRepBase = nullptr; }; //{{AFX_INSERT_LOCATION}} From adde1d74a4844e9e8081dbe6460fe774c0f30c8b Mon Sep 17 00:00:00 2001 From: jabbink Date: Wed, 1 Mar 2023 18:20:05 +0100 Subject: [PATCH 3/4] Add reputation menu item --- DynEconDlg.h | 2 +- FLCompanion.rc | 4 ++-- FLCompanionDlg.cpp | 6 +++--- resource.h | 3 ++- 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/DynEconDlg.h b/DynEconDlg.h index 374de2e..086b1d2 100644 --- a/DynEconDlg.h +++ b/DynEconDlg.h @@ -24,7 +24,7 @@ class CGameInspect IMPORT_PRICES = 0x01, IMPORT_CREDITS = 0x02, IMPORT_CARGOHOLD = 0x04, - //IMPORT_FACTIONS = 0x08, + IMPORT_FACTIONS = 0x08, }; int DoTask(DWORD flags); private: diff --git a/FLCompanion.rc b/FLCompanion.rc index 8ef322b..0b55d85 100644 --- a/FLCompanion.rc +++ b/FLCompanion.rc @@ -294,8 +294,7 @@ BEGIN PUSHBUTTON "Clear all",IDC_CLEAR_ALL_SYSTEMS,60,157,50,15 GROUPBOX "Exclude base by factions:",IDC_STATIC,125,15,110,160 RTEXT "Select Faction ID : ",IDC_STATIC,63,3,60,12 - COMBOBOX IDC_FACTION_ID, 125, 0, 150, 12, CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP - //LTEXT "[disabled]",IDC_STATIC,125,3,50,12 + COMBOBOX IDC_FACTION_ID,125,0,150,12,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP LISTBOX IDC_FACTIONS_LIST,130,25,100,131,LBS_SORT | LBS_OWNERDRAWFIXED | LBS_HASSTRINGS | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP PUSHBUTTON "Check all",IDC_CHECK_ALL_FACTIONS,130,157,50,15 PUSHBUTTON "Clear all",IDC_CLEAR_ALL_FACTIONS,180,157,50,15 @@ -503,6 +502,7 @@ BEGIN MENUITEM "Bases prices (dynamic economy)", ID_GAME_IMPORT_PRICES, CHECKED MENUITEM "Your credits (max investment)", ID_GAME_IMPORT_CREDITS, CHECKED MENUITEM "Your ship's cargo hold size", ID_GAME_IMPORT_CARGOHOLD, CHECKED + MENUITEM "Your reputation (exclude hostile factions)", ID_GAME_IMPORT_FACTIONS, CHECKED MENUITEM SEPARATOR MENUITEM "Check/Uncheck all", ID_GAME_IMPORT_CHECKALL MENUITEM "About this feature...", ID_GAME_IMPORT_ABOUT diff --git a/FLCompanionDlg.cpp b/FLCompanionDlg.cpp index 8dd89e1..0b3a4d9 100644 --- a/FLCompanionDlg.cpp +++ b/FLCompanionDlg.cpp @@ -155,9 +155,9 @@ BEGIN_MESSAGE_MAP(CFLCompanionDlg, CDialog) ON_UPDATE_COMMAND_UI(ID_MOD_INFO, OnUpdateModInfo) ON_BN_CLICKED(IDC_JUMPS, OnJumps) ON_BN_CLICKED(IDC_OPENMAP, OnMap) - ON_UPDATE_COMMAND_UI_RANGE(ID_GAME_IMPORT_PRICES, ID_GAME_IMPORT_CARGOHOLD, OnUpdateGameImport) + ON_UPDATE_COMMAND_UI_RANGE(ID_GAME_IMPORT_PRICES, ID_GAME_IMPORT_FACTIONS, OnUpdateGameImport) ON_COMMAND(ID_GAME_IMPORT_ABOUT, OnGameImportAbout) - ON_COMMAND_RANGE(ID_GAME_IMPORT_PRICES, ID_GAME_IMPORT_CARGOHOLD, OnGameImport) + ON_COMMAND_RANGE(ID_GAME_IMPORT_PRICES, ID_GAME_IMPORT_FACTIONS, OnGameImport) ON_COMMAND(ID_GAME_IMPORT_CHECKALL, OnGameImportCheckall) ON_UPDATE_COMMAND_UI(ID_GAME_IMPORT_CHECKALL, OnUpdateGameImportCheckall) ON_WM_ACTIVATEAPP() @@ -2010,7 +2010,7 @@ void CFLCompanionDlg::OnGameImportCheckall() if (m_importFromGame) m_importFromGame = 0; else - m_importFromGame = (1<<(ID_GAME_IMPORT_CARGOHOLD-ID_GAME_IMPORT_PRICES+1))-1; + m_importFromGame = (1<<(ID_GAME_IMPORT_FACTIONS-ID_GAME_IMPORT_PRICES+1))-1; theApp.WriteProfileInt(L"Settings", L"ImportFromGame", m_importFromGame); g_triggeredImport = true; ImportFromGame(); diff --git a/resource.h b/resource.h index a457ad4..16e906e 100644 --- a/resource.h +++ b/resource.h @@ -134,6 +134,7 @@ #define ID_GAME_IMPORT_PRICES 32800 #define ID_GAME_IMPORT_CREDITS 32801 #define ID_GAME_IMPORT_CARGOHOLD 32802 +#define ID_GAME_IMPORT_FACTIONS 32803 #define ID_VIEW_LOG 32811 #define ID_CLIENTREFRESH 32812 #define IDC_AVOIDGATES 32813 @@ -148,7 +149,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_3D_CONTROLS 1 #define _APS_NEXT_RESOURCE_VALUE 141 -#define _APS_NEXT_COMMAND_VALUE 32812 +#define _APS_NEXT_COMMAND_VALUE 32818 #define _APS_NEXT_CONTROL_VALUE 1068 #define _APS_NEXT_SYMED_VALUE 114 #endif From e5d60656a682d7ddfd3fc23de18983f8def02e1a Mon Sep 17 00:00:00 2001 From: jabbink Date: Wed, 1 Mar 2023 18:20:29 +0100 Subject: [PATCH 4/4] Read reputation and automatically exclude hostile factions --- Datas.cpp | 2 +- DynEconDlg.cpp | 107 +++++++++++++++++++++++++++++-------------------- 2 files changed, 64 insertions(+), 45 deletions(-) diff --git a/Datas.cpp b/Datas.cpp index 3041268..8a5e10b 100644 --- a/Datas.cpp +++ b/Datas.cpp @@ -1179,7 +1179,7 @@ BOOL LoadAppDatas(CWnd *wnd) GOODS_COUNT = 0; EQUIP_COUNT = 0; - //InitializeHashTable(); + InitializeHashTable(); DetectMod(); g_resourceProvider.Init(g_flAppPath); diff --git a/DynEconDlg.cpp b/DynEconDlg.cpp index 90e847a..1468761 100644 --- a/DynEconDlg.cpp +++ b/DynEconDlg.cpp @@ -133,7 +133,11 @@ struct FlFactionInfo #define FLCREDITS_ADDR 0x00673364 #define FLPLAYERSHIP_ADDR 0x0067337C #define FLFACTIONS_ADDR 0x064018EC -#define FLPLAYERS_ADDR 0x064018C4 //0x064018C4 // FlTree des joueurs +#define FLPLAYERS_ADDR 0x064018C4 + +#define MPREP_REPCOUNT_ADDR 0x303C +#define MPREP_REP_ADDR 0x3034 + // 0x64018D8 = currentNode #define READFLMEM(structure,addr) if (!ReadProcessMemory(m_hflProcess, LPCVOID(addr), &structure, sizeof(structure), NULL)) return 0; #define READFLPTR(ptr,addr,size) if (!ReadProcessMemory(m_hflProcess, LPCVOID(addr), LPVOID(ptr), size, NULL)) return 0; @@ -378,63 +382,78 @@ int CGameInspect::DoTask(DWORD flags) } } } -#if 0 - if (true) //(flags & IMPORT_FACTIONS) + if (flags & IMPORT_FACTIONS) { - UINT changed = 0; CMap idFactionMap; UINT i; for (i = 0; i < FACTIONS_COUNT; i++) idFactionMap[FLFactionHash(g_factions[i].m_nickname)] = &g_factions[i]; - FlTree factionsTree; - READFLMEM(factionsTree, FLFACTIONS_ADDR); + FlTree playersTree{}; + READFLMEM(playersTree, FLPLAYERS_ADDR) + + FlRep* reps = nullptr; + unsigned int count = 0; + if (m_mpRepBase != nullptr) + { + READFLMEM(count, static_cast(m_mpRepBase) + MPREP_REPCOUNT_ADDR) + unsigned int bytes = count * sizeof(FlRep); + reps = static_cast(malloc(bytes)); + DWORD repsAddress; + READFLMEM(repsAddress, static_cast(m_mpRepBase) + MPREP_REP_ADDR) + READFLPTR(reps, repsAddress, bytes) + } + else + { + DWORD player_id; + READFLMEM(player_id, FLCLIENTID_ADDR) + + LPVOID player_ptr = TreeFind(playersTree, player_id); + if (player_ptr) + { + FlPlayer player{}; + READFLMEM(player, player_ptr) + unsigned int bytes = reinterpret_cast(player._repsEnd) - reinterpret_cast(player._repsBegin); + count = bytes / sizeof(FlRep); + reps = static_cast(malloc(bytes)); + READFLPTR(reps, player._repsBegin, bytes) + } + } - LPBYTE ptr; - READFLMEM(ptr, 0x61e0260); - DWORD player_id; - int oset = 0; - player_id = 0; - while (player_id==0) - { - READFLMEM(player_id, ptr + (4+ oset)); - oset += 4; + if (reps != nullptr) + { + UINT removedAvoids = 0; + UINT addedAvoids = 0; + + for (i = 0; i < FACTIONS_COUNT; i++) { + if (g_factions[i].m_avoid) { + g_factions[i].m_avoid = false; + removedAvoids++; } + } - FlTree playersTree; - READFLMEM(playersTree, FLPLAYERS_ADDR); - FlNode playerNode; - READFLMEM(playerNode, playersTree._Head); - READFLMEM(playerNode, playerNode._Parent); - LPVOID playerPtr = TreeFind(playersTree, 1); - if (playerPtr) - { - FlPlayer player; - READFLMEM(player, playerPtr); - int count = player._repsEnd-player._repsBegin; - //CScopedArray reps = new FlRep[count]; - //READFLPTR(reps,player._repsBegin, count*sizeof(FlRep)); - for (int index = 0; index < count; index++) - //if (reps[index]._rep <= -0.6) - { - //CFaction *faction = idFactionMap[reps[index]._faction_id]; - ////if (!faction->m_avoid) - { - changed++; - //faction->m_avoid = true; - } - } - } - if (changed) + for (unsigned int index = 0; index < count; index++) { + if (reps[index]._rep <= -0.55f) { - Log(L"Imported from game: %d factions to avoid", changed); - g_mainDlg->Recalc(g_mainDlg->RECALC_PATHS); + CFaction *faction = idFactionMap[reps[index]._faction_id]; + if (faction != nullptr) + { + addedAvoids++; + faction->m_avoid = true; + } } - + } + + if (removedAvoids > 0 || addedAvoids > 0) + { + Log(L"Imported from game: %d factions no longer avoided, %d new factions to avoid", removedAvoids, addedAvoids); + g_mainDlg->Recalc(g_mainDlg->RECALC_PATHS); + } + free(reps); + } } -#endif SetPriorityClass(m_hflProcess, dwPriorityClass); } return 1;