如何写一个单机游戏修改器?

1天前 (03-10 06:09)阅读1回复0
zaibaike
zaibaike
  • 管理员
  • 注册排名1
  • 经验值206625
  • 级别管理员
  • 主题41325
  • 回复0
楼主

谢邀,只但是我早已写过此种讲义了

估计刷了63个小时了, 末于刷完会战了。

先说说此款肉搏游戏, 再入自问自答。

再说关于两个喜好玩肉搏游戏,但是又时间太少的开发人员来说, 不舞弊要被AI虐哭。

此款肉搏游戏我估计做了3个舞弊机能

1、能批改卡桌前的任一两部手机(好比把随意两张恶魔卡,取代成任一两张恶魔卡, 魔力,圈套卡也能取代)

2、取代Rokcom(仅指他们卡片里有的是卡, 他们卡片没有的是卡, 有个模块没研究怎么聚合的, 因而不克不及内部构造。 但是好比晓得卡片的完好ID, 我就能取代整个卡片都是那两张牌……)

3、能取代卡片(还没抽的那部门) 的任一两部手机, 也能取代次序。 好比我能设置下两部手机是哪部手机!(阿谁机能不可上)

但是我只做了一点儿小舞弊, 也没太生硬, 如果舞弊得太重的话, 就说实话了。

好比我如上所述两两张牌是

批改呵呵

接着将

取代成

此种就第二局无限抽2部手机。 根本此种玩就能了。 再舞弊就显得不太厚道了。

专业术语太少说, 他们入自问自答吧! 即便阿谁肉搏游戏是纯64位的, OD2.0极难用, 因而他们就用github上的开放源码软件法式 x64dbg. 还有x64的CE。

在他们起头亲身脱手之前, 他们必要把路子给顺清晰……

1、他们必要做什么舞弊机能

2、做那些机能必要如何的附加机能去实现此种的舞弊机能

3、从哪方面侧发力

好比,

1、他们必要做两个取代两两张牌的机能

2、那就必要两个以获取现阶段大部分的两两张牌,接着他们必要晓得大部分卡的文本(ID,Name,攻击,防卫等等)。 因而打破点是2个, 现阶段两两张牌的操做符门商标 和 大部分卡的文本

3、他们必定先做第三个,先把大部分卡的文本给结点出来, 那么侧发力能从余下卡片数量侧发力。 是阿谁

即便阿谁牵扯到牌组的文本, 先侧发力ID。 再侧发力文本;

………………颠末数次翻牌, CE就能查到

转至x64 dbg

下两个出访PT5716SB0。 看软件法式。

他们PT5716SB0往上跟呵呵。估计能窥见

阿谁是ID。

下面那一堆代码是将ID颠末一段左移和And运算后, 能否大于 r10的判断。 估计是校验阿谁ID能否合法的。

跳到阿谁门商标瞄呵呵

数了呵呵, 有9个ID。 也就暗示了9部手机。 那么哪里有9部手机呢?

附加牌组那里…… 当然测验考试召唤后, 就会发现少两张,我就不演示了。 即便都到了那一步了, 接下去是召唤两张附加牌组的卡, 看下那里会不会从9个ID酿成8个ID就晓得了。 那阿谁就他们试好了。

接着接下去那一点是经历之谈了.

1、先翻呵呵附近的内存, 看下有木有类似的构造。 他们来翻呵呵。

你会发现那段内存附近有两个十分类似的构造。 你数呵呵就晓得是现阶段牌组的ID, 不算墓地和两两张牌。 是即将抽取的牌组的ID。 看好。 如今最顶部是0x00401246, 第二张是0x6002B96。 那么他们抽两张尝尝

那是我现阶段的两两张牌。

你会发现少了前2个ID。 接着我两两张牌是

当然了, 即便我场上

阿谁的关系, 我每回合都能抽2两张牌的缘故。 从那一点上他们就能下定论。 阿谁门商标是现阶段他们的牌组的门商标。

