//************************************ // 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.h" extern HSQUIRRELVM v; extern std::recursive_mutex SqMtx; Controller::Controller() : assembler(Arch::kX86), Asm(NULL) { Asm = assembler.GetAssembler(); } Controller::~Controller() { } void Controller::init() { CMem::WriteUChar((void *)(base::GlobalData::Init_fix_1 - 0x1), 0); //.text:085BDE9D 83 F8 0A cmp eax, 10 CMem::WriteUChar((void *)(base::CParty::addDungeonClear_fix_1 + 2), 0x7E); // 普通被击 //.text:085BDF30 83 F8 1E cmp eax, 30 CMem::WriteUChar((void *)(base::CParty::addDungeonClear_fix_2 + 2), 0x7E); // 远古被击 //.text:085BDFC3 83 F8 32 cmp eax, 50 CMem::WriteUChar((void *)(base::CParty::addDungeonClear_fix_3 + 2), 0x7E); // 异界被击 CMem::WriteUChar((void *)(0x081C025F + 1), 0x0B); CMem::WriteUChar((void *)(0x081C029E + 1), 0x0B); /* 修正使用代币增加积分 地址 长度 原始字节 已修补字节 08179043 0x1 97 B8 0817904E 0x1 8C AD */ CMem::WriteUChar((void *)(0x08179043), 0xB8); CMem::WriteUChar((void *)(0x0817904E), 0xAD); // mov dword ptr [esp+4], 8E0F448h Asm->lea(eax, dword_ptr(ebp, -0x84)); Asm->mov(dword_ptr(esp), eax); Asm->mov(eax, int(&hook_importCashShopItemList)); Asm->call(eax); Asm->mov(dword_ptr(esp, 4), 0x8E0F448); Asm->mov(eax, base::importCashShopItemList_hook_end); Asm->jmp(eax); auto code_importCashShopItemList = assembler.GetBytes(true); void *new_importCashShopItemList_addr = Utils::alloc(code_importCashShopItemList.size()); CMem::WriteBytes(new_importCashShopItemList_addr, code_importCashShopItemList.data(), code_importCashShopItemList.size()); LOG("code :%s", Utils::ToHexString((const unsigned char *)code_importCashShopItemList.data(), code_importCashShopItemList.size()).c_str()); LOG("code_addr :%p", new_importCashShopItemList_addr); CMem::HookJmp(base::importCashShopItemList_hook_begin, (int)new_importCashShopItemList_addr); /************************************************************************/ /* HOOK 商城购买物品成功处理 */ /************************************************************************/ // mov dword ptr [ebp-0FCh], 0FFFFFFFFh Asm->lea(eax, dword_ptr(ebp, -0xEC)); Asm->mov(dword_ptr(esp, 0x10), eax); Asm->mov(eax, dword_ptr(ebp, -0x3A)); Asm->mov(dword_ptr(esp, 0xc), eax); Asm->mov(eax, dword_ptr(ebp, -0x5C)); Asm->mov(dword_ptr(esp, 8), eax); Asm->mov(eax, dword_ptr(ebp, -0x60)); Asm->mov(dword_ptr(esp, 4), eax); Asm->mov(eax, dword_ptr(ebp, 0xC)); Asm->mov(dword_ptr(esp), eax); Asm->mov(eax, int(&hook_ProcessIPG_ResultOutput)); Asm->call(eax); Asm->mov(dword_ptr(ebp, -0xfc), 0x0FFFFFFFF); Asm->mov(eax, base::ItemVendingMachine::ProcessIPG_ResultOutput_hook_end); Asm->jmp(eax); auto code_ProcessIPG_ResultOutput = assembler.GetBytes(true); void *new_ProcessIPG_ResultOutput_addr = Utils::alloc(code_ProcessIPG_ResultOutput.size()); CMem::WriteBytes(new_ProcessIPG_ResultOutput_addr, code_ProcessIPG_ResultOutput.data(), code_ProcessIPG_ResultOutput.size()); LOG("code_2 :%s", Utils::ToHexString((const unsigned char *)code_ProcessIPG_ResultOutput.data(), code_ProcessIPG_ResultOutput.size()).c_str()); LOG("code_addr_2 :%p", new_ProcessIPG_ResultOutput_addr); CMem::HookJmp(base::ItemVendingMachine::ProcessIPG_ResultOutput_hook_begin, (int)new_ProcessIPG_ResultOutput_addr); // HOOK_SETUP(IPacketDispatcher_ParamBase_dispatch_template); HOOK_SETUP(UseJewel_dispatch_sig); HOOK_SETUP(Dispatcher_ModItemAttr_dispatch_sig); HOOK_SETUP(PacketDispatcher_doDispatch); HOOK_SETUP(DisPatcher_MoveMap_dispatch_sig); HOOK_SETUP(Inter_LoadEtc_dispatch_sig); HOOK_SETUP(DisPatcher_ReturnToSelectCharacter_dispatch_sig); HOOK_SETUP(Init); LOG("Controller::init()"); } void Controller::Jinit() { // HOOK_SETUP(LenDispatcher_New_Gmdebug_Command); } int Controller::hook_IPacketDispatcher_ParamBase_dispatch_template(int a1, int a2, int a3) { //[root@nimzgryilkxubzo game] # [DNF_PROJECT] Recv() class :1 id : 84 len : 21 callback : 0x81258b6 (nil)0x81258b6 0x8125a06 (nil)(nil) // [DNF_PROJECT] + 12 0x8bd8d54 : Dispatcher_ModItemAttr::dispatch_sig(CUser *,PacketBuf &) // [DNF_PROJECT] + 16 0x8bd8d58 : IPacketDispatcher::check_state(CUser *,PacketBuf &) // [DNF_PROJECT] + 20 0x8bd8d5c : Dispatcher_ModItemAttr::read(PacketBuf &,MSG_BASE &) // [DNF_PROJECT] + 24 0x8bd8d60 : Dispatcher_ModItemAttr::process(CUser *,MSG_BASE &,ParamBase &) // [DNF_PROJECT] + 28 0x8bd8d64 : IPacketDispatcher::send(CUser *,ParamBase&) // // // [DNF_PROJECT] + 12 0x8bd7dd4 : Dispatcher_Antibot::dispatch_sig // [DNF_PROJECT] + 16 0x8bd7dd8 : IPacketDispatcher::check_state(CUser *,PacketBuf &) // [DNF_PROJECT] + 20 0x8bd7ddc : Dispatcher_Antibot::read(PacketBuf &,MSG_BASE &) // [DNF_PROJECT] + 24 0x8bd7de0 : Dispatcher_Antibot::process(CUser *,MSG_BASE &,ParamBase &) // [DNF_PROJECT] + 28 0x8bd7de4 : IPacketDispatcher::send(CUser *,ParamBase&) // LOG("ParamBase_dispatch_template[ +12 :%p +16 :%p +20 :%p +24 :%p +28 :%p ]" // , *(int*)a1 + 12 // , *(int*)a1 + 16 // , *(int*)a1 + 20 // , *(int*)a1 + 24 // , *(int*)a1 + 28 //); Controller::Get()->old_IPacketDispatcher_ParamBase_dispatch_template(a1, a2, a3); } int Controller::hook_UseJewel_dispatch_sig(void *pDispatcher_UseJewel, CUser *user, PacketBuf *pBuf) { ENUM_PACK_RET_TYPE ret = CDispatch::Get()->UseJewel_dispatch_sig(pDispatcher_UseJewel, user, pBuf); int result = (ret == PAK_ERROR) ? 1 : 0; // 08217C06 分解 return result; } int Controller::hook_Dispatcher_ModItemAttr_dispatch_sig(Dispatcher_ModItemAttr *dis_mod, CUser *user, PacketBuf *pBuf) { PacketBuf new_buf; memcpy(&new_buf, pBuf, sizeof(PacketBuf)); short equipment_pos = 0; int equipment_id = 0; short item_pos = 0; if ((unsigned __int8)new_buf.get_short(&equipment_pos) != 1 || (unsigned __int8)new_buf.get_int(&equipment_id) != 1 || (unsigned __int8)new_buf.get_short(&item_pos) != 1) { user->SendCmdErrorPacket(84, -1); return 0; } CInventory *CurCharacInvenW = user->getCurCharacInvenR(); auto item_inven = CurCharacInvenW->GetInvenRef(CInventory::INVENTORY_TYPE_ITEM, item_pos); if (!item_inven->isEmpty() && item_inven->getKey() == ITEM_ID_YIJIRUHUN) { ENUM_PACK_RET_TYPE ret = CDispatch::Get()->Dispatcher_ModItemAttr_dispatch_sig(dis_mod, user, pBuf); int result = (ret == PAK_ERROR) ? 1 : 0; return result; } return Get()->old_Dispatcher_ModItemAttr_dispatch_sig(dis_mod, user, pBuf); } int Controller::hook_PacketDispatcher_doDispatch(PacketDispatcher *a1, CUser *user, int packet_class, int packet_id, char *packet_src, int packet_len, int a7, int a8) { int (***dispatcher)(int, CUser *, char *) = (int (***)(int, CUser *, char *))a1->get_dispatcher(packet_id); if (dispatcher) { // v32 = (**dispatcher)(dispatcher, user, v25); // LOG("Recv() class:%d id:%d len:%d %p [ +00 :%p +12 :%p +16 :%p +20 :%p +24 :%p +28 :%p ]" // , packet_class // , packet_id // , packet_len // , (**dispatcher) // , *(int*)dispatcher // , *(int*)dispatcher + 12 // , *(int*)dispatcher + 16 // , *(int*)dispatcher + 20 // , *(int*)dispatcher + 24 // , *(int*)dispatcher + 28 // ); } // LOG("Recv() class:%d id:%d len:%d packet_data :%s ", packet_class, packet_id, packet_len, Utils::ToHexString((const unsigned char *)packet_src, packet_len).c_str()); if (packet_id == PACKET_ID_ITEM_USE_EQUIPMENT_MOVEITEM) { int result = 0; PacketBuf *v25 = PacketBuf::NewPacketBuf(); user->setLastPacketID(packet_id); v25->bind_packet(packet_src, packet_len); LOG("Recv() class:%d id:%d len:%d packet_data :%s ", packet_class, packet_id, packet_len, Utils::ToHexString((const unsigned char *)packet_src, packet_len).c_str()); if (v25) { ENUM_PACK_RET_TYPE ret = CDispatch::Get()->UseEquipmentMoveItem(user, v25); result = (ret == PAK_ERROR) ? 1 : 0; PacketBuf::DelPacketBuf(v25); } return result; } // 区域移动 else if (packet_id == 38) { std::lock_guard lock(SqMtx); SQBool R; // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushroottable(v); // pushes the global table sq_pushstring(v, _SC("Cb_move_area"), -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { // gets the fie123oo' from the global table sq_pushroottable(v); // push the 'this' (in this case is the global table) sq_pushuserpointer(v, user); sq_pushinteger(v, int(*(unsigned char *)(packet_src + 0x0D))); sq_pushinteger(v, int(*(unsigned char *)(packet_src + 0x0E))); sq_call(v, 4, SQTrue, SQTrue); // calls the function sq_getbool(v, -1, &R); } sq_settop(v, top); // restores the original stack size if (!R) return 0; } // 普通输入 else if (packet_id == 17) { std::string str = Utils::PackToHexString((const unsigned char *)packet_src, 20); std::lock_guard lock(SqMtx); SQBool R; // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushroottable(v); // pushes the global table sq_pushstring(v, _SC("Cb_base_input"), -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { // gets the fie123oo' from the global table sq_pushroottable(v); // push the 'this' (in this case is the global table) sq_pushuserpointer(v, user); sq_pushstring(v, _SC(str.c_str()), -1); sq_call(v, 3, SQTrue, SQTrue); // calls the function sq_getbool(v, -1, &R); } sq_settop(v, top); // restores the original stack size if (!R) return 0; } // GM输入 else if (packet_id == 179) { // std::cout << "传入的: " << std::hex << (int)user << std::endl; std::string str = Utils::PackToHexString((const unsigned char *)packet_src, 13); str = str.substr(2); std::lock_guard lock(SqMtx); // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushroottable(v); // pushes the global table sq_pushstring(v, _SC("Cb_gm_input"), -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { // gets the fie123oo' from the global table sq_pushroottable(v); // push the 'this' (in this case is the global table) sq_pushuserpointer(v, user); sq_pushstring(v, _SC(str.c_str()), -1); sq_call(v, 3, SQFalse, SQTrue); // calls the function } sq_settop(v, top); // restores the original stack size } // 特殊道具使用 else if (packet_id == 255) { std::lock_guard lock(SqMtx); // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushroottable(v); // pushes the global table sq_pushstring(v, _SC("Cb_use_item_sp"), -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { // gets the fie123oo' from the global table sq_pushroottable(v); // push the 'this' (in this case is the global table) sq_pushuserpointer(v, user); sq_pushinteger(v, int(*(int *)(packet_src + 0x0D))); sq_call(v, 3, SQFalse, SQTrue); // calls the function } sq_settop(v, top); // restores the original stack size } // 返回选择角色 else if (packet_id == 7) { std::lock_guard lock(SqMtx); // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushroottable(v); // pushes the global table sq_pushstring(v, _SC("Cb_return_select_character"), -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { // gets the fie123oo' from the global table sq_pushroottable(v); // push the 'this' (in this case is the global table) sq_pushuserpointer(v, user); sq_call(v, 2, SQFalse, SQTrue); // calls the function } sq_settop(v, top); // restores the original stack size } // 下线 else if (packet_id == 3) { std::lock_guard lock(SqMtx); // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushroottable(v); // pushes the global table sq_pushstring(v, _SC("Cb_player_exit"), -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { // gets the fie123oo' from the global table sq_pushroottable(v); // push the 'this' (in this case is the global table) sq_pushuserpointer(v, user); sq_call(v, 2, SQFalse, SQTrue); // calls the function } sq_settop(v, top); // restores the original stack size } // 放弃副本 else if (packet_id == 45) { std::lock_guard lock(SqMtx); // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushroottable(v); // pushes the global table sq_pushstring(v, _SC("Cb_giveup_dgn"), -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { // gets the fie123oo' from the global table sq_pushroottable(v); // push the 'this' (in this case is the global table) sq_pushuserpointer(v, user); sq_call(v, 2, SQFalse, SQTrue); // calls the function } sq_settop(v, top); // restores the original stack size } // 自定义包 else if (packet_id == 130) { std::string str = Utils::PackToHexString((const unsigned char *)packet_src, 13); std::lock_guard lock(SqMtx); // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushroottable(v); // pushes the global table sq_pushstring(v, _SC("OnClientSocketMsg"), -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { // gets the fie123oo' from the global table sq_pushroottable(v); // push the 'this' (in this case is the global table) sq_pushuserpointer(v, user); sq_pushstring(v, _SC(str.c_str()), -1); sq_call(v, 3, SQFalse, SQTrue); // calls the function } sq_settop(v, top); // restores the original stack size } return Get()->old_PacketDispatcher_doDispatch(a1, user, packet_class, packet_id, packet_src, packet_len, a7, a8); } int Controller::hook_LenDispatcher_New_Gmdebug_Command(void *Command, void *CUser, void *PacketBuf) { void *Pck = (void *)((*(int *)(PacketBuf + 20)) + 13); int msg_len = *(int *)(Pck); std::string msg((char *)(Pck + 4), msg_len); msg = msg.substr(2); std::lock_guard lock(SqMtx); // 执行虚拟机Main函数 SQInteger top = sq_gettop(v); // saves the stack size before the call sq_pushroottable(v); // pushes the global table sq_pushstring(v, _SC("Cb_gm_input"), -1); if (SQ_SUCCEEDED(sq_get(v, -2))) { // gets the fie123oo' from the global table sq_pushroottable(v); // push the 'this' (in this case is the global table) sq_pushuserpointer(v, Command); sq_pushuserpointer(v, CUser); sq_pushstring(v, _SC(msg.c_str()), -1); sq_call(v, 4, SQFalse, SQTrue); // calls the function } sq_settop(v, top); // restores the original stack size int Ret = Get()->old_LenDispatcher_New_Gmdebug_Command(Command, CUser, PacketBuf); return Ret; } int Controller::hook_DisPatcher_MoveMap_dispatch_sig(void *a1, CUser *pUser, PacketBuf *pBuf) { // ENUM_PACK_RET_TYPE ret = CDispatch::Get()->MoveMap_dispatch_sig(a1, pUser, pBuf); // int result = (ret == PAK_ERROR) ? 1 : 0; return Get()->old_DisPatcher_MoveMap_dispatch_sig(a1, pUser, pBuf); } int Controller::hook_Inter_LoadEtc_dispatch_sig(void *a1, CUser *pUser, char *a3) { CDispatch::Get()->Inter_LoadEtc_dispatch_sig(a1, pUser, a3); return Get()->old_Inter_LoadEtc_dispatch_sig(a1, pUser, a3); } int Controller::hook_DisPatcher_ReturnToSelectCharacter_dispatch_sig(void *a1, CUser *pUser, char *a3) { CDispatch::Get()->DisPatcher_ReturnToSelectCharacter_dispatch_sig(a1, pUser, a3); return Get()->old_DisPatcher_ReturnToSelectCharacter_dispatch_sig(a1, pUser, a3); } void Controller::hook_importCashShopItemList(const std::string *str) { if (str != NULL) CDispatch::Get()->importCashShopItemList(str); } void Controller::hook_ProcessIPG_ResultOutput(CUser *user, int Goods_No, int item_id, int Cera_Type, InterfacePacketBuf *pbuf) { CDispatch::Get()->ProcessIPG_ResultOutput(user, Goods_No, item_id, Cera_Type, pbuf); } int Controller::hook_Dispatcher_BuyCeraShopItem_dispatch_sig(void *a1, CUser *pUser, PacketBuf *pBuf) { return 0; } bool Controller::hook_Init(int a1, char **a2) { auto result = Get()->old_Init(a1, a2); if (result) { CDispatch::Get()->Init_done(a1, (const char **)a2); } return result; }