Skip to content

Commit

Permalink
plugin: use another in combat signature (#4268)
Browse files Browse the repository at this point in the history
The previous one is zero when dying in combat and also during some
cutscenes and transitions.  This is an attempt to use one similar
to the previous 6.0 version.  However, rather than using the writer
which is the "mov [rax+rcx],bl" line which is complicated to
untangled, use a reader instead.

Unfortunately, this reader is on a "cmp byte" line where the pointer
is not at the end of the instruction.  This requires modifying
the SigScan line to handle adjusting for this case, as the scanner
otherwise doesn't know anything about instruction boundaries.

Notes for the future:
```
Combat is a byte, 0x01 when on, 0x00 when out

Start in combat, search for 0x1, hit next scan a bunch
out of combat, search for 0x0, hit next scan a bunch
In combat but untargeted as 0x1
Find green static address, there should be ~2, see what writes to them:

One is (good):
ffxiv_dx11.exe+B61DD0 - 83 FA 68              - cmp edx,68 { 104 }
ffxiv_dx11.exe+B61DD3 - 7D 70                 - jnl
ffxiv_dx11.exe+B61E45
ffxiv_dx11.exe+B61DD5 - 53                    - push rbx
ffxiv_dx11.exe+B61DD6 - 48 83 EC 20           - sub rsp,20 { 32 }
ffxiv_dx11.exe+B61DDA - 48 63 C2              - movsxd  rax,edx
ffxiv_dx11.exe+B61DDD - 41 0FB6 D8            - movzx ebx,r8l
ffxiv_dx11.exe+B61DE1 - 38 1C 08              - cmp [rax+rcx],bl
ffxiv_dx11.exe+B61DE4 - 74 4E                 - je ffxiv_dx11.exe+B61E34
ffxiv_dx11.exe+B61DE6 - 88 1C 08              - mov [rax+rcx],bl

One is (bad):
ffxiv_dx11.exe+737F10 - 48 89 74 24 20        - mov [rsp+20],rsi
ffxiv_dx11.exe+737F15 - 57                    - push rdi
ffxiv_dx11.exe+737F16 - 48 83 EC 20           - sub rsp,20 { 32 }
ffxiv_dx11.exe+737F1A - 0FB6 02               - movzx eax,byte ptr [rdx]
ffxiv_dx11.exe+737F1D - 33 F6                 - xor esi,esi
ffxiv_dx11.exe+737F1F - 89 05 AB048301        - mov
[ffxiv_dx11.exe+1F683D0],eax { (1) }

The "bad" one apparently is zero when you die in combat, but the "good"
one is not.

Searching for what reads from the good one yields a couple of addresses:

(1) "120 hits"
ffxiv_dx11.exe+4C8229 - 83 78 20 00           - cmp dword ptr
[rax+20],00 { 0 }
ffxiv_dx11.exe+4C822D - 75 07                 - jne
ffxiv_dx11.exe+4C8236
ffxiv_dx11.exe+4C822F - 32 C0                 - xor al,al
ffxiv_dx11.exe+4C8231 - 48 83 C4 28           - add rsp,28 { 40 }
ffxiv_dx11.exe+4C8235 - C3                    - ret
ffxiv_dx11.exe+4C8236 - 80 3D FD82AB01 00     - cmp byte ptr
[ffxiv_dx11.exe+1F8053A],00 { (0),0 }
ffxiv_dx11.exe+4C823D - 0F95 C0               - setne al
ffxiv_dx11.exe+4C8240 - 48 83 C4 28           - add rsp,28 { 40 }

(2) "285 hits"
ffxiv_dx11.exe+4CA3EE - 48 8B 3D E38BA401     - mov
rdi,[ffxiv_dx11.exe+1F12FD8] { (1E2DD4FDA50) }
ffxiv_dx11.exe+4CA3F5 - 48 8D 4F 10           - lea rcx,[rdi+10]
ffxiv_dx11.exe+4CA3F9 - BA 22010000           - mov edx,00000122 { 290 }
ffxiv_dx11.exe+4CA3FE - E8 EDF3B9FF           - call
ffxiv_dx11.exe+697F0
ffxiv_dx11.exe+4CA403 - 83 78 20 00           - cmp dword ptr
[rax+20],00 { 0 }
ffxiv_dx11.exe+4CA407 - 74 2D                 - je ffxiv_dx11.exe+4CA436
ffxiv_dx11.exe+4CA409 - 80 3D 2A61AB01 00     - cmp byte ptr
[ffxiv_dx11.exe+1F8053A],00 { (1),0 }

(3) "866 hits"
ffxiv_dx11.exe+B61FCA - 74 04                 - je ffxiv_dx11.exe+B61FD0
ffxiv_dx11.exe+B61FCC - 3B CE                 - cmp ecx,esi
ffxiv_dx11.exe+B61FCE - 74 13                 - je ffxiv_dx11.exe+B61FE3
ffxiv_dx11.exe+B61FD0 - 85 FF                 - test edi,edi
ffxiv_dx11.exe+B61FD2 - 74 04                 - je ffxiv_dx11.exe+B61FD8
ffxiv_dx11.exe+B61FD4 - 3B CF                 - cmp ecx,edi
ffxiv_dx11.exe+B61FD6 - 74 0B                 - je ffxiv_dx11.exe+B61FE3
ffxiv_dx11.exe+B61FD8 - 80 3C 2A  01          - cmp byte ptr
[rdx+rbp],01 { 1 }
```
  • Loading branch information
quisquous authored Apr 13, 2022
1 parent 657219d commit ef11bb3
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 12 deletions.
12 changes: 6 additions & 6 deletions plugin/CactbotEventSource/FFXIVProcess.cs
Original file line number Diff line number Diff line change
Expand Up @@ -375,7 +375,7 @@ internal IntPtr ReadIntPtr(IntPtr addr) {
/// <param name="offset">The offset from the end of the found pattern to read a pointer from the process memory.</param>
/// <param name="rip_addressing">Uses x64 RIP relative addressing mode</param>
/// <returns>A list of pointers read relative to the end of strings in the process memory matching the |pattern|.</returns>
internal List<IntPtr> SigScan(string pattern, int offset, bool rip_addressing) {
internal List<IntPtr> SigScan(string pattern, int pattern_offset, bool rip_addressing, int rip_offset = 0) {
List<IntPtr> matches_list = new List<IntPtr>();

if (pattern == null || pattern.Length % 2 != 0) {
Expand Down Expand Up @@ -412,7 +412,7 @@ internal List<IntPtr> SigScan(string pattern, int offset, bool rip_addressing) {

IntPtr num_bytes_read = IntPtr.Zero;
if (NativeMethods.ReadProcessMemory(process_.Handle, read_start_addr, read_buffer, read_size, ref num_bytes_read)) {
int max_search_offset = num_bytes_read.ToInt32() - pattern_array.Length - Math.Max(0, offset);
int max_search_offset = num_bytes_read.ToInt32() - pattern_array.Length - Math.Max(0, pattern_offset);
// With RIP we will read a 4byte pointer at the |offset|, else we read an 8byte pointer. Either
// way we can't find a pattern such that the pointer we want to read is off the end of the buffer.
if (rip_addressing)
Expand All @@ -434,17 +434,17 @@ internal List<IntPtr> SigScan(string pattern, int offset, bool rip_addressing) {
if (found_pattern) {
IntPtr pointer;
if (rip_addressing) {
Int32 rip_ptr_offset = BitConverter.ToInt32(read_buffer, search_offset + pattern_array.Length + offset);
Int32 rip_ptr_offset = BitConverter.ToInt32(read_buffer, search_offset + pattern_array.Length + pattern_offset);
Int64 pattern_start_game_addr = read_start_addr.ToInt64() + search_offset;
Int64 pointer_offset_from_pattern_start = pattern_array.Length + offset;
Int64 rip_ptr_base = pattern_start_game_addr + pointer_offset_from_pattern_start + 4;
Int64 pointer_offset_from_pattern_start = pattern_array.Length + pattern_offset;
Int64 rip_ptr_base = pattern_start_game_addr + pointer_offset_from_pattern_start + 4 + rip_offset;
// In RIP addressing, the pointer from the executable is 32bits which we stored as |rip_ptr_offset|. The pointer
// is then added to the address of the byte following the pointer, making it relative to that address, which we
// stored as |rip_ptr_base|.
pointer = new IntPtr((Int64)rip_ptr_offset + rip_ptr_base);
} else {
// In normal addressing, the 64bits found with the pattern are the absolute pointer.
pointer = new IntPtr(BitConverter.ToInt64(read_buffer, search_offset + pattern_array.Length + offset));
pointer = new IntPtr(BitConverter.ToInt64(read_buffer, search_offset + pattern_array.Length + pattern_offset));
}
matches_list.Add(pointer);
}
Expand Down
13 changes: 7 additions & 6 deletions plugin/CactbotEventSource/FFXIVProcessIntl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,12 +97,13 @@ public FFXIVProcessIntl(ILogger logger) : base(logger) { }
private static int kCharmapStructOffsetPlayer = 0;

// In combat boolean.
// Variable seems to be set in two places:
// * mov [rax+rcx],bl line (on its own, with a calling function that sets rax(offset) and rcx(base address); the old way)
// * mov [address],eax line (this signature here)
private static String kInCombatSignature = "4889742420574883EC200FB60233F68905";
private static int kInCombatSignatureOffset = 0;
// This address is written to by "mov [rax+rcx],bl" and has three readers.
// This reader is "cmp byte ptr [ffxiv_dx11.exe+????????],00 { (0),0 }"
private static String kInCombatSignature = "803D????????000F95C04883C428";
private static int kInCombatSignatureOffset = -12;
private static bool kInCombatSignatureRIP = true;
// Because this line is a cmp byte line, the signature is not at the end of the line.
private static int kInCombatRipOffset = 1;

// Bait integer.
// Variable is accessed via a cmp eax,[...] line at offset=0.
Expand Down Expand Up @@ -147,7 +148,7 @@ internal override void ReadSignatures() {
job_data_outer_addr_ = IntPtr.Add(p[0], kJobDataOuterStructOffset);
}

p = SigScan(kInCombatSignature, kInCombatSignatureOffset, kInCombatSignatureRIP);
p = SigScan(kInCombatSignature, kInCombatSignatureOffset, kInCombatSignatureRIP, kInCombatRipOffset);
if (p.Count != 1) {
logger_.LogError(Strings.InCombatSignatureFoundMultipleMatchesErrorMessage, p.Count);
} else {
Expand Down

0 comments on commit ef11bb3

Please sign in to comment.