Add HookAnalyzer Logic#20
Conversation
|
Can you elaborate on what this does? |
|
OK let me explain the rest flags. Dry Run Mode
|
| bool HookAnalyzer::ReportLOG(bool ByAddr, bool ByLib) | ||
| { | ||
| constexpr auto const VersionString = "SyringeEx " SYRINGEEX_VER_TEXT ", based on Syringe 0.7.2.0"; | ||
|
|
||
| FileHandle File = FileHandle(fopen("HookAnalysis.log", "w")); | ||
| if (!File)return false; | ||
| fprintf(File, "%s will analyze the specified hooks.\n", VersionString); | ||
| if (ByAddr) | ||
| { | ||
| fputs("========================\n", File); | ||
| fputs("By Hook Position: (Execution order for each address)\n", File); | ||
| for (auto& p : ByAddress) | ||
| { | ||
| fprintf(File, "At %08X : \n", p.first); | ||
| for (auto v : p.second) | ||
| { | ||
| //fprintf(File, "Hook\"%s, Relative to\"%s\", From\"%s\", %d Bytes Overridden ,Priority %d, Sub Priority \"%s\"\n", v.Proc.c_str(), v.RelLib.c_str(), v.Lib.c_str(), v.Len, v.Priority, v.SubPriority.c_str()); | ||
| fprintf(File, "Hook\"%s, From\"%s\", %d Bytes Overridden\n", v.Proc.c_str(), v.Lib.c_str(), v.Len); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (ByLib) | ||
| { | ||
| fputs("========================\n", File); | ||
| fputs("By Hook Source: \n", File); | ||
| for (auto& p : ByLibName) | ||
| { | ||
| fprintf(File, "Analyzing DLL : \"%s\" ……\n", p.first.c_str()); | ||
| for (auto v : p.second) | ||
| { | ||
| //fprintf(File, "Hook\"%s, Relative to\"%s\", From\"%s\", %d Bytes Overridden ,Priority %d, Sub Priority \"%s\"\n", v.Proc.c_str(), v.RelLib.c_str(), v.Lib.c_str(), v.Len, v.Priority, v.SubPriority.c_str()); | ||
| fprintf(File, "Hook\"%s, From\"%s\", %d Bytes Overridden\n", v.Proc.c_str(), v.Lib.c_str(), v.Len); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| fputs("========================\n", File); | ||
| fprintf(File, "%s : Complete.\n", VersionString); | ||
| return true; | ||
| } |
There was a problem hiding this comment.
why do we need to write this in a separate log other than syringe.log?
| bool HookAnalyzer::GenerateINJ() | ||
| { | ||
| //Log::WriteLine(ExecutableDirectoryPath().c_str()); | ||
| auto path = ExecutableDirectoryPath() + "\\INJ"; | ||
| auto pp = CreateDirectoryA(path.c_str(), NULL); | ||
| if (pp || GetLastError() == ERROR_ALREADY_EXISTS) | ||
| { | ||
| //Log::WriteLine((path + "\\").c_str()); | ||
| for (auto& p : ByLibNameEx) | ||
| { | ||
| //Log::WriteLine((path + "\\" + p.first).c_str()); | ||
| FileHandle File = FileHandle(fopen((path + "\\" + p.first + ".inj").c_str(), "w")); | ||
| if (!File)return false; | ||
| for (auto& h : p.second) | ||
| { | ||
| if (!h.RelLib.empty()) | ||
| fputs(";Relative Hook Found ,failed to Generate", File); | ||
| else if (!h.SubPriority.empty()) | ||
| fprintf(File, "%X=%s,%X,%d,%s\n", h.Addr, h.Proc.c_str(), h.Len, h.Priority, h.SubPriority.c_str()); | ||
| else if (h.Priority == DefaultPriority) | ||
| fprintf(File, "%X=%s,%X\n", h.Addr, h.Proc.c_str(), h.Len); | ||
| else | ||
| fprintf(File, "%X=%s,%X,%d\n", h.Addr, h.Proc.c_str(), h.Len, h.Priority); | ||
| } | ||
| } | ||
| return true; | ||
| } | ||
| return false; | ||
| } No newline at end of file |
There was a problem hiding this comment.
what's the INJ generation for? is there some other tool that uses INJ files, or what's the premise for it?
| static constexpr std::string_view GENERATEINJ_FLAG = "--generate-inj"; | ||
| static constexpr std::string_view REPORT_LOG_FLAG = "--report-log"; | ||
| static constexpr std::string_view REPORT_JSON_FLAG = "--report-json"; | ||
| static constexpr std::string_view DETECT_CONFLICT_FLAG = "--detect-conflict"; |
There was a problem hiding this comment.
is it a slow operation? is there a reason to make it optional?
I would expect the conflict detection to be always on and outputting to syringe.log
| bool HookAnalyzer::ReportLOG(bool ByAddr, bool ByLib) | ||
| { | ||
| constexpr auto const VersionString = "SyringeEx " SYRINGEEX_VER_TEXT ", based on Syringe 0.7.2.0"; | ||
|
|
||
| FileHandle File = FileHandle(fopen("HookAnalysis.log", "w")); | ||
| if (!File)return false; | ||
| fprintf(File, "%s will analyze the specified hooks.\n", VersionString); | ||
| if (ByAddr) | ||
| { | ||
| fputs("========================\n", File); | ||
| fputs("By Hook Position: (Execution order for each address)\n", File); | ||
| for (auto& p : ByAddress) | ||
| { | ||
| fprintf(File, "At %08X : \n", p.first); | ||
| for (auto v : p.second) | ||
| { | ||
| //fprintf(File, "Hook\"%s, Relative to\"%s\", From\"%s\", %d Bytes Overridden ,Priority %d, Sub Priority \"%s\"\n", v.Proc.c_str(), v.RelLib.c_str(), v.Lib.c_str(), v.Len, v.Priority, v.SubPriority.c_str()); | ||
| fprintf(File, "Hook\"%s, From\"%s\", %d Bytes Overridden\n", v.Proc.c_str(), v.Lib.c_str(), v.Len); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| if (ByLib) | ||
| { | ||
| fputs("========================\n", File); | ||
| fputs("By Hook Source: \n", File); | ||
| for (auto& p : ByLibName) | ||
| { | ||
| fprintf(File, "Analyzing DLL : \"%s\" ……\n", p.first.c_str()); | ||
| for (auto v : p.second) | ||
| { | ||
| //fprintf(File, "Hook\"%s, Relative to\"%s\", From\"%s\", %d Bytes Overridden ,Priority %d, Sub Priority \"%s\"\n", v.Proc.c_str(), v.RelLib.c_str(), v.Lib.c_str(), v.Len, v.Priority, v.SubPriority.c_str()); | ||
| fprintf(File, "Hook\"%s, From\"%s\", %d Bytes Overridden\n", v.Proc.c_str(), v.Lib.c_str(), v.Len); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| fputs("========================\n", File); | ||
| fprintf(File, "%s : Complete.\n", VersionString); | ||
| return true; | ||
| } |
There was a problem hiding this comment.
does this output all hooks or only conflicts? I would expect only conflicts to be outputted, and I feel like they should always be sorted by address? not sure how the by DLL one functions, since the conflicts can (and will) be cross-dll. do we even need any sorting modes?
There was a problem hiding this comment.
OK let me explain :
Sorry to say that I did not redesign the hook analysis module so there might be something that didnt meet your expectations.
If you think these changes are needed, I will make a new commit for it.
Another thing is that what JSON library should we import ?
the NDJSON format output won't be there until a JSON library is chosen.
Details :
1.
why do we need to write this in a separate log other than syringe.log?
of course we can if you think this is necessary. If you want a why, it is just as it was.
If you think it should be in Syringe.log, we can change the target.
2.
what's the INJ generation for? is there some other tool that uses INJ files, or what's the premise for it?
For there was a INJ generation function.
If you think this is meaningless, a removal will be considered.
3.
is it a slow operation? is there a reason to make it optional?
I would expect the conflict detection to be always on and outputting to syringe.log
I'm sorry to say that again but it is optional because it was optional.
It's OK to let it enabled all the time.
4.
does this output all hooks or only conflicts? I would expect only conflicts to be outputted, and I feel like they should always be sorted by address? not sure how the by DLL one functions, since the conflicts can (and will) be cross-dll. do we even need any sorting modes?
this ReportLOG function is not the thing that detects conflicts.
there should be flags to control the range that ReportLOG outputs, however it isn't here.
" by DLL "just output these hooks DLL after DLL.
Sorting modes are not currently configurable.
There was a problem hiding this comment.
about --report-log :
Another thing is that TaranDahl's SKILL.md still depends on the HookAnalysis.log now and we need the adjusted logic functions similarly when rewritting it.
It enumerates hooks in the configured range. (still cannot configure it in this PR)
(an output format or output target change is OK)
about --detect-conflict :
Now the result is written in Syringe.log.
also you can change it's format and target.
It detects all cross-dll hook conflicts.
There was a problem hiding this comment.
No need to be sorry, it's alright.
On 1 and 3 let's do it then (though I wonder if having it always on will impact startup time a lot, have you checked it?);
on 2: I mean I don't mind it in principle, I just wonder what's the specific use case?
on 4, sorry, I didn't understand what you mean. I was asking about the ByAddr and ByLib function, and I was also wondering whether the output is only conflicts or something else too.
Context
See Phobos PR #2201
NOTE
all the flags are temporarily stored in the SyringeDebugger class, and maybe we need to move it to another subclass.
HookAnalyzer class is moved from SyringeIH here as it was except a few translations.
HookAnalyzer::ReportNDJSON is not yet implemented until we import a JSON library,and I place the function here just as Kerbiter's wish.
some of the flags are set to default because the coupled components are not here in SyringeEx, so now every hook are set to be shown in the hook analysis.
New & Enhanced Logic :
Components (1) :
HookAnalyzer
New Flags (8) :
Launch Arguments (8) :
--dryrun : run syringe without launching game.
--generate-inj : generate INJ files and place them in .\INJ folder
--report-log : generate a HookAnalysis.log, as it functions in SyringeIH but in English
--no-by-address : Disable the "By Address" part in HookAnalysis.log.
--no-by-library : Disable the "By Library" part in HookAnalysis.log.
--report-json : generate a HookAnalysis.json TODO
--detect-conflict : Detect hook conflict and output to Syringe.log, as it functions in SyringeIH but in English
--show-hook-conflict-popup : Show a popup when --detect-conflict is enabled and a conflict is detected.
In the dry run mode all other 7 flags are available.