2、 若是那段内存里面没有类似的构造怎么办, 那你能在阿谁函数, 或者在附近的函数查看呵呵, 有没有类似的构造。 是类似此种的构造

mov edx, dword ptr [rbp + rax*4 + 0x558]

测验考试下PT5716SB0发现没断下来。 那不妨, 他们继续往上找。

又发现了2个。 他们断下 [rbp+rax*4+7B0]阿谁PT5716SB0。 会发现阿谁门商标指向的内存如下

就孤零零只要两个ID。

那么巧的是, 他们墓地也只要1部手机。 那他们再改动呵呵墓地的卡片数量尝尝

从那里能得出。 阿谁门商标是墓地牌组

接着继续往上翻

+198阿谁对应的是4个卡片ID的门商标。 而他们两两张牌刚好又有4张……那里就不试给你们看了, 他们测验考试呵呵就能确定是 现阶段两两张牌的门商标

现阶段牌组门商标。 +378是了。

好了。 他们从那里就不但单能确认了卡片的ID。 还能确认一些牌组的门商标。 当然在阿谁过程中, 他们还能尝尝批改ID。

好比, 他们批改呵呵, 现阶段牌组门商标的下两部手机是 他们持有两两张牌的某个ID。 好比

他们现阶段两两张牌

对应那4两张牌。 他们就把下两部手机, 改成第两个ID, 是0xCC0275E

为什么我要此种批改尝尝呢? 是即便阿谁牌组的体例, 固然是数组的体例保留的, 但是它操做的动做, 十分像队列, 牌组里翻牌是把队列的头给拿出来。 因而他们批改第两个牌组的ID, 只要他是到那里来取ID的话, 阿谁过程应该是能生效的。 专业术语太少说, 他们尝尝吧!

改成

留意了。 那里的内存门商标是按字节次序来写的的。 因而他们也要根据阿谁体例写进去。

他的对应体例, 他们略微一看就能晓得规律了, 哪怕你不懂内存字节的对齐体例。

考虑到他们是抽2部手机的, 那么索性就改2个好了。

当然了, 你还会发现貌似哪里有问题。 即便

那卡貌似在不竭跑来跑去…… 阿谁时候就晓得。 固然抽下两部手机的效果貌似是对的, 现实上仍是哪里有抵触了。

他们再抽2部手机后查看呵呵两两张牌。

发现刚好有2张一毛一样的两两张牌, 那么此时他们两两张牌门商标是文本是:

你会发现, 固然那2个都暗示“光子圣域”, 但是2个ID竟然纷歧样!

但是认真察看你会发现, 只是前4位纷歧样, 后4位仍是一样的, 带着阿谁问题,他们查看呵呵上两个两两张牌“夜摄”在牌组看下有木有0x275E的

从上面的图你会发现, 都是有2个275E, 但是前4位却纷歧样! 因而前4位应该是暗示某种形态, 后4位才是ID。 但是必需要完好的ID才气准确显示。 当然了, 我也没兴趣研究他前4位的ID到底有什么用 是如何聚合的, 只要我把我必要的卡,组到牌组里面, 我天然就晓得阿谁卡的完好ID。

因而批改下两部手机的手段关于他们来说只要一种。 好比他们要批改“雷击”那部手机为下两部手机。 那么起首我必要在现阶段两两张牌里面晓得"雷击"的ID是0x02810F7, 也是0x10F7

去牌组里看呵呵, 哪些包罗了0x10F7

他们测验考试取代呵呵。

酿成了

抽卡尝尝!

此次就一般了。 不管怎么闹, 那些卡都是能用的。 因而批改牌组的下两部手机, 必需是牌组里存在的卡。 至于怎么批改牌组不存在的卡的话。 就当是我安插给你们的功课吧~ 你们他们研究呵呵, 我就没阿谁需求就不弄了。

接下去是若何结点大部分的卡。 究竟结果他们每次都要看内存门商标, 看现阶段两两张牌才气晓得ID, 那也太费事了。

若是看过我搞魔兽争霸那篇文章的话, 他们再次用阿谁办法, 是搜刮文本。 阿谁肉搏游戏是Unicode字符串编码, 因而他们搜呵呵;

第两个门商标下硬件出访PT5716SB0。接着用鼠标选上阿谁卡片, 让它被选中

必要此种选中

胜利断下来了。

能看到阿谁rax是名字, 而那段代码是找到名字的完毕符。

能从那里看。 rdi=-1, 接着不断+=1

inc rdi

不断轮回到字符串完毕。 他们把下面内存的字符串显示出来看看.

很明显阿谁不是他们必要的名字。

圆圈内才是他们必要的名字。 为什么呢…… 即便阿谁名字是会变的

好比阿谁鹰身女郎三姐妹等等的卡片, 就名字带有N长, 但是卡片的申明会说, 那部手时机当鹰身女郎利用, 因而那里的名字是会变的。 好比我想搜刮鹰身女郎三姐妹, 成果那里只能显示[鹰身女郎]. 因而下两个~

他们翻上面的图。 第三道门商标跟第两个几乎是一样的。 因而排除。

第三扇门商标是我显示的图。 那里是完全一样的, 他们来尝尝

那里的RAX是Name, 很明显是从上面阿谁CALL返回的。 并且阿谁CALL必要两个ECX做为模块。 那么看下ECX是什么

RCX=2DE5. 那也另一种水平上证了然我上述的推论。 只要后4位才是ID。

到那里。 只但是他们能间接挪用汇编代码, 就能返回名字的

WCHAR* GetNameById(DWORD dwId) { DWORD64 dwRetValue = 0; __asm { PUSH dwId; MOV RAX, 0x140875b20; CALL RAX; MOV dwRetValue,RAX; } return reinterpret_cast<WCHAR*>(dwRetValue); }

然而VS 其实不撑持内联汇编在x64形式下。 必要他们建asm文件。 当然他们也能完全把阿谁CALL他们解析出来写一通。

他们进去看下阿谁CALL

代码翻译呵呵如下:

估计是此种。

0000000140875469 | B8 3C 0F 00 00 | mov eax,F3C | 000000014087546E | 66 2B C8 | sub cx,ax | 0000000140875471 | B8 55 21 00 00 | mov eax,2155 | 0000000140875476 | 66 3B C8 | cmp cx,ax |

那段代码能窥见来卡的有效范畴是 CardID > 0xF3C && CardId < (0xF3C+0x2155)=0x3091

当然了, 除了卡的名字, 他们还能以获取一些更有趣的。 好比攻击力, 防卫力, 介绍。

要记得一点: 肉搏游戏内的构造都是惊人的类似

因而, 从那段代码

返回名字的, 那么他们来找呵呵阿谁函数里面还有没有类似的代码。

没有…… 那么他们返回函数的上一层看看

Mark上阿谁CALL的感化。

接着你跟踪调试呵呵附近的函数。 你会发现良多有趣的工具。 好比

里面的文本我就忽略不写了。 能他们去看。

若是你不想此种两个两个函数的去翻, 看CALL的返回值的话。 那你就用我上述若何搜刮名字的办法切确定位。 我就纷歧一演示了。

批改两两张牌的办法和批改牌组的办法一样。 都是互相取代CardId。 必需是8位的卡ID。后4位是不克不及的。

批改卡桌什么的路子跟找牌组和两两张牌的一样, 我就不演示了。 路子都是一样的, 过程也是一样的, 无非是代码略微有一点儿纷歧样。

上呵呵关键代码

Card.h

#ifndef __NEWYUGIOH_CHEATDLL_X64_CARD_CARD_H__ #define __NEWYUGIOH_CHEATDLL_X64_CARD_CARD_H__ #include "GameEnv.h" class CCard { public: CCard(); CCard(_In_ DWORD64 ulCardId); ~CCard() = default; // Get Card Attribute em_CardAttribute GetCardAttribute() CONST; CONST std::wstring& GetCardAttributeText() CONST; // Get Power DWORD GetPower() CONST; // Get Defence DWORD GetDefence() CONST; // Get Count of Star DWORD GetStarCount() CONST; // Card Name CONST std::wstring& GetCardName() CONST; // Card Detail CONST std::wstring& GetCardDetail() CONST; DWORD64 GetCardID() CONST; DWORD64 GetFullID() CONST; bool IsCard() CONST; private: VOID SetCardName(); VOID SetCardDetail(); private: DWORD64 m_dwCardID; std::wstring m_wsCardName; std::wstring m_wsCardDetail; mutable em_CardAttribute m_emCardAttribute; }; #endif // !__NEWYUGIOH_CHEATDLL_X64_CARD_CARD_H__

Card.cpp

#include "stdafx.h" #include "Card.h" #include <vector> #include <algorithm> CCard::CCard() : m_dwCardID(NULL), m_emCardAttribute(em_CardAttribute::em_CardAttribute_Unknow) { } CCard::CCard(_In_ DWORD64 dwCardId) : m_dwCardID(dwCardId), m_emCardAttribute(em_CardAttribute::em_CardAttribute_Unknow) { if (GetCardAttribute() != em_CardAttribute::em_CardAttribute_Unknow) { SetCardName(); SetCardDetail(); } } DWORD64 CCard::GetCardID() CONST { return m_dwCardID & 0xFFFF; } CONST std::wstring& CCard::GetCardDetail() CONST { return m_wsCardDetail; } CONST std::wstring& CCard::GetCardName() CONST { return m_wsCardName; } em_CardAttribute CCard::GetCardAttribute() CONST { if (m_emCardAttribute != em_CardAttribute::em_CardAttribute_Unknow) return m_emCardAttribute; if (!IsCard()) return em_CardAttribute::em_CardAttribute_Unknow; DWORD64 ulValue = GetCardID() * 3; ulValue *= 2; m_emCardAttribute = static_cast<em_CardAttribute>(ReadDWORD64(CARD_ATTRIBUTE_BASE + ulValue * 8 + 0x14)); return m_emCardAttribute; } VOID CCard::SetCardName() { DWORD64 r8 = ReadDWORD64(ReadDWORD64(CARD_NAME_BASE) + 0x18); DWORD64 rdx = ReadDWORD64(ReadDWORD64(CARD_NAME_BASE) + 0x28); if (r8 == NULL || rdx == NULL) return; if (!IsCard()) return; auto ulCardID = GetCardID() - 0xF3C; DWORD64 ulNamePtr = ReadDWORD64((ReadDWORD64(CARD_NAME_INDEX_BASE + ulCardID * 2) & 0xFFFF) * 8 + rdx) + r8; if (ulNamePtr == NULL) return; WCHAR wszCardName[512] = { 0 }; memcpy(wszCardName, reinterpret_cast<WCHAR*>(ulNamePtr & 0xFFFFFFFF), _countof(wszCardName) - 1); m_wsCardName = wszCardName; } bool CCard::IsCard() CONST { return GetCardID() <= 0x3091 && GetCardID() >= 0xF3C; } VOID CCard::SetCardDetail() { DWORD64 r8 = ReadDWORD64(ReadDWORD64(CARD_NAME_BASE) + 0x38); DWORD64 rdx = ReadDWORD64(ReadDWORD64(CARD_NAME_BASE) + 0x28); if (r8 == NULL || rdx == NULL) return; if (!IsCard()) return; auto ulCardID = GetCardID() - 0xF3C; DWORD64 ulDetailPtr = ReadDWORD64((ReadDWORD64(CARD_NAME_INDEX_BASE + ulCardID * 2) & 0xFFFF) * 8 + 0x4 + rdx) + r8; if (ulDetailPtr == NULL) return; WCHAR wszDetailText[512] = { 0 }; memcpy(wszDetailText, reinterpret_cast<WCHAR*>(ulDetailPtr & 0xFFFFFFFF), _countof(wszDetailText) - 1); m_wsCardDetail = wszDetailText; } DWORD CCard::GetPower() CONST { if (!IsCard()) return 0; auto RCX = GetCardID() * 3; RCX <<= 0x4; auto EAX = ReadDWORD64(CARD_ATTRIBUTE_BASE + RCX + 0x4); if (EAX == 0x1FF) return 0; EAX *= 5; EAX *= 2; return static_cast<DWORD>(EAX); } DWORD CCard::GetDefence() CONST { if (!IsCard()) return 0; auto RCX = GetCardID() * 3; RCX <<= 0x4; auto EAX = ReadDWORD64(CARD_ATTRIBUTE_BASE + RCX + 0x8); if (EAX == 0x1FF) return 0; EAX *= 5; EAX *= 2; return static_cast<DWORD>(EAX); } DWORD CCard::GetStarCount() CONST { if (!IsCard()) return 0; auto RCX = GetCardID() * 3; RCX <<= 0x4; auto EAX = ReadDWORD64(CARD_ATTRIBUTE_BASE + RCX + 0xC) & 0xFFFFFFFF; return static_cast<DWORD>(ReadDWORD64(CARD_ATTRIBUTE_BASE + RCX + 0x18) & 0xFFFFFFFF); } CONST std::wstring& CCard::GetCardAttributeText() CONST { struct AttributeText { em_CardAttribute emCardAttribute; std::wstring wsText; }; CONST static std::vector<AttributeText> VecAttributeText = { { em_CardAttribute::em_CardAttribute_Magic, L"魔力卡" }, { em_CardAttribute::em_CardAttribute_Trap, L"圈套卡" }, { em_CardAttribute::em_CardAttribute_Land, L"地" }, { em_CardAttribute::em_CardAttribute_Dark, L"暗" }, { em_CardAttribute::em_CardAttribute_Light, L"光" }, { em_CardAttribute::em_CardAttribute_Water, L"水" }, { em_CardAttribute::em_CardAttribute_Wind, L"风" }, { em_CardAttribute::em_CardAttribute_Fire, L"炎" }, { em_CardAttribute::em_CardAttribute_God, L"神" }, { em_CardAttribute::em_CardAttribute_Dark2, L"暗" }, }; CONST static std::wstring wsUnknow = L"未知"; auto itr = std::find_if(VecAttributeText.begin(), VecAttributeText.end(), [this](CONST AttributeText& AttributeText_){ return AttributeText_.emCardAttribute == m_emCardAttribute; }); return itr == VecAttributeText.end() ? wsUnknow : itr->wsText; } DWORD64 CCard::GetFullID() CONST { return m_dwCardID; }

CardExtend.h

#ifndef __NEWYUGIOH_CHEATDLL_X64_CARD_CARDEXTEND_H__ #define __NEWYUGIOH_CHEATDLL_X64_CARD_CARDEXTEND_H__ #include "Card.h" #include <vector> class CCardExtend { public: CCardExtend() = default; ~CCardExtend() = default; static CCardExtend& GetInstance(); // Get ALL Card UINT64 GetALLCard(_Out_opt_ std::vector<CCard>& VecCard) CONST; // Get Count of CurrentCardGroup UINT64 GetCurrentCardGroup(_Out_opt_ std::vector<CCard>& VecCard) CONST; // Set Next Card by CardID BOOL SetNextCard(_In_ DWORD dwCardId) CONST; // Set Card To Desk BOOL SetCardToDesk(_In_ DWORD dwCardId) CONST; BOOL SetIniazleCard(_In_ CONST std::vector<DWORD>& VecCard) CONST; private: BOOL ExistCardInCardGroup(_In_ DWORD dwCardId) CONST; }; #endif // !__NEWYUGIOH_CHEATDLL_X64_CARD_CARDEXTEND_H__ #include "stdafx.h" #include "CardExtend.h" #include <MyTools/Character.h> #include <MyTools/CLPublic.h> #include <MyTools/Log.h> #define _SELF L"CardExtend.cpp" CCardExtend& CCardExtend::GetInstance() { static CCardExtend CCardExtend_; return CCardExtend_; } UINT64 CCardExtend::GetALLCard(_Out_opt_ std::vector<CCard>& VecCard) CONST { for (DWORD dwCardId = 0xF3C; dwCardId < 0x3091; ++dwCardId) { CCard Card(dwCardId); if (Card.GetCardAttribute() != em_CardAttribute::em_CardAttribute_Unknow) VecCard.push_back(std::move(Card)); } return VecCard.size(); } UINT64 CCardExtend::GetCurrentCardGroup(_Out_opt_ std::vector<CCard>& VecCard) CONST { auto ulAddr = CURRENT_CARD_GROUP_BASE - 0x438; for (int i = 0; i < 60; ++i, ulAddr += 4) { if (ReadDWORD64(ulAddr) == NULL) continue; CCard Card(CCharacter::ReadDWORD(ulAddr) & 0xFFFFFFFF); if (Card.GetCardAttribute() != em_CardAttribute::em_CardAttribute_Unknow) VecCard.push_back(std::move(Card)); } return VecCard.size(); } BOOL CCardExtend::SetNextCard(_In_ DWORD dwCardId) CONST { /*if (!ExistCardInCardGroup(dwCardId)) { //::MessageBoxW(NULL, L"该ID不存在牌组里面!", L"", NULL); return FALSE; }*/ auto ulAddr = CURRENT_CARD_GROUP_BASE - 0x438; auto dwValue = ReadDWORD64(ulAddr); dwValue >>= 0x10; dwValue <<= 0x10; dwValue += dwCardId; *reinterpret_cast<DWORD64*>(ulAddr) = dwValue; return FALSE; } BOOL CCardExtend::ExistCardInCardGroup(_In_ DWORD dwCardId) CONST { std::vector<CCard> VecCard; GetCurrentCardGroup(VecCard); auto itr = std::find_if(VecCard.begin(), VecCard.end(), [dwCardId](CONST CCard& Card){ return static_cast<DWORD>(Card.GetFullID()) == dwCardId; }); return itr != VecCard.end(); } BOOL CCardExtend::SetCardToDesk(_In_ DWORD dwCardId) CONST { auto ulAddr = CURRENT_CARD_DESK_BASE + 0x30 + 0x48; for (DWORD64 i = 0; i <= 20; ++i) { DWORD64 ulCardAddr = ulAddr + i * 4 * 6; LOG_CF_D(L"ulCardAddr=%lX, CardId=%lX", ulCardAddr, (ReadDWORD64(ulCardAddr) & 0xFFFF)); if ((ReadDWORD64(ulCardAddr) & 0xFFFF) == NULL) continue; dwCardId += static_cast<DWORD>(ReadDWORD64(ulCardAddr) & 0xFFFF0000); LOG_CF_D(L"Set Value ulCardAddr=%lX, CardId=%X", ulCardAddr, dwCardId); WriteValue(ulCardAddr, dwCardId); return TRUE; } return FALSE; } BOOL CCardExtend::SetIniazleCard(_In_ CONST std::vector<DWORD>& VecCard) CONST { if (VecCard.size() > 5) { MsgBoxLog(L"VecCard.size=%d > 5!", VecCard.size()); return FALSE; } std::vector<CCard> VecGroupCard; GetCurrentCardGroup(VecGroupCard); DWORD64 ulGroupAddr = CURRENT_CARD_GROUP_BASE - 0x438; for (size_t i = 0;i < VecCard.size(); ++i) { DWORD dwCardId = VecCard.at(i); auto p = CLPublic::Vec_find_if(VecGroupCard, [dwCardId](CONST CCard& Card) { return static_cast<DWORD>(Card.GetCardID() & 0xFFFF) == (dwCardId & 0xFFFF); }); if (p == nullptr) continue; // swap for (size_t j = 0; j < 60; ++j) { DWORD dwGroupCardId = static_cast<DWORD>(CCharacter::ReadDWORD(ulGroupAddr + j * 4)); if ((dwGroupCardId & 0xFFFF) == dwCardId) { DWORD dwHandCardId = static_cast<DWORD>(CCharacter::ReadDWORD(CURRENT_HAND_CARD_BASE + i * 4)); LOG_CF_D(L"OldHandID=%X, OldGroupID=%X", dwHandCardId, dwGroupCardId); // Set Select Card Id to Hand Card LOG_CF_D(L"SetHandCardId=%X", dwGroupCardId); WriteValue(CURRENT_HAND_CARD_BASE + i * 4, dwGroupCardId); // Set Old HandCard to Group LOG_CF_D(L"SetGroupCardId=%X", dwHandCardId); WriteValue(ulGroupAddr + j * 4, dwHandCardId); LOG_CF_D(L"NewHandID=%X, NewGroupID=%X", static_cast<DWORD>(CCharacter::ReadDWORD(CURRENT_HAND_CARD_BASE + i * 4)), static_cast<DWORD>(CCharacter::ReadDWORD(ulGroupAddr + j * 4))); break; } } } return TRUE; }

