/
/
dllmain.cpp : 定义 DLL 应用程序的入口点。
void DllEntry();
char
*
GetName(uintptr_t
Object
);
BOOL
APIENTRY DllMain( HMODULE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
AllocConsole();
freopen(
"CON"
,
"w"
, stdout);
CreateThread(
0
,
0
, (LPTHREAD_START_ROUTINE)DllEntry,
0
,
0
,
0
);
break
;
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break
;
}
return
TRUE;
}
uintptr_t GameBase{
0
};
uintptr_t BotPosPtr{
0
};
const char BotName[
10
]
=
"BotPawn_C"
;
struct Array
{
uintptr_t
*
ArrayEntry;
int
Count;
};
struct Vec3
{
float
x;
float
y;
float
z;
};
Vec3
*
GetPos(uintptr_t
Object
);
void Hook();
void DllEntry()
{
GameBase
=
reinterpret_cast<uintptr_t>(GetModuleHandleW(L
"ShooterClient.exe"
));
Hook();
while
(true)
{
auto UOjbectArrayPtr
=
*
(uintptr_t
*
)(GameBase
+
0x2F71060
);
if
(!UOjbectArrayPtr)
continue
;
UOjbectArrayPtr
=
*
(uintptr_t
*
)(UOjbectArrayPtr
+
0x30
);
if
(!UOjbectArrayPtr)
continue
;
auto UOjbectArray
=
*
(Array
*
)(UOjbectArrayPtr
+
0x98
);
/
/
自己定义一个结构
for
(
int
index
=
0
; index < UOjbectArray.Count; index
+
+
)
{
auto
Object
=
UOjbectArray.ArrayEntry[index];
if
(
Object
)
{
auto NamePtr
=
GetName(
Object
);
if
(NamePtr)
{
if
(!strcmp(NamePtr,
"BotPawn_C"
))
{
auto pPos
=
GetPos(
Object
);
memcpy((void
*
)BotPosPtr, pPos, sizeof(Vec3));
}
/
/
printf(
"Ptr:%llx Name:%s\n"
,
Object
, NamePtr);
}
}
}
}
}
void Hook()
{
uint8_t BulletShellCode[]
=
"\x81\xC1\x6B\x63\x19\x36\x8B\xC1\x25\xFF\xFF\x7F\x00\x0D\x00\x00\x80\x3F\x89\x85\x00\x01\x00\x00\x50\x51\x48\xB8\x66\x66\x66\x66\x66\x66\x36\x12\x48\x8B\x08\x48\x89\x4C\x24\x70\x8B\x48\x08\x89\x4C\x24\x78\x59\x58\x68\x78\x56\x34\x12\xC7\x44\x24\x04\x34\x12\x00\x00\xC3"
;
uint8_t JmpShellCode[]
=
"\x68\x78\x56\x34\x12\xC7\x44\x24\x04\x34\x12\x00\x00\xC3"
;
BotPosPtr
=
(uintptr_t)malloc(sizeof(Vec3));
auto HookMemory
=
(uintptr_t)VirtualAlloc(
0
,
0x1000
,
0x1000
, PAGE_EXECUTE_READWRITE);
if
(BotPosPtr && HookMemory)
{
auto HookAddress
=
GameBase
+
0x51C162
;
auto ReturnAddress
=
GameBase
+
0x51C17A
;
*
(uintptr_t
*
)(BulletShellCode
+
0x1C
)
=
BotPosPtr;
*
(uint32_t
*
)(BulletShellCode
+
0x36
)
=
*
(uint32_t
*
)(&ReturnAddress);
*
(uint32_t
*
)(BulletShellCode
+
0x3E
)
=
*
(uint32_t
*
)((uint64_t)(&ReturnAddress)
+
4
);
memcpy((void
*
)HookMemory, BulletShellCode, sizeof(BulletShellCode)
-
1
);
*
(uint32_t
*
)(JmpShellCode
+
0x1
)
=
*
(uint32_t
*
)(&HookMemory);
*
(uint32_t
*
)(JmpShellCode
+
0x9
)
=
*
(uint32_t
*
)((uint64_t)(&HookMemory)
+
4
);
DWORD old{
0
};
VirtualProtect((void
*
)HookAddress,
0x100
,
0x40
, &old);
memcpy((void
*
)HookAddress, JmpShellCode, sizeof(JmpShellCode)
-
1
);
VirtualProtect((void
*
)HookAddress,
0x100
, old, &old);
}
printf(
"HookMemory:%llx BotPosPtr:%llx\n"
, HookMemory, BotPosPtr);
}
char
*
GetName(uintptr_t
Object
)
{
if
(IsBadReadPtr((void
*
)
Object
,
8
))
{
return
0
;
}
auto NameIndex
=
*
(
int
*
)(
Object
+
0x18
);
if
(!NameIndex)
return
NULL;
auto NameBase
=
*
(uintptr_t
*
)(GameBase
+
0x2E6E0C0
);
if
(!NameBase)
return
NULL;
auto NameIndexPtr
=
*
(uintptr_t
*
)(NameBase
+
8
*
(static_cast<uint64_t>(NameIndex)
/
0x4000
));
if
(!NameIndexPtr)
return
NULL;
NameIndexPtr
=
*
(uintptr_t
*
)(NameIndexPtr
+
8
*
(static_cast<uint64_t>(NameIndex)
%
0x4000
));
if
(!NameIndexPtr)
return
NULL;
return
(char
*
)(NameIndexPtr
+
0xC
);
/
/
v4
=
(
*
(
*
(qword_1800091A0
+
8i64
*
(
*
v3
/
0x4000
))
+
8i64
*
(
*
v3
%
0x4000
))
+
0x10i64
); 这里dump出来的dll最后是
0x10
哦
/
/
这里
0xC
为什么跟 dump出来的 那个
0x10
不一样呢 因为
0x10
取出来的名字是不完整的 不知道为什么出题人要这样写
}
Vec3
*
GetPos(uintptr_t
Object
)
{
if
(IsBadReadPtr((void
*
)
Object
,
8
))
{
return
0
;
}
auto PosPtr
=
*
(uintptr_t
*
)(
Object
+
0x158
);
return
(Vec3
*
)(PosPtr
+
0x164
);
}