添加项目文件。
This commit is contained in:
parent
f17a7cb9c8
commit
c5a2595302
|
|
@ -0,0 +1,12 @@
|
||||||
|
# 声明编译要求cmake最低版本
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
|
||||||
|
|
||||||
|
# ADD_DEFINITIONS(-std=c++11)
|
||||||
|
|
||||||
|
# 声明一个cmake工程
|
||||||
|
PROJECT(Dnf_Projet)
|
||||||
|
|
||||||
|
# 添加子目录, 并指定指定中间二进制和目标二进制存放的位置
|
||||||
|
ADD_SUBDIRECTORY(src)
|
||||||
|
ADD_SUBDIRECTORY(test)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,86 @@
|
||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "WSL-GCC-Debug",
|
||||||
|
"generator": "Unix Makefiles",
|
||||||
|
"configurationType": "Debug",
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeExecutable": "cmake",
|
||||||
|
"cmakeCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "linux_x64" ],
|
||||||
|
"wslPath": "Debian",
|
||||||
|
"buildCommandArgs": "-j3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "WSL-GCC-Release",
|
||||||
|
"generator": "Unix Makefiles",
|
||||||
|
"configurationType": "Release",
|
||||||
|
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||||
|
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||||
|
"cmakeExecutable": "cmake",
|
||||||
|
"cmakeCommandArgs": "",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "linux_x64" ],
|
||||||
|
"wslPath": "Debian",
|
||||||
|
"buildCommandArgs": "-j3"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Linux-GCC-Release",
|
||||||
|
"generator": "Unix Makefiles",
|
||||||
|
"configurationType": "RelWithDebInfo",
|
||||||
|
"cmakeExecutable": "cmake",
|
||||||
|
"remoteCopySourcesExclusionList": [ ".vs", ".git", "out" ],
|
||||||
|
"buildCommandArgs": "-j3",
|
||||||
|
"inheritEnvironments": [ "linux_x64" ],
|
||||||
|
"remoteMachineName": "${defaultRemoteMachineName}",
|
||||||
|
"remoteCMakeListsRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/src",
|
||||||
|
"remoteBuildRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/out/build/${name}",
|
||||||
|
"remoteInstallRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/out/install/${name}",
|
||||||
|
"remoteCopySources": true,
|
||||||
|
"rsyncCommandArgs": "-t --delete",
|
||||||
|
"remoteCopyBuildOutput": false,
|
||||||
|
"remoteCopySourcesMethod": "rsync",
|
||||||
|
"addressSanitizerEnabled": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Linux-GCC-Debug",
|
||||||
|
"generator": "Unix Makefiles",
|
||||||
|
"configurationType": "Debug",
|
||||||
|
"cmakeExecutable": "cmake",
|
||||||
|
"remoteCopySourcesExclusionList": [ ".vs", ".git", "out" ],
|
||||||
|
"buildCommandArgs": "-j3",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "linux_x64" ],
|
||||||
|
"remoteMachineName": "${defaultRemoteMachineName}",
|
||||||
|
"remoteCMakeListsRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/src",
|
||||||
|
"remoteBuildRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/out/build/${name}",
|
||||||
|
"remoteInstallRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/out/install/${name}",
|
||||||
|
"remoteCopySources": true,
|
||||||
|
"rsyncCommandArgs": "-t --delete",
|
||||||
|
"remoteCopyBuildOutput": false,
|
||||||
|
"remoteCopySourcesMethod": "rsync"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "x86-Linux-GCC-Release",
|
||||||
|
"generator": "Unix Makefiles",
|
||||||
|
"configurationType": "RelWithDebInfo",
|
||||||
|
"cmakeExecutable": "cmake",
|
||||||
|
"remoteCopySourcesExclusionList": [ ".vs", ".git", "out" ],
|
||||||
|
"cmakeCommandArgs": "",
|
||||||
|
"buildCommandArgs": "-j3",
|
||||||
|
"ctestCommandArgs": "",
|
||||||
|
"inheritEnvironments": [ "linux_x86" ],
|
||||||
|
"remoteMachineName": "${defaultRemoteMachineName}",
|
||||||
|
"remoteCMakeListsRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/src",
|
||||||
|
"remoteBuildRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/out/build/${name}",
|
||||||
|
"remoteInstallRoot": "$HOME/.vs/${projectDirName}/${workspaceHash}/out/install/${name}",
|
||||||
|
"remoteCopySources": true,
|
||||||
|
"rsyncCommandArgs": "-t --delete",
|
||||||
|
"remoteCopyBuildOutput": false,
|
||||||
|
"remoteCopySourcesMethod": "rsync",
|
||||||
|
"variables": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#ifndef __SINGLETON_H__
|
||||||
|
#define __SINGLETON_H__
|
||||||
|
|
||||||
|
//饿汉模式
|
||||||
|
#define SINGLETON_DEFINE_S(TypeName) \
|
||||||
|
static TypeName* Get() \
|
||||||
|
{ \
|
||||||
|
static TypeName type_instance; \
|
||||||
|
return &type_instance; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
TypeName(const TypeName&) = delete; \
|
||||||
|
TypeName& operator=(const TypeName&) = delete
|
||||||
|
|
||||||
|
#endif // __SINGLETON_H__
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
# 声明编译要求cmake最低版本
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
|
||||||
|
|
||||||
|
# 配置支持C++11
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -fpic")
|
||||||
|
|
||||||
|
#添加头文件目录
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
# 添加库源文件
|
||||||
|
set(LIB_SOURCE
|
||||||
|
controller.cc
|
||||||
|
|
||||||
|
df_main.cc
|
||||||
|
)
|
||||||
|
|
||||||
|
# 添加动态库,关键词为shared
|
||||||
|
ADD_LIBRARY(hook_shared SHARED ${LIB_SOURCE})
|
||||||
|
|
||||||
|
# 指定动态库的输出名称
|
||||||
|
SET_TARGET_PROPERTIES(hook_shared PROPERTIES OUTPUT_NAME "hook")
|
||||||
|
|
||||||
|
# 指定动态库版本, 视需求而定,可不加
|
||||||
|
# VERSION:动态库版本,SOVERSION:API版本
|
||||||
|
#SET_TARGET_PROPERTIES(hook_shared PROPERTIES VERSION 0.1.1 SOVERSION 0)
|
||||||
|
|
||||||
|
# 指定库编译输出目录
|
||||||
|
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
||||||
|
|
||||||
|
|
@ -0,0 +1,236 @@
|
||||||
|
#include "controller.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
controller* controller::pThis = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
controller::controller() :
|
||||||
|
old_UseJewel_dispatch_sig((UseJewel_dispatch_sig_Type*)base::Dispatcher_UseJewel::dispatch_sig),
|
||||||
|
old_PacketDispatcher_doDispatch((PacketDispatcher_doDispatch_Type*)base::PacketDispatcher::doDispatch)
|
||||||
|
{
|
||||||
|
pThis = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
controller::~controller()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void controller::init()
|
||||||
|
{
|
||||||
|
CodeHook::WriteUChar((void*)(base::GlobalData::Init_fix_1 - 0x1), 0);
|
||||||
|
//.text:085BDE9D 83 F8 0A cmp eax, 10
|
||||||
|
CodeHook::WriteUChar((void*)(base::CParty::addDungeonClear_fix_1 + 2), 0x7E); //普通被击
|
||||||
|
//.text:085BDF30 83 F8 1E cmp eax, 30
|
||||||
|
CodeHook::WriteUChar((void*)(base::CParty::addDungeonClear_fix_2 + 2), 0x7E); //远古被击
|
||||||
|
//.text:085BDFC3 83 F8 32 cmp eax, 50
|
||||||
|
CodeHook::WriteUChar((void*)(base::CParty::addDungeonClear_fix_3 + 2), 0x7E); //异界被击
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mhook_PacketDispatcher_doDispatch.Hook((void**)&old_PacketDispatcher_doDispatch, (void*)hook_PacketDispatcher_doDispatch);
|
||||||
|
|
||||||
|
mhook_UseJewel_dispatch_sig.Hook((void**)&old_UseJewel_dispatch_sig, (void*)hook_UseJewel_dispatch_sig);
|
||||||
|
|
||||||
|
LOG("controller::init()");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int controller::hook_UseJewel_dispatch_sig(void* pDispatcher_UseJewel, CUser* pUser, PacketBuf* pBuf)
|
||||||
|
{
|
||||||
|
printf("getCurCharacName :%s \n", pUser->getCurCharacName().c_str());
|
||||||
|
printf("getCurCharacNo :%d \n", pUser->getCurCharacNo());
|
||||||
|
printf("get_buf_ptr :%p %p \n", pBuf->get_buf_ptr(0));
|
||||||
|
printf("get_len :%d \n", pBuf->get_len());
|
||||||
|
|
||||||
|
// printf("pBuf :%s \n", Util::ToHexString((const unsigned char*)pBuf->get_buf_ptr(0),40).c_str());
|
||||||
|
int state = pUser->get_state();
|
||||||
|
printf("state :%d \n", state);
|
||||||
|
//校验角色状态是否允许镶嵌
|
||||||
|
if (state != 3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int isEnableAvatarSocketAction = pUser->isEnableAvatarSocketAction();
|
||||||
|
if (isEnableAvatarSocketAction)
|
||||||
|
pUser->SendCmdErrorPacket(205, (unsigned char)isEnableAvatarSocketAction);
|
||||||
|
//解析packet_buf
|
||||||
|
|
||||||
|
//时装所在的背包槽
|
||||||
|
int avartar_inven_slot = pBuf->get_short();
|
||||||
|
printf("avartar_inven_slot :%d \n", avartar_inven_slot);
|
||||||
|
//时装item_id
|
||||||
|
int avartar_item_id = pBuf->get_int();
|
||||||
|
printf("avartar_item_id :%d \n", avartar_item_id);
|
||||||
|
//本次镶嵌徽章数量
|
||||||
|
int emblem_cnt = pBuf->get_byte();
|
||||||
|
printf("emblem_cnt :%d \n", emblem_cnt);
|
||||||
|
|
||||||
|
if (pUser->CheckItemLock(2, avartar_inven_slot))
|
||||||
|
{
|
||||||
|
pUser->SendCmdErrorPacket(205, 213);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取时装道具
|
||||||
|
CInventory* inven = pUser->getCurCharacInvenW();
|
||||||
|
if (!inven)
|
||||||
|
{
|
||||||
|
printf("pUser->getCurCharacInvenW : error \n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Inven_Item* avartar = inven->GetInvenRef(CInventory::INVENTORY_TYPE_AVARTAR, avartar_inven_slot);
|
||||||
|
if (!avartar)
|
||||||
|
{
|
||||||
|
printf("inven->GetInvenRef : error \n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//校验时装 数据是否合法
|
||||||
|
if (avartar->isEmpty() || (avartar->getKey() != avartar_item_id) || pUser->CheckItemLock(2, avartar_inven_slot))
|
||||||
|
{
|
||||||
|
|
||||||
|
printf("avartar->isEmpty() || avartar->getKey() || pUser->CheckItemLock() : error \n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//获取时装插槽数据
|
||||||
|
WongWork::CAvatarItemMgr* avartar_add_info = avartar->get_add_info();
|
||||||
|
WongWork::CAvatarItemMgr* inven_avartar_mgr = inven->GetAvatarItemMgrR();
|
||||||
|
int jewel_socket_data = inven_avartar_mgr->getJewelSocketData(avartar_add_info);
|
||||||
|
if (!jewel_socket_data)
|
||||||
|
{
|
||||||
|
printf("jewel_socket_data : error \n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("jewel_socket_data :%s \n", Util::ToHexString((const unsigned char*)jewel_socket_data, 40).c_str());
|
||||||
|
if (emblem_cnt <= 3)
|
||||||
|
{
|
||||||
|
std::map<int, std::pair<int, int>> emblems;
|
||||||
|
for (int i = 0; i < emblem_cnt; i++)
|
||||||
|
{
|
||||||
|
//徽章所在的背包槽
|
||||||
|
int emblem_inven_slot = pBuf->get_short();
|
||||||
|
//徽章item_id
|
||||||
|
int emblem_item_id = pBuf->get_int();
|
||||||
|
//该徽章镶嵌的时装插槽id
|
||||||
|
int avartar_socket_slot = pBuf->get_byte();
|
||||||
|
|
||||||
|
//获取徽章道具
|
||||||
|
Inven_Item* emblem = inven->GetInvenRef(CInventory::INVENTORY_TYPE_ITEM, emblem_inven_slot);
|
||||||
|
//校验徽章及插槽数据是否合法
|
||||||
|
if (emblem->isEmpty() || (emblem->getKey() != emblem_item_id) || (avartar_socket_slot >= 3))
|
||||||
|
{
|
||||||
|
printf("emblem->isEmpty() || (emblem->getKey() : error \n");
|
||||||
|
pUser->SendCmdErrorPacket(205, 209);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//校验徽章是否满足时装插槽颜色要求
|
||||||
|
|
||||||
|
//获取徽章pvf数据
|
||||||
|
CDataManager* DataManager = CDataManager::G_CDataManager();
|
||||||
|
if (!DataManager)
|
||||||
|
{
|
||||||
|
printf("CDataManager::G_CDataManager() : error \n");
|
||||||
|
pUser->SendCmdErrorPacket(205, 209);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
CItem* citem = DataManager->find_item(emblem_item_id);
|
||||||
|
if (!citem)
|
||||||
|
{
|
||||||
|
printf("DataManager->find_item() : error \n");
|
||||||
|
pUser->SendCmdErrorPacket(205, 209);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//校验徽章类型
|
||||||
|
if (!citem->is_stackable() || (citem->GetItemType() != 20))
|
||||||
|
{
|
||||||
|
printf("citem->is_stackable() || (citem->GetItemType() : error \n");
|
||||||
|
pUser->SendCmdErrorPacket(205, 209);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取徽章支持的插槽
|
||||||
|
int emblem_socket_type = citem->getJewelTargetSocket();
|
||||||
|
|
||||||
|
//获取要镶嵌的时装插槽类型
|
||||||
|
int avartar_socket_type = *(short*)(jewel_socket_data + avartar_socket_slot * 6);
|
||||||
|
if (!(emblem_socket_type & avartar_socket_type))
|
||||||
|
{
|
||||||
|
//插槽类型不匹配
|
||||||
|
printf("emblem_socket_type & avartar_socket_type\n");
|
||||||
|
pUser->SendCmdErrorPacket(205, 209);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf("avartar_socket_slot:%d emblem_inven_slot:%d emblem_item_id:%d\n", avartar_socket_slot, emblem_inven_slot, emblem_item_id);
|
||||||
|
emblems[avartar_socket_slot] = std::make_pair(emblem_inven_slot, emblem_item_id);
|
||||||
|
}
|
||||||
|
printf("数据已读取!!!\n");
|
||||||
|
|
||||||
|
for (auto& avartar_socket_slot : emblems)
|
||||||
|
{
|
||||||
|
//删除徽章
|
||||||
|
int emblem_inven_slot = avartar_socket_slot.second.first;
|
||||||
|
inven->delete_item(1, emblem_inven_slot, 1, 8, 1);
|
||||||
|
|
||||||
|
//设置时装插槽数据
|
||||||
|
int emblem_item_id = avartar_socket_slot.second.second;
|
||||||
|
*(int*)(jewel_socket_data + avartar_socket_slot.first * 6 + 2) = emblem_item_id;
|
||||||
|
printf("徽章item_id=%d 已成功镶嵌进avartar_socket_slot=%d 的槽内!\n", emblem_item_id, avartar_socket_slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
//时装插槽数据存档
|
||||||
|
DB_UpdateAvatarJewelSlot::makeRequest(pUser->getCurCharacNo(), avartar->get_ui_id(), (void*)jewel_socket_data);
|
||||||
|
|
||||||
|
//通知客户端时装数据已更新
|
||||||
|
pUser->SendUpdateItemList(1, 1, avartar_inven_slot);
|
||||||
|
printf("徽章镶嵌完毕!!!\n");
|
||||||
|
//回包给客户端
|
||||||
|
InterfacePacketBuf* packet_guard = (InterfacePacketBuf*)PacketGuard::NewPacketGuard();
|
||||||
|
|
||||||
|
packet_guard->put_header(1, 204);
|
||||||
|
packet_guard->put_int(1);
|
||||||
|
packet_guard->finalize(1);
|
||||||
|
pUser->Send((PacketGuard*)packet_guard);
|
||||||
|
PacketGuard::DelPacketGuard((PacketGuard*)packet_guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 08217C06 分解
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int controller::hook_PacketDispatcher_doDispatch(PacketDispatcher* a1, CUser* user, int packet_class, int packet_id, void* packet_src, int pecakt_len, int a7, int a8)
|
||||||
|
{
|
||||||
|
//void* pAction = *a1->get_dispatcher(packet_id);
|
||||||
|
//
|
||||||
|
//if (pAction)
|
||||||
|
//{
|
||||||
|
// LOG("Recv() class:%d id:%d len:%d data:%s callback:%p %p %p %p %p %p "
|
||||||
|
// , packet_class
|
||||||
|
// , packet_id
|
||||||
|
// , pecakt_len
|
||||||
|
// , Util::ToHexString((const unsigned char*)packet_src, pecakt_len).c_str()
|
||||||
|
// , *((void**)pAction)
|
||||||
|
// , (void*)*((unsigned int*)pAction + 12)
|
||||||
|
// , (void*)*((unsigned int*)pAction + 16)
|
||||||
|
// , (void*)*((unsigned int*)pAction + 20)
|
||||||
|
// , (void*)*((unsigned int*)pAction + 24)
|
||||||
|
// , (void*)*((unsigned int*)pAction + 28)
|
||||||
|
// );
|
||||||
|
//}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// LOG("Recv() class:%d id:%d len:%d data:%s "
|
||||||
|
// , packet_class
|
||||||
|
// , packet_id
|
||||||
|
// , pecakt_len
|
||||||
|
// , Util::ToHexString((const unsigned char*)packet_src, pecakt_len).c_str()
|
||||||
|
// );
|
||||||
|
//}
|
||||||
|
|
||||||
|
if (packet_id == Packet_UseItem)
|
||||||
|
{
|
||||||
|
LOG("hook_PacketDispatcher_doDispatch packet_data :%s ", Util::ToHexString((const unsigned char*)packet_src, pecakt_len).c_str());
|
||||||
|
}
|
||||||
|
return pThis->old_PacketDispatcher_doDispatch(a1, user, packet_class, packet_id, packet_src, pecakt_len, a7, a8);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include "import.h"
|
||||||
|
#include "sdk_class.hpp"
|
||||||
|
#include "hook.h"
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
class controller
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
controller();
|
||||||
|
|
||||||
|
~controller();
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief hook修复镶嵌徽章
|
||||||
|
* @param pDispatcher_UseJewel
|
||||||
|
* @param pUser
|
||||||
|
* @param pBuf
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static int hook_UseJewel_dispatch_sig(void* pDispatcher_UseJewel, CUser* pUser, PacketBuf* pBuf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief hook收包处理
|
||||||
|
* @param a1
|
||||||
|
* @param a2
|
||||||
|
* @param a3
|
||||||
|
* @param a4
|
||||||
|
* @param src
|
||||||
|
* @param a6
|
||||||
|
* @param a7
|
||||||
|
* @param a8
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static int hook_PacketDispatcher_doDispatch(PacketDispatcher* a1, CUser* a2, int a3, int packet_id, void* packet_src, int pecakt_len, int a7, int a8);
|
||||||
|
|
||||||
|
private:
|
||||||
|
using UseJewel_dispatch_sig_Type = decltype(hook_UseJewel_dispatch_sig);
|
||||||
|
UseJewel_dispatch_sig_Type* old_UseJewel_dispatch_sig;
|
||||||
|
|
||||||
|
using PacketDispatcher_doDispatch_Type = decltype(hook_PacketDispatcher_doDispatch);
|
||||||
|
PacketDispatcher_doDispatch_Type* old_PacketDispatcher_doDispatch;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
FuncHook mhook_UseJewel_dispatch_sig;
|
||||||
|
FuncHook mhook_PacketDispatcher_doDispatch;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
static controller* pThis;
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,912 @@
|
||||||
|
#include "controller.hpp"
|
||||||
|
controller* manager = NULL;
|
||||||
|
|
||||||
|
char szGamePath[256];
|
||||||
|
int n_sleep_time = 10000;
|
||||||
|
int bGMMode = 0, bFairPVP = 0, bPickupRout = 0;
|
||||||
|
|
||||||
|
#define MAIN_OFFSET(offset) ((void *)((0x8048000) + (offset)))
|
||||||
|
#define SUBHOOK_INIT(func, addr) \
|
||||||
|
fn##func func = (fn##func)addr; \
|
||||||
|
FuncHook h##func
|
||||||
|
|
||||||
|
#define SUBHOOK_SETUP(func) h##func.Hook((void **)&func, (void *)_##func)
|
||||||
|
|
||||||
|
//SUBHOOK_INIT(PacketGuard, 0x0858DD4C);
|
||||||
|
SUBHOOK_INIT(GetVectorUserCharacInfo, 0x081A0BB8);
|
||||||
|
SUBHOOK_INIT(doDispatch, 0x08594922);
|
||||||
|
SUBHOOK_INIT(addServerHackCnt, 0x080F8C7E);
|
||||||
|
SUBHOOK_INIT(put_header, 0x080CB8FC);
|
||||||
|
SUBHOOK_INIT(IsRoutingItem, 0x08150F18);
|
||||||
|
SUBHOOK_INIT(setCharacInfoDetail, 0x0864AC1A);
|
||||||
|
SUBHOOK_INIT(IsGameMasterMode, 0x0811EDEE);
|
||||||
|
SUBHOOK_INIT(isGMUser, 0x0814589C);
|
||||||
|
SUBHOOK_INIT(GetPvPTeamCount, 0x08568CE0);
|
||||||
|
SUBHOOK_INIT(isGM, 0x08109346);
|
||||||
|
SUBHOOK_INIT(isGM1, 0x0829948C);
|
||||||
|
SUBHOOK_INIT(set_add_info, 0x080CB884);
|
||||||
|
SUBHOOK_INIT(get_dispatcher, 0x085948E2);
|
||||||
|
SUBHOOK_INIT(dispatch_template, 0x081258B6);
|
||||||
|
SUBHOOK_INIT(isSocketAvatar, 0x082F9228);
|
||||||
|
SUBHOOK_INIT(reach_game_world, 0x086C4E50);
|
||||||
|
SUBHOOK_INIT(Inter_LoadEtc_dispatch_sig, 0x084C0264);
|
||||||
|
|
||||||
|
//_setCharacInfoDetail
|
||||||
|
|
||||||
|
int checkGame(const char* pName)
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
char* path_end;
|
||||||
|
|
||||||
|
memset(path, 0, sizeof(path));
|
||||||
|
if (readlink("/proc/self/exe", path, sizeof(path)) <= 0)return -1;
|
||||||
|
path_end = strrchr(path, '/');
|
||||||
|
if (!path_end || strlen(path_end) < 9)return -1;
|
||||||
|
return strcmp(pName, ++path_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
int open_main_module_file()
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
memset(path, 0, sizeof(path));
|
||||||
|
if (readlink("/proc/self/exe", path, sizeof(path)) <= 0)return -1;
|
||||||
|
return open(path, O_RDONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getargs(char*** argv)
|
||||||
|
{
|
||||||
|
size_t buflen = 1024, readlen = 0, maxlen = buflen;
|
||||||
|
int fd = open("/proc/self/cmdline", O_RDONLY);
|
||||||
|
if (fd == -1)return 0;
|
||||||
|
char* buf = (char*)malloc(buflen);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
ssize_t n = read(fd, buf + readlen, buflen - readlen);
|
||||||
|
if (n == -1)
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
readlen += n;
|
||||||
|
if (!n || readlen < buflen)break;
|
||||||
|
maxlen += buflen;
|
||||||
|
buf = (char*)realloc(buf, maxlen);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
int argc = 0;
|
||||||
|
char* cp = buf;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
while (*cp != '\0')cp++;
|
||||||
|
argc++;
|
||||||
|
} while (++cp < buf + readlen);
|
||||||
|
*argv = (char**)malloc(argc * sizeof(char*));
|
||||||
|
argc = 0;
|
||||||
|
cp = buf;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
(*argv)[argc] = (char*)malloc(strlen(cp) + 1);
|
||||||
|
strcpy((*argv)[argc], cp);
|
||||||
|
argc++;
|
||||||
|
while (*cp != '\0')cp++;
|
||||||
|
} while (++cp < buf + readlen);
|
||||||
|
free(buf);
|
||||||
|
return argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getConfigPath(char* pPath, size_t nSize)
|
||||||
|
{
|
||||||
|
if (readlink("/proc/self/exe", pPath, nSize) <= 0)return -1;
|
||||||
|
char** argv = NULL;
|
||||||
|
int argc = getargs(&argv);
|
||||||
|
if (!argv || argc < 2)
|
||||||
|
{
|
||||||
|
if (argv)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (argv[i])free(argv[i]);
|
||||||
|
}
|
||||||
|
free(argv);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*strrchr(pPath, '/') = '\0';
|
||||||
|
sprintf(pPath, "%s/cfg/%s.cfg", pPath, argv[1]);
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (argv[i])free(argv[i]);
|
||||||
|
}
|
||||||
|
free(argv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetProfileString(const char* profile, const char* section, const char* key, char** val)
|
||||||
|
{
|
||||||
|
int hFile = open(profile, O_RDONLY);
|
||||||
|
if (hFile == -1)return -1;
|
||||||
|
struct stat st;
|
||||||
|
fstat(hFile, &st);
|
||||||
|
void* pFileData = mmap(0, st.st_size, PROT_READ, MAP_SHARED, hFile, 0);
|
||||||
|
if (!pFileData)
|
||||||
|
{
|
||||||
|
close(hFile);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
unsigned char readSection = 0, readKey = 1, readValue = 0, got = 0, notes = 0;
|
||||||
|
char* cur = (char*)pFileData, * end = (char*)pFileData + st.st_size;
|
||||||
|
char* sectionbuf = (char*)malloc(1024)
|
||||||
|
, * keybuf = (char*)malloc(1024)
|
||||||
|
, * valuebuf = (char*)malloc(1024);
|
||||||
|
memset(sectionbuf, 0, 1024);
|
||||||
|
memset(keybuf, 0, 1024);
|
||||||
|
memset(valuebuf, 0, 1024);
|
||||||
|
int i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (notes && *cur != '\n')continue;
|
||||||
|
switch (*cur)
|
||||||
|
{
|
||||||
|
case '#':
|
||||||
|
notes = 1;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
//jump space
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
//new line
|
||||||
|
if (readValue)
|
||||||
|
{
|
||||||
|
valuebuf[i] = '\0';
|
||||||
|
if (!strcmp(section, sectionbuf) && !strcmp(key, keybuf))
|
||||||
|
{
|
||||||
|
*val = (char*)malloc(i + 1);
|
||||||
|
memset(*val, 0, i + 1);
|
||||||
|
strcpy(*val, valuebuf);
|
||||||
|
got = 1;
|
||||||
|
}
|
||||||
|
//printf("value:%s\n", valuebuf);
|
||||||
|
}
|
||||||
|
notes = 0, readSection = 0, readKey = 1, readValue = 0, i = 0;
|
||||||
|
break;
|
||||||
|
case '[':
|
||||||
|
//section begin
|
||||||
|
readSection = 1;
|
||||||
|
readKey = 0;
|
||||||
|
readValue = 0;
|
||||||
|
i = 0;
|
||||||
|
break;
|
||||||
|
case ']':
|
||||||
|
//section end
|
||||||
|
if (readSection)
|
||||||
|
{
|
||||||
|
sectionbuf[i] = '\0';
|
||||||
|
//printf("section:%s\n", sectionbuf);
|
||||||
|
readSection = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
if (readKey)
|
||||||
|
{
|
||||||
|
keybuf[i] = '\0';
|
||||||
|
//printf("key:%s\n", keybuf);
|
||||||
|
readSection = 0;
|
||||||
|
readKey = 0;
|
||||||
|
readValue = 1;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (readSection)
|
||||||
|
{
|
||||||
|
sectionbuf[i++] = *cur;
|
||||||
|
}
|
||||||
|
else if (readKey)
|
||||||
|
{
|
||||||
|
keybuf[i++] = *cur;
|
||||||
|
}
|
||||||
|
else if (readValue)
|
||||||
|
{
|
||||||
|
valuebuf[i++] = *cur;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (++cur != end && !got);
|
||||||
|
free(sectionbuf);
|
||||||
|
free(keybuf);
|
||||||
|
free(valuebuf);
|
||||||
|
munmap(pFileData, st.st_size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetProfileInt(const char* profile, const char* section, const char* key)
|
||||||
|
{
|
||||||
|
int ival = 0;
|
||||||
|
char* pValue = NULL;
|
||||||
|
if (GetProfileString(profile, section, key, &pValue) || !pValue)return 0;
|
||||||
|
ival = atoi(pValue);
|
||||||
|
free(pValue);
|
||||||
|
return ival;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf32_Shdr* get_section_by_type(Elf32_Ehdr* pHeader, Elf32_Shdr* pSectionHeaderTable, Elf32_Word sh_type)
|
||||||
|
{
|
||||||
|
Elf32_Half i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (pSectionHeaderTable[i].sh_type == sh_type)
|
||||||
|
{
|
||||||
|
return &pSectionHeaderTable[i];
|
||||||
|
}
|
||||||
|
} while (++i < pHeader->e_shnum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf32_Shdr* get_section_by_index(Elf32_Ehdr* pHeader, Elf32_Shdr* pSectionHeaderTable, Elf32_Half i)
|
||||||
|
{
|
||||||
|
if (i < pHeader->e_shnum)
|
||||||
|
{
|
||||||
|
return &pSectionHeaderTable[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf32_Shdr* get_section_by_name(Elf32_Ehdr* pHeader, Elf32_Shdr* pSectionHeaderTable, const char* pSymStrTbl, const char* pName)
|
||||||
|
{
|
||||||
|
Elf32_Half i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!strcmp(pName, &pSymStrTbl[pSectionHeaderTable[i].sh_name]))
|
||||||
|
{
|
||||||
|
return &pSectionHeaderTable[i];
|
||||||
|
}
|
||||||
|
} while (++i < pHeader->e_shnum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_symbol_index_by_name(Elf32_Sym* pSymbolTbl, int nSymbols, const char* pSymStrTbl, const char* pName)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (ELF32_ST_TYPE(pSymbolTbl[i].st_info) == STT_FUNC && !strcmp(pName, &pSymStrTbl[pSymbolTbl[i].st_name]))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
} while (++i < nSymbols);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* replaceIAT(const char* pName, void* pAddr)
|
||||||
|
{
|
||||||
|
void* pOrgAddr = NULL;
|
||||||
|
|
||||||
|
int hFile = open_main_module_file();
|
||||||
|
if (hFile != -1)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
fstat(hFile, &st);
|
||||||
|
void* pFileData = mmap(0, st.st_size, PROT_READ, MAP_SHARED, hFile, 0);
|
||||||
|
if (pFileData)
|
||||||
|
{
|
||||||
|
Elf32_Ehdr* pHeader = (Elf32_Ehdr*)pFileData;
|
||||||
|
Elf32_Shdr* pSectionHeaderTable = (Elf32_Shdr*)((char*)pHeader + pHeader->e_shoff);
|
||||||
|
Elf32_Shdr* pSymSection = get_section_by_type(pHeader, pSectionHeaderTable, SHT_DYNSYM);
|
||||||
|
Elf32_Shdr* pSymStrSection = get_section_by_index(pHeader, pSectionHeaderTable, pSymSection->sh_link);
|
||||||
|
Elf32_Sym* pSymbolTbl = (Elf32_Sym*)((char*)pHeader + pSymSection->sh_offset);
|
||||||
|
const char* pSymStrTbl = (const char*)((char*)pHeader + pSymStrSection->sh_offset);
|
||||||
|
unsigned int iSymbol = get_symbol_index_by_name(pSymbolTbl, pSymSection->sh_size / sizeof(Elf32_Sym), pSymStrTbl, pName);
|
||||||
|
Elf32_Shdr* pStrSection = get_section_by_index(pHeader, pSectionHeaderTable, pHeader->e_shstrndx);
|
||||||
|
const char* pStrTbl = (const char*)((char*)pHeader + pStrSection->sh_offset);
|
||||||
|
Elf32_Shdr* pRelPltSection = get_section_by_name(pHeader, pSectionHeaderTable, pStrTbl, ".rel.plt");
|
||||||
|
Elf32_Shdr* pRelDynSection = get_section_by_name(pHeader, pSectionHeaderTable, pStrTbl, ".rel.dyn");
|
||||||
|
Elf32_Rel* pRelPlt = (Elf32_Rel*)(0x8047000 + pRelPltSection->sh_offset);
|
||||||
|
Elf32_Rel* pRelDyn = (Elf32_Rel*)(0x8047000 + pRelDynSection->sh_offset);
|
||||||
|
int nRelPlt = pRelPltSection->sh_size / sizeof(Elf32_Rel);
|
||||||
|
int nRelDyn = pRelDynSection->sh_size / sizeof(Elf32_Rel);
|
||||||
|
for (int i = 0; i < nRelPlt; i++)
|
||||||
|
{
|
||||||
|
if (ELF32_R_SYM(pRelPlt[i].r_info) == iSymbol && pRelPlt[i].r_offset)
|
||||||
|
{
|
||||||
|
pOrgAddr = *(void**)pRelPlt[i].r_offset;
|
||||||
|
*(void**)pRelPlt[i].r_offset = pAddr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pOrgAddr)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nRelDyn; i++)
|
||||||
|
{
|
||||||
|
if (ELF32_R_SYM(pRelDyn[i].r_info) == iSymbol && pRelDyn[i].r_offset)
|
||||||
|
{
|
||||||
|
void** jmpAddr = (void**)pRelDyn[i].r_offset;
|
||||||
|
//printf("jmpaddr::::::::::::::::::::%X\n", pRelDyn[i].r_offset);
|
||||||
|
pOrgAddr = (void*)((char*)(*jmpAddr) + (int)jmpAddr + sizeof(void*));
|
||||||
|
CodeHook::WriteBytes(pOrgAddr, &pAddr, sizeof(pAddr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
munmap(pFileData, st.st_size);
|
||||||
|
}
|
||||||
|
close(hFile);
|
||||||
|
}
|
||||||
|
return pOrgAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int my_select(int __nfds, fd_set* __restrict __readfds,
|
||||||
|
fd_set* __restrict __writefds,
|
||||||
|
fd_set* __restrict __exceptfds,
|
||||||
|
struct timeval* __restrict __timeout)
|
||||||
|
{
|
||||||
|
if (!__nfds && !__readfds && !__writefds && !__exceptfds)
|
||||||
|
{
|
||||||
|
if (!__timeout->tv_sec && __timeout->tv_usec >= 0 && __timeout->tv_usec <= 1000)
|
||||||
|
{
|
||||||
|
__timeout->tv_usec = n_sleep_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return select(__nfds, __readfds, __writefds, __exceptfds, __timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int my_usleep(__useconds_t __useconds)
|
||||||
|
{
|
||||||
|
if (__useconds >= 0 && __useconds <= 1000)
|
||||||
|
{
|
||||||
|
__useconds = n_sleep_time;
|
||||||
|
}
|
||||||
|
return usleep(__useconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void* my_malloc (size_t __size)
|
||||||
|
{
|
||||||
|
if (__size > 100 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
memset(path, 0, sizeof(path));
|
||||||
|
readlink("/proc/self/exe", path, sizeof(path));
|
||||||
|
printf("**********************************[%s][malloc]: %.2f\n", path, (double)__size / 1024 / 1024);
|
||||||
|
print_backtrace(2);
|
||||||
|
}
|
||||||
|
return malloc(__size);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
int _doDispatch(void* pPacketDispatcher, void* pUser, int a3, int a4, void* src, int a6, int a7, int a8)//收包处理
|
||||||
|
{
|
||||||
|
void* pAction = *get_dispatcher(pPacketDispatcher, a4);
|
||||||
|
if (pAction)
|
||||||
|
{
|
||||||
|
printf("Recv() cs:%d cmd:%d len:%d callback:%p\t%p\t%p\t%p\t%p\t%p\n"
|
||||||
|
, a3
|
||||||
|
, a4
|
||||||
|
, a6
|
||||||
|
, *((void**)pAction)
|
||||||
|
, (void*)*((unsigned int*)pAction + 12)
|
||||||
|
, (void*)*((unsigned int*)pAction + 16)
|
||||||
|
, (void*)*((unsigned int*)pAction + 20)
|
||||||
|
, (void*)*((unsigned int*)pAction + 24)
|
||||||
|
, (void*)*((unsigned int*)pAction + 28)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf("Recv() cs:%d cmd:%d len:%d\n"
|
||||||
|
, a3
|
||||||
|
, a4
|
||||||
|
, a6);
|
||||||
|
}
|
||||||
|
return doDispatch(pPacketDispatcher, pUser, a3, a4, src, a6, a7, a8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int _dispatch_template(void* pInst, void* pUser, void* pPacketBuf)
|
||||||
|
{
|
||||||
|
char* buf = (char*)(*((unsigned int*)pPacketBuf + 5));
|
||||||
|
//printf("Recv() cs:%d cmd:%d len:%d callback:%p|%p|%p|%p|%p\n"
|
||||||
|
// , buf[0]
|
||||||
|
// , *((unsigned short*)&buf[1])
|
||||||
|
// , *((unsigned int*)&buf[3])
|
||||||
|
// , *((void**)*((unsigned int*)pInst + 12))
|
||||||
|
// , *((void**)*((unsigned int*)pInst + 16))
|
||||||
|
// , *((void**)*((unsigned int*)pInst + 20))
|
||||||
|
// , *((void**)*((unsigned int*)pInst + 24))
|
||||||
|
// , *((void**)*((unsigned int*)pInst + 28))
|
||||||
|
//);
|
||||||
|
return dispatch_template(pInst, pUser, pPacketBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _addServerHackCnt(void* pCHackAnalyzer, void* pCUserCharacInfo, int HackType, int Cnt, int a5, int a6)
|
||||||
|
{
|
||||||
|
//printf("addServerHackCnt() HackType:%d \n", HackType);
|
||||||
|
//char pack_buf[0xC];
|
||||||
|
//PacketGuard(pack_buf);
|
||||||
|
return addServerHackCnt(pCHackAnalyzer, pCUserCharacInfo, HackType, Cnt, a5, a6);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _put_header(void* pInterfacePacketBuf, int Type, int Cmd)
|
||||||
|
{
|
||||||
|
//printf("Send() cmd:%d\n", Cmd);
|
||||||
|
return put_header(pInterfacePacketBuf, Type, Cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _IsRoutingItem(void* pItem)
|
||||||
|
{
|
||||||
|
//拾取掷点
|
||||||
|
return bPickupRout && (*((unsigned int*)pItem + 14) == 4 || *((unsigned char*)pItem + 189));
|
||||||
|
}
|
||||||
|
|
||||||
|
int _setCharacInfoDetail(void* pUser, int a2, int a3, void* pCHARAC_DATA)
|
||||||
|
{
|
||||||
|
//下线位置
|
||||||
|
unsigned char curArea = *((unsigned char*)pCHARAC_DATA + 34);
|
||||||
|
int ret = setCharacInfoDetail(pUser, a2, a3, pCHARAC_DATA);
|
||||||
|
if (curArea == 12 || curArea == 13)
|
||||||
|
{
|
||||||
|
*((char*)GetVectorUserCharacInfo((char*)pUser + 497384, a2) + 34) = 11;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _IsGameMasterMode(void* pUser)
|
||||||
|
{
|
||||||
|
//gm
|
||||||
|
return bGMMode || *((unsigned char*)pUser + 463320) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _isGMUser(void* pUser)
|
||||||
|
{
|
||||||
|
//gm
|
||||||
|
//printf("%s\n", __FUNCTION__);
|
||||||
|
return bGMMode || (*((unsigned char*)pUser + 463320) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _isGM(void* pGMAccounts, unsigned int a2)
|
||||||
|
{
|
||||||
|
//gm
|
||||||
|
//printf("%s\n", __FUNCTION__);
|
||||||
|
return bGMMode || isGM(pGMAccounts, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _isGM1(void* pGM_Manager)
|
||||||
|
{
|
||||||
|
//gm
|
||||||
|
//printf("%s\n", __FUNCTION__);
|
||||||
|
return bGMMode || isGM1(pGM_Manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _GetPvPTeamCount(void* pDataManager)
|
||||||
|
{
|
||||||
|
if (bFairPVP)return 10;
|
||||||
|
return *((unsigned int*)pDataManager + 11540);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* _set_add_info(void* pInven_Item, int a2)
|
||||||
|
{
|
||||||
|
if ((unsigned int)__builtin_return_address(0) == 0x0820156C)
|
||||||
|
{
|
||||||
|
char* _esp = NULL;
|
||||||
|
__asm__ __volatile__("movl %%esp, %[a1];": [a1] "=m"(_esp));
|
||||||
|
if (_esp) {
|
||||||
|
for (int i = 0; i < 200; i++) {
|
||||||
|
if (897 == *((unsigned int*)&_esp[i]))
|
||||||
|
{
|
||||||
|
//printf("Get !!! %X\n", i);
|
||||||
|
a2 = GetProfileInt(szGamePath, "", "val");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printf("====================_set_add_info======================%d\n", a2);
|
||||||
|
}
|
||||||
|
return set_add_info(pInven_Item, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _isSocketAvatar(void* pAvatarItemMgr1, void* pAvatarItemMgr2)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _reach_game_world(void* pThis, void* a2)
|
||||||
|
{
|
||||||
|
return reach_game_world(pThis, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _Inter_LoadEtc_dispatch_sig(void* pThis, void* pUser, char* a3)
|
||||||
|
{
|
||||||
|
int result = Inter_LoadEtc_dispatch_sig(pThis, pUser, a3);
|
||||||
|
printf("_Inter_LoadEtc_dispatch_sig begin");
|
||||||
|
|
||||||
|
//typedef double(__cdecl* FN_sqrt)(_In_ double _X);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CUserCharacInfo_getCurCharacNo getCurCharacNo = (CUserCharacInfo_getCurCharacNo)(0x080CBC4E);
|
||||||
|
int CurCharacNo = getCurCharacNo(pUser);
|
||||||
|
printf("CurCharacNo :%d", CurCharacNo);
|
||||||
|
|
||||||
|
CUserCharacInfo_getCurCharacName getCurCharacName = (CUserCharacInfo_getCurCharacName)0x8101028;
|
||||||
|
|
||||||
|
char* name = getCurCharacName(pUser);
|
||||||
|
printf("CurCharacName :%s", name);
|
||||||
|
|
||||||
|
printf("_Inter_LoadEtc_dispatch_sig end");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int patchGame()
|
||||||
|
{
|
||||||
|
int a = 1;
|
||||||
|
void* buf = malloc(4);
|
||||||
|
CodeHook::WriteBytes(buf, &a, 4);
|
||||||
|
getConfigPath(szGamePath, sizeof(szGamePath));
|
||||||
|
printf("GameConfigPath:%s\n", szGamePath);
|
||||||
|
|
||||||
|
replaceIAT("select", (void*)my_select);
|
||||||
|
replaceIAT("usleep", (void*)my_usleep);
|
||||||
|
//replaceIAT("malloc", (void*)my_malloc);
|
||||||
|
|
||||||
|
if (!checkGame("df_coserver_r"))
|
||||||
|
{
|
||||||
|
n_sleep_time = 13000;
|
||||||
|
}
|
||||||
|
else if (!checkGame("df_game_r"))
|
||||||
|
{
|
||||||
|
int nMaxClientNum_Game = GetProfileInt(szGamePath, "", "max_client");
|
||||||
|
int bHumanCertify = GetProfileInt(szGamePath, "", "random_human_certify") != 0;
|
||||||
|
unsigned int nMaxGrade = GetProfileInt(szGamePath, "", "max_grade");
|
||||||
|
if (nMaxGrade > 255)nMaxGrade = 255;
|
||||||
|
//if (nMaxGrade < 70)nMaxGrade = 70;
|
||||||
|
bGMMode = GetProfileInt(szGamePath, "", "force_gm_mode") != 0;
|
||||||
|
bFairPVP = GetProfileInt(szGamePath, "", "fair_pvp") != 0;
|
||||||
|
bPickupRout = GetProfileInt(szGamePath, "", "pickup_rout") != 0;
|
||||||
|
int bDespirTowerUnlimit = GetProfileInt(szGamePath, "", "despir_tower_unlimit") != 0;
|
||||||
|
printf("GM Mode: %s\n", bGMMode ? "on" : "off");
|
||||||
|
printf("Human Certify: %s\n", bHumanCertify ? "on" : "off");
|
||||||
|
printf("Fair PVP: %s\n", bFairPVP ? "on" : "off");
|
||||||
|
printf("Pickup Rout: %s\n", bPickupRout ? "on" : "off");
|
||||||
|
printf("Despir Tower Unlimit: %s\n", bDespirTowerUnlimit ? "on" : "off");
|
||||||
|
if (bGMMode)
|
||||||
|
{
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x2512DA + 1), 1);
|
||||||
|
}
|
||||||
|
/*CodeHook::WriteUChar(MAIN_OFFSET(0x1B954E), 0x68);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x1B954E + 1), (int)_hook_item_897);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x1B954E + 5), 0xC3);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x1B954E), 0xB8);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x1B954F), 0x64);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x1B9550), 0x00);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x1B9551), 0x00);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x1B9552), 0x00);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x1B9553), 0x90909090);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x1B9557), 0x90);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x1B9558), 0x90);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x1B9559), 0x90);*/
|
||||||
|
if (bDespirTowerUnlimit)
|
||||||
|
{
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x5FC1AC), 0xEB);
|
||||||
|
}
|
||||||
|
CodeHook::WriteBytes((void*)(0x080EE403 + 1), &nMaxClientNum_Game, sizeof(nMaxClientNum_Game));
|
||||||
|
CodeHook::WriteBytes((void*)(0x080EE423 + 1), &nMaxClientNum_Game, sizeof(nMaxClientNum_Game));
|
||||||
|
CodeHook::WriteBytes((void*)(0x080EE463 + 1), &nMaxClientNum_Game, sizeof(nMaxClientNum_Game));
|
||||||
|
CodeHook::WriteBytes((void*)(0x080EE483 + 1), &nMaxClientNum_Game, sizeof(nMaxClientNum_Game));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AE3F1 + 2), &nMaxClientNum_Game, sizeof(nMaxClientNum_Game));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AE88B + 2), &nMaxClientNum_Game, sizeof(nMaxClientNum_Game));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AEAE9 + 2), &nMaxClientNum_Game, sizeof(nMaxClientNum_Game));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AEFB9 + 2), &nMaxClientNum_Game, sizeof(nMaxClientNum_Game));
|
||||||
|
int for_num = nMaxClientNum_Game - 1;
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AE3FF + 1), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AE431 + 1), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AE4FF + 3), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AE899 + 1), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AE8CB + 1), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AE999 + 3), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AEAF7 + 1), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AEB29 + 1), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AEBF7 + 3), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AEFC7 + 1), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AEFF9 + 1), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AF0C7 + 3), &for_num, sizeof(for_num));
|
||||||
|
unsigned int val = 4 + 0x8EC3C * nMaxClientNum_Game;
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AE3E1 + 3), &val, sizeof(val));
|
||||||
|
val = 4 + 0x1B08 * nMaxClientNum_Game;
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AE87B + 3), &val, sizeof(val));
|
||||||
|
val = 4 + 0x6F0 * nMaxClientNum_Game;
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AEAD9 + 3), &val, sizeof(val));
|
||||||
|
val = 4 + 0xB6C * nMaxClientNum_Game;
|
||||||
|
CodeHook::WriteBytes((void*)(0x082AEFA9 + 3), &val, sizeof(val));
|
||||||
|
#if 0
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x135E32), 0xEB);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x22069B), 0x01);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x220894), 0x01);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x254D78), 0xEB);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x258E80), 0xEB);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x314ECB), 0xEB);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x314FCB), 0xEB);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318CC8), 0xE6);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31C128), 0x7E);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31C129), 0x06);
|
||||||
|
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x602DAF), 0x7C);
|
||||||
|
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61AF55), 0x55);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61B0F3), 0x55);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61DD28), 0x54);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61E86A), 0x57);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61EE9C), 0x54);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x6224A8), 0x54);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622929), 0x55);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x641D4B), 0x54);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647ECE), 0x55);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647EDA), 0x55);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647F82), 0x56);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647F88), 0x56);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x66521D), 0x56);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x665223), 0x56);
|
||||||
|
#else
|
||||||
|
//AradAppSystem::AradAppInit
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x135E32), 0xEB);
|
||||||
|
//ServerParameterScript::setDungeonOpen
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x22069B), 0x01);
|
||||||
|
//ServerParameterScript::isDungeonOpen
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x220894), 0x01);
|
||||||
|
//AntiBot init
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x254D78), 0xEB);
|
||||||
|
//Init DataManager
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x258E80), 0xEB);
|
||||||
|
//Init Level Exp
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x314ECB), 0xEB);
|
||||||
|
//Init Mob Reward
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x314FCB), 0xEB);
|
||||||
|
//CDataManager::GetSpAtLevelUp
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318CC8), 0xE6);
|
||||||
|
//fixbug
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31C128), 0x7E);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31C129), 0x06);
|
||||||
|
//pickup rout
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x107D53), 0x90);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x107D54), 0x90);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x55D6D1), 0x90);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x55D6D2), 0x90);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x6382F4), bHumanCertify);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x547005), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61AF55), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61B0F3), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61DD28), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61E86A), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61EE9C), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x6224A8), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622929), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x641D4B), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647ECE), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647EDA), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647F82), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647F88), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x66521D), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x665223), nMaxGrade);
|
||||||
|
if (nMaxGrade > 70)
|
||||||
|
{
|
||||||
|
//以下需要扩充类大小, 修改偏移
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x87162 + 3), 0xB678 + nMaxGrade * 4 + nMaxGrade * 12);
|
||||||
|
//CDataManager::set_reward_sp
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x318C26 + 2), 10836 + 840);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318C3B), nMaxGrade);
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x318C68 + 2), 10836 + 840);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318C79), nMaxGrade);
|
||||||
|
//CDataManager::GetSpAtLevelUp
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318CC4), nMaxGrade);
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x318CD4 + 2), 10836 + 840);
|
||||||
|
#if 0
|
||||||
|
//CDataManager::getDailyTrainingQuest
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31C110 + 1), 0xB678 + nMaxGrade * 4);
|
||||||
|
//CDataManager::isThereDailyTrainingQuestList
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31C12D), nMaxGrade);
|
||||||
|
//CDataManager::reselectDailyTrainingQuest
|
||||||
|
//扩充栈内存
|
||||||
|
unsigned int incsize = (nMaxGrade - 70) * 4 * 6;
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BCE6 + 2), 0x70C + incsize);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BD03 + 2), 0xFFFFF91C - incsize);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BD2E + 2), 0xFFFFF914 - incsize);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BD5E + 2), 0xFFFFF914 - incsize);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BD77 + 2), 0xFFFFF91C - incsize);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BDD2 + 2), 0xFFFFF91C - incsize);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BEED + 2), 0xFFFFF91C - incsize);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31C098 + 2), 0xFFFFF91C - incsize);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31C0AA + 2), 0xFFFFF91C - incsize);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31C0B6 + 2), 0xFFFFF91C - incsize);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31C0D9 + 2), 0xFFFFF91C - incsize);
|
||||||
|
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31BD0B + 1), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31BD38 + 1), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31C084 + 3), nMaxGrade);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BDA4 + 1), 0xB678 + nMaxGrade * 4);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BEBC + 1), 0xB678 + nMaxGrade * 4);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BF4A + 1), 0xB678 + nMaxGrade * 4);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BF82 + 1), 0xB678 + nMaxGrade * 4);
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x31BFAE + 1), 0xB678 + nMaxGrade * 4);
|
||||||
|
//TrainingQuestScript::getApplyLevel
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0xA67AFB + 3), nMaxGrade);
|
||||||
|
//TrainingQuestScript::suffleTrainingQuests
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0xA67DAA + 3), nMaxGrade);
|
||||||
|
//CDataManager::CDataManager
|
||||||
|
CodeHook::WriteBytes_uint(MAIN_OFFSET(0x30DF24 + 2), 0xB678 + nMaxGrade * 4);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x30DF2C + 1), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x30DF56 + 1), nMaxGrade - 1);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61B8F6), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622659), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622941), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622941), nMaxGrade);
|
||||||
|
|
||||||
|
SUBHOOK_SETUP(doDispatch);
|
||||||
|
//SUBHOOK_SETUP(addServerHackCnt);
|
||||||
|
SUBHOOK_SETUP(put_header);
|
||||||
|
SUBHOOK_SETUP(IsRoutingItem);
|
||||||
|
SUBHOOK_SETUP(setCharacInfoDetail);
|
||||||
|
//SUBHOOK_SETUP(IsGameMasterMode);
|
||||||
|
SUBHOOK_SETUP(isGMUser);
|
||||||
|
SUBHOOK_SETUP(isGM);
|
||||||
|
SUBHOOK_SETUP(isGM1);
|
||||||
|
SUBHOOK_SETUP(GetPvPTeamCount);
|
||||||
|
SUBHOOK_SETUP(set_add_info);
|
||||||
|
//SUBHOOK_SETUP(isSocketAvatar);
|
||||||
|
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (!checkGame("df_channel_r"))
|
||||||
|
{
|
||||||
|
int nMaxClientNum_Gate = GetProfileInt(szGamePath, "server", "max_client");
|
||||||
|
|
||||||
|
int for_num = nMaxClientNum_Gate - 1;
|
||||||
|
unsigned int val = 4 + 0x1C * nMaxClientNum_Gate;
|
||||||
|
CodeHook::WriteBytes((void*)(0x0805361E + 3), &val, sizeof(val));
|
||||||
|
CodeHook::WriteBytes((void*)(0x0805362E + 2), &nMaxClientNum_Gate, sizeof(nMaxClientNum_Gate));
|
||||||
|
CodeHook::WriteBytes((void*)(0x0805363C + 1), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x080536B8 + 4), &nMaxClientNum_Gate, sizeof(nMaxClientNum_Gate));
|
||||||
|
CodeHook::WriteBytes((void*)(0x08053783 + 3), &for_num, sizeof(for_num));
|
||||||
|
val = 4 + 0x140060 * nMaxClientNum_Gate;
|
||||||
|
CodeHook::WriteBytes((void*)0x0805380D, &val, sizeof(val));
|
||||||
|
CodeHook::WriteBytes((void*)0x0805381C, &nMaxClientNum_Gate, sizeof(nMaxClientNum_Gate));
|
||||||
|
CodeHook::WriteBytes((void*)0x08053829, &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)0x080538A4, &nMaxClientNum_Gate, sizeof(nMaxClientNum_Gate));
|
||||||
|
CodeHook::WriteBytes((void*)0x08053964, &for_num, sizeof(for_num));
|
||||||
|
}
|
||||||
|
else if (!checkGame("df_bridge_r"))
|
||||||
|
{
|
||||||
|
int nMaxClientNum_Gate = GetProfileInt(szGamePath, "server", "max_client");
|
||||||
|
|
||||||
|
int for_num = nMaxClientNum_Gate - 1;
|
||||||
|
unsigned int val = 4 + 0x1C * nMaxClientNum_Gate;
|
||||||
|
CodeHook::WriteBytes((void*)(0x08058018 + 3), &val, sizeof(val));
|
||||||
|
CodeHook::WriteBytes((void*)(0x08058028 + 2), &nMaxClientNum_Gate, sizeof(nMaxClientNum_Gate));
|
||||||
|
CodeHook::WriteBytes((void*)(0x08058036 + 1), &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)(0x080580B2 + 4), &nMaxClientNum_Gate, sizeof(nMaxClientNum_Gate));
|
||||||
|
CodeHook::WriteBytes((void*)(0x0805817D + 3), &for_num, sizeof(for_num));
|
||||||
|
val = 4 + 0x140060 * nMaxClientNum_Gate;
|
||||||
|
CodeHook::WriteBytes((void*)0x08058207, &val, sizeof(val));
|
||||||
|
CodeHook::WriteBytes((void*)0x08058216, &nMaxClientNum_Gate, sizeof(nMaxClientNum_Gate));
|
||||||
|
CodeHook::WriteBytes((void*)0x08058223, &for_num, sizeof(for_num));
|
||||||
|
CodeHook::WriteBytes((void*)0x0805829E, &nMaxClientNum_Gate, sizeof(nMaxClientNum_Gate));
|
||||||
|
CodeHook::WriteBytes((void*)0x0805835E, &for_num, sizeof(for_num));
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loga()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if (!checkGame("df_game_r"))
|
||||||
|
{
|
||||||
|
int a = 1;
|
||||||
|
void* buf = malloc(4);
|
||||||
|
CodeHook::WriteBytes(buf, &a, 4);
|
||||||
|
getConfigPath(szGamePath, sizeof(szGamePath));
|
||||||
|
unsigned int nMaxGrade = 70;
|
||||||
|
bGMMode = 1;
|
||||||
|
|
||||||
|
|
||||||
|
//max_level = nMaxGrade;
|
||||||
|
|
||||||
|
//ServerParameterScript::setDungeonOpen
|
||||||
|
|
||||||
|
//CodeHook::WriteUChar(MAIN_OFFSET(0x22069B), 0x01);
|
||||||
|
//ServerParameterScript::isDungeonOpen
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x220894), 0x01);
|
||||||
|
//Init DataManager
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x258E80), 0xEB);
|
||||||
|
//Init Level Exp
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x314ECB), 0xEB);
|
||||||
|
//Init Mob Reward
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x314FCB), 0xEB);
|
||||||
|
//CDataManager::GetSpAtLevelUp
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318CC8), 0xE6);
|
||||||
|
//fixbug
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31C128), 0x7E);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31C129), 0x06);
|
||||||
|
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x547005), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61AF55), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61B0F3), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61DD28), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61E86A), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61EE9C), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x6224A8), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622929), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x641D4B), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647ECE), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647EDA), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647F82), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647F88), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x66521D), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x665223), nMaxGrade);
|
||||||
|
SUBHOOK_SETUP(doDispatch);
|
||||||
|
SUBHOOK_SETUP(addServerHackCnt);
|
||||||
|
SUBHOOK_SETUP(put_header);
|
||||||
|
SUBHOOK_SETUP(IsRoutingItem);
|
||||||
|
SUBHOOK_SETUP(setCharacInfoDetail);
|
||||||
|
SUBHOOK_SETUP(IsGameMasterMode);
|
||||||
|
SUBHOOK_SETUP(isGMUser);
|
||||||
|
SUBHOOK_SETUP(isGM);
|
||||||
|
SUBHOOK_SETUP(isGM1);
|
||||||
|
SUBHOOK_SETUP(GetPvPTeamCount);
|
||||||
|
SUBHOOK_SETUP(set_add_info);
|
||||||
|
SUBHOOK_SETUP(reach_game_world);
|
||||||
|
SUBHOOK_SETUP(Inter_LoadEtc_dispatch_sig);
|
||||||
|
//manager->init();
|
||||||
|
SUBHOOK_SETUP(isSocketAvatar);
|
||||||
|
if (nMaxGrade > 70)
|
||||||
|
{
|
||||||
|
//以下需要扩充类大小, 修改偏移
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x87162 + 3), 0xB678 + nMaxGrade * 4 + nMaxGrade * 12);
|
||||||
|
//CDataManager::set_reward_sp
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x318C26 + 2), 10836 + 840);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318C3B), nMaxGrade);
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x318C68 + 2), 10836 + 840);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318C79), nMaxGrade);
|
||||||
|
//CDataManager::GetSpAtLevelUp
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318CC4), nMaxGrade);
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x318CD4 + 2), 10836 + 840);
|
||||||
|
}
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61B8F6), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622659), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622941), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622941), nMaxGrade);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PrintTag()
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf("**********************************************************\n");
|
||||||
|
printf("* DNF Server Plugin V%d.%02d *\n", Ver, Patch);
|
||||||
|
printf("* *\n");
|
||||||
|
printf("* /\\ /\\ *\n");
|
||||||
|
printf("* *\n");
|
||||||
|
printf("* __ Auther:Larva *\n");
|
||||||
|
printf("* QQ Group:81411049 *\n");
|
||||||
|
printf("**********************************************************\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void __attribute__((constructor)) my_init(void)
|
||||||
|
{
|
||||||
|
manager = new controller();
|
||||||
|
PrintTag();
|
||||||
|
//patchGame();
|
||||||
|
loga();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,381 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#define MOVEPOINT(p,i) (void*)((char*)p+i)
|
||||||
|
#define MAKEPOINTER(t, p, offset) ((t)((unsigned char*)(p) + (long)offset))
|
||||||
|
#define PADALIGN(x,mask) ((x+mask)&(~(x%mask)))
|
||||||
|
#define Addr_Align(addr,mask) ((void*)(((unsigned long)(addr))&(~((mask)-1))))
|
||||||
|
#define Move_Ptr(addr,offset) ((void*)((unsigned long)(addr)+(offset)))
|
||||||
|
|
||||||
|
enum flags {
|
||||||
|
MODRM = 1,
|
||||||
|
PLUS_R = 1 << 1,
|
||||||
|
REG_OPCODE = 1 << 2,
|
||||||
|
IMM8 = 1 << 3,
|
||||||
|
IMM16 = 1 << 4,
|
||||||
|
IMM32 = 1 << 5,
|
||||||
|
RELOC = 1 << 6
|
||||||
|
};
|
||||||
|
struct opcode_info {
|
||||||
|
unsigned char opcode;
|
||||||
|
unsigned char reg_opcode;
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
static unsigned char prefixes[] = {
|
||||||
|
0xF0, 0xF2, 0xF3,
|
||||||
|
0x2E, 0x36, 0x3E, 0x26, 0x64, 0x65,
|
||||||
|
0x66, /* operand size override */
|
||||||
|
0x67 /* address size override */
|
||||||
|
};
|
||||||
|
static struct opcode_info opcodes[] = {
|
||||||
|
/* ADD AL, imm8 */{ 0x04, 0, IMM8 },
|
||||||
|
/* ADD EAX, imm32 */{ 0x05, 0, IMM32 },
|
||||||
|
/* ADD r/m8, imm8 */{ 0x80, 0, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* ADD r/m32, imm32 */{ 0x81, 0, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* ADD r/m32, imm8 */{ 0x83, 0, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* ADD r/m8, r8 */{ 0x00, 0, MODRM },
|
||||||
|
/* ADD r/m32, r32 */{ 0x01, 0, MODRM },
|
||||||
|
/* ADD r8, r/m8 */{ 0x02, 0, MODRM },
|
||||||
|
/* ADD r32, r/m32 */{ 0x03, 0, MODRM },
|
||||||
|
/* AND AL, imm8 */{ 0x24, 0, IMM8 },
|
||||||
|
/* AND EAX, imm32 */{ 0x25, 0, IMM32 },
|
||||||
|
/* AND r/m8, imm8 */{ 0x80, 4, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* AND r/m32, imm32 */{ 0x81, 4, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* AND r/m32, imm8 */{ 0x83, 4, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* AND r/m8, r8 */{ 0x20, 0, MODRM },
|
||||||
|
/* AND r/m32, r32 */{ 0x21, 0, MODRM },
|
||||||
|
/* AND r8, r/m8 */{ 0x22, 0, MODRM },
|
||||||
|
/* AND r32, r/m32 */{ 0x23, 0, MODRM },
|
||||||
|
/* CALL rel32 */{ 0xE8, 0, IMM32 | RELOC },
|
||||||
|
/* CALL r/m32 */{ 0xFF, 2, MODRM | REG_OPCODE },
|
||||||
|
/* CMP r/m16/32, imm8*/{ 0x83, 7, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* DEC r/m16/32 */{ 0xFF, 1, MODRM | REG_OPCODE },
|
||||||
|
/* ENTER imm16, imm8 */{ 0xC8, 0, IMM16 | IMM8 },
|
||||||
|
/* INT 3 */{ 0xCC, 0, 0 },
|
||||||
|
/* JMP rel32 */{ 0xE9, 0, IMM32 | RELOC },
|
||||||
|
/* JMP r/m32 */{ 0xFF, 4, MODRM | REG_OPCODE },
|
||||||
|
/* LEA r32,m */{ 0x8D, 0, MODRM },
|
||||||
|
/* LEAVE */{ 0xC9, 0, 0 },
|
||||||
|
/* MOV r/m8,r8 */{ 0x88, 0, MODRM },
|
||||||
|
/* MOV r/m32,r32 */{ 0x89, 0, MODRM },
|
||||||
|
/* MOV r8,r/m8 */{ 0x8A, 0, MODRM },
|
||||||
|
/* MOV r32,r/m32 */{ 0x8B, 0, MODRM },
|
||||||
|
/* MOV r/m16,Sreg */{ 0x8C, 0, MODRM },
|
||||||
|
/* MOV Sreg,r/m16 */{ 0x8E, 0, MODRM },
|
||||||
|
/* MOV AL,moffs8 */{ 0xA0, 0, IMM8 },
|
||||||
|
/* MOV EAX,moffs32 */{ 0xA1, 0, IMM32 },
|
||||||
|
/* MOV moffs8,AL */{ 0xA2, 0, IMM8 },
|
||||||
|
/* MOV moffs32,EAX */{ 0xA3, 0, IMM32 },
|
||||||
|
/* MOV r8, imm8 */{ 0xB0, 0, PLUS_R | IMM8 },
|
||||||
|
/* MOV r32, imm32 */{ 0xB8, 0, PLUS_R | IMM32 },
|
||||||
|
/* MOV r/m8, imm8 */{ 0xC6, 0, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* MOV r/m32, imm32 */{ 0xC7, 0, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* NOP */{ 0x90, 0, 0 },
|
||||||
|
/* OR AL, imm8 */{ 0x0C, 0, IMM8 },
|
||||||
|
/* OR EAX, imm32 */{ 0x0D, 0, IMM32 },
|
||||||
|
/* OR r/m8, imm8 */{ 0x80, 1, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* OR r/m32, imm32 */{ 0x81, 1, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* OR r/m32, imm8 */{ 0x83, 1, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* OR r/m8, r8 */{ 0x08, 0, MODRM },
|
||||||
|
/* OR r/m32, r32 */{ 0x09, 0, MODRM },
|
||||||
|
/* OR r8, r/m8 */{ 0x0A, 0, MODRM },
|
||||||
|
/* OR r32, r/m32 */{ 0x0B, 0, MODRM },
|
||||||
|
/* POP r/m32 */{ 0x8F, 0, MODRM | REG_OPCODE },
|
||||||
|
/* POP r32 */{ 0x58, 0, PLUS_R },
|
||||||
|
/* PUSH r/m32 */{ 0xFF, 6, MODRM | REG_OPCODE },
|
||||||
|
/* PUSH r32 */{ 0x50, 0, PLUS_R },
|
||||||
|
/* PUSH imm8 */{ 0x6A, 0, IMM8 },
|
||||||
|
/* PUSH imm32 */{ 0x68, 0, IMM32 },
|
||||||
|
/* RET */{ 0xC3, 0, 0 },
|
||||||
|
/* RET imm16 */{ 0xC2, 0, IMM16 },
|
||||||
|
/* SUB AL, imm8 */{ 0x2C, 0, IMM8 },
|
||||||
|
/* SUB EAX, imm32 */{ 0x2D, 0, IMM32 },
|
||||||
|
/* SUB r/m8, imm8 */{ 0x80, 5, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* SUB r/m32, imm32 */{ 0x81, 5, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* SUB r/m32, imm8 */{ 0x83, 5, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* SUB r/m8, r8 */{ 0x28, 0, MODRM },
|
||||||
|
/* SUB r/m32, r32 */{ 0x29, 0, MODRM },
|
||||||
|
/* SUB r8, r/m8 */{ 0x2A, 0, MODRM },
|
||||||
|
/* SUB r32, r/m32 */{ 0x2B, 0, MODRM },
|
||||||
|
/* TEST AL, imm8 */{ 0xA8, 0, IMM8 },
|
||||||
|
/* TEST EAX, imm32 */{ 0xA9, 0, IMM32 },
|
||||||
|
/* TEST r/m8, imm8 */{ 0xF6, 0, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* TEST r/m32, imm32 */{ 0xF7, 0, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* TEST r/m8, r8 */{ 0x84, 0, MODRM },
|
||||||
|
/* TEST r/m32, r32 */{ 0x85, 0, MODRM },
|
||||||
|
/* XOR AL, imm8 */{ 0x34, 0, IMM8 },
|
||||||
|
/* XOR EAX, imm32 */{ 0x35, 0, IMM32 },
|
||||||
|
/* XOR r/m8, imm8 */{ 0x80, 6, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* XOR r/m32, imm32 */{ 0x81, 6, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* XOR r/m32, imm8 */{ 0x83, 6, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* XOR r/m8, r8 */{ 0x30, 0, MODRM },
|
||||||
|
/* XOR r/m32, r32 */{ 0x31, 0, MODRM },
|
||||||
|
/* XOR r8, r/m8 */{ 0x32, 0, MODRM },
|
||||||
|
/* XOR r32, r/m32 */{ 0x33, 0, MODRM }
|
||||||
|
};
|
||||||
|
|
||||||
|
class Asm
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static size_t GetCodeLen(void* Addr)
|
||||||
|
{
|
||||||
|
unsigned char* code = (unsigned char*)Addr;
|
||||||
|
size_t i = 0, len = 0, operand_size = 4;
|
||||||
|
bool found_opcode = false;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(prefixes); i++) {
|
||||||
|
if (code[len] == prefixes[i]) {
|
||||||
|
len++;
|
||||||
|
if (prefixes[i] == 0x66) {
|
||||||
|
operand_size = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(opcodes) / sizeof(*opcodes); i++) {
|
||||||
|
if (code[len] == opcodes[i].opcode) {
|
||||||
|
if (opcodes[i].flags & REG_OPCODE) {
|
||||||
|
found_opcode = ((code[len + 1] >> 3) & 7) == opcodes[i].reg_opcode;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
found_opcode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((opcodes[i].flags & PLUS_R) && (code[len] & 0xF8) == opcodes[i].opcode) {
|
||||||
|
found_opcode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_opcode) {
|
||||||
|
len++;
|
||||||
|
//opcode = code[len++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_opcode) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opcodes[i].flags & MODRM) {
|
||||||
|
uint8_t modrm = code[len++]; /* +1 for Mod/RM byte */
|
||||||
|
uint8_t mod = modrm >> 6;
|
||||||
|
uint8_t rm = modrm & 7;
|
||||||
|
|
||||||
|
if (mod != 3 && rm == 4) {
|
||||||
|
uint8_t sib = code[len++]; /* +1 for SIB byte */
|
||||||
|
uint8_t base = sib & 7;
|
||||||
|
|
||||||
|
if (base == 5) {
|
||||||
|
/* The SIB is followed by a disp32 with no base if the MOD is 00B.
|
||||||
|
* Otherwise, disp8 or disp32 + [EBP].
|
||||||
|
*/
|
||||||
|
if (mod == 1) {
|
||||||
|
len += 1; /* for disp8 */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
len += 4; /* for disp32 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mod == 1) {
|
||||||
|
len += 1; /* for disp8 */
|
||||||
|
}
|
||||||
|
if (mod == 2 || (mod == 0 && rm == 5)) {
|
||||||
|
len += 4; /* for disp32 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opcodes[i].flags & IMM8) {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
if (opcodes[i].flags & IMM16) {
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
|
if (opcodes[i].flags & IMM32) {
|
||||||
|
len += operand_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Utils
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
size_t SysPageSize;
|
||||||
|
void *MemPool;
|
||||||
|
std::map<void*, size_t> AllocMap;
|
||||||
|
std::map<void*, size_t> FreeMap;
|
||||||
|
public:
|
||||||
|
static Utils* GetInstance()
|
||||||
|
{
|
||||||
|
static Utils* pInst = NULL;
|
||||||
|
if (!pInst)pInst = new Utils();
|
||||||
|
return pInst;
|
||||||
|
}
|
||||||
|
Utils()
|
||||||
|
{
|
||||||
|
SysPageSize = sysconf(_SC_PAGESIZE);
|
||||||
|
int fd = open("/dev/zero", O_RDONLY);
|
||||||
|
MemPool = mmap(NULL, SysPageSize * 10, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||||
|
close(fd);
|
||||||
|
FreeMap[MemPool] = SysPageSize * 10;
|
||||||
|
}
|
||||||
|
~Utils()
|
||||||
|
{
|
||||||
|
munmap(MemPool, SysPageSize * 10);
|
||||||
|
}
|
||||||
|
bool SetPageProtect(void* Address, int Protect)
|
||||||
|
{
|
||||||
|
return SetAddressProtect(Addr_Align(Address, SysPageSize), SysPageSize, Protect);
|
||||||
|
}
|
||||||
|
static bool SetAddressProtect(void* Address, size_t Size, int Protect)
|
||||||
|
{
|
||||||
|
return !mprotect(Address, Size, Protect);
|
||||||
|
}
|
||||||
|
static void MakeJmp(void* Src, void* Dst, int nNop = 0)
|
||||||
|
{
|
||||||
|
unsigned char* code = (unsigned char*)Src;
|
||||||
|
code[0] = '\xE9';
|
||||||
|
*((unsigned long*)&code[1]) = (unsigned long)Dst - (unsigned long)&code[1] - 4;
|
||||||
|
for (int i = 0; i < nNop; i++)
|
||||||
|
{
|
||||||
|
code[5 + i] = '\x90';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void* alloc(size_t _size)
|
||||||
|
{
|
||||||
|
void *pBuf = NULL;
|
||||||
|
for (std::map<void*, size_t>::iterator iter = FreeMap.begin(); iter != FreeMap.end(); iter++)
|
||||||
|
{
|
||||||
|
if (iter->second >= _size)
|
||||||
|
{
|
||||||
|
pBuf = iter->first;
|
||||||
|
FreeMap.erase(pBuf);
|
||||||
|
if (iter->second > _size)
|
||||||
|
{
|
||||||
|
FreeMap[MOVEPOINT(pBuf, _size)] = iter->second - _size;
|
||||||
|
}
|
||||||
|
AllocMap[pBuf] = _size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pBuf;
|
||||||
|
}
|
||||||
|
void free(void* _ptr)
|
||||||
|
{
|
||||||
|
size_t _size = AllocMap[_ptr];
|
||||||
|
AllocMap.erase(_ptr);
|
||||||
|
FreeMap[_ptr] = _size;
|
||||||
|
if (FreeMap.size() >= 10)
|
||||||
|
{
|
||||||
|
sortMem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void sortMem()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FuncHook
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FuncHook()
|
||||||
|
: Actived(false)
|
||||||
|
, Src(NULL)
|
||||||
|
, SrcPtr(NULL)
|
||||||
|
, Dst(NULL)
|
||||||
|
, SrcCodeSize(0)
|
||||||
|
, HookCodeSize(5)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~FuncHook()
|
||||||
|
{
|
||||||
|
this->Restore();
|
||||||
|
}
|
||||||
|
void Hook(void** SrcAddr, void* DstAddr)
|
||||||
|
{
|
||||||
|
if (!SrcAddr || !*SrcAddr || !DstAddr)return;
|
||||||
|
//恢复上次HOOK
|
||||||
|
this->Restore();
|
||||||
|
//填充数据
|
||||||
|
this->HookCodeSize = 5;
|
||||||
|
this->SrcCodeSize = 0;
|
||||||
|
this->SrcPtr = SrcAddr;
|
||||||
|
this->Src = *SrcAddr;
|
||||||
|
this->Dst = DstAddr;
|
||||||
|
//计算HOOK代码大小
|
||||||
|
do
|
||||||
|
{
|
||||||
|
this->SrcCodeSize += Asm::GetCodeLen(Move_Ptr(this->Src, this->SrcCodeSize));
|
||||||
|
} while (this->SrcCodeSize < this->HookCodeSize);
|
||||||
|
this->HookCode = (unsigned char*)Utils::GetInstance()->alloc(this->SrcCodeSize + 11);
|
||||||
|
memcpy(this->HookCode, this->Src, this->SrcCodeSize);
|
||||||
|
//修改目标地址内存权限
|
||||||
|
Utils::MakeJmp(&this->HookCode[this->SrcCodeSize], Move_Ptr(this->Src, this->SrcCodeSize), this->SrcCodeSize - this->HookCodeSize);
|
||||||
|
//修改源地址内存权限
|
||||||
|
Utils::GetInstance()->SetPageProtect(this->Src, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||||
|
Utils::MakeJmp(this->Src, this->Dst, this->SrcCodeSize - this->HookCodeSize);
|
||||||
|
*this->SrcPtr = this->HookCode;
|
||||||
|
this->Actived = true;
|
||||||
|
}
|
||||||
|
void Restore()
|
||||||
|
{
|
||||||
|
if (this->Actived)
|
||||||
|
{
|
||||||
|
//修改源地址内存写权限
|
||||||
|
Utils::GetInstance()->SetPageProtect(this->Src, PROT_READ | PROT_WRITE);
|
||||||
|
memcpy(this->Src, this->HookCode, this->SrcCodeSize);
|
||||||
|
//修改源地址内存执行权限
|
||||||
|
Utils::GetInstance()->SetPageProtect(this->Src, PROT_READ | PROT_EXEC);
|
||||||
|
this->Actived = false;
|
||||||
|
this->SrcCodeSize = 0;
|
||||||
|
*this->SrcPtr = this->Src;
|
||||||
|
if (this->HookCode)
|
||||||
|
{
|
||||||
|
Utils::GetInstance()->free(this->HookCode);
|
||||||
|
}
|
||||||
|
this->HookCode = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool Actived;
|
||||||
|
void *Src;
|
||||||
|
void **SrcPtr;
|
||||||
|
void *Dst;
|
||||||
|
unsigned char* HookCode;
|
||||||
|
size_t SrcCodeSize;
|
||||||
|
size_t HookCodeSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CodeHook
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void WriteUChar(void *Addr, unsigned char Value)
|
||||||
|
{
|
||||||
|
WriteBytes(Addr, &Value, 1);
|
||||||
|
}
|
||||||
|
static void WriteUShort(void *Addr, unsigned short Value)
|
||||||
|
{
|
||||||
|
WriteBytes(Addr, &Value, 2);
|
||||||
|
}
|
||||||
|
static void WriteUInt(void *Addr, unsigned int Value)
|
||||||
|
{
|
||||||
|
WriteBytes(Addr, &Value, 4);
|
||||||
|
}
|
||||||
|
static void WriteBytes(void *Addr, void *Data, size_t Len)
|
||||||
|
{
|
||||||
|
Utils::GetInstance()->SetPageProtect(Addr, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||||
|
memcpy(Addr, Data, Len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <execinfo.h>
|
||||||
|
#include <elf.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define PADALIGN(x,mask) ((x+mask)&(~(x%mask)))
|
||||||
|
|
||||||
|
#define Ver 1
|
||||||
|
#define Patch 2
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef int(*fnPacketGuard)(void *pInst);
|
||||||
|
|
||||||
|
typedef int(*fnaddServerHackCnt)(void *pCHackAnalyzer, void *pCUserCharacInfo, int HackType, int Cnt, int a5, int a6);
|
||||||
|
|
||||||
|
typedef int(*fnParsing)(void *pUser, int nSize);
|
||||||
|
|
||||||
|
typedef int(*fnput_header)(void *pInterfacePacketBuf, int Type, int Cmd);
|
||||||
|
|
||||||
|
typedef int(*fnIsRoutingItem)(void *pItem);
|
||||||
|
|
||||||
|
typedef int(*fnsetCharacInfoDetail)(void *pUser, int a2, int a3, void *pCHARAC_DATA);
|
||||||
|
|
||||||
|
typedef void* (*fnGetVectorUserCharacInfo)(void *pUser, int a2);
|
||||||
|
|
||||||
|
typedef int(*fnIsGameMasterMode)(void *pUser);
|
||||||
|
|
||||||
|
typedef int(*fnisGMUser)(void *pUser);
|
||||||
|
|
||||||
|
typedef int(*fnGetPvPTeamCount)(void *pDataManager);
|
||||||
|
|
||||||
|
typedef int(*fnisGM)(void *pGMAccounts, unsigned int a2);
|
||||||
|
|
||||||
|
typedef int(*fnisGM1)(void *pGM_Manager);
|
||||||
|
|
||||||
|
typedef void* (*fnset_add_info)(void *pInven_Item, int a2);
|
||||||
|
|
||||||
|
typedef int(*fndoDispatch)(void *pPacketDispatcher, void *pUser, int a3, int a4, void *src, int a6, int a7, int a8);
|
||||||
|
|
||||||
|
typedef void** (*fnget_dispatcher)(void *pPacketDispatcher, int a2);
|
||||||
|
|
||||||
|
typedef int(*fnisSocketAvatar)(void *pAvatarItemMgr1, void *pAvatarItemMgr2);
|
||||||
|
|
||||||
|
typedef int(*fndispatch_template)(void *pInst, void *pUser, void *pPacketBuf);
|
||||||
|
|
||||||
|
typedef int(*fnreach_game_world)(void *pThis, void *a2);
|
||||||
|
|
||||||
|
typedef int(*fnInter_LoadEtc_dispatch_sig)(void *pThis, void * pUser, char*a3);
|
||||||
|
|
||||||
|
typedef int(* CUserCharacInfo_getCurCharacNo)(void* pUser);
|
||||||
|
|
||||||
|
typedef char*(* CUserCharacInfo_getCurCharacName)(void* pUser);
|
||||||
|
|
||||||
|
typedef int(*fnselect) (int __nfds, fd_set *__restrict __readfds,
|
||||||
|
fd_set *__restrict __writefds,
|
||||||
|
fd_set *__restrict __exceptfds,
|
||||||
|
struct timeval *__restrict __timeout);
|
||||||
|
|
||||||
|
typedef int(*fnusleep) (__useconds_t __useconds);
|
||||||
|
|
||||||
|
typedef void* (*fnmalloc) (size_t __size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
@ -0,0 +1,457 @@
|
||||||
|
#ifndef USER_CLASS_H
|
||||||
|
#define USER_CLASS_H
|
||||||
|
#include "base.h"
|
||||||
|
#include "enum.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename R, typename A, typename ... ARG> R CallT(A call_addr, const ARG ... arguments)
|
||||||
|
{
|
||||||
|
if (!call_addr)
|
||||||
|
{
|
||||||
|
return R();
|
||||||
|
}
|
||||||
|
const auto control = reinterpret_cast<R(*)(ARG...)>(call_addr);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return control(arguments ...);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
return R();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PacketBuf;
|
||||||
|
class DB_UpdateAvatarJewelSlot;
|
||||||
|
class CInventory;
|
||||||
|
class CStackableItem;
|
||||||
|
class Inven_Item;
|
||||||
|
class CItem;
|
||||||
|
class CUserCharacInfo;
|
||||||
|
class CUser;
|
||||||
|
class PacketBuf;
|
||||||
|
class PacketGuard;
|
||||||
|
class InterfacePacketBuf;
|
||||||
|
|
||||||
|
namespace WongWork
|
||||||
|
{
|
||||||
|
|
||||||
|
class CAvatarItemMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//获取时装插槽数据
|
||||||
|
int getJewelSocketData(WongWork::CAvatarItemMgr* a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(WongWork::CAvatarItemMgr* a1, void* a2);
|
||||||
|
return ((__func)base::WongWork::CAvatarItemMgr::getJewelSocketData)(this, a2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CHackAnalyzer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int addServerHackCnt(CUserCharacInfo* a2, int a3, int a4, int a5, int a6)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(WongWork::CHackAnalyzer* a1, CUserCharacInfo* a2, int a3, int a4, int a5, int a6);
|
||||||
|
|
||||||
|
return CallT<int>(base::WongWork::CHackAnalyzer::addServerHackCnt, this, a2, a3, a4, a5, a6);
|
||||||
|
return ((__func)base::WongWork::CHackAnalyzer::addServerHackCnt)(this, a2, a3, a4, a5, a6);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class CUserCharacInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//获取角色名字
|
||||||
|
std::string getCurCharacName()
|
||||||
|
{
|
||||||
|
typedef char* (*__func)(CUserCharacInfo* a1);
|
||||||
|
return std::string(((__func)base::CUserCharacInfo::getCurCharacName)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取角色编号
|
||||||
|
int getCurCharacNo()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUserCharacInfo* a1);
|
||||||
|
return int(((__func)base::CUserCharacInfo::getCurCharacNo)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取角色上次退出游戏时间
|
||||||
|
int getCurCharacLastPlayTick()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUserCharacInfo* a1);
|
||||||
|
return int(((__func)base::CUserCharacInfo::getCurCharacLastPlayTick)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取角色等级
|
||||||
|
int get_level_up_exp(int a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUserCharacInfo* a1, int a2);
|
||||||
|
return int(((__func)base::CUserCharacInfo::get_level_up_exp)(this, a2));
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取角色背包
|
||||||
|
CInventory* getCurCharacInvenW()
|
||||||
|
{
|
||||||
|
typedef CInventory* (*__func)(CUserCharacInfo* a1);
|
||||||
|
return ((__func)base::CUserCharacInfo::getCurCharacInvenW)(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CUser : public CUserCharacInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int get_state()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUser* a1);
|
||||||
|
return int(((__func)base::CUser::get_state)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckItemLock(int a2, int a3)
|
||||||
|
{
|
||||||
|
typedef bool (*__func)(CUser* a1, int a2, int a3);
|
||||||
|
return int(((__func)base::CUser::CheckItemLock)(this, a2, a3));
|
||||||
|
}
|
||||||
|
|
||||||
|
int SendNotiPacketMessage(char* a2, int a3)
|
||||||
|
{
|
||||||
|
typedef bool (*__func)(CUser* a1, char* a2, int a3);
|
||||||
|
return int(((__func)base::CUser::SendNotiPacketMessage)(this, a2, a3));
|
||||||
|
}
|
||||||
|
|
||||||
|
//角色增加经验
|
||||||
|
int gain_exp_sp(unsigned int a2, int a3, int a4, int a5, int a6, int a7)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUserCharacInfo* a1, unsigned int a2, int a3, int a4, int a5, int a6, int a7);
|
||||||
|
return int(((__func)base::CUser::gain_exp_sp)(this, a2, a3, a4, a5, a6, a7));
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送道具
|
||||||
|
int AddItem(int a2, int a3, int a4, int a5, int a6)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUser* a1, int a2, int a3, int a4, int a5, int a6);
|
||||||
|
return int(((__func)base::CUser::AddItem)(this, a2, a3, a4, a5, a6));
|
||||||
|
}
|
||||||
|
|
||||||
|
//通知客户端道具更新(客户端指针, 通知方式[仅客户端=1, 世界广播=0, 小队=2, war room=3], itemSpace[装备=0, 时装=1], 道具所在的背包槽)
|
||||||
|
int SendUpdateItemList(int a2, int a3, int a4)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUserCharacInfo* a1, int a2, int a3, int a4);
|
||||||
|
return int(((__func)base::CUser::SendUpdateItemList)(this, a2, a3, a4));
|
||||||
|
}
|
||||||
|
|
||||||
|
int SendCmdErrorPacket(int a2, unsigned char a3)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUser* a1, int a2, unsigned char a3);
|
||||||
|
return int(((__func)base::CUser::SendCmdErrorPacket)(this, a2, a3));
|
||||||
|
}
|
||||||
|
|
||||||
|
int isEnableAvatarSocketAction()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUser* a1);
|
||||||
|
return int(((__func)base::CUser::isEnableAvatarSocketAction)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Send(PacketGuard* a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUser* a1, PacketGuard* a2);
|
||||||
|
return int(((__func)base::CUser::Send)(this, a2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CStackableItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//获取消耗品类型
|
||||||
|
int GetItemType()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(void* a1);
|
||||||
|
return ((__func)base::CStackableItem::GetItemType)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取徽章支持的镶嵌槽类型
|
||||||
|
int getJewelTargetSocket()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CStackableItem* a1);
|
||||||
|
return ((__func)base::CStackableItem::getJewelTargetSocket)(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CItem : public CStackableItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//道具是否为消耗品
|
||||||
|
int is_stackable()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CItem* a1);
|
||||||
|
return ((__func)base::CItem::is_stackable)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRoutingItem()
|
||||||
|
{
|
||||||
|
typedef bool (*__func)(CItem* a1);
|
||||||
|
return ((__func)base::CItem::IsRoutingItem)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
class Inven_Item
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//获取道具附加信息
|
||||||
|
WongWork::CAvatarItemMgr* get_add_info()
|
||||||
|
{
|
||||||
|
typedef WongWork::CAvatarItemMgr* (*__func)(Inven_Item* a1);
|
||||||
|
return ((__func)base::Inven_Item::get_add_info)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//检查背包中道具是否为空
|
||||||
|
bool isEmpty()
|
||||||
|
{
|
||||||
|
typedef bool (*__func)(Inven_Item* a1);
|
||||||
|
return ((__func)base::Inven_Item::isEmpty)(this);
|
||||||
|
}
|
||||||
|
//获取背包中道具item_id
|
||||||
|
int getKey()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(Inven_Item* a1);
|
||||||
|
return ((__func)base::Inven_Item::getKey)(this);
|
||||||
|
}
|
||||||
|
//道具是否是装备
|
||||||
|
bool isEquipableItemType()
|
||||||
|
{
|
||||||
|
typedef bool (*__func)(Inven_Item* a1);
|
||||||
|
return ((__func)base::Inven_Item::isEquipableItemType)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_ui_id()
|
||||||
|
{
|
||||||
|
return *(int*)(this + 0x7);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CDataManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static CDataManager* G_CDataManager(void)
|
||||||
|
{
|
||||||
|
typedef CDataManager* (*__func)(void);
|
||||||
|
return ((__func)base::CDataManager::G_CDataManager)();
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取装备pvf数据
|
||||||
|
CItem* find_item(int a2)
|
||||||
|
{
|
||||||
|
typedef CItem* (*__func)(CDataManager* a1, int a2);
|
||||||
|
return ((__func)base::CDataManager::find_item)(this, a2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CInventory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum INVENTORY_TYPE : int
|
||||||
|
{
|
||||||
|
INVENTORY_TYPE_BODY = 0, //身上穿的装备
|
||||||
|
INVENTORY_TYPE_ITEM = 1, //物品栏
|
||||||
|
INVENTORY_TYPE_AVARTAR = 2, //时装栏
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
//获取时装管理器
|
||||||
|
WongWork::CAvatarItemMgr* GetAvatarItemMgrR()
|
||||||
|
{
|
||||||
|
typedef WongWork::CAvatarItemMgr* (*__func)(void* a1);
|
||||||
|
return ((__func)base::CInventory::GetAvatarItemMgrR)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int delete_item(int a2, int a3, int a4, int a5, int a6)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CInventory* a1, int a2, int a3, int a4, int a5, int a6);
|
||||||
|
return ((__func)base::CInventory::delete_item)(this, a2, a3, a4, a5, a6);
|
||||||
|
}
|
||||||
|
|
||||||
|
//使用金币
|
||||||
|
int use_money(int a2, int a3, char a4)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CInventory* a1, int a2, int a3, char a4);
|
||||||
|
return ((__func)base::CInventory::use_money)(this, a2, a3, a4);
|
||||||
|
}
|
||||||
|
|
||||||
|
//获得金币
|
||||||
|
int gain_money(unsigned int a2, int a3, char a4, int a5)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CInventory* a1, unsigned int a2, int a3, char a4, int a5);
|
||||||
|
return ((__func)base::CInventory::gain_money)(this, a2, a3, a4, a5);
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取背包槽中的道具
|
||||||
|
Inven_Item* GetInvenRef(INVENTORY_TYPE a2, int a3)
|
||||||
|
{
|
||||||
|
typedef Inven_Item* (*__func)(CInventory* a1, INVENTORY_TYPE a2, int a3);
|
||||||
|
return ((__func)base::CInventory::GetInvenRef)(this, a2, a3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DB_UpdateAvatarJewelSlot
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int makeRequest(int a1, unsigned int a2, void* src)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(int a1, unsigned int a2, void* src);
|
||||||
|
return ((__func)base::DB_UpdateAvatarJewelSlot::makeRequest)(a1, a2, src);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PacketBuf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//取大小
|
||||||
|
int get_len()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(PacketBuf* a1);
|
||||||
|
return ((__func)base::PacketBuf::get_len)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//取指针
|
||||||
|
int get_buf_ptr(int a2 = 0)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(PacketBuf* a1, int a2);
|
||||||
|
return ((__func)base::PacketBuf::get_buf_ptr)(this, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
char get_byte()
|
||||||
|
{
|
||||||
|
char result;
|
||||||
|
typedef int (*__func)(PacketBuf* a1, char* a2);
|
||||||
|
if (((__func)base::PacketBuf::get_byte)(this, &result) == 1)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
short get_short()
|
||||||
|
{
|
||||||
|
short result;
|
||||||
|
typedef int (*__func)(PacketBuf* a1, short* a2);
|
||||||
|
if (((__func)base::PacketBuf::get_short)(this, &result) == 1)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_int()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
typedef int (*__func)(PacketBuf* a1, int* a2);
|
||||||
|
if (((__func)base::PacketBuf::get_int)(this, &result) == 1)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_binary(char* a2, int a3)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(PacketBuf* a1, char* a2, int a3);
|
||||||
|
return ((__func)base::PacketBuf::get_binary)(this, a2, a3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class InterfacePacketBuf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int put_header(int a2, int a3)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, int a2, int a3);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_header)(this, a2, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int put_byte(char a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, char a2);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_byte)(this, a2);
|
||||||
|
}
|
||||||
|
int put_short(short a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, short a2);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_short)(this, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int put_int(int a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, int a2);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_int)(this, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int put_binary(char* a2, int a3)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, char* a2, int a3);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_binary)(this, a2, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int finalize(bool a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, bool a2);
|
||||||
|
return ((__func)base::InterfacePacketBuf::finalize)(this, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int put_str(const char* a2, int a3)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, const char* a2, int a3);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_str)(this, a2, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int put_packet(const Inven_Item* a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, const Inven_Item* a2);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_packet)(this, a2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PacketGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static PacketGuard* NewPacketGuard()
|
||||||
|
{
|
||||||
|
void* v62 = malloc(0x20000);
|
||||||
|
typedef int (*__func)(void* a1);
|
||||||
|
((__func)base::PacketGuard::PacketGuard_make)(v62);
|
||||||
|
return (PacketGuard*)v62;
|
||||||
|
}
|
||||||
|
static void DelPacketGuard(PacketGuard* a1)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(void* a1);
|
||||||
|
((__func)base::PacketGuard::PacketGuard_destroy)(a1);
|
||||||
|
free(a1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PacketDispatcher
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int getDispatcher(int a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(PacketDispatcher* a1, int a2);
|
||||||
|
return ((__func)base::PacketDispatcher::getDispatcher)(this, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void** get_dispatcher(int a2)
|
||||||
|
{
|
||||||
|
typedef void** (*__func)(PacketDispatcher* a1, int a2);
|
||||||
|
return ((__func)base::PacketDispatcher::get_dispatcher)(this, a2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __DXFBASE_H__
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
#include <string>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#define BUFFCOUNT (3196)
|
||||||
|
#define SET_TEXTW(X) L#X
|
||||||
|
#define SET_TEXTA(X) #X
|
||||||
|
|
||||||
|
namespace Util
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief 到16进制Hex文本
|
||||||
|
* @param buf
|
||||||
|
* @param len
|
||||||
|
* @param tok
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static std::string ToHexString(const unsigned char* buf, int len, std::string tok = " ")
|
||||||
|
{
|
||||||
|
std::string output;
|
||||||
|
char temp[8] ;
|
||||||
|
for (int i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
memset(temp,0,sizeof(temp));
|
||||||
|
snprintf(temp, sizeof(temp), "%.2X", buf[i]);
|
||||||
|
output.append(temp, 2);
|
||||||
|
output.append(tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _Log(const char* formatstring, ...)
|
||||||
|
{
|
||||||
|
int nSize = 0;
|
||||||
|
char buff[BUFFCOUNT];
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
va_list args;
|
||||||
|
va_start(args, formatstring);
|
||||||
|
nSize = vsnprintf(buff, sizeof(buff), formatstring, args);
|
||||||
|
va_end(args);
|
||||||
|
char szPrINT32[BUFFCOUNT + 50] = { 0 };
|
||||||
|
sprintf(szPrINT32, "[GameHelpers] %s \n", buff);//wsprintfA
|
||||||
|
printf(szPrINT32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define LOG(format,...) Util::_Log(format,##__VA_ARGS__)
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
# 声明编译要求cmake最低版本
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
|
||||||
|
|
||||||
|
# 配置支持C++11
|
||||||
|
|
||||||
|
set(CMAKE_CXX_STANDARD 11)
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32 -fpic")
|
||||||
|
|
||||||
|
#添加头文件目录
|
||||||
|
include_directories(${PROJECT_SOURCE_DIR}/include)
|
||||||
|
|
||||||
|
# 添加库源文件
|
||||||
|
set(LIB_SOURCE
|
||||||
|
"controller.cpp"
|
||||||
|
"df_main.cpp"
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
# 添加动态库,关键词为shared
|
||||||
|
ADD_LIBRARY(hook_shared SHARED ${LIB_SOURCE})
|
||||||
|
|
||||||
|
# 指定动态库的输出名称
|
||||||
|
SET_TARGET_PROPERTIES(hook_shared PROPERTIES OUTPUT_NAME "hook")
|
||||||
|
|
||||||
|
# 指定动态库版本, 视需求而定,可不加
|
||||||
|
# VERSION:动态库版本,SOVERSION:API版本
|
||||||
|
#SET_TARGET_PROPERTIES(hook_shared PROPERTIES VERSION 0.1.1 SOVERSION 0)
|
||||||
|
|
||||||
|
# 指定库编译输出目录
|
||||||
|
SET(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib)
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace base
|
||||||
|
{
|
||||||
|
namespace CGameManager
|
||||||
|
{
|
||||||
|
const int G_CGameManager = 0x080CC18E;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Dispatcher_UseJewel
|
||||||
|
{
|
||||||
|
const int dispatch_sig = 0x8217BD6;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace GlobalData
|
||||||
|
{
|
||||||
|
const int Init = 0x08299FA0;
|
||||||
|
const int Init_fix_1 = 0x0829C075;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CParty
|
||||||
|
{
|
||||||
|
const int addDungeonClear = 0x085BDDFC;
|
||||||
|
const int addDungeonClear_fix_1 = 0x085BDE9D; //ÆÕͨ±»»÷
|
||||||
|
const int addDungeonClear_fix_2 = 0x085BDF30; //Ô¶¹Å±»»÷
|
||||||
|
const int addDungeonClear_fix_3 = 0x085BDFC3; //Òì½ç±»»÷
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CUserCharacInfo
|
||||||
|
{
|
||||||
|
const int getCurCharacName = 0x8101028;
|
||||||
|
const int getCurCharacNo = 0x080CBC4E;
|
||||||
|
const int getCurCharacLastPlayTick = 0x82A66AA;
|
||||||
|
const int get_level_up_exp = 0x0864E3BA;
|
||||||
|
const int getCurCharacInvenW = 0x80DA28E;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CUser
|
||||||
|
{
|
||||||
|
const int get_acc_id=0x080DA36E;
|
||||||
|
const int get_state = 0x080DA38C;
|
||||||
|
const int CheckItemLock = 0x8646942;
|
||||||
|
const int SendNotiPacketMessage = 0x86886CE;
|
||||||
|
const int gain_exp_sp = 0x866A3FE;
|
||||||
|
const int AddItem = 0x867B6D4;
|
||||||
|
const int SendUpdateItemList = 0x867C65A;
|
||||||
|
const int SendCmdErrorPacket = 0x0867BF42;
|
||||||
|
const int isEnableAvatarSocketAction = 0x086810A8;
|
||||||
|
const int Send = 0x86485BA;
|
||||||
|
const int setCharacInfoDetail = 0x0864AC1A;
|
||||||
|
const int IsGameMasterMode = 0x0811EDEE;
|
||||||
|
const int isGMUser = 0x0814589C;
|
||||||
|
const int exchange_interspace = 0x0865F7B0;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CStackableItem
|
||||||
|
{
|
||||||
|
const int GetItemType = 0x8514A84;
|
||||||
|
const int getJewelTargetSocket = 0x0822CA28;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CItem
|
||||||
|
{
|
||||||
|
const int is_stackable = 0x80F12FA;
|
||||||
|
const int IsRoutingItem = 0x08150F18;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace Inven_Item
|
||||||
|
{
|
||||||
|
const int get_add_info = 0x80F783A;
|
||||||
|
const int isEmpty = 0x811ED66;
|
||||||
|
const int getKey = 0x850D14E;
|
||||||
|
const int isEquipableItemType = 0x08150812;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CDataManager
|
||||||
|
{
|
||||||
|
const int G_CDataManager = 0x80CC19B;
|
||||||
|
const int find_item = 0x835FA32;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CInventory
|
||||||
|
{
|
||||||
|
const int GetAvatarItemMgrR = 0x80DD576;
|
||||||
|
const int delete_item = 0x850400C;
|
||||||
|
const int use_money = 0x84FF54C;
|
||||||
|
const int gain_money = 0x84FF29C;
|
||||||
|
const int GetInvenRef = 0x84FC1DE;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace DB_UpdateAvatarJewelSlot
|
||||||
|
{
|
||||||
|
const int makeRequest = 0x843081C;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace PacketBuf
|
||||||
|
{
|
||||||
|
const int get_len = 0x0858DA52;
|
||||||
|
const int get_buf_ptr = 0x0858DA38;
|
||||||
|
const int get_byte = 0x858CF22;
|
||||||
|
const int get_short = 0x858CFC0;
|
||||||
|
const int get_int = 0x858D27E;
|
||||||
|
const int get_binary = 0x858D3B2;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace InterfacePacketBuf
|
||||||
|
{
|
||||||
|
const int put_header = 0x080CB8FC;
|
||||||
|
const int put_byte = 0x080CB920;
|
||||||
|
const int put_short = 0x80D9EA4;
|
||||||
|
const int put_int = 0x80CB93C;
|
||||||
|
const int put_binary = 0x811DF08;
|
||||||
|
const int finalize = 0x80CB958;
|
||||||
|
const int put_str = 0x0822B770;
|
||||||
|
const int put_packet = 0x0822B794;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace PacketGuard
|
||||||
|
{
|
||||||
|
const int PacketGuard_make = 0x0858DD4C;
|
||||||
|
const int PacketGuard_destroy = 0x0858DE80;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace PacketDispatcher
|
||||||
|
{
|
||||||
|
const int getDispatcher = 0x08231F2E;
|
||||||
|
const int server_load_monitoring = 0x0825F658;
|
||||||
|
const int log_recv_packet = 0x0825F72E;
|
||||||
|
const int PacketDispatcher_make = 0x08590A2E;
|
||||||
|
const int PacketDispatcher_destroy = 0x08594840;
|
||||||
|
const int get_dispatcher = 0x085948E2;
|
||||||
|
const int doDispatch = 0x08594922;
|
||||||
|
const int dispatch = 0x08594E52;
|
||||||
|
}
|
||||||
|
namespace WongWork
|
||||||
|
{
|
||||||
|
namespace CHackAnalyzer
|
||||||
|
{
|
||||||
|
const int addServerHackCnt = 0x080F8C7E;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CGMAccounts
|
||||||
|
{
|
||||||
|
const int isGM = 0x08109346;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CAvatarItemMgr
|
||||||
|
{
|
||||||
|
const int getJewelSocketData = 0x82F98F8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CGM_Manager
|
||||||
|
{
|
||||||
|
const int isGM = 0x0829948C;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace CDataManager
|
||||||
|
{
|
||||||
|
const int GetPvPTeamCount = 0x08568CE0;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace DisPatcher_MoveItem
|
||||||
|
{
|
||||||
|
const int process = 0x081C5904; //int __cdecl DisPatcher_MoveItem::process(DisPatcher_MoveItem *this, CUser *a2, MSG_BASE *a3, ParamBase *a4)
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace cMyTrace
|
||||||
|
{
|
||||||
|
const int cMyTrace_make =0x0854F746;
|
||||||
|
const int operator_ = 0x0854F788;
|
||||||
|
const int cMyTrace_destroy =0x0854F746;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,243 @@
|
||||||
|
//************************************
|
||||||
|
// FileName: D:\VisualStudioSource\dnf_project\src\controller.cpp
|
||||||
|
// FullName: D:\VisualStudioSource\dnf_project\src
|
||||||
|
// Date: 2022/09/01
|
||||||
|
// By: Vance
|
||||||
|
// Copyright (c) 2022. Vance All rights reserved
|
||||||
|
//************************************
|
||||||
|
|
||||||
|
#include "controller.hpp"
|
||||||
|
|
||||||
|
Controller::Controller() :
|
||||||
|
old_UseJewel_dispatch_sig((UseJewel_dispatch_sig_Type*)base::Dispatcher_UseJewel::dispatch_sig),
|
||||||
|
old_PacketDispatcher_doDispatch((PacketDispatcher_doDispatch_Type*)base::PacketDispatcher::doDispatch)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Controller::~Controller()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Controller::init()
|
||||||
|
{
|
||||||
|
CodeHook::WriteUChar((void*)(base::GlobalData::Init_fix_1 - 0x1), 0);
|
||||||
|
//.text:085BDE9D 83 F8 0A cmp eax, 10
|
||||||
|
CodeHook::WriteUChar((void*)(base::CParty::addDungeonClear_fix_1 + 2), 0x7E); //普通被击
|
||||||
|
//.text:085BDF30 83 F8 1E cmp eax, 30
|
||||||
|
CodeHook::WriteUChar((void*)(base::CParty::addDungeonClear_fix_2 + 2), 0x7E); //远古被击
|
||||||
|
//.text:085BDFC3 83 F8 32 cmp eax, 50
|
||||||
|
CodeHook::WriteUChar((void*)(base::CParty::addDungeonClear_fix_3 + 2), 0x7E); //异界被击
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
mhook_PacketDispatcher_doDispatch.Hook((void**)&old_PacketDispatcher_doDispatch, (void*)hook_PacketDispatcher_doDispatch);
|
||||||
|
|
||||||
|
mhook_UseJewel_dispatch_sig.Hook((void**)&old_UseJewel_dispatch_sig, (void*)hook_UseJewel_dispatch_sig);
|
||||||
|
|
||||||
|
LOG("Controller::init()");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int Controller::hook_UseJewel_dispatch_sig(void* pDispatcher_UseJewel, CUser* pUser, PacketBuf* pBuf)
|
||||||
|
{
|
||||||
|
printf("getCurCharacName :%s \n", pUser->getCurCharacName().c_str());
|
||||||
|
printf("getCurCharacNo :%d \n", pUser->getCurCharacNo());
|
||||||
|
printf("get_buf_ptr :%p %p \n", pBuf->get_buf_ptr(0));
|
||||||
|
printf("get_len :%d \n", pBuf->get_len());
|
||||||
|
|
||||||
|
// printf("pBuf :%s \n", Util::ToHexString((const unsigned char*)pBuf->get_buf_ptr(0),40).c_str());
|
||||||
|
int state = pUser->get_state();
|
||||||
|
printf("state :%d \n", state);
|
||||||
|
//校验角色状态是否允许镶嵌
|
||||||
|
if (state != 3)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
int isEnableAvatarSocketAction = pUser->isEnableAvatarSocketAction();
|
||||||
|
if (isEnableAvatarSocketAction)
|
||||||
|
pUser->SendCmdErrorPacket(205, (unsigned char)isEnableAvatarSocketAction);
|
||||||
|
//解析packet_buf
|
||||||
|
|
||||||
|
//时装所在的背包槽
|
||||||
|
int avartar_inven_slot = pBuf->get_short();
|
||||||
|
printf("avartar_inven_slot :%d \n", avartar_inven_slot);
|
||||||
|
//时装item_id
|
||||||
|
int avartar_item_id = pBuf->get_int();
|
||||||
|
printf("avartar_item_id :%d \n", avartar_item_id);
|
||||||
|
//本次镶嵌徽章数量
|
||||||
|
int emblem_cnt = pBuf->get_byte();
|
||||||
|
printf("emblem_cnt :%d \n", emblem_cnt);
|
||||||
|
|
||||||
|
if (pUser->CheckItemLock(2, avartar_inven_slot))
|
||||||
|
{
|
||||||
|
pUser->SendCmdErrorPacket(205, 213);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取时装道具
|
||||||
|
CInventory* inven = pUser->getCurCharacInvenW();
|
||||||
|
if (!inven)
|
||||||
|
{
|
||||||
|
printf("pUser->getCurCharacInvenW : error \n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Inven_Item* avartar = inven->GetInvenRef(CInventory::INVENTORY_TYPE_AVARTAR, avartar_inven_slot);
|
||||||
|
if (!avartar)
|
||||||
|
{
|
||||||
|
printf("inven->GetInvenRef : error \n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//校验时装 数据是否合法
|
||||||
|
if (avartar->isEmpty() || (avartar->getKey() != avartar_item_id) || pUser->CheckItemLock(2, avartar_inven_slot))
|
||||||
|
{
|
||||||
|
|
||||||
|
printf("avartar->isEmpty() || avartar->getKey() || pUser->CheckItemLock() : error \n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
//获取时装插槽数据
|
||||||
|
WongWork::CAvatarItemMgr* avartar_add_info = avartar->get_add_info();
|
||||||
|
WongWork::CAvatarItemMgr* inven_avartar_mgr = inven->GetAvatarItemMgrR();
|
||||||
|
int jewel_socket_data = inven_avartar_mgr->getJewelSocketData(avartar_add_info);
|
||||||
|
if (!jewel_socket_data)
|
||||||
|
{
|
||||||
|
printf("jewel_socket_data : error \n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("jewel_socket_data :%s \n", Util::ToHexString((const unsigned char*)jewel_socket_data, 40).c_str());
|
||||||
|
if (emblem_cnt <= 3)
|
||||||
|
{
|
||||||
|
std::map<int, std::pair<int, int>> emblems;
|
||||||
|
for (int i = 0; i < emblem_cnt; i++)
|
||||||
|
{
|
||||||
|
//徽章所在的背包槽
|
||||||
|
int emblem_inven_slot = pBuf->get_short();
|
||||||
|
//徽章item_id
|
||||||
|
int emblem_item_id = pBuf->get_int();
|
||||||
|
//该徽章镶嵌的时装插槽id
|
||||||
|
int avartar_socket_slot = pBuf->get_byte();
|
||||||
|
|
||||||
|
//获取徽章道具
|
||||||
|
Inven_Item* emblem = inven->GetInvenRef(CInventory::INVENTORY_TYPE_ITEM, emblem_inven_slot);
|
||||||
|
//校验徽章及插槽数据是否合法
|
||||||
|
if (emblem->isEmpty() || (emblem->getKey() != emblem_item_id) || (avartar_socket_slot >= 3))
|
||||||
|
{
|
||||||
|
printf("emblem->isEmpty() || (emblem->getKey() : error \n");
|
||||||
|
pUser->SendCmdErrorPacket(205, 209);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//校验徽章是否满足时装插槽颜色要求
|
||||||
|
|
||||||
|
//获取徽章pvf数据
|
||||||
|
CDataManager* DataManager = CDataManager::G_CDataManager();
|
||||||
|
if (!DataManager)
|
||||||
|
{
|
||||||
|
printf("CDataManager::G_CDataManager() : error \n");
|
||||||
|
pUser->SendCmdErrorPacket(205, 209);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
CItem* citem = DataManager->find_item(emblem_item_id);
|
||||||
|
if (!citem)
|
||||||
|
{
|
||||||
|
printf("DataManager->find_item() : error \n");
|
||||||
|
pUser->SendCmdErrorPacket(205, 209);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//校验徽章类型
|
||||||
|
if (!citem->is_stackable() || (citem->GetItemType() != 20))
|
||||||
|
{
|
||||||
|
printf("citem->is_stackable() || (citem->GetItemType() : error \n");
|
||||||
|
pUser->SendCmdErrorPacket(205, 209);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取徽章支持的插槽
|
||||||
|
int emblem_socket_type = citem->getJewelTargetSocket();
|
||||||
|
|
||||||
|
//获取要镶嵌的时装插槽类型
|
||||||
|
int avartar_socket_type = *(short*)(jewel_socket_data + avartar_socket_slot * 6);
|
||||||
|
if (!(emblem_socket_type & avartar_socket_type))
|
||||||
|
{
|
||||||
|
//插槽类型不匹配
|
||||||
|
printf("emblem_socket_type & avartar_socket_type\n");
|
||||||
|
pUser->SendCmdErrorPacket(205, 209);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
printf("avartar_socket_slot:%d emblem_inven_slot:%d emblem_item_id:%d\n", avartar_socket_slot, emblem_inven_slot, emblem_item_id);
|
||||||
|
emblems[avartar_socket_slot] = std::make_pair(emblem_inven_slot, emblem_item_id);
|
||||||
|
}
|
||||||
|
printf("数据已读取!!!\n");
|
||||||
|
|
||||||
|
for (auto& avartar_socket_slot : emblems)
|
||||||
|
{
|
||||||
|
//删除徽章
|
||||||
|
int emblem_inven_slot = avartar_socket_slot.second.first;
|
||||||
|
inven->delete_item(1, emblem_inven_slot, 1, 8, 1);
|
||||||
|
|
||||||
|
//设置时装插槽数据
|
||||||
|
int emblem_item_id = avartar_socket_slot.second.second;
|
||||||
|
*(int*)(jewel_socket_data + avartar_socket_slot.first * 6 + 2) = emblem_item_id;
|
||||||
|
printf("徽章item_id=%d 已成功镶嵌进avartar_socket_slot=%d 的槽内!\n", emblem_item_id, avartar_socket_slot);
|
||||||
|
}
|
||||||
|
|
||||||
|
//时装插槽数据存档
|
||||||
|
DB_UpdateAvatarJewelSlot::makeRequest(pUser->getCurCharacNo(), avartar->get_ui_id(), (void*)jewel_socket_data);
|
||||||
|
|
||||||
|
//通知客户端时装数据已更新
|
||||||
|
pUser->SendUpdateItemList(1, 1, avartar_inven_slot);
|
||||||
|
printf("徽章镶嵌完毕!!!\n");
|
||||||
|
//回包给客户端
|
||||||
|
InterfacePacketBuf* packet_guard = (InterfacePacketBuf*)PacketGuard::NewPacketGuard();
|
||||||
|
|
||||||
|
packet_guard->put_header(1, 204);
|
||||||
|
packet_guard->put_int(1);
|
||||||
|
packet_guard->finalize(1);
|
||||||
|
pUser->Send((PacketGuard*)packet_guard);
|
||||||
|
PacketGuard::DelPacketGuard((PacketGuard*)packet_guard);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 08217C06 分解
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int Controller::hook_PacketDispatcher_doDispatch(PacketDispatcher* a1, CUser* user, int packet_class, int packet_id, void* packet_src, int pecakt_len, int a7, int a8)
|
||||||
|
{
|
||||||
|
void* pAction = *a1->get_dispatcher(packet_id);
|
||||||
|
|
||||||
|
if (pAction)
|
||||||
|
{
|
||||||
|
LOG("Recv() class:%d id:%d len:%d data:%s callback:%p %p %p %p %p %p "
|
||||||
|
, packet_class
|
||||||
|
, packet_id
|
||||||
|
, pecakt_len
|
||||||
|
, Util::ToHexString((const unsigned char*)packet_src, pecakt_len).c_str()
|
||||||
|
, *((void**)pAction)
|
||||||
|
, (void*)*((unsigned int*)pAction + 12)
|
||||||
|
, (void*)*((unsigned int*)pAction + 16)
|
||||||
|
, (void*)*((unsigned int*)pAction + 20)
|
||||||
|
, (void*)*((unsigned int*)pAction + 24)
|
||||||
|
, (void*)*((unsigned int*)pAction + 28)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG("Recv() class:%d id:%d len:%d data:%s "
|
||||||
|
, packet_class
|
||||||
|
, packet_id
|
||||||
|
, pecakt_len
|
||||||
|
, Util::ToHexString((const unsigned char*)packet_src, pecakt_len).c_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (packet_id == Packet_UseItem)
|
||||||
|
{
|
||||||
|
LOG("hook_PacketDispatcher_doDispatch packet_data :%s ", Util::ToHexString((const unsigned char*)packet_src, pecakt_len).c_str());
|
||||||
|
}
|
||||||
|
return Controller::Get()->old_PacketDispatcher_doDispatch(a1, user, packet_class, packet_id, packet_src, pecakt_len, a7, a8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
#include "import.h"
|
||||||
|
#include "Singleton.hpp"
|
||||||
|
#include "sdk_class.hpp"
|
||||||
|
#include "inline_hook.h"
|
||||||
|
#include "utils.hpp"
|
||||||
|
|
||||||
|
#define MAIN_OFFSET(offset) ((void *)((0x8048000) + (offset)))
|
||||||
|
#define SUBHOOK_INIT(func, addr) \
|
||||||
|
fn##func func = (fn##func)addr; \
|
||||||
|
FuncHook h##func
|
||||||
|
|
||||||
|
#define SUBHOOK_SETUP(func) h##func.Hook((void **)&func, (void *)_##func)
|
||||||
|
|
||||||
|
class Controller
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SINGLETON_DEFINE_S(Controller);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Controller();
|
||||||
|
~Controller();
|
||||||
|
public:
|
||||||
|
void init();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* @brief hook修复镶嵌徽章
|
||||||
|
* @param pDispatcher_UseJewel
|
||||||
|
* @param pUser
|
||||||
|
* @param pBuf
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static int hook_UseJewel_dispatch_sig(void* pDispatcher_UseJewel, CUser* pUser, PacketBuf* pBuf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief hook收包处理
|
||||||
|
* @param a1
|
||||||
|
* @param a2
|
||||||
|
* @param a3
|
||||||
|
* @param a4
|
||||||
|
* @param src
|
||||||
|
* @param a6
|
||||||
|
* @param a7
|
||||||
|
* @param a8
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static int hook_PacketDispatcher_doDispatch(PacketDispatcher* a1, CUser* a2, int a3, int packet_id, void* packet_src, int pecakt_len, int a7, int a8);
|
||||||
|
|
||||||
|
private:
|
||||||
|
using UseJewel_dispatch_sig_Type = decltype(hook_UseJewel_dispatch_sig);
|
||||||
|
UseJewel_dispatch_sig_Type* old_UseJewel_dispatch_sig;
|
||||||
|
|
||||||
|
using PacketDispatcher_doDispatch_Type = decltype(hook_PacketDispatcher_doDispatch);
|
||||||
|
PacketDispatcher_doDispatch_Type* old_PacketDispatcher_doDispatch;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
FuncHook mhook_UseJewel_dispatch_sig;
|
||||||
|
FuncHook mhook_PacketDispatcher_doDispatch;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,647 @@
|
||||||
|
#include "import.h"
|
||||||
|
#include "controller.hpp"
|
||||||
|
|
||||||
|
char szGamePath[256];
|
||||||
|
int n_sleep_time = 10000;
|
||||||
|
int bGMMode = 0, bFairPVP = 0, bPickupRout = 0;
|
||||||
|
|
||||||
|
//SUBHOOK_INIT(PacketGuard, 0x0858DD4C);
|
||||||
|
SUBHOOK_INIT(GetVectorUserCharacInfo, 0x081A0BB8);
|
||||||
|
SUBHOOK_INIT(doDispatch, 0x08594922);
|
||||||
|
SUBHOOK_INIT(addServerHackCnt, 0x080F8C7E);
|
||||||
|
SUBHOOK_INIT(put_header, 0x080CB8FC);
|
||||||
|
SUBHOOK_INIT(IsRoutingItem, 0x08150F18);
|
||||||
|
SUBHOOK_INIT(setCharacInfoDetail, 0x0864AC1A);
|
||||||
|
SUBHOOK_INIT(IsGameMasterMode, 0x0811EDEE);
|
||||||
|
SUBHOOK_INIT(isGMUser, 0x0814589C);
|
||||||
|
SUBHOOK_INIT(GetPvPTeamCount, 0x08568CE0);
|
||||||
|
SUBHOOK_INIT(isGM, 0x08109346);
|
||||||
|
SUBHOOK_INIT(isGM1, 0x0829948C);
|
||||||
|
SUBHOOK_INIT(set_add_info, 0x080CB884);
|
||||||
|
SUBHOOK_INIT(get_dispatcher, 0x085948E2);
|
||||||
|
SUBHOOK_INIT(dispatch_template, 0x081258B6);
|
||||||
|
SUBHOOK_INIT(isSocketAvatar, 0x082F9228);
|
||||||
|
SUBHOOK_INIT(reach_game_world, 0x086C4E50);
|
||||||
|
SUBHOOK_INIT(Inter_LoadEtc_dispatch_sig, 0x084C0264);
|
||||||
|
|
||||||
|
//_setCharacInfoDetail
|
||||||
|
|
||||||
|
int checkGame(const char* pName)
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
char* path_end;
|
||||||
|
|
||||||
|
memset(path, 0, sizeof(path));
|
||||||
|
if (readlink("/proc/self/exe", path, sizeof(path)) <= 0)return -1;
|
||||||
|
path_end = strrchr(path, '/');
|
||||||
|
if (!path_end || strlen(path_end) < 9)return -1;
|
||||||
|
return strcmp(pName, ++path_end);
|
||||||
|
}
|
||||||
|
|
||||||
|
int open_main_module_file()
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
memset(path, 0, sizeof(path));
|
||||||
|
if (readlink("/proc/self/exe", path, sizeof(path)) <= 0)return -1;
|
||||||
|
return open(path, O_RDONLY);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getargs(char*** argv)
|
||||||
|
{
|
||||||
|
size_t buflen = 1024, readlen = 0, maxlen = buflen;
|
||||||
|
int fd = open("/proc/self/cmdline", O_RDONLY);
|
||||||
|
if (fd == -1)return 0;
|
||||||
|
char* buf = (char*)malloc(buflen);
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
ssize_t n = read(fd, buf + readlen, buflen - readlen);
|
||||||
|
if (n == -1)
|
||||||
|
{
|
||||||
|
free(buf);
|
||||||
|
close(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
readlen += n;
|
||||||
|
if (!n || readlen < buflen)break;
|
||||||
|
maxlen += buflen;
|
||||||
|
buf = (char*)realloc(buf, maxlen);
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
int argc = 0;
|
||||||
|
char* cp = buf;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
while (*cp != '\0')cp++;
|
||||||
|
argc++;
|
||||||
|
} while (++cp < buf + readlen);
|
||||||
|
*argv = (char**)malloc(argc * sizeof(char*));
|
||||||
|
argc = 0;
|
||||||
|
cp = buf;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
(*argv)[argc] = (char*)malloc(strlen(cp) + 1);
|
||||||
|
strcpy((*argv)[argc], cp);
|
||||||
|
argc++;
|
||||||
|
while (*cp != '\0')cp++;
|
||||||
|
} while (++cp < buf + readlen);
|
||||||
|
free(buf);
|
||||||
|
return argc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int getConfigPath(char* pPath, size_t nSize)
|
||||||
|
{
|
||||||
|
if (readlink("/proc/self/exe", pPath, nSize) <= 0)return -1;
|
||||||
|
char** argv = NULL;
|
||||||
|
int argc = getargs(&argv);
|
||||||
|
if (!argv || argc < 2)
|
||||||
|
{
|
||||||
|
if (argv)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (argv[i])free(argv[i]);
|
||||||
|
}
|
||||||
|
free(argv);
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
*strrchr(pPath, '/') = '\0';
|
||||||
|
sprintf(pPath, "%s/cfg/%s.cfg", pPath, argv[1]);
|
||||||
|
for (int i = 0; i < argc; i++)
|
||||||
|
{
|
||||||
|
if (argv[i])free(argv[i]);
|
||||||
|
}
|
||||||
|
free(argv);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetProfileString(const char* profile, const char* section, const char* key, char** val)
|
||||||
|
{
|
||||||
|
int hFile = open(profile, O_RDONLY);
|
||||||
|
if (hFile == -1)return -1;
|
||||||
|
struct stat st;
|
||||||
|
fstat(hFile, &st);
|
||||||
|
void* pFileData = mmap(0, st.st_size, PROT_READ, MAP_SHARED, hFile, 0);
|
||||||
|
if (!pFileData)
|
||||||
|
{
|
||||||
|
close(hFile);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
unsigned char readSection = 0, readKey = 1, readValue = 0, got = 0, notes = 0;
|
||||||
|
char* cur = (char*)pFileData, * end = (char*)pFileData + st.st_size;
|
||||||
|
char* sectionbuf = (char*)malloc(1024)
|
||||||
|
, * keybuf = (char*)malloc(1024)
|
||||||
|
, * valuebuf = (char*)malloc(1024);
|
||||||
|
memset(sectionbuf, 0, 1024);
|
||||||
|
memset(keybuf, 0, 1024);
|
||||||
|
memset(valuebuf, 0, 1024);
|
||||||
|
int i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (notes && *cur != '\n')continue;
|
||||||
|
switch (*cur)
|
||||||
|
{
|
||||||
|
case '#':
|
||||||
|
notes = 1;
|
||||||
|
break;
|
||||||
|
case ' ':
|
||||||
|
case '\t':
|
||||||
|
//jump space
|
||||||
|
break;
|
||||||
|
case '\n':
|
||||||
|
//new line
|
||||||
|
if (readValue)
|
||||||
|
{
|
||||||
|
valuebuf[i] = '\0';
|
||||||
|
if (!strcmp(section, sectionbuf) && !strcmp(key, keybuf))
|
||||||
|
{
|
||||||
|
*val = (char*)malloc(i + 1);
|
||||||
|
memset(*val, 0, i + 1);
|
||||||
|
strcpy(*val, valuebuf);
|
||||||
|
got = 1;
|
||||||
|
}
|
||||||
|
//printf("value:%s\n", valuebuf);
|
||||||
|
}
|
||||||
|
notes = 0, readSection = 0, readKey = 1, readValue = 0, i = 0;
|
||||||
|
break;
|
||||||
|
case '[':
|
||||||
|
//section begin
|
||||||
|
readSection = 1;
|
||||||
|
readKey = 0;
|
||||||
|
readValue = 0;
|
||||||
|
i = 0;
|
||||||
|
break;
|
||||||
|
case ']':
|
||||||
|
//section end
|
||||||
|
if (readSection)
|
||||||
|
{
|
||||||
|
sectionbuf[i] = '\0';
|
||||||
|
//printf("section:%s\n", sectionbuf);
|
||||||
|
readSection = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '=':
|
||||||
|
if (readKey)
|
||||||
|
{
|
||||||
|
keybuf[i] = '\0';
|
||||||
|
//printf("key:%s\n", keybuf);
|
||||||
|
readSection = 0;
|
||||||
|
readKey = 0;
|
||||||
|
readValue = 1;
|
||||||
|
i = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (readSection)
|
||||||
|
{
|
||||||
|
sectionbuf[i++] = *cur;
|
||||||
|
}
|
||||||
|
else if (readKey)
|
||||||
|
{
|
||||||
|
keybuf[i++] = *cur;
|
||||||
|
}
|
||||||
|
else if (readValue)
|
||||||
|
{
|
||||||
|
valuebuf[i++] = *cur;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while (++cur != end && !got);
|
||||||
|
free(sectionbuf);
|
||||||
|
free(keybuf);
|
||||||
|
free(valuebuf);
|
||||||
|
munmap(pFileData, st.st_size);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int GetProfileInt(const char* profile, const char* section, const char* key)
|
||||||
|
{
|
||||||
|
int ival = 0;
|
||||||
|
char* pValue = NULL;
|
||||||
|
if (GetProfileString(profile, section, key, &pValue) || !pValue)return 0;
|
||||||
|
ival = atoi(pValue);
|
||||||
|
free(pValue);
|
||||||
|
return ival;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf32_Shdr* get_section_by_type(Elf32_Ehdr* pHeader, Elf32_Shdr* pSectionHeaderTable, Elf32_Word sh_type)
|
||||||
|
{
|
||||||
|
Elf32_Half i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (pSectionHeaderTable[i].sh_type == sh_type)
|
||||||
|
{
|
||||||
|
return &pSectionHeaderTable[i];
|
||||||
|
}
|
||||||
|
} while (++i < pHeader->e_shnum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf32_Shdr* get_section_by_index(Elf32_Ehdr* pHeader, Elf32_Shdr* pSectionHeaderTable, Elf32_Half i)
|
||||||
|
{
|
||||||
|
if (i < pHeader->e_shnum)
|
||||||
|
{
|
||||||
|
return &pSectionHeaderTable[i];
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Elf32_Shdr* get_section_by_name(Elf32_Ehdr* pHeader, Elf32_Shdr* pSectionHeaderTable, const char* pSymStrTbl, const char* pName)
|
||||||
|
{
|
||||||
|
Elf32_Half i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!strcmp(pName, &pSymStrTbl[pSectionHeaderTable[i].sh_name]))
|
||||||
|
{
|
||||||
|
return &pSectionHeaderTable[i];
|
||||||
|
}
|
||||||
|
} while (++i < pHeader->e_shnum);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_symbol_index_by_name(Elf32_Sym* pSymbolTbl, int nSymbols, const char* pSymStrTbl, const char* pName)
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (ELF32_ST_TYPE(pSymbolTbl[i].st_info) == STT_FUNC && !strcmp(pName, &pSymStrTbl[pSymbolTbl[i].st_name]))
|
||||||
|
{
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
} while (++i < nSymbols);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* replaceIAT(const char* pName, void* pAddr)
|
||||||
|
{
|
||||||
|
void* pOrgAddr = NULL;
|
||||||
|
|
||||||
|
int hFile = open_main_module_file();
|
||||||
|
if (hFile != -1)
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
fstat(hFile, &st);
|
||||||
|
void* pFileData = mmap(0, st.st_size, PROT_READ, MAP_SHARED, hFile, 0);
|
||||||
|
if (pFileData)
|
||||||
|
{
|
||||||
|
Elf32_Ehdr* pHeader = (Elf32_Ehdr*)pFileData;
|
||||||
|
Elf32_Shdr* pSectionHeaderTable = (Elf32_Shdr*)((char*)pHeader + pHeader->e_shoff);
|
||||||
|
Elf32_Shdr* pSymSection = get_section_by_type(pHeader, pSectionHeaderTable, SHT_DYNSYM);
|
||||||
|
Elf32_Shdr* pSymStrSection = get_section_by_index(pHeader, pSectionHeaderTable, pSymSection->sh_link);
|
||||||
|
Elf32_Sym* pSymbolTbl = (Elf32_Sym*)((char*)pHeader + pSymSection->sh_offset);
|
||||||
|
const char* pSymStrTbl = (const char*)((char*)pHeader + pSymStrSection->sh_offset);
|
||||||
|
unsigned int iSymbol = get_symbol_index_by_name(pSymbolTbl, pSymSection->sh_size / sizeof(Elf32_Sym), pSymStrTbl, pName);
|
||||||
|
Elf32_Shdr* pStrSection = get_section_by_index(pHeader, pSectionHeaderTable, pHeader->e_shstrndx);
|
||||||
|
const char* pStrTbl = (const char*)((char*)pHeader + pStrSection->sh_offset);
|
||||||
|
Elf32_Shdr* pRelPltSection = get_section_by_name(pHeader, pSectionHeaderTable, pStrTbl, ".rel.plt");
|
||||||
|
Elf32_Shdr* pRelDynSection = get_section_by_name(pHeader, pSectionHeaderTable, pStrTbl, ".rel.dyn");
|
||||||
|
Elf32_Rel* pRelPlt = (Elf32_Rel*)(0x8047000 + pRelPltSection->sh_offset);
|
||||||
|
Elf32_Rel* pRelDyn = (Elf32_Rel*)(0x8047000 + pRelDynSection->sh_offset);
|
||||||
|
int nRelPlt = pRelPltSection->sh_size / sizeof(Elf32_Rel);
|
||||||
|
int nRelDyn = pRelDynSection->sh_size / sizeof(Elf32_Rel);
|
||||||
|
for (int i = 0; i < nRelPlt; i++)
|
||||||
|
{
|
||||||
|
if (ELF32_R_SYM(pRelPlt[i].r_info) == iSymbol && pRelPlt[i].r_offset)
|
||||||
|
{
|
||||||
|
pOrgAddr = *(void**)pRelPlt[i].r_offset;
|
||||||
|
*(void**)pRelPlt[i].r_offset = pAddr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!pOrgAddr)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < nRelDyn; i++)
|
||||||
|
{
|
||||||
|
if (ELF32_R_SYM(pRelDyn[i].r_info) == iSymbol && pRelDyn[i].r_offset)
|
||||||
|
{
|
||||||
|
void** jmpAddr = (void**)pRelDyn[i].r_offset;
|
||||||
|
//printf("jmpaddr::::::::::::::::::::%X\n", pRelDyn[i].r_offset);
|
||||||
|
pOrgAddr = (void*)((char*)(*jmpAddr) + (int)jmpAddr + sizeof(void*));
|
||||||
|
CodeHook::WriteBytes(pOrgAddr, &pAddr, sizeof(pAddr));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
munmap(pFileData, st.st_size);
|
||||||
|
}
|
||||||
|
close(hFile);
|
||||||
|
}
|
||||||
|
return pOrgAddr;
|
||||||
|
}
|
||||||
|
|
||||||
|
int my_select(int __nfds, fd_set* __restrict __readfds,
|
||||||
|
fd_set* __restrict __writefds,
|
||||||
|
fd_set* __restrict __exceptfds,
|
||||||
|
struct timeval* __restrict __timeout)
|
||||||
|
{
|
||||||
|
if (!__nfds && !__readfds && !__writefds && !__exceptfds)
|
||||||
|
{
|
||||||
|
if (!__timeout->tv_sec && __timeout->tv_usec >= 0 && __timeout->tv_usec <= 1000)
|
||||||
|
{
|
||||||
|
__timeout->tv_usec = n_sleep_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return select(__nfds, __readfds, __writefds, __exceptfds, __timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int my_usleep(__useconds_t __useconds)
|
||||||
|
{
|
||||||
|
if (__useconds >= 0 && __useconds <= 1000)
|
||||||
|
{
|
||||||
|
__useconds = n_sleep_time;
|
||||||
|
}
|
||||||
|
return usleep(__useconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void* my_malloc (size_t __size)
|
||||||
|
{
|
||||||
|
if (__size > 100 * 1024 * 1024)
|
||||||
|
{
|
||||||
|
char path[256];
|
||||||
|
memset(path, 0, sizeof(path));
|
||||||
|
readlink("/proc/self/exe", path, sizeof(path));
|
||||||
|
printf("**********************************[%s][malloc]: %.2f\n", path, (double)__size / 1024 / 1024);
|
||||||
|
print_backtrace(2);
|
||||||
|
}
|
||||||
|
return malloc(__size);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
int _doDispatch(void* pPacketDispatcher, void* pUser, int a3, int a4, void* src, int a6, int a7, int a8)//收包处理
|
||||||
|
{
|
||||||
|
void* pAction = *get_dispatcher(pPacketDispatcher, a4);
|
||||||
|
if (pAction)
|
||||||
|
{
|
||||||
|
//printf("Recv() cs:%d cmd:%d len:%d callback:%p\t%p\t%p\t%p\t%p\t%p\n"
|
||||||
|
// , a3
|
||||||
|
// , a4
|
||||||
|
// , a6
|
||||||
|
// , *((void**)pAction)
|
||||||
|
// , (void*)*((unsigned int*)pAction + 12)
|
||||||
|
// , (void*)*((unsigned int*)pAction + 16)
|
||||||
|
// , (void*)*((unsigned int*)pAction + 20)
|
||||||
|
// , (void*)*((unsigned int*)pAction + 24)
|
||||||
|
// , (void*)*((unsigned int*)pAction + 28)
|
||||||
|
//);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//printf("Recv() cs:%d cmd:%d len:%d\n"
|
||||||
|
// , a3
|
||||||
|
// , a4
|
||||||
|
// , a6);
|
||||||
|
}
|
||||||
|
return doDispatch(pPacketDispatcher, pUser, a3, a4, src, a6, a7, a8);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int _dispatch_template(void* pInst, void* pUser, void* pPacketBuf)
|
||||||
|
{
|
||||||
|
char* buf = (char*)(*((unsigned int*)pPacketBuf + 5));
|
||||||
|
//printf("Recv() cs:%d cmd:%d len:%d callback:%p|%p|%p|%p|%p\n"
|
||||||
|
// , buf[0]
|
||||||
|
// , *((unsigned short*)&buf[1])
|
||||||
|
// , *((unsigned int*)&buf[3])
|
||||||
|
// , *((void**)*((unsigned int*)pInst + 12))
|
||||||
|
// , *((void**)*((unsigned int*)pInst + 16))
|
||||||
|
// , *((void**)*((unsigned int*)pInst + 20))
|
||||||
|
// , *((void**)*((unsigned int*)pInst + 24))
|
||||||
|
// , *((void**)*((unsigned int*)pInst + 28))
|
||||||
|
//);
|
||||||
|
return dispatch_template(pInst, pUser, pPacketBuf);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _addServerHackCnt(void* pCHackAnalyzer, void* pCUserCharacInfo, int HackType, int Cnt, int a5, int a6)
|
||||||
|
{
|
||||||
|
//printf("addServerHackCnt() HackType:%d \n", HackType);
|
||||||
|
//char pack_buf[0xC];
|
||||||
|
//PacketGuard(pack_buf);
|
||||||
|
return addServerHackCnt(pCHackAnalyzer, pCUserCharacInfo, HackType, Cnt, a5, a6);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _put_header(void* pInterfacePacketBuf, int Type, int Cmd)
|
||||||
|
{
|
||||||
|
//printf("Send() cmd:%d\n", Cmd);
|
||||||
|
return put_header(pInterfacePacketBuf, Type, Cmd);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _IsRoutingItem(void* pItem)
|
||||||
|
{
|
||||||
|
//拾取掷点
|
||||||
|
return bPickupRout && (*((unsigned int*)pItem + 14) == 4 || *((unsigned char*)pItem + 189));
|
||||||
|
}
|
||||||
|
|
||||||
|
int _setCharacInfoDetail(void* pUser, int a2, int a3, void* pCHARAC_DATA)
|
||||||
|
{
|
||||||
|
//下线位置
|
||||||
|
unsigned char curArea = *((unsigned char*)pCHARAC_DATA + 34);
|
||||||
|
int ret = setCharacInfoDetail(pUser, a2, a3, pCHARAC_DATA);
|
||||||
|
if (curArea == 12 || curArea == 13)
|
||||||
|
{
|
||||||
|
*((char*)GetVectorUserCharacInfo((char*)pUser + 497384, a2) + 34) = 11;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _IsGameMasterMode(void* pUser)
|
||||||
|
{
|
||||||
|
//gm
|
||||||
|
return bGMMode || *((unsigned char*)pUser + 463320) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _isGMUser(void* pUser)
|
||||||
|
{
|
||||||
|
//gm
|
||||||
|
//printf("%s\n", __FUNCTION__);
|
||||||
|
return bGMMode || (*((unsigned char*)pUser + 463320) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _isGM(void* pGMAccounts, unsigned int a2)
|
||||||
|
{
|
||||||
|
//gm
|
||||||
|
//printf("%s\n", __FUNCTION__);
|
||||||
|
return bGMMode || isGM(pGMAccounts, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _isGM1(void* pGM_Manager)
|
||||||
|
{
|
||||||
|
//gm
|
||||||
|
//printf("%s\n", __FUNCTION__);
|
||||||
|
return bGMMode || isGM1(pGM_Manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _GetPvPTeamCount(void* pDataManager)
|
||||||
|
{
|
||||||
|
if (bFairPVP)return 10;
|
||||||
|
return *((unsigned int*)pDataManager + 11540);
|
||||||
|
}
|
||||||
|
|
||||||
|
void* _set_add_info(void* pInven_Item, int a2)
|
||||||
|
{
|
||||||
|
if ((unsigned int)__builtin_return_address(0) == 0x0820156C)
|
||||||
|
{
|
||||||
|
char* _esp = NULL;
|
||||||
|
__asm__ __volatile__("movl %%esp, %[a1];": [a1] "=m"(_esp));
|
||||||
|
if (_esp) {
|
||||||
|
for (int i = 0; i < 200; i++) {
|
||||||
|
if (897 == *((unsigned int*)&_esp[i]))
|
||||||
|
{
|
||||||
|
//printf("Get !!! %X\n", i);
|
||||||
|
a2 = GetProfileInt(szGamePath, "", "val");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//printf("====================_set_add_info======================%d\n", a2);
|
||||||
|
}
|
||||||
|
return set_add_info(pInven_Item, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _isSocketAvatar(void* pAvatarItemMgr1, void* pAvatarItemMgr2)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int _reach_game_world(void* pThis, void* a2)
|
||||||
|
{
|
||||||
|
return reach_game_world(pThis, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _Inter_LoadEtc_dispatch_sig(void* pThis, void* pUser, char* a3)
|
||||||
|
{
|
||||||
|
int result = Inter_LoadEtc_dispatch_sig(pThis, pUser, a3);
|
||||||
|
printf("_Inter_LoadEtc_dispatch_sig begin");
|
||||||
|
|
||||||
|
//typedef double(__cdecl* FN_sqrt)(_In_ double _X);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
CUserCharacInfo_getCurCharacNo getCurCharacNo = (CUserCharacInfo_getCurCharacNo)(0x080CBC4E);
|
||||||
|
int CurCharacNo = getCurCharacNo(pUser);
|
||||||
|
printf("CurCharacNo :%d", CurCharacNo);
|
||||||
|
|
||||||
|
CUserCharacInfo_getCurCharacName getCurCharacName = (CUserCharacInfo_getCurCharacName)0x8101028;
|
||||||
|
|
||||||
|
char* name = getCurCharacName(pUser);
|
||||||
|
printf("CurCharacName :%s", name);
|
||||||
|
|
||||||
|
printf("_Inter_LoadEtc_dispatch_sig end");
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void loga()
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
if (!checkGame("df_game_r"))
|
||||||
|
{
|
||||||
|
int a = 1;
|
||||||
|
void* buf = malloc(4);
|
||||||
|
CodeHook::WriteBytes(buf, &a, 4);
|
||||||
|
getConfigPath(szGamePath, sizeof(szGamePath));
|
||||||
|
unsigned int nMaxGrade = 80;
|
||||||
|
bGMMode = 1;
|
||||||
|
|
||||||
|
|
||||||
|
//max_level = nMaxGrade;
|
||||||
|
|
||||||
|
//ServerParameterScript::setDungeonOpen
|
||||||
|
|
||||||
|
//CodeHook::WriteUChar(MAIN_OFFSET(0x22069B), 0x01);
|
||||||
|
//ServerParameterScript::isDungeonOpen
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x220894), 0x01);
|
||||||
|
//Init DataManager
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x258E80), 0xEB);
|
||||||
|
//Init Level Exp
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x314ECB), 0xEB);
|
||||||
|
//Init Mob Reward
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x314FCB), 0xEB);
|
||||||
|
//CDataManager::GetSpAtLevelUp
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318CC8), 0xE6);
|
||||||
|
//fixbug
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31C128), 0x7E);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x31C129), 0x06);
|
||||||
|
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x547005), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61AF55), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61B0F3), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61DD28), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61E86A), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61EE9C), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x6224A8), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622929), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x641D4B), nMaxGrade - 1);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647ECE), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647EDA), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647F82), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x647F88), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x66521D), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x665223), nMaxGrade);
|
||||||
|
//SUBHOOK_SETUP(doDispatch);
|
||||||
|
SUBHOOK_SETUP(addServerHackCnt);
|
||||||
|
SUBHOOK_SETUP(put_header);
|
||||||
|
SUBHOOK_SETUP(IsRoutingItem);
|
||||||
|
SUBHOOK_SETUP(setCharacInfoDetail);
|
||||||
|
SUBHOOK_SETUP(IsGameMasterMode);
|
||||||
|
SUBHOOK_SETUP(isGMUser);
|
||||||
|
SUBHOOK_SETUP(isGM);
|
||||||
|
SUBHOOK_SETUP(isGM1);
|
||||||
|
SUBHOOK_SETUP(GetPvPTeamCount);
|
||||||
|
SUBHOOK_SETUP(set_add_info);
|
||||||
|
SUBHOOK_SETUP(reach_game_world);
|
||||||
|
SUBHOOK_SETUP(Inter_LoadEtc_dispatch_sig);
|
||||||
|
Controller::Get()->init();
|
||||||
|
//SUBHOOK_SETUP(isSocketAvatar);
|
||||||
|
if (nMaxGrade > 70)
|
||||||
|
{
|
||||||
|
//以下需要扩充类大小, 修改偏移
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x87162 + 3), 0xB678 + nMaxGrade * 4 + nMaxGrade * 12);
|
||||||
|
//CDataManager::set_reward_sp
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x318C26 + 2), 10836 + 840);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318C3B), nMaxGrade);
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x318C68 + 2), 10836 + 840);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318C79), nMaxGrade);
|
||||||
|
//CDataManager::GetSpAtLevelUp
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x318CC4), nMaxGrade);
|
||||||
|
CodeHook::WriteUInt(MAIN_OFFSET(0x318CD4 + 2), 10836 + 840);
|
||||||
|
}
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x61B8F6), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622659), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622941), nMaxGrade);
|
||||||
|
CodeHook::WriteUChar(MAIN_OFFSET(0x622941), nMaxGrade);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PrintTag()
|
||||||
|
{
|
||||||
|
printf("\n");
|
||||||
|
printf("**********************************************************\n");
|
||||||
|
printf("* DNF Server Plugin V%d.%02d *\n", Ver, Patch);
|
||||||
|
printf("* *\n");
|
||||||
|
printf("* /\\ /\\ *\n");
|
||||||
|
printf("* *\n");
|
||||||
|
printf("* __ Auther:Larva *\n");
|
||||||
|
printf("* QQ Group:81411049 *\n");
|
||||||
|
printf("**********************************************************\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void __attribute__((constructor)) my_init(void)
|
||||||
|
{
|
||||||
|
PrintTag();
|
||||||
|
//patchGame();
|
||||||
|
loga();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
#pragma once
|
||||||
|
enum ENUM_PACKET_ID
|
||||||
|
{
|
||||||
|
Packet_UseItem = 84,
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#include <execinfo.h>
|
||||||
|
#include <elf.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define PADALIGN(x,mask) ((x+mask)&(~(x%mask)))
|
||||||
|
|
||||||
|
#define Ver 1
|
||||||
|
#define Patch 2
|
||||||
|
|
||||||
|
__BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef int(*fnPacketGuard)(void *pInst);
|
||||||
|
|
||||||
|
typedef int(*fnaddServerHackCnt)(void *pCHackAnalyzer, void *pCUserCharacInfo, int HackType, int Cnt, int a5, int a6);
|
||||||
|
|
||||||
|
typedef int(*fnParsing)(void *pUser, int nSize);
|
||||||
|
|
||||||
|
typedef int(*fnput_header)(void *pInterfacePacketBuf, int Type, int Cmd);
|
||||||
|
|
||||||
|
typedef int(*fnIsRoutingItem)(void *pItem);
|
||||||
|
|
||||||
|
typedef int(*fnsetCharacInfoDetail)(void *pUser, int a2, int a3, void *pCHARAC_DATA);
|
||||||
|
|
||||||
|
typedef void* (*fnGetVectorUserCharacInfo)(void *pUser, int a2);
|
||||||
|
|
||||||
|
typedef int(*fnIsGameMasterMode)(void *pUser);
|
||||||
|
|
||||||
|
typedef int(*fnisGMUser)(void *pUser);
|
||||||
|
|
||||||
|
typedef int(*fnGetPvPTeamCount)(void *pDataManager);
|
||||||
|
|
||||||
|
typedef int(*fnisGM)(void *pGMAccounts, unsigned int a2);
|
||||||
|
|
||||||
|
typedef int(*fnisGM1)(void *pGM_Manager);
|
||||||
|
|
||||||
|
typedef void* (*fnset_add_info)(void *pInven_Item, int a2);
|
||||||
|
|
||||||
|
typedef int(*fndoDispatch)(void *pPacketDispatcher, void *pUser, int a3, int a4, void *src, int a6, int a7, int a8);
|
||||||
|
|
||||||
|
typedef void** (*fnget_dispatcher)(void *pPacketDispatcher, int a2);
|
||||||
|
|
||||||
|
typedef int(*fnisSocketAvatar)(void *pAvatarItemMgr1, void *pAvatarItemMgr2);
|
||||||
|
|
||||||
|
typedef int(*fndispatch_template)(void *pInst, void *pUser, void *pPacketBuf);
|
||||||
|
|
||||||
|
typedef int(*fnreach_game_world)(void *pThis, void *a2);
|
||||||
|
|
||||||
|
typedef int(*fnInter_LoadEtc_dispatch_sig)(void *pThis, void * pUser, char*a3);
|
||||||
|
|
||||||
|
typedef int(* CUserCharacInfo_getCurCharacNo)(void* pUser);
|
||||||
|
|
||||||
|
typedef char*(* CUserCharacInfo_getCurCharacName)(void* pUser);
|
||||||
|
|
||||||
|
typedef int(*fnselect) (int __nfds, fd_set *__restrict __readfds,
|
||||||
|
fd_set *__restrict __writefds,
|
||||||
|
fd_set *__restrict __exceptfds,
|
||||||
|
struct timeval *__restrict __timeout);
|
||||||
|
|
||||||
|
typedef int(*fnusleep) (__useconds_t __useconds);
|
||||||
|
|
||||||
|
typedef void* (*fnmalloc) (size_t __size);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
__END_DECLS
|
||||||
|
|
@ -0,0 +1,381 @@
|
||||||
|
#pragma once
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <map>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
|
#define MOVEPOINT(p,i) (void*)((char*)p+i)
|
||||||
|
#define MAKEPOINTER(t, p, offset) ((t)((unsigned char*)(p) + (long)offset))
|
||||||
|
#define PADALIGN(x,mask) ((x+mask)&(~(x%mask)))
|
||||||
|
#define Addr_Align(addr,mask) ((void*)(((unsigned long)(addr))&(~((mask)-1))))
|
||||||
|
#define Move_Ptr(addr,offset) ((void*)((unsigned long)(addr)+(offset)))
|
||||||
|
|
||||||
|
enum flags {
|
||||||
|
MODRM = 1,
|
||||||
|
PLUS_R = 1 << 1,
|
||||||
|
REG_OPCODE = 1 << 2,
|
||||||
|
IMM8 = 1 << 3,
|
||||||
|
IMM16 = 1 << 4,
|
||||||
|
IMM32 = 1 << 5,
|
||||||
|
RELOC = 1 << 6
|
||||||
|
};
|
||||||
|
struct opcode_info {
|
||||||
|
unsigned char opcode;
|
||||||
|
unsigned char reg_opcode;
|
||||||
|
unsigned int flags;
|
||||||
|
};
|
||||||
|
static unsigned char prefixes[] = {
|
||||||
|
0xF0, 0xF2, 0xF3,
|
||||||
|
0x2E, 0x36, 0x3E, 0x26, 0x64, 0x65,
|
||||||
|
0x66, /* operand size override */
|
||||||
|
0x67 /* address size override */
|
||||||
|
};
|
||||||
|
static struct opcode_info opcodes[] = {
|
||||||
|
/* ADD AL, imm8 */{ 0x04, 0, IMM8 },
|
||||||
|
/* ADD EAX, imm32 */{ 0x05, 0, IMM32 },
|
||||||
|
/* ADD r/m8, imm8 */{ 0x80, 0, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* ADD r/m32, imm32 */{ 0x81, 0, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* ADD r/m32, imm8 */{ 0x83, 0, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* ADD r/m8, r8 */{ 0x00, 0, MODRM },
|
||||||
|
/* ADD r/m32, r32 */{ 0x01, 0, MODRM },
|
||||||
|
/* ADD r8, r/m8 */{ 0x02, 0, MODRM },
|
||||||
|
/* ADD r32, r/m32 */{ 0x03, 0, MODRM },
|
||||||
|
/* AND AL, imm8 */{ 0x24, 0, IMM8 },
|
||||||
|
/* AND EAX, imm32 */{ 0x25, 0, IMM32 },
|
||||||
|
/* AND r/m8, imm8 */{ 0x80, 4, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* AND r/m32, imm32 */{ 0x81, 4, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* AND r/m32, imm8 */{ 0x83, 4, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* AND r/m8, r8 */{ 0x20, 0, MODRM },
|
||||||
|
/* AND r/m32, r32 */{ 0x21, 0, MODRM },
|
||||||
|
/* AND r8, r/m8 */{ 0x22, 0, MODRM },
|
||||||
|
/* AND r32, r/m32 */{ 0x23, 0, MODRM },
|
||||||
|
/* CALL rel32 */{ 0xE8, 0, IMM32 | RELOC },
|
||||||
|
/* CALL r/m32 */{ 0xFF, 2, MODRM | REG_OPCODE },
|
||||||
|
/* CMP r/m16/32, imm8*/{ 0x83, 7, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* DEC r/m16/32 */{ 0xFF, 1, MODRM | REG_OPCODE },
|
||||||
|
/* ENTER imm16, imm8 */{ 0xC8, 0, IMM16 | IMM8 },
|
||||||
|
/* INT 3 */{ 0xCC, 0, 0 },
|
||||||
|
/* JMP rel32 */{ 0xE9, 0, IMM32 | RELOC },
|
||||||
|
/* JMP r/m32 */{ 0xFF, 4, MODRM | REG_OPCODE },
|
||||||
|
/* LEA r32,m */{ 0x8D, 0, MODRM },
|
||||||
|
/* LEAVE */{ 0xC9, 0, 0 },
|
||||||
|
/* MOV r/m8,r8 */{ 0x88, 0, MODRM },
|
||||||
|
/* MOV r/m32,r32 */{ 0x89, 0, MODRM },
|
||||||
|
/* MOV r8,r/m8 */{ 0x8A, 0, MODRM },
|
||||||
|
/* MOV r32,r/m32 */{ 0x8B, 0, MODRM },
|
||||||
|
/* MOV r/m16,Sreg */{ 0x8C, 0, MODRM },
|
||||||
|
/* MOV Sreg,r/m16 */{ 0x8E, 0, MODRM },
|
||||||
|
/* MOV AL,moffs8 */{ 0xA0, 0, IMM8 },
|
||||||
|
/* MOV EAX,moffs32 */{ 0xA1, 0, IMM32 },
|
||||||
|
/* MOV moffs8,AL */{ 0xA2, 0, IMM8 },
|
||||||
|
/* MOV moffs32,EAX */{ 0xA3, 0, IMM32 },
|
||||||
|
/* MOV r8, imm8 */{ 0xB0, 0, PLUS_R | IMM8 },
|
||||||
|
/* MOV r32, imm32 */{ 0xB8, 0, PLUS_R | IMM32 },
|
||||||
|
/* MOV r/m8, imm8 */{ 0xC6, 0, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* MOV r/m32, imm32 */{ 0xC7, 0, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* NOP */{ 0x90, 0, 0 },
|
||||||
|
/* OR AL, imm8 */{ 0x0C, 0, IMM8 },
|
||||||
|
/* OR EAX, imm32 */{ 0x0D, 0, IMM32 },
|
||||||
|
/* OR r/m8, imm8 */{ 0x80, 1, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* OR r/m32, imm32 */{ 0x81, 1, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* OR r/m32, imm8 */{ 0x83, 1, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* OR r/m8, r8 */{ 0x08, 0, MODRM },
|
||||||
|
/* OR r/m32, r32 */{ 0x09, 0, MODRM },
|
||||||
|
/* OR r8, r/m8 */{ 0x0A, 0, MODRM },
|
||||||
|
/* OR r32, r/m32 */{ 0x0B, 0, MODRM },
|
||||||
|
/* POP r/m32 */{ 0x8F, 0, MODRM | REG_OPCODE },
|
||||||
|
/* POP r32 */{ 0x58, 0, PLUS_R },
|
||||||
|
/* PUSH r/m32 */{ 0xFF, 6, MODRM | REG_OPCODE },
|
||||||
|
/* PUSH r32 */{ 0x50, 0, PLUS_R },
|
||||||
|
/* PUSH imm8 */{ 0x6A, 0, IMM8 },
|
||||||
|
/* PUSH imm32 */{ 0x68, 0, IMM32 },
|
||||||
|
/* RET */{ 0xC3, 0, 0 },
|
||||||
|
/* RET imm16 */{ 0xC2, 0, IMM16 },
|
||||||
|
/* SUB AL, imm8 */{ 0x2C, 0, IMM8 },
|
||||||
|
/* SUB EAX, imm32 */{ 0x2D, 0, IMM32 },
|
||||||
|
/* SUB r/m8, imm8 */{ 0x80, 5, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* SUB r/m32, imm32 */{ 0x81, 5, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* SUB r/m32, imm8 */{ 0x83, 5, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* SUB r/m8, r8 */{ 0x28, 0, MODRM },
|
||||||
|
/* SUB r/m32, r32 */{ 0x29, 0, MODRM },
|
||||||
|
/* SUB r8, r/m8 */{ 0x2A, 0, MODRM },
|
||||||
|
/* SUB r32, r/m32 */{ 0x2B, 0, MODRM },
|
||||||
|
/* TEST AL, imm8 */{ 0xA8, 0, IMM8 },
|
||||||
|
/* TEST EAX, imm32 */{ 0xA9, 0, IMM32 },
|
||||||
|
/* TEST r/m8, imm8 */{ 0xF6, 0, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* TEST r/m32, imm32 */{ 0xF7, 0, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* TEST r/m8, r8 */{ 0x84, 0, MODRM },
|
||||||
|
/* TEST r/m32, r32 */{ 0x85, 0, MODRM },
|
||||||
|
/* XOR AL, imm8 */{ 0x34, 0, IMM8 },
|
||||||
|
/* XOR EAX, imm32 */{ 0x35, 0, IMM32 },
|
||||||
|
/* XOR r/m8, imm8 */{ 0x80, 6, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* XOR r/m32, imm32 */{ 0x81, 6, MODRM | REG_OPCODE | IMM32 },
|
||||||
|
/* XOR r/m32, imm8 */{ 0x83, 6, MODRM | REG_OPCODE | IMM8 },
|
||||||
|
/* XOR r/m8, r8 */{ 0x30, 0, MODRM },
|
||||||
|
/* XOR r/m32, r32 */{ 0x31, 0, MODRM },
|
||||||
|
/* XOR r8, r/m8 */{ 0x32, 0, MODRM },
|
||||||
|
/* XOR r32, r/m32 */{ 0x33, 0, MODRM }
|
||||||
|
};
|
||||||
|
|
||||||
|
class Asm
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static size_t GetCodeLen(void* Addr)
|
||||||
|
{
|
||||||
|
unsigned char* code = (unsigned char*)Addr;
|
||||||
|
size_t i = 0, len = 0, operand_size = 4;
|
||||||
|
bool found_opcode = false;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(prefixes); i++) {
|
||||||
|
if (code[len] == prefixes[i]) {
|
||||||
|
len++;
|
||||||
|
if (prefixes[i] == 0x66) {
|
||||||
|
operand_size = 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(opcodes) / sizeof(*opcodes); i++) {
|
||||||
|
if (code[len] == opcodes[i].opcode) {
|
||||||
|
if (opcodes[i].flags & REG_OPCODE) {
|
||||||
|
found_opcode = ((code[len + 1] >> 3) & 7) == opcodes[i].reg_opcode;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
found_opcode = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((opcodes[i].flags & PLUS_R) && (code[len] & 0xF8) == opcodes[i].opcode) {
|
||||||
|
found_opcode = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found_opcode) {
|
||||||
|
len++;
|
||||||
|
//opcode = code[len++];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found_opcode) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opcodes[i].flags & MODRM) {
|
||||||
|
uint8_t modrm = code[len++]; /* +1 for Mod/RM byte */
|
||||||
|
uint8_t mod = modrm >> 6;
|
||||||
|
uint8_t rm = modrm & 7;
|
||||||
|
|
||||||
|
if (mod != 3 && rm == 4) {
|
||||||
|
uint8_t sib = code[len++]; /* +1 for SIB byte */
|
||||||
|
uint8_t base = sib & 7;
|
||||||
|
|
||||||
|
if (base == 5) {
|
||||||
|
/* The SIB is followed by a disp32 with no base if the MOD is 00B.
|
||||||
|
* Otherwise, disp8 or disp32 + [EBP].
|
||||||
|
*/
|
||||||
|
if (mod == 1) {
|
||||||
|
len += 1; /* for disp8 */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
len += 4; /* for disp32 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mod == 1) {
|
||||||
|
len += 1; /* for disp8 */
|
||||||
|
}
|
||||||
|
if (mod == 2 || (mod == 0 && rm == 5)) {
|
||||||
|
len += 4; /* for disp32 */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opcodes[i].flags & IMM8) {
|
||||||
|
len += 1;
|
||||||
|
}
|
||||||
|
if (opcodes[i].flags & IMM16) {
|
||||||
|
len += 2;
|
||||||
|
}
|
||||||
|
if (opcodes[i].flags & IMM32) {
|
||||||
|
len += operand_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CMemPool
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
size_t SysPageSize;
|
||||||
|
void *MemPool;
|
||||||
|
std::map<void*, size_t> AllocMap;
|
||||||
|
std::map<void*, size_t> FreeMap;
|
||||||
|
public:
|
||||||
|
static CMemPool* GetInstance()
|
||||||
|
{
|
||||||
|
static CMemPool* pInst = NULL;
|
||||||
|
if (!pInst)pInst = new CMemPool();
|
||||||
|
return pInst;
|
||||||
|
}
|
||||||
|
CMemPool()
|
||||||
|
{
|
||||||
|
SysPageSize = sysconf(_SC_PAGESIZE);
|
||||||
|
int fd = open("/dev/zero", O_RDONLY);
|
||||||
|
MemPool = mmap(NULL, SysPageSize * 10, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE, fd, 0);
|
||||||
|
close(fd);
|
||||||
|
FreeMap[MemPool] = SysPageSize * 10;
|
||||||
|
}
|
||||||
|
~CMemPool()
|
||||||
|
{
|
||||||
|
munmap(MemPool, SysPageSize * 10);
|
||||||
|
}
|
||||||
|
bool SetPageProtect(void* Address, int Protect)
|
||||||
|
{
|
||||||
|
return SetAddressProtect(Addr_Align(Address, SysPageSize), SysPageSize, Protect);
|
||||||
|
}
|
||||||
|
static bool SetAddressProtect(void* Address, size_t Size, int Protect)
|
||||||
|
{
|
||||||
|
return !mprotect(Address, Size, Protect);
|
||||||
|
}
|
||||||
|
static void MakeJmp(void* Src, void* Dst, int nNop = 0)
|
||||||
|
{
|
||||||
|
unsigned char* code = (unsigned char*)Src;
|
||||||
|
code[0] = '\xE9';
|
||||||
|
*((unsigned long*)&code[1]) = (unsigned long)Dst - (unsigned long)&code[1] - 4;
|
||||||
|
for (int i = 0; i < nNop; i++)
|
||||||
|
{
|
||||||
|
code[5 + i] = '\x90';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void* alloc(size_t _size)
|
||||||
|
{
|
||||||
|
void *pBuf = NULL;
|
||||||
|
for (std::map<void*, size_t>::iterator iter = FreeMap.begin(); iter != FreeMap.end(); iter++)
|
||||||
|
{
|
||||||
|
if (iter->second >= _size)
|
||||||
|
{
|
||||||
|
pBuf = iter->first;
|
||||||
|
FreeMap.erase(pBuf);
|
||||||
|
if (iter->second > _size)
|
||||||
|
{
|
||||||
|
FreeMap[MOVEPOINT(pBuf, _size)] = iter->second - _size;
|
||||||
|
}
|
||||||
|
AllocMap[pBuf] = _size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pBuf;
|
||||||
|
}
|
||||||
|
void free(void* _ptr)
|
||||||
|
{
|
||||||
|
size_t _size = AllocMap[_ptr];
|
||||||
|
AllocMap.erase(_ptr);
|
||||||
|
FreeMap[_ptr] = _size;
|
||||||
|
if (FreeMap.size() >= 10)
|
||||||
|
{
|
||||||
|
sortMem();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void sortMem()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class FuncHook
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FuncHook()
|
||||||
|
: Actived(false)
|
||||||
|
, Src(NULL)
|
||||||
|
, SrcPtr(NULL)
|
||||||
|
, Dst(NULL)
|
||||||
|
, SrcCodeSize(0)
|
||||||
|
, HookCodeSize(5)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
~FuncHook()
|
||||||
|
{
|
||||||
|
this->Restore();
|
||||||
|
}
|
||||||
|
void Hook(void** SrcAddr, void* DstAddr)
|
||||||
|
{
|
||||||
|
if (!SrcAddr || !*SrcAddr || !DstAddr)return;
|
||||||
|
//恢复上次HOOK
|
||||||
|
this->Restore();
|
||||||
|
//填充数据
|
||||||
|
this->HookCodeSize = 5;
|
||||||
|
this->SrcCodeSize = 0;
|
||||||
|
this->SrcPtr = SrcAddr;
|
||||||
|
this->Src = *SrcAddr;
|
||||||
|
this->Dst = DstAddr;
|
||||||
|
//计算HOOK代码大小
|
||||||
|
do
|
||||||
|
{
|
||||||
|
this->SrcCodeSize += Asm::GetCodeLen(Move_Ptr(this->Src, this->SrcCodeSize));
|
||||||
|
} while (this->SrcCodeSize < this->HookCodeSize);
|
||||||
|
this->HookCode = (unsigned char*)CMemPool::GetInstance()->alloc(this->SrcCodeSize + 11);
|
||||||
|
memcpy(this->HookCode, this->Src, this->SrcCodeSize);
|
||||||
|
//修改目标地址内存权限
|
||||||
|
CMemPool::MakeJmp(&this->HookCode[this->SrcCodeSize], Move_Ptr(this->Src, this->SrcCodeSize), this->SrcCodeSize - this->HookCodeSize);
|
||||||
|
//修改源地址内存权限
|
||||||
|
CMemPool::GetInstance()->SetPageProtect(this->Src, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||||
|
CMemPool::MakeJmp(this->Src, this->Dst, this->SrcCodeSize - this->HookCodeSize);
|
||||||
|
*this->SrcPtr = this->HookCode;
|
||||||
|
this->Actived = true;
|
||||||
|
}
|
||||||
|
void Restore()
|
||||||
|
{
|
||||||
|
if (this->Actived)
|
||||||
|
{
|
||||||
|
//修改源地址内存写权限
|
||||||
|
CMemPool::GetInstance()->SetPageProtect(this->Src, PROT_READ | PROT_WRITE);
|
||||||
|
memcpy(this->Src, this->HookCode, this->SrcCodeSize);
|
||||||
|
//修改源地址内存执行权限
|
||||||
|
CMemPool::GetInstance()->SetPageProtect(this->Src, PROT_READ | PROT_EXEC);
|
||||||
|
this->Actived = false;
|
||||||
|
this->SrcCodeSize = 0;
|
||||||
|
*this->SrcPtr = this->Src;
|
||||||
|
if (this->HookCode)
|
||||||
|
{
|
||||||
|
CMemPool::GetInstance()->free(this->HookCode);
|
||||||
|
}
|
||||||
|
this->HookCode = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool Actived;
|
||||||
|
void *Src;
|
||||||
|
void **SrcPtr;
|
||||||
|
void *Dst;
|
||||||
|
unsigned char* HookCode;
|
||||||
|
size_t SrcCodeSize;
|
||||||
|
size_t HookCodeSize;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CodeHook
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void WriteUChar(void *Addr, unsigned char Value)
|
||||||
|
{
|
||||||
|
WriteBytes(Addr, &Value, 1);
|
||||||
|
}
|
||||||
|
static void WriteUShort(void *Addr, unsigned short Value)
|
||||||
|
{
|
||||||
|
WriteBytes(Addr, &Value, 2);
|
||||||
|
}
|
||||||
|
static void WriteUInt(void *Addr, unsigned int Value)
|
||||||
|
{
|
||||||
|
WriteBytes(Addr, &Value, 4);
|
||||||
|
}
|
||||||
|
static void WriteBytes(void *Addr, void *Data, size_t Len)
|
||||||
|
{
|
||||||
|
CMemPool::GetInstance()->SetPageProtect(Addr, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||||
|
memcpy(Addr, Data, Len);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,457 @@
|
||||||
|
#ifndef USER_CLASS_H
|
||||||
|
#define USER_CLASS_H
|
||||||
|
#include "base.h"
|
||||||
|
#include "enum.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
template<typename R, typename A, typename ... ARG> R CallT(A call_addr, const ARG ... arguments)
|
||||||
|
{
|
||||||
|
if (!call_addr)
|
||||||
|
{
|
||||||
|
return R();
|
||||||
|
}
|
||||||
|
const auto control = reinterpret_cast<R(*)(ARG...)>(call_addr);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return control(arguments ...);
|
||||||
|
}
|
||||||
|
catch (...)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
return R();
|
||||||
|
}
|
||||||
|
|
||||||
|
class PacketBuf;
|
||||||
|
class DB_UpdateAvatarJewelSlot;
|
||||||
|
class CInventory;
|
||||||
|
class CStackableItem;
|
||||||
|
class Inven_Item;
|
||||||
|
class CItem;
|
||||||
|
class CUserCharacInfo;
|
||||||
|
class CUser;
|
||||||
|
class PacketBuf;
|
||||||
|
class PacketGuard;
|
||||||
|
class InterfacePacketBuf;
|
||||||
|
|
||||||
|
namespace WongWork
|
||||||
|
{
|
||||||
|
|
||||||
|
class CAvatarItemMgr
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//获取时装插槽数据
|
||||||
|
int getJewelSocketData(WongWork::CAvatarItemMgr* a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(WongWork::CAvatarItemMgr* a1, void* a2);
|
||||||
|
return ((__func)base::WongWork::CAvatarItemMgr::getJewelSocketData)(this, a2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CHackAnalyzer
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int addServerHackCnt(CUserCharacInfo* a2, int a3, int a4, int a5, int a6)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(WongWork::CHackAnalyzer* a1, CUserCharacInfo* a2, int a3, int a4, int a5, int a6);
|
||||||
|
|
||||||
|
return CallT<int>(base::WongWork::CHackAnalyzer::addServerHackCnt, this, a2, a3, a4, a5, a6);
|
||||||
|
return ((__func)base::WongWork::CHackAnalyzer::addServerHackCnt)(this, a2, a3, a4, a5, a6);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class CUserCharacInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//获取角色名字
|
||||||
|
std::string getCurCharacName()
|
||||||
|
{
|
||||||
|
typedef char* (*__func)(CUserCharacInfo* a1);
|
||||||
|
return std::string(((__func)base::CUserCharacInfo::getCurCharacName)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取角色编号
|
||||||
|
int getCurCharacNo()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUserCharacInfo* a1);
|
||||||
|
return int(((__func)base::CUserCharacInfo::getCurCharacNo)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取角色上次退出游戏时间
|
||||||
|
int getCurCharacLastPlayTick()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUserCharacInfo* a1);
|
||||||
|
return int(((__func)base::CUserCharacInfo::getCurCharacLastPlayTick)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取角色等级
|
||||||
|
int get_level_up_exp(int a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUserCharacInfo* a1, int a2);
|
||||||
|
return int(((__func)base::CUserCharacInfo::get_level_up_exp)(this, a2));
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取角色背包
|
||||||
|
CInventory* getCurCharacInvenW()
|
||||||
|
{
|
||||||
|
typedef CInventory* (*__func)(CUserCharacInfo* a1);
|
||||||
|
return ((__func)base::CUserCharacInfo::getCurCharacInvenW)(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CUser : public CUserCharacInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int get_state()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUser* a1);
|
||||||
|
return int(((__func)base::CUser::get_state)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheckItemLock(int a2, int a3)
|
||||||
|
{
|
||||||
|
typedef bool (*__func)(CUser* a1, int a2, int a3);
|
||||||
|
return int(((__func)base::CUser::CheckItemLock)(this, a2, a3));
|
||||||
|
}
|
||||||
|
|
||||||
|
int SendNotiPacketMessage(char* a2, int a3)
|
||||||
|
{
|
||||||
|
typedef bool (*__func)(CUser* a1, char* a2, int a3);
|
||||||
|
return int(((__func)base::CUser::SendNotiPacketMessage)(this, a2, a3));
|
||||||
|
}
|
||||||
|
|
||||||
|
//角色增加经验
|
||||||
|
int gain_exp_sp(unsigned int a2, int a3, int a4, int a5, int a6, int a7)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUserCharacInfo* a1, unsigned int a2, int a3, int a4, int a5, int a6, int a7);
|
||||||
|
return int(((__func)base::CUser::gain_exp_sp)(this, a2, a3, a4, a5, a6, a7));
|
||||||
|
}
|
||||||
|
|
||||||
|
//发送道具
|
||||||
|
int AddItem(int a2, int a3, int a4, int a5, int a6)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUser* a1, int a2, int a3, int a4, int a5, int a6);
|
||||||
|
return int(((__func)base::CUser::AddItem)(this, a2, a3, a4, a5, a6));
|
||||||
|
}
|
||||||
|
|
||||||
|
//通知客户端道具更新(客户端指针, 通知方式[仅客户端=1, 世界广播=0, 小队=2, war room=3], itemSpace[装备=0, 时装=1], 道具所在的背包槽)
|
||||||
|
int SendUpdateItemList(int a2, int a3, int a4)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUserCharacInfo* a1, int a2, int a3, int a4);
|
||||||
|
return int(((__func)base::CUser::SendUpdateItemList)(this, a2, a3, a4));
|
||||||
|
}
|
||||||
|
|
||||||
|
int SendCmdErrorPacket(int a2, unsigned char a3)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUser* a1, int a2, unsigned char a3);
|
||||||
|
return int(((__func)base::CUser::SendCmdErrorPacket)(this, a2, a3));
|
||||||
|
}
|
||||||
|
|
||||||
|
int isEnableAvatarSocketAction()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUser* a1);
|
||||||
|
return int(((__func)base::CUser::isEnableAvatarSocketAction)(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
int Send(PacketGuard* a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CUser* a1, PacketGuard* a2);
|
||||||
|
return int(((__func)base::CUser::Send)(this, a2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CStackableItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//获取消耗品类型
|
||||||
|
int GetItemType()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(void* a1);
|
||||||
|
return ((__func)base::CStackableItem::GetItemType)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取徽章支持的镶嵌槽类型
|
||||||
|
int getJewelTargetSocket()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CStackableItem* a1);
|
||||||
|
return ((__func)base::CStackableItem::getJewelTargetSocket)(this);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CItem : public CStackableItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//道具是否为消耗品
|
||||||
|
int is_stackable()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CItem* a1);
|
||||||
|
return ((__func)base::CItem::is_stackable)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsRoutingItem()
|
||||||
|
{
|
||||||
|
typedef bool (*__func)(CItem* a1);
|
||||||
|
return ((__func)base::CItem::IsRoutingItem)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
};
|
||||||
|
|
||||||
|
class Inven_Item
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//获取道具附加信息
|
||||||
|
WongWork::CAvatarItemMgr* get_add_info()
|
||||||
|
{
|
||||||
|
typedef WongWork::CAvatarItemMgr* (*__func)(Inven_Item* a1);
|
||||||
|
return ((__func)base::Inven_Item::get_add_info)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//检查背包中道具是否为空
|
||||||
|
bool isEmpty()
|
||||||
|
{
|
||||||
|
typedef bool (*__func)(Inven_Item* a1);
|
||||||
|
return ((__func)base::Inven_Item::isEmpty)(this);
|
||||||
|
}
|
||||||
|
//获取背包中道具item_id
|
||||||
|
int getKey()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(Inven_Item* a1);
|
||||||
|
return ((__func)base::Inven_Item::getKey)(this);
|
||||||
|
}
|
||||||
|
//道具是否是装备
|
||||||
|
bool isEquipableItemType()
|
||||||
|
{
|
||||||
|
typedef bool (*__func)(Inven_Item* a1);
|
||||||
|
return ((__func)base::Inven_Item::isEquipableItemType)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_ui_id()
|
||||||
|
{
|
||||||
|
return *(int*)(this + 0x7);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CDataManager
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static CDataManager* G_CDataManager(void)
|
||||||
|
{
|
||||||
|
typedef CDataManager* (*__func)(void);
|
||||||
|
return ((__func)base::CDataManager::G_CDataManager)();
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取装备pvf数据
|
||||||
|
CItem* find_item(int a2)
|
||||||
|
{
|
||||||
|
typedef CItem* (*__func)(CDataManager* a1, int a2);
|
||||||
|
return ((__func)base::CDataManager::find_item)(this, a2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CInventory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum INVENTORY_TYPE : int
|
||||||
|
{
|
||||||
|
INVENTORY_TYPE_BODY = 0, //身上穿的装备
|
||||||
|
INVENTORY_TYPE_ITEM = 1, //物品栏
|
||||||
|
INVENTORY_TYPE_AVARTAR = 2, //时装栏
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
//获取时装管理器
|
||||||
|
WongWork::CAvatarItemMgr* GetAvatarItemMgrR()
|
||||||
|
{
|
||||||
|
typedef WongWork::CAvatarItemMgr* (*__func)(void* a1);
|
||||||
|
return ((__func)base::CInventory::GetAvatarItemMgrR)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
int delete_item(int a2, int a3, int a4, int a5, int a6)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CInventory* a1, int a2, int a3, int a4, int a5, int a6);
|
||||||
|
return ((__func)base::CInventory::delete_item)(this, a2, a3, a4, a5, a6);
|
||||||
|
}
|
||||||
|
|
||||||
|
//使用金币
|
||||||
|
int use_money(int a2, int a3, char a4)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CInventory* a1, int a2, int a3, char a4);
|
||||||
|
return ((__func)base::CInventory::use_money)(this, a2, a3, a4);
|
||||||
|
}
|
||||||
|
|
||||||
|
//获得金币
|
||||||
|
int gain_money(unsigned int a2, int a3, char a4, int a5)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(CInventory* a1, unsigned int a2, int a3, char a4, int a5);
|
||||||
|
return ((__func)base::CInventory::gain_money)(this, a2, a3, a4, a5);
|
||||||
|
}
|
||||||
|
|
||||||
|
//获取背包槽中的道具
|
||||||
|
Inven_Item* GetInvenRef(INVENTORY_TYPE a2, int a3)
|
||||||
|
{
|
||||||
|
typedef Inven_Item* (*__func)(CInventory* a1, INVENTORY_TYPE a2, int a3);
|
||||||
|
return ((__func)base::CInventory::GetInvenRef)(this, a2, a3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class DB_UpdateAvatarJewelSlot
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static int makeRequest(int a1, unsigned int a2, void* src)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(int a1, unsigned int a2, void* src);
|
||||||
|
return ((__func)base::DB_UpdateAvatarJewelSlot::makeRequest)(a1, a2, src);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PacketBuf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
//取大小
|
||||||
|
int get_len()
|
||||||
|
{
|
||||||
|
typedef int (*__func)(PacketBuf* a1);
|
||||||
|
return ((__func)base::PacketBuf::get_len)(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
//取指针
|
||||||
|
int get_buf_ptr(int a2 = 0)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(PacketBuf* a1, int a2);
|
||||||
|
return ((__func)base::PacketBuf::get_buf_ptr)(this, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
char get_byte()
|
||||||
|
{
|
||||||
|
char result;
|
||||||
|
typedef int (*__func)(PacketBuf* a1, char* a2);
|
||||||
|
if (((__func)base::PacketBuf::get_byte)(this, &result) == 1)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
short get_short()
|
||||||
|
{
|
||||||
|
short result;
|
||||||
|
typedef int (*__func)(PacketBuf* a1, short* a2);
|
||||||
|
if (((__func)base::PacketBuf::get_short)(this, &result) == 1)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_int()
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
typedef int (*__func)(PacketBuf* a1, int* a2);
|
||||||
|
if (((__func)base::PacketBuf::get_int)(this, &result) == 1)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int get_binary(char* a2, int a3)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(PacketBuf* a1, char* a2, int a3);
|
||||||
|
return ((__func)base::PacketBuf::get_binary)(this, a2, a3);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class InterfacePacketBuf
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int put_header(int a2, int a3)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, int a2, int a3);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_header)(this, a2, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int put_byte(char a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, char a2);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_byte)(this, a2);
|
||||||
|
}
|
||||||
|
int put_short(short a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, short a2);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_short)(this, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int put_int(int a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, int a2);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_int)(this, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int put_binary(char* a2, int a3)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, char* a2, int a3);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_binary)(this, a2, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int finalize(bool a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, bool a2);
|
||||||
|
return ((__func)base::InterfacePacketBuf::finalize)(this, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int put_str(const char* a2, int a3)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, const char* a2, int a3);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_str)(this, a2, a3);
|
||||||
|
}
|
||||||
|
|
||||||
|
int put_packet(const Inven_Item* a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(InterfacePacketBuf* a1, const Inven_Item* a2);
|
||||||
|
return ((__func)base::InterfacePacketBuf::put_packet)(this, a2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PacketGuard
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static PacketGuard* NewPacketGuard()
|
||||||
|
{
|
||||||
|
void* v62 = malloc(0x20000);
|
||||||
|
typedef int (*__func)(void* a1);
|
||||||
|
((__func)base::PacketGuard::PacketGuard_make)(v62);
|
||||||
|
return (PacketGuard*)v62;
|
||||||
|
}
|
||||||
|
static void DelPacketGuard(PacketGuard* a1)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(void* a1);
|
||||||
|
((__func)base::PacketGuard::PacketGuard_destroy)(a1);
|
||||||
|
free(a1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class PacketDispatcher
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int getDispatcher(int a2)
|
||||||
|
{
|
||||||
|
typedef int (*__func)(PacketDispatcher* a1, int a2);
|
||||||
|
return ((__func)base::PacketDispatcher::getDispatcher)(this, a2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void** get_dispatcher(int a2)
|
||||||
|
{
|
||||||
|
typedef void** (*__func)(PacketDispatcher* a1, int a2);
|
||||||
|
return ((__func)base::PacketDispatcher::get_dispatcher)(this, a2);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#endif // __DXFBASE_H__
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
#ifndef utils_h__
|
||||||
|
#define utils_h__
|
||||||
|
#include <string>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#define BUFFCOUNT (3196)
|
||||||
|
#define SET_TEXTW(X) L#X
|
||||||
|
#define SET_TEXTA(X) #X
|
||||||
|
|
||||||
|
|
||||||
|
namespace Util
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @brief 到16进制Hex文本
|
||||||
|
* @param buf
|
||||||
|
* @param len
|
||||||
|
* @param tok
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static std::string ToHexString(const unsigned char* buf, int len, std::string tok = " ")
|
||||||
|
{
|
||||||
|
std::string output;
|
||||||
|
char temp[8];
|
||||||
|
for (int i = 0; i < len; ++i)
|
||||||
|
{
|
||||||
|
memset(temp, 0, sizeof(temp));
|
||||||
|
snprintf(temp, sizeof(temp), "%.2X", buf[i]);
|
||||||
|
output.append(temp, 2);
|
||||||
|
output.append(tok);
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _Log(const char* formatstring, ...)
|
||||||
|
{
|
||||||
|
int nSize = 0;
|
||||||
|
char buff[BUFFCOUNT];
|
||||||
|
memset(buff, 0, sizeof(buff));
|
||||||
|
va_list args;
|
||||||
|
va_start(args, formatstring);
|
||||||
|
nSize = vsnprintf(buff, sizeof(buff), formatstring, args);
|
||||||
|
va_end(args);
|
||||||
|
char szPrINT32[BUFFCOUNT + 50] = { 0 };
|
||||||
|
sprintf(szPrINT32, "[GameHelpers] %s \n", buff);//wsprintfA
|
||||||
|
printf(szPrINT32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define LOG(format,...) Util::_Log(format,##__VA_ARGS__)
|
||||||
|
|
||||||
|
|
||||||
|
#endif // utils_h__
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
# 声明编译要求cmake最低版本
|
||||||
|
CMAKE_MINIMUM_REQUIRED(VERSION 3.0)
|
||||||
|
|
||||||
|
# 添加源文件
|
||||||
|
SET(SOURCE main.cc)
|
||||||
|
|
||||||
|
# 指定库的位置为项目根目录下的lib目录
|
||||||
|
LINK_DIRECTORIES(${PROJECT_SOURCE_DIR}/build/lib)
|
||||||
|
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/src)
|
||||||
|
|
||||||
|
# 添加一个可执行程序,名称和工程名称保持一致
|
||||||
|
ADD_EXECUTABLE(hook-test ${SOURCE})
|
||||||
|
TARGET_LINK_LIBRARIES(hook-test SHARED hook)
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
int main(int argc, char** argv)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
Loading…
Reference in New Issue