接着来测试呵呵。 测试代码

Expr.h

#ifndef __NEWYUGIOH_CHEATDLL_X64_EXPR_EXPR_H__ #define __NEWYUGIOH_CHEATDLL_X64_EXPR_EXPR_H__ #include <vector> #include <MyTools/CLExpression.h> #include <MyTools/ClassInstance.h> class CExpr : public CExprFunBase, virtual public CClassInstance<CExpr> { public: CExpr(); virtual ~CExpr(); public: virtual VOID Release(); virtual std::vector<ExpressionFunPtr>& GetVec(); private: virtual VOID Help(_In_ CONST std::vector<std::wstring>&); // VOID FindCard(_In_ CONST std::vector<std::wstring>&); // Set Next Card VOID SetDeskCard(_In_ CONST std::vector<std::wstring>&); // Set 5 Card when Start Game VOID SetInitialCard(_In_ CONST std::vector<std::wstring>&); }; #endif // !__NEWYUGIOH_CHEATDLL_X64_EXPR_EXPR_H__ #include "stdafx.h" #include "Expr.h" #include <MyTools/Log.h> #include <MyTools/Character.h> #include "CardExtend.h" #define _SELF L"Expr.cpp" CExpr::CExpr() { } CExpr::~CExpr() { } VOID CExpr::Release() { } std::vector<ExpressionFunPtr>& CExpr::GetVec() { static std::vector<ExpressionFunPtr> Vec = { { std::bind(&CExpr::Help, this, std::placeholders::_1), L"Help" }, { std::bind(&CExpr::FindCard, this, std::placeholders::_1), L"FindCard" }, { std::bind(&CExpr::SetDeskCard, this, std::placeholders::_1), L"SetDeskCard" }, { std::bind(&CExpr::SetInitialCard, this, std::placeholders::_1), L"SetInitialCard" }, }; return Vec; } VOID CExpr::Help(_In_ CONST std::vector<std::wstring>&) { auto& Vec = GetVec(); for (CONST auto& itm : Vec) LOG_C(CLog::em_Log_Type::em_Log_Type_Custome, L"FunctionName=%s", itm.wsFunName.c_str()); } VOID CExpr::FindCard(_In_ CONST std::vector<std::wstring>& VecParm) { if (VecParm.size() == 0) { LOG_CF_E(L"Parameter.size=0!"); return; } CONST std::wstring wsFindType = CCharacter::MakeTextToUpper(VecParm.at(0)); if (wsFindType == L"ALL") { std::vector<CCard> VecCard; CCardExtend::GetInstance().GetALLCard(VecCard); for (CONST auto& itm : VecCard) LOG_CF_D(L"ID=%X,Name=%s,Detail=%s", static_cast<DWORD>(itm.GetCardID()), itm.GetCardName().c_str(), itm.GetCardDetail().c_str()); } if (wsFindType == L"GROUP") { std::vector<CCard> VecCard; CCardExtend::GetInstance().GetCurrentCardGroup(VecCard); LOG_CF_D(L"GroupSize=%d", static_cast<DWORD>(VecCard.size())); for (CONST auto& itm : VecCard) LOG_CF_D(L"ID=%X,Name=%s,Detail=%s", static_cast<DWORD>(itm.GetCardID()), itm.GetCardName().c_str(), itm.GetCardDetail().c_str()); } else if (wsFindType == L"CARDNAME") { if (VecParm.size() == 1) { LOG_CF_E(L"Parameter.size=1!"); return; } CONST std::wstring& wsFindText = VecParm.at(1); std::vector<CCard> VecCard; CCardExtend::GetInstance().GetALLCard(VecCard); for (CONST auto& itm : VecCard) { if (itm.GetCardName().find(wsFindText) != -1) { LOG_CF_D(L"ID=%X,Name=%s,Detail=%s", static_cast<DWORD>(itm.GetCardID()), itm.GetCardName().c_str(), itm.GetCardDetail().c_str()); } } } else if (wsFindType == L"CARDID") { if (VecParm.size() == 1) { LOG_CF_E(L"Parameter.size=1!"); return; } DWORD dwCardId = wcstol(VecParm.at(1).c_str(), nullptr, 16); std::vector<CCard> VecCard; CCardExtend::GetInstance().GetALLCard(VecCard); for (CONST auto& itm : VecCard) { if (static_cast<DWORD>(itm.GetCardID()) == dwCardId) { LOG_CF_D(L"ID=%X,Name=%s,Detail=%s", static_cast<DWORD>(itm.GetCardID()), itm.GetCardName().c_str(), itm.GetCardDetail().c_str()); } } } } VOID CExpr::SetDeskCard(_In_ CONST std::vector<std::wstring>& VecParm) { if (VecParm.size() < 2) { LOG_CF_E(L"Parameter.size<2!"); return; } CONST std::wstring wsFindType = CCharacter::MakeTextToUpper(VecParm.at(0)); if (wsFindType == L"CARDID") { DWORD dwCardId = static_cast<DWORD>(wcstol(VecParm.at(1).c_str(), NULL, 16)); CCardExtend::GetInstance().SetCardToDesk(dwCardId); } } VOID CExpr::SetInitialCard(_In_ CONST std::vector<std::wstring>& VecParm) { std::vector<DWORD> VecCard; for (CONST auto& itm : VecParm) VecCard.push_back(wcstol(itm.c_str(), nullptr, 16)); CCardExtend::GetInstance().SetIniazleCard(VecCard); } extern DWORD64 ReadDWORD64(_In_ DWORD64 dwAddr) { __try { if (!::IsBadCodePtr(FARPROC(dwAddr))) return *reinterpret_cast<DWORD64*>(dwAddr); } __except (1) { } return NULL; } extern VOID WriteValue(_In_ DWORD64 ulAddr, _In_ DWORD dwValue) { auto dwCardValue = ReadDWORD64(ulAddr); // remove low Value dwCardValue >>= 0x20; dwCardValue <<= 0x20; dwCardValue += dwValue;

接着来尝尝;

接着试呵呵其他机能。 好比设置“守护神的宝扎”到卡桌前;

起首找到阿谁ID=2B96

但是他们必要两两张牌到桌面上,再取代它。 因而先以获取两部手机“光之护封剑”=1102

先策动卡

再取代

此种就好了……

固然能继续深切批改, 让我更为便利。 但是我觉得阿谁批改办法是我能承受的水平。 继续深切的话, 可能要花更多时间去逆向……此种我玩肉搏游戏的时间就会相对削减……究竟结果玩肉搏游戏+逆向的时间是有限的……还有更多工做和进修等着我……

X64的DLL注入在VideoCardGuy/X64Injector

代码: https://github.com/VideoCardGuy/NewYuGiOh_CheatDLL_x64

那篇文章在我差太少1年前写的。

外挂编程入门-4-肉搏游戏王 决斗者遗产 x64汇编

0
回帖

如何写一个单机游戏修改器? 期待您的回复!

取消