- Game Name
- Europa Universalis IV
- Anticheat
- None
- Tutorial Link
- N/A
- How long you been coding/hacking?
- 3 years
- Coding Language
- C++
Context
The objective here is to call a function that moves the selected army to a specific province. Upon analysing the source code in IDA I have come across this patch of code that should do what I'm trying to accomplish. Through further analysis I came to the conclusion that the variable
v43
stores the address to the target province object. The function I'm trying to call here is f_MoveArmy((v7 + 0x28), v43, v44);
. I know that the first argument always points to the currently selected army, the second argument points to the province object that is going to be used to determine where the currently selected army should move to and the last argument is a boolean that indicates if the path should be appended to the current path or create a new one. So far so good.
C++:
v43 = f_FetchProvinceID(v40, *(v42 + 2 * a2));
if ( v43 )
{
if ( sub_7FF684741D90(v7) )
{
v44 = (*(*v6 + 0x38i64))(v6);// Function for deciding whether to
// append to current path or create new one
f_MoveArmy((v7 + 0x28), v43, v44);
}
else if ( !*(qword_7FF685B06A10 + 304) && *(v43 + 1056) >> 56 )
{
_mm_storeu_si128(&v69, 0i64);
The implementation of previously mentioned is as follows:
C++:
CWorld* pWorld = (CWorld*)(BASE + 0x223D380);
DEBUG("[INFO] Fetching province object for province with ID: 1753\n");
uintptr_t *pProvince = tFetchProvinceID(BASE + 0xed0d0)(pWorld->pMap->pProvinces->pSelection->pNotSure1->pNotSure2->pNotSure3->pAdjacancies, 1753);
DEBUG("[INFO] Fetched province object = %p\n", (void*)pProvince);
DEBUG("[INFO] Moving currently selected army\n");
uintptr_t *currentArmy = (uintptr_t*)((uintptr_t) pWorld->pMap->pProvinces->pSelection + 0x28);
DEBUG("[INFO] Current army selected: %p\n", (void*) currentArmy);
tMoveArmy(BASE + 0xe7f4bb)(currentArmy, pProvince, 0);
DEBUG("[INFO] Army en route\n");
f_MoveArmy((v7 + 0x28), v43, v44)
and compared it to my arguments to see that I'm properly matching the game. No issue there. The only thing that could be iffy is the calling convention, but my assumption is that most x64 functions use fastcall as the calling convention. Feel free to comment on this.ISSUE
The error is referring to the following line:Exception thrown at 0x00007FF683E00F00 in eu4.exe: 0xC0000005: Access violation reading location 0xFFFFFFFFFFFFFFFF.
7FF683E00F00 - 0F29 74 24 30 - movaps [rsp+30], xmm6
. What I've noticed is that whenever the game executes this line the register always looks like this:
whereas when40733B9D0DA7886F
f_MoveArmy((v7 + 0x28), v43, v44)
is ran by me it looks like this
. I've also changed the XMM6 register to different values both when that line is executed by the game and me, and there's no difference. If the game executes that line then no matter what result resides inside XMM6 it will always go through. When000000004200AB5D
f_MoveArmy((v7 + 0x28), v43, v44)
is being executed by the game then that XMM6 register value is already there BEFORE it runs the function. This makes me wonder if I should climb the stack a couple of levels so that when I execute that function it would set the XMM6 as well as run f_MoveArmy((v7 + 0x28), v43, v44)
.Few things to keep in mind, this error occurs several layers inside
f_MoveArmy((v7 + 0x28), v43, v44)
and not in the function itself.
C++:
__int64 v44; // [rsp+98h] [rbp-68h]
__int64 v45; // [rsp+A0h] [rbp-60h]
char v46; // [rsp+B0h] [rbp-50h]
char *v47; // [rsp+E8h] [rbp-18h]
__int64 v48; // [rsp+F0h] [rbp-10h]
__int64 v49; // [rsp+130h] [rbp+30h]
v48 = -2i64;
v3 = a3;
v4 = a2;
v5 = 0;
v44 = 0i64;
v45 = 0i64;
v43 = &off_7FF685309220;
v6 = *a1;
if ( *a1 )
{
do
{
v7 = *v6;
if ( (*(**v6 + 0x38i64))(*v6, &v43, v4, v3) )
{
v5 |= (*(*v7 + 0x30i64))(v7, v4, v3);
v8 = HIDWORD(v45);
}
else
{
v8 = HIDWORD(v45);
v5 = HIDWORD(v45) != 0;
}
v6 = v6[2];
}
while ( v6 );
if ( v8 == 1 )
f_MoveArmy((v7 + 0x28), v43, v44)
function. The line v5 |= (*(*v7 + 0x30i64))(v7, v4, v3)
is where it crashes. We go deeper.
C++:
if ( dword_7FF685C2DD00 == -1 )
{
sub_7FF6839A8CF0(&qword_7FF685AE41C0, "army_move", 9ui64);
atexit(sub_7FF685143AA0);
Init_thread_footer(&dword_7FF685C2DD00);
}
}
if ( qword_7FF685AE41D8 >= 0x10 )
v86 = qword_7FF685AE41C0;
}
LABEL_258:
v95 = sub_7FF684BEE840(**(qword_7FF685AFD668 + 840), v86, 1);
f_AudioOnMarch(v95, v96, 1.0);
return v144;
}
f_AudioOnMarch(v95, v96, 1.0)
is where it crashes.Assembly of it:
7FF683E00EF0 - 40 53 - push rbx
7FF683E00EF2 - 48 83 EC 40 - sub rsp,40
7FF683E00EF6 - 48 8B 05 6BC7CF01 - mov rax,[7FF685AFD668]
7FF683E00EFD - 48 8B D9 - mov rbx,rcx
7FF683E00F00 - 0F29 74 24 30 - movaps [rsp+30],xmm6
7FF683E00F05 - 48 8B D3 - mov rdx,rbx
7FF683E00F08 - 0F28 F2 - movaps xmm6,xmm2
7FF683E00F0B - 48 8B 88 48030000 - mov rcx,[rax+00000348]
7FF683E00F12 - 48 8B 09 - mov rcx,[rcx]
7FF683E00F15 - E8 A6DDDE00 - call 7FF684BEECC0
7FF683E00F1A - 48 8B 05 47C7CF01 - mov rax,[7FF685AFD668]
7FF683E00F21 - 0F57 C0 - xorps xmm0,xmm0
7FF683E00F24 - 0F28 DE - movaps xmm3,xmm6
7FF683E00F27 - F3 0F11 44 24 20 - movss [rsp+20],xmm0
7FF683E00F2D - 45 33 C0 - xor r8d,r8d
7FF683E00F30 - 48 8B 90 48030000 - mov rdx,[rax+00000348]
7FF683E00F37 - 48 8B 0A - mov rcx,[rdx]
7FF683E00F3A - 48 8B D3 - mov rdx,rbx
7FF683E00F3D - E8 CE1EDF00 - call 7FF684BF2E10
7FF683E00F42 - 0F28 74 24 30 - movaps xmm6,[rsp+30]
7FF683E00F47 - 48 83 C4 40 - add rsp,40
With all this being said, any help would be appreciated, thanks!
Last edited: